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 * @version $Id: BalancedDTDGrammar.java,v 1.1 2010/08/11 07:18:38 joehw Exp $ 36 */ 37 final class BalancedDTDGrammar extends DTDGrammar { 38 39 // 40 // Data 41 // 42 43 /** Mixed. */ 44 private boolean fMixed; 45 46 /** Stack depth */ 47 private int fDepth = 0; 48 49 /** Children content model operation stack. */ 50 private short [] fOpStack = null; 51 52 /** Holder for choice/sequence/leaf groups at each depth. */ 53 private int [][] fGroupIndexStack; 54 55 /** Sizes of the allocated portions of each int[] in fGroupIndexStack. */ 56 private int [] fGroupIndexStackSizes; 57 58 // 59 // Constructors 60 // 61 62 /** Default constructor. */ 63 public BalancedDTDGrammar(SymbolTable symbolTable, XMLDTDDescription desc) { 64 super(symbolTable, desc); 65 } // BalancedDTDGrammar(SymbolTable,XMLDTDDescription) 66 67 // 68 // Public methods 69 // 70 71 /** 72 * The start of a content model. Depending on the type of the content 73 * model, specific methods may be called between the call to the 74 * startContentModel method and the call to the endContentModel method. 75 * 76 * @param elementName The name of the element. 77 * @param augs Additional information that may include infoset 78 * augmentations. 79 * @throws XNIException Thrown by handler to signal an error. 80 */ 81 public final void startContentModel(String elementName, Augmentations augs) 82 throws XNIException { 83 fDepth = 0; 84 initializeContentModelStacks(); 85 super.startContentModel(elementName, augs); 86 } // startContentModel(String) 87 88 /** 89 * A start of either a mixed or children content model. A mixed 90 * content model will immediately be followed by a call to the 91 * <code>pcdata()</code> method. A children content model will 92 * contain additional groups and/or elements. 93 * 94 * @param augs Additional information that may include infoset 95 * augmentations. 96 * @throws XNIException Thrown by handler to signal an error. 97 * 98 * @see #any 99 * @see #empty 100 */ 101 public final void startGroup(Augmentations augs) throws XNIException { 102 ++fDepth; 103 initializeContentModelStacks(); 104 fMixed = false; 105 } // startGroup() 106 107 /** 108 * The appearance of "#PCDATA" within a group signifying a 109 * mixed content model. This method will be the first called 110 * following the content model's <code>startGroup()</code>. 111 * 112 *@param augs Additional information that may include infoset 113 * augmentations. 114 * 115 * @throws XNIException Thrown by handler to signal an error. 116 * 117 * @see #startGroup 118 */ 119 public final void pcdata(Augmentations augs) throws XNIException { 120 fMixed = true; 121 } // pcdata() 122 123 /** 124 * A referenced element in a mixed or children content model. 125 * 126 * @param elementName The name of the referenced element. 127 * @param augs Additional information that may include infoset 128 * augmentations. 129 * 130 * @throws XNIException Thrown by handler to signal an error. 131 */ 132 public final void element(String elementName, Augmentations augs) throws XNIException { 133 addToCurrentGroup(addUniqueLeafNode(elementName)); 134 } // element(String) 135 136 /** 137 * The separator between choices or sequences of a mixed or children 138 * content model. 139 * 140 * @param separator The type of children separator. 141 * @param augs Additional information that may include infoset 142 * augmentations. 143 * @throws XNIException Thrown by handler to signal an error. 144 * 145 * @see org.apache.xerces.xni.XMLDTDContentModelHandler#SEPARATOR_CHOICE 146 * @see org.apache.xerces.xni.XMLDTDContentModelHandler#SEPARATOR_SEQUENCE 147 */ 148 public final void separator(short separator, Augmentations augs) throws XNIException { 149 if (separator == XMLDTDContentModelHandler.SEPARATOR_CHOICE) { 150 fOpStack[fDepth] = XMLContentSpec.CONTENTSPECNODE_CHOICE; 151 } 152 else if (separator == XMLDTDContentModelHandler.SEPARATOR_SEQUENCE) { 153 fOpStack[fDepth] = XMLContentSpec.CONTENTSPECNODE_SEQ; 154 } 155 } // separator(short) 156 157 /** 158 * The occurrence count for a child in a children content model or 159 * for the mixed content model group. 160 * 161 * @param occurrence The occurrence count for the last element 162 * or group. 163 * @param augs Additional information that may include infoset 164 * augmentations. 165 * @throws XNIException Thrown by handler to signal an error. 166 * 167 * @see org.apache.xerces.xni.XMLDTDContentModelHandler#OCCURS_ZERO_OR_ONE 168 * @see org.apache.xerces.xni.XMLDTDContentModelHandler#OCCURS_ZERO_OR_MORE 169 * @see org.apache.xerces.xni.XMLDTDContentModelHandler#OCCURS_ONE_OR_MORE 170 */ 171 public final void occurrence(short occurrence, Augmentations augs) throws XNIException { 172 if (!fMixed) { 173 int currentIndex = fGroupIndexStackSizes[fDepth] - 1; 174 if (occurrence == XMLDTDContentModelHandler.OCCURS_ZERO_OR_ONE) { 175 fGroupIndexStack[fDepth][currentIndex] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE, fGroupIndexStack[fDepth][currentIndex], -1); 176 } 177 else if ( occurrence == XMLDTDContentModelHandler.OCCURS_ZERO_OR_MORE) { 178 fGroupIndexStack[fDepth][currentIndex] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE, fGroupIndexStack[fDepth][currentIndex], -1); 179 } 180 else if ( occurrence == XMLDTDContentModelHandler.OCCURS_ONE_OR_MORE) { 181 fGroupIndexStack[fDepth][currentIndex] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE, fGroupIndexStack[fDepth][currentIndex], -1); 182 } 183 } 184 } // occurrence(short) 185 186 /** 187 * The end of a group for mixed or children content models. 188 * 189 * @param augs Additional information that may include infoset 190 * augmentations. 191 * @throws XNIException Thrown by handler to signal an error. 192 */ 193 public final void endGroup(Augmentations augs) throws XNIException { 194 final int length = fGroupIndexStackSizes[fDepth]; 195 final int group = length > 0 ? addContentSpecNodes(0, length - 1) : addUniqueLeafNode(null); 196 --fDepth; 197 addToCurrentGroup(group); 198 } // endGroup() 199 200 /** 201 * The end of the DTD. 202 * 203 * @param augs Additional information that may include infoset 204 * augmentations. 205 * @throws XNIException Thrown by handler to signal an error. 206 */ 207 public final void endDTD(Augmentations augs) throws XNIException { 208 super.endDTD(augs); 209 fOpStack = null; 210 fGroupIndexStack = null; 211 fGroupIndexStackSizes = null; 212 } // endDTD() 213 214 // 215 // Protected methods 216 // 217 218 /** 219 * Adds the content spec to the given element declaration. 220 */ 221 protected final void addContentSpecToElement(XMLElementDecl elementDecl) { 222 int contentSpec = fGroupIndexStackSizes[0] > 0 ? fGroupIndexStack[0][0] : -1; 223 setContentSpecIndex(fCurrentElementIndex, contentSpec); 224 } 225 226 // 227 // Private methods 228 // 229 230 /** 231 * Creates a subtree from the leaf nodes at the current depth. 232 */ 233 private int addContentSpecNodes(int begin, int end) { 234 if (begin == end) { 235 return fGroupIndexStack[fDepth][begin]; 236 } 237 final int middle = (begin + end) >>> 1; 238 return addContentSpecNode(fOpStack[fDepth], 239 addContentSpecNodes(begin, middle), 240 addContentSpecNodes(middle + 1, end)); 241 } // addContentSpecNodes(int,int) 242 243 /** 244 * Initialize the stacks which temporarily hold content models. 245 */ 246 private void initializeContentModelStacks() { 247 if (fOpStack == null) { 248 fOpStack = new short[8]; 249 fGroupIndexStack = new int [8][]; 250 fGroupIndexStackSizes = new int [8]; 251 } 252 else if (fDepth == fOpStack.length) { 253 short [] newOpStack = new short[fDepth * 2]; 254 System.arraycopy(fOpStack, 0, newOpStack, 0, fDepth); 255 fOpStack = newOpStack; 256 int [][] newGroupIndexStack = new int[fDepth * 2][]; 257 System.arraycopy(fGroupIndexStack, 0, newGroupIndexStack, 0, fDepth); 258 fGroupIndexStack = newGroupIndexStack; 259 int [] newGroupIndexStackLengths = new int[fDepth * 2]; 260 System.arraycopy(fGroupIndexStackSizes, 0, newGroupIndexStackLengths, 0, fDepth); 261 fGroupIndexStackSizes = newGroupIndexStackLengths; 262 } 263 fOpStack[fDepth] = -1; 264 fGroupIndexStackSizes[fDepth] = 0; 265 } // initializeContentModelStacks() 266 267 /** 268 * Add XMLContentSpec to the current group. 269 * 270 * @param contentSpec handle to the XMLContentSpec to add to the current group 271 */ 272 private void addToCurrentGroup(int contentSpec) { 273 int [] currentGroup = fGroupIndexStack[fDepth]; 274 int length = fGroupIndexStackSizes[fDepth]++; 275 if (currentGroup == null) { 276 currentGroup = new int[8]; 277 fGroupIndexStack[fDepth] = currentGroup; 278 } 279 else if (length == currentGroup.length) { 280 int [] newGroup = new int[currentGroup.length * 2]; 281 System.arraycopy(currentGroup, 0, newGroup, 0, currentGroup.length); 282 currentGroup = newGroup; 283 fGroupIndexStack[fDepth] = currentGroup; 284 } 285 currentGroup[length] = contentSpec; 286 } // addToCurrentGroup(int) 287 288 } // class BalancedDTDGrammar