0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */
0017:
0018: package org.apache.xerces.impl.xs;
0019:
0020: import java.io.IOException;
0021: import java.util.Enumeration;
0022: import java.util.Hashtable;
0023: import java.util.Stack;
0024: import java.util.Vector;
0025:
0026: import javax.xml.XMLConstants;
0027:
0028: import org.apache.xerces.impl.Constants;
0029: import org.apache.xerces.impl.RevalidationHandler;
0030: import org.apache.xerces.impl.XMLErrorReporter;
0031: import org.apache.xerces.impl.dv.DatatypeException;
0032: import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
0033: import org.apache.xerces.impl.dv.ValidatedInfo;
0034: import org.apache.xerces.impl.dv.XSSimpleType;
0035: import org.apache.xerces.impl.validation.ConfigurableValidationState;
0036: import org.apache.xerces.impl.validation.ValidationManager;
0037: import org.apache.xerces.impl.validation.ValidationState;
0038: import org.apache.xerces.impl.xs.identity.Field;
0039: import org.apache.xerces.impl.xs.identity.FieldActivator;
0040: import org.apache.xerces.impl.xs.identity.IdentityConstraint;
0041: import org.apache.xerces.impl.xs.identity.KeyRef;
0042: import org.apache.xerces.impl.xs.identity.Selector;
0043: import org.apache.xerces.impl.xs.identity.UniqueOrKey;
0044: import org.apache.xerces.impl.xs.identity.ValueStore;
0045: import org.apache.xerces.impl.xs.identity.XPathMatcher;
0046: import org.apache.xerces.impl.xs.models.CMBuilder;
0047: import org.apache.xerces.impl.xs.models.CMNodeFactory;
0048: import org.apache.xerces.impl.xs.models.XSCMValidator;
0049: import org.apache.xerces.util.AugmentationsImpl;
0050: import org.apache.xerces.util.IntStack;
0051: import org.apache.xerces.util.SymbolTable;
0052: import org.apache.xerces.util.XMLAttributesImpl;
0053: import org.apache.xerces.util.XMLChar;
0054: import org.apache.xerces.util.XMLSymbols;
0055: import org.apache.xerces.xni.Augmentations;
0056: import org.apache.xerces.xni.NamespaceContext;
0057: import org.apache.xerces.xni.QName;
0058: import org.apache.xerces.xni.XMLAttributes;
0059: import org.apache.xerces.xni.XMLDocumentHandler;
0060: import org.apache.xerces.xni.XMLLocator;
0061: import org.apache.xerces.xni.XMLResourceIdentifier;
0062: import org.apache.xerces.xni.XMLString;
0063: import org.apache.xerces.xni.XNIException;
0064: import org.apache.xerces.xni.grammars.XMLGrammarDescription;
0065: import org.apache.xerces.xni.grammars.XMLGrammarPool;
0066: import org.apache.xerces.xni.parser.XMLComponent;
0067: import org.apache.xerces.xni.parser.XMLComponentManager;
0068: import org.apache.xerces.xni.parser.XMLConfigurationException;
0069: import org.apache.xerces.xni.parser.XMLDocumentFilter;
0070: import org.apache.xerces.xni.parser.XMLDocumentSource;
0071: import org.apache.xerces.xni.parser.XMLEntityResolver;
0072: import org.apache.xerces.xni.parser.XMLInputSource;
0073: import org.apache.xerces.xs.AttributePSVI;
0074: import org.apache.xerces.xs.ElementPSVI;
0075: import org.apache.xerces.xs.ShortList;
0076: import org.apache.xerces.xs.XSConstants;
0077: import org.apache.xerces.xs.XSObjectList;
0078: import org.apache.xerces.xs.XSTypeDefinition;
0079:
0080: /**
0081: * The XML Schema validator. The validator implements a document
0082: * filter: receiving document events from the scanner; validating
0083: * the content and structure; augmenting the InfoSet, if applicable;
0084: * and notifying the parser of the information resulting from the
0085: * validation process.
0086: * <p>
0087: * This component requires the following features and properties from the
0088: * component manager that uses it:
0089: * <ul>
0090: * <li>http://xml.org/sax/features/validation</li>
0091: * <li>http://apache.org/xml/properties/internal/symbol-table</li>
0092: * <li>http://apache.org/xml/properties/internal/error-reporter</li>
0093: * <li>http://apache.org/xml/properties/internal/entity-resolver</li>
0094: * </ul>
0095: *
0096: * @xerces.internal
0097: *
0098: * @author Sandy Gao IBM
0099: * @author Elena Litani IBM
0100: * @author Andy Clark IBM
0101: * @author Neeraj Bajaj, Sun Microsystems, inc.
0102: * @version $Id: XMLSchemaValidator.java 548089 2007-06-17 18:29:01Z mrglavas $
0103: */
0104: public class XMLSchemaValidator implements XMLComponent,
0105: XMLDocumentFilter, FieldActivator, RevalidationHandler {
0106:
0107: //
0108: // Constants
0109: //
0110: private static final boolean DEBUG = false;
0111:
0112: // feature identifiers
0113:
0114: /** Feature identifier: validation. */
0115: protected static final String VALIDATION = Constants.SAX_FEATURE_PREFIX
0116: + Constants.VALIDATION_FEATURE;
0117:
0118: /** Feature identifier: validation. */
0119: protected static final String SCHEMA_VALIDATION = Constants.XERCES_FEATURE_PREFIX
0120: + Constants.SCHEMA_VALIDATION_FEATURE;
0121:
0122: /** Feature identifier: schema full checking*/
0123: protected static final String SCHEMA_FULL_CHECKING = Constants.XERCES_FEATURE_PREFIX
0124: + Constants.SCHEMA_FULL_CHECKING;
0125:
0126: /** Feature identifier: dynamic validation. */
0127: protected static final String DYNAMIC_VALIDATION = Constants.XERCES_FEATURE_PREFIX
0128: + Constants.DYNAMIC_VALIDATION_FEATURE;
0129:
0130: /** Feature identifier: expose schema normalized value */
0131: protected static final String NORMALIZE_DATA = Constants.XERCES_FEATURE_PREFIX
0132: + Constants.SCHEMA_NORMALIZED_VALUE;
0133:
0134: /** Feature identifier: send element default value via characters() */
0135: protected static final String SCHEMA_ELEMENT_DEFAULT = Constants.XERCES_FEATURE_PREFIX
0136: + Constants.SCHEMA_ELEMENT_DEFAULT;
0137:
0138: /** Feature identifier: augment PSVI */
0139: protected static final String SCHEMA_AUGMENT_PSVI = Constants.XERCES_FEATURE_PREFIX
0140: + Constants.SCHEMA_AUGMENT_PSVI;
0141:
0142: /** Feature identifier: whether to recognize java encoding names */
0143: protected static final String ALLOW_JAVA_ENCODINGS = Constants.XERCES_FEATURE_PREFIX
0144: + Constants.ALLOW_JAVA_ENCODINGS_FEATURE;
0145:
0146: /** Feature identifier: standard uri conformant feature. */
0147: protected static final String STANDARD_URI_CONFORMANT_FEATURE = Constants.XERCES_FEATURE_PREFIX
0148: + Constants.STANDARD_URI_CONFORMANT_FEATURE;
0149:
0150: /** Feature: generate synthetic annotations */
0151: protected static final String GENERATE_SYNTHETIC_ANNOTATIONS = Constants.XERCES_FEATURE_PREFIX
0152: + Constants.GENERATE_SYNTHETIC_ANNOTATIONS_FEATURE;
0153:
0154: /** Feature identifier: validate annotations. */
0155: protected static final String VALIDATE_ANNOTATIONS = Constants.XERCES_FEATURE_PREFIX
0156: + Constants.VALIDATE_ANNOTATIONS_FEATURE;
0157:
0158: /** Feature identifier: honour all schemaLocations */
0159: protected static final String HONOUR_ALL_SCHEMALOCATIONS = Constants.XERCES_FEATURE_PREFIX
0160: + Constants.HONOUR_ALL_SCHEMALOCATIONS_FEATURE;
0161:
0162: /** Feature identifier: use grammar pool only */
0163: protected static final String USE_GRAMMAR_POOL_ONLY = Constants.XERCES_FEATURE_PREFIX
0164: + Constants.USE_GRAMMAR_POOL_ONLY_FEATURE;
0165:
0166: /** Feature identifier: whether to continue parsing a schema after a fatal error is encountered */
0167: protected static final String CONTINUE_AFTER_FATAL_ERROR = Constants.XERCES_FEATURE_PREFIX
0168: + Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE;
0169:
0170: protected static final String PARSER_SETTINGS = Constants.XERCES_FEATURE_PREFIX
0171: + Constants.PARSER_SETTINGS;
0172:
0173: /** Feature identifier: whether to ignore xsi:type attributes until a global element declaration is encountered */
0174: protected static final String IGNORE_XSI_TYPE = Constants.XERCES_FEATURE_PREFIX
0175: + Constants.IGNORE_XSI_TYPE_FEATURE;
0176:
0177: /** Feature identifier: whether to ignore ID/IDREF errors */
0178: protected static final String ID_IDREF_CHECKING = Constants.XERCES_FEATURE_PREFIX
0179: + Constants.ID_IDREF_CHECKING_FEATURE;
0180:
0181: /** Feature identifier: whether to ignore unparsed entity errors */
0182: protected static final String UNPARSED_ENTITY_CHECKING = Constants.XERCES_FEATURE_PREFIX
0183: + Constants.UNPARSED_ENTITY_CHECKING_FEATURE;
0184:
0185: /** Feature identifier: whether to ignore identity constraint errors */
0186: protected static final String IDENTITY_CONSTRAINT_CHECKING = Constants.XERCES_FEATURE_PREFIX
0187: + Constants.IDC_CHECKING_FEATURE;
0188:
0189: // property identifiers
0190:
0191: /** Property identifier: symbol table. */
0192: public static final String SYMBOL_TABLE = Constants.XERCES_PROPERTY_PREFIX
0193: + Constants.SYMBOL_TABLE_PROPERTY;
0194:
0195: /** Property identifier: error reporter. */
0196: public static final String ERROR_REPORTER = Constants.XERCES_PROPERTY_PREFIX
0197: + Constants.ERROR_REPORTER_PROPERTY;
0198:
0199: /** Property identifier: entity resolver. */
0200: public static final String ENTITY_RESOLVER = Constants.XERCES_PROPERTY_PREFIX
0201: + Constants.ENTITY_RESOLVER_PROPERTY;
0202:
0203: /** Property identifier: grammar pool. */
0204: public static final String XMLGRAMMAR_POOL = Constants.XERCES_PROPERTY_PREFIX
0205: + Constants.XMLGRAMMAR_POOL_PROPERTY;
0206:
0207: protected static final String VALIDATION_MANAGER = Constants.XERCES_PROPERTY_PREFIX
0208: + Constants.VALIDATION_MANAGER_PROPERTY;
0209:
0210: protected static final String ENTITY_MANAGER = Constants.XERCES_PROPERTY_PREFIX
0211: + Constants.ENTITY_MANAGER_PROPERTY;
0212:
0213: /** Property identifier: schema location. */
0214: protected static final String SCHEMA_LOCATION = Constants.XERCES_PROPERTY_PREFIX
0215: + Constants.SCHEMA_LOCATION;
0216:
0217: /** Property identifier: no namespace schema location. */
0218: protected static final String SCHEMA_NONS_LOCATION = Constants.XERCES_PROPERTY_PREFIX
0219: + Constants.SCHEMA_NONS_LOCATION;
0220:
0221: /** Property identifier: JAXP schema source. */
0222: protected static final String JAXP_SCHEMA_SOURCE = Constants.JAXP_PROPERTY_PREFIX
0223: + Constants.SCHEMA_SOURCE;
0224:
0225: /** Property identifier: JAXP schema language. */
0226: protected static final String JAXP_SCHEMA_LANGUAGE = Constants.JAXP_PROPERTY_PREFIX
0227: + Constants.SCHEMA_LANGUAGE;
0228:
0229: /** Property identifier: root type definition. */
0230: protected static final String ROOT_TYPE_DEF = Constants.XERCES_PROPERTY_PREFIX
0231: + Constants.ROOT_TYPE_DEFINITION_PROPERTY;
0232:
0233: // recognized features and properties
0234:
0235: /** Recognized features. */
0236: private static final String[] RECOGNIZED_FEATURES = { VALIDATION,
0237: SCHEMA_VALIDATION, DYNAMIC_VALIDATION,
0238: SCHEMA_FULL_CHECKING, ALLOW_JAVA_ENCODINGS,
0239: CONTINUE_AFTER_FATAL_ERROR,
0240: STANDARD_URI_CONFORMANT_FEATURE,
0241: GENERATE_SYNTHETIC_ANNOTATIONS, VALIDATE_ANNOTATIONS,
0242: HONOUR_ALL_SCHEMALOCATIONS, USE_GRAMMAR_POOL_ONLY,
0243: IGNORE_XSI_TYPE, ID_IDREF_CHECKING,
0244: IDENTITY_CONSTRAINT_CHECKING, UNPARSED_ENTITY_CHECKING, };
0245:
0246: /** Feature defaults. */
0247: private static final Boolean[] FEATURE_DEFAULTS = { null,
0248: // NOTE: The following defaults are nulled out on purpose.
0249: // If they are set, then when the XML Schema validator
0250: // is constructed dynamically, these values may override
0251: // those set by the application. This goes against the
0252: // whole purpose of XMLComponent#getFeatureDefault but
0253: // it can't be helped in this case. -Ac
0254: // NOTE: Instead of adding default values here, add them (and
0255: // the corresponding recognized features) to the objects
0256: // that have an XMLSchemaValidator instance as a member,
0257: // such as the parser configurations. -PM
0258: null, //Boolean.FALSE,
0259: null, //Boolean.FALSE,
0260: null, //Boolean.FALSE,
0261: null, //Boolean.FALSE,
0262: null, //Boolean.FALSE,
0263: null, null, null, null, null, null, null, null, null, };
0264:
0265: /** Recognized properties. */
0266: private static final String[] RECOGNIZED_PROPERTIES = {
0267: SYMBOL_TABLE, ERROR_REPORTER, ENTITY_RESOLVER,
0268: VALIDATION_MANAGER, SCHEMA_LOCATION, SCHEMA_NONS_LOCATION,
0269: JAXP_SCHEMA_SOURCE, JAXP_SCHEMA_LANGUAGE, ROOT_TYPE_DEF, };
0270:
0271: /** Property defaults. */
0272: private static final Object[] PROPERTY_DEFAULTS = { null, null,
0273: null, null, null, null, null, null, null, };
0274:
0275: // this is the number of valuestores of each kind
0276: // we expect an element to have. It's almost
0277: // never > 1; so leave it at that.
0278: protected static final int ID_CONSTRAINT_NUM = 1;
0279:
0280: // xsi:* attribute declarations
0281: static final XSAttributeDecl XSI_TYPE = SchemaGrammar.SG_XSI
0282: .getGlobalAttributeDecl(SchemaSymbols.XSI_TYPE);
0283: static final XSAttributeDecl XSI_NIL = SchemaGrammar.SG_XSI
0284: .getGlobalAttributeDecl(SchemaSymbols.XSI_NIL);
0285: static final XSAttributeDecl XSI_SCHEMALOCATION = SchemaGrammar.SG_XSI
0286: .getGlobalAttributeDecl(SchemaSymbols.XSI_SCHEMALOCATION);
0287: static final XSAttributeDecl XSI_NONAMESPACESCHEMALOCATION = SchemaGrammar.SG_XSI
0288: .getGlobalAttributeDecl(SchemaSymbols.XSI_NONAMESPACESCHEMALOCATION);
0289:
0290: //
0291: // Data
0292: //
0293:
0294: /** current PSVI element info */
0295: protected ElementPSVImpl fCurrentPSVI = new ElementPSVImpl();
0296:
0297: // since it is the responsibility of each component to an
0298: // Augmentations parameter if one is null, to save ourselves from
0299: // having to create this object continually, it is created here.
0300: // If it is not present in calls that we're passing on, we *must*
0301: // clear this before we introduce it into the pipeline.
0302: protected final AugmentationsImpl fAugmentations = new AugmentationsImpl();
0303:
0304: // this is included for the convenience of handleEndElement
0305: protected XMLString fDefaultValue;
0306:
0307: // Validation features
0308: protected boolean fDynamicValidation = false;
0309: protected boolean fSchemaDynamicValidation = false;
0310: protected boolean fDoValidation = false;
0311: protected boolean fFullChecking = false;
0312: protected boolean fNormalizeData = true;
0313: protected boolean fSchemaElementDefault = true;
0314: protected boolean fAugPSVI = true;
0315: protected boolean fIdConstraint = false;
0316: protected boolean fUseGrammarPoolOnly = false;
0317:
0318: /** Schema type: None, DTD, Schema */
0319: private String fSchemaType = null;
0320:
0321: // to indicate whether we are in the scope of entity reference or CData
0322: protected boolean fEntityRef = false;
0323: protected boolean fInCDATA = false;
0324:
0325: // properties
0326:
0327: /** Symbol table. */
0328: protected SymbolTable fSymbolTable;
0329:
0330: /**
0331: * While parsing a document, keep the location of the document.
0332: */
0333: private XMLLocator fLocator;
0334:
0335: /**
0336: * A wrapper of the standard error reporter. We'll store all schema errors
0337: * in this wrapper object, so that we can get all errors (error codes) of
0338: * a specific element. This is useful for PSVI.
0339: */
0340: protected final class XSIErrorReporter {
0341:
0342: // the error reporter property
0343: XMLErrorReporter fErrorReporter;
0344:
0345: // store error codes; starting position of the errors for each element;
0346: // number of element (depth); and whether to record error
0347: Vector fErrors = new Vector();
0348: int[] fContext = new int[INITIAL_STACK_SIZE];
0349: int fContextCount;
0350:
0351: // set the external error reporter, clear errors
0352: public void reset(XMLErrorReporter errorReporter) {
0353: fErrorReporter = errorReporter;
0354: fErrors.removeAllElements();
0355: fContextCount = 0;
0356: }
0357:
0358: // should be called when starting process an element or an attribute.
0359: // store the starting position for the current context
0360: public void pushContext() {
0361: if (!fAugPSVI) {
0362: return;
0363: }
0364: // resize array if necessary
0365: if (fContextCount == fContext.length) {
0366: int newSize = fContextCount + INC_STACK_SIZE;
0367: int[] newArray = new int[newSize];
0368: System.arraycopy(fContext, 0, newArray, 0,
0369: fContextCount);
0370: fContext = newArray;
0371: }
0372:
0373: fContext[fContextCount++] = fErrors.size();
0374: }
0375:
0376: // should be called on endElement: get all errors of the current element
0377: public String[] popContext() {
0378: if (!fAugPSVI) {
0379: return null;
0380: }
0381: // get starting position of the current element
0382: int contextPos = fContext[--fContextCount];
0383: // number of errors of the current element
0384: int size = fErrors.size() - contextPos;
0385: // if no errors, return null
0386: if (size == 0)
0387: return null;
0388: // copy errors from the list to an string array
0389: String[] errors = new String[size];
0390: for (int i = 0; i < size; i++) {
0391: errors[i] = (String) fErrors.elementAt(contextPos + i);
0392: }
0393: // remove errors of the current element
0394: fErrors.setSize(contextPos);
0395: return errors;
0396: }
0397:
0398: // should be called when an attribute is done: get all errors of
0399: // this attribute, but leave the errors to the containing element
0400: // also called after an element was strictly assessed.
0401: public String[] mergeContext() {
0402: if (!fAugPSVI) {
0403: return null;
0404: }
0405: // get starting position of the current element
0406: int contextPos = fContext[--fContextCount];
0407: // number of errors of the current element
0408: int size = fErrors.size() - contextPos;
0409: // if no errors, return null
0410: if (size == 0)
0411: return null;
0412: // copy errors from the list to an string array
0413: String[] errors = new String[size];
0414: for (int i = 0; i < size; i++) {
0415: errors[i] = (String) fErrors.elementAt(contextPos + i);
0416: }
0417: // don't resize the vector: leave the errors for this attribute
0418: // to the containing element
0419: return errors;
0420: }
0421:
0422: public void reportError(String domain, String key,
0423: Object[] arguments, short severity) throws XNIException {
0424: fErrorReporter
0425: .reportError(domain, key, arguments, severity);
0426: if (fAugPSVI) {
0427: fErrors.addElement(key);
0428: }
0429: } // reportError(String,String,Object[],short)
0430:
0431: public void reportError(XMLLocator location, String domain,
0432: String key, Object[] arguments, short severity)
0433: throws XNIException {
0434: fErrorReporter.reportError(location, domain, key,
0435: arguments, severity);
0436: if (fAugPSVI) {
0437: fErrors.addElement(key);
0438: }
0439: } // reportError(XMLLocator,String,String,Object[],short)
0440: }
0441:
0442: /** Error reporter. */
0443: protected final XSIErrorReporter fXSIErrorReporter = new XSIErrorReporter();
0444:
0445: /** Entity resolver */
0446: protected XMLEntityResolver fEntityResolver;
0447:
0448: // updated during reset
0449: protected ValidationManager fValidationManager = null;
0450: protected ConfigurableValidationState fValidationState = new ConfigurableValidationState();
0451: protected XMLGrammarPool fGrammarPool;
0452:
0453: // schema location property values
0454: protected String fExternalSchemas = null;
0455: protected String fExternalNoNamespaceSchema = null;
0456:
0457: //JAXP Schema Source property
0458: protected Object fJaxpSchemaSource = null;
0459:
0460: /** Schema Grammar Description passed, to give a chance to application to supply the Grammar */
0461: protected final XSDDescription fXSDDescription = new XSDDescription();
0462: protected final Hashtable fLocationPairs = new Hashtable();
0463:
0464: // handlers
0465:
0466: /** Document handler. */
0467: protected XMLDocumentHandler fDocumentHandler;
0468:
0469: protected XMLDocumentSource fDocumentSource;
0470:
0471: //
0472: // XMLComponent methods
0473: //
0474:
0475: /**
0476: * Returns a list of feature identifiers that are recognized by
0477: * this component. This method may return null if no features
0478: * are recognized by this component.
0479: */
0480: public String[] getRecognizedFeatures() {
0481: return (String[]) (RECOGNIZED_FEATURES.clone());
0482: } // getRecognizedFeatures():String[]
0483:
0484: /**
0485: * Sets the state of a feature. This method is called by the component
0486: * manager any time after reset when a feature changes state.
0487: * <p>
0488: * <strong>Note:</strong> Components should silently ignore features
0489: * that do not affect the operation of the component.
0490: *
0491: * @param featureId The feature identifier.
0492: * @param state The state of the feature.
0493: *
0494: * @throws SAXNotRecognizedException The component should not throw
0495: * this exception.
0496: * @throws SAXNotSupportedException The component should not throw
0497: * this exception.
0498: */
0499: public void setFeature(String featureId, boolean state)
0500: throws XMLConfigurationException {
0501: } // setFeature(String,boolean)
0502:
0503: /**
0504: * Returns a list of property identifiers that are recognized by
0505: * this component. This method may return null if no properties
0506: * are recognized by this component.
0507: */
0508: public String[] getRecognizedProperties() {
0509: return (String[]) (RECOGNIZED_PROPERTIES.clone());
0510: } // getRecognizedProperties():String[]
0511:
0512: /**
0513: * Sets the value of a property. This method is called by the component
0514: * manager any time after reset when a property changes value.
0515: * <p>
0516: * <strong>Note:</strong> Components should silently ignore properties
0517: * that do not affect the operation of the component.
0518: *
0519: * @param propertyId The property identifier.
0520: * @param value The value of the property.
0521: *
0522: * @throws SAXNotRecognizedException The component should not throw
0523: * this exception.
0524: * @throws SAXNotSupportedException The component should not throw
0525: * this exception.
0526: */
0527: public void setProperty(String propertyId, Object value)
0528: throws XMLConfigurationException {
0529: if (propertyId.equals(ROOT_TYPE_DEF)) {
0530: fRootTypeQName = (javax.xml.namespace.QName) value;
0531: }
0532: } // setProperty(String,Object)
0533:
0534: /**
0535: * Returns the default state for a feature, or null if this
0536: * component does not want to report a default value for this
0537: * feature.
0538: *
0539: * @param featureId The feature identifier.
0540: *
0541: * @since Xerces 2.2.0
0542: */
0543: public Boolean getFeatureDefault(String featureId) {
0544: for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
0545: if (RECOGNIZED_FEATURES[i].equals(featureId)) {
0546: return FEATURE_DEFAULTS[i];
0547: }
0548: }
0549: return null;
0550: } // getFeatureDefault(String):Boolean
0551:
0552: /**
0553: * Returns the default state for a property, or null if this
0554: * component does not want to report a default value for this
0555: * property.
0556: *
0557: * @param propertyId The property identifier.
0558: *
0559: * @since Xerces 2.2.0
0560: */
0561: public Object getPropertyDefault(String propertyId) {
0562: for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
0563: if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
0564: return PROPERTY_DEFAULTS[i];
0565: }
0566: }
0567: return null;
0568: } // getPropertyDefault(String):Object
0569:
0570: //
0571: // XMLDocumentSource methods
0572: //
0573:
0574: /** Sets the document handler to receive information about the document. */
0575: public void setDocumentHandler(XMLDocumentHandler documentHandler) {
0576: fDocumentHandler = documentHandler;
0577: } // setDocumentHandler(XMLDocumentHandler)
0578:
0579: /** Returns the document handler */
0580: public XMLDocumentHandler getDocumentHandler() {
0581: return fDocumentHandler;
0582: } // setDocumentHandler(XMLDocumentHandler)
0583:
0584: //
0585: // XMLDocumentHandler methods
0586: //
0587:
0588: /** Sets the document source */
0589: public void setDocumentSource(XMLDocumentSource source) {
0590: fDocumentSource = source;
0591: } // setDocumentSource
0592:
0593: /** Returns the document source */
0594: public XMLDocumentSource getDocumentSource() {
0595: return fDocumentSource;
0596: } // getDocumentSource
0597:
0598: /**
0599: * The start of the document.
0600: *
0601: * @param locator The system identifier of the entity if the entity
0602: * is external, null otherwise.
0603: * @param encoding The auto-detected IANA encoding name of the entity
0604: * stream. This value will be null in those situations
0605: * where the entity encoding is not auto-detected (e.g.
0606: * internal entities or a document entity that is
0607: * parsed from a java.io.Reader).
0608: * @param namespaceContext
0609: * The namespace context in effect at the
0610: * start of this document.
0611: * This object represents the current context.
0612: * Implementors of this class are responsible
0613: * for copying the namespace bindings from the
0614: * the current context (and its parent contexts)
0615: * if that information is important.
0616: * @param augs Additional information that may include infoset augmentations
0617: *
0618: * @throws XNIException Thrown by handler to signal an error.
0619: */
0620: public void startDocument(XMLLocator locator, String encoding,
0621: NamespaceContext namespaceContext, Augmentations augs)
0622: throws XNIException {
0623:
0624: fValidationState.setNamespaceSupport(namespaceContext);
0625: fState4XsiType.setNamespaceSupport(namespaceContext);
0626: fState4ApplyDefault.setNamespaceSupport(namespaceContext);
0627: fLocator = locator;
0628:
0629: handleStartDocument(locator, encoding);
0630: // call handlers
0631: if (fDocumentHandler != null) {
0632: fDocumentHandler.startDocument(locator, encoding,
0633: namespaceContext, augs);
0634: }
0635:
0636: } // startDocument(XMLLocator,String)
0637:
0638: /**
0639: * Notifies of the presence of an XMLDecl line in the document. If
0640: * present, this method will be called immediately following the
0641: * startDocument call.
0642: *
0643: * @param version The XML version.
0644: * @param encoding The IANA encoding name of the document, or null if
0645: * not specified.
0646: * @param standalone The standalone value, or null if not specified.
0647: * @param augs Additional information that may include infoset augmentations
0648: *
0649: * @throws XNIException Thrown by handler to signal an error.
0650: */
0651: public void xmlDecl(String version, String encoding,
0652: String standalone, Augmentations augs) throws XNIException {
0653:
0654: // call handlers
0655: if (fDocumentHandler != null) {
0656: fDocumentHandler.xmlDecl(version, encoding, standalone,
0657: augs);
0658: }
0659:
0660: } // xmlDecl(String,String,String)
0661:
0662: /**
0663: * Notifies of the presence of the DOCTYPE line in the document.
0664: *
0665: * @param rootElement The name of the root element.
0666: * @param publicId The public identifier if an external DTD or null
0667: * if the external DTD is specified using SYSTEM.
0668: * @param systemId The system identifier if an external DTD, null
0669: * otherwise.
0670: * @param augs Additional information that may include infoset augmentations
0671: *
0672: * @throws XNIException Thrown by handler to signal an error.
0673: */
0674: public void doctypeDecl(String rootElement, String publicId,
0675: String systemId, Augmentations augs) throws XNIException {
0676:
0677: // call handlers
0678: if (fDocumentHandler != null) {
0679: fDocumentHandler.doctypeDecl(rootElement, publicId,
0680: systemId, augs);
0681: }
0682:
0683: } // doctypeDecl(String,String,String)
0684:
0685: /**
0686: * The start of an element.
0687: *
0688: * @param element The name of the element.
0689: * @param attributes The element attributes.
0690: * @param augs Additional information that may include infoset augmentations
0691: *
0692: * @throws XNIException Thrown by handler to signal an error.
0693: */
0694: public void startElement(QName element, XMLAttributes attributes,
0695: Augmentations augs) throws XNIException {
0696:
0697: Augmentations modifiedAugs = handleStartElement(element,
0698: attributes, augs);
0699: // call handlers
0700: if (fDocumentHandler != null) {
0701: fDocumentHandler.startElement(element, attributes,
0702: modifiedAugs);
0703: }
0704:
0705: } // startElement(QName,XMLAttributes, Augmentations)
0706:
0707: /**
0708: * An empty element.
0709: *
0710: * @param element The name of the element.
0711: * @param attributes The element attributes.
0712: * @param augs Additional information that may include infoset augmentations
0713: *
0714: * @throws XNIException Thrown by handler to signal an error.
0715: */
0716: public void emptyElement(QName element, XMLAttributes attributes,
0717: Augmentations augs) throws XNIException {
0718:
0719: Augmentations modifiedAugs = handleStartElement(element,
0720: attributes, augs);
0721:
0722: // in the case where there is a {value constraint}, and the element
0723: // doesn't have any text content, change emptyElement call to
0724: // start + characters + end
0725: fDefaultValue = null;
0726: // fElementDepth == -2 indicates that the schema validator was removed
0727: // from the pipeline. then we don't need to call handleEndElement.
0728: if (fElementDepth != -2)
0729: modifiedAugs = handleEndElement(element, modifiedAugs);
0730:
0731: // call handlers
0732: if (fDocumentHandler != null) {
0733: if (!fSchemaElementDefault || fDefaultValue == null) {
0734: fDocumentHandler.emptyElement(element, attributes,
0735: modifiedAugs);
0736: } else {
0737: fDocumentHandler.startElement(element, attributes,
0738: modifiedAugs);
0739: fDocumentHandler.characters(fDefaultValue, null);
0740: fDocumentHandler.endElement(element, modifiedAugs);
0741: }
0742: }
0743: } // emptyElement(QName,XMLAttributes, Augmentations)
0744:
0745: /**
0746: * Character content.
0747: *
0748: * @param text The content.
0749: * @param augs Additional information that may include infoset augmentations
0750: *
0751: * @throws XNIException Thrown by handler to signal an error.
0752: */
0753: public void characters(XMLString text, Augmentations augs)
0754: throws XNIException {
0755:
0756: text = handleCharacters(text);
0757: // call handlers
0758: if (fDocumentHandler != null) {
0759: if (fNormalizeData && fUnionType) {
0760: // for union types we can't normalize data
0761: // thus we only need to send augs information if any;
0762: // the normalized data for union will be send
0763: // after normalization is performed (at the endElement())
0764: if (augs != null)
0765: fDocumentHandler.characters(fEmptyXMLStr, augs);
0766: } else {
0767: fDocumentHandler.characters(text, augs);
0768: }
0769: }
0770:
0771: } // characters(XMLString)
0772:
0773: /**
0774: * Ignorable whitespace. For this method to be called, the document
0775: * source must have some way of determining that the text containing
0776: * only whitespace characters should be considered ignorable. For
0777: * example, the validator can determine if a length of whitespace
0778: * characters in the document are ignorable based on the element
0779: * content model.
0780: *
0781: * @param text The ignorable whitespace.
0782: * @param augs Additional information that may include infoset augmentations
0783: *
0784: * @throws XNIException Thrown by handler to signal an error.
0785: */
0786: public void ignorableWhitespace(XMLString text, Augmentations augs)
0787: throws XNIException {
0788:
0789: handleIgnorableWhitespace(text);
0790: // call handlers
0791: if (fDocumentHandler != null) {
0792: fDocumentHandler.ignorableWhitespace(text, augs);
0793: }
0794:
0795: } // ignorableWhitespace(XMLString)
0796:
0797: /**
0798: * The end of an element.
0799: *
0800: * @param element The name of the element.
0801: * @param augs Additional information that may include infoset augmentations
0802: *
0803: * @throws XNIException Thrown by handler to signal an error.
0804: */
0805: public void endElement(QName element, Augmentations augs)
0806: throws XNIException {
0807:
0808: // in the case where there is a {value constraint}, and the element
0809: // doesn't have any text content, add a characters call.
0810: fDefaultValue = null;
0811: Augmentations modifiedAugs = handleEndElement(element, augs);
0812: // call handlers
0813: if (fDocumentHandler != null) {
0814: if (!fSchemaElementDefault || fDefaultValue == null) {
0815: fDocumentHandler.endElement(element, modifiedAugs);
0816: } else {
0817: fDocumentHandler.characters(fDefaultValue, null);
0818: fDocumentHandler.endElement(element, modifiedAugs);
0819: }
0820: }
0821: } // endElement(QName, Augmentations)
0822:
0823: /**
0824: * The start of a CDATA section.
0825: *
0826: * @param augs Additional information that may include infoset augmentations
0827: *
0828: * @throws XNIException Thrown by handler to signal an error.
0829: */
0830: public void startCDATA(Augmentations augs) throws XNIException {
0831:
0832: // REVISIT: what should we do here if schema normalization is on??
0833: fInCDATA = true;
0834: // call handlers
0835: if (fDocumentHandler != null) {
0836: fDocumentHandler.startCDATA(augs);
0837: }
0838:
0839: } // startCDATA()
0840:
0841: /**
0842: * The end of a CDATA section.
0843: *
0844: * @param augs Additional information that may include infoset augmentations
0845: *
0846: * @throws XNIException Thrown by handler to signal an error.
0847: */
0848: public void endCDATA(Augmentations augs) throws XNIException {
0849:
0850: // call handlers
0851: fInCDATA = false;
0852: if (fDocumentHandler != null) {
0853: fDocumentHandler.endCDATA(augs);
0854: }
0855:
0856: } // endCDATA()
0857:
0858: /**
0859: * The end of the document.
0860: *
0861: * @param augs Additional information that may include infoset augmentations
0862: *
0863: * @throws XNIException Thrown by handler to signal an error.
0864: */
0865: public void endDocument(Augmentations augs) throws XNIException {
0866:
0867: handleEndDocument();
0868:
0869: // call handlers
0870: if (fDocumentHandler != null) {
0871: fDocumentHandler.endDocument(augs);
0872: }
0873: fLocator = null;
0874:
0875: } // endDocument(Augmentations)
0876:
0877: //
0878: // DOMRevalidationHandler methods
0879: //
0880:
0881: public boolean characterData(String data, Augmentations augs) {
0882:
0883: fSawText = fSawText || data.length() > 0;
0884:
0885: // REVISIT: this methods basically duplicates implementation of
0886: // handleCharacters(). We should be able to reuse some code
0887:
0888: // if whitespace == -1 skip normalization, because it is a complexType
0889: // or a union type.
0890: if (fNormalizeData && fWhiteSpace != -1
0891: && fWhiteSpace != XSSimpleType.WS_PRESERVE) {
0892: // normalize data
0893: normalizeWhitespace(data,
0894: fWhiteSpace == XSSimpleType.WS_COLLAPSE);
0895: fBuffer.append(fNormalizedStr.ch, fNormalizedStr.offset,
0896: fNormalizedStr.length);
0897: } else {
0898: if (fAppendBuffer)
0899: fBuffer.append(data);
0900: }
0901:
0902: // When it's a complex type with element-only content, we need to
0903: // find out whether the content contains any non-whitespace character.
0904: boolean allWhiteSpace = true;
0905: if (fCurrentType != null
0906: && fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
0907: XSComplexTypeDecl ctype = (XSComplexTypeDecl) fCurrentType;
0908: if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_ELEMENT) {
0909: // data outside of element content
0910: for (int i = 0; i < data.length(); i++) {
0911: if (!XMLChar.isSpace(data.charAt(i))) {
0912: allWhiteSpace = false;
0913: fSawCharacters = true;
0914: break;
0915: }
0916: }
0917: }
0918: }
0919:
0920: return allWhiteSpace;
0921: }
0922:
0923: public void elementDefault(String data) {
0924: // no-op
0925: }
0926:
0927: //
0928: // XMLDocumentHandler and XMLDTDHandler methods
0929: //
0930:
0931: /**
0932: * This method notifies the start of a general entity.
0933: * <p>
0934: * <strong>Note:</strong> This method is not called for entity references
0935: * appearing as part of attribute values.
0936: *
0937: * @param name The name of the general entity.
0938: * @param identifier The resource identifier.
0939: * @param encoding The auto-detected IANA encoding name of the entity
0940: * stream. This value will be null in those situations
0941: * where the entity encoding is not auto-detected (e.g.
0942: * internal entities or a document entity that is
0943: * parsed from a java.io.Reader).
0944: * @param augs Additional information that may include infoset augmentations
0945: *
0946: * @exception XNIException Thrown by handler to signal an error.
0947: */
0948: public void startGeneralEntity(String name,
0949: XMLResourceIdentifier identifier, String encoding,
0950: Augmentations augs) throws XNIException {
0951:
0952: // REVISIT: what should happen if normalize_data_ is on??
0953: fEntityRef = true;
0954: // call handlers
0955: if (fDocumentHandler != null) {
0956: fDocumentHandler.startGeneralEntity(name, identifier,
0957: encoding, augs);
0958: }
0959:
0960: } // startEntity(String,String,String,String,String)
0961:
0962: /**
0963: * Notifies of the presence of a TextDecl line in an entity. If present,
0964: * this method will be called immediately following the startEntity call.
0965: * <p>
0966: * <strong>Note:</strong> This method will never be called for the
0967: * document entity; it is only called for external general entities
0968: * referenced in document content.
0969: * <p>
0970: * <strong>Note:</strong> This method is not called for entity references
0971: * appearing as part of attribute values.
0972: *
0973: * @param version The XML version, or null if not specified.
0974: * @param encoding The IANA encoding name of the entity.
0975: * @param augs Additional information that may include infoset augmentations
0976: *
0977: * @throws XNIException Thrown by handler to signal an error.
0978: */
0979: public void textDecl(String version, String encoding,
0980: Augmentations augs) throws XNIException {
0981:
0982: // call handlers
0983: if (fDocumentHandler != null) {
0984: fDocumentHandler.textDecl(version, encoding, augs);
0985: }
0986:
0987: } // textDecl(String,String)
0988:
0989: /**
0990: * A comment.
0991: *
0992: * @param text The text in the comment.
0993: * @param augs Additional information that may include infoset augmentations
0994: *
0995: * @throws XNIException Thrown by application to signal an error.
0996: */
0997: public void comment(XMLString text, Augmentations augs)
0998: throws XNIException {
0999:
1000: // call handlers
1001: if (fDocumentHandler != null) {
1002: fDocumentHandler.comment(text, augs);
1003: }
1004:
1005: } // comment(XMLString)
1006:
1007: /**
1008: * A processing instruction. Processing instructions consist of a
1009: * target name and, optionally, text data. The data is only meaningful
1010: * to the application.
1011: * <p>
1012: * Typically, a processing instruction's data will contain a series
1013: * of pseudo-attributes. These pseudo-attributes follow the form of
1014: * element attributes but are <strong>not</strong> parsed or presented
1015: * to the application as anything other than text. The application is
1016: * responsible for parsing the data.
1017: *
1018: * @param target The target.
1019: * @param data The data or null if none specified.
1020: * @param augs Additional information that may include infoset augmentations
1021: *
1022: * @throws XNIException Thrown by handler to signal an error.
1023: */
1024: public void processingInstruction(String target, XMLString data,
1025: Augmentations augs) throws XNIException {
1026:
1027: // call handlers
1028: if (fDocumentHandler != null) {
1029: fDocumentHandler.processingInstruction(target, data, augs);
1030: }
1031:
1032: } // processingInstruction(String,XMLString)
1033:
1034: /**
1035: * This method notifies the end of a general entity.
1036: * <p>
1037: * <strong>Note:</strong> This method is not called for entity references
1038: * appearing as part of attribute values.
1039: *
1040: * @param name The name of the entity.
1041: * @param augs Additional information that may include infoset augmentations
1042: *
1043: * @exception XNIException
1044: * Thrown by handler to signal an error.
1045: */
1046: public void endGeneralEntity(String name, Augmentations augs)
1047: throws XNIException {
1048:
1049: // call handlers
1050: fEntityRef = false;
1051: if (fDocumentHandler != null) {
1052: fDocumentHandler.endGeneralEntity(name, augs);
1053: }
1054:
1055: } // endEntity(String)
1056:
1057: // constants
1058:
1059: static final int INITIAL_STACK_SIZE = 8;
1060: static final int INC_STACK_SIZE = 8;
1061:
1062: //
1063: // Data
1064: //
1065:
1066: // Schema Normalization
1067:
1068: private static final boolean DEBUG_NORMALIZATION = false;
1069: // temporary empty string buffer.
1070: private final XMLString fEmptyXMLStr = new XMLString(null, 0, -1);
1071: // temporary character buffer, and empty string buffer.
1072: private static final int BUFFER_SIZE = 20;
1073: private final XMLString fNormalizedStr = new XMLString();
1074: private boolean fFirstChunk = true;
1075: // got first chunk in characters() (SAX)
1076: private boolean fTrailing = false; // Previous chunk had a trailing space
1077: private short fWhiteSpace = -1; //whiteSpace: preserve/replace/collapse
1078: private boolean fUnionType = false;
1079:
1080: /** Schema grammar resolver. */
1081: private final XSGrammarBucket fGrammarBucket = new XSGrammarBucket();
1082: private final SubstitutionGroupHandler fSubGroupHandler = new SubstitutionGroupHandler(
1083: fGrammarBucket);
1084:
1085: /** the DV usd to convert xsi:type to a QName */
1086: // REVISIT: in new simple type design, make things in DVs static,
1087: // so that we can QNameDV.getCompiledForm()
1088: private final XSSimpleType fQNameDV = (XSSimpleType) SchemaGrammar.SG_SchemaNS
1089: .getGlobalTypeDecl(SchemaSymbols.ATTVAL_QNAME);
1090:
1091: private final CMNodeFactory nodeFactory = new CMNodeFactory();
1092: /** used to build content models */
1093: // REVISIT: create decl pool, and pass it to each traversers
1094: private final CMBuilder fCMBuilder = new CMBuilder(nodeFactory);
1095:
1096: // Schema grammar loader
1097: private final XMLSchemaLoader fSchemaLoader = new XMLSchemaLoader(
1098: fXSIErrorReporter.fErrorReporter, fGrammarBucket,
1099: fSubGroupHandler, fCMBuilder);
1100:
1101: // state
1102:
1103: /** String representation of the validation root. */
1104: // REVISIT: what do we store here? QName, XPATH, some ID? use rawname now.
1105: private String fValidationRoot;
1106:
1107: /** Skip validation: anything below this level should be skipped */
1108: private int fSkipValidationDepth;
1109:
1110: /** anything above this level has validation_attempted != full */
1111: private int fNFullValidationDepth;
1112:
1113: /** anything above this level has validation_attempted != none */
1114: private int fNNoneValidationDepth;
1115:
1116: /** Element depth: -2: validator not in pipeline; >= -1 current depth. */
1117: private int fElementDepth;
1118:
1119: /** Seen sub elements. */
1120: private boolean fSubElement;
1121:
1122: /** Seen sub elements stack. */
1123: private boolean[] fSubElementStack = new boolean[INITIAL_STACK_SIZE];
1124:
1125: /** Current element declaration. */
1126: private XSElementDecl fCurrentElemDecl;
1127:
1128: /** Element decl stack. */
1129: private XSElementDecl[] fElemDeclStack = new XSElementDecl[INITIAL_STACK_SIZE];
1130:
1131: /** nil value of the current element */
1132: private boolean fNil;
1133:
1134: /** nil value stack */
1135: private boolean[] fNilStack = new boolean[INITIAL_STACK_SIZE];
1136:
1137: /** notation value of the current element */
1138: private XSNotationDecl fNotation;
1139:
1140: /** notation stack */
1141: private XSNotationDecl[] fNotationStack = new XSNotationDecl[INITIAL_STACK_SIZE];
1142:
1143: /** Current type. */
1144: private XSTypeDefinition fCurrentType;
1145:
1146: /** type stack. */
1147: private XSTypeDefinition[] fTypeStack = new XSTypeDefinition[INITIAL_STACK_SIZE];
1148:
1149: /** Current content model. */
1150: private XSCMValidator fCurrentCM;
1151:
1152: /** Content model stack. */
1153: private XSCMValidator[] fCMStack = new XSCMValidator[INITIAL_STACK_SIZE];
1154:
1155: /** the current state of the current content model */
1156: private int[] fCurrCMState;
1157:
1158: /** stack to hold content model states */
1159: private int[][] fCMStateStack = new int[INITIAL_STACK_SIZE][];
1160:
1161: /** whether the curret element is strictly assessed */
1162: private boolean fStrictAssess = true;
1163:
1164: /** strict assess stack */
1165: private boolean[] fStrictAssessStack = new boolean[INITIAL_STACK_SIZE];
1166:
1167: /** Temporary string buffers. */
1168: private final StringBuffer fBuffer = new StringBuffer();
1169:
1170: /** Whether need to append characters to fBuffer */
1171: private boolean fAppendBuffer = true;
1172:
1173: /** Did we see any character data? */
1174: private boolean fSawText = false;
1175:
1176: /** stack to record if we saw character data */
1177: private boolean[] fSawTextStack = new boolean[INITIAL_STACK_SIZE];
1178:
1179: /** Did we see non-whitespace character data? */
1180: private boolean fSawCharacters = false;
1181:
1182: /** Stack to record if we saw character data outside of element content*/
1183: private boolean[] fStringContent = new boolean[INITIAL_STACK_SIZE];
1184:
1185: /** temporary qname */
1186: private final QName fTempQName = new QName();
1187:
1188: private javax.xml.namespace.QName fRootTypeQName = null;
1189:
1190: private int fIgnoreXSITypeDepth;
1191:
1192: private boolean fIDCChecking;
1193:
1194: /** temporary validated info */
1195: private ValidatedInfo fValidatedInfo = new ValidatedInfo();
1196:
1197: // used to validate default/fixed values against xsi:type
1198: // only need to check facets, so we set extraChecking to false (in reset)
1199: private ValidationState fState4XsiType = new ValidationState();
1200:
1201: // used to apply default/fixed values
1202: // only need to check id/idref/entity, so we set checkFacets to false
1203: private ValidationState fState4ApplyDefault = new ValidationState();
1204:
1205: // identity constraint information
1206:
1207: /**
1208: * Stack of active XPath matchers for identity constraints. All
1209: * active XPath matchers are notified of startElement
1210: * and endElement callbacks in order to perform their matches.
1211: * <p>
1212: * For each element with identity constraints, the selector of
1213: * each identity constraint is activated. When the selector matches
1214: * its XPath, then all the fields of the identity constraint are
1215: * activated.
1216: * <p>
1217: * <strong>Note:</strong> Once the activation scope is left, the
1218: * XPath matchers are automatically removed from the stack of
1219: * active matchers and no longer receive callbacks.
1220: */
1221: protected XPathMatcherStack fMatcherStack = new XPathMatcherStack();
1222:
1223: /** Cache of value stores for identity constraint fields. */
1224: protected ValueStoreCache fValueStoreCache = new ValueStoreCache();
1225:
1226: //
1227: // Constructors
1228: //
1229:
1230: /** Default constructor. */
1231: public XMLSchemaValidator() {
1232: fState4XsiType.setExtraChecking(false);
1233: fState4ApplyDefault.setFacetChecking(false);
1234:
1235: } // <init>()
1236:
1237: /*
1238: * Resets the component. The component can query the component manager
1239: * about any features and properties that affect the operation of the
1240: * component.
1241: *
1242: * @param componentManager The component manager.
1243: *
1244: * @throws SAXException Thrown by component on finitialization error.
1245: * For example, if a feature or property is
1246: * required for the operation of the component, the
1247: * component manager may throw a
1248: * SAXNotRecognizedException or a
1249: * SAXNotSupportedException.
1250: */
1251: public void reset(XMLComponentManager componentManager)
1252: throws XMLConfigurationException {
1253:
1254: fIdConstraint = false;
1255: //reset XSDDescription
1256: fLocationPairs.clear();
1257:
1258: // cleanup id table
1259: fValidationState.resetIDTables();
1260:
1261: //pass the component manager to the factory..
1262: nodeFactory.reset(componentManager);
1263:
1264: // reset schema loader
1265: fSchemaLoader.reset(componentManager);
1266:
1267: // initialize state
1268: fCurrentElemDecl = null;
1269: fCurrentCM = null;
1270: fCurrCMState = null;
1271: fSkipValidationDepth = -1;
1272: fNFullValidationDepth = -1;
1273: fNNoneValidationDepth = -1;
1274: fElementDepth = -1;
1275: fSubElement = false;
1276: fSchemaDynamicValidation = false;
1277:
1278: // datatype normalization
1279: fEntityRef = false;
1280: fInCDATA = false;
1281:
1282: fMatcherStack.clear();
1283:
1284: // get error reporter
1285: fXSIErrorReporter.reset((XMLErrorReporter) componentManager
1286: .getProperty(ERROR_REPORTER));
1287:
1288: boolean parser_settings;
1289: try {
1290: parser_settings = componentManager
1291: .getFeature(PARSER_SETTINGS);
1292: } catch (XMLConfigurationException e) {
1293: parser_settings = true;
1294: }
1295:
1296: if (!parser_settings) {
1297: // parser settings have not been changed
1298: fValidationManager.addValidationState(fValidationState);
1299: // Re-parse external schema location properties.
1300: XMLSchemaLoader.processExternalHints(fExternalSchemas,
1301: fExternalNoNamespaceSchema, fLocationPairs,
1302: fXSIErrorReporter.fErrorReporter);
1303: return;
1304: }
1305:
1306: // get symbol table. if it's a new one, add symbols to it.
1307: SymbolTable symbolTable = (SymbolTable) componentManager
1308: .getProperty(SYMBOL_TABLE);
1309: if (symbolTable != fSymbolTable) {
1310: fSymbolTable = symbolTable;
1311: }
1312:
1313: try {
1314: fDynamicValidation = componentManager
1315: .getFeature(DYNAMIC_VALIDATION);
1316: } catch (XMLConfigurationException e) {
1317: fDynamicValidation = false;
1318: }
1319:
1320: if (fDynamicValidation) {
1321: fDoValidation = true;
1322: } else {
1323: try {
1324: fDoValidation = componentManager.getFeature(VALIDATION);
1325: } catch (XMLConfigurationException e) {
1326: fDoValidation = false;
1327: }
1328: }
1329:
1330: if (fDoValidation) {
1331: try {
1332: fDoValidation = componentManager
1333: .getFeature(XMLSchemaValidator.SCHEMA_VALIDATION);
1334: } catch (XMLConfigurationException e) {
1335: }
1336: }
1337:
1338: try {
1339: fFullChecking = componentManager
1340: .getFeature(SCHEMA_FULL_CHECKING);
1341: } catch (XMLConfigurationException e) {
1342: fFullChecking = false;
1343: }
1344:
1345: try {
1346: fNormalizeData = componentManager
1347: .getFeature(NORMALIZE_DATA);
1348: } catch (XMLConfigurationException e) {
1349: fNormalizeData = false;
1350: }
1351:
1352: try {
1353: fSchemaElementDefault = componentManager
1354: .getFeature(SCHEMA_ELEMENT_DEFAULT);
1355: } catch (XMLConfigurationException e) {
1356: fSchemaElementDefault = false;
1357: }
1358:
1359: try {
1360: fAugPSVI = componentManager.getFeature(SCHEMA_AUGMENT_PSVI);
1361: } catch (XMLConfigurationException e) {
1362: fAugPSVI = true;
1363: }
1364: try {
1365: fSchemaType = (String) componentManager
1366: .getProperty(Constants.JAXP_PROPERTY_PREFIX
1367: + Constants.SCHEMA_LANGUAGE);
1368: } catch (XMLConfigurationException e) {
1369: fSchemaType = null;
1370: }
1371:
1372: try {
1373: fUseGrammarPoolOnly = componentManager
1374: .getFeature(USE_GRAMMAR_POOL_ONLY);
1375: } catch (XMLConfigurationException e) {
1376: fUseGrammarPoolOnly = false;
1377: }
1378:
1379: fEntityResolver = (XMLEntityResolver) componentManager
1380: .getProperty(ENTITY_MANAGER);
1381:
1382: fValidationManager = (ValidationManager) componentManager
1383: .getProperty(VALIDATION_MANAGER);
1384: fValidationManager.addValidationState(fValidationState);
1385: fValidationState.setSymbolTable(fSymbolTable);
1386:
1387: try {
1388: fRootTypeQName = (javax.xml.namespace.QName) componentManager
1389: .getProperty(ROOT_TYPE_DEF);
1390: } catch (XMLConfigurationException e) {
1391: fRootTypeQName = null;
1392: }
1393:
1394: boolean ignoreXSIType;
1395: try {
1396: ignoreXSIType = componentManager
1397: .getFeature(IGNORE_XSI_TYPE);
1398: } catch (XMLConfigurationException e) {
1399: ignoreXSIType = false;
1400: }
1401: // An initial value of -1 means that the root element considers itself
1402: // below the depth where xsi:type stopped being ignored (which means that
1403: // xsi:type attributes will not be ignored for the entire document)
1404: fIgnoreXSITypeDepth = ignoreXSIType ? 0 : -1;
1405:
1406: try {
1407: fIDCChecking = componentManager
1408: .getFeature(IDENTITY_CONSTRAINT_CHECKING);
1409: } catch (XMLConfigurationException e) {
1410: fIDCChecking = true;
1411: }
1412:
1413: try {
1414: fValidationState.setIdIdrefChecking(componentManager
1415: .getFeature(ID_IDREF_CHECKING));
1416: } catch (XMLConfigurationException e) {
1417: fValidationState.setIdIdrefChecking(true);
1418: }
1419:
1420: try {
1421: fValidationState.setUnparsedEntityChecking(componentManager
1422: .getFeature(UNPARSED_ENTITY_CHECKING));
1423: } catch (XMLConfigurationException e) {
1424: fValidationState.setUnparsedEntityChecking(true);
1425: }
1426:
1427: // get schema location properties
1428: try {
1429: fExternalSchemas = (String) componentManager
1430: .getProperty(SCHEMA_LOCATION);
1431: fExternalNoNamespaceSchema = (String) componentManager
1432: .getProperty(SCHEMA_NONS_LOCATION);
1433: } catch (XMLConfigurationException e) {
1434: fExternalSchemas = null;
1435: fExternalNoNamespaceSchema = null;
1436: }
1437:
1438: // store the external schema locations. they are set when reset is called,
1439: // so any other schemaLocation declaration for the same namespace will be
1440: // effectively ignored. becuase we choose to take first location hint
1441: // available for a particular namespace.
1442: XMLSchemaLoader.processExternalHints(fExternalSchemas,
1443: fExternalNoNamespaceSchema, fLocationPairs,
1444: fXSIErrorReporter.fErrorReporter);
1445:
1446: try {
1447: fJaxpSchemaSource = componentManager
1448: .getProperty(JAXP_SCHEMA_SOURCE);
1449: } catch (XMLConfigurationException e) {
1450: fJaxpSchemaSource = null;
1451:
1452: }
1453:
1454: // clear grammars, and put the one for schema namespace there
1455: try {
1456: fGrammarPool = (XMLGrammarPool) componentManager
1457: .getProperty(XMLGRAMMAR_POOL);
1458: } catch (XMLConfigurationException e) {
1459: fGrammarPool = null;
1460: }
1461:
1462: fState4XsiType.setSymbolTable(symbolTable);
1463: fState4ApplyDefault.setSymbolTable(symbolTable);
1464:
1465: } // reset(XMLComponentManager)
1466:
1467: //
1468: // FieldActivator methods
1469: //
1470:
1471: /**
1472: * Start the value scope for the specified identity constraint. This
1473: * method is called when the selector matches in order to initialize
1474: * the value store.
1475: *
1476: * @param identityConstraint The identity constraint.
1477: */
1478: public void startValueScopeFor(
1479: IdentityConstraint identityConstraint, int initialDepth) {
1480:
1481: ValueStoreBase valueStore = fValueStoreCache.getValueStoreFor(
1482: identityConstraint, initialDepth);
1483: valueStore.startValueScope();
1484:
1485: } // startValueScopeFor(IdentityConstraint identityConstraint)
1486:
1487: /**
1488: * Request to activate the specified field. This method returns the
1489: * matcher for the field.
1490: *
1491: * @param field The field to activate.
1492: */
1493: public XPathMatcher activateField(Field field, int initialDepth) {
1494: ValueStore valueStore = fValueStoreCache.getValueStoreFor(field
1495: .getIdentityConstraint(), initialDepth);
1496: XPathMatcher matcher = field.createMatcher(valueStore);
1497: fMatcherStack.addMatcher(matcher);
1498: matcher.startDocumentFragment();
1499: return matcher;
1500: } // activateField(Field):XPathMatcher
1501:
1502: /**
1503: * Ends the value scope for the specified identity constraint.
1504: *
1505: * @param identityConstraint The identity constraint.
1506: */
1507: public void endValueScopeFor(IdentityConstraint identityConstraint,
1508: int initialDepth) {
1509:
1510: ValueStoreBase valueStore = fValueStoreCache.getValueStoreFor(
1511: identityConstraint, initialDepth);
1512: valueStore.endValueScope();
1513:
1514: } // endValueScopeFor(IdentityConstraint)
1515:
1516: // a utility method for Identity constraints
1517: private void activateSelectorFor(IdentityConstraint ic) {
1518: Selector selector = ic.getSelector();
1519: FieldActivator activator = this ;
1520: if (selector == null)
1521: return;
1522: XPathMatcher matcher = selector.createMatcher(activator,
1523: fElementDepth);
1524: fMatcherStack.addMatcher(matcher);
1525: matcher.startDocumentFragment();
1526: }
1527:
1528: //
1529: // Protected methods
1530: //
1531:
1532: /** ensure element stack capacity */
1533: void ensureStackCapacity() {
1534:
1535: if (fElementDepth == fElemDeclStack.length) {
1536: int newSize = fElementDepth + INC_STACK_SIZE;
1537: boolean[] newArrayB = new boolean[newSize];
1538: System.arraycopy(fSubElementStack, 0, newArrayB, 0,
1539: fElementDepth);
1540: fSubElementStack = newArrayB;
1541:
1542: XSElementDecl[] newArrayE = new XSElementDecl[newSize];
1543: System.arraycopy(fElemDeclStack, 0, newArrayE, 0,
1544: fElementDepth);
1545: fElemDeclStack = newArrayE;
1546:
1547: newArrayB = new boolean[newSize];
1548: System.arraycopy(fNilStack, 0, newArrayB, 0, fElementDepth);
1549: fNilStack = newArrayB;
1550:
1551: XSNotationDecl[] newArrayN = new XSNotationDecl[newSize];
1552: System.arraycopy(fNotationStack, 0, newArrayN, 0,
1553: fElementDepth);
1554: fNotationStack = newArrayN;
1555:
1556: XSTypeDefinition[] newArrayT = new XSTypeDefinition[newSize];
1557: System
1558: .arraycopy(fTypeStack, 0, newArrayT, 0,
1559: fElementDepth);
1560: fTypeStack = newArrayT;
1561:
1562: XSCMValidator[] newArrayC = new XSCMValidator[newSize];
1563: System.arraycopy(fCMStack, 0, newArrayC, 0, fElementDepth);
1564: fCMStack = newArrayC;
1565:
1566: newArrayB = new boolean[newSize];
1567: System.arraycopy(fSawTextStack, 0, newArrayB, 0,
1568: fElementDepth);
1569: fSawTextStack = newArrayB;
1570:
1571: newArrayB = new boolean[newSize];
1572: System.arraycopy(fStringContent, 0, newArrayB, 0,
1573: fElementDepth);
1574: fStringContent = newArrayB;
1575:
1576: newArrayB = new boolean[newSize];
1577: System.arraycopy(fStrictAssessStack, 0, newArrayB, 0,
1578: fElementDepth);
1579: fStrictAssessStack = newArrayB;
1580:
1581: int[][] newArrayIA = new int[newSize][];
1582: System.arraycopy(fCMStateStack, 0, newArrayIA, 0,
1583: fElementDepth);
1584: fCMStateStack = newArrayIA;
1585: }
1586:
1587: } // ensureStackCapacity
1588:
1589: // handle start document
1590: void handleStartDocument(XMLLocator locator, String encoding) {
1591: if (fIDCChecking) {
1592: fValueStoreCache.startDocument();
1593: }
1594: if (fAugPSVI) {
1595: fCurrentPSVI.fGrammars = null;
1596: fCurrentPSVI.fSchemaInformation = null;
1597: }
1598: } // handleStartDocument(XMLLocator,String)
1599:
1600: void handleEndDocument() {
1601: if (fIDCChecking) {
1602: fValueStoreCache.endDocument();
1603: }
1604: } // handleEndDocument()
1605:
1606: // handle character contents
1607: // returns the normalized string if possible, otherwise the original string
1608: XMLString handleCharacters(XMLString text) {
1609:
1610: if (fSkipValidationDepth >= 0)
1611: return text;
1612:
1613: fSawText = fSawText || text.length > 0;
1614:
1615: // Note: data in EntityRef and CDATA is normalized as well
1616: // if whitespace == -1 skip normalization, because it is a complexType
1617: // or a union type.
1618: if (fNormalizeData && fWhiteSpace != -1
1619: && fWhiteSpace != XSSimpleType.WS_PRESERVE) {
1620: // normalize data
1621: normalizeWhitespace(text,
1622: fWhiteSpace == XSSimpleType.WS_COLLAPSE);
1623: text = fNormalizedStr;
1624: }
1625: if (fAppendBuffer)
1626: fBuffer.append(text.ch, text.offset, text.length);
1627:
1628: // When it's a complex type with element-only content, we need to
1629: // find out whether the content contains any non-whitespace character.
1630: if (fCurrentType != null
1631: && fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
1632: XSComplexTypeDecl ctype = (XSComplexTypeDecl) fCurrentType;
1633: if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_ELEMENT) {
1634: // data outside of element content
1635: for (int i = text.offset; i < text.offset + text.length; i++) {
1636: if (!XMLChar.isSpace(text.ch[i])) {
1637: fSawCharacters = true;
1638: break;
1639: }
1640: }
1641: }
1642: }
1643:
1644: return text;
1645: } // handleCharacters(XMLString)
1646:
1647: /**
1648: * Normalize whitespace in an XMLString according to the rules defined
1649: * in XML Schema specifications.
1650: * @param value The string to normalize.
1651: * @param collapse replace or collapse
1652: */
1653: private void normalizeWhitespace(XMLString value, boolean collapse) {
1654: boolean skipSpace = collapse;
1655: boolean sawNonWS = false;
1656: boolean leading = false;
1657: boolean trailing = false;
1658: char c;
1659: int size = value.offset + value.length;
1660:
1661: // ensure the ch array is big enough
1662: if (fNormalizedStr.ch == null
1663: || fNormalizedStr.ch.length < value.length + 1) {
1664: fNormalizedStr.ch = new char[value.length + 1];
1665: }
1666: // don't include the leading ' ' for now. might include it later.
1667: fNormalizedStr.offset = 1;
1668: fNormalizedStr.length = 1;
1669:
1670: for (int i = value.offset; i < size; i++) {
1671: c = value.ch[i];
1672: if (XMLChar.isSpace(c)) {
1673: if (!skipSpace) {
1674: // take the first whitespace as a space and skip the others
1675: fNormalizedStr.ch[fNormalizedStr.length++] = ' ';
1676: skipSpace = collapse;
1677: }
1678: if (!sawNonWS) {
1679: // this is a leading whitespace, record it
1680: leading = true;
1681: }
1682: } else {
1683: fNormalizedStr.ch[fNormalizedStr.length++] = c;
1684: skipSpace = false;
1685: sawNonWS = true;
1686: }
1687: }
1688: if (skipSpace) {
1689: if (fNormalizedStr.length > 1) {
1690: // if we finished on a space trim it but also record it
1691: fNormalizedStr.length--;
1692: trailing = true;
1693: } else if (leading && !fFirstChunk) {
1694: // if all we had was whitespace we skipped record it as
1695: // trailing whitespace as well
1696: trailing = true;
1697: }
1698: }
1699:
1700: if (fNormalizedStr.length > 1) {
1701: if (!fFirstChunk
1702: && (fWhiteSpace == XSSimpleType.WS_COLLAPSE)) {
1703: if (fTrailing) {
1704: // previous chunk ended on whitespace
1705: // insert whitespace
1706: fNormalizedStr.offset = 0;
1707: fNormalizedStr.ch[0] = ' ';
1708: } else if (leading) {
1709: // previous chunk ended on character,
1710: // this chunk starts with whitespace
1711: fNormalizedStr.offset = 0;
1712: fNormalizedStr.ch[0] = ' ';
1713: }
1714: }
1715: }
1716:
1717: // The length includes the leading ' '. Now removing it.
1718: fNormalizedStr.length -= fNormalizedStr.offset;
1719:
1720: fTrailing = trailing;
1721:
1722: if (trailing || sawNonWS)
1723: fFirstChunk = false;
1724: }
1725:
1726: private void normalizeWhitespace(String value, boolean collapse) {
1727: boolean skipSpace = collapse;
1728: char c;
1729: int size = value.length();
1730:
1731: // ensure the ch array is big enough
1732: if (fNormalizedStr.ch == null
1733: || fNormalizedStr.ch.length < size) {
1734: fNormalizedStr.ch = new char[size];
1735: }
1736: fNormalizedStr.offset = 0;
1737: fNormalizedStr.length = 0;
1738:
1739: for (int i = 0; i < size; i++) {
1740: c = value.charAt(i);
1741: if (XMLChar.isSpace(c)) {
1742: if (!skipSpace) {
1743: // take the first whitespace as a space and skip the others
1744: fNormalizedStr.ch[fNormalizedStr.length++] = ' ';
1745: skipSpace = collapse;
1746: }
1747: } else {
1748: fNormalizedStr.ch[fNormalizedStr.length++] = c;
1749: skipSpace = false;
1750: }
1751: }
1752: if (skipSpace) {
1753: if (fNormalizedStr.length != 0)
1754: // if we finished on a space trim it but also record it
1755: fNormalizedStr.length--;
1756: }
1757: }
1758:
1759: // handle ignorable whitespace
1760: void handleIgnorableWhitespace(XMLString text) {
1761:
1762: if (fSkipValidationDepth >= 0)
1763: return;
1764:
1765: // REVISIT: the same process needs to be performed as handleCharacters.
1766: // only it's simpler here: we know all characters are whitespaces.
1767:
1768: } // handleIgnorableWhitespace(XMLString)
1769:
1770: /** Handle element. */
1771: Augmentations handleStartElement(QName element,
1772: XMLAttributes attributes, Augmentations augs) {
1773:
1774: if (DEBUG) {
1775: System.out.println("==>handleStartElement: " + element);
1776: }
1777:
1778: // root element
1779: if (fElementDepth == -1 && fValidationManager.isGrammarFound()) {
1780: if (fSchemaType == null) {
1781: // schemaType is not specified
1782: // if a DTD grammar is found, we do the same thing as Dynamic:
1783: // if a schema grammar is found, validation is performed;
1784: // otherwise, skip the whole document.
1785: fSchemaDynamicValidation = true;
1786: } else {
1787: // [1] Either schemaType is DTD, and in this case validate/schema is turned off
1788: // [2] Validating against XML Schemas only
1789: // [a] dynamic validation is false: report error if SchemaGrammar is not found
1790: // [b] dynamic validation is true: if grammar is not found ignore.
1791: }
1792:
1793: }
1794:
1795: // get xsi:schemaLocation and xsi:noNamespaceSchemaLocation attributes,
1796: // parse them to get the grammars
1797:
1798: String sLocation = attributes.getValue(SchemaSymbols.URI_XSI,
1799: SchemaSymbols.XSI_SCHEMALOCATION);
1800: String nsLocation = attributes.getValue(SchemaSymbols.URI_XSI,
1801: SchemaSymbols.XSI_NONAMESPACESCHEMALOCATION);
1802: //store the location hints.. we need to do it so that we can defer the loading of grammar until
1803: //there is a reference to a component from that namespace. To provide location hints to the
1804: //application for a namespace
1805: storeLocations(sLocation, nsLocation);
1806:
1807: // if we are in the content of "skip", then just skip this element
1808: // REVISIT: is this the correct behaviour for ID constraints? -NG
1809: if (fSkipValidationDepth >= 0) {
1810: fElementDepth++;
1811: if (fAugPSVI)
1812: augs = getEmptyAugs(augs);
1813: return augs;
1814: }
1815:
1816: //try to find schema grammar by different means..
1817: SchemaGrammar sGrammar = findSchemaGrammar(
1818: XSDDescription.CONTEXT_ELEMENT, element.uri, null,
1819: element, attributes);
1820:
1821: // if we are not skipping this element, and there is a content model,
1822: // we try to find the corresponding decl object for this element.
1823: // the reason we move this part of code here is to make sure the
1824: // error reported here (if any) is stored within the parent element's
1825: // context, instead of that of the current element.
1826: Object decl = null;
1827: if (fCurrentCM != null) {
1828: decl = fCurrentCM.oneTransition(element, fCurrCMState,
1829: fSubGroupHandler);
1830: // it could be an element decl or a wildcard decl
1831: if (fCurrCMState[0] == XSCMValidator.FIRST_ERROR) {
1832: XSComplexTypeDecl ctype = (XSComplexTypeDecl) fCurrentType;
1833: //REVISIT: is it the only case we will have particle = null?
1834: Vector next;
1835: if (ctype.fParticle != null
1836: && (next = fCurrentCM
1837: .whatCanGoHere(fCurrCMState)).size() > 0) {
1838: String expected = expectedStr(next);
1839: reportSchemaError("cvc-complex-type.2.4.a",
1840: new Object[] { element.rawname, expected });
1841: } else {
1842: reportSchemaError("cvc-complex-type.2.4.d",
1843: new Object[] { element.rawname });
1844: }
1845: }
1846: }
1847:
1848: // if it's not the root element, we push the current states in the stacks
1849: if (fElementDepth != -1) {
1850: ensureStackCapacity();
1851: fSubElementStack[fElementDepth] = true;
1852: fSubElement = false;
1853: fElemDeclStack[fElementDepth] = fCurrentElemDecl;
1854: fNilStack[fElementDepth] = fNil;
1855: fNotationStack[fElementDepth] = fNotation;
1856: fTypeStack[fElementDepth] = fCurrentType;
1857: fStrictAssessStack[fElementDepth] = fStrictAssess;
1858: fCMStack[fElementDepth] = fCurrentCM;
1859: fCMStateStack[fElementDepth] = fCurrCMState;
1860: fSawTextStack[fElementDepth] = fSawText;
1861: fStringContent[fElementDepth] = fSawCharacters;
1862: }
1863:
1864: // increase the element depth after we've saved
1865: // all states for the parent element
1866: fElementDepth++;
1867: fCurrentElemDecl = null;
1868: XSWildcardDecl wildcard = null;
1869: fCurrentType = null;
1870: fStrictAssess = true;
1871: fNil = false;
1872: fNotation = null;
1873:
1874: // and the buffer to hold the value of the element
1875: fBuffer.setLength(0);
1876: fSawText = false;
1877: fSawCharacters = false;
1878:
1879: // check what kind of declaration the "decl" from
1880: // oneTransition() maps to
1881: if (decl != null) {
1882: if (decl instanceof XSElementDecl) {
1883: fCurrentElemDecl = (XSElementDecl) decl;
1884: } else {
1885: wildcard = (XSWildcardDecl) decl;
1886: }
1887: }
1888:
1889: // if the wildcard is skip, then return
1890: if (wildcard != null
1891: && wildcard.fProcessContents == XSWildcardDecl.PC_SKIP) {
1892: fSkipValidationDepth = fElementDepth;
1893: if (fAugPSVI)
1894: augs = getEmptyAugs(augs);
1895: return augs;
1896: }
1897:
1898: // 1.2.1.1 A type definition was stipulated by the processor
1899: if (fElementDepth == 0 && fRootTypeQName != null) {
1900: String rootTypeNamespace = fRootTypeQName.getNamespaceURI();
1901: if (rootTypeNamespace != null
1902: && rootTypeNamespace
1903: .equals(XMLConstants.NULL_NS_URI)) {
1904: rootTypeNamespace = null;
1905: }
1906: if (SchemaSymbols.URI_SCHEMAFORSCHEMA
1907: .equals(rootTypeNamespace)) {
1908: fCurrentType = SchemaGrammar.SG_SchemaNS
1909: .getGlobalTypeDecl(fRootTypeQName
1910: .getLocalPart());
1911: } else {
1912: SchemaGrammar grammarForRootType = findSchemaGrammar(
1913: XSDDescription.CONTEXT_ELEMENT,
1914: rootTypeNamespace, null, null, null);
1915: if (grammarForRootType != null) {
1916: fCurrentType = grammarForRootType
1917: .getGlobalTypeDecl(fRootTypeQName
1918: .getLocalPart());
1919: }
1920: }
1921: if (fCurrentType == null) {
1922: String typeName = (fRootTypeQName.getPrefix()
1923: .equals(XMLConstants.DEFAULT_NS_PREFIX)) ? fRootTypeQName
1924: .getLocalPart()
1925: : fRootTypeQName.getPrefix() + ":"
1926: + fRootTypeQName.getLocalPart();
1927: reportSchemaError("cvc-type.1",
1928: new Object[] { typeName });
1929: }
1930: }
1931:
1932: // if there was no processor stipulated type
1933: if (fCurrentType == null) {
1934: // try again to get the element decl:
1935: // case 1: find declaration for root element
1936: // case 2: find declaration for element from another namespace
1937: if (fCurrentElemDecl == null) {
1938: if (sGrammar != null) {
1939: fCurrentElemDecl = sGrammar
1940: .getGlobalElementDecl(element.localpart);
1941: }
1942: }
1943:
1944: if (fCurrentElemDecl != null) {
1945: // then get the type
1946: fCurrentType = fCurrentElemDecl.fType;
1947: }
1948: }
1949:
1950: // check if we should be ignoring xsi:type on this element
1951: if (fElementDepth == fIgnoreXSITypeDepth
1952: && fCurrentElemDecl == null) {
1953: fIgnoreXSITypeDepth++;
1954: }
1955:
1956: // process xsi:type attribute information
1957: String xsiType = null;
1958: if (fElementDepth >= fIgnoreXSITypeDepth) {
1959: xsiType = attributes.getValue(SchemaSymbols.URI_XSI,
1960: SchemaSymbols.XSI_TYPE);
1961: }
1962:
1963: // if no decl/type found for the current element
1964: if (fCurrentType == null && xsiType == null) {
1965: // if this is the validation root, report an error, because
1966: // we can't find eith decl or type for this element
1967: // REVISIT: should we report error, or warning?
1968: if (fElementDepth == 0) {
1969: // for dynamic validation, skip the whole content,
1970: // because no grammar was found.
1971: if (fDynamicValidation || fSchemaDynamicValidation) {
1972: // no schema grammar was found, but it's either dynamic
1973: // validation, or another kind of grammar was found (DTD,
1974: // for example). The intended behavior here is to skip
1975: // the whole document. To improve performance, we try to
1976: // remove the validator from the pipeline, since it's not
1977: // supposed to do anything.
1978: if (fDocumentSource != null) {
1979: fDocumentSource
1980: .setDocumentHandler(fDocumentHandler);
1981: if (fDocumentHandler != null)
1982: fDocumentHandler
1983: .setDocumentSource(fDocumentSource);
1984: // indicate that the validator was removed.
1985: fElementDepth = -2;
1986: return augs;
1987: }
1988:
1989: fSkipValidationDepth = fElementDepth;
1990: if (fAugPSVI)
1991: augs = getEmptyAugs(augs);
1992: return augs;
1993: }
1994: // We don't call reportSchemaError here, because the spec
1995: // doesn't think it's invalid not to be able to find a
1996: // declaration or type definition for an element. Xerces is
1997: // reporting it as an error for historical reasons, but in
1998: // PSVI, we shouldn't mark this element as invalid because
1999: // of this. - SG
2000: fXSIErrorReporter.fErrorReporter.reportError(
2001: XSMessageFormatter.SCHEMA_DOMAIN, "cvc-elt.1",
2002: new Object[] { element.rawname },
2003: XMLErrorReporter.SEVERITY_ERROR);
2004: }
2005: // if wildcard = strict, report error.
2006: // needs to be called before fXSIErrorReporter.pushContext()
2007: // so that the error belongs to the parent element.
2008: else if (wildcard != null
2009: && wildcard.fProcessContents == XSWildcardDecl.PC_STRICT) {
2010: // report error, because wilcard = strict
2011: reportSchemaError("cvc-complex-type.2.4.c",
2012: new Object[] { element.rawname });
2013: }
2014: // no element decl or type found for this element.
2015: // Allowed by the spec, we can choose to either laxly assess this
2016: // element, or to skip it. Now we choose lax assessment.
2017: fCurrentType = SchemaGrammar.fAnyType;
2018: fStrictAssess = false;
2019: fNFullValidationDepth = fElementDepth;
2020: // any type has mixed content, so we don't need to append buffer
2021: fAppendBuffer = false;
2022:
2023: // push error reporter context: record the current position
2024: // This has to happen after we process skip contents,
2025: // otherwise push and pop won't be correctly paired.
2026: fXSIErrorReporter.pushContext();
2027: } else {
2028: // push error reporter context: record the current position
2029: // This has to happen after we process skip contents,
2030: // otherwise push and pop won't be correctly paired.
2031: fXSIErrorReporter.pushContext();
2032:
2033: // get xsi:type
2034: if (xsiType != null) {
2035: XSTypeDefinition oldType = fCurrentType;
2036: fCurrentType = getAndCheckXsiType(element, xsiType,
2037: attributes);
2038: // If it fails, use the old type. Use anyType if ther is no old type.
2039: if (fCurrentType == null) {
2040: if (oldType == null)
2041: fCurrentType = SchemaGrammar.fAnyType;
2042: else
2043: fCurrentType = oldType;
2044: }
2045: }
2046:
2047: fNNoneValidationDepth = fElementDepth;
2048: // if the element has a fixed value constraint, we need to append
2049: if (fCurrentElemDecl != null
2050: && fCurrentElemDecl.getConstraintType() == XSConstants.VC_FIXED) {
2051: fAppendBuffer = true;
2052: }
2053: // if the type is simple, we need to append
2054: else if (fCurrentType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
2055: fAppendBuffer = true;
2056: } else {
2057: // if the type is simple content complex type, we need to append
2058: XSComplexTypeDecl ctype = (XSComplexTypeDecl) fCurrentType;
2059: fAppendBuffer = (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_SIMPLE);
2060: }
2061: }
2062:
2063: // Element Locally Valid (Element)
2064: // 2 Its {abstract} must be false.
2065: if (fCurrentElemDecl != null && fCurrentElemDecl.getAbstract())
2066: reportSchemaError("cvc-elt.2",
2067: new Object[] { element.rawname });
2068:
2069: // make the current element validation root
2070: if (fElementDepth == 0) {
2071: fValidationRoot = element.rawname;
2072: }
2073:
2074: // update normalization flags
2075: if (fNormalizeData) {
2076: // reset values
2077: fFirstChunk = true;
2078: fTrailing = false;
2079: fUnionType = false;
2080: fWhiteSpace = -1;
2081: }
2082:
2083: // Element Locally Valid (Type)
2084: // 2 Its {abstract} must be false.
2085: if (fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
2086: XSComplexTypeDecl ctype = (XSComplexTypeDecl) fCurrentType;
2087: if (ctype.getAbstract()) {
2088: reportSchemaError("cvc-type.2",
2089: new Object[] { element.rawname });
2090: }
2091: if (fNormalizeData) {
2092: // find out if the content type is simple and if variety is union
2093: // to be able to do character normalization
2094: if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_SIMPLE) {
2095: if (ctype.fXSSimpleType.getVariety() == XSSimpleType.VARIETY_UNION) {
2096: fUnionType = true;
2097: } else {
2098: try {
2099: fWhiteSpace = ctype.fXSSimpleType
2100: .getWhitespace();
2101: } catch (DatatypeException e) {
2102: // do nothing
2103: }
2104: }
2105: }
2106: }
2107: }
2108: // normalization: simple type
2109: else if (fNormalizeData) {
2110: // if !union type
2111: XSSimpleType dv = (XSSimpleType) fCurrentType;
2112: if (dv.getVariety() == XSSimpleType.VARIETY_UNION) {
2113: fUnionType = true;
2114: } else {
2115: try {
2116: fWhiteSpace = dv.getWhitespace();
2117: } catch (DatatypeException e) {
2118: // do nothing
2119: }
2120: }
2121: }
2122:
2123: // then try to get the content model
2124: fCurrentCM = null;
2125: if (fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
2126: fCurrentCM = ((XSComplexTypeDecl) fCurrentType)
2127: .getContentModel(fCMBuilder);
2128: }
2129:
2130: // and get the initial content model state
2131: fCurrCMState = null;
2132: if (fCurrentCM != null)
2133: fCurrCMState = fCurrentCM.startContentModel();
2134:
2135: // get information about xsi:nil
2136: String xsiNil = attributes.getValue(SchemaSymbols.URI_XSI,
2137: SchemaSymbols.XSI_NIL);
2138: // only deal with xsi:nil when there is an element declaration
2139: if (xsiNil != null && fCurrentElemDecl != null)
2140: fNil = getXsiNil(element, xsiNil);
2141:
2142: // now validate everything related with the attributes
2143: // first, get the attribute group
2144: XSAttributeGroupDecl attrGrp = null;
2145: if (fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
2146: XSComplexTypeDecl ctype = (XSComplexTypeDecl) fCurrentType;
2147: attrGrp = ctype.getAttrGrp();
2148: }
2149:
2150: if (fIDCChecking) {
2151: // activate identity constraints
2152: fValueStoreCache.startElement();
2153: fMatcherStack.pushContext();
2154: //if (fCurrentElemDecl != null && fCurrentElemDecl.fIDCPos > 0 && !fIgnoreIDC) {
2155: if (fCurrentElemDecl != null
2156: && fCurrentElemDecl.fIDCPos > 0) {
2157: fIdConstraint = true;
2158: // initialize when identity constrains are defined for the elem
2159: fValueStoreCache.initValueStoresFor(fCurrentElemDecl,
2160: this );
2161: }
2162: }
2163: processAttributes(element, attributes, attrGrp);
2164:
2165: // add default attributes
2166: if (attrGrp != null) {
2167: addDefaultAttributes(element, attributes, attrGrp);
2168: }
2169:
2170: // call all active identity constraints
2171: int count = fMatcherStack.getMatcherCount();
2172: for (int i = 0; i < count; i++) {
2173: XPathMatcher matcher = fMatcherStack.getMatcherAt(i);
2174: matcher.startElement(element, attributes);
2175: }
2176:
2177: if (fAugPSVI) {
2178: augs = getEmptyAugs(augs);
2179:
2180: // PSVI: add validation context
2181: fCurrentPSVI.fValidationContext = fValidationRoot;
2182: // PSVI: add element declaration
2183: fCurrentPSVI.fDeclaration = fCurrentElemDecl;
2184: // PSVI: add element type
2185: fCurrentPSVI.fTypeDecl = fCurrentType;
2186: // PSVI: add notation attribute
2187: fCurrentPSVI.fNotation = fNotation;
2188: // PSVI: add nil
2189: fCurrentPSVI.fNil = fNil;
2190: }
2191:
2192: return augs;
2193:
2194: } // handleStartElement(QName,XMLAttributes,boolean)
2195:
2196: /**
2197: * Handle end element. If there is not text content, and there is a
2198: * {value constraint} on the corresponding element decl, then
2199: * set the fDefaultValue XMLString representing the default value.
2200: */
2201: Augmentations handleEndElement(QName element, Augmentations augs) {
2202:
2203: if (DEBUG) {
2204: System.out.println("==>handleEndElement:" + element);
2205: }
2206: // if we are skipping, return
2207: if (fSkipValidationDepth >= 0) {
2208: // but if this is the top element that we are skipping,
2209: // restore the states.
2210: if (fSkipValidationDepth == fElementDepth
2211: && fSkipValidationDepth > 0) {
2212: // set the partial validation depth to the depth of parent
2213: fNFullValidationDepth = fSkipValidationDepth - 1;
2214: fSkipValidationDepth = -1;
2215: fElementDepth--;
2216: fSubElement = fSubElementStack[fElementDepth];
2217: fCurrentElemDecl = fElemDeclStack[fElementDepth];
2218: fNil = fNilStack[fElementDepth];
2219: fNotation = fNotationStack[fElementDepth];
2220: fCurrentType = fTypeStack[fElementDepth];
2221: fCurrentCM = fCMStack[fElementDepth];
2222: fStrictAssess = fStrictAssessStack[fElementDepth];
2223: fCurrCMState = fCMStateStack[fElementDepth];
2224: fSawText = fSawTextStack[fElementDepth];
2225: fSawCharacters = fStringContent[fElementDepth];
2226: } else {
2227: fElementDepth--;
2228: }
2229:
2230: // PSVI: validation attempted:
2231: // use default values in psvi item for
2232: // validation attempted, validity, and error codes
2233:
2234: // check extra schema constraints on root element
2235: if (fElementDepth == -1 && fFullChecking
2236: && !fUseGrammarPoolOnly) {
2237: XSConstraints.fullSchemaChecking(fGrammarBucket,
2238: fSubGroupHandler, fCMBuilder,
2239: fXSIErrorReporter.fErrorReporter);
2240: }
2241:
2242: if (fAugPSVI)
2243: augs = getEmptyAugs(augs);
2244: return augs;
2245: }
2246:
2247: // now validate the content of the element
2248: processElementContent(element);
2249:
2250: if (fIDCChecking) {
2251: // Element Locally Valid (Element)
2252: // 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).
2253:
2254: // call matchers and de-activate context
2255: int oldCount = fMatcherStack.getMatcherCount();
2256: for (int i = oldCount - 1; i >= 0; i--) {
2257: XPathMatcher matcher = fMatcherStack.getMatcherAt(i);
2258: if (fCurrentElemDecl == null) {
2259: matcher.endElement(element, fCurrentType, false,
2260: fValidatedInfo.actualValue,
2261: fValidatedInfo.actualValueType,
2262: fValidatedInfo.itemValueTypes);
2263: } else {
2264: matcher
2265: .endElement(
2266: element,
2267: fCurrentType,
2268: fCurrentElemDecl.getNillable(),
2269: fDefaultValue == null ? fValidatedInfo.actualValue
2270: : fCurrentElemDecl.fDefault.actualValue,
2271: fDefaultValue == null ? fValidatedInfo.actualValueType
2272: : fCurrentElemDecl.fDefault.actualValueType,
2273: fDefaultValue == null ? fValidatedInfo.itemValueTypes
2274: : fCurrentElemDecl.fDefault.itemValueTypes);
2275: }
2276: }
2277:
2278: if (fMatcherStack.size() > 0) {
2279: fMatcherStack.popContext();
2280: }
2281:
2282: int newCount = fMatcherStack.getMatcherCount();
2283: // handle everything *but* keyref's.
2284: for (int i = oldCount - 1; i >= newCount; i--) {
2285: XPathMatcher matcher = fMatcherStack.getMatcherAt(i);
2286: if (matcher instanceof Selector.Matcher) {
2287: Selector.Matcher selMatcher = (Selector.Matcher) matcher;
2288: IdentityConstraint id;
2289: if ((id = selMatcher.getIdentityConstraint()) != null
2290: && id.getCategory() != IdentityConstraint.IC_KEYREF) {
2291: fValueStoreCache.transplant(id, selMatcher
2292: .getInitialDepth());
2293: }
2294: }
2295: }
2296:
2297: // now handle keyref's/...
2298: for (int i = oldCount - 1; i >= newCount; i--) {
2299: XPathMatcher matcher = fMatcherStack.getMatcherAt(i);
2300: if (matcher instanceof Selector.Matcher) {
2301: Selector.Matcher selMatcher = (Selector.Matcher) matcher;
2302: IdentityConstraint id;
2303: if ((id = selMatcher.getIdentityConstraint()) != null
2304: && id.getCategory() == IdentityConstraint.IC_KEYREF) {
2305: ValueStoreBase values = fValueStoreCache
2306: .getValueStoreFor(id, selMatcher
2307: .getInitialDepth());
2308: if (values != null) // nothing to do if nothing matched!
2309: values.endDocumentFragment();
2310: }
2311: }
2312: }
2313: fValueStoreCache.endElement();
2314: }
2315:
2316: // Check if we should modify the xsi:type ignore depth
2317: // This check is independent of whether this is the validation root,
2318: // and should be done before the element depth is decremented.
2319: if (fElementDepth < fIgnoreXSITypeDepth) {
2320: fIgnoreXSITypeDepth--;
2321: }
2322:
2323: SchemaGrammar[] grammars = null;
2324: // have we reached the end tag of the validation root?
2325: if (fElementDepth == 0) {
2326: // 7 If the element information item is the validation root, it must be valid per Validation Root Valid (ID/IDREF) (3.3.4).
2327: String invIdRef = fValidationState.checkIDRefID();
2328: fValidationState.resetIDTables();
2329: if (invIdRef != null) {
2330: reportSchemaError("cvc-id.1", new Object[] { invIdRef });
2331: }
2332: // check extra schema constraints
2333: if (fFullChecking && !fUseGrammarPoolOnly) {
2334: XSConstraints.fullSchemaChecking(fGrammarBucket,
2335: fSubGroupHandler, fCMBuilder,
2336: fXSIErrorReporter.fErrorReporter);
2337: }
2338:
2339: grammars = fGrammarBucket.getGrammars();
2340: // return the final set of grammars validator ended up with
2341: if (fGrammarPool != null) {
2342: fGrammarPool.cacheGrammars(
2343: XMLGrammarDescription.XML_SCHEMA, grammars);
2344: }
2345: augs = endElementPSVI(true, grammars, augs);
2346: } else {
2347: augs = endElementPSVI(false, grammars, augs);
2348:
2349: // decrease element depth and restore states
2350: fElementDepth--;
2351:
2352: // get the states for the parent element.
2353: fSubElement = fSubElementStack[fElementDepth];
2354: fCurrentElemDecl = fElemDeclStack[fElementDepth];
2355: fNil = fNilStack[fElementDepth];
2356: fNotation = fNotationStack[fElementDepth];
2357: fCurrentType = fTypeStack[fElementDepth];
2358: fCurrentCM = fCMStack[fElementDepth];
2359: fStrictAssess = fStrictAssessStack[fElementDepth];
2360: fCurrCMState = fCMStateStack[fElementDepth];
2361: fSawText = fSawTextStack[fElementDepth];
2362: fSawCharacters = fStringContent[fElementDepth];
2363:
2364: // We should have a stack for whitespace value, and pop it up here.
2365: // But when fWhiteSpace != -1, and we see a sub-element, it must be
2366: // an error (at least for Schema 1.0). So for valid documents, the
2367: // only value we are going to push/pop in the stack is -1.
2368: // Here we just mimic the effect of popping -1. -SG
2369: fWhiteSpace = -1;
2370: // Same for append buffer. Simple types and elements with fixed
2371: // value constraint don't allow sub-elements. -SG
2372: fAppendBuffer = false;
2373: // same here.
2374: fUnionType = false;
2375: }
2376:
2377: return augs;
2378: } // handleEndElement(QName,boolean)*/
2379:
2380: final Augmentations endElementPSVI(boolean root,
2381: SchemaGrammar[] grammars, Augmentations augs) {
2382:
2383: if (fAugPSVI) {
2384: augs = getEmptyAugs(augs);
2385:
2386: // the 5 properties sent on startElement calls
2387: fCurrentPSVI.fDeclaration = this .fCurrentElemDecl;
2388: fCurrentPSVI.fTypeDecl = this .fCurrentType;
2389: fCurrentPSVI.fNotation = this .fNotation;
2390: fCurrentPSVI.fValidationContext = this .fValidationRoot;
2391: fCurrentPSVI.fNil = this .fNil;
2392: // PSVI: validation attempted
2393: // nothing below or at the same level has none or partial
2394: // (which means this level is strictly assessed, and all chidren
2395: // are full), so this one has full
2396: if (fElementDepth > fNFullValidationDepth) {
2397: fCurrentPSVI.fValidationAttempted = ElementPSVI.VALIDATION_FULL;
2398: }
2399: // nothing below or at the same level has full or partial
2400: // (which means this level is not strictly assessed, and all chidren
2401: // are none), so this one has none
2402: else if (fElementDepth > fNNoneValidationDepth) {
2403: fCurrentPSVI.fValidationAttempted = ElementPSVI.VALIDATION_NONE;
2404: }
2405: // otherwise partial, and anything above this level will be partial
2406: else {
2407: fCurrentPSVI.fValidationAttempted = ElementPSVI.VALIDATION_PARTIAL;
2408: }
2409:
2410: // this guarantees that depth settings do not cross-over between sibling nodes
2411: if (fNFullValidationDepth == fElementDepth) {
2412: fNFullValidationDepth = fElementDepth - 1;
2413: }
2414: if (fNNoneValidationDepth == fElementDepth) {
2415: fNNoneValidationDepth = fElementDepth - 1;
2416: }
2417:
2418: if (fDefaultValue != null)
2419: fCurrentPSVI.fSpecified = true;
2420: fCurrentPSVI.fMemberType = fValidatedInfo.memberType;
2421: fCurrentPSVI.fNormalizedValue = fValidatedInfo.normalizedValue;
2422: fCurrentPSVI.fActualValue = fValidatedInfo.actualValue;
2423: fCurrentPSVI.fActualValueType = fValidatedInfo.actualValueType;
2424: fCurrentPSVI.fItemValueTypes = fValidatedInfo.itemValueTypes;
2425:
2426: if (fStrictAssess) {
2427: // get all errors for the current element, its attribute,
2428: // and subelements (if they were strictly assessed).
2429: // any error would make this element invalid.
2430: // and we merge these errors to the parent element.
2431: String[] errors = fXSIErrorReporter.mergeContext();
2432:
2433: // PSVI: error codes
2434: fCurrentPSVI.fErrorCodes = errors;
2435: // PSVI: validity
2436: fCurrentPSVI.fValidity = (errors == null) ? ElementPSVI.VALIDITY_VALID
2437: : ElementPSVI.VALIDITY_INVALID;
2438: } else {
2439: // PSVI: validity
2440: fCurrentPSVI.fValidity = ElementPSVI.VALIDITY_NOTKNOWN;
2441: // Discard the current context: ignore any error happened within
2442: // the sub-elements/attributes of this element, because those
2443: // errors won't affect the validity of the parent elements.
2444: fXSIErrorReporter.popContext();
2445: }
2446:
2447: if (root) {
2448: // store [schema information] in the PSVI
2449: fCurrentPSVI.fGrammars = grammars;
2450: fCurrentPSVI.fSchemaInformation = null;
2451: }
2452: }
2453:
2454: return augs;
2455:
2456: }
2457:
2458: Augmentations getEmptyAugs(Augmentations augs) {
2459: if (augs == null) {
2460: augs = fAugmentations;
2461: augs.removeAllItems();
2462: }
2463: augs.putItem(Constants.ELEMENT_PSVI, fCurrentPSVI);
2464: fCurrentPSVI.reset();
2465:
2466: return augs;
2467: }
2468:
2469: void storeLocations(String sLocation, String nsLocation) {
2470: if (sLocation != null) {
2471: if (!XMLSchemaLoader.tokenizeSchemaLocationStr(sLocation,
2472: fLocationPairs)) {
2473: // error!
2474: fXSIErrorReporter.reportError(
2475: XSMessageFormatter.SCHEMA_DOMAIN,
2476: "SchemaLocation", new Object[] { sLocation },
2477: XMLErrorReporter.SEVERITY_WARNING);
2478: }
2479: }
2480: if (nsLocation != null) {
2481: XMLSchemaLoader.LocationArray la = ((XMLSchemaLoader.LocationArray) fLocationPairs
2482: .get(XMLSymbols.EMPTY_STRING));
2483: if (la == null) {
2484: la = new XMLSchemaLoader.LocationArray();
2485: fLocationPairs.put(XMLSymbols.EMPTY_STRING, la);
2486: }
2487: la.addLocation(nsLocation);
2488: }
2489:
2490: } //storeLocations
2491:
2492: //this is the function where logic of retrieving grammar is written , parser first tries to get the grammar from
2493: //the local pool, if not in local pool, it gives chance to application to be able to retrieve the grammar, then it
2494: //tries to parse the grammar using location hints from the give namespace.
2495: SchemaGrammar findSchemaGrammar(short contextType,
2496: String namespace, QName enclosingElement,
2497: QName triggeringComponet, XMLAttributes attributes) {
2498: SchemaGrammar grammar = null;
2499: //get the grammar from local pool...
2500: grammar = fGrammarBucket.getGrammar(namespace);
2501: if (grammar == null) {
2502: fXSDDescription.reset();
2503: fXSDDescription.fContextType = contextType;
2504: fXSDDescription.setNamespace(namespace);
2505: fXSDDescription.fEnclosedElementName = enclosingElement;
2506: fXSDDescription.fTriggeringComponent = triggeringComponet;
2507: fXSDDescription.fAttributes = attributes;
2508: if (fLocator != null) {
2509: fXSDDescription.setBaseSystemId(fLocator
2510: .getExpandedSystemId());
2511: }
2512:
2513: String[] temp = null;
2514: Object locationArray = fLocationPairs
2515: .get(namespace == null ? XMLSymbols.EMPTY_STRING
2516: : namespace);
2517: if (locationArray != null)
2518: temp = ((XMLSchemaLoader.LocationArray) locationArray)
2519: .getLocationArray();
2520: if (temp != null && temp.length != 0) {
2521: fXSDDescription.fLocationHints = new String[temp.length];
2522: System.arraycopy(temp, 0,
2523: fXSDDescription.fLocationHints, 0, temp.length);
2524: }
2525:
2526: // give a chance to application to be able to retreive the grammar.
2527: if (fGrammarPool != null) {
2528: grammar = (SchemaGrammar) fGrammarPool
2529: .retrieveGrammar(fXSDDescription);
2530: if (grammar != null) {
2531: // put this grammar into the bucket, along with grammars
2532: // imported by it (directly or indirectly)
2533: if (!fGrammarBucket.putGrammar(grammar, true)) {
2534: // REVISIT: a conflict between new grammar(s) and grammars
2535: // in the bucket. What to do? A warning? An exception?
2536: fXSIErrorReporter.fErrorReporter.reportError(
2537: XSMessageFormatter.SCHEMA_DOMAIN,
2538: "GrammarConflict", null,
2539: XMLErrorReporter.SEVERITY_WARNING);
2540: grammar = null;
2541: }
2542: }
2543: }
2544: if (grammar == null && !fUseGrammarPoolOnly) {
2545: // try to parse the grammar using location hints from that namespace..
2546: try {
2547: XMLInputSource xis = XMLSchemaLoader
2548: .resolveDocument(fXSDDescription,
2549: fLocationPairs, fEntityResolver);
2550: grammar = fSchemaLoader.loadSchema(fXSDDescription,
2551: xis, fLocationPairs);
2552: } catch (IOException ex) {
2553: final String[] locationHints = fXSDDescription
2554: .getLocationHints();
2555: fXSIErrorReporter.fErrorReporter
2556: .reportError(
2557: XSMessageFormatter.SCHEMA_DOMAIN,
2558: "schema_reference.4",
2559: new Object[] { locationHints != null ? locationHints[0]
2560: : XMLSymbols.EMPTY_STRING },
2561: XMLErrorReporter.SEVERITY_WARNING);
2562: }
2563: }
2564: }
2565:
2566: return grammar;
2567:
2568: } //findSchemaGrammar
2569:
2570: XSTypeDefinition getAndCheckXsiType(QName element, String xsiType,
2571: XMLAttributes attributes) {
2572: // This method also deals with clause 1.2.1.2 of the constraint
2573: // Validation Rule: Schema-Validity Assessment (Element)
2574:
2575: // Element Locally Valid (Element)
2576: // 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:
2577: // 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);
2578: QName typeName = null;
2579: try {
2580: typeName = (QName) fQNameDV.validate(xsiType,
2581: fValidationState, null);
2582: } catch (InvalidDatatypeValueException e) {
2583: reportSchemaError(e.getKey(), e.getArgs());
2584: reportSchemaError("cvc-elt.4.1", new Object[] {
2585: element.rawname,
2586: SchemaSymbols.URI_XSI + ","
2587: + SchemaSymbols.XSI_TYPE, xsiType });
2588: return null;
2589: }
2590:
2591: // 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)
2592: XSTypeDefinition type = null;
2593: // if the namespace is schema namespace, first try built-in types
2594: if (typeName.uri == SchemaSymbols.URI_SCHEMAFORSCHEMA) {
2595: type = SchemaGrammar.SG_SchemaNS
2596: .getGlobalTypeDecl(typeName.localpart);
2597: }
2598: // if it's not schema built-in types, then try to get a grammar
2599: if (type == null) {
2600: //try to find schema grammar by different means....
2601: SchemaGrammar grammar = findSchemaGrammar(
2602: XSDDescription.CONTEXT_XSITYPE, typeName.uri,
2603: element, typeName, attributes);
2604:
2605: if (grammar != null)
2606: type = grammar.getGlobalTypeDecl(typeName.localpart);
2607: }
2608: // still couldn't find the type, report an error
2609: if (type == null) {
2610: reportSchemaError("cvc-elt.4.2", new Object[] {
2611: element.rawname, xsiType });
2612: return null;
2613: }
2614:
2615: // if there is no current type, set this one as current.
2616: // and we don't need to do extra checking
2617: if (fCurrentType != null) {
2618: short block = XSConstants.DERIVATION_NONE;
2619: // 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).
2620: // Note: It's possible to have fCurrentType be non-null and fCurrentElemDecl
2621: // be null, if the current type is set using the property "root-type-definition".
2622: // In that case, we don't disallow any substitutions. -PM
2623: if (fCurrentElemDecl != null) {
2624: block = fCurrentElemDecl.fBlock;
2625: }
2626: if (fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
2627: block |= ((XSComplexTypeDecl) fCurrentType).fBlock;
2628: }
2629: if (!XSConstraints.checkTypeDerivationOk(type,
2630: fCurrentType, block)) {
2631: reportSchemaError("cvc-elt.4.3", new Object[] {
2632: element.rawname, xsiType,
2633: fCurrentType.getName() });
2634: }
2635: }
2636:
2637: return type;
2638: } //getAndCheckXsiType
2639:
2640: boolean getXsiNil(QName element, String xsiNil) {
2641: // Element Locally Valid (Element)
2642: // 3 The appropriate case among the following must be true:
2643: // 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.
2644: if (fCurrentElemDecl != null && !fCurrentElemDecl.getNillable()) {
2645: reportSchemaError("cvc-elt.3.1",
2646: new Object[] {
2647: element.rawname,
2648: SchemaSymbols.URI_XSI + ","
2649: + SchemaSymbols.XSI_NIL });
2650: }
2651: // 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:
2652: // 3.2.2 There must be no fixed {value constraint}.
2653: else {
2654: String value = XMLChar.trim(xsiNil);
2655: if (value.equals(SchemaSymbols.ATTVAL_TRUE)
2656: || value.equals(SchemaSymbols.ATTVAL_TRUE_1)) {
2657: if (fCurrentElemDecl != null
2658: && fCurrentElemDecl.getConstraintType() == XSConstants.VC_FIXED) {
2659: reportSchemaError("cvc-elt.3.2.2", new Object[] {
2660: element.rawname,
2661: SchemaSymbols.URI_XSI + ","
2662: + SchemaSymbols.XSI_NIL });
2663: }
2664: return true;
2665: }
2666: }
2667: return false;
2668: }
2669:
2670: void processAttributes(QName element, XMLAttributes attributes,
2671: XSAttributeGroupDecl attrGrp) {
2672:
2673: if (DEBUG) {
2674: System.out.println("==>processAttributes: "
2675: + attributes.getLength());
2676: }
2677:
2678: // whether we have seen a Wildcard ID.
2679: String wildcardIDName = null;
2680:
2681: // for each present attribute
2682: int attCount = attributes.getLength();
2683:
2684: Augmentations augs = null;
2685: AttributePSVImpl attrPSVI = null;
2686:
2687: boolean isSimple = fCurrentType == null
2688: || fCurrentType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE;
2689:
2690: XSObjectList attrUses = null;
2691: int useCount = 0;
2692: XSWildcardDecl attrWildcard = null;
2693: if (!isSimple) {
2694: attrUses = attrGrp.getAttributeUses();
2695: useCount = attrUses.getLength();
2696: attrWildcard = attrGrp.fAttributeWC;
2697: }
2698:
2699: // Element Locally Valid (Complex Type)
2700: // 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:
2701: // get the corresponding attribute decl
2702: for (int index = 0; index < attCount; index++) {
2703:
2704: attributes.getName(index, fTempQName);
2705:
2706: if (DEBUG) {
2707: System.out.println("==>process attribute: "
2708: + fTempQName);
2709: }
2710:
2711: if (fAugPSVI || fIdConstraint) {
2712: augs = attributes.getAugmentations(index);
2713: attrPSVI = (AttributePSVImpl) augs
2714: .getItem(Constants.ATTRIBUTE_PSVI);
2715: if (attrPSVI != null) {
2716: attrPSVI.reset();
2717: } else {
2718: attrPSVI = new AttributePSVImpl();
2719: augs.putItem(Constants.ATTRIBUTE_PSVI, attrPSVI);
2720: }
2721: // PSVI attribute: validation context
2722: attrPSVI.fValidationContext = fValidationRoot;
2723: }
2724:
2725: // Element Locally Valid (Type)
2726: // 3.1.1 The element information item's [attributes] must be empty, excepting those
2727: // whose [namespace name] is identical to http://www.w3.org/2001/XMLSchema-instance and
2728: // whose [local name] is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
2729:
2730: // for the 4 xsi attributes, get appropriate decl, and validate
2731: if (fTempQName.uri == SchemaSymbols.URI_XSI) {
2732: XSAttributeDecl attrDecl = null;
2733: if (fTempQName.localpart == SchemaSymbols.XSI_TYPE) {
2734: attrDecl = XSI_TYPE;
2735: } else if (fTempQName.localpart == SchemaSymbols.XSI_NIL) {
2736: attrDecl = XSI_NIL;
2737: } else if (fTempQName.localpart == SchemaSymbols.XSI_SCHEMALOCATION) {
2738: attrDecl = XSI_SCHEMALOCATION;
2739: } else if (fTempQName.localpart == SchemaSymbols.XSI_NONAMESPACESCHEMALOCATION) {
2740: attrDecl = XSI_NONAMESPACESCHEMALOCATION;
2741: }
2742: if (attrDecl != null) {
2743: processOneAttribute(element, attributes, index,
2744: attrDecl, null, attrPSVI);
2745: continue;
2746: }
2747: }
2748:
2749: // for namespace attributes, no_validation/unknow_validity
2750: if (fTempQName.rawname == XMLSymbols.PREFIX_XMLNS
2751: || fTempQName.rawname.startsWith("xmlns:")) {
2752: continue;
2753: }
2754:
2755: // simple type doesn't allow any other attributes
2756: if (isSimple) {
2757: reportSchemaError("cvc-type.3.1.1", new Object[] {
2758: element.rawname, fTempQName.rawname });
2759: continue;
2760: }
2761:
2762: // it's not xmlns, and not xsi, then we need to find a decl for it
2763: XSAttributeUseImpl currUse = null, oneUse;
2764: for (int i = 0; i < useCount; i++) {
2765: oneUse = (XSAttributeUseImpl) attrUses.item(i);
2766: if (oneUse.fAttrDecl.fName == fTempQName.localpart
2767: && oneUse.fAttrDecl.fTargetNamespace == fTempQName.uri) {
2768: currUse = oneUse;
2769: break;
2770: }
2771: }
2772:
2773: // 3.2 otherwise all of the following must be true:
2774: // 3.2.1 There must be an {attribute wildcard}.
2775: // 3.2.2 The attribute information item must be valid with respect to it as defined in Item Valid (Wildcard) (3.10.4).
2776:
2777: // if failed, get it from wildcard
2778: if (currUse == null) {
2779: //if (attrWildcard == null)
2780: // reportSchemaError("cvc-complex-type.3.2.1", new Object[]{element.rawname, fTempQName.rawname});
2781: if (attrWildcard == null
2782: || !attrWildcard.allowNamespace(fTempQName.uri)) {
2783: // so this attribute is not allowed
2784: reportSchemaError("cvc-complex-type.3.2.2",
2785: new Object[] { element.rawname,
2786: fTempQName.rawname });
2787: continue;
2788: }
2789: }
2790:
2791: XSAttributeDecl currDecl = null;
2792: if (currUse != null) {
2793: currDecl = currUse.fAttrDecl;
2794: } else {
2795: // which means it matches a wildcard
2796: // skip it if processContents is skip
2797: if (attrWildcard.fProcessContents == XSWildcardDecl.PC_SKIP)
2798: continue;
2799:
2800: //try to find grammar by different means...
2801: SchemaGrammar grammar = findSchemaGrammar(
2802: XSDDescription.CONTEXT_ATTRIBUTE,
2803: fTempQName.uri, element, fTempQName, attributes);
2804:
2805: if (grammar != null) {
2806: currDecl = grammar
2807: .getGlobalAttributeDecl(fTempQName.localpart);
2808: }
2809:
2810: // if can't find
2811: if (currDecl == null) {
2812: // if strict, report error
2813: if (attrWildcard.fProcessContents == XSWildcardDecl.PC_STRICT) {
2814: reportSchemaError("cvc-complex-type.3.2.2",
2815: new Object[] { element.rawname,
2816: fTempQName.rawname });
2817: }
2818:
2819: // then continue to the next attribute
2820: continue;
2821: } else {
2822: // 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:
2823: // 5.1 There must be no more than one item in wild IDs.
2824: if (currDecl.fType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE
2825: && ((XSSimpleType) currDecl.fType)
2826: .isIDType()) {
2827: if (wildcardIDName != null) {
2828: reportSchemaError("cvc-complex-type.5.1",
2829: new Object[] { element.rawname,
2830: currDecl.fName,
2831: wildcardIDName });
2832: } else
2833: wildcardIDName = currDecl.fName;
2834: }
2835: }
2836: }
2837:
2838: processOneAttribute(element, attributes, index, currDecl,
2839: currUse, attrPSVI);
2840: } // end of for (all attributes)
2841:
2842: // 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.
2843: if (!isSimple && attrGrp.fIDAttrName != null
2844: && wildcardIDName != null) {
2845: reportSchemaError("cvc-complex-type.5.2", new Object[] {
2846: element.rawname, wildcardIDName,
2847: attrGrp.fIDAttrName });
2848: }
2849:
2850: } //processAttributes
2851:
2852: void processOneAttribute(QName element, XMLAttributes attributes,
2853: int index, XSAttributeDecl currDecl,
2854: XSAttributeUseImpl currUse, AttributePSVImpl attrPSVI) {
2855:
2856: String attrValue = attributes.getValue(index);
2857: fXSIErrorReporter.pushContext();
2858:
2859: // Attribute Locally Valid
2860: // For an attribute information item to be locally valid with respect to an attribute declaration all of the following must be true:
2861: // 1 The declaration must not be absent (see Missing Sub-components (5.3) for how this can fail to be the case).
2862: // 2 Its {type definition} must not be absent.
2863: // 3 The item's normalized value must be locally valid with respect to that {type definition} as per String Valid (3.14.4).
2864: // get simple type
2865: XSSimpleType attDV = currDecl.fType;
2866:
2867: Object actualValue = null;
2868: try {
2869: actualValue = attDV.validate(attrValue, fValidationState,
2870: fValidatedInfo);
2871: // store the normalized value
2872: if (fNormalizeData)
2873: attributes.setValue(index,
2874: fValidatedInfo.normalizedValue);
2875: if (attributes instanceof XMLAttributesImpl) {
2876: XMLAttributesImpl attrs = (XMLAttributesImpl) attributes;
2877: boolean schemaId = fValidatedInfo.memberType != null ? fValidatedInfo.memberType
2878: .isIDType()
2879: : attDV.isIDType();
2880: attrs.setSchemaId(index, schemaId);
2881: }
2882:
2883: // PSVI: element notation
2884: if (attDV.getVariety() == XSSimpleType.VARIETY_ATOMIC
2885: && attDV.getPrimitiveKind() == XSSimpleType.PRIMITIVE_NOTATION) {
2886: QName qName = (QName) actualValue;
2887: SchemaGrammar grammar = fGrammarBucket
2888: .getGrammar(qName.uri);
2889:
2890: //REVISIT: is it possible for the notation to be in different namespace than the attribute
2891: //with which it is associated, CHECK !! <fof n1:att1 = "n2:notation1" ..>
2892: // should we give chance to the application to be able to retrieve a grammar - nb
2893: //REVISIT: what would be the triggering component here.. if it is attribute value that
2894: // triggered the loading of grammar ?? -nb
2895:
2896: if (grammar != null) {
2897: fNotation = grammar
2898: .getGlobalNotationDecl(qName.localpart);
2899: }
2900: }
2901: } catch (InvalidDatatypeValueException idve) {
2902: reportSchemaError(idve.getKey(), idve.getArgs());
2903: reportSchemaError("cvc-attribute.3", new Object[] {
2904: element.rawname, fTempQName.rawname, attrValue,
2905: attDV.getName() });
2906: }
2907:
2908: // get the value constraint from use or decl
2909: // 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
2910: if (actualValue != null
2911: && currDecl.getConstraintType() == XSConstants.VC_FIXED) {
2912: if (!ValidatedInfo.isComparable(fValidatedInfo,
2913: currDecl.fDefault)
2914: || !actualValue
2915: .equals(currDecl.fDefault.actualValue)) {
2916: reportSchemaError("cvc-attribute.4", new Object[] {
2917: element.rawname, fTempQName.rawname, attrValue,
2918: currDecl.fDefault.stringValue() });
2919: }
2920: }
2921:
2922: // 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).
2923: if (actualValue != null && currUse != null
2924: && currUse.fConstraintType == XSConstants.VC_FIXED) {
2925: if (!ValidatedInfo.isComparable(fValidatedInfo,
2926: currUse.fDefault)
2927: || !actualValue
2928: .equals(currUse.fDefault.actualValue)) {
2929: reportSchemaError("cvc-complex-type.3.1", new Object[] {
2930: element.rawname, fTempQName.rawname, attrValue,
2931: currUse.fDefault.stringValue() });
2932: }
2933: }
2934: if (fIdConstraint) {
2935: attrPSVI.fActualValue = actualValue;
2936: }
2937:
2938: if (fAugPSVI) {
2939: // PSVI: attribute declaration
2940: attrPSVI.fDeclaration = currDecl;
2941: // PSVI: attribute type
2942: attrPSVI.fTypeDecl = attDV;
2943:
2944: // PSVI: attribute memberType
2945: attrPSVI.fMemberType = fValidatedInfo.memberType;
2946: // PSVI: attribute normalized value
2947: // NOTE: we always store the normalized value, even if it's invlid,
2948: // because it might still be useful to the user. But when the it's
2949: // not valid, the normalized value is not trustable.
2950: attrPSVI.fNormalizedValue = fValidatedInfo.normalizedValue;
2951: attrPSVI.fActualValue = fValidatedInfo.actualValue;
2952: attrPSVI.fActualValueType = fValidatedInfo.actualValueType;
2953: attrPSVI.fItemValueTypes = fValidatedInfo.itemValueTypes;
2954:
2955: // PSVI: validation attempted:
2956: attrPSVI.fValidationAttempted = AttributePSVI.VALIDATION_FULL;
2957:
2958: String[] errors = fXSIErrorReporter.mergeContext();
2959: // PSVI: error codes
2960: attrPSVI.fErrorCodes = errors;
2961: // PSVI: validity
2962: attrPSVI.fValidity = (errors == null) ? AttributePSVI.VALIDITY_VALID
2963: : AttributePSVI.VALIDITY_INVALID;
2964: }
2965: }
2966:
2967: void addDefaultAttributes(QName element, XMLAttributes attributes,
2968: XSAttributeGroupDecl attrGrp) {
2969: // Check after all specified attrs are scanned
2970: // (1) report error for REQUIRED attrs that are missing (V_TAGc)
2971: // REVISIT: should we check prohibited attributes?
2972: // (2) report error for PROHIBITED attrs that are present (V_TAGc)
2973: // (3) add default attrs (FIXED and NOT_FIXED)
2974: //
2975: if (DEBUG) {
2976: System.out.println("==>addDefaultAttributes: " + element);
2977: }
2978: XSObjectList attrUses = attrGrp.getAttributeUses();
2979: int useCount = attrUses.getLength();
2980: XSAttributeUseImpl currUse;
2981: XSAttributeDecl currDecl;
2982: short constType;
2983: ValidatedInfo defaultValue;
2984: boolean isSpecified;
2985: QName attName;
2986: // for each attribute use
2987: for (int i = 0; i < useCount; i++) {
2988:
2989: currUse = (XSAttributeUseImpl) attrUses.item(i);
2990: currDecl = currUse.fAttrDecl;
2991: // get value constraint
2992: constType = currUse.fConstraintType;
2993: defaultValue = currUse.fDefault;
2994: if (constType == XSConstants.VC_NONE) {
2995: constType = currDecl.getConstraintType();
2996: defaultValue = currDecl.fDefault;
2997: }
2998: // whether this attribute is specified
2999: isSpecified = attributes.getValue(
3000: currDecl.fTargetNamespace, currDecl.fName) != null;
3001:
3002: // Element Locally Valid (Complex Type)
3003: // 4 The {attribute declaration} of each attribute use in the {attribute uses} whose
3004: // {required} is true matches one of the attribute information items in the element
3005: // information item's [attributes] as per clause 3.1 above.
3006: if (currUse.fUse == SchemaSymbols.USE_REQUIRED) {
3007: if (!isSpecified)
3008: reportSchemaError("cvc-complex-type.4",
3009: new Object[] { element.rawname,
3010: currDecl.fName });
3011: }
3012: // if the attribute is not specified, then apply the value constraint
3013: if (!isSpecified && constType != XSConstants.VC_NONE) {
3014: attName = new QName(null, currDecl.fName,
3015: currDecl.fName, currDecl.fTargetNamespace);
3016: String normalized = (defaultValue != null) ? defaultValue
3017: .stringValue()
3018: : "";
3019: int attrIndex;
3020: if (attributes instanceof XMLAttributesImpl) {
3021: XMLAttributesImpl attrs = (XMLAttributesImpl) attributes;
3022: attrIndex = attrs.getLength();
3023: attrs.addAttributeNS(attName, "CDATA", normalized);
3024: boolean schemaId = defaultValue != null
3025: && defaultValue.memberType != null ? defaultValue.memberType
3026: .isIDType()
3027: : currDecl.fType.isIDType();
3028: attrs.setSchemaId(attrIndex, schemaId);
3029: } else {
3030: attrIndex = attributes.addAttribute(attName,
3031: "CDATA", normalized);
3032: }
3033:
3034: if (fAugPSVI) {
3035:
3036: // PSVI: attribute is "schema" specified
3037: Augmentations augs = attributes
3038: .getAugmentations(attrIndex);
3039: AttributePSVImpl attrPSVI = new AttributePSVImpl();
3040: augs.putItem(Constants.ATTRIBUTE_PSVI, attrPSVI);
3041:
3042: attrPSVI.fDeclaration = currDecl;
3043: attrPSVI.fTypeDecl = currDecl.fType;
3044: attrPSVI.fMemberType = defaultValue.memberType;
3045: attrPSVI.fNormalizedValue = normalized;
3046: attrPSVI.fActualValue = defaultValue.actualValue;
3047: attrPSVI.fActualValueType = defaultValue.actualValueType;
3048: attrPSVI.fItemValueTypes = defaultValue.itemValueTypes;
3049: attrPSVI.fValidationContext = fValidationRoot;
3050: attrPSVI.fValidity = AttributePSVI.VALIDITY_VALID;
3051: attrPSVI.fValidationAttempted = AttributePSVI.VALIDATION_FULL;
3052: attrPSVI.fSpecified = true;
3053: }
3054: }
3055:
3056: } // for
3057: } // addDefaultAttributes
3058:
3059: /**
3060: * If there is not text content, and there is a
3061: * {value constraint} on the corresponding element decl, then return
3062: * an XMLString representing the default value.
3063: */
3064: void processElementContent(QName element) {
3065: // 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.
3066: if (fCurrentElemDecl != null
3067: && fCurrentElemDecl.fDefault != null && !fSawText
3068: && !fSubElement && !fNil) {
3069:
3070: String strv = fCurrentElemDecl.fDefault.stringValue();
3071: int bufLen = strv.length();
3072: if (fNormalizedStr.ch == null
3073: || fNormalizedStr.ch.length < bufLen) {
3074: fNormalizedStr.ch = new char[bufLen];
3075: }
3076: strv.getChars(0, bufLen, fNormalizedStr.ch, 0);
3077: fNormalizedStr.offset = 0;
3078: fNormalizedStr.length = bufLen;
3079: fDefaultValue = fNormalizedStr;
3080: }
3081: // fixed values are handled later, after xsi:type determined.
3082:
3083: fValidatedInfo.normalizedValue = null;
3084:
3085: // Element Locally Valid (Element)
3086: // 3.2.1 The element information item must have no character or element information item [children].
3087: if (fNil) {
3088: if (fSubElement || fSawText) {
3089: reportSchemaError("cvc-elt.3.2.1", new Object[] {
3090: element.rawname,
3091: SchemaSymbols.URI_XSI + ","
3092: + SchemaSymbols.XSI_NIL });
3093: }
3094: }
3095:
3096: this .fValidatedInfo.reset();
3097:
3098: // 5 The appropriate case among the following must be true:
3099: // 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:
3100: if (fCurrentElemDecl != null
3101: && fCurrentElemDecl.getConstraintType() != XSConstants.VC_NONE
3102: && !fSubElement && !fSawText && !fNil) {
3103: // 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).
3104: if (fCurrentType != fCurrentElemDecl.fType) {
3105: //REVISIT:we should pass ValidatedInfo here.
3106: if (XSConstraints.ElementDefaultValidImmediate(
3107: fCurrentType, fCurrentElemDecl.fDefault
3108: .stringValue(), fState4XsiType, null) == null)
3109: reportSchemaError("cvc-elt.5.1.1", new Object[] {
3110: element.rawname, fCurrentType.getName(),
3111: fCurrentElemDecl.fDefault.stringValue() });
3112: }
3113: // 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).
3114: // REVISIT: don't use toString, but validateActualValue instead
3115: // use the fState4ApplyDefault
3116: elementLocallyValidType(element, fCurrentElemDecl.fDefault
3117: .stringValue());
3118: } else {
3119: // The following method call also deal with clause 1.2.2 of the constraint
3120: // Validation Rule: Schema-Validity Assessment (Element)
3121:
3122: // 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:
3123: // 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).
3124: Object actualValue = elementLocallyValidType(element,
3125: fBuffer);
3126: // 5.2.2 If there is a fixed {value constraint} and clause 3.2 has not applied, all of the following must be true:
3127: if (fCurrentElemDecl != null
3128: && fCurrentElemDecl.getConstraintType() == XSConstants.VC_FIXED
3129: && !fNil) {
3130: String content = fBuffer.toString();
3131: // 5.2.2.1 The element information item must have no element information item [children].
3132: if (fSubElement)
3133: reportSchemaError("cvc-elt.5.2.2.1",
3134: new Object[] { element.rawname });
3135: // 5.2.2.2 The appropriate case among the following must be true:
3136: if (fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
3137: XSComplexTypeDecl ctype = (XSComplexTypeDecl) fCurrentType;
3138: // 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.
3139: if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_MIXED) {
3140: // REVISIT: how to get the initial value, does whiteSpace count?
3141: if (!fCurrentElemDecl.fDefault.normalizedValue
3142: .equals(content))
3143: reportSchemaError(
3144: "cvc-elt.5.2.2.2.1",
3145: new Object[] {
3146: element.rawname,
3147: content,
3148: fCurrentElemDecl.fDefault.normalizedValue });
3149: }
3150: // 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.
3151: else if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_SIMPLE) {
3152: if (actualValue != null
3153: && (!ValidatedInfo.isComparable(
3154: fValidatedInfo,
3155: fCurrentElemDecl.fDefault) || !actualValue
3156: .equals(fCurrentElemDecl.fDefault.actualValue))) {
3157: reportSchemaError("cvc-elt.5.2.2.2.2",
3158: new Object[] {
3159: element.rawname,
3160: content,
3161: fCurrentElemDecl.fDefault
3162: .stringValue() });
3163: }
3164: }
3165: } else if (fCurrentType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
3166: if (actualValue != null
3167: && (!ValidatedInfo.isComparable(
3168: fValidatedInfo,
3169: fCurrentElemDecl.fDefault) || !actualValue
3170: .equals(fCurrentElemDecl.fDefault.actualValue))) {
3171: // REVISIT: the spec didn't mention this case: fixed
3172: // value with simple type
3173: reportSchemaError("cvc-elt.5.2.2.2.2",
3174: new Object[] {
3175: element.rawname,
3176: content,
3177: fCurrentElemDecl.fDefault
3178: .stringValue() });
3179: }
3180: }
3181: }
3182: }
3183:
3184: if (fDefaultValue == null && fNormalizeData
3185: && fDocumentHandler != null && fUnionType) {
3186: // for union types we need to send data because we delayed sending
3187: // this data when we received it in the characters() call.
3188: String content = fValidatedInfo.normalizedValue;
3189: if (content == null)
3190: content = fBuffer.toString();
3191:
3192: int bufLen = content.length();
3193: if (fNormalizedStr.ch == null
3194: || fNormalizedStr.ch.length < bufLen) {
3195: fNormalizedStr.ch = new char[bufLen];
3196: }
3197: content.getChars(0, bufLen, fNormalizedStr.ch, 0);
3198: fNormalizedStr.offset = 0;
3199: fNormalizedStr.length = bufLen;
3200: fDocumentHandler.characters(fNormalizedStr, null);
3201: }
3202: } // processElementContent
3203:
3204: Object elementLocallyValidType(QName element, Object textContent) {
3205: if (fCurrentType == null)
3206: return null;
3207:
3208: Object retValue = null;
3209: // Element Locally Valid (Type)
3210: // 3 The appropriate case among the following must be true:
3211: // 3.1 If the type definition is a simple type definition, then all of the following must be true:
3212: if (fCurrentType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
3213: // 3.1.2 The element information item must have no element information item [children].
3214: if (fSubElement)
3215: reportSchemaError("cvc-type.3.1.2",
3216: new Object[] { element.rawname });
3217: // 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).
3218: if (!fNil) {
3219: XSSimpleType dv = (XSSimpleType) fCurrentType;
3220: try {
3221: if (!fNormalizeData || fUnionType) {
3222: fValidationState.setNormalizationRequired(true);
3223: }
3224: retValue = dv.validate(textContent,
3225: fValidationState, fValidatedInfo);
3226: } catch (InvalidDatatypeValueException e) {
3227: reportSchemaError(e.getKey(), e.getArgs());
3228: reportSchemaError("cvc-type.3.1.3", new Object[] {
3229: element.rawname, textContent });
3230: }
3231: }
3232: } else {
3233: // 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);
3234: retValue = elementLocallyValidComplexType(element,
3235: textContent);
3236: }
3237:
3238: return retValue;
3239: } // elementLocallyValidType
3240:
3241: Object elementLocallyValidComplexType(QName element,
3242: Object textContent) {
3243: Object actualValue = null;
3244: XSComplexTypeDecl ctype = (XSComplexTypeDecl) fCurrentType;
3245:
3246: // Element Locally Valid (Complex Type)
3247: // For an element information item to be locally valid with respect to a complex type definition all of the following must be true:
3248: // 1 {abstract} is false.
3249: // 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:
3250: if (!fNil) {
3251: // 2.1 If the {content type} is empty, then the element information item has no character or element information item [children].
3252: if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_EMPTY
3253: && (fSubElement || fSawText)) {
3254: reportSchemaError("cvc-complex-type.2.1",
3255: new Object[] { element.rawname });
3256: }
3257: // 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).
3258: else if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_SIMPLE) {
3259: if (fSubElement)
3260: reportSchemaError("cvc-complex-type.2.2",
3261: new Object[] { element.rawname });
3262: XSSimpleType dv = ctype.fXSSimpleType;
3263: try {
3264: if (!fNormalizeData || fUnionType) {
3265: fValidationState.setNormalizationRequired(true);
3266: }
3267: actualValue = dv.validate(textContent,
3268: fValidationState, fValidatedInfo);
3269: } catch (InvalidDatatypeValueException e) {
3270: reportSchemaError(e.getKey(), e.getArgs());
3271: reportSchemaError("cvc-complex-type.2.2",
3272: new Object[] { element.rawname });
3273: }
3274: // REVISIT: eventually, this method should return the same actualValue as elementLocallyValidType...
3275: // obviously it'll return null when the content is complex.
3276: }
3277: // 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)].
3278: else if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_ELEMENT) {
3279: if (fSawCharacters) {
3280: reportSchemaError("cvc-complex-type.2.3",
3281: new Object[] { element.rawname });
3282: }
3283: }
3284: // 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).
3285: if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_ELEMENT
3286: || ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_MIXED) {
3287: // if the current state is a valid state, check whether
3288: // it's one of the final states.
3289: if (DEBUG) {
3290: System.out.println(fCurrCMState);
3291: }
3292: if (fCurrCMState[0] >= 0
3293: && !fCurrentCM.endContentModel(fCurrCMState)) {
3294: String expected = expectedStr(fCurrentCM
3295: .whatCanGoHere(fCurrCMState));
3296: reportSchemaError("cvc-complex-type.2.4.b",
3297: new Object[] { element.rawname, expected });
3298: }
3299: }
3300: }
3301: return actualValue;
3302: } // elementLocallyValidComplexType
3303:
3304: void reportSchemaError(String key, Object[] arguments) {
3305: if (fDoValidation)
3306: fXSIErrorReporter.reportError(
3307: XSMessageFormatter.SCHEMA_DOMAIN, key, arguments,
3308: XMLErrorReporter.SEVERITY_ERROR);
3309: }
3310:
3311: private String expectedStr(Vector expected) {
3312: StringBuffer ret = new StringBuffer("{");
3313: int size = expected.size();
3314: for (int i = 0; i < size; i++) {
3315: if (i > 0)
3316: ret.append(", ");
3317: ret.append(expected.elementAt(i).toString());
3318: }
3319: ret.append('}');
3320: return ret.toString();
3321: }
3322:
3323: /**********************************/
3324:
3325: // xpath matcher information
3326: /**
3327: * Stack of XPath matchers for identity constraints.
3328: *
3329: * @author Andy Clark, IBM
3330: */
3331: protected static class XPathMatcherStack {
3332:
3333: //
3334: // Data
3335: //
3336:
3337: /** Active matchers. */
3338: protected XPathMatcher[] fMatchers = new XPathMatcher[4];
3339:
3340: /** Count of active matchers. */
3341: protected int fMatchersCount;
3342:
3343: /** Offset stack for contexts. */
3344: protected IntStack fContextStack = new IntStack();
3345:
3346: //
3347: // Constructors
3348: //
3349:
3350: public XPathMatcherStack() {
3351: } // <init>()
3352:
3353: //
3354: // Public methods
3355: //
3356:
3357: /** Resets the XPath matcher stack. */
3358: public void clear() {
3359: for (int i = 0; i < fMatchersCount; i++) {
3360: fMatchers[i] = null;
3361: }
3362: fMatchersCount = 0;
3363: fContextStack.clear();
3364: } // clear()
3365:
3366: /** Returns the size of the stack. */
3367: public int size() {
3368: return fContextStack.size();
3369: } // size():int
3370:
3371: /** Returns the count of XPath matchers. */
3372: public int getMatcherCount() {
3373: return fMatchersCount;
3374: } // getMatcherCount():int
3375:
3376: /** Adds a matcher. */
3377: public void addMatcher(XPathMatcher matcher) {
3378: ensureMatcherCapacity();
3379: fMatchers[fMatchersCount++] = matcher;
3380: } // addMatcher(XPathMatcher)
3381:
3382: /** Returns the XPath matcher at the specified index. */
3383: public XPathMatcher getMatcherAt(int index) {
3384: return fMatchers[index];
3385: } // getMatcherAt(index):XPathMatcher
3386:
3387: /** Pushes a new context onto the stack. */
3388: public void pushContext() {
3389: fContextStack.push(fMatchersCount);
3390: } // pushContext()
3391:
3392: /** Pops a context off of the stack. */
3393: public void popContext() {
3394: fMatchersCount = fContextStack.pop();
3395: } // popContext()
3396:
3397: //
3398: // Private methods
3399: //
3400:
3401: /** Ensures the size of the matchers array. */
3402: private void ensureMatcherCapacity() {
3403: if (fMatchersCount == fMatchers.length) {
3404: XPathMatcher[] array = new XPathMatcher[fMatchers.length * 2];
3405: System.arraycopy(fMatchers, 0, array, 0,
3406: fMatchers.length);
3407: fMatchers = array;
3408: }
3409: } // ensureMatcherCapacity()
3410:
3411: } // class XPathMatcherStack
3412:
3413: // value store implementations
3414:
3415: /**
3416: * Value store implementation base class. There are specific subclasses
3417: * for handling unique, key, and keyref.
3418: *
3419: * @author Andy Clark, IBM
3420: */
3421: protected abstract class ValueStoreBase implements ValueStore {
3422:
3423: //
3424: // Data
3425: //
3426:
3427: /** Identity constraint. */
3428: protected IdentityConstraint fIdentityConstraint;
3429: protected int fFieldCount = 0;
3430: protected Field[] fFields = null;
3431: /** current data */
3432: protected Object[] fLocalValues = null;
3433: protected short[] fLocalValueTypes = null;
3434: protected ShortList[] fLocalItemValueTypes = null;
3435:
3436: /** Current data value count. */
3437: protected int fValuesCount;
3438:
3439: /** global data */
3440: public final Vector fValues = new Vector();
3441: public ShortVector fValueTypes = null;
3442: public Vector fItemValueTypes = null;
3443:
3444: private boolean fUseValueTypeVector = false;
3445: private int fValueTypesLength = 0;
3446: private short fValueType = 0;
3447:
3448: private boolean fUseItemValueTypeVector = false;
3449: private int fItemValueTypesLength = 0;
3450: private ShortList fItemValueType = null;
3451:
3452: /** buffer for error messages */
3453: final StringBuffer fTempBuffer = new StringBuffer();
3454:
3455: //
3456: // Constructors
3457: //
3458:
3459: /** Constructs a value store for the specified identity constraint. */
3460: protected ValueStoreBase(IdentityConstraint identityConstraint) {
3461: fIdentityConstraint = identityConstraint;
3462: fFieldCount = fIdentityConstraint.getFieldCount();
3463: fFields = new Field[fFieldCount];
3464: fLocalValues = new Object[fFieldCount];
3465: fLocalValueTypes = new short[fFieldCount];
3466: fLocalItemValueTypes = new ShortList[fFieldCount];
3467: for (int i = 0; i < fFieldCount; i++) {
3468: fFields[i] = fIdentityConstraint.getFieldAt(i);
3469: }
3470: } // <init>(IdentityConstraint)
3471:
3472: //
3473: // Public methods
3474: //
3475:
3476: // destroys this ValueStore; useful when, for instance, a
3477: // locally-scoped ID constraint is involved.
3478: public void clear() {
3479: fValuesCount = 0;
3480: fUseValueTypeVector = false;
3481: fValueTypesLength = 0;
3482: fValueType = 0;
3483: fUseItemValueTypeVector = false;
3484: fItemValueTypesLength = 0;
3485: fItemValueType = null;
3486: fValues.setSize(0);
3487: if (fValueTypes != null) {
3488: fValueTypes.clear();
3489: }
3490: if (fItemValueTypes != null) {
3491: fItemValueTypes.setSize(0);
3492: }
3493: } // end clear():void
3494:
3495: // appends the contents of one ValueStore to those of us.
3496: public void append(ValueStoreBase newVal) {
3497: for (int i = 0; i < newVal.fValues.size(); i++) {
3498: fValues.addElement(newVal.fValues.elementAt(i));
3499: }
3500: } // append(ValueStoreBase)
3501:
3502: /** Start scope for value store. */
3503: public void startValueScope() {
3504: fValuesCount = 0;
3505: for (int i = 0; i < fFieldCount; i++) {
3506: fLocalValues[i] = null;
3507: fLocalValueTypes[i] = 0;
3508: fLocalItemValueTypes[i] = null;
3509: }
3510: } // startValueScope()
3511:
3512: /** Ends scope for value store. */
3513: public void endValueScope() {
3514:
3515: if (fValuesCount == 0) {
3516: if (fIdentityConstraint.getCategory() == IdentityConstraint.IC_KEY) {
3517: String code = "AbsentKeyValue";
3518: String eName = fIdentityConstraint.getElementName();
3519: String cName = fIdentityConstraint
3520: .getIdentityConstraintName();
3521: reportSchemaError(code,
3522: new Object[] { eName, cName });
3523: }
3524: return;
3525: }
3526:
3527: // Validation Rule: Identity-constraint Satisfied
3528: // 4.2 If the {identity-constraint category} is key, then all of the following must be true:
3529: // 4.2.1 The target node set and the qualified node set are equal, that is, every member of the
3530: // target node set is also a member of the qualified node set and vice versa.
3531: //
3532: // If the IDC is a key check whether we have all the fields.
3533: if (fValuesCount != fFieldCount) {
3534: if (fIdentityConstraint.getCategory() == IdentityConstraint.IC_KEY) {
3535: String code = "KeyNotEnoughValues";
3536: UniqueOrKey key = (UniqueOrKey) fIdentityConstraint;
3537: String eName = fIdentityConstraint.getElementName();
3538: String cName = key.getIdentityConstraintName();
3539: reportSchemaError(code,
3540: new Object[] { eName, cName });
3541: }
3542: return;
3543: }
3544:
3545: } // endValueScope()
3546:
3547: // This is needed to allow keyref's to look for matched keys
3548: // in the correct scope. Unique and Key may also need to
3549: // override this method for purposes of their own.
3550: // This method is called whenever the DocumentFragment
3551: // of an ID Constraint goes out of scope.
3552: public void endDocumentFragment() {
3553: } // endDocumentFragment():void
3554:
3555: /**
3556: * Signals the end of the document. This is where the specific
3557: * instances of value stores can verify the integrity of the
3558: * identity constraints.
3559: */
3560: public void endDocument() {
3561: } // endDocument()
3562:
3563: //
3564: // ValueStore methods
3565: //
3566:
3567: /* reports an error if an element is matched
3568: * has nillable true and is matched by a key.
3569: */
3570:
3571: public void reportError(String key, Object[] args) {
3572: reportSchemaError(key, args);
3573: } // reportError(String,Object[])
3574:
3575: /**
3576: * Adds the specified value to the value store.
3577: *
3578: * @param field The field associated to the value. This reference
3579: * is used to ensure that each field only adds a value
3580: * once within a selection scope.
3581: * @param mayMatch a flag indiciating whether the field may be matched.
3582: * @param actualValue The value to add.
3583: * @param valueType Type of the value to add.
3584: * @param itemValueType If the value is a list, a list of types for each of the values in the list.
3585: */
3586: public void addValue(Field field, boolean mayMatch,
3587: Object actualValue, short valueType,
3588: ShortList itemValueType) {
3589: int i;
3590: for (i = fFieldCount - 1; i > -1; i--) {
3591: if (fFields[i] == field) {
3592: break;
3593: }
3594: }
3595: // do we even know this field?
3596: if (i == -1) {
3597: String code = "UnknownField";
3598: String eName = fIdentityConstraint.getElementName();
3599: String cName = fIdentityConstraint
3600: .getIdentityConstraintName();
3601: reportSchemaError(code, new Object[] {
3602: field.toString(), eName, cName });
3603: return;
3604: }
3605: if (!mayMatch) {
3606: String code = "FieldMultipleMatch";
3607: String cName = fIdentityConstraint
3608: .getIdentityConstraintName();
3609: reportSchemaError(code, new Object[] {
3610: field.toString(), cName });
3611: } else {
3612: fValuesCount++;
3613: }
3614: fLocalValues[i] = actualValue;
3615: fLocalValueTypes[i] = valueType;
3616: fLocalItemValueTypes[i] = itemValueType;
3617: if (fValuesCount == fFieldCount) {
3618: checkDuplicateValues();
3619: // store values
3620: for (i = 0; i < fFieldCount; i++) {
3621: fValues.addElement(fLocalValues[i]);
3622: addValueType(fLocalValueTypes[i]);
3623: addItemValueType(fLocalItemValueTypes[i]);
3624: }
3625: }
3626: } // addValue(String,Field)
3627:
3628: /**
3629: * Returns true if this value store contains the locally scoped value stores
3630: */
3631: public boolean contains() {
3632: // REVISIT: we can improve performance by using hash codes, instead of
3633: // traversing global vector that could be quite large.
3634: int next = 0;
3635: final int size = fValues.size();
3636: LOOP: for (int i = 0; i < size; i = next) {
3637: next = i + fFieldCount;
3638: for (int j = 0; j < fFieldCount; j++) {
3639: Object value1 = fLocalValues[j];
3640: Object value2 = fValues.elementAt(i);
3641: short valueType1 = fLocalValueTypes[j];
3642: short valueType2 = getValueTypeAt(i);
3643: if (value1 == null || value2 == null
3644: || valueType1 != valueType2
3645: || !(value1.equals(value2))) {
3646: continue LOOP;
3647: } else if (valueType1 == XSConstants.LIST_DT
3648: || valueType1 == XSConstants.LISTOFUNION_DT) {
3649: ShortList list1 = fLocalItemValueTypes[j];
3650: ShortList list2 = getItemValueTypeAt(i);
3651: if (list1 == null || list2 == null
3652: || !list1.equals(list2))
3653: continue LOOP;
3654: }
3655: i++;
3656: }
3657: // found it
3658: return true;
3659: }
3660: // didn't find it
3661: return false;
3662: } // contains():boolean
3663:
3664: /**
3665: * Returns -1 if this value store contains the specified
3666: * values, otherwise the index of the first field in the
3667: * key sequence.
3668: */
3669: public int contains(ValueStoreBase vsb) {
3670:
3671: final Vector values = vsb.fValues;
3672: final int size1 = values.size();
3673: if (fFieldCount <= 1) {
3674: for (int i = 0; i < size1; ++i) {
3675: short val = vsb.getValueTypeAt(i);
3676: if (!valueTypeContains(val)
3677: || !fValues.contains(values.elementAt(i))) {
3678: return i;
3679: } else if (val == XSConstants.LIST_DT
3680: || val == XSConstants.LISTOFUNION_DT) {
3681: ShortList list1 = vsb.getItemValueTypeAt(i);
3682: if (!itemValueTypeContains(list1)) {
3683: return i;
3684: }
3685: }
3686: }
3687: }
3688: /** Handle n-tuples. **/
3689: else {
3690: final int size2 = fValues.size();
3691: /** Iterate over each set of fields. **/
3692: OUTER: for (int i = 0; i < size1; i += fFieldCount) {
3693: /** Check whether this set is contained in the value store. **/
3694: INNER: for (int j = 0; j < size2; j += fFieldCount) {
3695: for (int k = 0; k < fFieldCount; ++k) {
3696: final Object value1 = values.elementAt(i
3697: + k);
3698: final Object value2 = fValues.elementAt(j
3699: + k);
3700: final short valueType1 = vsb
3701: .getValueTypeAt(i + k);
3702: final short valueType2 = getValueTypeAt(j
3703: + k);
3704: if (value1 != value2
3705: && (valueType1 != valueType2
3706: || value1 == null || !value1
3707: .equals(value2))) {
3708: continue INNER;
3709: } else if (valueType1 == XSConstants.LIST_DT
3710: || valueType1 == XSConstants.LISTOFUNION_DT) {
3711: ShortList list1 = vsb
3712: .getItemValueTypeAt(i + k);
3713: ShortList list2 = getItemValueTypeAt(j
3714: + k);
3715: if (list1 == null || list2 == null
3716: || !list1.equals(list2)) {
3717: continue INNER;
3718: }
3719: }
3720: }
3721: continue OUTER;
3722: }
3723: return i;
3724: }
3725: }
3726: return -1;
3727:
3728: } // contains(Vector):Object
3729:
3730: //
3731: // Protected methods
3732: //
3733:
3734: protected void checkDuplicateValues() {
3735: // no-op
3736: } // duplicateValue(Hashtable)
3737:
3738: /** Returns a string of the specified values. */
3739: protected String toString(Object[] values) {
3740:
3741: // no values
3742: int size = values.length;
3743: if (size == 0) {
3744: return "";
3745: }
3746:
3747: fTempBuffer.setLength(0);
3748:
3749: // construct value string
3750: for (int i = 0; i < size; i++) {
3751: if (i > 0) {
3752: fTempBuffer.append(',');
3753: }
3754: fTempBuffer.append(values[i]);
3755: }
3756: return fTempBuffer.toString();
3757:
3758: } // toString(Object[]):String
3759:
3760: /** Returns a string of the specified values. */
3761: protected String toString(Vector values, int start, int length) {
3762:
3763: // no values
3764: if (length == 0) {
3765: return "";
3766: }
3767:
3768: // one value
3769: if (length == 1) {
3770: return String.valueOf(values.elementAt(start));
3771: }
3772:
3773: // construct value string
3774: StringBuffer str = new StringBuffer();
3775: for (int i = 0; i < length; i++) {
3776: if (i > 0) {
3777: str.append(',');
3778: }
3779: str.append(values.elementAt(start + i));
3780: }
3781: return str.toString();
3782:
3783: } // toString(Vector,int,int):String
3784:
3785: //
3786: // Object methods
3787: //
3788:
3789: /** Returns a string representation of this object. */
3790: public String toString() {
3791: String s = super .toString();
3792: int index1 = s.lastIndexOf('$');
3793: if (index1 != -1) {
3794: s = s.substring(index1 + 1);
3795: }
3796: int index2 = s.lastIndexOf('.');
3797: if (index2 != -1) {
3798: s = s.substring(index2 + 1);
3799: }
3800: return s + '[' + fIdentityConstraint + ']';
3801: } // toString():String
3802:
3803: //
3804: // Private methods
3805: //
3806:
3807: private void addValueType(short type) {
3808: if (fUseValueTypeVector) {
3809: fValueTypes.add(type);
3810: } else if (fValueTypesLength++ == 0) {
3811: fValueType = type;
3812: } else if (fValueType != type) {
3813: fUseValueTypeVector = true;
3814: if (fValueTypes == null) {
3815: fValueTypes = new ShortVector(fValueTypesLength * 2);
3816: }
3817: for (int i = 1; i < fValueTypesLength; ++i) {
3818: fValueTypes.add(fValueType);
3819: }
3820: fValueTypes.add(type);
3821: }
3822: }
3823:
3824: private short getValueTypeAt(int index) {
3825: if (fUseValueTypeVector) {
3826: return fValueTypes.valueAt(index);
3827: }
3828: return fValueType;
3829: }
3830:
3831: private boolean valueTypeContains(short value) {
3832: if (fUseValueTypeVector) {
3833: return fValueTypes.contains(value);
3834: }
3835: return fValueType == value;
3836: }
3837:
3838: private void addItemValueType(ShortList itemValueType) {
3839: if (fUseItemValueTypeVector) {
3840: fItemValueTypes.add(itemValueType);
3841: } else if (fItemValueTypesLength++ == 0) {
3842: fItemValueType = itemValueType;
3843: } else if (!(fItemValueType == itemValueType || (fItemValueType != null && fItemValueType
3844: .equals(itemValueType)))) {
3845: fUseItemValueTypeVector = true;
3846: if (fItemValueTypes == null) {
3847: fItemValueTypes = new Vector(
3848: fItemValueTypesLength * 2);
3849: }
3850: for (int i = 1; i < fItemValueTypesLength; ++i) {
3851: fItemValueTypes.add(fItemValueType);
3852: }
3853: fItemValueTypes.add(itemValueType);
3854: }
3855: }
3856:
3857: private ShortList getItemValueTypeAt(int index) {
3858: if (fUseItemValueTypeVector) {
3859: return (ShortList) fItemValueTypes.elementAt(index);
3860: }
3861: return fItemValueType;
3862: }
3863:
3864: private boolean itemValueTypeContains(ShortList value) {
3865: if (fUseItemValueTypeVector) {
3866: return fItemValueTypes.contains(value);
3867: }
3868: return fItemValueType == value
3869: || (fItemValueType != null && fItemValueType
3870: .equals(value));
3871: }
3872:
3873: } // class ValueStoreBase
3874:
3875: /**
3876: * Unique value store.
3877: *
3878: * @author Andy Clark, IBM
3879: */
3880: protected class UniqueValueStore extends ValueStoreBase {
3881:
3882: //
3883: // Constructors
3884: //
3885:
3886: /** Constructs a unique value store. */
3887: public UniqueValueStore(UniqueOrKey unique) {
3888: super (unique);
3889: } // <init>(Unique)
3890:
3891: //
3892: // ValueStoreBase protected methods
3893: //
3894:
3895: /**
3896: * Called when a duplicate value is added.
3897: */
3898: protected void checkDuplicateValues() {
3899: // is this value as a group duplicated?
3900: if (contains()) {
3901: String code = "DuplicateUnique";
3902: String value = toString(fLocalValues);
3903: String eName = fIdentityConstraint.getElementName();
3904: String cName = fIdentityConstraint
3905: .getIdentityConstraintName();
3906: reportSchemaError(code, new Object[] { value, eName,
3907: cName });
3908: }
3909: } // duplicateValue(Hashtable)
3910:
3911: } // class UniqueValueStore
3912:
3913: /**
3914: * Key value store.
3915: *
3916: * @author Andy Clark, IBM
3917: */
3918: protected class KeyValueStore extends ValueStoreBase {
3919:
3920: // REVISIT: Implement a more efficient storage mechanism. -Ac
3921:
3922: //
3923: // Constructors
3924: //
3925:
3926: /** Constructs a key value store. */
3927: public KeyValueStore(UniqueOrKey key) {
3928: super (key);
3929: } // <init>(Key)
3930:
3931: //
3932: // ValueStoreBase protected methods
3933: //
3934:
3935: /**
3936: * Called when a duplicate value is added.
3937: */
3938: protected void checkDuplicateValues() {
3939: if (contains()) {
3940: String code = "DuplicateKey";
3941: String value = toString(fLocalValues);
3942: String eName = fIdentityConstraint.getElementName();
3943: String cName = fIdentityConstraint
3944: .getIdentityConstraintName();
3945: reportSchemaError(code, new Object[] { value, eName,
3946: cName });
3947: }
3948: } // duplicateValue(Hashtable)
3949:
3950: } // class KeyValueStore
3951:
3952: /**
3953: * Key reference value store.
3954: *
3955: * @author Andy Clark, IBM
3956: */
3957: protected class KeyRefValueStore extends ValueStoreBase {
3958:
3959: //
3960: // Data
3961: //
3962:
3963: /** Key value store. */
3964: protected ValueStoreBase fKeyValueStore;
3965:
3966: //
3967: // Constructors
3968: //
3969:
3970: /** Constructs a key value store. */
3971: public KeyRefValueStore(KeyRef keyRef,
3972: KeyValueStore keyValueStore) {
3973: super (keyRef);
3974: fKeyValueStore = keyValueStore;
3975: } // <init>(KeyRef)
3976:
3977: //
3978: // ValueStoreBase methods
3979: //
3980:
3981: // end the value Scope; here's where we have to tie
3982: // up keyRef loose ends.
3983: public void endDocumentFragment() {
3984:
3985: // do all the necessary management...
3986: super .endDocumentFragment();
3987:
3988: // verify references
3989: // get the key store corresponding (if it exists):
3990: fKeyValueStore = (ValueStoreBase) fValueStoreCache.fGlobalIDConstraintMap
3991: .get(((KeyRef) fIdentityConstraint).getKey());
3992:
3993: if (fKeyValueStore == null) {
3994: // report error
3995: String code = "KeyRefOutOfScope";
3996: String value = fIdentityConstraint.toString();
3997: reportSchemaError(code, new Object[] { value });
3998: return;
3999: }
4000: int errorIndex = fKeyValueStore.contains(this );
4001: if (errorIndex != -1) {
4002: String code = "KeyNotFound";
4003: String values = toString(fValues, errorIndex,
4004: fFieldCount);
4005: String element = fIdentityConstraint.getElementName();
4006: String name = fIdentityConstraint.getName();
4007: reportSchemaError(code, new Object[] { name, values,
4008: element });
4009: }
4010:
4011: } // endDocumentFragment()
4012:
4013: /** End document. */
4014: public void endDocument() {
4015: super .endDocument();
4016:
4017: } // endDocument()
4018:
4019: } // class KeyRefValueStore
4020:
4021: // value store management
4022:
4023: /**
4024: * Value store cache. This class is used to store the values for
4025: * identity constraints.
4026: *
4027: * @author Andy Clark, IBM
4028: */
4029: protected class ValueStoreCache {
4030:
4031: //
4032: // Data
4033: //
4034: final LocalIDKey fLocalId = new LocalIDKey();
4035: // values stores
4036:
4037: /** stores all global Values stores. */
4038: protected final Vector fValueStores = new Vector();
4039:
4040: /**
4041: * Values stores associated to specific identity constraints.
4042: * This hashtable maps IdentityConstraints and
4043: * the 0-based element on which their selectors first matched to
4044: * a corresponding ValueStore. This should take care
4045: * of all cases, including where ID constraints with
4046: * descendant-or-self axes occur on recursively-defined
4047: * elements.
4048: */
4049: protected final Hashtable fIdentityConstraint2ValueStoreMap = new Hashtable();
4050:
4051: // sketch of algorithm:
4052: // - when a constraint is first encountered, its
4053: // values are stored in the (local) fIdentityConstraint2ValueStoreMap;
4054: // - Once it is validated (i.e., when it goes out of scope),
4055: // its values are merged into the fGlobalIDConstraintMap;
4056: // - as we encounter keyref's, we look at the global table to
4057: // validate them.
4058: //
4059: // The fGlobalIDMapStack has the following structure:
4060: // - validation always occurs against the fGlobalIDConstraintMap
4061: // (which comprises all the "eligible" id constraints);
4062: // When an endElement is found, this Hashtable is merged with the one
4063: // below in the stack.
4064: // When a start tag is encountered, we create a new
4065: // fGlobalIDConstraintMap.
4066: // i.e., the top of the fGlobalIDMapStack always contains
4067: // the preceding siblings' eligible id constraints;
4068: // the fGlobalIDConstraintMap contains descendants+self.
4069: // keyrefs can only match descendants+self.
4070: protected final Stack fGlobalMapStack = new Stack();
4071: protected final Hashtable fGlobalIDConstraintMap = new Hashtable();
4072:
4073: //
4074: // Constructors
4075: //
4076:
4077: /** Default constructor. */
4078: public ValueStoreCache() {
4079: } // <init>()
4080:
4081: //
4082: // Public methods
4083: //
4084:
4085: /** Resets the identity constraint cache. */
4086: public void startDocument() {
4087: fValueStores.removeAllElements();
4088: fIdentityConstraint2ValueStoreMap.clear();
4089: fGlobalIDConstraintMap.clear();
4090: fGlobalMapStack.removeAllElements();
4091: } // startDocument()
4092:
4093: // startElement: pushes the current fGlobalIDConstraintMap
4094: // onto fGlobalMapStack and clears fGlobalIDConstraint map.
4095: public void startElement() {
4096: // only clone the hashtable when there are elements
4097: if (fGlobalIDConstraintMap.size() > 0)
4098: fGlobalMapStack.push(fGlobalIDConstraintMap.clone());
4099: else
4100: fGlobalMapStack.push(null);
4101: fGlobalIDConstraintMap.clear();
4102: } // startElement(void)
4103:
4104: /** endElement(): merges contents of fGlobalIDConstraintMap with the
4105: * top of fGlobalMapStack into fGlobalIDConstraintMap.
4106: */
4107: public void endElement() {
4108: if (fGlobalMapStack.isEmpty())
4109: return; // must be an invalid doc!
4110: Hashtable oldMap = (Hashtable) fGlobalMapStack.pop();
4111: // return if there is no element
4112: if (oldMap == null)
4113: return;
4114:
4115: Enumeration keys = oldMap.keys();
4116: while (keys.hasMoreElements()) {
4117: IdentityConstraint id = (IdentityConstraint) keys
4118: .nextElement();
4119: ValueStoreBase oldVal = (ValueStoreBase) oldMap.get(id);
4120: if (oldVal != null) {
4121: ValueStoreBase currVal = (ValueStoreBase) fGlobalIDConstraintMap
4122: .get(id);
4123: if (currVal == null)
4124: fGlobalIDConstraintMap.put(id, oldVal);
4125: else if (currVal != oldVal) {
4126: currVal.append(oldVal);
4127: }
4128: }
4129: }
4130: } // endElement()
4131:
4132: /**
4133: * Initializes the value stores for the specified element
4134: * declaration.
4135: */
4136: public void initValueStoresFor(XSElementDecl eDecl,
4137: FieldActivator activator) {
4138: // initialize value stores for unique fields
4139: IdentityConstraint[] icArray = eDecl.fIDConstraints;
4140: int icCount = eDecl.fIDCPos;
4141: for (int i = 0; i < icCount; i++) {
4142: switch (icArray[i].getCategory()) {
4143: case (IdentityConstraint.IC_UNIQUE):
4144: // initialize value stores for unique fields
4145: UniqueOrKey unique = (UniqueOrKey) icArray[i];
4146: LocalIDKey toHash = new LocalIDKey(unique,
4147: fElementDepth);
4148: UniqueValueStore uniqueValueStore = (UniqueValueStore) fIdentityConstraint2ValueStoreMap
4149: .get(toHash);
4150: if (uniqueValueStore == null) {
4151: uniqueValueStore = new UniqueValueStore(unique);
4152: fIdentityConstraint2ValueStoreMap.put(toHash,
4153: uniqueValueStore);
4154: } else {
4155: uniqueValueStore.clear();
4156: }
4157: fValueStores.addElement(uniqueValueStore);
4158: activateSelectorFor(icArray[i]);
4159: break;
4160: case (IdentityConstraint.IC_KEY):
4161: // initialize value stores for key fields
4162: UniqueOrKey key = (UniqueOrKey) icArray[i];
4163: toHash = new LocalIDKey(key, fElementDepth);
4164: KeyValueStore keyValueStore = (KeyValueStore) fIdentityConstraint2ValueStoreMap
4165: .get(toHash);
4166: if (keyValueStore == null) {
4167: keyValueStore = new KeyValueStore(key);
4168: fIdentityConstraint2ValueStoreMap.put(toHash,
4169: keyValueStore);
4170: } else {
4171: keyValueStore.clear();
4172: }
4173: fValueStores.addElement(keyValueStore);
4174: activateSelectorFor(icArray[i]);
4175: break;
4176: case (IdentityConstraint.IC_KEYREF):
4177: // initialize value stores for keyRef fields
4178: KeyRef keyRef = (KeyRef) icArray[i];
4179: toHash = new LocalIDKey(keyRef, fElementDepth);
4180: KeyRefValueStore keyRefValueStore = (KeyRefValueStore) fIdentityConstraint2ValueStoreMap
4181: .get(toHash);
4182: if (keyRefValueStore == null) {
4183: keyRefValueStore = new KeyRefValueStore(keyRef,
4184: null);
4185: fIdentityConstraint2ValueStoreMap.put(toHash,
4186: keyRefValueStore);
4187: } else {
4188: keyRefValueStore.clear();
4189: }
4190: fValueStores.addElement(keyRefValueStore);
4191: activateSelectorFor(icArray[i]);
4192: break;
4193: }
4194: }
4195: } // initValueStoresFor(XSElementDecl)
4196:
4197: /** Returns the value store associated to the specified IdentityConstraint. */
4198: public ValueStoreBase getValueStoreFor(IdentityConstraint id,
4199: int initialDepth) {
4200: fLocalId.fDepth = initialDepth;
4201: fLocalId.fId = id;
4202: return (ValueStoreBase) fIdentityConstraint2ValueStoreMap
4203: .get(fLocalId);
4204: } // getValueStoreFor(IdentityConstraint, int):ValueStoreBase
4205:
4206: /** Returns the global value store associated to the specified IdentityConstraint. */
4207: public ValueStoreBase getGlobalValueStoreFor(
4208: IdentityConstraint id) {
4209: return (ValueStoreBase) fGlobalIDConstraintMap.get(id);
4210: } // getValueStoreFor(IdentityConstraint):ValueStoreBase
4211:
4212: // This method takes the contents of the (local) ValueStore
4213: // associated with id and moves them into the global
4214: // hashtable, if id is a <unique> or a <key>.
4215: // If it's a <keyRef>, then we leave it for later.
4216: public void transplant(IdentityConstraint id, int initialDepth) {
4217: fLocalId.fDepth = initialDepth;
4218: fLocalId.fId = id;
4219: ValueStoreBase newVals = (ValueStoreBase) fIdentityConstraint2ValueStoreMap
4220: .get(fLocalId);
4221: if (id.getCategory() == IdentityConstraint.IC_KEYREF)
4222: return;
4223: ValueStoreBase currVals = (ValueStoreBase) fGlobalIDConstraintMap
4224: .get(id);
4225: if (currVals != null) {
4226: currVals.append(newVals);
4227: fGlobalIDConstraintMap.put(id, currVals);
4228: } else
4229: fGlobalIDConstraintMap.put(id, newVals);
4230:
4231: } // transplant(id)
4232:
4233: /** Check identity constraints. */
4234: public void endDocument() {
4235:
4236: int count = fValueStores.size();
4237: for (int i = 0; i < count; i++) {
4238: ValueStoreBase valueStore = (ValueStoreBase) fValueStores
4239: .elementAt(i);
4240: valueStore.endDocument();
4241: }
4242:
4243: } // endDocument()
4244:
4245: //
4246: // Object methods
4247: //
4248:
4249: /** Returns a string representation of this object. */
4250: public String toString() {
4251: String s = super .toString();
4252: int index1 = s.lastIndexOf('$');
4253: if (index1 != -1) {
4254: return s.substring(index1 + 1);
4255: }
4256: int index2 = s.lastIndexOf('.');
4257: if (index2 != -1) {
4258: return s.substring(index2 + 1);
4259: }
4260: return s;
4261: } // toString():String
4262:
4263: } // class ValueStoreCache
4264:
4265: // the purpose of this class is to enable IdentityConstraint,int
4266: // pairs to be used easily as keys in Hashtables.
4267: protected static final class LocalIDKey {
4268:
4269: public IdentityConstraint fId;
4270: public int fDepth;
4271:
4272: public LocalIDKey() {
4273: }
4274:
4275: public LocalIDKey(IdentityConstraint id, int depth) {
4276: fId = id;
4277: fDepth = depth;
4278: } // init(IdentityConstraint, int)
4279:
4280: // object method
4281: public int hashCode() {
4282: return fId.hashCode() + fDepth;
4283: }
4284:
4285: public boolean equals(Object localIDKey) {
4286: if (localIDKey instanceof LocalIDKey) {
4287: LocalIDKey lIDKey = (LocalIDKey) localIDKey;
4288: return (lIDKey.fId == fId && lIDKey.fDepth == fDepth);
4289: }
4290: return false;
4291: }
4292: } // class LocalIDKey
4293:
4294: /**
4295: * A simple vector for <code>short</code>s.
4296: */
4297: protected static final class ShortVector {
4298:
4299: //
4300: // Data
4301: //
4302:
4303: /** Current length. */
4304: private int fLength;
4305:
4306: /** Data. */
4307: private short[] fData;
4308:
4309: //
4310: // Constructors
4311: //
4312:
4313: public ShortVector() {
4314: }
4315:
4316: public ShortVector(int initialCapacity) {
4317: fData = new short[initialCapacity];
4318: }
4319:
4320: //
4321: // Public methods
4322: //
4323:
4324: /** Returns the length of the vector. */
4325: public int length() {
4326: return fLength;
4327: }
4328:
4329: /** Adds the value to the vector. */
4330: public void add(short value) {
4331: ensureCapacity(fLength + 1);
4332: fData[fLength++] = value;
4333: }
4334:
4335: /** Returns the short value at the specified position in the vector. */
4336: public short valueAt(int position) {
4337: return fData[position];
4338: }
4339:
4340: /** Clears the vector. */
4341: public void clear() {
4342: fLength = 0;
4343: }
4344:
4345: /** Returns whether the short is contained in the vector. */
4346: public boolean contains(short value) {
4347: for (int i = 0; i < fLength; ++i) {
4348: if (fData[i] == value) {
4349: return true;
4350: }
4351: }
4352: return false;
4353: }
4354:
4355: //
4356: // Private methods
4357: //
4358:
4359: /** Ensures capacity. */
4360: private void ensureCapacity(int size) {
4361: if (fData == null) {
4362: fData = new short[8];
4363: } else if (fData.length <= size) {
4364: short[] newdata = new short[fData.length * 2];
4365: System.arraycopy(fData, 0, newdata, 0, fData.length);
4366: fData = newdata;
4367: }
4368: }
4369: }
4370:
4371: } // class SchemaValidator
|