1. /*
  2. * The Apache Software License, Version 1.1
  3. *
  4. *
  5. * Copyright (c) 2001-2004 The Apache Software Foundation. All rights
  6. * reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. *
  20. * 3. The end-user documentation included with the redistribution,
  21. * if any, must include the following acknowledgment:
  22. * "This product includes software developed by the
  23. * Apache Software Foundation (http://www.apache.org/)."
  24. * Alternately, this acknowledgment may appear in the software itself,
  25. * if and wherever such third-party acknowledgments normally appear.
  26. *
  27. * 4. The names "Xerces" and "Apache Software Foundation" must
  28. * not be used to endorse or promote products derived from this
  29. * software without prior written permission. For written
  30. * permission, please contact apache@apache.org.
  31. *
  32. * 5. Products derived from this software may not be called "Apache",
  33. * nor may "Apache" appear in their name, without prior written
  34. * permission of the Apache Software Foundation.
  35. *
  36. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  37. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  38. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  39. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  40. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  41. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  42. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  43. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  44. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  45. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  46. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  47. * SUCH DAMAGE.
  48. * ====================================================================
  49. *
  50. * This software consists of voluntary contributions made by many
  51. * individuals on behalf of the Apache Software Foundation and was
  52. * originally based on software copyright (c) 2001, International
  53. * Business Machines, Inc., http://www.apache.org. For more
  54. * information on the Apache Software Foundation, please see
  55. * <http://www.apache.org/>.
  56. */
  57. package com.sun.org.apache.xerces.internal.impl.xs.traversers;
  58. import com.sun.org.apache.xerces.internal.impl.xs.SchemaGrammar;
  59. import com.sun.org.apache.xerces.internal.impl.xs.SchemaSymbols;
  60. import com.sun.org.apache.xerces.internal.impl.xs.XSParticleDecl;
  61. import com.sun.org.apache.xerces.internal.impl.xs.XSModelGroupImpl;
  62. import com.sun.org.apache.xerces.internal.impl.xs.XSAnnotationImpl;
  63. import com.sun.org.apache.xerces.internal.util.DOMUtil;
  64. import com.sun.org.apache.xerces.internal.impl.xs.util.XInt;
  65. import com.sun.org.apache.xerces.internal.xs.XSObject;
  66. import org.w3c.dom.Element;
  67. /**
  68. * @author Elena Litani, IBM
  69. * @author Sandy Gao, IBM
  70. * @version $Id: XSDAbstractParticleTraverser.java,v 1.16 2004/02/04 18:48:15 mrglavas Exp $
  71. */
  72. abstract class XSDAbstractParticleTraverser extends XSDAbstractTraverser {
  73. XSDAbstractParticleTraverser (XSDHandler handler,
  74. XSAttributeChecker gAttrCheck) {
  75. super(handler, gAttrCheck);
  76. }
  77. /**
  78. *
  79. * Traverse the "All" declaration
  80. *
  81. * <all
  82. * id = ID
  83. * maxOccurs = 1 : 1
  84. * minOccurs = (0 | 1) : 1>
  85. * Content: (annotation? , element*)
  86. * </all>
  87. **/
  88. XSParticleDecl traverseAll(Element allDecl,
  89. XSDocumentInfo schemaDoc,
  90. SchemaGrammar grammar,
  91. int allContextFlags,
  92. XSObject parent) {
  93. // General Attribute Checking
  94. Object[] attrValues = fAttrChecker.checkAttributes(allDecl, false, schemaDoc);
  95. Element child = DOMUtil.getFirstChildElement(allDecl);
  96. XSAnnotationImpl annotation = null;
  97. if (child !=null) {
  98. // traverse Annotation
  99. if (DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION)) {
  100. annotation = traverseAnnotationDecl(child, attrValues, false, schemaDoc);
  101. child = DOMUtil.getNextSiblingElement(child);
  102. }
  103. }
  104. String childName = null;
  105. XSParticleDecl particle;
  106. fPArray.pushContext();
  107. for (; child != null; child = DOMUtil.getNextSiblingElement(child)) {
  108. particle = null;
  109. childName = DOMUtil.getLocalName(child);
  110. // Only elements are allowed in <all>
  111. if (childName.equals(SchemaSymbols.ELT_ELEMENT)) {
  112. particle = fSchemaHandler.fElementTraverser.traverseLocal(child, schemaDoc, grammar, PROCESSING_ALL_EL, parent);
  113. }
  114. else {
  115. Object[] args = {"all", "(annotation?, element*)", DOMUtil.getLocalName(child)};
  116. reportSchemaError("s4s-elt-must-match.1", args, child);
  117. }
  118. if (particle != null)
  119. fPArray.addParticle(particle);
  120. }
  121. particle = null;
  122. XInt minAtt = (XInt)attrValues[XSAttributeChecker.ATTIDX_MINOCCURS];
  123. XInt maxAtt = (XInt)attrValues[XSAttributeChecker.ATTIDX_MAXOCCURS];
  124. Long defaultVals = (Long)attrValues[XSAttributeChecker.ATTIDX_FROMDEFAULT];
  125. XSModelGroupImpl group = new XSModelGroupImpl();
  126. group.fCompositor = XSModelGroupImpl.MODELGROUP_ALL;
  127. group.fParticleCount = fPArray.getParticleCount();
  128. group.fParticles = fPArray.popContext();
  129. group.fAnnotation = annotation;
  130. particle = new XSParticleDecl();
  131. particle.fType = XSParticleDecl.PARTICLE_MODELGROUP;
  132. particle.fMinOccurs = minAtt.intValue();
  133. particle.fMaxOccurs = maxAtt.intValue();
  134. particle.fValue = group;
  135. particle = checkOccurrences(particle,
  136. SchemaSymbols.ELT_ALL,
  137. (Element)allDecl.getParentNode(),
  138. allContextFlags,
  139. defaultVals.longValue());
  140. fAttrChecker.returnAttrArray(attrValues, schemaDoc);
  141. return particle;
  142. }
  143. /**
  144. * Traverse the Sequence declaration
  145. *
  146. * <sequence
  147. * id = ID
  148. * maxOccurs = string
  149. * minOccurs = nonNegativeInteger>
  150. * Content: (annotation? , (element | group | choice | sequence | any)*)
  151. * </sequence>
  152. *
  153. * @param seqDecl
  154. * @param schemaDoc
  155. * @param grammar
  156. * @return
  157. */
  158. XSParticleDecl traverseSequence(Element seqDecl,
  159. XSDocumentInfo schemaDoc,
  160. SchemaGrammar grammar,
  161. int allContextFlags,
  162. XSObject parent) {
  163. return traverseSeqChoice(seqDecl, schemaDoc, grammar, allContextFlags, false, parent);
  164. }
  165. /**
  166. * Traverse the Choice declaration
  167. *
  168. * <choice
  169. * id = ID
  170. * maxOccurs = string
  171. * minOccurs = nonNegativeInteger>
  172. * Content: (annotation? , (element | group | choice | sequence | any)*)
  173. * </choice>
  174. *
  175. * @param choiceDecl
  176. * @param schemaDoc
  177. * @param grammar
  178. * @return
  179. */
  180. XSParticleDecl traverseChoice(Element choiceDecl,
  181. XSDocumentInfo schemaDoc,
  182. SchemaGrammar grammar,
  183. int allContextFlags,
  184. XSObject parent) {
  185. return traverseSeqChoice (choiceDecl, schemaDoc, grammar, allContextFlags, true, parent);
  186. }
  187. /**
  188. * Common traversal for <choice> and <sequence>
  189. *
  190. * @param decl
  191. * @param schemaDoc
  192. * @param grammar
  193. * @param choice If traversing <choice> this parameter is true.
  194. * @return
  195. */
  196. private XSParticleDecl traverseSeqChoice(Element decl,
  197. XSDocumentInfo schemaDoc,
  198. SchemaGrammar grammar,
  199. int allContextFlags,
  200. boolean choice,
  201. XSObject parent) {
  202. // General Attribute Checking
  203. Object[] attrValues = fAttrChecker.checkAttributes(decl, false, schemaDoc);
  204. Element child = DOMUtil.getFirstChildElement(decl);
  205. XSAnnotationImpl annotation = null;
  206. if (child !=null) {
  207. // traverse Annotation
  208. if (DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION)) {
  209. annotation = traverseAnnotationDecl(child, attrValues, false, schemaDoc);
  210. child = DOMUtil.getNextSiblingElement(child);
  211. }
  212. }
  213. boolean hadContent = false;
  214. String childName = null;
  215. XSParticleDecl particle;
  216. fPArray.pushContext();
  217. for (;child != null;child = DOMUtil.getNextSiblingElement(child)) {
  218. particle = null;
  219. childName = DOMUtil.getLocalName(child);
  220. if (childName.equals(SchemaSymbols.ELT_ELEMENT)) {
  221. particle = fSchemaHandler.fElementTraverser.traverseLocal(child, schemaDoc, grammar, NOT_ALL_CONTEXT, parent);
  222. }
  223. else if (childName.equals(SchemaSymbols.ELT_GROUP)) {
  224. particle = fSchemaHandler.fGroupTraverser.traverseLocal(child, schemaDoc, grammar);
  225. // A content type of all can only appear
  226. // as the content type of a complex type definition.
  227. if (hasAllContent(particle)) {
  228. // don't insert the "all" particle, otherwise we won't be
  229. // able to create DFA from this content model
  230. particle = null;
  231. reportSchemaError("cos-all-limited.1.2", null, child);
  232. }
  233. }
  234. else if (childName.equals(SchemaSymbols.ELT_CHOICE)) {
  235. particle = traverseChoice(child, schemaDoc, grammar, NOT_ALL_CONTEXT, parent);
  236. }
  237. else if (childName.equals(SchemaSymbols.ELT_SEQUENCE)) {
  238. particle = traverseSequence(child, schemaDoc, grammar, NOT_ALL_CONTEXT, parent);
  239. }
  240. else if (childName.equals(SchemaSymbols.ELT_ANY)) {
  241. particle = fSchemaHandler.fWildCardTraverser.traverseAny(child, schemaDoc, grammar);
  242. }
  243. else {
  244. Object [] args;
  245. if (choice) {
  246. args = new Object[]{"choice", "(annotation?, (element | group | choice | sequence | any)*)", DOMUtil.getLocalName(child)};
  247. }
  248. else {
  249. args = new Object[]{"sequence", "(annotation?, (element | group | choice | sequence | any)*)", DOMUtil.getLocalName(child)};
  250. }
  251. reportSchemaError("s4s-elt-must-match.1", args, child);
  252. }
  253. if (particle != null)
  254. fPArray.addParticle(particle);
  255. }
  256. particle = null;
  257. XInt minAtt = (XInt)attrValues[XSAttributeChecker.ATTIDX_MINOCCURS];
  258. XInt maxAtt = (XInt)attrValues[XSAttributeChecker.ATTIDX_MAXOCCURS];
  259. Long defaultVals = (Long)attrValues[XSAttributeChecker.ATTIDX_FROMDEFAULT];
  260. XSModelGroupImpl group = new XSModelGroupImpl();
  261. group.fCompositor = choice ? XSModelGroupImpl.MODELGROUP_CHOICE : XSModelGroupImpl.MODELGROUP_SEQUENCE;
  262. group.fParticleCount = fPArray.getParticleCount();
  263. group.fParticles = fPArray.popContext();
  264. group.fAnnotation = annotation;
  265. particle = new XSParticleDecl();
  266. particle.fType = XSParticleDecl.PARTICLE_MODELGROUP;
  267. particle.fMinOccurs = minAtt.intValue();
  268. particle.fMaxOccurs = maxAtt.intValue();
  269. particle.fValue = group;
  270. particle = checkOccurrences(particle,
  271. choice ? SchemaSymbols.ELT_CHOICE : SchemaSymbols.ELT_SEQUENCE,
  272. (Element)decl.getParentNode(),
  273. allContextFlags,
  274. defaultVals.longValue());
  275. fAttrChecker.returnAttrArray(attrValues, schemaDoc);
  276. return particle;
  277. }
  278. // Determines whether a content spec tree represents an "all" content model
  279. protected boolean hasAllContent(XSParticleDecl particle) {
  280. // If the content is not empty, is the top node ALL?
  281. if (particle != null && particle.fType == XSParticleDecl.PARTICLE_MODELGROUP) {
  282. return ((XSModelGroupImpl)particle.fValue).fCompositor == XSModelGroupImpl.MODELGROUP_ALL;
  283. }
  284. return false;
  285. }
  286. // the inner class: used to store particles for model groups
  287. // to avoid creating a new Vector in each model group, or when traversing
  288. // each model group, we use this one big array to store all particles
  289. // for model groups. when the traversal finishes, this class returns an
  290. // XSParticleDecl[] containing all particles for the current model group.
  291. // it's possible that we need to traverse another model group while
  292. // traversing one (one inside another one; referring to a global group,
  293. // etc.), so we have push/pos context methods to save the same of the
  294. // current traversal before starting the traversal of another model group.
  295. protected static class ParticleArray {
  296. // big array to contain all particles
  297. XSParticleDecl[] fParticles = new XSParticleDecl[10];
  298. // the ending position of particles in the array for each context
  299. // index 0 is reserved, with value 0. index 1 is used for the fist
  300. // context. so that the number of particles for context 'i' can be
  301. // computed simply by fPos[i] - fPos[i-1].
  302. int[] fPos = new int[5];
  303. // number of contexts
  304. int fContextCount = 0;
  305. // start a new context (start traversing a new model group)
  306. void pushContext() {
  307. fContextCount++;
  308. // resize position array if necessary
  309. if (fContextCount == fPos.length) {
  310. int newSize = fContextCount * 2;
  311. int[] newArray = new int[newSize];
  312. System.arraycopy(fPos, 0, newArray, 0, fContextCount);
  313. fPos = newArray;
  314. }
  315. // the initial ending position of the current context is the
  316. // ending position of the previsous context. which means there is
  317. // no particle for the current context yet.
  318. fPos[fContextCount] = fPos[fContextCount-1];
  319. }
  320. // get the number of particles of this context (model group)
  321. int getParticleCount() {
  322. return fPos[fContextCount] - fPos[fContextCount-1];
  323. }
  324. // add a particle to the current context
  325. void addParticle(XSParticleDecl particle) {
  326. // resize the particle array if necessary
  327. if (fPos[fContextCount] == fParticles.length) {
  328. int newSize = fPos[fContextCount] * 2;
  329. XSParticleDecl[] newArray = new XSParticleDecl[newSize];
  330. System.arraycopy(fParticles, 0, newArray, 0, fPos[fContextCount]);
  331. fParticles = newArray;
  332. }
  333. fParticles[fPos[fContextCount]++] = particle;
  334. }
  335. // end the current context, and return an array of particles
  336. XSParticleDecl[] popContext() {
  337. int count = fPos[fContextCount] - fPos[fContextCount-1];
  338. XSParticleDecl[] array = null;
  339. if (count != 0) {
  340. array = new XSParticleDecl[count];
  341. System.arraycopy(fParticles, fPos[fContextCount-1], array, 0, count);
  342. // clear the particle array, to release memory
  343. for (int i = fPos[fContextCount-1]; i < fPos[fContextCount]; i++)
  344. fParticles[i] = null;
  345. }
  346. fContextCount--;
  347. return array;
  348. }
  349. }
  350. // the big particle array to hold all particles in model groups
  351. ParticleArray fPArray = new ParticleArray();
  352. }