1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 /* 6 * Copyright 2001-2004 The Apache Software Foundation. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 21 package com.sun.org.apache.xerces.internal.impl.xs.traversers; 22 23 import com.sun.org.apache.xerces.internal.impl.xs.SchemaGrammar; 24 import com.sun.org.apache.xerces.internal.impl.xs.SchemaSymbols; 25 import com.sun.org.apache.xerces.internal.impl.xs.XSAnnotationImpl; 26 import com.sun.org.apache.xerces.internal.impl.xs.XSModelGroupImpl; 27 import com.sun.org.apache.xerces.internal.impl.xs.XSParticleDecl; 28 import com.sun.org.apache.xerces.internal.impl.xs.util.XInt; 29 import com.sun.org.apache.xerces.internal.impl.xs.util.XSObjectListImpl; 30 import com.sun.org.apache.xerces.internal.util.DOMUtil; 31 import com.sun.org.apache.xerces.internal.xs.XSObject; 32 import com.sun.org.apache.xerces.internal.xs.XSObjectList; 33 import org.w3c.dom.Element; 34 35 /** 36 * @xerces.internal 37 * 38 * @author Elena Litani, IBM 39 * @author Sandy Gao, IBM 40 */ 41 abstract class XSDAbstractParticleTraverser extends XSDAbstractTraverser { 42 43 XSDAbstractParticleTraverser (XSDHandler handler, 44 XSAttributeChecker gAttrCheck) { 45 super(handler, gAttrCheck); 46 } 47 48 /** 49 * 50 * Traverse the "All" declaration 51 * 52 * <all 53 * id = ID 54 * maxOccurs = 1 : 1 55 * minOccurs = (0 | 1) : 1> 56 * Content: (annotation? , element*) 57 * </all> 58 **/ 59 XSParticleDecl traverseAll(Element allDecl, 60 XSDocumentInfo schemaDoc, 61 SchemaGrammar grammar, 62 int allContextFlags, 63 XSObject parent) { 64 65 // General Attribute Checking 66 67 Object[] attrValues = fAttrChecker.checkAttributes(allDecl, false, schemaDoc); 68 69 Element child = DOMUtil.getFirstChildElement(allDecl); 70 71 XSAnnotationImpl annotation = null; 72 if (child !=null && DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION)) { 73 annotation = traverseAnnotationDecl(child, attrValues, false, schemaDoc); 74 child = DOMUtil.getNextSiblingElement(child); 75 } 76 else { 77 String text = DOMUtil.getSyntheticAnnotation(allDecl); 78 if (text != null) { 79 annotation = traverseSyntheticAnnotation(allDecl, text, attrValues, false, schemaDoc); 80 } 81 } 82 String childName = null; 83 XSParticleDecl particle; 84 fPArray.pushContext(); 85 86 for (; child != null; child = DOMUtil.getNextSiblingElement(child)) { 87 88 particle = null; 89 childName = DOMUtil.getLocalName(child); 90 91 // Only elements are allowed in <all> 92 if (childName.equals(SchemaSymbols.ELT_ELEMENT)) { 93 particle = fSchemaHandler.fElementTraverser.traverseLocal(child, schemaDoc, grammar, PROCESSING_ALL_EL, parent); 94 } 95 else { 96 Object[] args = {"all", "(annotation?, element*)", DOMUtil.getLocalName(child)}; 97 reportSchemaError("s4s-elt-must-match.1", args, child); 98 } 99 100 if (particle != null) 101 fPArray.addParticle(particle); 102 } 103 104 particle = null; 105 XInt minAtt = (XInt)attrValues[XSAttributeChecker.ATTIDX_MINOCCURS]; 106 XInt maxAtt = (XInt)attrValues[XSAttributeChecker.ATTIDX_MAXOCCURS]; 107 Long defaultVals = (Long)attrValues[XSAttributeChecker.ATTIDX_FROMDEFAULT]; 108 109 XSModelGroupImpl group = new XSModelGroupImpl(); 110 group.fCompositor = XSModelGroupImpl.MODELGROUP_ALL; 111 group.fParticleCount = fPArray.getParticleCount(); 112 group.fParticles = fPArray.popContext(); 113 XSObjectList annotations; 114 if (annotation != null) { 115 annotations = new XSObjectListImpl(); 116 ((XSObjectListImpl)annotations).addXSObject (annotation); 117 } else { 118 annotations = XSObjectListImpl.EMPTY_LIST; 119 } 120 group.fAnnotations = annotations; 121 particle = new XSParticleDecl(); 122 particle.fType = XSParticleDecl.PARTICLE_MODELGROUP; 123 particle.fMinOccurs = minAtt.intValue(); 124 particle.fMaxOccurs = maxAtt.intValue(); 125 particle.fValue = group; 126 particle.fAnnotations = annotations; 127 128 particle = checkOccurrences(particle, 129 SchemaSymbols.ELT_ALL, 130 (Element)allDecl.getParentNode(), 131 allContextFlags, 132 defaultVals.longValue()); 133 fAttrChecker.returnAttrArray(attrValues, schemaDoc); 134 135 return particle; 136 } 137 138 /** 139 * Traverse the Sequence declaration 140 * 141 * <sequence 142 * id = ID 143 * maxOccurs = string 144 * minOccurs = nonNegativeInteger> 145 * Content: (annotation? , (element | group | choice | sequence | any)*) 146 * </sequence> 147 * 148 * @param seqDecl 149 * @param schemaDoc 150 * @param grammar 151 * @return 152 */ 153 XSParticleDecl traverseSequence(Element seqDecl, 154 XSDocumentInfo schemaDoc, 155 SchemaGrammar grammar, 156 int allContextFlags, 157 XSObject parent) { 158 159 return traverseSeqChoice(seqDecl, schemaDoc, grammar, allContextFlags, false, parent); 160 } 161 162 /** 163 * Traverse the Choice declaration 164 * 165 * <choice 166 * id = ID 167 * maxOccurs = string 168 * minOccurs = nonNegativeInteger> 169 * Content: (annotation? , (element | group | choice | sequence | any)*) 170 * </choice> 171 * 172 * @param choiceDecl 173 * @param schemaDoc 174 * @param grammar 175 * @return 176 */ 177 XSParticleDecl traverseChoice(Element choiceDecl, 178 XSDocumentInfo schemaDoc, 179 SchemaGrammar grammar, 180 int allContextFlags, 181 XSObject parent) { 182 183 return traverseSeqChoice (choiceDecl, schemaDoc, grammar, allContextFlags, true, parent); 184 } 185 186 /** 187 * Common traversal for <choice> and <sequence> 188 * 189 * @param decl 190 * @param schemaDoc 191 * @param grammar 192 * @param choice If traversing <choice> this parameter is true. 193 * @return 194 */ 195 private XSParticleDecl traverseSeqChoice(Element decl, 196 XSDocumentInfo schemaDoc, 197 SchemaGrammar grammar, 198 int allContextFlags, 199 boolean choice, 200 XSObject parent) { 201 202 // General Attribute Checking 203 Object[] attrValues = fAttrChecker.checkAttributes(decl, false, schemaDoc); 204 205 Element child = DOMUtil.getFirstChildElement(decl); 206 XSAnnotationImpl annotation = null; 207 if (child !=null && DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION)) { 208 annotation = traverseAnnotationDecl(child, attrValues, false, schemaDoc); 209 child = DOMUtil.getNextSiblingElement(child); 210 } 211 else { 212 String text = DOMUtil.getSyntheticAnnotation(decl); 213 if (text != null) { 214 annotation = traverseSyntheticAnnotation(decl, text, attrValues, false, schemaDoc); 215 } 216 } 217 218 String childName = null; 219 XSParticleDecl particle; 220 fPArray.pushContext(); 221 222 for (;child != null;child = DOMUtil.getNextSiblingElement(child)) { 223 224 particle = null; 225 226 childName = DOMUtil.getLocalName(child); 227 if (childName.equals(SchemaSymbols.ELT_ELEMENT)) { 228 particle = fSchemaHandler.fElementTraverser.traverseLocal(child, schemaDoc, grammar, NOT_ALL_CONTEXT, parent); 229 } 230 else if (childName.equals(SchemaSymbols.ELT_GROUP)) { 231 particle = fSchemaHandler.fGroupTraverser.traverseLocal(child, schemaDoc, grammar); 232 233 // A content type of all can only appear 234 // as the content type of a complex type definition. 235 if (hasAllContent(particle)) { 236 // don't insert the "all" particle, otherwise we won't be 237 // able to create DFA from this content model 238 particle = null; 239 reportSchemaError("cos-all-limited.1.2", null, child); 240 } 241 242 } 243 else if (childName.equals(SchemaSymbols.ELT_CHOICE)) { 244 particle = traverseChoice(child, schemaDoc, grammar, NOT_ALL_CONTEXT, parent); 245 } 246 else if (childName.equals(SchemaSymbols.ELT_SEQUENCE)) { 247 particle = traverseSequence(child, schemaDoc, grammar, NOT_ALL_CONTEXT, parent); 248 } 249 else if (childName.equals(SchemaSymbols.ELT_ANY)) { 250 particle = fSchemaHandler.fWildCardTraverser.traverseAny(child, schemaDoc, grammar); 251 } 252 else { 253 Object [] args; 254 if (choice) { 255 args = new Object[]{"choice", "(annotation?, (element | group | choice | sequence | any)*)", DOMUtil.getLocalName(child)}; 256 } 257 else { 258 args = new Object[]{"sequence", "(annotation?, (element | group | choice | sequence | any)*)", DOMUtil.getLocalName(child)}; 259 } 260 reportSchemaError("s4s-elt-must-match.1", args, child); 261 } 262 263 if (particle != null) 264 fPArray.addParticle(particle); 265 } 266 267 particle = null; 268 269 XInt minAtt = (XInt)attrValues[XSAttributeChecker.ATTIDX_MINOCCURS]; 270 XInt maxAtt = (XInt)attrValues[XSAttributeChecker.ATTIDX_MAXOCCURS]; 271 Long defaultVals = (Long)attrValues[XSAttributeChecker.ATTIDX_FROMDEFAULT]; 272 273 XSModelGroupImpl group = new XSModelGroupImpl(); 274 group.fCompositor = choice ? XSModelGroupImpl.MODELGROUP_CHOICE : XSModelGroupImpl.MODELGROUP_SEQUENCE; 275 group.fParticleCount = fPArray.getParticleCount(); 276 group.fParticles = fPArray.popContext(); 277 XSObjectList annotations; 278 if (annotation != null) { 279 annotations = new XSObjectListImpl(); 280 ((XSObjectListImpl)annotations).addXSObject (annotation); 281 } else { 282 annotations = XSObjectListImpl.EMPTY_LIST; 283 } 284 group.fAnnotations = annotations; 285 particle = new XSParticleDecl(); 286 particle.fType = XSParticleDecl.PARTICLE_MODELGROUP; 287 particle.fMinOccurs = minAtt.intValue(); 288 particle.fMaxOccurs = maxAtt.intValue(); 289 particle.fValue = group; 290 particle.fAnnotations = annotations; 291 292 particle = checkOccurrences(particle, 293 choice ? SchemaSymbols.ELT_CHOICE : SchemaSymbols.ELT_SEQUENCE, 294 (Element)decl.getParentNode(), 295 allContextFlags, 296 defaultVals.longValue()); 297 fAttrChecker.returnAttrArray(attrValues, schemaDoc); 298 299 return particle; 300 } 301 302 // Determines whether a content spec tree represents an "all" content model 303 protected boolean hasAllContent(XSParticleDecl particle) { 304 // If the content is not empty, is the top node ALL? 305 if (particle != null && particle.fType == XSParticleDecl.PARTICLE_MODELGROUP) { 306 return ((XSModelGroupImpl)particle.fValue).fCompositor == XSModelGroupImpl.MODELGROUP_ALL; 307 } 308 309 return false; 310 } 311 312 // the inner class: used to store particles for model groups 313 // to avoid creating a new Vector in each model group, or when traversing 314 // each model group, we use this one big array to store all particles 315 // for model groups. when the traversal finishes, this class returns an 316 // XSParticleDecl[] containing all particles for the current model group. 317 // it's possible that we need to traverse another model group while 318 // traversing one (one inside another one; referring to a global group, 319 // etc.), so we have push/pos context methods to save the same of the 320 // current traversal before starting the traversal of another model group. 321 protected static class ParticleArray { 322 // big array to contain all particles 323 XSParticleDecl[] fParticles = new XSParticleDecl[10]; 324 // the ending position of particles in the array for each context 325 // index 0 is reserved, with value 0. index 1 is used for the fist 326 // context. so that the number of particles for context 'i' can be 327 // computed simply by fPos[i] - fPos[i-1]. 328 int[] fPos = new int[5]; 329 // number of contexts 330 int fContextCount = 0; 331 332 // start a new context (start traversing a new model group) 333 void pushContext() { 334 fContextCount++; 335 // resize position array if necessary 336 if (fContextCount == fPos.length) { 337 int newSize = fContextCount * 2; 338 int[] newArray = new int[newSize]; 339 System.arraycopy(fPos, 0, newArray, 0, fContextCount); 340 fPos = newArray; 341 } 342 // the initial ending position of the current context is the 343 // ending position of the previsous context. which means there is 344 // no particle for the current context yet. 345 fPos[fContextCount] = fPos[fContextCount-1]; 346 } 347 348 // get the number of particles of this context (model group) 349 int getParticleCount() { 350 return fPos[fContextCount] - fPos[fContextCount-1]; 351 } 352 353 // add a particle to the current context 354 void addParticle(XSParticleDecl particle) { 355 // resize the particle array if necessary 356 if (fPos[fContextCount] == fParticles.length) { 357 int newSize = fPos[fContextCount] * 2; 358 XSParticleDecl[] newArray = new XSParticleDecl[newSize]; 359 System.arraycopy(fParticles, 0, newArray, 0, fPos[fContextCount]); 360 fParticles = newArray; 361 } 362 fParticles[fPos[fContextCount]++] = particle; 363 } 364 365 // end the current context, and return an array of particles 366 XSParticleDecl[] popContext() { 367 int count = fPos[fContextCount] - fPos[fContextCount-1]; 368 XSParticleDecl[] array = null; 369 if (count != 0) { 370 array = new XSParticleDecl[count]; 371 System.arraycopy(fParticles, fPos[fContextCount-1], array, 0, count); 372 // clear the particle array, to release memory 373 for (int i = fPos[fContextCount-1]; i < fPos[fContextCount]; i++) 374 fParticles[i] = null; 375 } 376 fContextCount--; 377 return array; 378 } 379 380 } 381 382 // the big particle array to hold all particles in model groups 383 ParticleArray fPArray = new ParticleArray(); 384 }