1. /*
  2. * The Apache Software License, Version 1.1
  3. *
  4. *
  5. * Copyright (c) 1999-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) 1999, 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;
  58. import com.sun.org.apache.xerces.internal.impl.dv.XSSimpleType;
  59. import com.sun.org.apache.xerces.internal.impl.dv.InvalidDatatypeValueException;
  60. import com.sun.org.apache.xerces.internal.impl.dv.ValidatedInfo;
  61. import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter;
  62. import com.sun.org.apache.xerces.internal.impl.xs.models.CMBuilder;
  63. import com.sun.org.apache.xerces.internal.impl.xs.models.XSCMValidator;
  64. import com.sun.org.apache.xerces.internal.impl.xs.util.SimpleLocator;
  65. import com.sun.org.apache.xerces.internal.xs.XSConstants;
  66. import com.sun.org.apache.xerces.internal.xs.XSObjectList;
  67. import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition;
  68. import com.sun.org.apache.xerces.internal.impl.dv.ValidationContext;
  69. import com.sun.org.apache.xerces.internal.util.SymbolHash;
  70. import java.util.Vector;
  71. /**
  72. * Constaints shared by traversers and validator
  73. *
  74. * @author Sandy Gao, IBM
  75. *
  76. * @version $Id: XSConstraints.java,v 1.37 2004/02/03 17:27:45 sandygao Exp $
  77. */
  78. public class XSConstraints {
  79. static final int OCCURRENCE_UNKNOWN = SchemaSymbols.OCCURRENCE_UNBOUNDED-1;
  80. static final XSSimpleType STRING_TYPE = (XSSimpleType)SchemaGrammar.SG_SchemaNS.getGlobalTypeDecl(SchemaSymbols.ATTVAL_STRING);
  81. /**
  82. * check whether derived is valid derived from base, given a subset
  83. * of {restriction, extension}.B
  84. */
  85. public static boolean checkTypeDerivationOk(XSTypeDefinition derived, XSTypeDefinition base, short block) {
  86. // if derived is anyType, then it's valid only if base is anyType too
  87. if (derived == SchemaGrammar.fAnyType)
  88. return derived == base;
  89. // if derived is anySimpleType, then it's valid only if the base
  90. // is ur-type
  91. if (derived == SchemaGrammar.fAnySimpleType) {
  92. return (base == SchemaGrammar.fAnyType ||
  93. base == SchemaGrammar.fAnySimpleType);
  94. }
  95. // if derived is simple type
  96. if (derived.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
  97. // if base is complex type
  98. if (base.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
  99. // if base is anyType, change base to anySimpleType,
  100. // otherwise, not valid
  101. if (base == SchemaGrammar.fAnyType)
  102. base = SchemaGrammar.fAnySimpleType;
  103. else
  104. return false;
  105. }
  106. return checkSimpleDerivation((XSSimpleType)derived,
  107. (XSSimpleType)base, block);
  108. } else {
  109. return checkComplexDerivation((XSComplexTypeDecl)derived, base, block);
  110. }
  111. }
  112. /**
  113. * check whether simple type derived is valid derived from base,
  114. * given a subset of {restriction, extension}.
  115. */
  116. public static boolean checkSimpleDerivationOk(XSSimpleType derived, XSTypeDefinition base, short block) {
  117. // if derived is anySimpleType, then it's valid only if the base
  118. // is ur-type
  119. if (derived == SchemaGrammar.fAnySimpleType) {
  120. return (base == SchemaGrammar.fAnyType ||
  121. base == SchemaGrammar.fAnySimpleType);
  122. }
  123. // if base is complex type
  124. if (base.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
  125. // if base is anyType, change base to anySimpleType,
  126. // otherwise, not valid
  127. if (base == SchemaGrammar.fAnyType)
  128. base = SchemaGrammar.fAnySimpleType;
  129. else
  130. return false;
  131. }
  132. return checkSimpleDerivation((XSSimpleType)derived,
  133. (XSSimpleType)base, block);
  134. }
  135. /**
  136. * check whether complex type derived is valid derived from base,
  137. * given a subset of {restriction, extension}.
  138. */
  139. public static boolean checkComplexDerivationOk(XSComplexTypeDecl derived, XSTypeDefinition base, short block) {
  140. // if derived is anyType, then it's valid only if base is anyType too
  141. if (derived == SchemaGrammar.fAnyType)
  142. return derived == base;
  143. return checkComplexDerivation((XSComplexTypeDecl)derived, base, block);
  144. }
  145. /**
  146. * Note: this will be a private method, and it assumes that derived is not
  147. * anySimpleType, and base is not anyType. Another method will be
  148. * introduced for public use, which will call this method.
  149. */
  150. private static boolean checkSimpleDerivation(XSSimpleType derived, XSSimpleType base, short block) {
  151. // 1 They are the same type definition.
  152. if (derived == base)
  153. return true;
  154. // 2 All of the following must be true:
  155. // 2.1 restriction is not in the subset, or in the {final} of its own {base type definition};
  156. if ((block & XSConstants.DERIVATION_RESTRICTION) != 0 ||
  157. (derived.getBaseType().getFinal() & XSConstants.DERIVATION_RESTRICTION) != 0) {
  158. return false;
  159. }
  160. // 2.2 One of the following must be true:
  161. // 2.2.1 D's base type definition is B.
  162. XSSimpleType directBase = (XSSimpleType)derived.getBaseType();
  163. if (directBase == base)
  164. return true;
  165. // 2.2.2 D's base type definition is not the simple ur-type definition and is validly derived from B given the subset, as defined by this constraint.
  166. if (directBase != SchemaGrammar.fAnySimpleType &&
  167. checkSimpleDerivation(directBase, base, block)) {
  168. return true;
  169. }
  170. // 2.2.3 D's {variety} is list or union and B is the simple ur-type definition.
  171. if ((derived.getVariety() == XSSimpleType.VARIETY_LIST ||
  172. derived.getVariety() == XSSimpleType.VARIETY_UNION) &&
  173. base == SchemaGrammar.fAnySimpleType) {
  174. return true;
  175. }
  176. // 2.2.4 B's {variety} is union and D is validly derived from a type definition in B's {member type definitions} given the subset, as defined by this constraint.
  177. if (base.getVariety() == XSSimpleType.VARIETY_UNION) {
  178. XSObjectList subUnionMemberDV = base.getMemberTypes();
  179. int subUnionSize = subUnionMemberDV.getLength();
  180. for (int i=0; i<subUnionSize; i++) {
  181. base = (XSSimpleType)subUnionMemberDV.item(i);
  182. if (checkSimpleDerivation(derived, base, block))
  183. return true;
  184. }
  185. }
  186. return false;
  187. }
  188. /**
  189. * Note: this will be a private method, and it assumes that derived is not
  190. * anyType. Another method will be introduced for public use,
  191. * which will call this method.
  192. */
  193. private static boolean checkComplexDerivation(XSComplexTypeDecl derived, XSTypeDefinition base, short block) {
  194. // 2.1 B and D must be the same type definition.
  195. if (derived == base)
  196. return true;
  197. // 1 If B and D are not the same type definition, then the {derivation method} of D must not be in the subset.
  198. if ((derived.fDerivedBy & block) != 0)
  199. return false;
  200. // 2 One of the following must be true:
  201. XSTypeDefinition directBase = derived.fBaseType;
  202. // 2.2 B must be D's {base type definition}.
  203. if (directBase == base)
  204. return true;
  205. // 2.3 All of the following must be true:
  206. // 2.3.1 D's {base type definition} must not be the ur-type definition.
  207. if (directBase == SchemaGrammar.fAnyType ||
  208. directBase == SchemaGrammar.fAnySimpleType) {
  209. return false;
  210. }
  211. // 2.3.2 The appropriate case among the following must be true:
  212. // 2.3.2.1 If D's {base type definition} is complex, then it must be validly derived from B given the subset as defined by this constraint.
  213. if (directBase.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE)
  214. return checkComplexDerivation((XSComplexTypeDecl)directBase, base, block);
  215. // 2.3.2.2 If D's {base type definition} is simple, then it must be validly derived from B given the subset as defined in Type Derivation OK (Simple) (3.14.6).
  216. if (directBase.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
  217. // if base is complex type
  218. if (base.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
  219. // if base is anyType, change base to anySimpleType,
  220. // otherwise, not valid
  221. if (base == SchemaGrammar.fAnyType)
  222. base = SchemaGrammar.fAnySimpleType;
  223. else
  224. return false;
  225. }
  226. return checkSimpleDerivation((XSSimpleType)directBase,
  227. (XSSimpleType)base, block);
  228. }
  229. return false;
  230. }
  231. /**
  232. * check whether a value is a valid default for some type
  233. * returns the compiled form of the value
  234. * The parameter value could be either a String or a ValidatedInfo object
  235. */
  236. public static Object ElementDefaultValidImmediate(XSTypeDefinition type, String value, ValidationContext context, ValidatedInfo vinfo) {
  237. XSSimpleType dv = null;
  238. // e-props-correct
  239. // For a string to be a valid default with respect to a type definition the appropriate case among the following must be true:
  240. // 1 If the type definition is a simple type definition, then the string must be valid with respect to that definition as defined by String Valid (3.14.4).
  241. if (type.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
  242. dv = (XSSimpleType)type;
  243. }
  244. // 2 If the type definition is a complex type definition, then all of the following must be true:
  245. else {
  246. // 2.1 its {content type} must be a simple type definition or mixed.
  247. XSComplexTypeDecl ctype = (XSComplexTypeDecl)type;
  248. // 2.2 The appropriate case among the following must be true:
  249. // 2.2.1 If the {content type} is a simple type definition, then the string must be valid with respect to that simple type definition as defined by String Valid (3.14.4).
  250. if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_SIMPLE) {
  251. dv = ctype.fXSSimpleType;
  252. }
  253. // 2.2.2 If the {content type} is mixed, then the {content type}'s particle must be emptiable as defined by Particle Emptiable (3.9.6).
  254. else if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_MIXED) {
  255. if (!((XSParticleDecl)ctype.getParticle()).emptiable())
  256. return null;
  257. }
  258. else {
  259. return null;
  260. }
  261. }
  262. // get the simple type declaration, and validate
  263. Object actualValue = null;
  264. if (dv == null) {
  265. // complex type with mixed. to make sure that we store correct
  266. // information in vinfo and return the correct value, we use
  267. // "string" type for validation
  268. dv = STRING_TYPE;
  269. }
  270. try {
  271. // validate the original lexical rep, and set the actual value
  272. actualValue = dv.validate(value, context, vinfo);
  273. // validate the canonical lexical rep
  274. if (vinfo != null)
  275. actualValue = dv.validate(vinfo.stringValue(), context, vinfo);
  276. } catch (InvalidDatatypeValueException ide) {
  277. return null;
  278. }
  279. return actualValue;
  280. }
  281. static void reportSchemaError(XMLErrorReporter errorReporter,
  282. SimpleLocator loc,
  283. String key, Object[] args) {
  284. if (loc != null) {
  285. errorReporter.reportError(loc, XSMessageFormatter.SCHEMA_DOMAIN,
  286. key, args, XMLErrorReporter.SEVERITY_ERROR);
  287. }
  288. else {
  289. errorReporter.reportError(XSMessageFormatter.SCHEMA_DOMAIN,
  290. key, args, XMLErrorReporter.SEVERITY_ERROR);
  291. }
  292. }
  293. /**
  294. * used to check the 3 constraints against each complex type
  295. * (should be each model group):
  296. * Unique Particle Attribution, Particle Derivation (Restriction),
  297. * Element Declrations Consistent.
  298. */
  299. public static void fullSchemaChecking(XSGrammarBucket grammarBucket,
  300. SubstitutionGroupHandler SGHandler,
  301. CMBuilder cmBuilder,
  302. XMLErrorReporter errorReporter) {
  303. // get all grammars, and put all substitution group information
  304. // in the substitution group handler
  305. SGHandler.reset();
  306. SchemaGrammar[] grammars = grammarBucket.getGrammars();
  307. for (int i = grammars.length-1; i >= 0; i--) {
  308. SGHandler.addSubstitutionGroup(grammars[i].getSubstitutionGroups());
  309. }
  310. XSParticleDecl fakeDerived = new XSParticleDecl();
  311. XSParticleDecl fakeBase = new XSParticleDecl();
  312. fakeDerived.fType = XSParticleDecl.PARTICLE_MODELGROUP;
  313. fakeBase.fType = XSParticleDecl.PARTICLE_MODELGROUP;
  314. // before worrying about complexTypes, let's get
  315. // groups redefined by restriction out of the way.
  316. for (int g = grammars.length-1; g >= 0; g--) {
  317. XSGroupDecl [] redefinedGroups = grammars[g].getRedefinedGroupDecls();
  318. SimpleLocator [] rgLocators = grammars[g].getRGLocators();
  319. for(int i=0; i<redefinedGroups.length; ) {
  320. XSGroupDecl derivedGrp = redefinedGroups[i++];
  321. XSModelGroupImpl derivedMG = derivedGrp.fModelGroup;
  322. XSGroupDecl baseGrp = redefinedGroups[i++];
  323. XSModelGroupImpl baseMG = baseGrp.fModelGroup;
  324. if(baseMG == null) {
  325. if(derivedMG != null) { // can't be a restriction!
  326. reportSchemaError(errorReporter, rgLocators[i2-1],
  327. "src-redefine.6.2.2",
  328. new Object[]{derivedGrp.fName, "rcase-Recurse.2"});
  329. }
  330. } else {
  331. fakeDerived.fValue = derivedMG;
  332. fakeBase.fValue = baseMG;
  333. try {
  334. particleValidRestriction(fakeDerived, SGHandler, fakeBase, SGHandler);
  335. } catch (XMLSchemaException e) {
  336. String key = e.getKey();
  337. reportSchemaError(errorReporter, rgLocators[i2-1],
  338. key,
  339. e.getArgs());
  340. reportSchemaError(errorReporter, rgLocators[i2-1],
  341. "src-redefine.6.2.2",
  342. new Object[]{derivedGrp.fName, key});
  343. }
  344. }
  345. }
  346. }
  347. // for each complex type, check the 3 constraints.
  348. // types need to be checked
  349. XSComplexTypeDecl[] types;
  350. SimpleLocator [] ctLocators;
  351. // to hold the errors
  352. // REVISIT: do we want to report all errors? or just one?
  353. //XMLSchemaError1D errors = new XMLSchemaError1D();
  354. // whether need to check this type again;
  355. // whether only do UPA checking
  356. boolean further, fullChecked;
  357. // if do all checkings, how many need to be checked again.
  358. int keepType;
  359. // i: grammar; j: type; k: error
  360. // for all grammars
  361. SymbolHash elemTable = new SymbolHash();
  362. for (int i = grammars.length-1, j, k; i >= 0; i--) {
  363. // get whether to skip EDC, and types need to be checked
  364. keepType = 0;
  365. fullChecked = grammars[i].fFullChecked;
  366. types = grammars[i].getUncheckedComplexTypeDecls();
  367. ctLocators = grammars[i].getUncheckedCTLocators();
  368. // for each type
  369. for (j = types.length-1; j >= 0; j--) {
  370. // if we've already full-checked this grammar, then
  371. // skip the EDC constraint
  372. if (!fullChecked) {
  373. // 1. Element Decl Consistent
  374. if (types[j].fParticle!=null) {
  375. elemTable.clear();
  376. try {
  377. checkElementDeclsConsistent(types[j], types[j].fParticle,
  378. elemTable, SGHandler);
  379. }
  380. catch (XMLSchemaException e) {
  381. reportSchemaError(errorReporter, ctLocators[j],
  382. e.getKey(),
  383. e.getArgs());
  384. }
  385. }
  386. }
  387. // 2. Particle Derivation
  388. if (types[j].fBaseType != null &&
  389. types[j].fBaseType != SchemaGrammar.fAnyType &&
  390. types[j].fDerivedBy == XSConstants.DERIVATION_RESTRICTION &&
  391. (types[j].fBaseType instanceof XSComplexTypeDecl)) {
  392. XSParticleDecl derivedParticle=types[j].fParticle;
  393. XSParticleDecl baseParticle=
  394. ((XSComplexTypeDecl)(types[j].fBaseType)).fParticle;
  395. if (derivedParticle==null && (!(baseParticle==null ||
  396. baseParticle.emptiable()))) {
  397. reportSchemaError(errorReporter,ctLocators[j],
  398. "derivation-ok-restriction.5.3.2",
  399. new Object[]{types[j].fName, types[j].fBaseType.getName()});
  400. }
  401. else if (derivedParticle!=null &&
  402. baseParticle!=null)
  403. try {
  404. particleValidRestriction(types[j].fParticle,
  405. SGHandler,
  406. ((XSComplexTypeDecl)(types[j].fBaseType)).fParticle,
  407. SGHandler);
  408. } catch (XMLSchemaException e) {
  409. reportSchemaError(errorReporter, ctLocators[j],
  410. e.getKey(),
  411. e.getArgs());
  412. reportSchemaError(errorReporter, ctLocators[j],
  413. "derivation-ok-restriction.5.4.2",
  414. new Object[]{types[j].fName});
  415. }
  416. }
  417. // 3. UPA
  418. // get the content model and check UPA
  419. XSCMValidator cm = types[j].getContentModel(cmBuilder);
  420. further = false;
  421. if (cm != null) {
  422. try {
  423. further = cm.checkUniqueParticleAttribution(SGHandler);
  424. } catch (XMLSchemaException e) {
  425. reportSchemaError(errorReporter, ctLocators[j],
  426. e.getKey(),
  427. e.getArgs());
  428. }
  429. }
  430. // now report all errors
  431. // REVISIT: do we want to report all errors? or just one?
  432. /*for (k = errors.getErrorCodeNum()-1; k >= 0; k--) {
  433. reportSchemaError(errorReporter, ctLocators[j],
  434. errors.getErrorCode(k),
  435. errors.getArgs(k));
  436. }*/
  437. // if we are doing all checkings, and this one needs further
  438. // checking, store it in the type array.
  439. if (!fullChecked && further)
  440. types[keepType++] = types[j];
  441. // clear errors for the next type.
  442. // REVISIT: do we want to report all errors? or just one?
  443. //errors.clear();
  444. }
  445. // we've done with the types in this grammar. if we are checking
  446. // all constraints, need to trim type array to a proper size:
  447. // only contain those need further checking.
  448. // and mark this grammar that it only needs UPA checking.
  449. if (!fullChecked) {
  450. grammars[i].setUncheckedTypeNum(keepType);
  451. grammars[i].fFullChecked = true;
  452. }
  453. }
  454. }
  455. /*
  456. Check that a given particle is a valid restriction of a base particle.
  457. */
  458. public static void checkElementDeclsConsistent(XSComplexTypeDecl type,
  459. XSParticleDecl particle,
  460. SymbolHash elemDeclHash,
  461. SubstitutionGroupHandler sgHandler)
  462. throws XMLSchemaException {
  463. // check for elements in the tree with the same name and namespace
  464. int pType = particle.fType;
  465. if (pType == XSParticleDecl.PARTICLE_WILDCARD)
  466. return;
  467. if (pType == XSParticleDecl.PARTICLE_ELEMENT) {
  468. XSElementDecl elem = (XSElementDecl)(particle.fValue);
  469. findElemInTable(type, elem, elemDeclHash);
  470. if (elem.fScope == XSConstants.SCOPE_GLOBAL) {
  471. // Check for subsitution groups.
  472. XSElementDecl[] subGroup = sgHandler.getSubstitutionGroup(elem);
  473. for (int i = 0; i < subGroup.length; i++) {
  474. findElemInTable(type, subGroup[i], elemDeclHash);
  475. }
  476. }
  477. return;
  478. }
  479. XSModelGroupImpl group = (XSModelGroupImpl)particle.fValue;
  480. for (int i = 0; i < group.fParticleCount; i++)
  481. checkElementDeclsConsistent(type, group.fParticles[i], elemDeclHash, sgHandler);
  482. }
  483. public static void findElemInTable(XSComplexTypeDecl type, XSElementDecl elem,
  484. SymbolHash elemDeclHash)
  485. throws XMLSchemaException {
  486. // How can we avoid this concat? LM.
  487. String name = elem.fName + "," + elem.fTargetNamespace;
  488. XSElementDecl existingElem = null;
  489. if ((existingElem = (XSElementDecl)(elemDeclHash.get(name))) == null) {
  490. // just add it in
  491. elemDeclHash.put(name, elem);
  492. }
  493. else {
  494. // If this is the same check element, we're O.K.
  495. if (elem == existingElem)
  496. return;
  497. if (elem.fType != existingElem.fType) {
  498. // Types are not the same
  499. throw new XMLSchemaException("cos-element-consistent",
  500. new Object[] {type.fName, elem.fName});
  501. }
  502. }
  503. }
  504. /*
  505. Check that a given particle is a valid restriction of a base particle.
  506. */
  507. private static void particleValidRestriction(XSParticleDecl dParticle,
  508. SubstitutionGroupHandler dSGHandler,
  509. XSParticleDecl bParticle,
  510. SubstitutionGroupHandler bSGHandler)
  511. throws XMLSchemaException {
  512. particleValidRestriction(dParticle, dSGHandler, bParticle, bSGHandler, true);
  513. }
  514. private static void particleValidRestriction(XSParticleDecl dParticle,
  515. SubstitutionGroupHandler dSGHandler,
  516. XSParticleDecl bParticle,
  517. SubstitutionGroupHandler bSGHandler,
  518. boolean checkWCOccurrence)
  519. throws XMLSchemaException {
  520. Vector dChildren = null;
  521. Vector bChildren = null;
  522. int dMinEffectiveTotalRange=OCCURRENCE_UNKNOWN;
  523. int dMaxEffectiveTotalRange=OCCURRENCE_UNKNOWN;
  524. // Check for empty particles. If either base or derived particle is empty,
  525. // (and the other isn't) it's an error.
  526. if (dParticle.isEmpty() && !bParticle.emptiable()) {
  527. throw new XMLSchemaException("cos-particle-restrict.a", null);
  528. }
  529. else if (!dParticle.isEmpty() && bParticle.isEmpty()) {
  530. throw new XMLSchemaException("cos-particle-restrict.b", null);
  531. }
  532. //
  533. // Do setup prior to invoking the Particle (Restriction) cases.
  534. // This involves:
  535. // - removing pointless occurrences for groups, and retrieving a vector of
  536. // non-pointless children
  537. // - turning top-level elements with substitution groups into CHOICE groups.
  538. //
  539. short dType = dParticle.fType;
  540. //
  541. // Handle pointless groups for the derived particle
  542. //
  543. if (dType == XSParticleDecl.PARTICLE_MODELGROUP) {
  544. dType = ((XSModelGroupImpl)dParticle.fValue).fCompositor;
  545. // Find a group, starting with this particle, with more than 1 child. There
  546. // may be none, and the particle of interest trivially becomes an element or
  547. // wildcard.
  548. XSParticleDecl dtmp = getNonUnaryGroup(dParticle);
  549. if (dtmp != dParticle) {
  550. // Particle has been replaced. Retrieve new type info.
  551. dParticle = dtmp;
  552. dType = dParticle.fType;
  553. if (dType == XSParticleDecl.PARTICLE_MODELGROUP)
  554. dType = ((XSModelGroupImpl)dParticle.fValue).fCompositor;
  555. }
  556. // Fill in a vector with the children of the particle, removing any
  557. // pointless model groups in the process.
  558. dChildren = removePointlessChildren(dParticle);
  559. }
  560. int dMinOccurs = dParticle.fMinOccurs;
  561. int dMaxOccurs = dParticle.fMaxOccurs;
  562. //
  563. // For elements which are the heads of substitution groups, treat as CHOICE
  564. //
  565. if (dSGHandler != null && dType == XSParticleDecl.PARTICLE_ELEMENT) {
  566. XSElementDecl dElement = (XSElementDecl)dParticle.fValue;
  567. if (dElement.fScope == XSConstants.SCOPE_GLOBAL) {
  568. // Check for subsitution groups. Treat any element that has a
  569. // subsitution group as a choice. Fill in the children vector with the
  570. // members of the substitution group
  571. XSElementDecl[] subGroup = dSGHandler.getSubstitutionGroup(dElement);
  572. if (subGroup.length >0 ) {
  573. // Now, set the type to be CHOICE. The "group" will have the same
  574. // occurrence information as the original particle.
  575. dType = XSModelGroupImpl.MODELGROUP_CHOICE;
  576. dMinEffectiveTotalRange = dMinOccurs;
  577. dMaxEffectiveTotalRange = dMaxOccurs;
  578. // Fill in the vector of children
  579. dChildren = new Vector(subGroup.length+1);
  580. for (int i = 0; i < subGroup.length; i++) {
  581. addElementToParticleVector(dChildren, subGroup[i]);
  582. }
  583. addElementToParticleVector(dChildren, dElement);
  584. // Set the handler to null, to indicate that we've finished handling
  585. // substitution groups for this particle.
  586. dSGHandler = null;
  587. }
  588. }
  589. }
  590. short bType = bParticle.fType;
  591. //
  592. // Handle pointless groups for the base particle
  593. //
  594. if (bType == XSParticleDecl.PARTICLE_MODELGROUP) {
  595. bType = ((XSModelGroupImpl)bParticle.fValue).fCompositor;
  596. // Find a group, starting with this particle, with more than 1 child. There
  597. // may be none, and the particle of interest trivially becomes an element or
  598. // wildcard.
  599. XSParticleDecl btmp = getNonUnaryGroup(bParticle);
  600. if (btmp != bParticle) {
  601. // Particle has been replaced. Retrieve new type info.
  602. bParticle = btmp;
  603. bType = bParticle.fType;
  604. if (bType == XSParticleDecl.PARTICLE_MODELGROUP)
  605. bType = ((XSModelGroupImpl)bParticle.fValue).fCompositor;
  606. }
  607. // Fill in a vector with the children of the particle, removing any
  608. // pointless model groups in the process.
  609. bChildren = removePointlessChildren(bParticle);
  610. }
  611. int bMinOccurs = bParticle.fMinOccurs;
  612. int bMaxOccurs = bParticle.fMaxOccurs;
  613. if (bSGHandler != null && bType == XSParticleDecl.PARTICLE_ELEMENT) {
  614. XSElementDecl bElement = (XSElementDecl)bParticle.fValue;
  615. if (bElement.fScope == XSConstants.SCOPE_GLOBAL) {
  616. // Check for subsitution groups. Treat any element that has a
  617. // subsitution group as a choice. Fill in the children vector with the
  618. // members of the substitution group
  619. XSElementDecl[] bsubGroup = bSGHandler.getSubstitutionGroup(bElement);
  620. if (bsubGroup.length >0 ) {
  621. // Now, set the type to be CHOICE
  622. bType = XSModelGroupImpl.MODELGROUP_CHOICE;
  623. bChildren = new Vector(bsubGroup.length+1);
  624. for (int i = 0; i < bsubGroup.length; i++) {
  625. addElementToParticleVector(bChildren, bsubGroup[i]);
  626. }
  627. addElementToParticleVector(bChildren, bElement);
  628. // Set the handler to null, to indicate that we've finished handling
  629. // substitution groups for this particle.
  630. bSGHandler = null;
  631. }
  632. }
  633. }
  634. //
  635. // O.K. - Figure out which particle derivation rule applies and call it
  636. //
  637. switch (dType) {
  638. case XSParticleDecl.PARTICLE_ELEMENT:
  639. {
  640. switch (bType) {
  641. // Elt:Elt NameAndTypeOK
  642. case XSParticleDecl.PARTICLE_ELEMENT:
  643. {
  644. checkNameAndTypeOK((XSElementDecl)dParticle.fValue,dMinOccurs,dMaxOccurs,
  645. (XSElementDecl)bParticle.fValue,bMinOccurs,bMaxOccurs);
  646. return;
  647. }
  648. // Elt:Any NSCompat
  649. case XSParticleDecl.PARTICLE_WILDCARD:
  650. {
  651. checkNSCompat((XSElementDecl)dParticle.fValue,dMinOccurs,dMaxOccurs,
  652. (XSWildcardDecl)bParticle.fValue,bMinOccurs,bMaxOccurs,
  653. checkWCOccurrence);
  654. return;
  655. }
  656. // Elt:All RecurseAsIfGroup
  657. case XSModelGroupImpl.MODELGROUP_CHOICE:
  658. {
  659. // Treat the element as if it were in a group of the same type
  660. // as the base Particle
  661. dChildren = new Vector();
  662. dChildren.addElement(dParticle);
  663. checkRecurseLax(dChildren, 1, 1, dSGHandler,
  664. bChildren, bMinOccurs, bMaxOccurs, bSGHandler);
  665. return;
  666. }
  667. case XSModelGroupImpl.MODELGROUP_SEQUENCE:
  668. case XSModelGroupImpl.MODELGROUP_ALL:
  669. {
  670. // Treat the element as if it were in a group of the same type
  671. // as the base Particle
  672. dChildren = new Vector();
  673. dChildren.addElement(dParticle);
  674. checkRecurse(dChildren, 1, 1, dSGHandler,
  675. bChildren, bMinOccurs, bMaxOccurs, bSGHandler);
  676. return;
  677. }
  678. default:
  679. {
  680. throw new XMLSchemaException("Internal-Error",
  681. new Object[]{"in particleValidRestriction"});
  682. }
  683. }
  684. }
  685. case XSParticleDecl.PARTICLE_WILDCARD:
  686. {
  687. switch (bType) {
  688. // Any:Any NSSubset
  689. case XSParticleDecl.PARTICLE_WILDCARD:
  690. {
  691. checkNSSubset((XSWildcardDecl)dParticle.fValue, dMinOccurs, dMaxOccurs,
  692. (XSWildcardDecl)bParticle.fValue, bMinOccurs, bMaxOccurs);
  693. return;
  694. }
  695. case XSModelGroupImpl.MODELGROUP_CHOICE:
  696. case XSModelGroupImpl.MODELGROUP_SEQUENCE:
  697. case XSModelGroupImpl.MODELGROUP_ALL:
  698. case XSParticleDecl.PARTICLE_ELEMENT:
  699. {
  700. throw new XMLSchemaException("cos-particle-restrict.2",
  701. new Object[]{"any:choice,sequence,all,elt"});
  702. }
  703. default:
  704. {
  705. throw new XMLSchemaException("Internal-Error",
  706. new Object[]{"in particleValidRestriction"});
  707. }
  708. }
  709. }
  710. case XSModelGroupImpl.MODELGROUP_ALL:
  711. {
  712. switch (bType) {
  713. // All:Any NSRecurseCheckCardinality
  714. case XSParticleDecl.PARTICLE_WILDCARD:
  715. {
  716. if (dMinEffectiveTotalRange == OCCURRENCE_UNKNOWN)
  717. dMinEffectiveTotalRange = dParticle.minEffectiveTotalRange();
  718. if (dMaxEffectiveTotalRange == OCCURRENCE_UNKNOWN)
  719. dMaxEffectiveTotalRange = dParticle.maxEffectiveTotalRange();
  720. checkNSRecurseCheckCardinality(dChildren, dMinEffectiveTotalRange,
  721. dMaxEffectiveTotalRange,
  722. dSGHandler,
  723. bParticle,bMinOccurs,bMaxOccurs,
  724. checkWCOccurrence);
  725. return;
  726. }
  727. case XSModelGroupImpl.MODELGROUP_ALL:
  728. {
  729. checkRecurse(dChildren, dMinOccurs, dMaxOccurs, dSGHandler,
  730. bChildren, bMinOccurs, bMaxOccurs, bSGHandler);
  731. return;
  732. }
  733. case XSModelGroupImpl.MODELGROUP_CHOICE:
  734. case XSModelGroupImpl.MODELGROUP_SEQUENCE:
  735. case XSParticleDecl.PARTICLE_ELEMENT:
  736. {
  737. throw new XMLSchemaException("cos-particle-restrict.2",
  738. new Object[]{"all:choice,sequence,elt"});
  739. }
  740. default:
  741. {
  742. throw new XMLSchemaException("Internal-Error",
  743. new Object[]{"in particleValidRestriction"});
  744. }
  745. }
  746. }
  747. case XSModelGroupImpl.MODELGROUP_CHOICE:
  748. {
  749. switch (bType) {
  750. // Choice:Any NSRecurseCheckCardinality
  751. case XSParticleDecl.PARTICLE_WILDCARD:
  752. {
  753. if (dMinEffectiveTotalRange == OCCURRENCE_UNKNOWN)
  754. dMinEffectiveTotalRange = dParticle.minEffectiveTotalRange();
  755. if (dMaxEffectiveTotalRange == OCCURRENCE_UNKNOWN)
  756. dMaxEffectiveTotalRange = dParticle.maxEffectiveTotalRange();
  757. checkNSRecurseCheckCardinality(dChildren, dMinEffectiveTotalRange,
  758. dMaxEffectiveTotalRange,
  759. dSGHandler,
  760. bParticle,bMinOccurs,bMaxOccurs,
  761. checkWCOccurrence);
  762. return;
  763. }
  764. case XSModelGroupImpl.MODELGROUP_CHOICE:
  765. {
  766. checkRecurseLax(dChildren, dMinOccurs, dMaxOccurs, dSGHandler,
  767. bChildren, bMinOccurs, bMaxOccurs, bSGHandler);
  768. return;
  769. }
  770. case XSModelGroupImpl.MODELGROUP_ALL:
  771. case XSModelGroupImpl.MODELGROUP_SEQUENCE:
  772. case XSParticleDecl.PARTICLE_ELEMENT:
  773. {
  774. throw new XMLSchemaException("cos-particle-restrict.2",
  775. new Object[]{"choice:all,sequence,elt"});
  776. }
  777. default:
  778. {
  779. throw new XMLSchemaException("Internal-Error",
  780. new Object[]{"in particleValidRestriction"});
  781. }
  782. }
  783. }
  784. case XSModelGroupImpl.MODELGROUP_SEQUENCE:
  785. {
  786. switch (bType) {
  787. // Choice:Any NSRecurseCheckCardinality
  788. case XSParticleDecl.PARTICLE_WILDCARD:
  789. {
  790. if (dMinEffectiveTotalRange == OCCURRENCE_UNKNOWN)
  791. dMinEffectiveTotalRange = dParticle.minEffectiveTotalRange();
  792. if (dMaxEffectiveTotalRange == OCCURRENCE_UNKNOWN)
  793. dMaxEffectiveTotalRange = dParticle.maxEffectiveTotalRange();
  794. checkNSRecurseCheckCardinality(dChildren, dMinEffectiveTotalRange,
  795. dMaxEffectiveTotalRange,
  796. dSGHandler,
  797. bParticle,bMinOccurs,bMaxOccurs,
  798. checkWCOccurrence);
  799. return;
  800. }
  801. case XSModelGroupImpl.MODELGROUP_ALL:
  802. {
  803. checkRecurseUnordered(dChildren, dMinOccurs, dMaxOccurs, dSGHandler,
  804. bChildren, bMinOccurs, bMaxOccurs, bSGHandler);
  805. return;
  806. }
  807. case XSModelGroupImpl.MODELGROUP_SEQUENCE:
  808. {
  809. checkRecurse(dChildren, dMinOccurs, dMaxOccurs, dSGHandler,
  810. bChildren, bMinOccurs, bMaxOccurs, bSGHandler);
  811. return;
  812. }
  813. case XSModelGroupImpl.MODELGROUP_CHOICE:
  814. {
  815. int min1 = dMinOccurs * dChildren.size();
  816. int max1 = (dMaxOccurs == SchemaSymbols.OCCURRENCE_UNBOUNDED)?
  817. dMaxOccurs : dMaxOccurs * dChildren.size();
  818. checkMapAndSum(dChildren, min1, max1, dSGHandler,
  819. bChildren, bMinOccurs, bMaxOccurs, bSGHandler);
  820. return;
  821. }
  822. case XSParticleDecl.PARTICLE_ELEMENT:
  823. {
  824. throw new XMLSchemaException("cos-particle-restrict.2",
  825. new Object[]{"seq:elt"});
  826. }
  827. default:
  828. {
  829. throw new XMLSchemaException("Internal-Error",
  830. new Object[]{"in particleValidRestriction"});
  831. }
  832. }
  833. }
  834. }
  835. }
  836. private static void addElementToParticleVector (Vector v, XSElementDecl d) {
  837. XSParticleDecl p = new XSParticleDecl();
  838. p.fValue = d;
  839. p.fType = XSParticleDecl.PARTICLE_ELEMENT;
  840. v.addElement(p);
  841. }
  842. private static XSParticleDecl getNonUnaryGroup(XSParticleDecl p) {
  843. if (p.fType == XSParticleDecl.PARTICLE_ELEMENT ||
  844. p.fType == XSParticleDecl.PARTICLE_WILDCARD)
  845. return p;
  846. if (p.fMinOccurs==1 && p.fMaxOccurs==1 &&
  847. p.fValue!=null && ((XSModelGroupImpl)p.fValue).fParticleCount == 1)
  848. return getNonUnaryGroup(((XSModelGroupImpl)p.fValue).fParticles[0]);
  849. else
  850. return p;
  851. }
  852. private static Vector removePointlessChildren(XSParticleDecl p) {
  853. if (p.fType == XSParticleDecl.PARTICLE_ELEMENT ||
  854. p.fType == XSParticleDecl.PARTICLE_WILDCARD)
  855. return null;
  856. Vector children = new Vector();
  857. XSModelGroupImpl group = (XSModelGroupImpl)p.fValue;
  858. for (int i = 0; i < group.fParticleCount; i++)
  859. gatherChildren(group.fCompositor, group.fParticles[i], children);
  860. return children;
  861. }
  862. private static void gatherChildren(int parentType, XSParticleDecl p, Vector children) {
  863. int min = p.fMinOccurs;
  864. int max = p.fMaxOccurs;
  865. int type = p.fType;
  866. if (type == XSParticleDecl.PARTICLE_MODELGROUP)
  867. type = ((XSModelGroupImpl)p.fValue).fCompositor;
  868. if (type == XSParticleDecl.PARTICLE_ELEMENT ||
  869. type== XSParticleDecl.PARTICLE_WILDCARD) {
  870. children.addElement(p);
  871. return;
  872. }
  873. if (! (min==1 && max==1)) {
  874. children.addElement(p);
  875. }
  876. else if (parentType == type) {
  877. XSModelGroupImpl group = (XSModelGroupImpl)p.fValue;
  878. for (int i = 0; i < group.fParticleCount; i++)
  879. gatherChildren(type, group.fParticles[i], children);
  880. }
  881. else if (!p.isEmpty()) {
  882. children.addElement(p);
  883. }
  884. }
  885. private static void checkNameAndTypeOK(XSElementDecl dElement, int dMin, int dMax,
  886. XSElementDecl bElement, int bMin, int bMax)
  887. throws XMLSchemaException {
  888. //
  889. // Check that the names are the same
  890. //
  891. if (dElement.fName != bElement.fName ||
  892. dElement.fTargetNamespace != bElement.fTargetNamespace) {
  893. throw new XMLSchemaException(
  894. "rcase-NameAndTypeOK.1",new Object[]{dElement.fName,
  895. dElement.fTargetNamespace, bElement.fName, bElement.fTargetNamespace});
  896. }
  897. //
  898. // Check nillable
  899. //
  900. if (!bElement.getNillable() && dElement.getNillable()) {
  901. throw new XMLSchemaException("rcase-NameAndTypeOK.2",
  902. new Object[]{dElement.fName});
  903. }
  904. //
  905. // Check occurrence range
  906. //
  907. if (!checkOccurrenceRange(dMin, dMax, bMin, bMax)) {
  908. throw new XMLSchemaException("rcase-NameAndTypeOK.3",
  909. new Object[]{
  910. dElement.fName,
  911. Integer.toString(dMin),
  912. dMax==SchemaSymbols.OCCURRENCE_UNBOUNDED?"unbounded":Integer.toString(dMax),
  913. Integer.toString(bMin),
  914. bMax==SchemaSymbols.OCCURRENCE_UNBOUNDED?"unbounded":Integer.toString(bMax)});
  915. }
  916. //
  917. // Check for consistent fixed values
  918. //
  919. if (bElement.getConstraintType() == XSConstants.VC_FIXED) {
  920. // derived one has to have a fixed value
  921. if (dElement.getConstraintType() != XSConstants.VC_FIXED) {
  922. throw new XMLSchemaException("rcase-NameAndTypeOK.4.a",
  923. new Object[]{dElement.fName, bElement.fDefault.stringValue()});
  924. }
  925. // get simple type
  926. boolean isSimple = false;
  927. if (dElement.fType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE ||
  928. ((XSComplexTypeDecl)dElement.fType).fContentType == XSComplexTypeDecl.CONTENTTYPE_SIMPLE) {
  929. isSimple = true;
  930. }
  931. // if there is no simple type, then compare based on string
  932. if (!isSimple && !bElement.fDefault.normalizedValue.equals(dElement.fDefault.normalizedValue) ||
  933. isSimple && !bElement.fDefault.actualValue.equals(dElement.fDefault.actualValue)) {
  934. throw new XMLSchemaException("rcase-NameAndTypeOK.4.b",
  935. new Object[]{dElement.fName,
  936. dElement.fDefault.stringValue(),
  937. bElement.fDefault.stringValue()});
  938. }
  939. }
  940. //
  941. // Check identity constraints
  942. //
  943. checkIDConstraintRestriction(dElement, bElement);
  944. //
  945. // Check for disallowed substitutions
  946. //
  947. int blockSet1 = dElement.fBlock;
  948. int blockSet2 = bElement.fBlock;
  949. if (((blockSet1 & blockSet2)!=blockSet2) ||
  950. (blockSet1==XSConstants.DERIVATION_NONE && blockSet2!=XSConstants.DERIVATION_NONE))
  951. throw new XMLSchemaException("rcase-NameAndTypeOK.6",
  952. new Object[]{dElement.fName});
  953. //
  954. // Check that the derived element's type is derived from the base's.
  955. //
  956. if (!checkTypeDerivationOk(dElement.fType, bElement.fType,
  957. (short)(XSConstants.DERIVATION_EXTENSION|XSConstants.DERIVATION_LIST|XSConstants.DERIVATION_UNION))) {
  958. throw new XMLSchemaException("rcase-NameAndTypeOK.7",
  959. new Object[]{dElement.fName, dElement.fType.getName(), bElement.fType.getName()});
  960. }
  961. }
  962. private static void checkIDConstraintRestriction(XSElementDecl derivedElemDecl,
  963. XSElementDecl baseElemDecl)
  964. throws XMLSchemaException {
  965. // TODO
  966. } // checkIDConstraintRestriction
  967. private static boolean checkOccurrenceRange(int min1, int max1, int min2, int max2) {
  968. if ((min1 >= min2) &&
  969. ((max2==SchemaSymbols.OCCURRENCE_UNBOUNDED) ||
  970. (max1!=SchemaSymbols.OCCURRENCE_UNBOUNDED && max1<=max2)))
  971. return true;
  972. else
  973. return false;
  974. }
  975. private static void checkNSCompat(XSElementDecl elem, int min1, int max1,
  976. XSWildcardDecl wildcard, int min2, int max2,
  977. boolean checkWCOccurrence)
  978. throws XMLSchemaException {
  979. // check Occurrence ranges
  980. if (checkWCOccurrence && !checkOccurrenceRange(min1,max1,min2,max2)) {
  981. throw new XMLSchemaException("rcase-NSCompat.2",
  982. new Object[]{
  983. elem.fName,
  984. Integer.toString(min1),
  985. max1==SchemaSymbols.OCCURRENCE_UNBOUNDED?"unbounded":Integer.toString(max1),
  986. Integer.toString(min2),
  987. max2==SchemaSymbols.OCCURRENCE_UNBOUNDED?"unbounded":Integer.toString(max2)});
  988. }
  989. // check wildcard allows namespace of element
  990. if (!wildcard.allowNamespace(elem.fTargetNamespace)) {
  991. throw new XMLSchemaException("rcase-NSCompat.1",
  992. new Object[]{elem.fName,elem.fTargetNamespace});
  993. }
  994. }
  995. private static void checkNSSubset(XSWildcardDecl dWildcard, int min1, int max1,
  996. XSWildcardDecl bWildcard, int min2, int max2)
  997. throws XMLSchemaException {
  998. // check Occurrence ranges
  999. if (!checkOccurrenceRange(min1,max1,min2,max2)) {
  1000. throw new XMLSchemaException("rcase-NSSubset.2", new Object[]{
  1001. Integer.toString(min1),
  1002. max1==SchemaSymbols.OCCURRENCE_UNBOUNDED?"unbounded":Integer.toString(max1),
  1003. Integer.toString(min2),
  1004. max2==SchemaSymbols.OCCURRENCE_UNBOUNDED?"unbounded":Integer.toString(max2)});
  1005. }
  1006. // check wildcard subset
  1007. if (!dWildcard.isSubsetOf(bWildcard)) {
  1008. throw new XMLSchemaException("rcase-NSSubset.1", null);
  1009. }
  1010. if (dWildcard.weakerProcessContents(bWildcard)) {
  1011. throw new XMLSchemaException("rcase-NSSubset.3",
  1012. new Object[]{dWildcard.getProcessContentsAsString(),
  1013. bWildcard.getProcessContentsAsString()});
  1014. }
  1015. }
  1016. private static void checkNSRecurseCheckCardinality(Vector children, int min1, int max1,
  1017. SubstitutionGroupHandler dSGHandler,
  1018. XSParticleDecl wildcard, int min2, int max2,
  1019. boolean checkWCOccurrence)
  1020. throws XMLSchemaException {
  1021. // check Occurrence ranges
  1022. if (checkWCOccurrence && !checkOccurrenceRange(min1,max1,min2,max2)) {
  1023. throw new XMLSchemaException("rcase-NSRecurseCheckCardinality.2", new Object[]{
  1024. Integer.toString(min1),
  1025. max1==SchemaSymbols.OCCURRENCE_UNBOUNDED?"unbounded":Integer.toString(max1),
  1026. Integer.toString(min2),
  1027. max2==SchemaSymbols.OCCURRENCE_UNBOUNDED?"unbounded":Integer.toString(max2)});
  1028. }
  1029. // Check that each member of the group is a valid restriction of the wildcard
  1030. int count = children.size();
  1031. try {
  1032. for (int i = 0; i < count; i++) {
  1033. XSParticleDecl particle1 = (XSParticleDecl)children.elementAt(i);
  1034. particleValidRestriction(particle1, dSGHandler, wildcard, null, false);
  1035. }
  1036. }
  1037. // REVISIT: should we really just ignore original cause of this error?
  1038. // how can we report it?
  1039. catch (XMLSchemaException e) {
  1040. throw new XMLSchemaException("rcase-NSRecurseCheckCardinality.1", null);
  1041. }
  1042. }
  1043. private static void checkRecurse(Vector dChildren, int min1, int max1,
  1044. SubstitutionGroupHandler dSGHandler,
  1045. Vector bChildren, int min2, int max2,
  1046. SubstitutionGroupHandler bSGHandler)
  1047. throws XMLSchemaException {
  1048. // check Occurrence ranges
  1049. if (!checkOccurrenceRange(min1,max1,min2,max2)) {
  1050. throw new XMLSchemaException("rcase-Recurse.1", new Object[]{
  1051. Integer.toString(min1),
  1052. max1==SchemaSymbols.OCCURRENCE_UNBOUNDED?"unbounded":Integer.toString(max1),
  1053. Integer.toString(min2),
  1054. max2==SchemaSymbols.OCCURRENCE_UNBOUNDED?"unbounded":Integer.toString(max2)});
  1055. }
  1056. int count1= dChildren.size();
  1057. int count2= bChildren.size();
  1058. int current = 0;
  1059. label: for (int i = 0; i<count1; i++) {
  1060. XSParticleDecl particle1 = (XSParticleDecl)dChildren.elementAt(i);
  1061. for (int j = current; j<count2; j++) {
  1062. XSParticleDecl particle2 = (XSParticleDecl)bChildren.elementAt(j);
  1063. current +=1;
  1064. try {
  1065. particleValidRestriction(particle1, dSGHandler, particle2, bSGHandler);
  1066. continue label;
  1067. }
  1068. catch (XMLSchemaException e) {
  1069. if (!particle2.emptiable())
  1070. throw new XMLSchemaException("rcase-Recurse.2", null);
  1071. }
  1072. }
  1073. throw new XMLSchemaException("rcase-Recurse.2", null);
  1074. }
  1075. // Now, see if there are some elements in the base we didn't match up
  1076. for (int j=current; j < count2; j++) {
  1077. XSParticleDecl particle2 = (XSParticleDecl)bChildren.elementAt(j);
  1078. if (!particle2.emptiable()) {
  1079. throw new XMLSchemaException("rcase-Recurse.2", null);
  1080. }
  1081. }
  1082. }
  1083. private static void checkRecurseUnordered(Vector dChildren, int min1, int max1,
  1084. SubstitutionGroupHandler dSGHandler,
  1085. Vector bChildren, int min2, int max2,
  1086. SubstitutionGroupHandler bSGHandler)
  1087. throws XMLSchemaException {
  1088. // check Occurrence ranges
  1089. if (!checkOccurrenceRange(min1,max1,min2,max2)) {
  1090. throw new XMLSchemaException("rcase-RecurseUnordered.1", new Object[]{
  1091. Integer.toString(min1),
  1092. max1==SchemaSymbols.OCCURRENCE_UNBOUNDED?"unbounded":Integer.toString(max1),
  1093. Integer.toString(min2),
  1094. max2==SchemaSymbols.OCCURRENCE_UNBOUNDED?"unbounded":Integer.toString(max2)});
  1095. }
  1096. int count1= dChildren.size();
  1097. int count2 = bChildren.size();
  1098. boolean foundIt[] = new boolean[count2];
  1099. label: for (int i = 0; i<count1; i++) {
  1100. XSParticleDecl particle1 = (XSParticleDecl)dChildren.elementAt(i);
  1101. for (int j = 0; j<count2; j++) {
  1102. XSParticleDecl particle2 = (XSParticleDecl)bChildren.elementAt(j);
  1103. try {
  1104. particleValidRestriction(particle1, dSGHandler, particle2, bSGHandler);
  1105. if (foundIt[j])
  1106. throw new XMLSchemaException("rcase-RecurseUnordered.2", null);
  1107. else
  1108. foundIt[j]=true;
  1109. continue label;
  1110. }
  1111. catch (XMLSchemaException e) {
  1112. }
  1113. }
  1114. // didn't find a match. Detect an error
  1115. throw new XMLSchemaException("rcase-RecurseUnordered.2", null);
  1116. }
  1117. // Now, see if there are some elements in the base we didn't match up
  1118. for (int j=0; j < count2; j++) {
  1119. XSParticleDecl particle2 = (XSParticleDecl)bChildren.elementAt(j);
  1120. if (!foundIt[j] && !particle2.emptiable()) {
  1121. throw new XMLSchemaException("rcase-RecurseUnordered.2", null);
  1122. }
  1123. }
  1124. }
  1125. private static void checkRecurseLax(Vector dChildren, int min1, int max1,
  1126. SubstitutionGroupHandler dSGHandler,
  1127. Vector bChildren, int min2, int max2,
  1128. SubstitutionGroupHandler bSGHandler)
  1129. throws XMLSchemaException {
  1130. // check Occurrence ranges
  1131. if (!checkOccurrenceRange(min1,max1,min2,max2)) {
  1132. throw new XMLSchemaException("rcase-RecurseLax.1", new Object[]{
  1133. Integer.toString(min1),
  1134. max1==SchemaSymbols.OCCURRENCE_UNBOUNDED?"unbounded":Integer.toString(max1),
  1135. Integer.toString(min2),
  1136. max2==SchemaSymbols.OCCURRENCE_UNBOUNDED?"unbounded":Integer.toString(max2)});
  1137. }
  1138. int count1= dChildren.size();
  1139. int count2 = bChildren.size();
  1140. int current = 0;
  1141. label: for (int i = 0; i<count1; i++) {
  1142. XSParticleDecl particle1 = (XSParticleDecl)dChildren.elementAt(i);
  1143. for (int j = current; j<count2; j++) {
  1144. XSParticleDecl particle2 = (XSParticleDecl)bChildren.elementAt(j);
  1145. current +=1;
  1146. try {
  1147. particleValidRestriction(particle1, dSGHandler, particle2, bSGHandler);
  1148. continue label;
  1149. }
  1150. catch (XMLSchemaException e) {
  1151. }
  1152. }
  1153. // didn't find a match. Detect an error
  1154. throw new XMLSchemaException("rcase-RecurseLax.2", null);
  1155. }
  1156. }
  1157. private static void checkMapAndSum(Vector dChildren, int min1, int max1,
  1158. SubstitutionGroupHandler dSGHandler,
  1159. Vector bChildren, int min2, int max2,
  1160. SubstitutionGroupHandler bSGHandler)
  1161. throws XMLSchemaException {
  1162. // See if the sequence group is a valid restriction of the choice
  1163. // Here is an example of a valid restriction:
  1164. // <choice minOccurs="2">
  1165. // <a/>
  1166. // <b/>
  1167. // <c/>
  1168. // </choice>
  1169. //
  1170. // <sequence>
  1171. // <b/>
  1172. // <a/>
  1173. // </sequence>
  1174. // check Occurrence ranges
  1175. if (!checkOccurrenceRange(min1,max1,min2,max2)) {
  1176. throw new XMLSchemaException("rcase-MapAndSum.2",
  1177. new Object[]{Integer.toString(min1),
  1178. max1==SchemaSymbols.OCCURRENCE_UNBOUNDED?"unbounded":Integer.toString(max1),
  1179. Integer.toString(min2),
  1180. max2==SchemaSymbols.OCCURRENCE_UNBOUNDED?"unbounded":Integer.toString(max2)});
  1181. }
  1182. int count1 = dChildren.size();
  1183. int count2 = bChildren.size();
  1184. label: for (int i = 0; i<count1; i++) {
  1185. XSParticleDecl particle1 = (XSParticleDecl)dChildren.elementAt(i);
  1186. for (int j = 0; j<count2; j++) {
  1187. XSParticleDecl particle2 = (XSParticleDecl)bChildren.elementAt(j);
  1188. try {
  1189. particleValidRestriction(particle1, dSGHandler, particle2, bSGHandler);
  1190. continue label;
  1191. }
  1192. catch (XMLSchemaException e) {
  1193. }
  1194. }
  1195. // didn't find a match. Detect an error
  1196. throw new XMLSchemaException("rcase-MapAndSum.1", null);
  1197. }
  1198. }
  1199. // to check whether two element overlap, as defined in constraint UPA
  1200. public static boolean overlapUPA(XSElementDecl element1,
  1201. XSElementDecl element2,
  1202. SubstitutionGroupHandler sgHandler) {
  1203. // if the two element have the same name and namespace,
  1204. if (element1.fName == element2.fName &&
  1205. element1.fTargetNamespace == element2.fTargetNamespace) {
  1206. return true;
  1207. }
  1208. // or if there is an element decl in element1's substitution group,
  1209. // who has the same name/namespace with element2
  1210. XSElementDecl[] subGroup = sgHandler.getSubstitutionGroup(element1);
  1211. for (int i = subGroup.length-1; i >= 0; i--) {
  1212. if (subGroup[i].fName == element2.fName &&
  1213. subGroup[i].fTargetNamespace == element2.fTargetNamespace) {
  1214. return true;
  1215. }
  1216. }
  1217. // or if there is an element decl in element2's substitution group,
  1218. // who has the same name/namespace with element1
  1219. subGroup = sgHandler.getSubstitutionGroup(element2);
  1220. for (int i = subGroup.length-1; i >= 0; i--) {
  1221. if (subGroup[i].fName == element1.fName &&
  1222. subGroup[i].fTargetNamespace == element1.fTargetNamespace) {
  1223. return true;
  1224. }
  1225. }
  1226. return false;
  1227. }
  1228. // to check whether an element overlaps with a wildcard,
  1229. // as defined in constraint UPA
  1230. public static boolean overlapUPA(XSElementDecl element,
  1231. XSWildcardDecl wildcard,
  1232. SubstitutionGroupHandler sgHandler) {
  1233. // if the wildcard allows the element
  1234. if (wildcard.allowNamespace(element.fTargetNamespace))
  1235. return true;
  1236. // or if the wildcard allows any element in the substitution group
  1237. XSElementDecl[] subGroup = sgHandler.getSubstitutionGroup(element);
  1238. for (int i = subGroup.length-1; i >= 0; i--) {
  1239. if (wildcard.allowNamespace(subGroup[i].fTargetNamespace))
  1240. return true;
  1241. }
  1242. return false;
  1243. }
  1244. public static boolean overlapUPA(XSWildcardDecl wildcard1,
  1245. XSWildcardDecl wildcard2) {
  1246. // if the intersection of the two wildcard is not empty list
  1247. XSWildcardDecl intersect = wildcard1.performIntersectionWith(wildcard2, wildcard1.fProcessContents);
  1248. if (intersect == null ||
  1249. intersect.fType != XSWildcardDecl.NSCONSTRAINT_LIST ||
  1250. intersect.fNamespaceList.length != 0) {
  1251. return true;
  1252. }
  1253. return false;
  1254. }
  1255. // call one of the above methods according to the type of decls
  1256. public static boolean overlapUPA(Object decl1, Object decl2,
  1257. SubstitutionGroupHandler sgHandler) {
  1258. if (decl1 instanceof XSElementDecl) {
  1259. if (decl2 instanceof XSElementDecl) {
  1260. return overlapUPA((XSElementDecl)decl1,
  1261. (XSElementDecl)decl2,
  1262. sgHandler);
  1263. } else {
  1264. return overlapUPA((XSElementDecl)decl1,
  1265. (XSWildcardDecl)decl2,
  1266. sgHandler);
  1267. }
  1268. } else {
  1269. if (decl2 instanceof XSElementDecl) {
  1270. return overlapUPA((XSElementDecl)decl2,
  1271. (XSWildcardDecl)decl1,
  1272. sgHandler);
  1273. } else {
  1274. return overlapUPA((XSWildcardDecl)decl1,
  1275. (XSWildcardDecl)decl2);
  1276. }
  1277. }
  1278. }
  1279. } // class XSContraints