1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 /* 6 * Licensed to the Apache Software Foundation (ASF) under one or more 7 * contributor license agreements. See the NOTICE file distributed with 8 * this work for additional information regarding copyright ownership. 9 * The ASF licenses this file to You under the Apache License, Version 2.0 10 * (the "License"); you may not use this file except in compliance with 11 * the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 */ 21 22 package com.sun.org.apache.xerces.internal.impl.dtd; 23 24 import com.sun.org.apache.xerces.internal.util.SymbolTable; 25 import com.sun.org.apache.xerces.internal.xni.Augmentations; 26 import com.sun.org.apache.xerces.internal.xni.XMLDTDContentModelHandler; 27 import com.sun.org.apache.xerces.internal.xni.XNIException; 28 29 /** 30 * <p>A DTD grammar that produces balanced syntax trees.</p> 31 * 32 * @xerces.internal 33 * 34 * @author Michael Glavassevich, IBM 35 */ 36 final class BalancedDTDGrammar extends DTDGrammar { 37 38 // 39 // Data 40 // 41 42 /** Mixed. */ 43 private boolean fMixed; 44 45 /** Stack depth */ 46 private int fDepth = 0; 47 48 /** Children content model operation stack. */ 49 private short [] fOpStack = null; 50 51 /** Holder for choice/sequence/leaf groups at each depth. */ 52 private int [][] fGroupIndexStack; 53 54 /** Sizes of the allocated portions of each int[] in fGroupIndexStack. */ 55 private int [] fGroupIndexStackSizes; 56 57 // 58 // Constructors 59 // 60 61 /** Default constructor. */ 62 public BalancedDTDGrammar(SymbolTable symbolTable, XMLDTDDescription desc) { 63 super(symbolTable, desc); 64 } // BalancedDTDGrammar(SymbolTable,XMLDTDDescription) 65 66 // 67 // Public methods 68 // 69 70 /** 71 * The start of a content model. Depending on the type of the content 72 * model, specific methods may be called between the call to the 73 * startContentModel method and the call to the endContentModel method. 74 * 75 * @param elementName The name of the element. 76 * @param augs Additional information that may include infoset 77 * augmentations. 78 * @throws XNIException Thrown by handler to signal an error. 79 */ 80 public final void startContentModel(String elementName, Augmentations augs) 81 throws XNIException { 82 fDepth = 0; 83 initializeContentModelStacks(); 84 super.startContentModel(elementName, augs); 85 } // startContentModel(String) 86 87 /** 88 * A start of either a mixed or children content model. A mixed 89 * content model will immediately be followed by a call to the 90 * <code>pcdata()</code> method. A children content model will 91 * contain additional groups and/or elements. 92 * 93 * @param augs Additional information that may include infoset 94 * augmentations. 95 * @throws XNIException Thrown by handler to signal an error. 96 * 97 * @see #any 98 * @see #empty 99 */ 100 public final void startGroup(Augmentations augs) throws XNIException { 101 ++fDepth; 102 initializeContentModelStacks(); 103 fMixed = false; 104 } // startGroup() 105 106 /** 107 * The appearance of "#PCDATA" within a group signifying a 108 * mixed content model. This method will be the first called 109 * following the content model's <code>startGroup()</code>. 110 * 111 *@param augs Additional information that may include infoset 112 * augmentations. 113 * 114 * @throws XNIException Thrown by handler to signal an error. 115 * 116 * @see #startGroup 117 */ 118 public final void pcdata(Augmentations augs) throws XNIException { 119 fMixed = true; 120 } // pcdata() 121 122 /** 123 * A referenced element in a mixed or children content model. 124 * 125 * @param elementName The name of the referenced element. 126 * @param augs Additional information that may include infoset 127 * augmentations. 128 * 129 * @throws XNIException Thrown by handler to signal an error. 130 */ 131 public final void element(String elementName, Augmentations augs) throws XNIException { 132 addToCurrentGroup(addUniqueLeafNode(elementName)); 133 } // element(String) 134 135 /** 136 * The separator between choices or sequences of a mixed or children 137 * content model. 138 * 139 * @param separator The type of children separator. 140 * @param augs Additional information that may include infoset 141 * augmentations. 142 * @throws XNIException Thrown by handler to signal an error. 143 * 144 * @see org.apache.xerces.xni.XMLDTDContentModelHandler#SEPARATOR_CHOICE 145 * @see org.apache.xerces.xni.XMLDTDContentModelHandler#SEPARATOR_SEQUENCE 146 */ 147 public final void separator(short separator, Augmentations augs) throws XNIException { 148 if (separator == XMLDTDContentModelHandler.SEPARATOR_CHOICE) { 149 fOpStack[fDepth] = XMLContentSpec.CONTENTSPECNODE_CHOICE; 150 } 151 else if (separator == XMLDTDContentModelHandler.SEPARATOR_SEQUENCE) { 152 fOpStack[fDepth] = XMLContentSpec.CONTENTSPECNODE_SEQ; 153 } 154 } // separator(short) 155 156 /** 157 * The occurrence count for a child in a children content model or 158 * for the mixed content model group. 159 * 160 * @param occurrence The occurrence count for the last element 161 * or group. 162 * @param augs Additional information that may include infoset 163 * augmentations. 164 * @throws XNIException Thrown by handler to signal an error. 165 * 166 * @see org.apache.xerces.xni.XMLDTDContentModelHandler#OCCURS_ZERO_OR_ONE 167 * @see org.apache.xerces.xni.XMLDTDContentModelHandler#OCCURS_ZERO_OR_MORE 168 * @see org.apache.xerces.xni.XMLDTDContentModelHandler#OCCURS_ONE_OR_MORE 169 */ 170 public final void occurrence(short occurrence, Augmentations augs) throws XNIException { 171 if (!fMixed) { 172 int currentIndex = fGroupIndexStackSizes[fDepth] - 1; 173 if (occurrence == XMLDTDContentModelHandler.OCCURS_ZERO_OR_ONE) { 174 fGroupIndexStack[fDepth][currentIndex] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE, fGroupIndexStack[fDepth][currentIndex], -1); 175 } 176 else if ( occurrence == XMLDTDContentModelHandler.OCCURS_ZERO_OR_MORE) { 177 fGroupIndexStack[fDepth][currentIndex] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE, fGroupIndexStack[fDepth][currentIndex], -1); 178 } 179 else if ( occurrence == XMLDTDContentModelHandler.OCCURS_ONE_OR_MORE) { 180 fGroupIndexStack[fDepth][currentIndex] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE, fGroupIndexStack[fDepth][currentIndex], -1); 181 } 182 } 183 } // occurrence(short) 184 185 /** 186 * The end of a group for mixed or children content models. 187 * 188 * @param augs Additional information that may include infoset 189 * augmentations. 190 * @throws XNIException Thrown by handler to signal an error. 191 */ 192 public final void endGroup(Augmentations augs) throws XNIException { 193 final int length = fGroupIndexStackSizes[fDepth]; 194 final int group = length > 0 ? addContentSpecNodes(0, length - 1) : addUniqueLeafNode(null); 195 --fDepth; 196 addToCurrentGroup(group); 197 } // endGroup() 198 199 /** 200 * The end of the DTD. 201 * 202 * @param augs Additional information that may include infoset 203 * augmentations. 204 * @throws XNIException Thrown by handler to signal an error. 205 */ 206 public final void endDTD(Augmentations augs) throws XNIException { 207 super.endDTD(augs); 208 fOpStack = null; 209 fGroupIndexStack = null; 210 fGroupIndexStackSizes = null; 211 } // endDTD() 212 213 // 214 // Protected methods 215 // 216 217 /** 218 * Adds the content spec to the given element declaration. 219 */ 220 protected final void addContentSpecToElement(XMLElementDecl elementDecl) { 221 int contentSpec = fGroupIndexStackSizes[0] > 0 ? fGroupIndexStack[0][0] : -1; 222 setContentSpecIndex(fCurrentElementIndex, contentSpec); 223 } 224 225 // 226 // Private methods 227 // 228 229 /** 230 * Creates a subtree from the leaf nodes at the current depth. 231 */ 232 private int addContentSpecNodes(int begin, int end) { 233 if (begin == end) { 234 return fGroupIndexStack[fDepth][begin]; 235 } 236 final int middle = (begin + end) >>> 1; 237 return addContentSpecNode(fOpStack[fDepth], 238 addContentSpecNodes(begin, middle), 239 addContentSpecNodes(middle + 1, end)); 240 } // addContentSpecNodes(int,int) 241 242 /** 243 * Initialize the stacks which temporarily hold content models. 244 */ 245 private void initializeContentModelStacks() { 246 if (fOpStack == null) { 247 fOpStack = new short[8]; 248 fGroupIndexStack = new int [8][]; 249 fGroupIndexStackSizes = new int [8]; 250 } 251 else if (fDepth == fOpStack.length) { 252 short [] newOpStack = new short[fDepth * 2]; 253 System.arraycopy(fOpStack, 0, newOpStack, 0, fDepth); 254 fOpStack = newOpStack; 255 int [][] newGroupIndexStack = new int[fDepth * 2][]; 256 System.arraycopy(fGroupIndexStack, 0, newGroupIndexStack, 0, fDepth); 257 fGroupIndexStack = newGroupIndexStack; 258 int [] newGroupIndexStackLengths = new int[fDepth * 2]; 259 System.arraycopy(fGroupIndexStackSizes, 0, newGroupIndexStackLengths, 0, fDepth); 260 fGroupIndexStackSizes = newGroupIndexStackLengths; 261 } 262 fOpStack[fDepth] = -1; 263 fGroupIndexStackSizes[fDepth] = 0; 264 } // initializeContentModelStacks() 265 266 /** 267 * Add XMLContentSpec to the current group. 268 * 269 * @param contentSpec handle to the XMLContentSpec to add to the current group 270 */ 271 private void addToCurrentGroup(int contentSpec) { 272 int [] currentGroup = fGroupIndexStack[fDepth]; 273 int length = fGroupIndexStackSizes[fDepth]++; 274 if (currentGroup == null) { 275 currentGroup = new int[8]; 276 fGroupIndexStack[fDepth] = currentGroup; 277 } 278 else if (length == currentGroup.length) { 279 int [] newGroup = new int[currentGroup.length * 2]; 280 System.arraycopy(currentGroup, 0, newGroup, 0, currentGroup.length); 281 currentGroup = newGroup; 282 fGroupIndexStack[fDepth] = currentGroup; 283 } 284 currentGroup[length] = contentSpec; 285 } // addToCurrentGroup(int) 286 287 } // class BalancedDTDGrammar