1. /*
  2. * The Apache Software License, Version 1.1
  3. *
  4. *
  5. * Copyright (c) 1999-2004 The Apache Software Foundation.
  6. * All rights 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 java.io.IOException;
  59. import java.util.Enumeration;
  60. import java.util.Hashtable;
  61. import java.util.HashMap;
  62. import java.util.Stack;
  63. import java.util.Vector;
  64. import com.sun.org.apache.xerces.internal.impl.Constants;
  65. import com.sun.org.apache.xerces.internal.impl.RevalidationHandler;
  66. import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter;
  67. import com.sun.org.apache.xerces.internal.impl.dv.DatatypeException;
  68. import com.sun.org.apache.xerces.internal.impl.dv.InvalidDatatypeValueException;
  69. import com.sun.org.apache.xerces.internal.impl.dv.ValidatedInfo;
  70. import com.sun.org.apache.xerces.internal.impl.dv.XSSimpleType;
  71. import com.sun.org.apache.xerces.internal.impl.dv.xs.XSSimpleTypeDecl;
  72. import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager;
  73. import com.sun.org.apache.xerces.internal.impl.validation.ValidationState;
  74. import com.sun.org.apache.xerces.internal.impl.xs.identity.Field;
  75. import com.sun.org.apache.xerces.internal.impl.xs.identity.FieldActivator;
  76. import com.sun.org.apache.xerces.internal.impl.xs.identity.IdentityConstraint;
  77. import com.sun.org.apache.xerces.internal.impl.xs.identity.KeyRef;
  78. import com.sun.org.apache.xerces.internal.impl.xs.identity.Selector;
  79. import com.sun.org.apache.xerces.internal.impl.xs.identity.UniqueOrKey;
  80. import com.sun.org.apache.xerces.internal.impl.xs.identity.ValueStore;
  81. import com.sun.org.apache.xerces.internal.impl.xs.identity.XPathMatcher;
  82. import com.sun.org.apache.xerces.internal.impl.xs.models.CMBuilder;
  83. import com.sun.org.apache.xerces.internal.impl.xs.models.CMNodeFactory;
  84. import com.sun.org.apache.xerces.internal.impl.xs.models.XSCMValidator;
  85. import com.sun.org.apache.xerces.internal.xs.XSConstants;
  86. import com.sun.org.apache.xerces.internal.xs.XSObjectList;
  87. import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition;
  88. import com.sun.org.apache.xerces.internal.util.AugmentationsImpl;
  89. import com.sun.org.apache.xerces.internal.util.IntStack;
  90. import com.sun.org.apache.xerces.internal.util.SymbolTable;
  91. import com.sun.org.apache.xerces.internal.util.XMLChar;
  92. import com.sun.org.apache.xerces.internal.util.XMLResourceIdentifierImpl;
  93. import com.sun.org.apache.xerces.internal.util.XMLSymbols;
  94. import com.sun.org.apache.xerces.internal.xni.Augmentations;
  95. import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
  96. import com.sun.org.apache.xerces.internal.xni.QName;
  97. import com.sun.org.apache.xerces.internal.xni.XMLAttributes;
  98. import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler;
  99. import com.sun.org.apache.xerces.internal.xni.XMLLocator;
  100. import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier;
  101. import com.sun.org.apache.xerces.internal.xni.XMLString;
  102. import com.sun.org.apache.xerces.internal.xni.XNIException;
  103. import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription;
  104. import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool;
  105. import com.sun.org.apache.xerces.internal.xni.parser.XMLComponent;
  106. import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
  107. import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
  108. import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentFilter;
  109. import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource;
  110. import com.sun.org.apache.xerces.internal.xni.parser.XMLEntityResolver;
  111. import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
  112. import com.sun.org.apache.xerces.internal.xs.AttributePSVI;
  113. import com.sun.org.apache.xerces.internal.xs.ElementPSVI;
  114. import com.sun.org.apache.xerces.internal.xs.XSComplexTypeDefinition;
  115. /**
  116. * The XML Schema validator. The validator implements a document
  117. * filter: receiving document events from the scanner; validating
  118. * the content and structure; augmenting the InfoSet, if applicable;
  119. * and notifying the parser of the information resulting from the
  120. * validation process.
  121. * <p>
  122. * This component requires the following features and properties from the
  123. * component manager that uses it:
  124. * <ul>
  125. * <li>http://xml.org/sax/features/validation</li>
  126. * <li>http://apache.org/xml/properties/internal/symbol-table</li>
  127. * <li>http://apache.org/xml/properties/internal/error-reporter</li>
  128. * <li>http://apache.org/xml/properties/internal/entity-resolver</li>
  129. * </ul>
  130. *
  131. * @author Sandy Gao IBM
  132. * @author Elena Litani IBM
  133. * @author Andy Clark IBM
  134. * @author Neeraj Bajaj, Sun Microsystems, inc.
  135. * @version $Id: XMLSchemaValidator.java,v 1.155 2004/03/25 04:03:23 mrglavas Exp $
  136. */
  137. public class XMLSchemaValidator
  138. implements XMLComponent, XMLDocumentFilter, FieldActivator, RevalidationHandler {
  139. //
  140. // Constants
  141. //
  142. private static final boolean DEBUG = false;
  143. // feature identifiers
  144. /** Feature identifier: validation. */
  145. protected static final String VALIDATION =
  146. Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
  147. /** Feature identifier: validation. */
  148. protected static final String SCHEMA_VALIDATION =
  149. Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE;
  150. /** Feature identifier: schema full checking*/
  151. protected static final String SCHEMA_FULL_CHECKING =
  152. Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_FULL_CHECKING;
  153. /** Feature identifier: dynamic validation. */
  154. protected static final String DYNAMIC_VALIDATION =
  155. Constants.XERCES_FEATURE_PREFIX + Constants.DYNAMIC_VALIDATION_FEATURE;
  156. /** Feature identifier: expose schema normalized value */
  157. protected static final String NORMALIZE_DATA =
  158. Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_NORMALIZED_VALUE;
  159. /** Feature identifier: send element default value via characters() */
  160. protected static final String SCHEMA_ELEMENT_DEFAULT =
  161. Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_ELEMENT_DEFAULT;
  162. /** Feature identifier: augment PSVI */
  163. protected static final String SCHEMA_AUGMENT_PSVI =
  164. Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_AUGMENT_PSVI;
  165. /** Feature identifier: whether to recognize java encoding names */
  166. protected static final String ALLOW_JAVA_ENCODINGS =
  167. Constants.XERCES_FEATURE_PREFIX + Constants.ALLOW_JAVA_ENCODINGS_FEATURE;
  168. /** Feature identifier: standard uri conformant feature. */
  169. protected static final String STANDARD_URI_CONFORMANT_FEATURE =
  170. Constants.XERCES_FEATURE_PREFIX + Constants.STANDARD_URI_CONFORMANT_FEATURE;
  171. /** Feature identifier: whether to continue parsing a schema after a fatal error is encountered */
  172. protected static final String CONTINUE_AFTER_FATAL_ERROR =
  173. Constants.XERCES_FEATURE_PREFIX + Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE;
  174. /** Feature identifier: ignore xsi:schemaLocation and xsi:noNamespaceSchemaLocation */
  175. protected static final String IGNORE_SCHEMA_LOCATION_HINTS =
  176. Constants.XERCES_FEATURE_PREFIX + Constants.IGNORE_SCHEMA_LOCATION_HINTS;
  177. protected static final String CHANGE_IGNORABLE_CHARACTERS_INTO_IGNORABLE_WHITESPACES =
  178. Constants.XERCES_FEATURE_PREFIX + Constants.CHANGE_IGNORABLE_CHARACTERS_INTO_IGNORABLE_WHITESPACES;
  179. protected static final String PARSER_SETTINGS =
  180. Constants.XERCES_FEATURE_PREFIX + Constants.PARSER_SETTINGS;
  181. // property identifiers
  182. /** Property identifier: symbol table. */
  183. public static final String SYMBOL_TABLE =
  184. Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
  185. /** Property identifier: error reporter. */
  186. public static final String ERROR_REPORTER =
  187. Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
  188. /** Property identifier: entity resolver. */
  189. public static final String ENTITY_RESOLVER =
  190. Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
  191. /** Property identifier: grammar pool. */
  192. public static final String XMLGRAMMAR_POOL =
  193. Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
  194. protected static final String VALIDATION_MANAGER =
  195. Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY;
  196. protected static final String ENTITY_MANAGER =
  197. Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY;
  198. /** Property identifier: schema location. */
  199. protected static final String SCHEMA_LOCATION =
  200. Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_LOCATION;
  201. /** Property identifier: no namespace schema location. */
  202. protected static final String SCHEMA_NONS_LOCATION =
  203. Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_NONS_LOCATION;
  204. /** Property identifier: JAXP schema source. */
  205. protected static final String JAXP_SCHEMA_SOURCE =
  206. Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE;
  207. /** Property identifier: JAXP schema language. */
  208. protected static final String JAXP_SCHEMA_LANGUAGE =
  209. Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE;
  210. // recognized features and properties
  211. /** Recognized features. */
  212. private static final String[] RECOGNIZED_FEATURES = {
  213. VALIDATION,
  214. SCHEMA_VALIDATION,
  215. DYNAMIC_VALIDATION,
  216. SCHEMA_FULL_CHECKING,
  217. ALLOW_JAVA_ENCODINGS,
  218. CONTINUE_AFTER_FATAL_ERROR,
  219. STANDARD_URI_CONFORMANT_FEATURE,
  220. IGNORE_SCHEMA_LOCATION_HINTS,
  221. CHANGE_IGNORABLE_CHARACTERS_INTO_IGNORABLE_WHITESPACES };
  222. /** Feature defaults. */
  223. private static final Boolean[] FEATURE_DEFAULTS = { null,
  224. // NOTE: The following defaults are nulled out on purpose.
  225. // If they are set, then when the XML Schema validator
  226. // is constructed dynamically, these values may override
  227. // those set by the application. This goes against the
  228. // whole purpose of XMLComponent#getFeatureDefault but
  229. // it can't be helped in this case. -Ac
  230. null, //Boolean.FALSE,
  231. null, //Boolean.FALSE,
  232. null, //Boolean.FALSE,
  233. null, //Boolean.FALSE,
  234. null, //Boolean.FALSE,
  235. null, //Boolean.FALSE,
  236. null, //Boolean.FALSE,
  237. null };
  238. /** Recognized properties. */
  239. private static final String[] RECOGNIZED_PROPERTIES = {
  240. SYMBOL_TABLE,
  241. ERROR_REPORTER,
  242. ENTITY_RESOLVER,
  243. VALIDATION_MANAGER,
  244. SCHEMA_LOCATION,
  245. SCHEMA_NONS_LOCATION,
  246. JAXP_SCHEMA_SOURCE,
  247. JAXP_SCHEMA_LANGUAGE,
  248. };
  249. /** Property defaults. */
  250. private static final Object[] PROPERTY_DEFAULTS =
  251. { null, null, null, null, null, null, null, null, };
  252. // this is the number of valuestores of each kind
  253. // we expect an element to have. It's almost
  254. // never > 1; so leave it at that.
  255. protected static final int ID_CONSTRAINT_NUM = 1;
  256. //
  257. // Data
  258. //
  259. /** current PSVI element info */
  260. protected ElementPSVImpl fCurrentPSVI = new ElementPSVImpl();
  261. // since it is the responsibility of each component to an
  262. // Augmentations parameter if one is null, to save ourselves from
  263. // having to create this object continually, it is created here.
  264. // If it is not present in calls that we're passing on, we *must*
  265. // clear this before we introduce it into the pipeline.
  266. protected final AugmentationsImpl fAugmentations = new AugmentationsImpl();
  267. /**
  268. * Map which is used to catch instance documents that try
  269. * and match a field several times in the same scope.
  270. */
  271. protected final HashMap fMayMatchFieldMap = new HashMap();
  272. // this is included for the convenience of handleEndElement
  273. protected XMLString fDefaultValue;
  274. // Validation features
  275. protected boolean fDynamicValidation = false;
  276. protected boolean fSchemaDynamicValidation = false;
  277. protected boolean fDoValidation = false;
  278. protected boolean fFullChecking = false;
  279. protected boolean fNormalizeData = true;
  280. protected boolean fSchemaElementDefault = true;
  281. protected boolean fAugPSVI = true;
  282. protected boolean fIdConstraint = false;
  283. protected boolean fIgnoreXsiSchemaLocationHints = false;
  284. protected boolean fTurnIgnorableCharactersIntoIgnorableWhitespaces = false;
  285. /** Schema type: None, DTD, Schema */
  286. private String fSchemaType = null;
  287. // to indicate whether we are in the scope of entity reference or CData
  288. protected boolean fEntityRef = false;
  289. protected boolean fInCDATA = false;
  290. // properties
  291. /** Symbol table. */
  292. protected SymbolTable fSymbolTable;
  293. /**
  294. * While parsing a document, keep the location of the document.
  295. */
  296. private XMLLocator fLocator;
  297. /**
  298. * A wrapper of the standard error reporter. We'll store all schema errors
  299. * in this wrapper object, so that we can get all errors (error codes) of
  300. * a specific element. This is useful for PSVI.
  301. */
  302. protected final class XSIErrorReporter {
  303. // the error reporter property
  304. XMLErrorReporter fErrorReporter;
  305. // store error codes; starting position of the errors for each element;
  306. // number of element (depth); and whether to record error
  307. Vector fErrors = new Vector(INITIAL_STACK_SIZE, INC_STACK_SIZE);
  308. int[] fContext = new int[INITIAL_STACK_SIZE];
  309. int fContextCount;
  310. // set the external error reporter, clear errors
  311. public void reset(XMLErrorReporter errorReporter) {
  312. fErrorReporter = errorReporter;
  313. fErrors.removeAllElements();
  314. fContextCount = 0;
  315. }
  316. // should be called when starting process an element or an attribute.
  317. // store the starting position for the current context
  318. public void pushContext() {
  319. if (!fAugPSVI)
  320. return;
  321. // resize array if necessary
  322. if (fContextCount == fContext.length) {
  323. int newSize = fContextCount + INC_STACK_SIZE;
  324. int[] newArray = new int[newSize];
  325. System.arraycopy(fContext, 0, newArray, 0, fContextCount);
  326. fContext = newArray;
  327. }
  328. fContext[fContextCount++] = fErrors.size();
  329. }
  330. // should be called on endElement: get all errors of the current element
  331. public String[] popContext() {
  332. if (!fAugPSVI)
  333. return null;
  334. // get starting position of the current element
  335. int contextPos = fContext[--fContextCount];
  336. // number of errors of the current element
  337. int size = fErrors.size() - contextPos;
  338. // if no errors, return null
  339. if (size == 0)
  340. return null;
  341. // copy errors from the list to an string array
  342. String[] errors = new String[size];
  343. for (int i = 0; i < size; i++) {
  344. errors[i] = (String) fErrors.elementAt(contextPos + i);
  345. }
  346. // remove errors of the current element
  347. fErrors.setSize(contextPos);
  348. return errors;
  349. }
  350. // should be called when an attribute is done: get all errors of
  351. // this attribute, but leave the errors to the containing element
  352. // also called after an element was strictly assessed.
  353. public String[] mergeContext() {
  354. if (!fAugPSVI)
  355. return null;
  356. // get starting position of the current element
  357. int contextPos = fContext[--fContextCount];
  358. // number of errors of the current element
  359. int size = fErrors.size() - contextPos;
  360. // if no errors, return null
  361. if (size == 0)
  362. return null;
  363. // copy errors from the list to an string array
  364. String[] errors = new String[size];
  365. for (int i = 0; i < size; i++) {
  366. errors[i] = (String) fErrors.elementAt(contextPos + i);
  367. }
  368. // don't resize the vector: leave the errors for this attribute
  369. // to the containing element
  370. return errors;
  371. }
  372. public void reportError(String domain, String key, Object[] arguments, short severity)
  373. throws XNIException {
  374. fErrorReporter.reportError(domain, key, arguments, severity);
  375. fErrors.addElement(key);
  376. } // reportError(String,String,Object[],short)
  377. public void reportError(
  378. XMLLocator location,
  379. String domain,
  380. String key,
  381. Object[] arguments,
  382. short severity)
  383. throws XNIException {
  384. fErrorReporter.reportError(location, domain, key, arguments, severity);
  385. fErrors.addElement(key);
  386. } // reportError(XMLLocator,String,String,Object[],short)
  387. }
  388. /** Error reporter. */
  389. protected final XSIErrorReporter fXSIErrorReporter = new XSIErrorReporter();
  390. /** Entity resolver */
  391. protected XMLEntityResolver fEntityResolver;
  392. // updated during reset
  393. protected ValidationManager fValidationManager = null;
  394. protected ValidationState fValidationState = new ValidationState();
  395. protected XMLGrammarPool fGrammarPool;
  396. // schema location property values
  397. protected String fExternalSchemas = null;
  398. protected String fExternalNoNamespaceSchema = null;
  399. //JAXP Schema Source property
  400. protected Object fJaxpSchemaSource = null;
  401. //ResourceIdentifier for use in calling EntityResolver
  402. final XMLResourceIdentifierImpl fResourceIdentifier = new XMLResourceIdentifierImpl();
  403. /** Schema Grammar Description passed, to give a chance to application to supply the Grammar */
  404. protected final XSDDescription fXSDDescription = new XSDDescription();
  405. protected final Hashtable fLocationPairs = new Hashtable();
  406. // handlers
  407. /** Document handler. */
  408. protected XMLDocumentHandler fDocumentHandler;
  409. protected XMLDocumentSource fDocumentSource;
  410. //
  411. // XMLComponent methods
  412. //
  413. /**
  414. * Returns a list of feature identifiers that are recognized by
  415. * this component. This method may return null if no features
  416. * are recognized by this component.
  417. */
  418. public String[] getRecognizedFeatures() {
  419. return (String[]) (RECOGNIZED_FEATURES.clone());
  420. } // getRecognizedFeatures():String[]
  421. /**
  422. * Sets the state of a feature. This method is called by the component
  423. * manager any time after reset when a feature changes state.
  424. * <p>
  425. * <strong>Note:</strong> Components should silently ignore features
  426. * that do not affect the operation of the component.
  427. *
  428. * @param featureId The feature identifier.
  429. * @param state The state of the feature.
  430. *
  431. * @throws SAXNotRecognizedException The component should not throw
  432. * this exception.
  433. * @throws SAXNotSupportedException The component should not throw
  434. * this exception.
  435. */
  436. public void setFeature(String featureId, boolean state) throws XMLConfigurationException {
  437. } // setFeature(String,boolean)
  438. /**
  439. * Returns a list of property identifiers that are recognized by
  440. * this component. This method may return null if no properties
  441. * are recognized by this component.
  442. */
  443. public String[] getRecognizedProperties() {
  444. return (String[])(RECOGNIZED_PROPERTIES.clone());
  445. } // getRecognizedProperties():String[]
  446. /**
  447. * Sets the value of a property. This method is called by the component
  448. * manager any time after reset when a property changes value.
  449. * <p>
  450. * <strong>Note:</strong> Components should silently ignore properties
  451. * that do not affect the operation of the component.
  452. *
  453. * @param propertyId The property identifier.
  454. * @param value The value of the property.
  455. *
  456. * @throws SAXNotRecognizedException The component should not throw
  457. * this exception.
  458. * @throws SAXNotSupportedException The component should not throw
  459. * this exception.
  460. */
  461. public void setProperty(String propertyId, Object value) throws XMLConfigurationException {
  462. } // setProperty(String,Object)
  463. /**
  464. * Returns the default state for a feature, or null if this
  465. * component does not want to report a default value for this
  466. * feature.
  467. *
  468. * @param featureId The feature identifier.
  469. *
  470. * @since Xerces 2.2.0
  471. */
  472. public Boolean getFeatureDefault(String featureId) {
  473. for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
  474. if (RECOGNIZED_FEATURES[i].equals(featureId)) {
  475. return FEATURE_DEFAULTS[i];
  476. }
  477. }
  478. return null;
  479. } // getFeatureDefault(String):Boolean
  480. /**
  481. * Returns the default state for a property, or null if this
  482. * component does not want to report a default value for this
  483. * property.
  484. *
  485. * @param propertyId The property identifier.
  486. *
  487. * @since Xerces 2.2.0
  488. */
  489. public Object getPropertyDefault(String propertyId) {
  490. for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
  491. if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
  492. return PROPERTY_DEFAULTS[i];
  493. }
  494. }
  495. return null;
  496. } // getPropertyDefault(String):Object
  497. //
  498. // XMLDocumentSource methods
  499. //
  500. /** Sets the document handler to receive information about the document. */
  501. public void setDocumentHandler(XMLDocumentHandler documentHandler) {
  502. fDocumentHandler = documentHandler;
  503. } // setDocumentHandler(XMLDocumentHandler)
  504. /** Returns the document handler */
  505. public XMLDocumentHandler getDocumentHandler() {
  506. return fDocumentHandler;
  507. } // setDocumentHandler(XMLDocumentHandler)
  508. //
  509. // XMLDocumentHandler methods
  510. //
  511. /** Sets the document source */
  512. public void setDocumentSource(XMLDocumentSource source){
  513. fDocumentSource = source;
  514. } // setDocumentSource
  515. /** Returns the document source */
  516. public XMLDocumentSource getDocumentSource(){
  517. return fDocumentSource;
  518. } // getDocumentSource
  519. /**
  520. * The start of the document.
  521. *
  522. * @param locator The system identifier of the entity if the entity
  523. * is external, null otherwise.
  524. * @param encoding The auto-detected IANA encoding name of the entity
  525. * stream. This value will be null in those situations
  526. * where the entity encoding is not auto-detected (e.g.
  527. * internal entities or a document entity that is
  528. * parsed from a java.io.Reader).
  529. * @param namespaceContext
  530. * The namespace context in effect at the
  531. * start of this document.
  532. * This object represents the current context.
  533. * Implementors of this class are responsible
  534. * for copying the namespace bindings from the
  535. * the current context (and its parent contexts)
  536. * if that information is important.
  537. * @param augs Additional information that may include infoset augmentations
  538. *
  539. * @throws XNIException Thrown by handler to signal an error.
  540. */
  541. public void startDocument(
  542. XMLLocator locator,
  543. String encoding,
  544. NamespaceContext namespaceContext,
  545. Augmentations augs)
  546. throws XNIException {
  547. fValidationState.setNamespaceSupport(namespaceContext);
  548. fState4XsiType.setNamespaceSupport(namespaceContext);
  549. fState4ApplyDefault.setNamespaceSupport(namespaceContext);
  550. fLocator = locator;
  551. handleStartDocument(locator, encoding);
  552. // call handlers
  553. if (fDocumentHandler != null) {
  554. fDocumentHandler.startDocument(locator, encoding, namespaceContext, augs);
  555. }
  556. } // startDocument(XMLLocator,String)
  557. /**
  558. * Notifies of the presence of an XMLDecl line in the document. If
  559. * present, this method will be called immediately following the
  560. * startDocument call.
  561. *
  562. * @param version The XML version.
  563. * @param encoding The IANA encoding name of the document, or null if
  564. * not specified.
  565. * @param standalone The standalone value, or null if not specified.
  566. * @param augs Additional information that may include infoset augmentations
  567. *
  568. * @throws XNIException Thrown by handler to signal an error.
  569. */
  570. public void xmlDecl(String version, String encoding, String standalone, Augmentations augs)
  571. throws XNIException {
  572. // call handlers
  573. if (fDocumentHandler != null) {
  574. fDocumentHandler.xmlDecl(version, encoding, standalone, augs);
  575. }
  576. } // xmlDecl(String,String,String)
  577. /**
  578. * Notifies of the presence of the DOCTYPE line in the document.
  579. *
  580. * @param rootElement The name of the root element.
  581. * @param publicId The public identifier if an external DTD or null
  582. * if the external DTD is specified using SYSTEM.
  583. * @param systemId The system identifier if an external DTD, null
  584. * otherwise.
  585. * @param augs Additional information that may include infoset augmentations
  586. *
  587. * @throws XNIException Thrown by handler to signal an error.
  588. */
  589. public void doctypeDecl(
  590. String rootElement,
  591. String publicId,
  592. String systemId,
  593. Augmentations augs)
  594. throws XNIException {
  595. // call handlers
  596. if (fDocumentHandler != null) {
  597. fDocumentHandler.doctypeDecl(rootElement, publicId, systemId, augs);
  598. }
  599. } // doctypeDecl(String,String,String)
  600. /**
  601. * The start of an element.
  602. *
  603. * @param element The name of the element.
  604. * @param attributes The element attributes.
  605. * @param augs Additional information that may include infoset augmentations
  606. *
  607. * @throws XNIException Thrown by handler to signal an error.
  608. */
  609. public void startElement(QName element, XMLAttributes attributes, Augmentations augs)
  610. throws XNIException {
  611. Augmentations modifiedAugs = handleStartElement(element, attributes, augs);
  612. // call handlers
  613. if (fDocumentHandler != null) {
  614. fDocumentHandler.startElement(element, attributes, modifiedAugs );
  615. }
  616. } // startElement(QName,XMLAttributes, Augmentations)
  617. /**
  618. * An empty element.
  619. *
  620. * @param element The name of the element.
  621. * @param attributes The element attributes.
  622. * @param augs Additional information that may include infoset augmentations
  623. *
  624. * @throws XNIException Thrown by handler to signal an error.
  625. */
  626. public void emptyElement(QName element, XMLAttributes attributes, Augmentations augs)
  627. throws XNIException {
  628. Augmentations modifiedAugs = handleStartElement(element, attributes, augs);
  629. // in the case where there is a {value constraint}, and the element
  630. // doesn't have any text content, change emptyElement call to
  631. // start + characters + end
  632. fDefaultValue = null;
  633. // fElementDepth == -2 indicates that the schema validator was removed
  634. // from the pipeline. then we don't need to call handleEndElement.
  635. if (fElementDepth != -2)
  636. modifiedAugs = handleEndElement(element, modifiedAugs);
  637. // call handlers
  638. if (fDocumentHandler != null) {
  639. if (!fSchemaElementDefault || fDefaultValue == null) {
  640. fDocumentHandler.emptyElement(element, attributes, modifiedAugs);
  641. } else {
  642. fDocumentHandler.startElement(element, attributes, modifiedAugs);
  643. fDocumentHandler.characters(fDefaultValue, null);
  644. fDocumentHandler.endElement(element, modifiedAugs);
  645. }
  646. }
  647. } // emptyElement(QName,XMLAttributes, Augmentations)
  648. /**
  649. * Character content.
  650. *
  651. * @param text The content.
  652. * @param augs Additional information that may include infoset augmentations
  653. *
  654. * @throws XNIException Thrown by handler to signal an error.
  655. */
  656. public void characters(XMLString text, Augmentations augs) throws XNIException {
  657. text = handleCharacters(text);
  658. // call handlers
  659. if (fDocumentHandler != null) {
  660. if (fNormalizeData && fUnionType) {
  661. // for union types we can't normalize data
  662. // thus we only need to send augs information if any;
  663. // the normalized data for union will be send
  664. // after normalization is performed (at the endElement())
  665. if (augs != null)
  666. fDocumentHandler.characters(fEmptyXMLStr, augs);
  667. } else {
  668. if( fTurnIgnorableCharactersIntoIgnorableWhitespaces && isElementOnlyContent() )
  669. fDocumentHandler.ignorableWhitespace(text, augs);
  670. else
  671. fDocumentHandler.characters(text, augs);
  672. }
  673. }
  674. } // characters(XMLString)
  675. /**
  676. * Ignorable whitespace. For this method to be called, the document
  677. * source must have some way of determining that the text containing
  678. * only whitespace characters should be considered ignorable. For
  679. * example, the validator can determine if a length of whitespace
  680. * characters in the document are ignorable based on the element
  681. * content model.
  682. *
  683. * @param text The ignorable whitespace.
  684. * @param augs Additional information that may include infoset augmentations
  685. *
  686. * @throws XNIException Thrown by handler to signal an error.
  687. */
  688. public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException {
  689. handleIgnorableWhitespace(text);
  690. // call handlers
  691. if (fDocumentHandler != null) {
  692. fDocumentHandler.ignorableWhitespace(text, augs);
  693. }
  694. } // ignorableWhitespace(XMLString)
  695. /**
  696. * The end of an element.
  697. *
  698. * @param element The name of the element.
  699. * @param augs Additional information that may include infoset augmentations
  700. *
  701. * @throws XNIException Thrown by handler to signal an error.
  702. */
  703. public void endElement(QName element, Augmentations augs) throws XNIException {
  704. // in the case where there is a {value constraint}, and the element
  705. // doesn't have any text content, add a characters call.
  706. fDefaultValue = null;
  707. Augmentations modifiedAugs = handleEndElement(element, augs);
  708. // call handlers
  709. if (fDocumentHandler != null) {
  710. if (!fSchemaElementDefault || fDefaultValue == null) {
  711. fDocumentHandler.endElement(element, modifiedAugs);
  712. } else {
  713. fDocumentHandler.characters(fDefaultValue, null);
  714. fDocumentHandler.endElement(element, modifiedAugs);
  715. }
  716. }
  717. } // endElement(QName, Augmentations)
  718. /**
  719. * The start of a CDATA section.
  720. *
  721. * @param augs Additional information that may include infoset augmentations
  722. *
  723. * @throws XNIException Thrown by handler to signal an error.
  724. */
  725. public void startCDATA(Augmentations augs) throws XNIException {
  726. // REVISIT: what should we do here if schema normalization is on??
  727. fInCDATA = true;
  728. // call handlers
  729. if (fDocumentHandler != null) {
  730. fDocumentHandler.startCDATA(augs);
  731. }
  732. } // startCDATA()
  733. /**
  734. * The end of a CDATA section.
  735. *
  736. * @param augs Additional information that may include infoset augmentations
  737. *
  738. * @throws XNIException Thrown by handler to signal an error.
  739. */
  740. public void endCDATA(Augmentations augs) throws XNIException {
  741. // call handlers
  742. fInCDATA = false;
  743. if (fDocumentHandler != null) {
  744. fDocumentHandler.endCDATA(augs);
  745. }
  746. } // endCDATA()
  747. /**
  748. * The end of the document.
  749. *
  750. * @param augs Additional information that may include infoset augmentations
  751. *
  752. * @throws XNIException Thrown by handler to signal an error.
  753. */
  754. public void endDocument(Augmentations augs) throws XNIException {
  755. handleEndDocument();
  756. // call handlers
  757. if (fDocumentHandler != null) {
  758. fDocumentHandler.endDocument(augs);
  759. }
  760. fLocator = null;
  761. } // endDocument(Augmentations)
  762. //
  763. // DOMRevalidationHandler methods
  764. //
  765. public boolean characterData(String data, Augmentations augs) {
  766. fSawText = fSawText || data.length() > 0;
  767. // REVISIT: this methods basically duplicates implementation of
  768. // handleCharacters(). We should be able to reuse some code
  769. // if whitespace == -1 skip normalization, because it is a complexType
  770. // or a union type.
  771. if (fNormalizeData && fWhiteSpace != -1 && fWhiteSpace != XSSimpleType.WS_PRESERVE) {
  772. // normalize data
  773. normalizeWhitespace(data, fWhiteSpace == XSSimpleType.WS_COLLAPSE);
  774. fBuffer.append(fNormalizedStr.ch, fNormalizedStr.offset, fNormalizedStr.length);
  775. } else {
  776. if (fAppendBuffer)
  777. fBuffer.append(data);
  778. }
  779. // When it's a complex type with element-only content, we need to
  780. // find out whether the content contains any non-whitespace character.
  781. boolean allWhiteSpace = true;
  782. if (fCurrentType != null
  783. && fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
  784. XSComplexTypeDecl ctype = (XSComplexTypeDecl)fCurrentType;
  785. if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_ELEMENT) {
  786. // data outside of element content
  787. for (int i=0; i< data.length(); i++) {
  788. if (!XMLChar.isSpace(data.charAt(i))) {
  789. allWhiteSpace = false;
  790. fSawCharacters = true;
  791. break;
  792. }
  793. }
  794. }
  795. }
  796. return allWhiteSpace;
  797. }
  798. public void elementDefault(String data){
  799. // no-op
  800. }
  801. //
  802. // XMLDocumentHandler and XMLDTDHandler methods
  803. //
  804. /**
  805. * This method notifies the start of a general entity.
  806. * <p>
  807. * <strong>Note:</strong> This method is not called for entity references
  808. * appearing as part of attribute values.
  809. *
  810. * @param name The name of the general entity.
  811. * @param identifier The resource identifier.
  812. * @param encoding The auto-detected IANA encoding name of the entity
  813. * stream. This value will be null in those situations
  814. * where the entity encoding is not auto-detected (e.g.
  815. * internal entities or a document entity that is
  816. * parsed from a java.io.Reader).
  817. * @param augs Additional information that may include infoset augmentations
  818. *
  819. * @exception XNIException Thrown by handler to signal an error.
  820. */
  821. public void startGeneralEntity(
  822. String name,
  823. XMLResourceIdentifier identifier,
  824. String encoding,
  825. Augmentations augs)
  826. throws XNIException {
  827. // REVISIT: what should happen if normalize_data_ is on??
  828. fEntityRef = true;
  829. // call handlers
  830. if (fDocumentHandler != null) {
  831. fDocumentHandler.startGeneralEntity(name, identifier, encoding, augs);
  832. }
  833. } // startEntity(String,String,String,String,String)
  834. /**
  835. * Notifies of the presence of a TextDecl line in an entity. If present,
  836. * this method will be called immediately following the startEntity call.
  837. * <p>
  838. * <strong>Note:</strong> This method will never be called for the
  839. * document entity; it is only called for external general entities
  840. * referenced in document content.
  841. * <p>
  842. * <strong>Note:</strong> This method is not called for entity references
  843. * appearing as part of attribute values.
  844. *
  845. * @param version The XML version, or null if not specified.
  846. * @param encoding The IANA encoding name of the entity.
  847. * @param augs Additional information that may include infoset augmentations
  848. *
  849. * @throws XNIException Thrown by handler to signal an error.
  850. */
  851. public void textDecl(String version, String encoding, Augmentations augs) throws XNIException {
  852. // call handlers
  853. if (fDocumentHandler != null) {
  854. fDocumentHandler.textDecl(version, encoding, augs);
  855. }
  856. } // textDecl(String,String)
  857. /**
  858. * A comment.
  859. *
  860. * @param text The text in the comment.
  861. * @param augs Additional information that may include infoset augmentations
  862. *
  863. * @throws XNIException Thrown by application to signal an error.
  864. */
  865. public void comment(XMLString text, Augmentations augs) throws XNIException {
  866. // record the fact that there is a comment child.
  867. fSawChildren = true;
  868. // call handlers
  869. if (fDocumentHandler != null) {
  870. fDocumentHandler.comment(text, augs);
  871. }
  872. } // comment(XMLString)
  873. /**
  874. * A processing instruction. Processing instructions consist of a
  875. * target name and, optionally, text data. The data is only meaningful
  876. * to the application.
  877. * <p>
  878. * Typically, a processing instruction's data will contain a series
  879. * of pseudo-attributes. These pseudo-attributes follow the form of
  880. * element attributes but are <strong>not</strong> parsed or presented
  881. * to the application as anything other than text. The application is
  882. * responsible for parsing the data.
  883. *
  884. * @param target The target.
  885. * @param data The data or null if none specified.
  886. * @param augs Additional information that may include infoset augmentations
  887. *
  888. * @throws XNIException Thrown by handler to signal an error.
  889. */
  890. public void processingInstruction(String target, XMLString data, Augmentations augs)
  891. throws XNIException {
  892. // record the fact that there is a PI child.
  893. fSawChildren = true;
  894. // call handlers
  895. if (fDocumentHandler != null) {
  896. fDocumentHandler.processingInstruction(target, data, augs);
  897. }
  898. } // processingInstruction(String,XMLString)
  899. /**
  900. * This method notifies the end of a general entity.
  901. * <p>
  902. * <strong>Note:</strong> This method is not called for entity references
  903. * appearing as part of attribute values.
  904. *
  905. * @param name The name of the entity.
  906. * @param augs Additional information that may include infoset augmentations
  907. *
  908. * @exception XNIException
  909. * Thrown by handler to signal an error.
  910. */
  911. public void endGeneralEntity(String name, Augmentations augs) throws XNIException {
  912. // call handlers
  913. fEntityRef = false;
  914. if (fDocumentHandler != null) {
  915. fDocumentHandler.endGeneralEntity(name, augs);
  916. }
  917. } // endEntity(String)
  918. // constants
  919. static final int INITIAL_STACK_SIZE = 8;
  920. static final int INC_STACK_SIZE = 8;
  921. //
  922. // Data
  923. //
  924. // Schema Normalization
  925. private static final boolean DEBUG_NORMALIZATION = false;
  926. // temporary empty string buffer.
  927. private final XMLString fEmptyXMLStr = new XMLString(null, 0, -1);
  928. // temporary character buffer, and empty string buffer.
  929. private static final int BUFFER_SIZE = 20;
  930. private final XMLString fNormalizedStr = new XMLString();
  931. private boolean fFirstChunk = true;
  932. // got first chunk in characters() (SAX)
  933. private boolean fTrailing = false; // Previous chunk had a trailing space
  934. private short fWhiteSpace = -1; //whiteSpace: preserve/replace/collapse
  935. private boolean fUnionType = false;
  936. /** Schema grammar resolver. */
  937. final XSGrammarBucket fGrammarBucket;
  938. final SubstitutionGroupHandler fSubGroupHandler;
  939. // Schema grammar loader
  940. final XMLSchemaLoader fSchemaLoader;
  941. /** the DV usd to convert xsi:type to a QName */
  942. // REVISIT: in new simple type design, make things in DVs static,
  943. // so that we can QNameDV.getCompiledForm()
  944. final XSSimpleType fQNameDV =
  945. (XSSimpleType) SchemaGrammar.SG_SchemaNS.getGlobalTypeDecl(SchemaSymbols.ATTVAL_QNAME);
  946. final CMNodeFactory nodeFactory = new CMNodeFactory();
  947. /** used to build content models */
  948. // REVISIT: create decl pool, and pass it to each traversers
  949. final CMBuilder fCMBuilder = new CMBuilder(nodeFactory);
  950. // state
  951. /** String representation of the validation root. */
  952. // REVISIT: what do we store here? QName, XPATH, some ID? use rawname now.
  953. String fValidationRoot;
  954. /** Skip validation: anything below this level should be skipped */
  955. int fSkipValidationDepth;
  956. /** anything above this level has validation_attempted != full */
  957. int fNFullValidationDepth;
  958. /** anything above this level has validation_attempted != none */
  959. int fNNoneValidationDepth;
  960. /** Element depth: -2: validator not in pipeline; >= -1 current depth. */
  961. int fElementDepth;
  962. /** Seen sub elements. */
  963. boolean fSubElement;
  964. /** Seen sub elements stack. */
  965. boolean[] fSubElementStack = new boolean[INITIAL_STACK_SIZE];
  966. /** Current element declaration. */
  967. XSElementDecl fCurrentElemDecl;
  968. /** Element decl stack. */
  969. XSElementDecl[] fElemDeclStack = new XSElementDecl[INITIAL_STACK_SIZE];
  970. /** nil value of the current element */
  971. boolean fNil;
  972. /** nil value stack */
  973. boolean[] fNilStack = new boolean[INITIAL_STACK_SIZE];
  974. /** notation value of the current element */
  975. XSNotationDecl fNotation;
  976. /** notation stack */
  977. XSNotationDecl[] fNotationStack = new XSNotationDecl[INITIAL_STACK_SIZE];
  978. /** Current type. */
  979. XSTypeDefinition fCurrentType;
  980. /** type stack. */
  981. XSTypeDefinition[] fTypeStack = new XSTypeDefinition[INITIAL_STACK_SIZE];
  982. /** Current content model. */
  983. XSCMValidator fCurrentCM;
  984. /** Content model stack. */
  985. XSCMValidator[] fCMStack = new XSCMValidator[INITIAL_STACK_SIZE];
  986. /** the current state of the current content model */
  987. int[] fCurrCMState;
  988. /** stack to hold content model states */
  989. int[][] fCMStateStack = new int[INITIAL_STACK_SIZE][];
  990. /** whether the curret element is strictly assessed */
  991. boolean fStrictAssess = true;
  992. /** strict assess stack */
  993. boolean[] fStrictAssessStack = new boolean[INITIAL_STACK_SIZE];
  994. /** Temporary string buffers. */
  995. final StringBuffer fBuffer = new StringBuffer();
  996. /** Whether need to append characters to fBuffer */
  997. boolean fAppendBuffer = true;
  998. /** Did we see any character data? */
  999. boolean fSawText = false;
  1000. /** stack to record if we saw character data */
  1001. boolean[] fSawTextStack = new boolean[INITIAL_STACK_SIZE];
  1002. /** Did we see non-whitespace character data? */
  1003. boolean fSawCharacters = false;
  1004. /** Stack to record if we saw character data outside of element content*/
  1005. boolean[] fStringContent = new boolean[INITIAL_STACK_SIZE];
  1006. /** Did we see children that are neither characters nor elements? */
  1007. boolean fSawChildren = false;
  1008. /** Stack to record if we other children that character or elements */
  1009. boolean[] fSawChildrenStack = new boolean[INITIAL_STACK_SIZE];
  1010. /** temprory qname */
  1011. final QName fTempQName = new QName();
  1012. /** temprory validated info */
  1013. ValidatedInfo fValidatedInfo = new ValidatedInfo();
  1014. // used to validate default/fixed values against xsi:type
  1015. // only need to check facets, so we set extraChecking to false (in reset)
  1016. private ValidationState fState4XsiType = new ValidationState();
  1017. // used to apply default/fixed values
  1018. // only need to check id/idref/entity, so we set checkFacets to false
  1019. private ValidationState fState4ApplyDefault = new ValidationState();
  1020. // identity constraint information
  1021. /**
  1022. * Stack of active XPath matchers for identity constraints. All
  1023. * active XPath matchers are notified of startElement
  1024. * and endElement callbacks in order to perform their matches.
  1025. * <p>
  1026. * For each element with identity constraints, the selector of
  1027. * each identity constraint is activated. When the selector matches
  1028. * its XPath, then all the fields of the identity constraint are
  1029. * activated.
  1030. * <p>
  1031. * <strong>Note:</strong> Once the activation scope is left, the
  1032. * XPath matchers are automatically removed from the stack of
  1033. * active matchers and no longer receive callbacks.
  1034. */
  1035. protected XPathMatcherStack fMatcherStack = new XPathMatcherStack();
  1036. /** Cache of value stores for identity constraint fields. */
  1037. protected ValueStoreCache fValueStoreCache = new ValueStoreCache();
  1038. //
  1039. // Constructors
  1040. //
  1041. /** Default constructor. */
  1042. public XMLSchemaValidator() {
  1043. fGrammarBucket = new XSGrammarBucket();
  1044. fSubGroupHandler = new SubstitutionGroupHandler(fGrammarBucket);
  1045. // initialize the schema loader
  1046. fSchemaLoader =
  1047. new XMLSchemaLoader(
  1048. fXSIErrorReporter.fErrorReporter,
  1049. fGrammarBucket,
  1050. fSubGroupHandler,
  1051. fCMBuilder);
  1052. fState4XsiType.setExtraChecking(false);
  1053. fState4ApplyDefault.setFacetChecking(false);
  1054. } // <init>()
  1055. /*
  1056. * Resets the component. The component can query the component manager
  1057. * about any features and properties that affect the operation of the
  1058. * component.
  1059. *
  1060. * @param componentManager The component manager.
  1061. *
  1062. * @throws SAXException Thrown by component on finitialization error.
  1063. * For example, if a feature or property is
  1064. * required for the operation of the component, the
  1065. * component manager may throw a
  1066. * SAXNotRecognizedException or a
  1067. * SAXNotSupportedException.
  1068. */
  1069. public void reset(XMLComponentManager componentManager) throws XMLConfigurationException {
  1070. fIdConstraint = false;
  1071. //reset XSDDescription
  1072. fLocationPairs.clear();
  1073. // cleanup id table
  1074. fValidationState.resetIDTables();
  1075. //pass the component manager to the factory..
  1076. nodeFactory.reset(componentManager);
  1077. // reset schema loader
  1078. fSchemaLoader.reset(componentManager);
  1079. // initialize state
  1080. fCurrentElemDecl = null;
  1081. fCurrentCM = null;
  1082. fCurrCMState = null;
  1083. fSkipValidationDepth = -1;
  1084. fNFullValidationDepth = -1;
  1085. fNNoneValidationDepth = -1;
  1086. fElementDepth = -1;
  1087. fSubElement = false;
  1088. fSchemaDynamicValidation = false;
  1089. // datatype normalization
  1090. fEntityRef = false;
  1091. fInCDATA = false;
  1092. fMatcherStack.clear();
  1093. if (!fMayMatchFieldMap.isEmpty()) {
  1094. // should only clear this if the last schema had identity constraints.
  1095. fMayMatchFieldMap.clear();
  1096. }
  1097. // get error reporter
  1098. fXSIErrorReporter.reset((XMLErrorReporter) componentManager.getProperty(ERROR_REPORTER));
  1099. boolean parser_settings;
  1100. try {
  1101. parser_settings = componentManager.getFeature(PARSER_SETTINGS);
  1102. }
  1103. catch (XMLConfigurationException e){
  1104. parser_settings = true;
  1105. }
  1106. if (!parser_settings){
  1107. // parser settings have not been changed
  1108. fValidationManager.addValidationState(fValidationState);
  1109. return;
  1110. }
  1111. // get symbol table. if it's a new one, add symbols to it.
  1112. SymbolTable symbolTable = (SymbolTable)componentManager.getProperty(SYMBOL_TABLE);
  1113. if (symbolTable != fSymbolTable) {
  1114. fSymbolTable = symbolTable;
  1115. }
  1116. try {
  1117. fDynamicValidation = componentManager.getFeature(DYNAMIC_VALIDATION);
  1118. } catch (XMLConfigurationException e) {
  1119. fDynamicValidation = false;
  1120. }
  1121. if (fDynamicValidation) {
  1122. fDoValidation = true;
  1123. } else {
  1124. try {
  1125. fDoValidation = componentManager.getFeature(VALIDATION);
  1126. } catch (XMLConfigurationException e) {
  1127. fDoValidation = false;
  1128. }
  1129. }
  1130. if (fDoValidation) {
  1131. try {
  1132. fDoValidation = componentManager.getFeature(XMLSchemaValidator.SCHEMA_VALIDATION);
  1133. } catch (XMLConfigurationException e) {
  1134. }
  1135. }
  1136. try {
  1137. fFullChecking = componentManager.getFeature(SCHEMA_FULL_CHECKING);
  1138. } catch (XMLConfigurationException e) {
  1139. fFullChecking = false;
  1140. }
  1141. try {
  1142. fNormalizeData = componentManager.getFeature(NORMALIZE_DATA);
  1143. } catch (XMLConfigurationException e) {
  1144. fNormalizeData = false;
  1145. }
  1146. try {
  1147. fSchemaElementDefault = componentManager.getFeature(SCHEMA_ELEMENT_DEFAULT);
  1148. } catch (XMLConfigurationException e) {
  1149. fSchemaElementDefault = false;
  1150. }
  1151. try {
  1152. fAugPSVI = componentManager.getFeature(SCHEMA_AUGMENT_PSVI);
  1153. } catch (XMLConfigurationException e) {
  1154. fAugPSVI = true;
  1155. }
  1156. try {
  1157. fSchemaType =
  1158. (String)componentManager.getProperty(Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE);
  1159. } catch (XMLConfigurationException e) {
  1160. fSchemaType = null;
  1161. }
  1162. try {
  1163. fIgnoreXsiSchemaLocationHints = componentManager.getFeature(IGNORE_SCHEMA_LOCATION_HINTS);
  1164. } catch( XMLConfigurationException e) {
  1165. fIgnoreXsiSchemaLocationHints = false;
  1166. }
  1167. try {
  1168. fTurnIgnorableCharactersIntoIgnorableWhitespaces = componentManager.getFeature(CHANGE_IGNORABLE_CHARACTERS_INTO_IGNORABLE_WHITESPACES);
  1169. } catch( XMLConfigurationException e) {
  1170. fTurnIgnorableCharactersIntoIgnorableWhitespaces = false;
  1171. }
  1172. fEntityResolver = (XMLEntityResolver)componentManager.getProperty(ENTITY_MANAGER);
  1173. fValidationManager = (ValidationManager)componentManager.getProperty(VALIDATION_MANAGER);
  1174. fValidationManager.addValidationState(fValidationState);
  1175. fValidationState.setSymbolTable(fSymbolTable);
  1176. // get schema location properties
  1177. try {
  1178. fExternalSchemas = (String)componentManager.getProperty(SCHEMA_LOCATION);
  1179. fExternalNoNamespaceSchema = (String)componentManager.getProperty(SCHEMA_NONS_LOCATION);
  1180. } catch (XMLConfigurationException e) {
  1181. fExternalSchemas = null;
  1182. fExternalNoNamespaceSchema = null;
  1183. }
  1184. // store the external schema locations. they are set when reset is called,
  1185. // so any other schemaLocation declaration for the same namespace will be
  1186. // effectively ignored. becuase we choose to take first location hint
  1187. // available for a particular namespace.
  1188. XMLSchemaLoader.processExternalHints(fExternalSchemas, fExternalNoNamespaceSchema,
  1189. fLocationPairs, fXSIErrorReporter.fErrorReporter);
  1190. try {
  1191. fJaxpSchemaSource = componentManager.getProperty(JAXP_SCHEMA_SOURCE);
  1192. } catch (XMLConfigurationException e){
  1193. fJaxpSchemaSource = null;
  1194. }
  1195. fResourceIdentifier.clear();
  1196. // clear grammars, and put the one for schema namespace there
  1197. try {
  1198. fGrammarPool = (XMLGrammarPool)componentManager.getProperty(XMLGRAMMAR_POOL);
  1199. } catch (XMLConfigurationException e){
  1200. fGrammarPool = null;
  1201. }
  1202. fSchemaLoader.setProperty(XMLGRAMMAR_POOL, fGrammarPool);
  1203. fState4XsiType.setSymbolTable(symbolTable);
  1204. fState4ApplyDefault.setSymbolTable(symbolTable);
  1205. } // reset(XMLComponentManager)
  1206. //
  1207. // FieldActivator methods
  1208. //
  1209. /**
  1210. * Start the value scope for the specified identity constraint. This
  1211. * method is called when the selector matches in order to initialize
  1212. * the value store.
  1213. *
  1214. * @param identityConstraint The identity constraint.
  1215. */
  1216. public void startValueScopeFor(IdentityConstraint identityConstraint, int initialDepth) {
  1217. ValueStoreBase valueStore =
  1218. fValueStoreCache.getValueStoreFor(identityConstraint, initialDepth);
  1219. valueStore.startValueScope();
  1220. } // startValueScopeFor(IdentityConstraint identityConstraint)
  1221. /**
  1222. * Request to activate the specified field. This method returns the
  1223. * matcher for the field.
  1224. *
  1225. * @param field The field to activate.
  1226. */
  1227. public XPathMatcher activateField(Field field, int initialDepth) {
  1228. ValueStore valueStore =
  1229. fValueStoreCache.getValueStoreFor(field.getIdentityConstraint(), initialDepth);
  1230. setMayMatch(field, Boolean.TRUE);
  1231. XPathMatcher matcher = field.createMatcher(this, valueStore);
  1232. fMatcherStack.addMatcher(matcher);
  1233. matcher.startDocumentFragment();
  1234. return matcher;
  1235. } // activateField(Field):XPathMatcher
  1236. /**
  1237. * Ends the value scope for the specified identity constraint.
  1238. *
  1239. * @param identityConstraint The identity constraint.
  1240. */
  1241. public void endValueScopeFor(IdentityConstraint identityConstraint, int initialDepth) {
  1242. ValueStoreBase valueStore =
  1243. fValueStoreCache.getValueStoreFor(identityConstraint, initialDepth);
  1244. valueStore.endValueScope();
  1245. } // endValueScopeFor(IdentityConstraint)
  1246. /**
  1247. * Sets whether the given field is permitted to match a value.
  1248. * This should be used to catch instance documents that try
  1249. * and match a field several times in the same scope.
  1250. *
  1251. * @param field The field that may be permitted to be matched.
  1252. * @param state Boolean indiciating whether the field may be matched.
  1253. */
  1254. public void setMayMatch(Field field, Boolean state) {
  1255. fMayMatchFieldMap.put(field, state);
  1256. } // setMayMatch(Field, Boolean)
  1257. /**
  1258. * Returns whether the given field is permitted to match a value.
  1259. *
  1260. * @param field The field that may be permitted to be matched.
  1261. * @return Boolean indicating whether the field may be matched.
  1262. */
  1263. public Boolean mayMatch(Field field) {
  1264. return (Boolean) fMayMatchFieldMap.get(field);
  1265. } // mayMatch(Field):Boolean
  1266. // a utility method for Identity constraints
  1267. private void activateSelectorFor(IdentityConstraint ic) {
  1268. Selector selector = ic.getSelector();
  1269. FieldActivator activator = this;
  1270. if (selector == null)
  1271. return;
  1272. XPathMatcher matcher = selector.createMatcher(activator, fElementDepth);
  1273. fMatcherStack.addMatcher(matcher);
  1274. matcher.startDocumentFragment();
  1275. }
  1276. //
  1277. // Protected methods
  1278. //
  1279. /** ensure element stack capacity */
  1280. void ensureStackCapacity() {
  1281. if (fElementDepth == fElemDeclStack.length) {
  1282. int newSize = fElementDepth + INC_STACK_SIZE;
  1283. boolean[] newArrayB = new boolean[newSize];
  1284. System.arraycopy(fSubElementStack, 0, newArrayB, 0, fElementDepth);
  1285. fSubElementStack = newArrayB;
  1286. XSElementDecl[] newArrayE = new XSElementDecl[newSize];
  1287. System.arraycopy(fElemDeclStack, 0, newArrayE, 0, fElementDepth);
  1288. fElemDeclStack = newArrayE;
  1289. newArrayB = new boolean[newSize];
  1290. System.arraycopy(fNilStack, 0, newArrayB, 0, fElementDepth);
  1291. fNilStack = newArrayB;
  1292. XSNotationDecl[] newArrayN = new XSNotationDecl[newSize];
  1293. System.arraycopy(fNotationStack, 0, newArrayN, 0, fElementDepth);
  1294. fNotationStack = newArrayN;
  1295. XSTypeDefinition[] newArrayT = new XSTypeDefinition[newSize];
  1296. System.arraycopy(fTypeStack, 0, newArrayT, 0, fElementDepth);
  1297. fTypeStack = newArrayT;
  1298. XSCMValidator[] newArrayC = new XSCMValidator[newSize];
  1299. System.arraycopy(fCMStack, 0, newArrayC, 0, fElementDepth);
  1300. fCMStack = newArrayC;
  1301. newArrayB = new boolean[newSize];
  1302. System.arraycopy(fSawTextStack, 0, newArrayB, 0, fElementDepth);
  1303. fSawTextStack = newArrayB;
  1304. newArrayB = new boolean[newSize];
  1305. System.arraycopy(fStringContent, 0, newArrayB, 0, fElementDepth);
  1306. fStringContent = newArrayB;
  1307. newArrayB = new boolean[newSize];
  1308. System.arraycopy(fSawChildrenStack, 0, newArrayB, 0, fElementDepth);
  1309. fSawChildrenStack = newArrayB;
  1310. newArrayB = new boolean[newSize];
  1311. System.arraycopy(fStrictAssessStack, 0, newArrayB, 0, fElementDepth);
  1312. fStrictAssessStack = newArrayB;
  1313. int[][] newArrayIA = new int[newSize][];
  1314. System.arraycopy(fCMStateStack, 0, newArrayIA, 0, fElementDepth);
  1315. fCMStateStack = newArrayIA;
  1316. }
  1317. } // ensureStackCapacity
  1318. // handle start document
  1319. void handleStartDocument(XMLLocator locator, String encoding) {
  1320. fValueStoreCache.startDocument();
  1321. } // handleStartDocument(XMLLocator,String)
  1322. void handleEndDocument() {
  1323. fValueStoreCache.endDocument();
  1324. } // handleEndDocument()
  1325. // handle character contents
  1326. // returns the normalized string if possible, otherwise the original string
  1327. XMLString handleCharacters(XMLString text) {
  1328. if (fSkipValidationDepth >= 0)
  1329. return text;
  1330. fSawText = fSawText || text.length > 0;
  1331. // Note: data in EntityRef and CDATA is normalized as well
  1332. // if whitespace == -1 skip normalization, because it is a complexType
  1333. // or a union type.
  1334. if (fNormalizeData && fWhiteSpace != -1 && fWhiteSpace != XSSimpleType.WS_PRESERVE) {
  1335. // normalize data
  1336. normalizeWhitespace(text, fWhiteSpace == XSSimpleType.WS_COLLAPSE);
  1337. text = fNormalizedStr;
  1338. }
  1339. if (fAppendBuffer)
  1340. fBuffer.append(text.ch, text.offset, text.length);
  1341. // When it's a complex type with element-only content, we need to
  1342. // find out whether the content contains any non-whitespace character.
  1343. if (fCurrentType != null
  1344. && fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
  1345. XSComplexTypeDecl ctype = (XSComplexTypeDecl)fCurrentType;
  1346. if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_ELEMENT) {
  1347. // data outside of element content
  1348. for (int i=text.offset; i< text.offset+text.length; i++) {
  1349. if (!XMLChar.isSpace(text.ch[i])) {
  1350. fSawCharacters = true;
  1351. break;
  1352. }
  1353. }
  1354. }
  1355. }
  1356. return text;
  1357. } // handleCharacters(XMLString)
  1358. /**
  1359. * Returns true if the current element is expecting only
  1360. * ignorable whitespaces as characters.
  1361. */
  1362. public final boolean isElementOnlyContent() {
  1363. if (fCurrentType == null
  1364. || fCurrentType.getTypeCategory() != XSTypeDefinition.COMPLEX_TYPE)
  1365. return false;
  1366. XSComplexTypeDecl ctype = (XSComplexTypeDecl)fCurrentType;
  1367. if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_ELEMENT
  1368. || ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_EMPTY )
  1369. return !fSawCharacters;
  1370. return false;
  1371. }
  1372. /**
  1373. * Normalize whitespace in an XMLString according to the rules defined
  1374. * in XML Schema specifications.
  1375. * @param value The string to normalize.
  1376. * @param collapse replace or collapse
  1377. */
  1378. private void normalizeWhitespace( XMLString value, boolean collapse) {
  1379. boolean skipSpace = collapse;
  1380. boolean sawNonWS = false;
  1381. boolean leading = false;
  1382. boolean trailing = false;
  1383. char c;
  1384. int size = value.offset+value.length;
  1385. // ensure the ch array is big enough
  1386. if (fNormalizedStr.ch == null || fNormalizedStr.ch.length < value.length+1) {
  1387. fNormalizedStr.ch = new char[value.length+1];
  1388. }
  1389. // don't include the leading ' ' for now. might include it later.
  1390. fNormalizedStr.offset = 1;
  1391. fNormalizedStr.length = 1;
  1392. for (int i = value.offset; i < size; i++) {
  1393. c = value.ch[i];
  1394. if (XMLChar.isSpace(c)) {
  1395. if (!skipSpace) {
  1396. // take the first whitespace as a space and skip the others
  1397. fNormalizedStr.ch[fNormalizedStr.length++] = ' ';
  1398. skipSpace = collapse;
  1399. }
  1400. if (!sawNonWS) {
  1401. // this is a leading whitespace, record it
  1402. leading = true;
  1403. }
  1404. } else {
  1405. fNormalizedStr.ch[fNormalizedStr.length++] = c;
  1406. skipSpace = false;
  1407. sawNonWS = true;
  1408. }
  1409. }
  1410. if (skipSpace) {
  1411. if ( fNormalizedStr.length > 1) {
  1412. // if we finished on a space trim it but also record it
  1413. fNormalizedStr.length--;
  1414. trailing = true;
  1415. } else if (leading && !fFirstChunk) {
  1416. // if all we had was whitespace we skipped record it as
  1417. // trailing whitespace as well
  1418. trailing = true;
  1419. }
  1420. }
  1421. if (fNormalizedStr.length > 1) {
  1422. if (!fFirstChunk && (fWhiteSpace==XSSimpleType.WS_COLLAPSE) ) {
  1423. if (fTrailing) {
  1424. // previous chunk ended on whitespace
  1425. // insert whitespace
  1426. fNormalizedStr.offset = 0;
  1427. fNormalizedStr.ch[0] = ' ';
  1428. } else if (leading) {
  1429. // previous chunk ended on character,
  1430. // this chunk starts with whitespace
  1431. fNormalizedStr.offset = 0;
  1432. fNormalizedStr.ch[0] = ' ';
  1433. }
  1434. }
  1435. }
  1436. // The length includes the leading ' '. Now removing it.
  1437. fNormalizedStr.length -= fNormalizedStr.offset;
  1438. fTrailing = trailing;
  1439. if (trailing || sawNonWS)
  1440. fFirstChunk = false;
  1441. }
  1442. private void normalizeWhitespace( String value, boolean collapse) {
  1443. boolean skipSpace = collapse;
  1444. char c;
  1445. int size = value.length();
  1446. // ensure the ch array is big enough
  1447. if (fNormalizedStr.ch == null || fNormalizedStr.ch.length < size) {
  1448. fNormalizedStr.ch = new char[size];
  1449. }
  1450. fNormalizedStr.offset = 0;
  1451. fNormalizedStr.length = 0;
  1452. for (int i = 0; i < size; i++) {
  1453. c = value.charAt(i);
  1454. if (XMLChar.isSpace(c)) {
  1455. if (!skipSpace) {
  1456. // take the first whitespace as a space and skip the others
  1457. fNormalizedStr.ch[fNormalizedStr.length++] = ' ';
  1458. skipSpace = collapse;
  1459. }
  1460. } else {
  1461. fNormalizedStr.ch[fNormalizedStr.length++] = c;
  1462. skipSpace = false;
  1463. }
  1464. }
  1465. if (skipSpace) {
  1466. if (fNormalizedStr.length != 0)
  1467. // if we finished on a space trim it but also record it
  1468. fNormalizedStr.length--;
  1469. }
  1470. }
  1471. // handle ignorable whitespace
  1472. void handleIgnorableWhitespace(XMLString text) {
  1473. if (fSkipValidationDepth >= 0)
  1474. return;
  1475. // REVISIT: the same process needs to be performed as handleCharacters.
  1476. // only it's simpler here: we know all characters are whitespaces.
  1477. } // handleIgnorableWhitespace(XMLString)
  1478. /** Handle element. */
  1479. Augmentations handleStartElement(QName element, XMLAttributes attributes, Augmentations augs) {
  1480. if (DEBUG) {
  1481. System.out.println("==>handleStartElement: " +element);
  1482. }
  1483. // root element
  1484. if (fElementDepth == -1 && fValidationManager.isGrammarFound()) {
  1485. if (fSchemaType == null) {
  1486. // schemaType is not specified
  1487. // if a DTD grammar is found, we do the same thing as Dynamic:
  1488. // if a schema grammar is found, validation is performed;
  1489. // otherwise, skip the whole document.
  1490. fSchemaDynamicValidation = true;
  1491. } else {
  1492. // [1] Either schemaType is DTD, and in this case validate/schema is turned off
  1493. // [2] Validating against XML Schemas only
  1494. // [a] dynamic validation is false: report error if SchemaGrammar is not found
  1495. // [b] dynamic validation is true: if grammar is not found ignore.
  1496. }
  1497. }
  1498. // get xsi:schemaLocation and xsi:noNamespaceSchemaLocation attributes,
  1499. // parse them to get the grammars
  1500. String sLocation =
  1501. attributes.getValue(SchemaSymbols.URI_XSI, SchemaSymbols.XSI_SCHEMALOCATION);
  1502. String nsLocation =
  1503. attributes.getValue(SchemaSymbols.URI_XSI, SchemaSymbols.XSI_NONAMESPACESCHEMALOCATION);
  1504. //store the location hints.. we need to do it so that we can defer the loading of grammar until
  1505. //there is a reference to a component from that namespace. To provide location hints to the
  1506. //application for a namespace
  1507. storeLocations(sLocation, nsLocation) ;
  1508. // if we are in the content of "skip", then just skip this element
  1509. // REVISIT: is this the correct behaviour for ID constraints? -NG
  1510. if (fSkipValidationDepth >= 0) {
  1511. fElementDepth++;
  1512. if (fAugPSVI)
  1513. augs = getEmptyAugs(augs);
  1514. return augs;
  1515. }
  1516. //try to find schema grammar by different means..
  1517. SchemaGrammar sGrammar =
  1518. findSchemaGrammar(
  1519. XSDDescription.CONTEXT_ELEMENT,
  1520. element.uri,
  1521. null,
  1522. element,
  1523. attributes);
  1524. // if we are not skipping this element, and there is a content model,
  1525. // we try to find the corresponding decl object for this element.
  1526. // the reason we move this part of code here is to make sure the
  1527. // error reported here (if any) is stored within the parent element's
  1528. // context, instead of that of the current element.
  1529. Object decl = null;
  1530. if (fCurrentCM != null) {
  1531. decl = fCurrentCM.oneTransition(element, fCurrCMState, fSubGroupHandler);
  1532. // it could be an element decl or a wildcard decl
  1533. if (fCurrCMState[0] == XSCMValidator.FIRST_ERROR) {
  1534. XSComplexTypeDecl ctype = (XSComplexTypeDecl)fCurrentType;
  1535. //REVISIT: is it the only case we will have particle = null?
  1536. Vector next;
  1537. if (ctype.fParticle != null
  1538. && (next = fCurrentCM.whatCanGoHere(fCurrCMState)).size() > 0) {
  1539. String expected = expectedStr(next);
  1540. reportSchemaError(
  1541. "cvc-complex-type.2.4.a",
  1542. new Object[] { element.rawname, expected });
  1543. } else {
  1544. reportSchemaError("cvc-complex-type.2.4.d", new Object[]{element.rawname});
  1545. }
  1546. }
  1547. }
  1548. // if it's not the root element, we push the current states in the stacks
  1549. if (fElementDepth != -1) {
  1550. ensureStackCapacity();
  1551. fSubElementStack[fElementDepth] = true;
  1552. fSubElement = false;
  1553. fElemDeclStack[fElementDepth] = fCurrentElemDecl;
  1554. fNilStack[fElementDepth] = fNil;
  1555. fNotationStack[fElementDepth] = fNotation;
  1556. fTypeStack[fElementDepth] = fCurrentType;
  1557. fStrictAssessStack[fElementDepth] = fStrictAssess;
  1558. fCMStack[fElementDepth] = fCurrentCM;
  1559. fCMStateStack[fElementDepth] = fCurrCMState;
  1560. fSawTextStack[fElementDepth] = fSawText;
  1561. fStringContent[fElementDepth] = fSawCharacters;
  1562. fSawChildrenStack[fElementDepth] = fSawChildren;
  1563. }
  1564. // increase the element depth after we've saved
  1565. // all states for the parent element
  1566. fElementDepth++;
  1567. fCurrentElemDecl = null;
  1568. XSWildcardDecl wildcard = null;
  1569. fCurrentType = null;
  1570. fStrictAssess = true;
  1571. fNil = false;
  1572. fNotation = null;
  1573. // and the buffer to hold the value of the element
  1574. fBuffer.setLength(0);
  1575. fSawText = false;
  1576. fSawCharacters = false;
  1577. fSawChildren = false;
  1578. // check what kind of declaration the "decl" from
  1579. // oneTransition() maps to
  1580. if (decl != null) {
  1581. if (decl instanceof XSElementDecl) {
  1582. fCurrentElemDecl = (XSElementDecl)decl;
  1583. } else {
  1584. wildcard = (XSWildcardDecl)decl;
  1585. }
  1586. }
  1587. // if the wildcard is skip, then return
  1588. if (wildcard != null && wildcard.fProcessContents == XSWildcardDecl.PC_SKIP) {
  1589. fSkipValidationDepth = fElementDepth;
  1590. if (fAugPSVI)
  1591. augs = getEmptyAugs(augs);
  1592. return augs;
  1593. }
  1594. // try again to get the element decl:
  1595. // case 1: find declaration for root element
  1596. // case 2: find declaration for element from another namespace
  1597. if (fCurrentElemDecl == null) {
  1598. if (sGrammar != null){
  1599. fCurrentElemDecl = sGrammar.getGlobalElementDecl(element.localpart);
  1600. }
  1601. }
  1602. if (fCurrentElemDecl != null) {
  1603. // then get the type
  1604. fCurrentType = fCurrentElemDecl.fType;
  1605. }
  1606. // get type from xsi:type
  1607. String xsiType = attributes.getValue(SchemaSymbols.URI_XSI, SchemaSymbols.XSI_TYPE);
  1608. // if no decl/type found for the current element
  1609. if (fCurrentType == null && xsiType == null) {
  1610. // if this is the validation root, report an error, because
  1611. // we can't find eith decl or type for this element
  1612. // REVISIT: should we report error, or warning?
  1613. if (fElementDepth == 0) {
  1614. // for dynamic validation, skip the whole content,
  1615. // because no grammar was found.
  1616. if (fDynamicValidation || fSchemaDynamicValidation) {
  1617. // no schema grammar was found, but it's either dynamic
  1618. // validation, or another kind of grammar was found (DTD,
  1619. // for example). The intended behavior here is to skip
  1620. // the whole document. To improve performance, we try to
  1621. // remove the validator from the pipeline, since it's not
  1622. // supposed to do anything.
  1623. if (fDocumentSource != null) {
  1624. fDocumentSource.setDocumentHandler(fDocumentHandler);
  1625. if (fDocumentHandler != null)
  1626. fDocumentHandler.setDocumentSource(fDocumentSource);
  1627. // indicate that the validator was removed.
  1628. fElementDepth = -2;
  1629. return augs;
  1630. }
  1631. fSkipValidationDepth = fElementDepth;
  1632. if (fAugPSVI)
  1633. augs = getEmptyAugs(augs);
  1634. return augs;
  1635. }
  1636. // We don't call reportSchemaError here, because the spec
  1637. // doesn't think it's invalid not to be able to find a
  1638. // declaration or type definition for an element. Xerces is
  1639. // reporting it as an error for historical reasons, but in
  1640. // PSVI, we shouldn't mark this element as invalid because
  1641. // of this. - SG
  1642. fXSIErrorReporter.fErrorReporter.reportError(
  1643. XSMessageFormatter.SCHEMA_DOMAIN,
  1644. "cvc-elt.1",
  1645. new Object[] { element.rawname },
  1646. XMLErrorReporter.SEVERITY_ERROR);
  1647. }
  1648. // if wildcard = strict, report error.
  1649. // needs to be called before fXSIErrorReporter.pushContext()
  1650. // so that the error belongs to the parent element.
  1651. else if (wildcard != null && wildcard.fProcessContents == XSWildcardDecl.PC_STRICT) {
  1652. // report error, because wilcard = strict
  1653. reportSchemaError("cvc-complex-type.2.4.c", new Object[] { element.rawname });
  1654. }
  1655. // no element decl or type found for this element.
  1656. // Allowed by the spec, we can choose to either laxly assess this
  1657. // element, or to skip it. Now we choose lax assessment.
  1658. fCurrentType = SchemaGrammar.fAnyType;
  1659. fStrictAssess = false;
  1660. fNFullValidationDepth = fElementDepth;
  1661. // any type has mixed content, so we don't need to append buffer
  1662. fAppendBuffer = false;
  1663. // push error reporter context: record the current position
  1664. // This has to happen after we process skip contents,
  1665. // otherwise push and pop won't be correctly paired.
  1666. fXSIErrorReporter.pushContext();
  1667. } else {
  1668. // push error reporter context: record the current position
  1669. // This has to happen after we process skip contents,
  1670. // otherwise push and pop won't be correctly paired.
  1671. fXSIErrorReporter.pushContext();
  1672. // get xsi:type
  1673. if (xsiType != null) {
  1674. XSTypeDefinition oldType = fCurrentType;
  1675. fCurrentType = getAndCheckXsiType(element, xsiType, attributes);
  1676. // If it fails, use the old type. Use anyType if ther is no old type.
  1677. if (fCurrentType == null) {
  1678. if (oldType == null)
  1679. fCurrentType = SchemaGrammar.fAnyType;
  1680. else
  1681. fCurrentType = oldType;
  1682. }
  1683. }
  1684. fNNoneValidationDepth = fElementDepth;
  1685. // if the element has a fixed value constraint, we need to append
  1686. if (fCurrentElemDecl != null
  1687. && fCurrentElemDecl.getConstraintType() == XSConstants.VC_FIXED) {
  1688. fAppendBuffer = true;
  1689. }
  1690. // if the type is simple, we need to append
  1691. else if (fCurrentType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
  1692. fAppendBuffer = true;
  1693. } else {
  1694. // if the type is simple content complex type, we need to append
  1695. XSComplexTypeDecl ctype = (XSComplexTypeDecl)fCurrentType;
  1696. fAppendBuffer = (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_SIMPLE);
  1697. }
  1698. }
  1699. // Element Locally Valid (Element)
  1700. // 2 Its {abstract} must be false.
  1701. if (fCurrentElemDecl != null && fCurrentElemDecl.getAbstract())
  1702. reportSchemaError("cvc-elt.2", new Object[] { element.rawname });
  1703. // make the current element validation root
  1704. if (fElementDepth == 0) {
  1705. fValidationRoot = element.rawname;
  1706. }
  1707. // update normalization flags
  1708. if (fNormalizeData) {
  1709. // reset values
  1710. fFirstChunk = true;
  1711. fTrailing = false;
  1712. fUnionType = false;
  1713. fWhiteSpace = -1;
  1714. }
  1715. // Element Locally Valid (Type)
  1716. // 2 Its {abstract} must be false.
  1717. if (fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
  1718. XSComplexTypeDecl ctype = (XSComplexTypeDecl) fCurrentType;
  1719. if (ctype.getAbstract()) {
  1720. reportSchemaError("cvc-type.2", new Object[] { element.rawname });
  1721. }
  1722. if (fNormalizeData) {
  1723. // find out if the content type is simple and if variety is union
  1724. // to be able to do character normalization
  1725. if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_SIMPLE) {
  1726. if (ctype.fXSSimpleType.getVariety() == XSSimpleType.VARIETY_UNION) {
  1727. fUnionType = true;
  1728. } else {
  1729. try {
  1730. fWhiteSpace = ctype.fXSSimpleType.getWhitespace();
  1731. } catch (DatatypeException e) {
  1732. // do nothing
  1733. }
  1734. }
  1735. }
  1736. }
  1737. }
  1738. // normalization: simple type
  1739. else if (fNormalizeData) {
  1740. // if !union type
  1741. XSSimpleType dv = (XSSimpleType) fCurrentType;
  1742. if (dv.getVariety() == XSSimpleType.VARIETY_UNION) {
  1743. fUnionType = true;
  1744. } else {
  1745. try {
  1746. fWhiteSpace = dv.getWhitespace();
  1747. } catch (DatatypeException e) {
  1748. // do nothing
  1749. }
  1750. }
  1751. }
  1752. // then try to get the content model
  1753. fCurrentCM = null;
  1754. if (fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
  1755. fCurrentCM = ((XSComplexTypeDecl) fCurrentType).getContentModel(fCMBuilder);
  1756. }
  1757. // and get the initial content model state
  1758. fCurrCMState = null;
  1759. if (fCurrentCM != null)
  1760. fCurrCMState = fCurrentCM.startContentModel();
  1761. // get information about xsi:nil
  1762. String xsiNil = attributes.getValue(SchemaSymbols.URI_XSI, SchemaSymbols.XSI_NIL);
  1763. // only deal with xsi:nil when there is an element declaration
  1764. if (xsiNil != null && fCurrentElemDecl != null)
  1765. fNil = getXsiNil(element, xsiNil);
  1766. // now validate everything related with the attributes
  1767. // first, get the attribute group
  1768. XSAttributeGroupDecl attrGrp = null;
  1769. if (fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
  1770. XSComplexTypeDecl ctype = (XSComplexTypeDecl) fCurrentType;
  1771. attrGrp = ctype.getAttrGrp();
  1772. }
  1773. // activate identity constraints
  1774. fValueStoreCache.startElement();
  1775. fMatcherStack.pushContext();
  1776. if (fCurrentElemDecl != null && fCurrentElemDecl.fIDCPos > 0) {
  1777. fIdConstraint = true;
  1778. // initialize when identity constrains are defined for the elem
  1779. fValueStoreCache.initValueStoresFor(fCurrentElemDecl, this);
  1780. }
  1781. processAttributes(element, attributes, attrGrp);
  1782. // add default attributes
  1783. if (attrGrp != null) {
  1784. addDefaultAttributes(element, attributes, attrGrp);
  1785. }
  1786. // call all active identity constraints
  1787. int count = fMatcherStack.getMatcherCount();
  1788. for (int i = 0; i < count; i++) {
  1789. XPathMatcher matcher = fMatcherStack.getMatcherAt(i);
  1790. matcher.startElement( element, attributes);
  1791. }
  1792. if (fAugPSVI) {
  1793. augs = getEmptyAugs(augs);
  1794. // PSVI: add validation context
  1795. fCurrentPSVI.fValidationContext = fValidationRoot;
  1796. // PSVI: add element declaration
  1797. fCurrentPSVI.fDeclaration = fCurrentElemDecl;
  1798. // PSVI: add element type
  1799. fCurrentPSVI.fTypeDecl = fCurrentType;
  1800. // PSVI: add notation attribute
  1801. fCurrentPSVI.fNotation = fNotation;
  1802. }
  1803. return augs;
  1804. } // handleStartElement(QName,XMLAttributes,boolean)
  1805. /**
  1806. * Handle end element. If there is not text content, and there is a
  1807. * {value constraint} on the corresponding element decl, then
  1808. * set the fDefaultValue XMLString representing the default value.
  1809. */
  1810. Augmentations handleEndElement(QName element, Augmentations augs) {
  1811. if (DEBUG) {
  1812. System.out.println("==>handleEndElement:" +element);
  1813. }
  1814. // if we are skipping, return
  1815. if (fSkipValidationDepth >= 0) {
  1816. // but if this is the top element that we are skipping,
  1817. // restore the states.
  1818. if (fSkipValidationDepth == fElementDepth && fSkipValidationDepth > 0) {
  1819. // set the partial validation depth to the depth of parent
  1820. fNFullValidationDepth = fSkipValidationDepth-1;
  1821. fSkipValidationDepth = -1;
  1822. fElementDepth--;
  1823. fSubElement = fSubElementStack[fElementDepth];
  1824. fCurrentElemDecl = fElemDeclStack[fElementDepth];
  1825. fNil = fNilStack[fElementDepth];
  1826. fNotation = fNotationStack[fElementDepth];
  1827. fCurrentType = fTypeStack[fElementDepth];
  1828. fCurrentCM = fCMStack[fElementDepth];
  1829. fStrictAssess = fStrictAssessStack[fElementDepth];
  1830. fCurrCMState = fCMStateStack[fElementDepth];
  1831. fSawText = fSawTextStack[fElementDepth];
  1832. fSawCharacters = fStringContent[fElementDepth];
  1833. fSawChildren = fSawChildrenStack[fElementDepth];
  1834. } else {
  1835. fElementDepth--;
  1836. }
  1837. // PSVI: validation attempted:
  1838. // use default values in psvi item for
  1839. // validation attempted, validity, and error codes
  1840. // check extra schema constraints on root element
  1841. if (fElementDepth == -1 && fFullChecking) {
  1842. XSConstraints.fullSchemaChecking(
  1843. fGrammarBucket,
  1844. fSubGroupHandler,
  1845. fCMBuilder,
  1846. fXSIErrorReporter.fErrorReporter);
  1847. }
  1848. if (fAugPSVI)
  1849. augs = getEmptyAugs(augs);
  1850. return augs;
  1851. }
  1852. // now validate the content of the element
  1853. processElementContent(element);
  1854. // Element Locally Valid (Element)
  1855. // 6 The element information item must be valid with respect to each of the {identity-constraint definitions} as per Identity-constraint Satisfied (3.11.4).
  1856. // call matchers and de-activate context
  1857. int oldCount = fMatcherStack.getMatcherCount();
  1858. for (int i = oldCount - 1; i >= 0; i--) {
  1859. XPathMatcher matcher = fMatcherStack.getMatcherAt(i);
  1860. if (fCurrentElemDecl == null)
  1861. matcher.endElement(element, null, false, fValidatedInfo.actualValue);
  1862. else
  1863. matcher.endElement(
  1864. element,
  1865. fCurrentType,
  1866. fCurrentElemDecl.getNillable(),
  1867. fDefaultValue == null
  1868. ? fValidatedInfo.actualValue
  1869. : fCurrentElemDecl.fDefault.actualValue);
  1870. }
  1871. if (fMatcherStack.size() > 0) {
  1872. fMatcherStack.popContext();
  1873. }
  1874. int newCount = fMatcherStack.getMatcherCount();
  1875. // handle everything *but* keyref's.
  1876. for (int i = oldCount - 1; i >= newCount; i--) {
  1877. XPathMatcher matcher = fMatcherStack.getMatcherAt(i);
  1878. if(matcher instanceof Selector.Matcher) {
  1879. Selector.Matcher selMatcher = (Selector.Matcher)matcher;
  1880. IdentityConstraint id;
  1881. if ((id = selMatcher.getIdentityConstraint()) != null
  1882. && id.getCategory() != IdentityConstraint.IC_KEYREF) {
  1883. fValueStoreCache.transplant(id, selMatcher.getInitialDepth());
  1884. }
  1885. }
  1886. }
  1887. // now handle keyref's/...
  1888. for (int i = oldCount - 1; i >= newCount; i--) {
  1889. XPathMatcher matcher = fMatcherStack.getMatcherAt(i);
  1890. if(matcher instanceof Selector.Matcher) {
  1891. Selector.Matcher selMatcher = (Selector.Matcher)matcher;
  1892. IdentityConstraint id;
  1893. if ((id = selMatcher.getIdentityConstraint()) != null
  1894. && id.getCategory() == IdentityConstraint.IC_KEYREF) {
  1895. ValueStoreBase values =
  1896. fValueStoreCache.getValueStoreFor(id, selMatcher.getInitialDepth());
  1897. if (values != null) // nothing to do if nothing matched!
  1898. values.endDocumentFragment();
  1899. }
  1900. }
  1901. }
  1902. fValueStoreCache.endElement();
  1903. SchemaGrammar[] grammars = null;
  1904. // have we reached the end tag of the validation root?
  1905. if (fElementDepth == 0) {
  1906. // 7 If the element information item is the validation root, it must be valid per Validation Root Valid (ID/IDREF) (3.3.4).
  1907. String invIdRef = fValidationState.checkIDRefID();
  1908. fValidationState.resetIDTables();
  1909. if (invIdRef != null) {
  1910. reportSchemaError("cvc-id.1", new Object[] { invIdRef });
  1911. }
  1912. // check extra schema constraints
  1913. if (fFullChecking) {
  1914. XSConstraints.fullSchemaChecking(
  1915. fGrammarBucket,
  1916. fSubGroupHandler,
  1917. fCMBuilder,
  1918. fXSIErrorReporter.fErrorReporter);
  1919. }
  1920. grammars = fGrammarBucket.getGrammars();
  1921. // return the final set of grammars validator ended up with
  1922. if (fGrammarPool != null) {
  1923. fGrammarPool.cacheGrammars(XMLGrammarDescription.XML_SCHEMA, grammars);
  1924. }
  1925. augs = endElementPSVI(true, grammars, augs);
  1926. } else {
  1927. augs = endElementPSVI(false, grammars, augs);
  1928. // decrease element depth and restore states
  1929. fElementDepth--;
  1930. // get the states for the parent element.
  1931. fSubElement = fSubElementStack[fElementDepth];
  1932. fCurrentElemDecl = fElemDeclStack[fElementDepth];
  1933. fNil = fNilStack[fElementDepth];
  1934. fNotation = fNotationStack[fElementDepth];
  1935. fCurrentType = fTypeStack[fElementDepth];
  1936. fCurrentCM = fCMStack[fElementDepth];
  1937. fStrictAssess = fStrictAssessStack[fElementDepth];
  1938. fCurrCMState = fCMStateStack[fElementDepth];
  1939. fSawText = fSawTextStack[fElementDepth];
  1940. fSawCharacters = fStringContent[fElementDepth];
  1941. fSawChildren = fSawChildrenStack[fElementDepth];
  1942. // We should have a stack for whitespace value, and pop it up here.
  1943. // But when fWhiteSpace != -1, and we see a sub-element, it must be
  1944. // an error (at least for Schema 1.0). So for valid documents, the
  1945. // only value we are going to push/pop in the stack is -1.
  1946. // Here we just mimic the effect of popping -1. -SG
  1947. fWhiteSpace = -1;
  1948. // Same for append buffer. Simple types and elements with fixed
  1949. // value constraint don't allow sub-elements. -SG
  1950. fAppendBuffer = false;
  1951. // same here.
  1952. fUnionType = false;
  1953. }
  1954. return augs;
  1955. } // handleEndElement(QName,boolean)*/
  1956. final Augmentations endElementPSVI(
  1957. boolean root,
  1958. SchemaGrammar[] grammars,
  1959. Augmentations augs){
  1960. if (fAugPSVI) {
  1961. augs = getEmptyAugs(augs);
  1962. // the 4 properties sent on startElement calls
  1963. fCurrentPSVI.fDeclaration = this.fCurrentElemDecl;
  1964. fCurrentPSVI.fTypeDecl = this.fCurrentType;
  1965. fCurrentPSVI.fNotation = this.fNotation;
  1966. fCurrentPSVI.fValidationContext = this.fValidationRoot;
  1967. // PSVI: validation attempted
  1968. // nothing below or at the same level has none or partial
  1969. // (which means this level is strictly assessed, and all chidren
  1970. // are full), so this one has full
  1971. if (fElementDepth > fNFullValidationDepth) {
  1972. fCurrentPSVI.fValidationAttempted = ElementPSVI.VALIDATION_FULL;
  1973. }
  1974. // nothing below or at the same level has full or partial
  1975. // (which means this level is not strictly assessed, and all chidren
  1976. // are none), so this one has none
  1977. else if (fElementDepth > fNNoneValidationDepth) {
  1978. fCurrentPSVI.fValidationAttempted = ElementPSVI.VALIDATION_NONE;
  1979. }
  1980. // otherwise partial, and anything above this level will be partial
  1981. else {
  1982. fCurrentPSVI.fValidationAttempted = ElementPSVI.VALIDATION_PARTIAL;
  1983. fNFullValidationDepth = fNNoneValidationDepth = fElementDepth - 1;
  1984. }
  1985. if (fDefaultValue != null)
  1986. fCurrentPSVI.fSpecified = true;
  1987. fCurrentPSVI.fNil = fNil;
  1988. fCurrentPSVI.fMemberType = fValidatedInfo.memberType;
  1989. fCurrentPSVI.fNormalizedValue = fValidatedInfo.normalizedValue;
  1990. fCurrentPSVI.fActualValue = fValidatedInfo.actualValue;
  1991. fCurrentPSVI.fActualValueType = fValidatedInfo.actualValueType;
  1992. fCurrentPSVI.fItemValueTypes = fValidatedInfo.itemValueTypes;
  1993. if (fStrictAssess) {
  1994. // get all errors for the current element, its attribute,
  1995. // and subelements (if they were strictly assessed).
  1996. // any error would make this element invalid.
  1997. // and we merge these errors to the parent element.
  1998. String[] errors = fXSIErrorReporter.mergeContext();
  1999. // PSVI: error codes
  2000. fCurrentPSVI.fErrorCodes = errors;
  2001. // PSVI: validity
  2002. fCurrentPSVI.fValidity =
  2003. (errors == null) ? ElementPSVI.VALIDITY_VALID : ElementPSVI.VALIDITY_INVALID;
  2004. } else {
  2005. // PSVI: validity
  2006. fCurrentPSVI.fValidity = ElementPSVI.VALIDITY_NOTKNOWN;
  2007. // Discard the current context: ignore any error happened within
  2008. // the sub-elements/attributes of this element, because those
  2009. // errors won't affect the validity of the parent elements.
  2010. fXSIErrorReporter.popContext();
  2011. }
  2012. if (root) {
  2013. // store [schema information] in the PSVI
  2014. fCurrentPSVI.fSchemaInformation = new XSModelImpl(grammars);
  2015. }
  2016. }
  2017. return augs;
  2018. }
  2019. Augmentations getEmptyAugs(Augmentations augs) {
  2020. if (augs == null) {
  2021. augs = fAugmentations;
  2022. augs.removeAllItems();
  2023. }
  2024. augs.putItem(Constants.ELEMENT_PSVI, fCurrentPSVI);
  2025. fCurrentPSVI.reset();
  2026. return augs;
  2027. }
  2028. void storeLocations(String sLocation, String nsLocation){
  2029. if (sLocation != null) {
  2030. if (!XMLSchemaLoader.tokenizeSchemaLocationStr(sLocation, fLocationPairs)) {
  2031. // error!
  2032. fXSIErrorReporter.reportError(
  2033. XSMessageFormatter.SCHEMA_DOMAIN,
  2034. "SchemaLocation",
  2035. new Object[]{sLocation},
  2036. XMLErrorReporter.SEVERITY_WARNING);
  2037. }
  2038. }
  2039. if (nsLocation != null) {
  2040. XMLSchemaLoader.LocationArray la =
  2041. ((XMLSchemaLoader.LocationArray) fLocationPairs.get(XMLSymbols.EMPTY_STRING));
  2042. if(la == null) {
  2043. la = new XMLSchemaLoader.LocationArray();
  2044. fLocationPairs.put(XMLSymbols.EMPTY_STRING, la);
  2045. }
  2046. la.addLocation(nsLocation);
  2047. }
  2048. }//storeLocations
  2049. //this is the function where logic of retrieving grammar is written , parser first tries to get the grammar from
  2050. //the local pool, if not in local pool, it gives chance to application to be able to retrieve the grammar, then it
  2051. //tries to parse the grammar using location hints from the give namespace.
  2052. SchemaGrammar findSchemaGrammar(
  2053. short contextType,
  2054. String namespace,
  2055. QName enclosingElement,
  2056. QName triggeringComponet,
  2057. XMLAttributes attributes) {
  2058. SchemaGrammar grammar = null;
  2059. //get the grammar from local pool...
  2060. grammar = fGrammarBucket.getGrammar(namespace);
  2061. if (grammar == null) {
  2062. fXSDDescription.reset();
  2063. fXSDDescription.fContextType = contextType;
  2064. fXSDDescription.setNamespace(namespace);
  2065. fXSDDescription.fEnclosedElementName = enclosingElement;
  2066. fXSDDescription.fTriggeringComponent = triggeringComponet;
  2067. fXSDDescription.fAttributes = attributes;
  2068. if (fLocator != null) {
  2069. fXSDDescription.setBaseSystemId(fLocator.getExpandedSystemId());
  2070. }
  2071. String[] temp = null ;
  2072. Object locationArray =
  2073. fLocationPairs.get(namespace == null ? XMLSymbols.EMPTY_STRING : namespace);
  2074. if(locationArray != null)
  2075. temp = ((XMLSchemaLoader.LocationArray)locationArray).getLocationArray() ;
  2076. if (temp != null && temp.length != 0) {
  2077. fXSDDescription.fLocationHints = new String [temp.length] ;
  2078. System.arraycopy(temp, 0 , fXSDDescription.fLocationHints, 0, temp.length );
  2079. }
  2080. // give a chance to application to be able to retreive the grammar.
  2081. if (fGrammarPool != null){
  2082. grammar = (SchemaGrammar)fGrammarPool.retrieveGrammar(fXSDDescription);
  2083. if (grammar != null) {
  2084. // put this grammar into the bucket, along with grammars
  2085. // imported by it (directly or indirectly)
  2086. if (!fGrammarBucket.putGrammar(grammar, true)) {
  2087. // REVISIT: a conflict between new grammar(s) and grammars
  2088. // in the bucket. What to do? A warning? An exception?
  2089. fXSIErrorReporter.fErrorReporter.reportError(
  2090. XSMessageFormatter.SCHEMA_DOMAIN,
  2091. "GrammarConflict",
  2092. null,
  2093. XMLErrorReporter.SEVERITY_WARNING);
  2094. grammar = null;
  2095. }
  2096. }
  2097. }
  2098. if (grammar == null && !fIgnoreXsiSchemaLocationHints) {
  2099. // try to parse the grammar using location hints from that namespace..
  2100. try {
  2101. XMLInputSource xis =
  2102. XMLSchemaLoader.resolveDocument(
  2103. fXSDDescription,
  2104. fLocationPairs,
  2105. fEntityResolver);
  2106. grammar = fSchemaLoader.loadSchema(fXSDDescription, xis.toSource(), fLocationPairs);
  2107. } catch (IOException ex) {
  2108. fXSIErrorReporter.fErrorReporter.reportError(
  2109. XSMessageFormatter.SCHEMA_DOMAIN,
  2110. "schema_reference.4",
  2111. new Object[]{fXSDDescription.getLocationHints()[0]},
  2112. XMLErrorReporter.SEVERITY_WARNING);
  2113. }
  2114. }
  2115. }
  2116. return grammar ;
  2117. }//findSchemaGrammar
  2118. XSTypeDefinition getAndCheckXsiType(QName element, String xsiType, XMLAttributes attributes) {
  2119. // This method also deals with clause 1.2.1.2 of the constraint
  2120. // Validation Rule: Schema-Validity Assessment (Element)
  2121. // Element Locally Valid (Element)
  2122. // 4 If there is an attribute information item among the element information item's [attributes] whose [namespace name] is identical to http://www.w3.org/2001/XMLSchema-instance and whose [local name] is type, then all of the following must be true:
  2123. // 4.1 The normalized value of that attribute information item must be valid with respect to the built-in QName simple type, as defined by String Valid (3.14.4);
  2124. QName typeName = null;
  2125. try {
  2126. typeName = (QName)fQNameDV.validate(xsiType, fValidationState, null);
  2127. } catch (InvalidDatatypeValueException e) {
  2128. reportSchemaError(e.getKey(), e.getArgs());
  2129. reportSchemaError(
  2130. "cvc-elt.4.1",
  2131. new Object[] {
  2132. element.rawname,
  2133. SchemaSymbols.URI_XSI + "," + SchemaSymbols.XSI_TYPE,
  2134. xsiType });
  2135. return null;
  2136. }
  2137. // 4.2 The local name and namespace name (as defined in QName Interpretation (3.15.3)), of the actual value of that attribute information item must resolve to a type definition, as defined in QName resolution (Instance) (3.15.4)
  2138. XSTypeDefinition type = null;
  2139. // if the namespace is schema namespace, first try built-in types
  2140. if (typeName.uri == SchemaSymbols.URI_SCHEMAFORSCHEMA) {
  2141. type = SchemaGrammar.SG_SchemaNS.getGlobalTypeDecl(typeName.localpart);
  2142. }
  2143. // if it's not schema built-in types, then try to get a grammar
  2144. if (type == null) {
  2145. //try to find schema grammar by different means....
  2146. SchemaGrammar grammar =
  2147. findSchemaGrammar(
  2148. XSDDescription.CONTEXT_XSITYPE,
  2149. typeName.uri,
  2150. element,
  2151. typeName,
  2152. attributes);
  2153. if (grammar != null)
  2154. type = grammar.getGlobalTypeDecl(typeName.localpart);
  2155. }
  2156. // still couldn't find the type, report an error
  2157. if (type == null) {
  2158. reportSchemaError("cvc-elt.4.2", new Object[]{element.rawname, xsiType});
  2159. return null;
  2160. }
  2161. // if there is no current type, set this one as current.
  2162. // and we don't need to do extra checking
  2163. if (fCurrentType != null) {
  2164. // 4.3 The local type definition must be validly derived from the {type definition} given the union of the {disallowed substitutions} and the {type definition}'s {prohibited substitutions}, as defined in Type Derivation OK (Complex) (3.4.6) (if it is a complex type definition), or given {disallowed substitutions} as defined in Type Derivation OK (Simple) (3.14.6) (if it is a simple type definition).
  2165. short block = fCurrentElemDecl.fBlock;
  2166. if (fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE)
  2167. block |= ((XSComplexTypeDecl)fCurrentType).fBlock;
  2168. if (!XSConstraints.checkTypeDerivationOk(type, fCurrentType, block))
  2169. reportSchemaError(
  2170. "cvc-elt.4.3",
  2171. new Object[] { element.rawname, xsiType, fCurrentType.getName()});
  2172. }
  2173. return type;
  2174. }//getAndCheckXsiType
  2175. boolean getXsiNil(QName element, String xsiNil) {
  2176. // Element Locally Valid (Element)
  2177. // 3 The appropriate case among the following must be true:
  2178. // 3.1 If {nillable} is false, then there must be no attribute information item among the element information item's [attributes] whose [namespace name] is identical to http://www.w3.org/2001/XMLSchema-instance and whose [local name] is nil.
  2179. if (fCurrentElemDecl != null && !fCurrentElemDecl.getNillable()) {
  2180. reportSchemaError(
  2181. "cvc-elt.3.1",
  2182. new Object[] {
  2183. element.rawname,
  2184. SchemaSymbols.URI_XSI + "," + SchemaSymbols.XSI_NIL });
  2185. }
  2186. // 3.2 If {nillable} is true and there is such an attribute information item and its actual value is true , then all of the following must be true:
  2187. // 3.2.2 There must be no fixed {value constraint}.
  2188. else {
  2189. String value = xsiNil.trim();
  2190. if (value.equals(SchemaSymbols.ATTVAL_TRUE)
  2191. || value.equals(SchemaSymbols.ATTVAL_TRUE_1)) {
  2192. if (fCurrentElemDecl != null
  2193. && fCurrentElemDecl.getConstraintType() == XSConstants.VC_FIXED) {
  2194. reportSchemaError(
  2195. "cvc-elt.3.2.2",
  2196. new Object[] {
  2197. element.rawname,
  2198. SchemaSymbols.URI_XSI + "," + SchemaSymbols.XSI_NIL });
  2199. }
  2200. return true;
  2201. }
  2202. }
  2203. return false;
  2204. }
  2205. void processAttributes(QName element, XMLAttributes attributes, XSAttributeGroupDecl attrGrp) {
  2206. if (DEBUG) {
  2207. System.out.println("==>processAttributes: " +attributes.getLength());
  2208. }
  2209. // whether we have seen a Wildcard ID.
  2210. String wildcardIDName = null;
  2211. // for each present attribute
  2212. int attCount = attributes.getLength();
  2213. Augmentations augs = null;
  2214. AttributePSVImpl attrPSVI = null;
  2215. boolean isSimple =
  2216. fCurrentType == null || fCurrentType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE;
  2217. XSObjectList attrUses = null;
  2218. int useCount = 0;
  2219. XSWildcardDecl attrWildcard = null;
  2220. if (!isSimple) {
  2221. attrUses = attrGrp.getAttributeUses();
  2222. useCount = attrUses.getLength();
  2223. attrWildcard = attrGrp.fAttributeWC;
  2224. }
  2225. // Element Locally Valid (Complex Type)
  2226. // 3 For each attribute information item in the element information item's [attributes] excepting those whose [namespace name] is identical to http://www.w3.org/2001/XMLSchema-instance and whose [local name] is one of type, nil, schemaLocation or noNamespaceSchemaLocation, the appropriate case among the following must be true:
  2227. // get the corresponding attribute decl
  2228. for (int index = 0; index < attCount; index++) {
  2229. attributes.getName(index, fTempQName);
  2230. if (DEBUG) {
  2231. System.out.println("==>process attribute: "+fTempQName);
  2232. }
  2233. if (fAugPSVI || fIdConstraint) {
  2234. augs = attributes.getAugmentations(index);
  2235. attrPSVI = (AttributePSVImpl) augs.getItem(Constants.ATTRIBUTE_PSVI);
  2236. if (attrPSVI != null) {
  2237. attrPSVI.reset();
  2238. } else {
  2239. attrPSVI= new AttributePSVImpl();
  2240. augs.putItem(Constants.ATTRIBUTE_PSVI, attrPSVI);
  2241. }
  2242. // PSVI attribute: validation context
  2243. attrPSVI.fValidationContext = fValidationRoot;
  2244. }
  2245. // Element Locally Valid (Type)
  2246. // 3.1.1 The element information item's [attributes] must be empty, excepting those
  2247. // whose [namespace name] is identical to http://www.w3.org/2001/XMLSchema-instance and
  2248. // whose [local name] is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
  2249. // for the 4 xsi attributes, get appropriate decl, and validate
  2250. if (fTempQName.uri == SchemaSymbols.URI_XSI) {
  2251. XSAttributeDecl attrDecl = null;
  2252. if (fTempQName.localpart == SchemaSymbols.XSI_SCHEMALOCATION)
  2253. attrDecl =
  2254. SchemaGrammar.SG_XSI.getGlobalAttributeDecl(
  2255. SchemaSymbols.XSI_SCHEMALOCATION);
  2256. else if (fTempQName.localpart == SchemaSymbols.XSI_NONAMESPACESCHEMALOCATION)
  2257. attrDecl =
  2258. SchemaGrammar.SG_XSI.getGlobalAttributeDecl(
  2259. SchemaSymbols.XSI_NONAMESPACESCHEMALOCATION);
  2260. else if (fTempQName.localpart == SchemaSymbols.XSI_NIL)
  2261. attrDecl = SchemaGrammar.SG_XSI.getGlobalAttributeDecl(SchemaSymbols.XSI_NIL);
  2262. else if (fTempQName.localpart == SchemaSymbols.XSI_TYPE)
  2263. attrDecl = SchemaGrammar.SG_XSI.getGlobalAttributeDecl(SchemaSymbols.XSI_TYPE);
  2264. if (attrDecl != null) {
  2265. processOneAttribute(element, attributes, index, attrDecl, null, attrPSVI);
  2266. continue;
  2267. }
  2268. }
  2269. // for namespace attributes, no_validation/unknow_validity
  2270. if (fTempQName.rawname == XMLSymbols.PREFIX_XMLNS
  2271. || fTempQName.rawname.startsWith("xmlns:")) {
  2272. continue;
  2273. }
  2274. // simple type doesn't allow any other attributes
  2275. if (isSimple) {
  2276. reportSchemaError(
  2277. "cvc-type.3.1.1",
  2278. new Object[] { element.rawname, fTempQName.rawname });
  2279. continue;
  2280. }
  2281. // it's not xmlns, and not xsi, then we need to find a decl for it
  2282. XSAttributeUseImpl currUse = null, oneUse;
  2283. for (int i = 0; i < useCount; i++) {
  2284. oneUse = (XSAttributeUseImpl)attrUses.item(i);
  2285. if (oneUse.fAttrDecl.fName == fTempQName.localpart
  2286. && oneUse.fAttrDecl.fTargetNamespace == fTempQName.uri) {
  2287. currUse = oneUse;
  2288. break;
  2289. }
  2290. }
  2291. // 3.2 otherwise all of the following must be true:
  2292. // 3.2.1 There must be an {attribute wildcard}.
  2293. // 3.2.2 The attribute information item must be valid with respect to it as defined in Item Valid (Wildcard) (3.10.4).
  2294. // if failed, get it from wildcard
  2295. if (currUse == null) {
  2296. //if (attrWildcard == null)
  2297. // reportSchemaError("cvc-complex-type.3.2.1", new Object[]{element.rawname, fTempQName.rawname});
  2298. if (attrWildcard == null || !attrWildcard.allowNamespace(fTempQName.uri)) {
  2299. // so this attribute is not allowed
  2300. reportSchemaError(
  2301. "cvc-complex-type.3.2.2",
  2302. new Object[] { element.rawname, fTempQName.rawname });
  2303. continue;
  2304. }
  2305. }
  2306. XSAttributeDecl currDecl = null;
  2307. if (currUse != null) {
  2308. currDecl = currUse.fAttrDecl;
  2309. } else {
  2310. // which means it matches a wildcard
  2311. // skip it if processContents is skip
  2312. if (attrWildcard.fProcessContents == XSWildcardDecl.PC_SKIP)
  2313. continue;
  2314. //try to find grammar by different means...
  2315. SchemaGrammar grammar =
  2316. findSchemaGrammar(
  2317. XSDDescription.CONTEXT_ATTRIBUTE,
  2318. fTempQName.uri,
  2319. element,
  2320. fTempQName,
  2321. attributes);
  2322. if (grammar != null){
  2323. currDecl = grammar.getGlobalAttributeDecl(fTempQName.localpart);
  2324. }
  2325. // if can't find
  2326. if (currDecl == null) {
  2327. // if strict, report error
  2328. if (attrWildcard.fProcessContents == XSWildcardDecl.PC_STRICT){
  2329. reportSchemaError(
  2330. "cvc-complex-type.3.2.2",
  2331. new Object[] { element.rawname, fTempQName.rawname });
  2332. }
  2333. // then continue to the next attribute
  2334. continue;
  2335. } else {
  2336. // 5 Let [Definition:] the wild IDs be the set of all attribute information item to which clause 3.2 applied and whose validation resulted in a context-determined declaration of mustFind or no context-determined declaration at all, and whose [local name] and [namespace name] resolve (as defined by QName resolution (Instance) (3.15.4)) to an attribute declaration whose {type definition} is or is derived from ID. Then all of the following must be true:
  2337. // 5.1 There must be no more than one item in wild IDs.
  2338. if (currDecl.fType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE
  2339. && ((XSSimpleType) currDecl.fType).isIDType()) {
  2340. if (wildcardIDName != null){
  2341. reportSchemaError(
  2342. "cvc-complex-type.5.1",
  2343. new Object[] { element.rawname, currDecl.fName, wildcardIDName });
  2344. } else
  2345. wildcardIDName = currDecl.fName;
  2346. }
  2347. }
  2348. }
  2349. processOneAttribute(element, attributes, index, currDecl, currUse, attrPSVI);
  2350. } // end of for (all attributes)
  2351. // 5.2 If wild IDs is non-empty, there must not be any attribute uses among the {attribute uses} whose {attribute declaration}'s {type definition} is or is derived from ID.
  2352. if (!isSimple && attrGrp.fIDAttrName != null && wildcardIDName != null){
  2353. reportSchemaError(
  2354. "cvc-complex-type.5.2",
  2355. new Object[] { element.rawname, wildcardIDName, attrGrp.fIDAttrName });
  2356. }
  2357. } //processAttributes
  2358. void processOneAttribute(
  2359. QName element,
  2360. XMLAttributes attributes,
  2361. int index,
  2362. XSAttributeDecl currDecl,
  2363. XSAttributeUseImpl currUse,
  2364. AttributePSVImpl attrPSVI) {
  2365. String attrValue = attributes.getValue(index);
  2366. fXSIErrorReporter.pushContext();
  2367. // Attribute Locally Valid
  2368. // For an attribute information item to be locally valid with respect to an attribute declaration all of the following must be true:
  2369. // 1 The declaration must not be absent (see Missing Sub-components (5.3) for how this can fail to be the case).
  2370. // 2 Its {type definition} must not be absent.
  2371. // 3 The item's normalized value must be locally valid with respect to that {type definition} as per String Valid (3.14.4).
  2372. // get simple type
  2373. XSSimpleType attDV = currDecl.fType;
  2374. Object actualValue = null;
  2375. try {
  2376. actualValue = attDV.validate(attrValue, fValidationState, fValidatedInfo);
  2377. // store the normalized value
  2378. if (fNormalizeData)
  2379. attributes.setValue(index, fValidatedInfo.normalizedValue);
  2380. Augmentations augs = attributes.getAugmentations(index);
  2381. XSSimpleType effectiveType = fValidatedInfo.memberType != null
  2382. ? fValidatedInfo.memberType : attDV;
  2383. augs.putItem(Constants.ID_ATTRIBUTE,
  2384. effectiveType.isIDType()?Boolean.TRUE:Boolean.FALSE );
  2385. augs.putItem(Constants.TYPEINFO, effectiveType );
  2386. // PSVI: element notation
  2387. if (attDV.getVariety() == XSSimpleType.VARIETY_ATOMIC &&
  2388. attDV.getPrimitiveKind() == XSSimpleType.PRIMITIVE_NOTATION){
  2389. QName qName = (QName)actualValue;
  2390. SchemaGrammar grammar = fGrammarBucket.getGrammar(qName.uri);
  2391. //REVISIT: is it possible for the notation to be in different namespace than the attribute
  2392. //with which it is associated, CHECK !! <fof n1:att1 = "n2:notation1" ..>
  2393. // should we give chance to the application to be able to retrieve a grammar - nb
  2394. //REVISIT: what would be the triggering component here.. if it is attribute value that
  2395. // triggered the loading of grammar ?? -nb
  2396. if (grammar != null) {
  2397. fNotation = grammar.getGlobalNotationDecl(qName.localpart);
  2398. }
  2399. }
  2400. } catch (InvalidDatatypeValueException idve) {
  2401. reportSchemaError(idve.getKey(), idve.getArgs());
  2402. reportSchemaError(
  2403. "cvc-attribute.3",
  2404. new Object[] { element.rawname, fTempQName.rawname, attrValue, attDV.getName()});
  2405. }
  2406. // get the value constraint from use or decl
  2407. // 4 The item's actual value must match the value of the {value constraint}, if it is present and fixed. // now check the value against the simpleType
  2408. if (actualValue != null && currDecl.getConstraintType() == XSConstants.VC_FIXED) {
  2409. if (!actualValue.equals(currDecl.fDefault.actualValue)){
  2410. reportSchemaError(
  2411. "cvc-attribute.4",
  2412. new Object[] {
  2413. element.rawname,
  2414. fTempQName.rawname,
  2415. attrValue,
  2416. currDecl.fDefault.stringValue()});
  2417. }
  2418. }
  2419. // 3.1 If there is among the {attribute uses} an attribute use with an {attribute declaration} whose {name} matches the attribute information item's [local name] and whose {target namespace} is identical to the attribute information item's [namespace name] (where an absent {target namespace} is taken to be identical to a [namespace name] with no value), then the attribute information must be valid with respect to that attribute use as per Attribute Locally Valid (Use) (3.5.4). In this case the {attribute declaration} of that attribute use is the context-determined declaration for the attribute information item with respect to Schema-Validity Assessment (Attribute) (3.2.4) and Assessment Outcome (Attribute) (3.2.5).
  2420. if (actualValue != null
  2421. && currUse != null
  2422. && currUse.fConstraintType == XSConstants.VC_FIXED) {
  2423. if (!actualValue.equals(currUse.fDefault.actualValue)){
  2424. reportSchemaError(
  2425. "cvc-complex-type.3.1",
  2426. new Object[] {
  2427. element.rawname,
  2428. fTempQName.rawname,
  2429. attrValue,
  2430. currUse.fDefault.stringValue()});
  2431. }
  2432. }
  2433. if (fIdConstraint) {
  2434. attrPSVI.fActualValue = actualValue;
  2435. }
  2436. if (fAugPSVI) {
  2437. // PSVI: attribute declaration
  2438. attrPSVI.fDeclaration = currDecl;
  2439. // PSVI: attribute type
  2440. attrPSVI.fTypeDecl = attDV;
  2441. // PSVI: attribute memberType
  2442. attrPSVI.fMemberType = fValidatedInfo.memberType;
  2443. // PSVI: attribute normalized value
  2444. // NOTE: we always store the normalized value, even if it's invlid,
  2445. // because it might still be useful to the user. But when the it's
  2446. // not valid, the normalized value is not trustable.
  2447. attrPSVI.fNormalizedValue = fValidatedInfo.normalizedValue;
  2448. attrPSVI.fActualValue = fValidatedInfo.actualValue;
  2449. attrPSVI.fActualValueType = fValidatedInfo.actualValueType;
  2450. attrPSVI.fItemValueTypes = fValidatedInfo.itemValueTypes;
  2451. // PSVI: validation attempted:
  2452. attrPSVI.fValidationAttempted = AttributePSVI.VALIDATION_FULL;
  2453. String[] errors = fXSIErrorReporter.mergeContext();
  2454. // PSVI: error codes
  2455. attrPSVI.fErrorCodes = errors;
  2456. // PSVI: validity
  2457. attrPSVI.fValidity =
  2458. (errors == null) ? AttributePSVI.VALIDITY_VALID : AttributePSVI.VALIDITY_INVALID;
  2459. }
  2460. }
  2461. void addDefaultAttributes(
  2462. QName element,
  2463. XMLAttributes attributes,
  2464. XSAttributeGroupDecl attrGrp) {
  2465. // Check after all specified attrs are scanned
  2466. // (1) report error for REQUIRED attrs that are missing (V_TAGc)
  2467. // REVISIT: should we check prohibited attributes?
  2468. // (2) report error for PROHIBITED attrs that are present (V_TAGc)
  2469. // (3) add default attrs (FIXED and NOT_FIXED)
  2470. //
  2471. if (DEBUG) {
  2472. System.out.println("==>addDefaultAttributes: " + element);
  2473. }
  2474. XSObjectList attrUses = attrGrp.getAttributeUses();
  2475. int useCount = attrUses.getLength();
  2476. XSAttributeUseImpl currUse;
  2477. XSAttributeDecl currDecl;
  2478. short constType;
  2479. ValidatedInfo defaultValue;
  2480. boolean isSpecified;
  2481. QName attName;
  2482. // for each attribute use
  2483. for (int i = 0; i < useCount; i++) {
  2484. currUse = (XSAttributeUseImpl)attrUses.item(i);
  2485. currDecl = currUse.fAttrDecl;
  2486. // get value constraint
  2487. constType = currUse.fConstraintType;
  2488. defaultValue = currUse.fDefault;
  2489. if (constType == XSConstants.VC_NONE) {
  2490. constType = currDecl.getConstraintType();
  2491. defaultValue = currDecl.fDefault;
  2492. }
  2493. // whether this attribute is specified
  2494. isSpecified = attributes.getValue(currDecl.fTargetNamespace, currDecl.fName) != null;
  2495. // Element Locally Valid (Complex Type)
  2496. // 4 The {attribute declaration} of each attribute use in the {attribute uses} whose
  2497. // {required} is true matches one of the attribute information items in the element
  2498. // information item's [attributes] as per clause 3.1 above.
  2499. if (currUse.fUse == SchemaSymbols.USE_REQUIRED) {
  2500. if (!isSpecified)
  2501. reportSchemaError("cvc-complex-type.4", new Object[]{element.rawname, currDecl.fName});
  2502. }
  2503. // if the attribute is not specified, then apply the value constraint
  2504. if (!isSpecified && constType != XSConstants.VC_NONE) {
  2505. attName = new QName(null, currDecl.fName, currDecl.fName, currDecl.fTargetNamespace);
  2506. String normalized = (defaultValue!=null)?defaultValue.stringValue():"";
  2507. int attrIndex = attributes.addAttribute(attName, "CDATA", normalized);
  2508. Augmentations augs = attributes.getAugmentations(attrIndex);
  2509. XSSimpleType effectiveType = defaultValue.memberType!=null
  2510. ? defaultValue.memberType : currDecl.fType;
  2511. augs.putItem(Constants.ID_ATTRIBUTE,
  2512. effectiveType.isIDType()?Boolean.TRUE:Boolean.FALSE );
  2513. augs.putItem(Constants.TYPEINFO,effectiveType);
  2514. if (fAugPSVI) {
  2515. // PSVI: attribute is "schema" specified
  2516. AttributePSVImpl attrPSVI = new AttributePSVImpl();
  2517. augs.putItem(Constants.ATTRIBUTE_PSVI, attrPSVI);
  2518. attrPSVI.fDeclaration = currDecl;
  2519. attrPSVI.fTypeDecl = currDecl.fType;
  2520. attrPSVI.fMemberType = defaultValue.memberType;
  2521. attrPSVI.fNormalizedValue = normalized;
  2522. attrPSVI.fActualValue = defaultValue.actualValue;
  2523. attrPSVI.fActualValueType = defaultValue.actualValueType;
  2524. attrPSVI.fItemValueTypes = defaultValue.itemValueTypes;
  2525. attrPSVI.fValidationContext = fValidationRoot;
  2526. attrPSVI.fValidity = AttributePSVI.VALIDITY_VALID;
  2527. attrPSVI.fValidationAttempted = AttributePSVI.VALIDATION_FULL;
  2528. attrPSVI.fSpecified = true;
  2529. }
  2530. }
  2531. } // for
  2532. } // addDefaultAttributes
  2533. /**
  2534. * If there is not text content, and there is a
  2535. * {value constraint} on the corresponding element decl, then return
  2536. * an XMLString representing the default value.
  2537. */
  2538. void processElementContent(QName element) {
  2539. // 1 If the item is ?valid? with respect to an element declaration as per Element Locally Valid (Element) (?3.3.4) and the {value constraint} is present, but clause 3.2 of Element Locally Valid (Element) (?3.3.4) above is not satisfied and the item has no element or character information item [children], then schema. Furthermore, the post-schema-validation infoset has the canonical lexical representation of the {value constraint} value as the item's [schema normalized value] property.
  2540. if (fCurrentElemDecl != null
  2541. && fCurrentElemDecl.fDefault != null
  2542. && !fSawText
  2543. && !fSubElement
  2544. && !fNil) {
  2545. String strv = fCurrentElemDecl.fDefault.stringValue();
  2546. int bufLen = strv.length();
  2547. if (fNormalizedStr.ch == null || fNormalizedStr.ch.length < bufLen) {
  2548. fNormalizedStr.ch = new char[bufLen];
  2549. }
  2550. strv.getChars(0, bufLen, fNormalizedStr.ch, 0);
  2551. fNormalizedStr.offset = 0;
  2552. fNormalizedStr.length = bufLen;
  2553. fDefaultValue = fNormalizedStr;
  2554. }
  2555. // fixed values are handled later, after xsi:type determined.
  2556. fValidatedInfo.normalizedValue = null;
  2557. // Element Locally Valid (Element)
  2558. // 3.2.1 The element information item must have no character or element information item [children].
  2559. if (fNil) {
  2560. if (fSubElement || fSawText){
  2561. reportSchemaError(
  2562. "cvc-elt.3.2.1",
  2563. new Object[] {
  2564. element.rawname,
  2565. SchemaSymbols.URI_XSI + "," + SchemaSymbols.XSI_NIL });
  2566. }
  2567. }
  2568. this.fValidatedInfo.reset();
  2569. // 5 The appropriate case among the following must be true:
  2570. // 5.1 If the declaration has a {value constraint}, the item has neither element nor character [children] and clause 3.2 has not applied, then all of the following must be true:
  2571. if (fCurrentElemDecl != null
  2572. && fCurrentElemDecl.getConstraintType() != XSConstants.VC_NONE
  2573. && !fSubElement
  2574. && !fSawText
  2575. && !fNil) {
  2576. // 5.1.1 If the actual type definition is a local type definition then the canonical lexical representation of the {value constraint} value must be a valid default for the actual type definition as defined in Element Default Valid (Immediate) (3.3.6).
  2577. if (fCurrentType != fCurrentElemDecl.fType) {
  2578. //REVISIT:we should pass ValidatedInfo here.
  2579. if (XSConstraints
  2580. .ElementDefaultValidImmediate(
  2581. fCurrentType,
  2582. fCurrentElemDecl.fDefault.stringValue(),
  2583. fState4XsiType,
  2584. null)
  2585. == null)
  2586. reportSchemaError(
  2587. "cvc-elt.5.1.1",
  2588. new Object[] {
  2589. element.rawname,
  2590. fCurrentType.getName(),
  2591. fCurrentElemDecl.fDefault.stringValue()});
  2592. }
  2593. // 5.1.2 The element information item with the canonical lexical representation of the {value constraint} value used as its normalized value must be valid with respect to the actual type definition as defined by Element Locally Valid (Type) (3.3.4).
  2594. // REVISIT: don't use toString, but validateActualValue instead
  2595. // use the fState4ApplyDefault
  2596. elementLocallyValidType(element, fCurrentElemDecl.fDefault.stringValue());
  2597. } else {
  2598. // The following method call also deal with clause 1.2.2 of the constraint
  2599. // Validation Rule: Schema-Validity Assessment (Element)
  2600. // 5.2 If the declaration has no {value constraint} or the item has either element or character [children] or clause 3.2 has applied, then all of the following must be true:
  2601. // 5.2.1 The element information item must be valid with respect to the actual type definition as defined by Element Locally Valid (Type) (3.3.4).
  2602. Object actualValue = elementLocallyValidType(element, fBuffer);
  2603. // 5.2.2 If there is a fixed {value constraint} and clause 3.2 has not applied, all of the following must be true:
  2604. if (fCurrentElemDecl != null
  2605. && fCurrentElemDecl.getConstraintType() == XSConstants.VC_FIXED
  2606. && !fNil) {
  2607. String content = fBuffer.toString();
  2608. // 5.2.2.1 The element information item must have no element information item [children].
  2609. if (fSubElement)
  2610. reportSchemaError("cvc-elt.5.2.2.1", new Object[]{element.rawname});
  2611. // 5.2.2.2 The appropriate case among the following must be true:
  2612. if (fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
  2613. XSComplexTypeDecl ctype = (XSComplexTypeDecl)fCurrentType;
  2614. // 5.2.2.2.1 If the {content type} of the actual type definition is mixed, then the initial value of the item must match the canonical lexical representation of the {value constraint} value.
  2615. if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_MIXED) {
  2616. // REVISIT: how to get the initial value, does whiteSpace count?
  2617. if (!fCurrentElemDecl.fDefault.normalizedValue.equals(content))
  2618. reportSchemaError(
  2619. "cvc-elt.5.2.2.2.1",
  2620. new Object[] {
  2621. element.rawname,
  2622. content,
  2623. fCurrentElemDecl.fDefault.normalizedValue });
  2624. }
  2625. // 5.2.2.2.2 If the {content type} of the actual type definition is a simple type definition, then the actual value of the item must match the canonical lexical representation of the {value constraint} value.
  2626. else if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_SIMPLE) {
  2627. if (actualValue != null
  2628. && !actualValue.equals(fCurrentElemDecl.fDefault.actualValue))
  2629. reportSchemaError(
  2630. "cvc-elt.5.2.2.2.2",
  2631. new Object[] {
  2632. element.rawname,
  2633. content,
  2634. fCurrentElemDecl.fDefault.stringValue()});
  2635. }
  2636. } else if (fCurrentType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
  2637. if (actualValue != null
  2638. && !actualValue.equals(fCurrentElemDecl.fDefault.actualValue))
  2639. // REVISIT: the spec didn't mention this case: fixed
  2640. // value with simple type
  2641. reportSchemaError(
  2642. "cvc-elt.5.2.2.2.2",
  2643. new Object[] {
  2644. element.rawname,
  2645. content,
  2646. fCurrentElemDecl.fDefault.stringValue()});
  2647. }
  2648. }
  2649. }
  2650. if (fDefaultValue == null && fNormalizeData && fDocumentHandler != null && fUnionType) {
  2651. // for union types we need to send data because we delayed sending
  2652. // this data when we received it in the characters() call.
  2653. String content = fValidatedInfo.normalizedValue;
  2654. if (content == null)
  2655. content = fBuffer.toString();
  2656. int bufLen = content.length();
  2657. if (fNormalizedStr.ch == null || fNormalizedStr.ch.length < bufLen) {
  2658. fNormalizedStr.ch = new char[bufLen];
  2659. }
  2660. content.getChars(0, bufLen, fNormalizedStr.ch, 0);
  2661. fNormalizedStr.offset = 0;
  2662. fNormalizedStr.length = bufLen;
  2663. fDocumentHandler.characters(fNormalizedStr, null);
  2664. }
  2665. } // processElementContent
  2666. Object elementLocallyValidType(QName element, Object textContent) {
  2667. if (fCurrentType == null)
  2668. return null;
  2669. Object retValue = null;
  2670. // Element Locally Valid (Type)
  2671. // 3 The appropriate case among the following must be true:
  2672. // 3.1 If the type definition is a simple type definition, then all of the following must be true:
  2673. if (fCurrentType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
  2674. // 3.1.2 The element information item must have no element information item [children].
  2675. if (fSubElement)
  2676. reportSchemaError("cvc-type.3.1.2", new Object[]{element.rawname});
  2677. // 3.1.3 If clause 3.2 of Element Locally Valid (Element) (3.3.4) did not apply, then the normalized value must be valid with respect to the type definition as defined by String Valid (3.14.4).
  2678. if (!fNil) {
  2679. XSSimpleType dv = (XSSimpleType)fCurrentType;
  2680. try {
  2681. if (!fNormalizeData || fUnionType) {
  2682. fValidationState.setNormalizationRequired(true);
  2683. }
  2684. retValue = dv.validate(textContent, fValidationState, fValidatedInfo);
  2685. } catch (InvalidDatatypeValueException e) {
  2686. reportSchemaError(e.getKey(), e.getArgs());
  2687. reportSchemaError(
  2688. "cvc-type.3.1.3",
  2689. new Object[] { element.rawname, textContent });
  2690. }
  2691. }
  2692. } else {
  2693. // 3.2 If the type definition is a complex type definition, then the element information item must be valid with respect to the type definition as per Element Locally Valid (Complex Type) (3.4.4);
  2694. retValue = elementLocallyValidComplexType(element, textContent);
  2695. }
  2696. return retValue;
  2697. } // elementLocallyValidType
  2698. Object elementLocallyValidComplexType(QName element, Object textContent) {
  2699. Object actualValue = null;
  2700. XSComplexTypeDecl ctype = (XSComplexTypeDecl)fCurrentType;
  2701. // Element Locally Valid (Complex Type)
  2702. // For an element information item to be locally valid with respect to a complex type definition all of the following must be true:
  2703. // 1 {abstract} is false.
  2704. // 2 If clause 3.2 of Element Locally Valid (Element) (3.3.4) did not apply, then the appropriate case among the following must be true:
  2705. if (!fNil) {
  2706. // 2.1 If the {content type} is empty, then the element information item has no character or element information item [children].
  2707. if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_EMPTY
  2708. && (fSubElement || fSawText || fSawChildren)) {
  2709. reportSchemaError("cvc-complex-type.2.1", new Object[]{element.rawname});
  2710. }
  2711. // 2.2 If the {content type} is a simple type definition, then the element information item has no element information item [children], and the normalized value of the element information item is valid with respect to that simple type definition as defined by String Valid (3.14.4).
  2712. else if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_SIMPLE) {
  2713. if (fSubElement)
  2714. reportSchemaError("cvc-complex-type.2.2", new Object[]{element.rawname});
  2715. XSSimpleType dv = ctype.fXSSimpleType;
  2716. try {
  2717. if (!fNormalizeData || fUnionType) {
  2718. fValidationState.setNormalizationRequired(true);
  2719. }
  2720. actualValue = dv.validate(textContent, fValidationState, fValidatedInfo);
  2721. } catch (InvalidDatatypeValueException e) {
  2722. reportSchemaError(e.getKey(), e.getArgs());
  2723. reportSchemaError("cvc-complex-type.2.2", new Object[]{element.rawname});
  2724. }
  2725. // REVISIT: eventually, this method should return the same actualValue as elementLocallyValidType...
  2726. // obviously it'll return null when the content is complex.
  2727. }
  2728. // 2.3 If the {content type} is element-only, then the element information item has no character information item [children] other than those whose [character code] is defined as a white space in [XML 1.0 (Second Edition)].
  2729. else if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_ELEMENT) {
  2730. if (fSawCharacters) {
  2731. reportSchemaError("cvc-complex-type.2.3", new Object[]{element.rawname});
  2732. }
  2733. }
  2734. // 2.4 If the {content type} is element-only or mixed, then the sequence of the element information item's element information item [children], if any, taken in order, is valid with respect to the {content type}'s particle, as defined in Element Sequence Locally Valid (Particle) (3.9.4).
  2735. if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_ELEMENT
  2736. || ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_MIXED) {
  2737. // if the current state is a valid state, check whether
  2738. // it's one of the final states.
  2739. if (DEBUG) {
  2740. System.out.println(fCurrCMState);
  2741. }
  2742. if (fCurrCMState[0] >= 0 && !fCurrentCM.endContentModel(fCurrCMState)) {
  2743. String expected = expectedStr(fCurrentCM.whatCanGoHere(fCurrCMState));
  2744. reportSchemaError(
  2745. "cvc-complex-type.2.4.b",
  2746. new Object[] { element.rawname, expected });
  2747. }
  2748. }
  2749. }
  2750. return actualValue;
  2751. } // elementLocallyValidComplexType
  2752. public void reportSchemaError(String key, Object[] arguments) {
  2753. if (fDoValidation)
  2754. fXSIErrorReporter.reportError(
  2755. XSMessageFormatter.SCHEMA_DOMAIN,
  2756. key,
  2757. arguments,
  2758. XMLErrorReporter.SEVERITY_ERROR);
  2759. }
  2760. private String expectedStr(Vector expected) {
  2761. StringBuffer ret = new StringBuffer("{");
  2762. int size = expected.size();
  2763. for (int i = 0; i < size; i++) {
  2764. if (i > 0)
  2765. ret.append(", ");
  2766. ret.append(expected.elementAt(i).toString());
  2767. }
  2768. ret.append('}');
  2769. return ret.toString();
  2770. }
  2771. /**********************************/
  2772. // xpath matcher information
  2773. /**
  2774. * Stack of XPath matchers for identity constraints.
  2775. *
  2776. * @author Andy Clark, IBM
  2777. */
  2778. protected static class XPathMatcherStack {
  2779. //
  2780. // Data
  2781. //
  2782. /** Active matchers. */
  2783. protected XPathMatcher[] fMatchers = new XPathMatcher[4];
  2784. /** Count of active matchers. */
  2785. protected int fMatchersCount;
  2786. /** Offset stack for contexts. */
  2787. protected IntStack fContextStack = new IntStack();
  2788. //
  2789. // Constructors
  2790. //
  2791. public XPathMatcherStack() {
  2792. } // <init>()
  2793. //
  2794. // Public methods
  2795. //
  2796. /** Resets the XPath matcher stack. */
  2797. public void clear() {
  2798. for (int i = 0; i < fMatchersCount; i++) {
  2799. fMatchers[i] = null;
  2800. }
  2801. fMatchersCount = 0;
  2802. fContextStack.clear();
  2803. } // clear()
  2804. /** Returns the size of the stack. */
  2805. public int size() {
  2806. return fContextStack.size();
  2807. } // size():int
  2808. /** Returns the count of XPath matchers. */
  2809. public int getMatcherCount() {
  2810. return fMatchersCount;
  2811. } // getMatcherCount():int
  2812. /** Adds a matcher. */
  2813. public void addMatcher(XPathMatcher matcher) {
  2814. ensureMatcherCapacity();
  2815. fMatchers[fMatchersCount++] = matcher;
  2816. } // addMatcher(XPathMatcher)
  2817. /** Returns the XPath matcher at the specified index. */
  2818. public XPathMatcher getMatcherAt(int index) {
  2819. return fMatchers[index];
  2820. } // getMatcherAt(index):XPathMatcher
  2821. /** Pushes a new context onto the stack. */
  2822. public void pushContext() {
  2823. fContextStack.push(fMatchersCount);
  2824. } // pushContext()
  2825. /** Pops a context off of the stack. */
  2826. public void popContext() {
  2827. fMatchersCount = fContextStack.pop();
  2828. } // popContext()
  2829. //
  2830. // Private methods
  2831. //
  2832. /** Ensures the size of the matchers array. */
  2833. private void ensureMatcherCapacity() {
  2834. if (fMatchersCount == fMatchers.length) {
  2835. XPathMatcher[] array = new XPathMatcher[fMatchers.length * 2];
  2836. System.arraycopy(fMatchers, 0, array, 0, fMatchers.length);
  2837. fMatchers = array;
  2838. }
  2839. } // ensureMatcherCapacity()
  2840. } // class XPathMatcherStack
  2841. // value store implementations
  2842. /**
  2843. * Value store implementation base class. There are specific subclasses
  2844. * for handling unique, key, and keyref.
  2845. *
  2846. * @author Andy Clark, IBM
  2847. */
  2848. protected abstract class ValueStoreBase implements ValueStore {
  2849. //
  2850. // Data
  2851. //
  2852. /** Identity constraint. */
  2853. protected IdentityConstraint fIdentityConstraint;
  2854. protected int fFieldCount = 0;
  2855. protected Field[] fFields = null;
  2856. /** current data */
  2857. protected Object[] fLocalValues = null;
  2858. protected Object[] fLocalValueTypes = null;
  2859. /** Current data value count. */
  2860. protected int fValuesCount;
  2861. /** global data */
  2862. public final Vector fValues = new Vector();
  2863. public final Vector fValueTypes = new Vector();
  2864. /** buffer for error messages */
  2865. final StringBuffer fTempBuffer = new StringBuffer();
  2866. //
  2867. // Constructors
  2868. //
  2869. /** Constructs a value store for the specified identity constraint. */
  2870. protected ValueStoreBase(IdentityConstraint identityConstraint) {
  2871. fIdentityConstraint = identityConstraint;
  2872. fFieldCount = fIdentityConstraint.getFieldCount();
  2873. fFields = new Field[fFieldCount];
  2874. fLocalValues = new Object[fFieldCount];
  2875. fLocalValueTypes = new Object[fFieldCount];
  2876. for (int i = 0; i < fFieldCount; i++) {
  2877. fFields[i] = fIdentityConstraint.getFieldAt(i);
  2878. }
  2879. } // <init>(IdentityConstraint)
  2880. //
  2881. // Public methods
  2882. //
  2883. // destroys this ValueStore; useful when, for instance, a
  2884. // locally-scoped ID constraint is involved.
  2885. public void clear() {
  2886. fValuesCount = 0;
  2887. fValues.setSize(0);
  2888. fValueTypes.setSize(0);
  2889. } // end clear():void
  2890. // appends the contents of one ValueStore to those of us.
  2891. public void append(ValueStoreBase newVal) {
  2892. for (int i = 0; i < newVal.fValues.size(); i++) {
  2893. fValues.addElement(newVal.fValues.elementAt(i));
  2894. fValueTypes.addElement(newVal.fValueTypes.elementAt(i));
  2895. }
  2896. } // append(ValueStoreBase)
  2897. /** Start scope for value store. */
  2898. public void startValueScope() {
  2899. fValuesCount = 0;
  2900. for (int i = 0; i < fFieldCount; i++) {
  2901. fLocalValues[i] = null;
  2902. fLocalValueTypes[i] = null;
  2903. }
  2904. } // startValueScope()
  2905. /** Ends scope for value store. */
  2906. public void endValueScope() {
  2907. if (fValuesCount == 0) {
  2908. if (fIdentityConstraint.getCategory() == IdentityConstraint.IC_KEY) {
  2909. String code = "AbsentKeyValue";
  2910. String eName = fIdentityConstraint.getElementName();
  2911. reportSchemaError(code, new Object[] { eName });
  2912. }
  2913. return;
  2914. }
  2915. // do we have enough values?
  2916. if (fValuesCount != fFieldCount) {
  2917. switch (fIdentityConstraint.getCategory()) {
  2918. case IdentityConstraint.IC_UNIQUE : {
  2919. String code = "UniqueNotEnoughValues";
  2920. String ename = fIdentityConstraint.getElementName();
  2921. reportSchemaError(code, new Object[] { ename });
  2922. break;
  2923. }
  2924. case IdentityConstraint.IC_KEY : {
  2925. String code = "KeyNotEnoughValues";
  2926. UniqueOrKey key = (UniqueOrKey) fIdentityConstraint;
  2927. String ename = fIdentityConstraint.getElementName();
  2928. String kname = key.getIdentityConstraintName();
  2929. reportSchemaError(code, new Object[] { ename, kname });
  2930. break;
  2931. }
  2932. case IdentityConstraint.IC_KEYREF : {
  2933. String code = "KeyRefNotEnoughValues";
  2934. KeyRef keyref = (KeyRef) fIdentityConstraint;
  2935. String ename = fIdentityConstraint.getElementName();
  2936. String kname = (keyref.getKey()).getIdentityConstraintName();
  2937. reportSchemaError(code, new Object[] { ename, kname });
  2938. break;
  2939. }
  2940. }
  2941. return;
  2942. }
  2943. } // endValueScope()
  2944. // This is needed to allow keyref's to look for matched keys
  2945. // in the correct scope. Unique and Key may also need to
  2946. // override this method for purposes of their own.
  2947. // This method is called whenever the DocumentFragment
  2948. // of an ID Constraint goes out of scope.
  2949. public void endDocumentFragment() {
  2950. } // endDocumentFragment():void
  2951. /**
  2952. * Signals the end of the document. This is where the specific
  2953. * instances of value stores can verify the integrity of the
  2954. * identity constraints.
  2955. */
  2956. public void endDocument() {
  2957. } // endDocument()
  2958. //
  2959. // ValueStore methods
  2960. //
  2961. /* reports an error if an element is matched
  2962. * has nillable true and is matched by a key.
  2963. */
  2964. public void reportError(String key, Object[] args) {
  2965. reportSchemaError(key, args);
  2966. } // reportError(String,Object[])
  2967. /**
  2968. * Adds the specified value to the value store.
  2969. *
  2970. * @param value The value to add.
  2971. * @param field The field associated to the value. This reference
  2972. * is used to ensure that each field only adds a value
  2973. * once within a selection scope.
  2974. */
  2975. public void addValue(Field field, Object actualValue) {
  2976. addValue(field,actualValue,null);
  2977. }
  2978. public void addValue(Field field, Object actualValue,Object type) {
  2979. int i;
  2980. for (i = fFieldCount - 1; i > -1; i--) {
  2981. if (fFields[i] == field) {
  2982. break;
  2983. }
  2984. }
  2985. // do we even know this field?
  2986. if (i == -1) {
  2987. String code = "UnknownField";
  2988. reportSchemaError(code, new Object[] { field.toString()});
  2989. return;
  2990. }
  2991. if (Boolean.TRUE != mayMatch(field)) {
  2992. String code = "FieldMultipleMatch";
  2993. reportSchemaError(code, new Object[] { field.toString()});
  2994. } else {
  2995. fValuesCount++;
  2996. }
  2997. fLocalValues[i] = actualValue;
  2998. fLocalValueTypes[i] = type;
  2999. if (fValuesCount == fFieldCount) {
  3000. checkDuplicateValues();
  3001. // store values
  3002. for (i = 0; i < fFieldCount; i++) {
  3003. fValues.addElement(fLocalValues[i]);
  3004. if(fLocalValueTypes[i] != null)
  3005. fValueTypes.addElement(fLocalValueTypes[i]);
  3006. }
  3007. }
  3008. } // addValue(String,Field)
  3009. /**
  3010. * Returns true if this value store contains the locally scoped value stores
  3011. */
  3012. public boolean contains() {
  3013. // REVISIT: we can improve performance by using hash codes, instead of
  3014. // traversing global vector that could be quite large.
  3015. int next = 0;
  3016. LOOP : for (int i = 0; i < fValues.size(); i = next) {
  3017. next = i + fFieldCount;
  3018. for (int j = 0; j < fFieldCount; j++) {
  3019. Object value1 = fLocalValues[j];
  3020. Object value2 = fValues.elementAt(i++);
  3021. if (value1 == null || value2 == null || !(value1.equals(value2))) {
  3022. continue LOOP;
  3023. }
  3024. }
  3025. // found it
  3026. return true;
  3027. }
  3028. // didn't find it
  3029. return false;
  3030. } // contains():boolean
  3031. /**
  3032. * Returns true if this value store contains the specified
  3033. * values.
  3034. */
  3035. public Object contains(Vector values) {
  3036. for (int i = 0; i < values.size(); i++) {
  3037. if (!fValues.contains(values.elementAt(i)))
  3038. return values.elementAt(i);
  3039. }
  3040. return null;
  3041. } // contains(Vector):boolean
  3042. protected boolean isDerivedFromSamePrimitiveType(XSTypeDefinition typeOne , XSTypeDefinition typeTwo){
  3043. if(typeOne == null || typeTwo == null)
  3044. return false;
  3045. if(typeOne.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE &&
  3046. ((XSComplexTypeDefinition) typeOne).getContentType() == XSComplexTypeDefinition.CONTENTTYPE_SIMPLE) {
  3047. typeOne = ((XSComplexTypeDefinition)typeOne).getSimpleType();
  3048. }
  3049. if(typeTwo.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE && ((XSComplexTypeDefinition) typeTwo).getContentType() == XSComplexTypeDefinition.CONTENTTYPE_SIMPLE) {
  3050. typeTwo = ((XSComplexTypeDefinition)typeTwo).getSimpleType();
  3051. }
  3052. if(typeOne == null || typeTwo == null)
  3053. return false;
  3054. if((typeOne.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) && (typeTwo.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE)){
  3055. try{
  3056. short s1 = ((XSSimpleTypeDecl)typeOne).getPrimitiveKind();
  3057. short s2 = ((XSSimpleTypeDecl)typeTwo).getPrimitiveKind();
  3058. if(s1 == s2)
  3059. return true;
  3060. }catch(Exception ex){
  3061. if(DEBUG)ex.printStackTrace();
  3062. }
  3063. }
  3064. return false;
  3065. }
  3066. public Object contains(Vector values,Vector types) {
  3067. for (int i = 0; i < values.size(); i++) {
  3068. if (fValues.contains(values.elementAt(i))){
  3069. int j = fValues.indexOf(values.elementAt(i));
  3070. try{
  3071. if(!isDerivedFromSamePrimitiveType((XSTypeDefinition)fValueTypes.elementAt(j),(XSTypeDefinition)types.elementAt(i)))
  3072. return values.elementAt(i);
  3073. }catch(Exception ex){
  3074. return values.elementAt(i);
  3075. }
  3076. }else
  3077. return values.elementAt(i);
  3078. }
  3079. return null;
  3080. } // contains(Vector):boolean
  3081. //
  3082. // Protected methods
  3083. //
  3084. protected void checkDuplicateValues() {
  3085. // no-op
  3086. } // duplicateValue(Hashtable)
  3087. /** Returns a string of the specified values. */
  3088. protected String toString(Object[] values) {
  3089. // no values
  3090. int size = values.length;
  3091. if (size == 0) {
  3092. return "";
  3093. }
  3094. fTempBuffer.setLength(0);
  3095. // construct value string
  3096. for (int i = 0; i < size; i++) {
  3097. if (i > 0) {
  3098. fTempBuffer.append(',');
  3099. }
  3100. fTempBuffer.append(values[i]);
  3101. }
  3102. return fTempBuffer.toString();
  3103. } // toString(Object[]):String
  3104. //
  3105. // Object methods
  3106. //
  3107. /** Returns a string representation of this object. */
  3108. public String toString() {
  3109. String s = super.toString();
  3110. int index1 = s.lastIndexOf('$');
  3111. if (index1 != -1) {
  3112. s = s.substring(index1 + 1);
  3113. }
  3114. int index2 = s.lastIndexOf('.');
  3115. if (index2 != -1) {
  3116. s = s.substring(index2 + 1);
  3117. }
  3118. return s + '[' + fIdentityConstraint + ']';
  3119. } // toString():String
  3120. } // class ValueStoreBase
  3121. /**
  3122. * Unique value store.
  3123. *
  3124. * @author Andy Clark, IBM
  3125. */
  3126. protected class UniqueValueStore extends ValueStoreBase {
  3127. //
  3128. // Constructors
  3129. //
  3130. /** Constructs a unique value store. */
  3131. public UniqueValueStore(UniqueOrKey unique) {
  3132. super(unique);
  3133. } // <init>(Unique)
  3134. //
  3135. // ValueStoreBase protected methods
  3136. //
  3137. /**
  3138. * Called when a duplicate value is added.
  3139. */
  3140. protected void checkDuplicateValues() {
  3141. // is this value as a group duplicated?
  3142. if (contains()) {
  3143. String code = "DuplicateUnique";
  3144. String value = toString(fLocalValues);
  3145. String ename = fIdentityConstraint.getElementName();
  3146. reportSchemaError(code, new Object[]{value,ename});
  3147. }
  3148. } // duplicateValue(Hashtable)
  3149. } // class UniqueValueStore
  3150. /**
  3151. * Key value store.
  3152. *
  3153. * @author Andy Clark, IBM
  3154. */
  3155. protected class KeyValueStore extends ValueStoreBase {
  3156. // REVISIT: Implement a more efficient storage mechanism. -Ac
  3157. //
  3158. // Constructors
  3159. //
  3160. /** Constructs a key value store. */
  3161. public KeyValueStore(UniqueOrKey key) {
  3162. super(key);
  3163. } // <init>(Key)
  3164. //
  3165. // ValueStoreBase protected methods
  3166. //
  3167. /**
  3168. * Called when a duplicate value is added.
  3169. */
  3170. protected void checkDuplicateValues() {
  3171. if (contains()) {
  3172. String code = "DuplicateKey";
  3173. String value = toString(fLocalValues);
  3174. String ename = fIdentityConstraint.getElementName();
  3175. reportSchemaError(code, new Object[]{value,ename});
  3176. }
  3177. } // duplicateValue(Hashtable)
  3178. } // class KeyValueStore
  3179. /**
  3180. * Key reference value store.
  3181. *
  3182. * @author Andy Clark, IBM
  3183. */
  3184. protected class KeyRefValueStore extends ValueStoreBase {
  3185. //
  3186. // Data
  3187. //
  3188. /** Key value store. */
  3189. protected ValueStoreBase fKeyValueStore;
  3190. //
  3191. // Constructors
  3192. //
  3193. /** Constructs a key value store. */
  3194. public KeyRefValueStore(KeyRef keyRef, KeyValueStore keyValueStore) {
  3195. super(keyRef);
  3196. fKeyValueStore = keyValueStore;
  3197. } // <init>(KeyRef)
  3198. //
  3199. // ValueStoreBase methods
  3200. //
  3201. // end the value Scope; here's where we have to tie
  3202. // up keyRef loose ends.
  3203. public void endDocumentFragment() {
  3204. // do all the necessary management...
  3205. super.endDocumentFragment();
  3206. // verify references
  3207. // get the key store corresponding (if it exists):
  3208. fKeyValueStore =
  3209. (ValueStoreBase) fValueStoreCache.fGlobalIDConstraintMap.get(
  3210. ((KeyRef) fIdentityConstraint).getKey());
  3211. if (fKeyValueStore == null) {
  3212. // report error
  3213. String code = "KeyRefOutOfScope";
  3214. String value = fIdentityConstraint.toString();
  3215. reportSchemaError(code, new Object[]{value});
  3216. return;
  3217. }
  3218. Object value = fKeyValueStore.contains(fValues,fValueTypes);
  3219. if (value != null) {
  3220. String code = "KeyNotFound";
  3221. String element = fIdentityConstraint.getElementName();
  3222. String name = fIdentityConstraint.getName();
  3223. reportSchemaError(code, new Object[] { name, value.toString(), element });
  3224. }
  3225. } // endDocumentFragment()
  3226. /** End document. */
  3227. public void endDocument() {
  3228. super.endDocument();
  3229. } // endDocument()
  3230. } // class KeyRefValueStore
  3231. // value store management
  3232. /**
  3233. * Value store cache. This class is used to store the values for
  3234. * identity constraints.
  3235. *
  3236. * @author Andy Clark, IBM
  3237. */
  3238. protected class ValueStoreCache {
  3239. //
  3240. // Data
  3241. //
  3242. final LocalIDKey fLocalId = new LocalIDKey();
  3243. // values stores
  3244. /** stores all global Values stores. */
  3245. protected final Vector fValueStores = new Vector();
  3246. /**
  3247. * Values stores associated to specific identity constraints.
  3248. * This hashtable maps IdentityConstraints and
  3249. * the 0-based element on which their selectors first matched to
  3250. * a corresponding ValueStore. This should take care
  3251. * of all cases, including where ID constraints with
  3252. * descendant-or-self axes occur on recursively-defined
  3253. * elements.
  3254. */
  3255. protected final Hashtable fIdentityConstraint2ValueStoreMap = new Hashtable();
  3256. // sketch of algorithm:
  3257. // - when a constraint is first encountered, its
  3258. // values are stored in the (local) fIdentityConstraint2ValueStoreMap;
  3259. // - Once it is validated (i.e., when it goes out of scope),
  3260. // its values are merged into the fGlobalIDConstraintMap;
  3261. // - as we encounter keyref's, we look at the global table to
  3262. // validate them.
  3263. //
  3264. // The fGlobalIDMapStack has the following structure:
  3265. // - validation always occurs against the fGlobalIDConstraintMap
  3266. // (which comprises all the "eligible" id constraints);
  3267. // When an endElement is found, this Hashtable is merged with the one
  3268. // below in the stack.
  3269. // When a start tag is encountered, we create a new
  3270. // fGlobalIDConstraintMap.
  3271. // i.e., the top of the fGlobalIDMapStack always contains
  3272. // the preceding siblings' eligible id constraints;
  3273. // the fGlobalIDConstraintMap contains descendants+self.
  3274. // keyrefs can only match descendants+self.
  3275. protected final Stack fGlobalMapStack = new Stack();
  3276. protected final Hashtable fGlobalIDConstraintMap = new Hashtable();
  3277. //
  3278. // Constructors
  3279. //
  3280. /** Default constructor. */
  3281. public ValueStoreCache() {
  3282. } // <init>()
  3283. //
  3284. // Public methods
  3285. //
  3286. /** Resets the identity constraint cache. */
  3287. public void startDocument() {
  3288. fValueStores.removeAllElements();
  3289. fIdentityConstraint2ValueStoreMap.clear();
  3290. fGlobalIDConstraintMap.clear();
  3291. fGlobalMapStack.removeAllElements();
  3292. } // startDocument()
  3293. // startElement: pushes the current fGlobalIDConstraintMap
  3294. // onto fGlobalMapStack and clears fGlobalIDConstraint map.
  3295. public void startElement() {
  3296. // only clone the hashtable when there are elements
  3297. if (fGlobalIDConstraintMap.size() > 0)
  3298. fGlobalMapStack.push(fGlobalIDConstraintMap.clone());
  3299. else
  3300. fGlobalMapStack.push(null);
  3301. fGlobalIDConstraintMap.clear();
  3302. } // startElement(void)
  3303. /** endElement(): merges contents of fGlobalIDConstraintMap with the
  3304. * top of fGlobalMapStack into fGlobalIDConstraintMap.
  3305. */
  3306. public void endElement() {
  3307. if (fGlobalMapStack.isEmpty())
  3308. return; // must be an invalid doc!
  3309. Hashtable oldMap = (Hashtable)fGlobalMapStack.pop();
  3310. // return if there is no element
  3311. if (oldMap == null)
  3312. return;
  3313. Enumeration keys = oldMap.keys();
  3314. while (keys.hasMoreElements()) {
  3315. IdentityConstraint id = (IdentityConstraint)keys.nextElement();
  3316. ValueStoreBase oldVal = (ValueStoreBase)oldMap.get(id);
  3317. if (oldVal != null) {
  3318. ValueStoreBase currVal = (ValueStoreBase)fGlobalIDConstraintMap.get(id);
  3319. if (currVal == null)
  3320. fGlobalIDConstraintMap.put(id, oldVal);
  3321. else if (currVal != oldVal) {
  3322. currVal.append(oldVal);
  3323. }
  3324. }
  3325. }
  3326. } // endElement()
  3327. /**
  3328. * Initializes the value stores for the specified element
  3329. * declaration.
  3330. */
  3331. public void initValueStoresFor(XSElementDecl eDecl, FieldActivator activator) {
  3332. // initialize value stores for unique fields
  3333. IdentityConstraint [] icArray = eDecl.fIDConstraints;
  3334. int icCount = eDecl.fIDCPos;
  3335. for (int i = 0; i < icCount; i++) {
  3336. switch (icArray[i].getCategory()) {
  3337. case (IdentityConstraint.IC_UNIQUE):
  3338. // initialize value stores for unique fields
  3339. UniqueOrKey unique = (UniqueOrKey)icArray[i];
  3340. LocalIDKey toHash = new LocalIDKey(unique, fElementDepth);
  3341. UniqueValueStore uniqueValueStore =
  3342. (UniqueValueStore) fIdentityConstraint2ValueStoreMap.get(toHash);
  3343. if (uniqueValueStore == null) {
  3344. uniqueValueStore = new UniqueValueStore(unique);
  3345. fIdentityConstraint2ValueStoreMap.put(toHash, uniqueValueStore);
  3346. } else {
  3347. uniqueValueStore.clear();
  3348. }
  3349. fValueStores.addElement(uniqueValueStore);
  3350. activateSelectorFor(icArray[i]);
  3351. break;
  3352. case (IdentityConstraint.IC_KEY):
  3353. // initialize value stores for key fields
  3354. UniqueOrKey key = (UniqueOrKey)icArray[i];
  3355. toHash = new LocalIDKey(key, fElementDepth);
  3356. KeyValueStore keyValueStore =
  3357. (KeyValueStore) fIdentityConstraint2ValueStoreMap.get(toHash);
  3358. if (keyValueStore == null) {
  3359. keyValueStore = new KeyValueStore(key);
  3360. fIdentityConstraint2ValueStoreMap.put(toHash, keyValueStore);
  3361. } else {
  3362. keyValueStore.clear();
  3363. }
  3364. fValueStores.addElement(keyValueStore);
  3365. activateSelectorFor(icArray[i]);
  3366. break;
  3367. case (IdentityConstraint.IC_KEYREF):
  3368. // initialize value stores for keyRef fields
  3369. KeyRef keyRef = (KeyRef)icArray[i];
  3370. toHash = new LocalIDKey(keyRef, fElementDepth);
  3371. KeyRefValueStore keyRefValueStore =
  3372. (KeyRefValueStore) fIdentityConstraint2ValueStoreMap.get(toHash);
  3373. if (keyRefValueStore == null) {
  3374. keyRefValueStore = new KeyRefValueStore(keyRef, null);
  3375. fIdentityConstraint2ValueStoreMap.put(toHash, keyRefValueStore);
  3376. } else {
  3377. keyRefValueStore.clear();
  3378. }
  3379. fValueStores.addElement(keyRefValueStore);
  3380. activateSelectorFor(icArray[i]);
  3381. break;
  3382. }
  3383. }
  3384. } // initValueStoresFor(XSElementDecl)
  3385. /** Returns the value store associated to the specified IdentityConstraint. */
  3386. public ValueStoreBase getValueStoreFor(IdentityConstraint id, int initialDepth) {
  3387. fLocalId.fDepth = initialDepth;
  3388. fLocalId.fId = id;
  3389. return (ValueStoreBase) fIdentityConstraint2ValueStoreMap.get(fLocalId);
  3390. } // getValueStoreFor(IdentityConstraint, int):ValueStoreBase
  3391. /** Returns the global value store associated to the specified IdentityConstraint. */
  3392. public ValueStoreBase getGlobalValueStoreFor(IdentityConstraint id) {
  3393. return(ValueStoreBase)fGlobalIDConstraintMap.get(id);
  3394. } // getValueStoreFor(IdentityConstraint):ValueStoreBase
  3395. // This method takes the contents of the (local) ValueStore
  3396. // associated with id and moves them into the global
  3397. // hashtable, if id is a <unique> or a <key>.
  3398. // If it's a <keyRef>, then we leave it for later.
  3399. public void transplant(IdentityConstraint id, int initialDepth) {
  3400. fLocalId.fDepth = initialDepth;
  3401. fLocalId.fId = id;
  3402. ValueStoreBase newVals =
  3403. (ValueStoreBase) fIdentityConstraint2ValueStoreMap.get(fLocalId);
  3404. if (id.getCategory() == IdentityConstraint.IC_KEYREF)
  3405. return;
  3406. ValueStoreBase currVals = (ValueStoreBase)fGlobalIDConstraintMap.get(id);
  3407. if (currVals != null) {
  3408. currVals.append(newVals);
  3409. fGlobalIDConstraintMap.put(id, currVals);
  3410. } else
  3411. fGlobalIDConstraintMap.put(id, newVals);
  3412. } // transplant(id)
  3413. /** Check identity constraints. */
  3414. public void endDocument() {
  3415. int count = fValueStores.size();
  3416. for (int i = 0; i < count; i++) {
  3417. ValueStoreBase valueStore = (ValueStoreBase)fValueStores.elementAt(i);
  3418. valueStore.endDocument();
  3419. }
  3420. } // endDocument()
  3421. //
  3422. // Object methods
  3423. //
  3424. /** Returns a string representation of this object. */
  3425. public String toString() {
  3426. String s = super.toString();
  3427. int index1 = s.lastIndexOf('$');
  3428. if (index1 != -1) {
  3429. return s.substring(index1 + 1);
  3430. }
  3431. int index2 = s.lastIndexOf('.');
  3432. if (index2 != -1) {
  3433. return s.substring(index2 + 1);
  3434. }
  3435. return s;
  3436. } // toString():String
  3437. } // class ValueStoreCache
  3438. // the purpose of this class is to enable IdentityConstraint,int
  3439. // pairs to be used easily as keys in Hashtables.
  3440. protected class LocalIDKey {
  3441. public IdentityConstraint fId;
  3442. public int fDepth;
  3443. public LocalIDKey() {
  3444. }
  3445. public LocalIDKey(IdentityConstraint id, int depth) {
  3446. fId = id;
  3447. fDepth = depth;
  3448. } // init(IdentityConstraint, int)
  3449. // object method
  3450. public int hashCode() {
  3451. return fId.hashCode()+fDepth;
  3452. }
  3453. public boolean equals(Object localIDKey) {
  3454. if(localIDKey instanceof LocalIDKey) {
  3455. LocalIDKey lIDKey = (LocalIDKey)localIDKey;
  3456. return (lIDKey.fId == fId && lIDKey.fDepth == fDepth);
  3457. }
  3458. return false;
  3459. }
  3460. } // class LocalIDKey
  3461. } // class SchemaValidator