diff options
Diffstat (limited to 'src/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java')
-rw-r--r-- | src/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java | 4304 |
1 files changed, 4304 insertions, 0 deletions
diff --git a/src/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java b/src/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java new file mode 100644 index 0000000..7c9974e --- /dev/null +++ b/src/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java @@ -0,0 +1,4304 @@ +/* + * reserved comment block + * DO NOT REMOVE OR ALTER! + */ +/* + * Copyright 1999-2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.sun.org.apache.xerces.internal.impl.xs.traversers; + +import java.io.IOException; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.Stack; +import java.util.Vector; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import com.sun.org.apache.xerces.internal.impl.Constants; +import com.sun.org.apache.xerces.internal.impl.XMLEntityManager; +import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter; +import com.sun.org.apache.xerces.internal.impl.dv.SchemaDVFactory; +import com.sun.org.apache.xerces.internal.impl.dv.xs.XSSimpleTypeDecl; +import com.sun.org.apache.xerces.internal.impl.xs.SchemaGrammar; +import com.sun.org.apache.xerces.internal.impl.xs.SchemaNamespaceSupport; +import com.sun.org.apache.xerces.internal.impl.xs.SchemaSymbols; +import com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaException; +import com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader; +import com.sun.org.apache.xerces.internal.impl.xs.XSAttributeDecl; +import com.sun.org.apache.xerces.internal.impl.xs.XSAttributeGroupDecl; +import com.sun.org.apache.xerces.internal.impl.xs.XSComplexTypeDecl; +import com.sun.org.apache.xerces.internal.impl.xs.XSDDescription; +import com.sun.org.apache.xerces.internal.impl.xs.XSDeclarationPool; +import com.sun.org.apache.xerces.internal.impl.xs.XSElementDecl; +import com.sun.org.apache.xerces.internal.impl.xs.XSGrammarBucket; +import com.sun.org.apache.xerces.internal.impl.xs.XSGroupDecl; +import com.sun.org.apache.xerces.internal.impl.xs.XSMessageFormatter; +import com.sun.org.apache.xerces.internal.impl.xs.XSModelGroupImpl; +import com.sun.org.apache.xerces.internal.impl.xs.XSNotationDecl; +import com.sun.org.apache.xerces.internal.impl.xs.XSParticleDecl; +import com.sun.org.apache.xerces.internal.impl.xs.identity.IdentityConstraint; +import com.sun.org.apache.xerces.internal.impl.xs.opti.ElementImpl; +import com.sun.org.apache.xerces.internal.impl.xs.opti.SchemaDOMParser; +import com.sun.org.apache.xerces.internal.impl.xs.opti.SchemaParsingConfig; +import com.sun.org.apache.xerces.internal.impl.xs.util.SimpleLocator; +import com.sun.org.apache.xerces.internal.impl.xs.util.XSInputSource; +import com.sun.org.apache.xerces.internal.parsers.SAXParser; +import com.sun.org.apache.xerces.internal.parsers.XML11Configuration; +import com.sun.org.apache.xerces.internal.util.DOMInputSource; +import com.sun.org.apache.xerces.internal.util.DOMUtil; +import com.sun.org.apache.xerces.internal.util.DefaultErrorHandler; +import com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper; +import com.sun.org.apache.xerces.internal.util.SAXInputSource; +import com.sun.org.apache.xerces.internal.util.SecurityManager; +import com.sun.org.apache.xerces.internal.util.StAXInputSource; +import com.sun.org.apache.xerces.internal.util.StAXLocationWrapper; +import com.sun.org.apache.xerces.internal.util.SymbolHash; +import com.sun.org.apache.xerces.internal.util.SymbolTable; +import com.sun.org.apache.xerces.internal.util.XMLSymbols; +import com.sun.org.apache.xerces.internal.util.URI.MalformedURIException; +import com.sun.org.apache.xerces.internal.xni.QName; +import com.sun.org.apache.xerces.internal.xni.XNIException; +import com.sun.org.apache.xerces.internal.xni.grammars.Grammar; +import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription; +import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool; +import com.sun.org.apache.xerces.internal.xni.grammars.XMLSchemaDescription; +import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager; +import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException; +import com.sun.org.apache.xerces.internal.xni.parser.XMLEntityResolver; +import com.sun.org.apache.xerces.internal.xni.parser.XMLErrorHandler; +import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource; +import com.sun.org.apache.xerces.internal.xni.parser.XMLParseException; +import com.sun.org.apache.xerces.internal.xs.StringList; +import com.sun.org.apache.xerces.internal.xs.XSAttributeDeclaration; +import com.sun.org.apache.xerces.internal.xs.XSAttributeGroupDefinition; +import com.sun.org.apache.xerces.internal.xs.XSAttributeUse; +import com.sun.org.apache.xerces.internal.xs.XSConstants; +import com.sun.org.apache.xerces.internal.xs.XSElementDeclaration; +import com.sun.org.apache.xerces.internal.xs.XSModelGroup; +import com.sun.org.apache.xerces.internal.xs.XSModelGroupDefinition; +import com.sun.org.apache.xerces.internal.xs.XSNamedMap; +import com.sun.org.apache.xerces.internal.xs.XSObject; +import com.sun.org.apache.xerces.internal.xs.XSObjectList; +import com.sun.org.apache.xerces.internal.xs.XSParticle; +import com.sun.org.apache.xerces.internal.xs.XSSimpleTypeDefinition; +import com.sun.org.apache.xerces.internal.xs.XSTerm; +import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition; +import com.sun.org.apache.xerces.internal.xs.datatypes.ObjectList; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.XMLReaderFactory; + +/** + * The purpose of this class is to co-ordinate the construction of a + * grammar object corresponding to a schema. To do this, it must be + * prepared to parse several schema documents (for instance if the + * schema document originally referred to contains <include> or + * <redefined> information items). If any of the schemas imports a + * schema, other grammars may be constructed as a side-effect. + * + * @xerces.internal + * + * @author Neil Graham, IBM + * @author Pavani Mukthipudi, Sun Microsystems + * + * @version $Id: XSDHandler.java,v 1.9 2010-11-01 04:40:02 joehw Exp $ + */ +public class XSDHandler { + + /** Feature identifier: validation. */ + protected static final String VALIDATION = + Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE; + + /** feature identifier: XML Schema validation */ + protected static final String XMLSCHEMA_VALIDATION = + Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE; + + /** Feature identifier: allow java encodings */ + protected static final String ALLOW_JAVA_ENCODINGS = + Constants.XERCES_FEATURE_PREFIX + Constants.ALLOW_JAVA_ENCODINGS_FEATURE; + + /** Feature identifier: continue after fatal error */ + protected static final String CONTINUE_AFTER_FATAL_ERROR = + Constants.XERCES_FEATURE_PREFIX + Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE; + + /** Feature identifier: allow java encodings */ + protected static final String STANDARD_URI_CONFORMANT_FEATURE = + Constants.XERCES_FEATURE_PREFIX + Constants.STANDARD_URI_CONFORMANT_FEATURE; + + /** Feature: disallow doctype*/ + protected static final String DISALLOW_DOCTYPE = + Constants.XERCES_FEATURE_PREFIX + Constants.DISALLOW_DOCTYPE_DECL_FEATURE; + + /** Feature: generate synthetic annotations */ + protected static final String GENERATE_SYNTHETIC_ANNOTATIONS = + Constants.XERCES_FEATURE_PREFIX + Constants.GENERATE_SYNTHETIC_ANNOTATIONS_FEATURE; + + /** Feature identifier: validate annotations. */ + protected static final String VALIDATE_ANNOTATIONS = + Constants.XERCES_FEATURE_PREFIX + Constants.VALIDATE_ANNOTATIONS_FEATURE; + + /** Feature identifier: honour all schemaLocations */ + protected static final String HONOUR_ALL_SCHEMALOCATIONS = + Constants.XERCES_FEATURE_PREFIX + Constants.HONOUR_ALL_SCHEMALOCATIONS_FEATURE; + + /** Feature identifier: namespace growth */ + protected static final String NAMESPACE_GROWTH = + Constants.XERCES_FEATURE_PREFIX + Constants.NAMESPACE_GROWTH_FEATURE; + + /** Feature identifier: tolerate duplicates */ + protected static final String TOLERATE_DUPLICATES = + Constants.XERCES_FEATURE_PREFIX + Constants.TOLERATE_DUPLICATES_FEATURE; + + /** Feature identifier: namespace prefixes. */ + private static final String NAMESPACE_PREFIXES = + Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACE_PREFIXES_FEATURE; + + /** Feature identifier: string interning. */ + protected static final String STRING_INTERNING = + Constants.SAX_FEATURE_PREFIX + Constants.STRING_INTERNING_FEATURE; + + /** Property identifier: error handler. */ + protected static final String ERROR_HANDLER = + Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY; + + /** Property identifier: JAXP schema source. */ + protected static final String JAXP_SCHEMA_SOURCE = + Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE; + + /** Property identifier: entity resolver. */ + public static final String ENTITY_RESOLVER = + Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY; + /** Property identifier: entity manager. */ + protected static final String ENTITY_MANAGER = + Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY; + + /** Property identifier: error reporter. */ + public static final String ERROR_REPORTER = + Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY; + + /** Property identifier: grammar pool. */ + public static final String XMLGRAMMAR_POOL = + Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY; + + /** Property identifier: symbol table. */ + public static final String SYMBOL_TABLE = + Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY; + + /** Property identifier: security manager. */ + protected static final String SECURITY_MANAGER = + Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY; + + private static final String SECURE_PROCESSING = + Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY; + + /** Property identifier: locale. */ + protected static final String LOCALE = + Constants.XERCES_PROPERTY_PREFIX + Constants.LOCALE_PROPERTY; + + protected static final boolean DEBUG_NODE_POOL = false; + + // Data + + // different sorts of declarations; should make lookup and + // traverser calling more efficient/less bulky. + final static int ATTRIBUTE_TYPE = 1; + final static int ATTRIBUTEGROUP_TYPE = 2; + final static int ELEMENT_TYPE = 3; + final static int GROUP_TYPE = 4; + final static int IDENTITYCONSTRAINT_TYPE = 5; + final static int NOTATION_TYPE = 6; + final static int TYPEDECL_TYPE = 7; + + // this string gets appended to redefined names; it's purpose is to be + // as unlikely as possible to cause collisions. + public final static String REDEF_IDENTIFIER = "_fn3dktizrknc9pi"; + + // + //protected data that can be accessable by any traverser + + protected XSDeclarationPool fDeclPool = null; + + /** + * <p>Security manager in effect.</p> + * + * <p>Protected to allow access by any traverser.</p> + */ + protected SecurityManager fSecureProcessing = null; + + // These tables correspond to the symbol spaces defined in the + // spec. + // They are keyed with a QName (that is, String("URI,localpart) and + // their values are nodes corresponding to the given name's decl. + // By asking the node for its ownerDocument and looking in + // XSDocumentInfoRegistry we can easily get the corresponding + // XSDocumentInfo object. + private boolean registryEmpty = true; + private Map<String, Element> fUnparsedAttributeRegistry = new HashMap(); + private Map<String, Element> fUnparsedAttributeGroupRegistry = new HashMap(); + private Map<String, Element> fUnparsedElementRegistry = new HashMap(); + private Map<String, Element> fUnparsedGroupRegistry = new HashMap(); + private Map<String, Element> fUnparsedIdentityConstraintRegistry = new HashMap(); + private Map<String, Element> fUnparsedNotationRegistry = new HashMap(); + private Map<String, Element> fUnparsedTypeRegistry = new HashMap(); + // Compensation for the above hashtables to locate XSDocumentInfo, + // Since we may take Schema Element directly, so can not get the + // corresponding XSDocumentInfo object just using above hashtables. + private Map<String, XSDocumentInfo> fUnparsedAttributeRegistrySub = new HashMap(); + private Map<String, XSDocumentInfo> fUnparsedAttributeGroupRegistrySub = new HashMap(); + private Map<String, XSDocumentInfo> fUnparsedElementRegistrySub = new HashMap(); + private Map<String, XSDocumentInfo> fUnparsedGroupRegistrySub = new HashMap(); + private Map<String, XSDocumentInfo> fUnparsedIdentityConstraintRegistrySub = new HashMap(); + private Map<String, XSDocumentInfo> fUnparsedNotationRegistrySub = new HashMap(); + private Map<String, XSDocumentInfo> fUnparsedTypeRegistrySub = new HashMap(); + + // Stores XSDocumentInfo (keyed by component name), to check for duplicate + // components declared within the same xsd document + private Map fUnparsedRegistriesExt[] = new HashMap[] { + null, + null, // ATTRIBUTE_TYPE + null, // ATTRIBUTEGROUP_TYPE + null, // ELEMENT_TYPE + null, // GROUP_TYPE + null, // IDENTITYCONSTRAINT_TYPE + null, // NOTATION_TYPE + null, // TYPEDECL_TYPE + }; + + // this hashtable is keyed on by XSDocumentInfo objects. Its values + // are Vectors containing the XSDocumentInfo objects <include>d, + // <import>ed or <redefine>d by the key XSDocumentInfo. + private Map<XSDocumentInfo, Vector> fDependencyMap = new HashMap(); + + // this hashtable is keyed on by a target namespace. Its values + // are Vectors containing namespaces imported by schema documents + // with the key target namespace. + // if an imprted schema has absent namespace, the value "null" is stored. + private Map<String, Vector> fImportMap = new HashMap(); + // all namespaces that imports other namespaces + // if the importing schema has absent namespace, empty string is stored. + // (because the key of a hashtable can't be null.) + private Vector fAllTNSs = new Vector(); + // stores instance document mappings between namespaces and schema hints + private Map fLocationPairs = null; + private static final Map EMPTY_TABLE = new HashMap(); + + // Records which nodes are hidden when the input is a DOMInputSource. + Hashtable fHiddenNodes = null; + + // convenience methods + private String null2EmptyString(String ns) { + return ns == null ? XMLSymbols.EMPTY_STRING : ns; + } + private String emptyString2Null(String ns) { + return ns == XMLSymbols.EMPTY_STRING ? null : ns; + } + // use Schema Element to lookup the SystemId. + private String doc2SystemId(Element ele) { + String documentURI = null; + /** + * REVISIT: Casting until DOM Level 3 interfaces are available. -- mrglavas + */ + if(ele.getOwnerDocument() instanceof com.sun.org.apache.xerces.internal.impl.xs.opti.SchemaDOM){ + documentURI = ((com.sun.org.apache.xerces.internal.impl.xs.opti.SchemaDOM) ele.getOwnerDocument()).getDocumentURI(); + } + return documentURI != null ? documentURI : (String) fDoc2SystemId.get(ele); + } + + // This vector stores strings which are combinations of the + // publicId and systemId of the inputSource corresponding to a + // schema document. This combination is used so that the user's + // EntityResolver can provide a consistent way of identifying a + // schema document that is included in multiple other schemas. + private Map fTraversed = new HashMap(); + + // this hashtable contains a mapping from Schema Element to its systemId + // this is useful to resolve a uri relative to the referring document + private Map fDoc2SystemId = new HashMap(); + + // the primary XSDocumentInfo we were called to parse + private XSDocumentInfo fRoot = null; + + // This hashtable's job is to act as a link between the Schema Element and its + // XSDocumentInfo object. + private Map fDoc2XSDocumentMap = new HashMap(); + + // map between <redefine> elements and the XSDocumentInfo + // objects that correspond to the documents being redefined. + private Map fRedefine2XSDMap = null; + + // map between <redefine> elements and the namespace support + private Map fRedefine2NSSupport = null; + + // these objects store a mapping between the names of redefining + // groups/attributeGroups and the groups/AttributeGroups which + // they redefine by restriction (implicitly). It is up to the + // Group and AttributeGroup traversers to check these restrictions for + // validity. + private Map fRedefinedRestrictedAttributeGroupRegistry = new HashMap(); + private Map fRedefinedRestrictedGroupRegistry = new HashMap(); + + // a variable storing whether the last schema document + // processed (by getSchema) was a duplicate. + private boolean fLastSchemaWasDuplicate; + + // validate annotations feature + private boolean fValidateAnnotations = false; + + //handle multiple import feature + private boolean fHonourAllSchemaLocations = false; + + //handle namespace growth feature + boolean fNamespaceGrowth = false; + + // handle tolerate duplicates feature + boolean fTolerateDuplicates = false; + + // the XMLErrorReporter + private XMLErrorReporter fErrorReporter; + private XMLEntityResolver fEntityResolver; + + // the XSAttributeChecker + private XSAttributeChecker fAttributeChecker; + + // the symbol table + private SymbolTable fSymbolTable; + + // the GrammarResolver + private XSGrammarBucket fGrammarBucket; + + // the Grammar description + private XSDDescription fSchemaGrammarDescription; + + // the Grammar Pool + private XMLGrammarPool fGrammarPool; + + //************ Traversers ********** + XSDAttributeGroupTraverser fAttributeGroupTraverser; + XSDAttributeTraverser fAttributeTraverser; + XSDComplexTypeTraverser fComplexTypeTraverser; + XSDElementTraverser fElementTraverser; + XSDGroupTraverser fGroupTraverser; + XSDKeyrefTraverser fKeyrefTraverser; + XSDNotationTraverser fNotationTraverser; + XSDSimpleTypeTraverser fSimpleTypeTraverser; + XSDUniqueOrKeyTraverser fUniqueOrKeyTraverser; + XSDWildcardTraverser fWildCardTraverser; + + SchemaDVFactory fDVFactory; + SchemaDOMParser fSchemaParser; + SchemaContentHandler fXSContentHandler; + StAXSchemaParser fStAXSchemaParser; + XML11Configuration fAnnotationValidator; + XSAnnotationGrammarPool fGrammarBucketAdapter; + + // these data members are needed for the deferred traversal + // of local elements. + + // the initial size of the array to store deferred local elements + private static final int INIT_STACK_SIZE = 30; + // the incremental size of the array to store deferred local elements + private static final int INC_STACK_SIZE = 10; + // current position of the array (# of deferred local elements) + private int fLocalElemStackPos = 0; + + private XSParticleDecl[] fParticle = new XSParticleDecl[INIT_STACK_SIZE]; + private Element[] fLocalElementDecl = new Element[INIT_STACK_SIZE]; + private XSDocumentInfo[] fLocalElementDecl_schema = new XSDocumentInfo[INIT_STACK_SIZE]; //JACK + private int[] fAllContext = new int[INIT_STACK_SIZE]; + private XSObject[] fParent = new XSObject[INIT_STACK_SIZE]; + private String [][] fLocalElemNamespaceContext = new String [INIT_STACK_SIZE][1]; + + // these data members are needed for the deferred traversal + // of keyrefs. + + // the initial size of the array to store deferred keyrefs + private static final int INIT_KEYREF_STACK = 2; + // the incremental size of the array to store deferred keyrefs + private static final int INC_KEYREF_STACK_AMOUNT = 2; + // current position of the array (# of deferred keyrefs) + private int fKeyrefStackPos = 0; + + private Element [] fKeyrefs = new Element[INIT_KEYREF_STACK]; + private XSDocumentInfo [] fKeyrefsMapXSDocumentInfo = new XSDocumentInfo[INIT_KEYREF_STACK]; + private XSElementDecl [] fKeyrefElems = new XSElementDecl [INIT_KEYREF_STACK]; + private String [][] fKeyrefNamespaceContext = new String[INIT_KEYREF_STACK][1]; + + // global decls: map from decl name to decl object + SymbolHash fGlobalAttrDecls = new SymbolHash(); + SymbolHash fGlobalAttrGrpDecls = new SymbolHash(); + SymbolHash fGlobalElemDecls = new SymbolHash(); + SymbolHash fGlobalGroupDecls = new SymbolHash(); + SymbolHash fGlobalNotationDecls = new SymbolHash(); + SymbolHash fGlobalIDConstraintDecls = new SymbolHash(); + SymbolHash fGlobalTypeDecls = new SymbolHash(); + + // Constructors + public XSDHandler(){ + fHiddenNodes = new Hashtable(); + fSchemaParser = new SchemaDOMParser(new SchemaParsingConfig()); + } + + // it should be possible to use the same XSDHandler to parse + // multiple schema documents; this will allow one to be + // constructed. + public XSDHandler (XSGrammarBucket gBucket) { + this(); + fGrammarBucket = gBucket; + + // Note: don't use SchemaConfiguration internally + // we will get stack overflaw because + // XMLSchemaValidator will be instantiating XSDHandler... + fSchemaGrammarDescription = new XSDDescription(); + } // end constructor + + /** + * This method initiates the parse of a schema. It will likely be + * called from the Validator and it will make the + * resulting grammar available; it returns a reference to this object just + * in case. A reset(XMLComponentManager) must be called before this methods is called. + * @param is + * @param desc + * @param locationPairs + * @return the SchemaGrammar + * @throws IOException + */ + public SchemaGrammar parseSchema(XMLInputSource is, XSDDescription desc, + Map locationPairs) + throws IOException { + fLocationPairs = locationPairs; + fSchemaParser.resetNodePool(); + SchemaGrammar grammar = null; + String schemaNamespace = null; + short referType = desc.getContextType(); + + // if loading using JAXP schemaSource property, or using grammar caching loadGrammar + // the desc.targetNamespace is always null. + // Therefore we should not attempt to find out if + // the schema is already in the bucket, since in the case we have + // no namespace schema in the bucket, findGrammar will always return the + // no namespace schema. + if (referType != XSDDescription.CONTEXT_PREPARSE){ + // first try to find it in the bucket/pool, return if one is found + if (fHonourAllSchemaLocations && referType == XSDDescription.CONTEXT_IMPORT && isExistingGrammar(desc, fNamespaceGrowth)) { + grammar = fGrammarBucket.getGrammar(desc.getTargetNamespace()); + } + else { + grammar = findGrammar(desc, fNamespaceGrowth); + } + if (grammar != null) { + if (!fNamespaceGrowth) { + return grammar; + } + else { + try { + if (grammar.getDocumentLocations().contains(XMLEntityManager.expandSystemId(is.getSystemId(), is.getBaseSystemId(), false))) { + return grammar; + } + } + catch (MalformedURIException e) { + //REVISIT: return the grammar? + } + } + } + + schemaNamespace = desc.getTargetNamespace(); + // handle empty string URI as null + if (schemaNamespace != null) { + schemaNamespace = fSymbolTable.addSymbol(schemaNamespace); + } + } + + // before parsing a schema, need to clear registries associated with + // parsing schemas + prepareForParse(); + + Element schemaRoot = null; + // first phase: construct trees. + if (is instanceof DOMInputSource) { + schemaRoot = getSchemaDocument(schemaNamespace, (DOMInputSource) is, + referType == XSDDescription.CONTEXT_PREPARSE, + referType, null); + } // DOMInputSource + else if (is instanceof SAXInputSource) { + schemaRoot = getSchemaDocument(schemaNamespace, (SAXInputSource) is, + referType == XSDDescription.CONTEXT_PREPARSE, + referType, null); + } // SAXInputSource + else if (is instanceof StAXInputSource) { + schemaRoot = getSchemaDocument(schemaNamespace, (StAXInputSource) is, + referType == XSDDescription.CONTEXT_PREPARSE, + referType, null); + } // StAXInputSource + else if (is instanceof XSInputSource) { + schemaRoot = getSchemaDocument((XSInputSource) is, desc); + } // XSInputSource + else { + schemaRoot = getSchemaDocument(schemaNamespace, is, + referType == XSDDescription.CONTEXT_PREPARSE, + referType, null); + + } //is instanceof XMLInputSource + + if (schemaRoot == null) { + // something went wrong right off the hop + if (is instanceof XSInputSource) { + return fGrammarBucket.getGrammar(desc.getTargetNamespace()); + } + return grammar; + } + + if (referType == XSDDescription.CONTEXT_PREPARSE) { + Element schemaElem = schemaRoot; + schemaNamespace = DOMUtil.getAttrValue(schemaElem, SchemaSymbols.ATT_TARGETNAMESPACE); + if(schemaNamespace != null && schemaNamespace.length() > 0) { + // Since now we've discovered a namespace, we need to update xsd key + // and store this schema in traversed schemas bucket + schemaNamespace = fSymbolTable.addSymbol(schemaNamespace); + desc.setTargetNamespace(schemaNamespace); + } + else { + schemaNamespace = null; + } + grammar = findGrammar(desc, fNamespaceGrowth); + String schemaId = XMLEntityManager.expandSystemId(is.getSystemId(), is.getBaseSystemId(), false); + if (grammar != null) { + // When namespace growth is enabled and a null location is provided we cannot tell + // whether we've loaded this schema document before so we must assume that we haven't. + if (!fNamespaceGrowth || (schemaId != null && grammar.getDocumentLocations().contains(schemaId))) { + return grammar; + } + } + + XSDKey key = new XSDKey(schemaId, referType, schemaNamespace); + fTraversed.put(key, schemaRoot); + if (schemaId != null) { + fDoc2SystemId.put(schemaRoot, schemaId); + } + } + + // before constructing trees and traversing a schema, need to reset + // all traversers and clear all registries + prepareForTraverse(); + + fRoot = constructTrees(schemaRoot, is.getSystemId(), desc, grammar != null); + if (fRoot == null) { + return null; + } + + // second phase: fill global registries. + buildGlobalNameRegistries(); + + // third phase: call traversers + ArrayList annotationInfo = fValidateAnnotations ? new ArrayList() : null; + traverseSchemas(annotationInfo); + + // fourth phase: handle local element decls + traverseLocalElements(); + + // fifth phase: handle Keyrefs + resolveKeyRefs(); + + // sixth phase: validate attribute of non-schema namespaces + // REVISIT: skip this for now. we really don't want to do it. + //fAttributeChecker.checkNonSchemaAttributes(fGrammarBucket); + + // seventh phase: store imported grammars + // for all grammars with <import>s + for (int i = fAllTNSs.size() - 1; i >= 0; i--) { + // get its target namespace + String tns = (String)fAllTNSs.elementAt(i); + // get all namespaces it imports + Vector ins = (Vector)fImportMap.get(tns); + // get the grammar + SchemaGrammar sg = fGrammarBucket.getGrammar(emptyString2Null(tns)); + if (sg == null) + continue; + SchemaGrammar isg; + // for imported namespace + int count = 0; + for (int j = 0; j < ins.size(); j++) { + // get imported grammar + isg = fGrammarBucket.getGrammar((String)ins.elementAt(j)); + // reuse the same vector + if (isg != null) + ins.setElementAt(isg, count++); + } + ins.setSize(count); + // set the imported grammars + sg.setImportedGrammars(ins); + } + + /** validate annotations **/ + if (fValidateAnnotations && annotationInfo.size() > 0) { + validateAnnotations(annotationInfo); + } + + // and return. + return fGrammarBucket.getGrammar(fRoot.fTargetNamespace); + } // end parseSchema + + private void validateAnnotations(ArrayList annotationInfo) { + if (fAnnotationValidator == null) { + createAnnotationValidator(); + } + final int size = annotationInfo.size(); + final XMLInputSource src = new XMLInputSource(null, null, null); + fGrammarBucketAdapter.refreshGrammars(fGrammarBucket); + for (int i = 0; i < size; i += 2) { + src.setSystemId((String) annotationInfo.get(i)); + XSAnnotationInfo annotation = (XSAnnotationInfo) annotationInfo.get(i+1); + while (annotation != null) { + src.setCharacterStream(new StringReader(annotation.fAnnotation)); + try { + fAnnotationValidator.parse(src); + } + catch (IOException exc) {} + annotation = annotation.next; + } + } + } + + private void createAnnotationValidator() { + fAnnotationValidator = new XML11Configuration(); + fGrammarBucketAdapter = new XSAnnotationGrammarPool(); + fAnnotationValidator.setFeature(VALIDATION, true); + fAnnotationValidator.setFeature(XMLSCHEMA_VALIDATION, true); + fAnnotationValidator.setProperty(XMLGRAMMAR_POOL, fGrammarBucketAdapter); + /** Set error handler. **/ + XMLErrorHandler errorHandler = fErrorReporter.getErrorHandler(); + fAnnotationValidator.setProperty(ERROR_HANDLER, (errorHandler != null) ? errorHandler : new DefaultErrorHandler()); + /** Set locale. **/ + Locale locale = fErrorReporter.getLocale(); + fAnnotationValidator.setProperty(LOCALE, locale); + } + + /** + * Pull the grammar out of the bucket simply using + * its TNS as a key + */ + SchemaGrammar getGrammar(String tns) { + return fGrammarBucket.getGrammar(tns); + } + + /** + * First try to find a grammar in the bucket, if failed, consult the + * grammar pool. If a grammar is found in the pool, then add it (and all + * imported ones) into the bucket. + */ + protected SchemaGrammar findGrammar(XSDDescription desc, boolean ignoreConflict) { + SchemaGrammar sg = fGrammarBucket.getGrammar(desc.getTargetNamespace()); + if (sg == null) { + if (fGrammarPool != null) { + sg = (SchemaGrammar)fGrammarPool.retrieveGrammar(desc); + if (sg != null) { + // put this grammar into the bucket, along with grammars + // imported by it (directly or indirectly) + if (!fGrammarBucket.putGrammar(sg, true, ignoreConflict)) { + // REVISIT: a conflict between new grammar(s) and grammars + // in the bucket. What to do? A warning? An exception? + reportSchemaWarning("GrammarConflict", null, null); + sg = null; + } + } + } + } + return sg; + } + + // may wish to have setter methods for ErrorHandler, + // EntityResolver... + + private static final String[][] NS_ERROR_CODES = { + {"src-include.2.1", "src-include.2.1"}, + {"src-redefine.3.1", "src-redefine.3.1"}, + {"src-import.3.1", "src-import.3.2"}, + null, + {"TargetNamespace.1", "TargetNamespace.2"}, + {"TargetNamespace.1", "TargetNamespace.2"}, + {"TargetNamespace.1", "TargetNamespace.2"}, + {"TargetNamespace.1", "TargetNamespace.2"} + }; + + private static final String[] ELE_ERROR_CODES = { + "src-include.1", "src-redefine.2", "src-import.2", "schema_reference.4", + "schema_reference.4", "schema_reference.4", "schema_reference.4", "schema_reference.4" + }; + + // This method does several things: + // It constructs an instance of an XSDocumentInfo object using the + // schemaRoot node. Then, for each <include>, + // <redefine>, and <import> children, it attempts to resolve the + // requested schema document, initiates a DOM parse, and calls + // itself recursively on that document's root. It also records in + // the DependencyMap object what XSDocumentInfo objects its XSDocumentInfo + // depends on. + // It also makes sure the targetNamespace of the schema it was + // called to parse is correct. + protected XSDocumentInfo constructTrees(Element schemaRoot, String locationHint, XSDDescription desc, boolean nsCollision) { + if (schemaRoot == null) return null; + String callerTNS = desc.getTargetNamespace(); + short referType = desc.getContextType(); + + XSDocumentInfo currSchemaInfo = null; + try { + // note that attributes are freed at end of traverseSchemas() + currSchemaInfo = new XSDocumentInfo(schemaRoot, fAttributeChecker, fSymbolTable); + } catch (XMLSchemaException se) { + reportSchemaError(ELE_ERROR_CODES[referType], + new Object[]{locationHint}, + schemaRoot); + return null; + } + // targetNamespace="" is not valid, issue a warning, and ignore it + if (currSchemaInfo.fTargetNamespace != null && + currSchemaInfo.fTargetNamespace.length() == 0) { + reportSchemaWarning("EmptyTargetNamespace", + new Object[]{locationHint}, + schemaRoot); + currSchemaInfo.fTargetNamespace = null; + } + + if (callerTNS != null) { + // the second index to the NS_ERROR_CODES array + // if the caller/expected NS is not absent, we use the first column + int secondIdx = 0; + // for include and redefine + if (referType == XSDDescription.CONTEXT_INCLUDE || + referType == XSDDescription.CONTEXT_REDEFINE) { + // if the referred document has no targetNamespace, + // it's a chameleon schema + if (currSchemaInfo.fTargetNamespace == null) { + currSchemaInfo.fTargetNamespace = callerTNS; + currSchemaInfo.fIsChameleonSchema = true; + } + // if the referred document has a target namespace differing + // from the caller, it's an error + else if (callerTNS != currSchemaInfo.fTargetNamespace) { + reportSchemaError(NS_ERROR_CODES[referType][secondIdx], + new Object [] {callerTNS, currSchemaInfo.fTargetNamespace}, + schemaRoot); + return null; + } + } + // for instance and import, the two NS's must be the same + else if (referType != XSDDescription.CONTEXT_PREPARSE && callerTNS != currSchemaInfo.fTargetNamespace) { + reportSchemaError(NS_ERROR_CODES[referType][secondIdx], + new Object [] {callerTNS, currSchemaInfo.fTargetNamespace}, + schemaRoot); + return null; + } + } + // now there is no caller/expected NS, it's an error for the referred + // document to have a target namespace, unless we are preparsing a schema + else if (currSchemaInfo.fTargetNamespace != null) { + // set the target namespace of the description + if (referType == XSDDescription.CONTEXT_PREPARSE) { + desc.setTargetNamespace(currSchemaInfo.fTargetNamespace); + callerTNS = currSchemaInfo.fTargetNamespace; + } + else { + // the second index to the NS_ERROR_CODES array + // if the caller/expected NS is absent, we use the second column + int secondIdx = 1; + reportSchemaError(NS_ERROR_CODES[referType][secondIdx], + new Object [] {callerTNS, currSchemaInfo.fTargetNamespace}, + schemaRoot); + return null; + } + } + // the other cases (callerTNS == currSchemaInfo.fTargetNamespce == null) + // are valid + + // a schema document can always access it's own target namespace + currSchemaInfo.addAllowedNS(currSchemaInfo.fTargetNamespace); + + SchemaGrammar sg = null; + + // we have a namespace collision + if (nsCollision) { + SchemaGrammar sg2 = fGrammarBucket.getGrammar(currSchemaInfo.fTargetNamespace); + if (sg2.isImmutable()) { + sg = new SchemaGrammar(sg2); + fGrammarBucket.putGrammar(sg); + // update all the grammars in the bucket to point to the new grammar. + updateImportListWith(sg); + } + else { + sg = sg2; + } + + // update import list of the new grammar + updateImportListFor(sg); + } + else if (referType == XSDDescription.CONTEXT_INCLUDE || + referType == XSDDescription.CONTEXT_REDEFINE) { + sg = fGrammarBucket.getGrammar(currSchemaInfo.fTargetNamespace); + } + else if(fHonourAllSchemaLocations && referType == XSDDescription.CONTEXT_IMPORT) { + sg = findGrammar(desc, false); + if(sg == null) { + sg = new SchemaGrammar(currSchemaInfo.fTargetNamespace, desc.makeClone(), fSymbolTable); + fGrammarBucket.putGrammar(sg); + } + } + else { + sg = new SchemaGrammar(currSchemaInfo.fTargetNamespace, desc.makeClone(), fSymbolTable); + fGrammarBucket.putGrammar(sg); + } + + // store the document and its location + // REVISIT: don't expose the DOM tree + sg.addDocument(null, (String)fDoc2SystemId.get(currSchemaInfo.fSchemaElement)); + + fDoc2XSDocumentMap.put(schemaRoot, currSchemaInfo); + Vector dependencies = new Vector(); + Element rootNode = schemaRoot; + + Element newSchemaRoot = null; + for (Element child = DOMUtil.getFirstChildElement(rootNode); + child != null; + child = DOMUtil.getNextSiblingElement(child)) { + String schemaNamespace=null; + String schemaHint=null; + String localName = DOMUtil.getLocalName(child); + + short refType = -1; + boolean importCollision = false; + + if (localName.equals(SchemaSymbols.ELT_ANNOTATION)) + continue; + else if (localName.equals(SchemaSymbols.ELT_IMPORT)) { + refType = XSDDescription.CONTEXT_IMPORT; + // have to handle some validation here too! + // call XSAttributeChecker to fill in attrs + Object[] importAttrs = fAttributeChecker.checkAttributes(child, true, currSchemaInfo); + schemaHint = (String)importAttrs[XSAttributeChecker.ATTIDX_SCHEMALOCATION]; + schemaNamespace = (String)importAttrs[XSAttributeChecker.ATTIDX_NAMESPACE]; + if (schemaNamespace != null) + schemaNamespace = fSymbolTable.addSymbol(schemaNamespace); + + // check contents and process optional annotations + Element importChild = DOMUtil.getFirstChildElement(child); + if(importChild != null ) { + String importComponentType = DOMUtil.getLocalName(importChild); + if (importComponentType.equals(SchemaSymbols.ELT_ANNOTATION)) { + // promoting annotations to parent component + sg.addAnnotation( + fElementTraverser.traverseAnnotationDecl(importChild, importAttrs, true, currSchemaInfo)); + } else { + reportSchemaError("s4s-elt-must-match.1", new Object [] {localName, "annotation?", importComponentType}, child); + } + if(DOMUtil.getNextSiblingElement(importChild) != null) { + reportSchemaError("s4s-elt-must-match.1", new Object [] {localName, "annotation?", DOMUtil.getLocalName(DOMUtil.getNextSiblingElement(importChild))}, child); + } + } + else { + String text = DOMUtil.getSyntheticAnnotation(child); + if (text != null) { + sg.addAnnotation(fElementTraverser.traverseSyntheticAnnotation(child, text, importAttrs, true, currSchemaInfo)); + } + } + fAttributeChecker.returnAttrArray(importAttrs, currSchemaInfo); + + // a document can't import another document with the same namespace + if (schemaNamespace == currSchemaInfo.fTargetNamespace) { + reportSchemaError(schemaNamespace != null ? + "src-import.1.1" : "src-import.1.2", new Object [] {schemaNamespace}, child); + continue; + } + + // if this namespace has not been imported by this document, + // then import if multiple imports support is enabled. + if(currSchemaInfo.isAllowedNS(schemaNamespace)) { + if(!fHonourAllSchemaLocations && !fNamespaceGrowth) + continue; + } + else { + currSchemaInfo.addAllowedNS(schemaNamespace); + } + // also record the fact that one namespace imports another one + // convert null to "" + String tns = null2EmptyString(currSchemaInfo.fTargetNamespace); + // get all namespaces imported by this one + Vector ins = (Vector)fImportMap.get(tns); + // if no namespace was imported, create new Vector + if (ins == null) { + // record that this one imports other(s) + fAllTNSs.addElement(tns); + ins = new Vector(); + fImportMap.put(tns, ins); + ins.addElement(schemaNamespace); + } + else if (!ins.contains(schemaNamespace)){ + ins.addElement(schemaNamespace); + } + + fSchemaGrammarDescription.reset(); + fSchemaGrammarDescription.setContextType(XSDDescription.CONTEXT_IMPORT); + fSchemaGrammarDescription.setBaseSystemId(doc2SystemId(schemaRoot)); + fSchemaGrammarDescription.setLiteralSystemId(schemaHint); + fSchemaGrammarDescription.setLocationHints(new String[]{schemaHint}); + fSchemaGrammarDescription.setTargetNamespace(schemaNamespace); + + // if a grammar with the same namespace and location exists (or being + // built), ignore this one (don't traverse it). + SchemaGrammar isg = findGrammar(fSchemaGrammarDescription, fNamespaceGrowth); + if (isg != null) { + if (fNamespaceGrowth) { + try { + if (isg.getDocumentLocations().contains(XMLEntityManager.expandSystemId(schemaHint, fSchemaGrammarDescription.getBaseSystemId(), false))) { + continue; + } + else { + importCollision = true; + } + } + catch (MalformedURIException e) { + } + } + else if (!fHonourAllSchemaLocations || isExistingGrammar(fSchemaGrammarDescription, false)) { + continue; + } + } + //if ((!fHonourAllSchemaLocations && findGrammar(fSchemaGrammarDescription) != null) || isExistingGrammar(fSchemaGrammarDescription)) + // continue; + + // If "findGrammar" returns a grammar, then this is not the + // the first time we see a location for a given namespace. + // Don't consult the location pair hashtable in this case, + // otherwise the location will be ignored because it'll get + // resolved to the same location as the first hint. + newSchemaRoot = resolveSchema(fSchemaGrammarDescription, false, child, isg == null); + } + else if ((localName.equals(SchemaSymbols.ELT_INCLUDE)) || + (localName.equals(SchemaSymbols.ELT_REDEFINE))) { + // validation for redefine/include will be the same here; just + // make sure TNS is right (don't care about redef contents + // yet). + Object[] includeAttrs = fAttributeChecker.checkAttributes(child, true, currSchemaInfo); + schemaHint = (String)includeAttrs[XSAttributeChecker.ATTIDX_SCHEMALOCATION]; + // store the namespace decls of the redefine element + if (localName.equals(SchemaSymbols.ELT_REDEFINE)) { + if (fRedefine2NSSupport == null) fRedefine2NSSupport = new HashMap(); + fRedefine2NSSupport.put(child, new SchemaNamespaceSupport(currSchemaInfo.fNamespaceSupport)); + } + + // check annotations. Must do this here to avoid having to + // re-parse attributes later + if(localName.equals(SchemaSymbols.ELT_INCLUDE)) { + Element includeChild = DOMUtil.getFirstChildElement(child); + if(includeChild != null ) { + String includeComponentType = DOMUtil.getLocalName(includeChild); + if (includeComponentType.equals(SchemaSymbols.ELT_ANNOTATION)) { + // promoting annotations to parent component + sg.addAnnotation( + fElementTraverser.traverseAnnotationDecl(includeChild, includeAttrs, true, currSchemaInfo)); + } else { + reportSchemaError("s4s-elt-must-match.1", new Object [] {localName, "annotation?", includeComponentType}, child); + } + if(DOMUtil.getNextSiblingElement(includeChild) != null) { + reportSchemaError("s4s-elt-must-match.1", new Object [] {localName, "annotation?", DOMUtil.getLocalName(DOMUtil.getNextSiblingElement(includeChild))}, child); + } + } + else { + String text = DOMUtil.getSyntheticAnnotation(child); + if (text != null) { + sg.addAnnotation(fElementTraverser.traverseSyntheticAnnotation(child, text, includeAttrs, true, currSchemaInfo)); + } + } + } + else { + for (Element redefinedChild = DOMUtil.getFirstChildElement(child); + redefinedChild != null; + redefinedChild = DOMUtil.getNextSiblingElement(redefinedChild)) { + String redefinedComponentType = DOMUtil.getLocalName(redefinedChild); + if (redefinedComponentType.equals(SchemaSymbols.ELT_ANNOTATION)) { + // promoting annotations to parent component + sg.addAnnotation( + fElementTraverser.traverseAnnotationDecl(redefinedChild, includeAttrs, true, currSchemaInfo)); + DOMUtil.setHidden(redefinedChild, fHiddenNodes); + } + else { + String text = DOMUtil.getSyntheticAnnotation(child); + if (text != null) { + sg.addAnnotation(fElementTraverser.traverseSyntheticAnnotation(child, text, includeAttrs, true, currSchemaInfo)); + } + } + // catch all other content errors later + } + } + fAttributeChecker.returnAttrArray(includeAttrs, currSchemaInfo); + // schemaLocation is required on <include> and <redefine> + if (schemaHint == null) { + reportSchemaError("s4s-att-must-appear", new Object [] { + "<include> or <redefine>", "schemaLocation"}, + child); + } + // pass the systemId of the current document as the base systemId + boolean mustResolve = false; + refType = XSDDescription.CONTEXT_INCLUDE; + if(localName.equals(SchemaSymbols.ELT_REDEFINE)) { + mustResolve = nonAnnotationContent(child); + refType = XSDDescription.CONTEXT_REDEFINE; + } + fSchemaGrammarDescription.reset(); + fSchemaGrammarDescription.setContextType(refType); + fSchemaGrammarDescription.setBaseSystemId(doc2SystemId(schemaRoot)); + fSchemaGrammarDescription.setLocationHints(new String[]{schemaHint}); + fSchemaGrammarDescription.setTargetNamespace(callerTNS); + + boolean alreadyTraversed = false; + XMLInputSource schemaSource = resolveSchemaSource(fSchemaGrammarDescription, mustResolve, child, true); + if (fNamespaceGrowth && refType == XSDDescription.CONTEXT_INCLUDE) { + try { + final String schemaId = XMLEntityManager.expandSystemId(schemaSource.getSystemId(), schemaSource.getBaseSystemId(), false); + alreadyTraversed = sg.getDocumentLocations().contains(schemaId); + } + catch(MalformedURIException e) { + + } + } + + if (!alreadyTraversed) { + newSchemaRoot = resolveSchema(schemaSource, fSchemaGrammarDescription, mustResolve, child); + schemaNamespace = currSchemaInfo.fTargetNamespace; + } + else { + fLastSchemaWasDuplicate = true; + } + } + else { + // no more possibility of schema references in well-formed + // schema... + break; + } + + // If the schema is duplicate, we needn't call constructTrees() again. + // To handle mutual <include>s + XSDocumentInfo newSchemaInfo = null; + if (fLastSchemaWasDuplicate) { + newSchemaInfo = newSchemaRoot == null ? null : (XSDocumentInfo)fDoc2XSDocumentMap.get(newSchemaRoot); + } + else { + newSchemaInfo = constructTrees(newSchemaRoot, schemaHint, fSchemaGrammarDescription, importCollision); + } + + if (localName.equals(SchemaSymbols.ELT_REDEFINE) && + newSchemaInfo != null) { + // must record which schema we're redefining so that we can + // rename the right things later! + if (fRedefine2XSDMap == null) fRedefine2XSDMap = new HashMap(); + fRedefine2XSDMap.put(child, newSchemaInfo); + } + if (newSchemaRoot != null) { + if (newSchemaInfo != null) + dependencies.addElement(newSchemaInfo); + newSchemaRoot = null; + } + } + + fDependencyMap.put(currSchemaInfo, dependencies); + return currSchemaInfo; + } // end constructTrees + + private boolean isExistingGrammar(XSDDescription desc, boolean ignoreConflict) { + SchemaGrammar sg = fGrammarBucket.getGrammar(desc.getTargetNamespace()); + if (sg == null) { + return findGrammar(desc, ignoreConflict) != null; + } + else if (sg.isImmutable()) { + return true; + } + else { + try { + return sg.getDocumentLocations().contains(XMLEntityManager.expandSystemId(desc.getLiteralSystemId(), desc.getBaseSystemId(), false)); + } + catch (MalformedURIException e) { + return false; + } + } + } + + /** + * Namespace growth + * + * Go through the import list of a given grammar and for each imported + * grammar, check to see if the grammar bucket has a newer version. + * If a new instance is found, we update the import list with the + * newer version. + */ + private void updateImportListFor(SchemaGrammar grammar) { + Vector importedGrammars = grammar.getImportedGrammars(); + if (importedGrammars != null) { + for (int i=0; i<importedGrammars.size(); i++) { + SchemaGrammar isg1 = (SchemaGrammar) importedGrammars.elementAt(i); + SchemaGrammar isg2 = fGrammarBucket.getGrammar(isg1.getTargetNamespace()); + if (isg2 != null && isg1 != isg2) { + importedGrammars.set(i, isg2); + } + } + } + } + + /** + * Namespace growth + * + * Go throuth the grammar bucket, and for each grammar in the bucket + * check the import list. If there exists a grammar in import list + * that has the same namespace as newGrammar, but a different instance, + * then update the import list and replace the old grammar instance with + * the new one + */ + private void updateImportListWith(SchemaGrammar newGrammar) { + SchemaGrammar[] schemaGrammars = fGrammarBucket.getGrammars(); + for (int i = 0; i < schemaGrammars.length; ++i) { + SchemaGrammar sg = schemaGrammars[i]; + if (sg != newGrammar) { + Vector importedGrammars = sg.getImportedGrammars(); + if (importedGrammars != null) { + for (int j=0; j<importedGrammars.size(); j++) { + SchemaGrammar isg = (SchemaGrammar) importedGrammars.elementAt(j); + if (null2EmptyString(isg.getTargetNamespace()).equals(null2EmptyString(newGrammar.getTargetNamespace()))) { + if (isg != newGrammar) { + importedGrammars.set(j, newGrammar); + } + break; + } + } + } + } + } + } + + // This method builds registries for all globally-referenceable + // names. A registry will be built for each symbol space defined + // by the spec. It is also this method's job to rename redefined + // components, and to record which components redefine others (so + // that implicit redefinitions of groups and attributeGroups can be handled). + protected void buildGlobalNameRegistries() { + + registryEmpty = false; + // Starting with fRoot, we examine each child of the schema + // element. Skipping all imports and includes, we record the names + // of all other global components (and children of <redefine>). We + // also put <redefine> names in a registry that we look through in + // case something needs renaming. Once we're done with a schema we + // set its Document node to hidden so that we don't try to traverse + // it again; then we look to its Dependency map entry. We keep a + // stack of schemas that we haven't yet finished processing; this + // is a depth-first traversal. + + Stack schemasToProcess = new Stack(); + schemasToProcess.push(fRoot); + + while (!schemasToProcess.empty()) { + XSDocumentInfo currSchemaDoc = + (XSDocumentInfo)schemasToProcess.pop(); + Element currDoc = currSchemaDoc.fSchemaElement; + if(DOMUtil.isHidden(currDoc, fHiddenNodes)){ + // must have processed this already! + continue; + } + + Element currRoot = currDoc; + // process this schema's global decls + boolean dependenciesCanOccur = true; + for (Element globalComp = + DOMUtil.getFirstChildElement(currRoot); + globalComp != null; + globalComp = DOMUtil.getNextSiblingElement(globalComp)) { + // this loop makes sure the <schema> element ordering is + // also valid. + if (DOMUtil.getLocalName(globalComp).equals(SchemaSymbols.ELT_ANNOTATION)) { + //skip it; traverse it later + continue; + } + else if (DOMUtil.getLocalName(globalComp).equals(SchemaSymbols.ELT_INCLUDE) || + DOMUtil.getLocalName(globalComp).equals(SchemaSymbols.ELT_IMPORT)) { + if (!dependenciesCanOccur) { + reportSchemaError("s4s-elt-invalid-content.3", new Object [] {DOMUtil.getLocalName(globalComp)}, globalComp); + } + DOMUtil.setHidden(globalComp, fHiddenNodes); + } + else if (DOMUtil.getLocalName(globalComp).equals(SchemaSymbols.ELT_REDEFINE)) { + if (!dependenciesCanOccur) { + reportSchemaError("s4s-elt-invalid-content.3", new Object [] {DOMUtil.getLocalName(globalComp)}, globalComp); + } + for (Element redefineComp = DOMUtil.getFirstChildElement(globalComp); + redefineComp != null; + redefineComp = DOMUtil.getNextSiblingElement(redefineComp)) { + String lName = DOMUtil.getAttrValue(redefineComp, SchemaSymbols.ATT_NAME); + if (lName.length() == 0) // an error we'll catch later + continue; + String qName = currSchemaDoc.fTargetNamespace == null ? + ","+lName: + currSchemaDoc.fTargetNamespace +","+lName; + String componentType = DOMUtil.getLocalName(redefineComp); + if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) { + checkForDuplicateNames(qName, ATTRIBUTEGROUP_TYPE, fUnparsedAttributeGroupRegistry, fUnparsedAttributeGroupRegistrySub, redefineComp, currSchemaDoc); + // the check will have changed our name; + String targetLName = DOMUtil.getAttrValue(redefineComp, SchemaSymbols.ATT_NAME)+REDEF_IDENTIFIER; + // and all we need to do is error-check+rename our kkids: + renameRedefiningComponents(currSchemaDoc, redefineComp, SchemaSymbols.ELT_ATTRIBUTEGROUP, + lName, targetLName); + } + else if ((componentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) || + (componentType.equals(SchemaSymbols.ELT_SIMPLETYPE))) { + checkForDuplicateNames(qName, TYPEDECL_TYPE, fUnparsedTypeRegistry, fUnparsedTypeRegistrySub, redefineComp, currSchemaDoc); + // the check will have changed our name; + String targetLName = DOMUtil.getAttrValue(redefineComp, SchemaSymbols.ATT_NAME) + REDEF_IDENTIFIER; + // and all we need to do is error-check+rename our kkids: + if (componentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) { + renameRedefiningComponents(currSchemaDoc, redefineComp, SchemaSymbols.ELT_COMPLEXTYPE, + lName, targetLName); + } + else { // must be simpleType + renameRedefiningComponents(currSchemaDoc, redefineComp, SchemaSymbols.ELT_SIMPLETYPE, + lName, targetLName); + } + } + else if (componentType.equals(SchemaSymbols.ELT_GROUP)) { + checkForDuplicateNames(qName, GROUP_TYPE, fUnparsedGroupRegistry, fUnparsedGroupRegistrySub, redefineComp, currSchemaDoc); + // the check will have changed our name; + String targetLName = DOMUtil.getAttrValue(redefineComp, SchemaSymbols.ATT_NAME)+REDEF_IDENTIFIER; + // and all we need to do is error-check+rename our kids: + renameRedefiningComponents(currSchemaDoc, redefineComp, SchemaSymbols.ELT_GROUP, + lName, targetLName); + } + } // end march through <redefine> children + // and now set as traversed + //DOMUtil.setHidden(globalComp); + } + else { + dependenciesCanOccur = false; + String lName = DOMUtil.getAttrValue(globalComp, SchemaSymbols.ATT_NAME); + if (lName.length() == 0) // an error we'll catch later + continue; + String qName = currSchemaDoc.fTargetNamespace == null? + ","+lName: + currSchemaDoc.fTargetNamespace +","+lName; + String componentType = DOMUtil.getLocalName(globalComp); + + if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTE)) { + checkForDuplicateNames(qName, ATTRIBUTE_TYPE, fUnparsedAttributeRegistry, fUnparsedAttributeRegistrySub, globalComp, currSchemaDoc); + } + else if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) { + checkForDuplicateNames(qName, ATTRIBUTEGROUP_TYPE, fUnparsedAttributeGroupRegistry, fUnparsedAttributeGroupRegistrySub, globalComp, currSchemaDoc); + } + else if ((componentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) || + (componentType.equals(SchemaSymbols.ELT_SIMPLETYPE))) { + checkForDuplicateNames(qName, TYPEDECL_TYPE, fUnparsedTypeRegistry, fUnparsedTypeRegistrySub, globalComp, currSchemaDoc); + } + else if (componentType.equals(SchemaSymbols.ELT_ELEMENT)) { + checkForDuplicateNames(qName, ELEMENT_TYPE, fUnparsedElementRegistry, fUnparsedElementRegistrySub, globalComp, currSchemaDoc); + } + else if (componentType.equals(SchemaSymbols.ELT_GROUP)) { + checkForDuplicateNames(qName, GROUP_TYPE, fUnparsedGroupRegistry, fUnparsedGroupRegistrySub, globalComp, currSchemaDoc); + } + else if (componentType.equals(SchemaSymbols.ELT_NOTATION)) { + checkForDuplicateNames(qName, NOTATION_TYPE, fUnparsedNotationRegistry, fUnparsedNotationRegistrySub, globalComp, currSchemaDoc); + } + } + } // end for + + // now we're done with this one! + DOMUtil.setHidden(currDoc, fHiddenNodes); + // now add the schemas this guy depends on + Vector currSchemaDepends = (Vector)fDependencyMap.get(currSchemaDoc); + for (int i = 0; i < currSchemaDepends.size(); i++) { + schemasToProcess.push(currSchemaDepends.elementAt(i)); + } + } // while + + } // end buildGlobalNameRegistries + + // Beginning at the first schema processing was requested for + // (fRoot), this method + // examines each child (global schema information item) of each + // schema document (and of each <redefine> element) + // corresponding to an XSDocumentInfo object. If the + // readOnly field on that node has not been set, it calls an + // appropriate traverser to traverse it. Once all global decls in + // an XSDocumentInfo object have been traversed, it marks that object + // as traversed (or hidden) in order to avoid infinite loops. It completes + // when it has visited all XSDocumentInfo objects in the + // DependencyMap and marked them as traversed. + protected void traverseSchemas(ArrayList annotationInfo) { + // the process here is very similar to that in + // buildGlobalRegistries, except we can't set our schemas as + // hidden for a second time; so make them all visible again + // first! + setSchemasVisible(fRoot); + Stack schemasToProcess = new Stack(); + schemasToProcess.push(fRoot); + while (!schemasToProcess.empty()) { + XSDocumentInfo currSchemaDoc = + (XSDocumentInfo)schemasToProcess.pop(); + Element currDoc = currSchemaDoc.fSchemaElement; + + SchemaGrammar currSG = fGrammarBucket.getGrammar(currSchemaDoc.fTargetNamespace); + + if(DOMUtil.isHidden(currDoc, fHiddenNodes)) { + // must have processed this already! + continue; + } + Element currRoot = currDoc; + boolean sawAnnotation = false; + // traverse this schema's global decls + for (Element globalComp = + DOMUtil.getFirstVisibleChildElement(currRoot, fHiddenNodes); + globalComp != null; + globalComp = DOMUtil.getNextVisibleSiblingElement(globalComp, fHiddenNodes)) { + DOMUtil.setHidden(globalComp, fHiddenNodes); + String componentType = DOMUtil.getLocalName(globalComp); + // includes and imports will not show up here! + if (DOMUtil.getLocalName(globalComp).equals(SchemaSymbols.ELT_REDEFINE)) { + // use the namespace decls for the redefine, instead of for the parent <schema> + currSchemaDoc.backupNSSupport((fRedefine2NSSupport!=null)?(SchemaNamespaceSupport)fRedefine2NSSupport.get(globalComp):null); + for (Element redefinedComp = DOMUtil.getFirstVisibleChildElement(globalComp, fHiddenNodes); + redefinedComp != null; + redefinedComp = DOMUtil.getNextVisibleSiblingElement(redefinedComp, fHiddenNodes)) { + String redefinedComponentType = DOMUtil.getLocalName(redefinedComp); + DOMUtil.setHidden(redefinedComp, fHiddenNodes); + if (redefinedComponentType.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) { + fAttributeGroupTraverser.traverseGlobal(redefinedComp, currSchemaDoc, currSG); + } + else if (redefinedComponentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) { + fComplexTypeTraverser.traverseGlobal(redefinedComp, currSchemaDoc, currSG); + } + else if (redefinedComponentType.equals(SchemaSymbols.ELT_GROUP)) { + fGroupTraverser.traverseGlobal(redefinedComp, currSchemaDoc, currSG); + } + else if (redefinedComponentType.equals(SchemaSymbols.ELT_SIMPLETYPE)) { + fSimpleTypeTraverser.traverseGlobal(redefinedComp, currSchemaDoc, currSG); + } + // annotations will have been processed already; this is now + // unnecessary + //else if (redefinedComponentType.equals(SchemaSymbols.ELT_ANNOTATION)) { + // fElementTraverser.traverseAnnotationDecl(redefinedComp, null, true, currSchemaDoc); + //} + else { + reportSchemaError("s4s-elt-must-match.1", new Object [] {DOMUtil.getLocalName(globalComp), "(annotation | (simpleType | complexType | group | attributeGroup))*", redefinedComponentType}, redefinedComp); + } + } // end march through <redefine> children + currSchemaDoc.restoreNSSupport(); + } + else if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTE)) { + fAttributeTraverser.traverseGlobal(globalComp, currSchemaDoc, currSG); + } + else if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) { + fAttributeGroupTraverser.traverseGlobal(globalComp, currSchemaDoc, currSG); + } + else if (componentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) { + fComplexTypeTraverser.traverseGlobal(globalComp, currSchemaDoc, currSG); + } + else if (componentType.equals(SchemaSymbols.ELT_ELEMENT)) { + fElementTraverser.traverseGlobal(globalComp, currSchemaDoc, currSG); + } + else if (componentType.equals(SchemaSymbols.ELT_GROUP)) { + fGroupTraverser.traverseGlobal(globalComp, currSchemaDoc, currSG); + } + else if (componentType.equals(SchemaSymbols.ELT_NOTATION)) { + fNotationTraverser.traverse(globalComp, currSchemaDoc, currSG); + } + else if (componentType.equals(SchemaSymbols.ELT_SIMPLETYPE)) { + fSimpleTypeTraverser.traverseGlobal(globalComp, currSchemaDoc, currSG); + } + else if (componentType.equals(SchemaSymbols.ELT_ANNOTATION)) { + currSG.addAnnotation(fElementTraverser.traverseAnnotationDecl(globalComp, currSchemaDoc.getSchemaAttrs(), true, currSchemaDoc)); + sawAnnotation = true; + } + else { + reportSchemaError("s4s-elt-invalid-content.1", new Object [] {SchemaSymbols.ELT_SCHEMA, DOMUtil.getLocalName(globalComp)}, globalComp); + } + } // end for + + if (!sawAnnotation) { + String text = DOMUtil.getSyntheticAnnotation(currRoot); + if (text != null) { + currSG.addAnnotation(fElementTraverser.traverseSyntheticAnnotation(currRoot, text, currSchemaDoc.getSchemaAttrs(), true, currSchemaDoc)); + } + } + + /** Collect annotation information for validation. **/ + if (annotationInfo != null) { + XSAnnotationInfo info = currSchemaDoc.getAnnotations(); + /** Only add annotations to the list if there were any in this document. **/ + if (info != null) { + annotationInfo.add(doc2SystemId(currDoc)); + annotationInfo.add(info); + } + } + // now we're done with this one! + currSchemaDoc.returnSchemaAttrs(); + DOMUtil.setHidden(currDoc, fHiddenNodes); + + // now add the schemas this guy depends on + Vector currSchemaDepends = (Vector)fDependencyMap.get(currSchemaDoc); + for (int i = 0; i < currSchemaDepends.size(); i++) { + schemasToProcess.push(currSchemaDepends.elementAt(i)); + } + } // while + } // end traverseSchemas + + // store whether we have reported an error about that no grammar + // is found for the given namespace uri + private Vector fReportedTNS = null; + // check whether we need to report an error against the given uri. + // if we have reported an error, then we don't need to report again; + // otherwise we reported the error, and remember this fact. + private final boolean needReportTNSError(String uri) { + if (fReportedTNS == null) + fReportedTNS = new Vector(); + else if (fReportedTNS.contains(uri)) + return false; + fReportedTNS.addElement(uri); + return true; + } + + private static final String[] COMP_TYPE = { + null, // index 0 + "attribute declaration", + "attribute group", + "element declaration", + "group", + "identity constraint", + "notation", + "type definition", + }; + + private static final String[] CIRCULAR_CODES = { + "Internal-Error", + "Internal-Error", + "src-attribute_group.3", + "e-props-correct.6", + "mg-props-correct.2", + "Internal-Error", + "Internal-Error", + "st-props-correct.2", //or ct-props-correct.3 + }; + + // add a global attribute decl from a current schema load (only if no existing decl is found) + void addGlobalAttributeDecl(XSAttributeDecl decl) { + final String namespace = decl.getNamespace(); + final String declKey = (namespace == null || namespace.length() == 0) + ? "," + decl.getName() : namespace + "," + decl.getName(); + + if (fGlobalAttrDecls.get(declKey) == null) { + fGlobalAttrDecls.put(declKey, decl); + } + } + + // add a global attribute group decl from a current schema load (only if no existing decl is found) + void addGlobalAttributeGroupDecl(XSAttributeGroupDecl decl) { + final String namespace = decl.getNamespace(); + final String declKey = (namespace == null || namespace.length() == 0) + ? "," + decl.getName() : namespace + "," + decl.getName(); + + if (fGlobalAttrGrpDecls.get(declKey) == null) { + fGlobalAttrGrpDecls.put(declKey, decl); + } + } + + // add a global element decl from a current schema load (only if no existing decl is found) + void addGlobalElementDecl(XSElementDecl decl) { + final String namespace = decl.getNamespace(); + final String declKey = (namespace == null || namespace.length() == 0) + ? "," + decl.getName() : namespace + "," + decl.getName(); + + if (fGlobalElemDecls.get(declKey) == null) { + fGlobalElemDecls.put(declKey, decl); + } + } + + // add a global group decl from a current schema load (only if no existing decl is found) + void addGlobalGroupDecl(XSGroupDecl decl) { + final String namespace = decl.getNamespace(); + final String declKey = (namespace == null || namespace.length() == 0) + ? "," + decl.getName() : namespace + "," + decl.getName(); + + if (fGlobalGroupDecls.get(declKey) == null) { + fGlobalGroupDecls.put(declKey, decl); + } + } + + // add a global notation decl from a current schema load (only if no existing decl is found) + void addGlobalNotationDecl(XSNotationDecl decl) { + final String namespace = decl.getNamespace(); + final String declKey = (namespace == null || namespace.length() == 0) + ? "," + decl.getName() : namespace + "," + decl.getName(); + + if (fGlobalNotationDecls.get(declKey) == null) { + fGlobalNotationDecls.put(declKey, decl); + } + } + + // add a global type decl from a current schema load (only if no existing decl is found) + void addGlobalTypeDecl(XSTypeDefinition decl) { + final String namespace = decl.getNamespace(); + final String declKey = (namespace == null || namespace.length() == 0) + ? "," + decl.getName() : namespace + "," + decl.getName(); + + if (fGlobalTypeDecls.get(declKey) == null) { + fGlobalTypeDecls.put(declKey, decl); + } + } + + // add a identity constraint decl from a current schema load (only if no existing decl is found) + void addIDConstraintDecl(IdentityConstraint decl) { + final String namespace = decl.getNamespace(); + final String declKey = (namespace == null || namespace.length() == 0) + ? "," + decl.getIdentityConstraintName() : namespace + "," + decl.getIdentityConstraintName(); + + if (fGlobalIDConstraintDecls.get(declKey) == null) { + fGlobalIDConstraintDecls.put(declKey, decl); + } + } + + private XSAttributeDecl getGlobalAttributeDecl(String declKey) { + return (XSAttributeDecl)fGlobalAttrDecls.get(declKey); + } + + private XSAttributeGroupDecl getGlobalAttributeGroupDecl(String declKey) { + return (XSAttributeGroupDecl)fGlobalAttrGrpDecls.get(declKey); + } + + private XSElementDecl getGlobalElementDecl(String declKey) { + return (XSElementDecl)fGlobalElemDecls.get(declKey); + } + + private XSGroupDecl getGlobalGroupDecl(String declKey) { + return (XSGroupDecl)fGlobalGroupDecls.get(declKey); + } + + private XSNotationDecl getGlobalNotationDecl(String declKey) { + return (XSNotationDecl)fGlobalNotationDecls.get(declKey); + } + + private XSTypeDefinition getGlobalTypeDecl(String declKey) { + return (XSTypeDefinition)fGlobalTypeDecls.get(declKey); + } + + private IdentityConstraint getIDConstraintDecl(String declKey) { + return (IdentityConstraint)fGlobalIDConstraintDecls.get(declKey); + } + + // since it is forbidden for traversers to talk to each other + // directly (except wen a traverser encounters a local declaration), + // this provides a generic means for a traverser to call + // for the traversal of some declaration. An XSDocumentInfo is + // required because the XSDocumentInfo that the traverser is traversing + // may bear no relation to the one the handler is operating on. + // This method will: + // 1. See if a global definition matching declToTraverse exists; + // 2. if so, determine if there is a path from currSchema to the + // schema document where declToTraverse lives (i.e., do a lookup + // in DependencyMap); + // 3. depending on declType (which will be relevant to step 1 as + // well), call the appropriate traverser with the appropriate + // XSDocumentInfo object. + // This method returns whatever the traverser it called returned; + // this will be an Object of some kind + // that lives in the Grammar. + protected Object getGlobalDecl(XSDocumentInfo currSchema, + int declType, + QName declToTraverse, + Element elmNode) { + + if (DEBUG_NODE_POOL) { + System.out.println("TRAVERSE_GL: "+declToTraverse.toString()); + } + + // from the schema spec, all built-in types are present in all schemas, + // so if the requested component is a type, and could be found in the + // default schema grammar, we should return that type. + // otherwise (since we would support user-defined schema grammar) we'll + // use the normal way to get the decl + if (declToTraverse.uri != null && + declToTraverse.uri == SchemaSymbols.URI_SCHEMAFORSCHEMA) { + if (declType == TYPEDECL_TYPE) { + Object retObj = SchemaGrammar.SG_SchemaNS.getGlobalTypeDecl(declToTraverse.localpart); + if (retObj != null) + return retObj; + } + } + + // now check whether this document can access the requsted namespace + if (!currSchema.isAllowedNS(declToTraverse.uri)) { + // cannot get to this schema from the one containing the requesting decl + if (currSchema.needReportTNSError(declToTraverse.uri)) { + String code = declToTraverse.uri == null ? "src-resolve.4.1" : "src-resolve.4.2"; + reportSchemaError(code, new Object[]{fDoc2SystemId.get(currSchema.fSchemaElement), declToTraverse.uri, declToTraverse.rawname}, elmNode); + } + // Recover and continue to look for the component. + // return null; + } + + // check whether there is grammar for the requested namespace + SchemaGrammar sGrammar = fGrammarBucket.getGrammar(declToTraverse.uri); + if (sGrammar == null) { + if (needReportTNSError(declToTraverse.uri)) + reportSchemaError("src-resolve", new Object[]{declToTraverse.rawname, COMP_TYPE[declType]}, elmNode); + return null; + } + + // if there is such grammar, check whether the requested component is in the grammar + Object retObj = getGlobalDeclFromGrammar(sGrammar, declType, declToTraverse.localpart); + String declKey = declToTraverse.uri == null? ","+declToTraverse.localpart: + declToTraverse.uri+","+declToTraverse.localpart; + + // if the component is parsed, return it + if (!fTolerateDuplicates) { + if (retObj != null) { + return retObj; + } + } + else { + Object retObj2 = getGlobalDecl(declKey, declType); + if (retObj2 != null) { + return retObj2; + } + } + + XSDocumentInfo schemaWithDecl = null; + Element decl = null; + XSDocumentInfo declDoc = null; + + // the component is not parsed, try to find a DOM element for it + switch (declType) { + case ATTRIBUTE_TYPE : + decl = getElementFromMap(fUnparsedAttributeRegistry, declKey); + declDoc = getDocInfoFromMap(fUnparsedAttributeRegistrySub, declKey); + break; + case ATTRIBUTEGROUP_TYPE : + decl = getElementFromMap(fUnparsedAttributeGroupRegistry, declKey); + declDoc = getDocInfoFromMap(fUnparsedAttributeGroupRegistrySub, declKey); + break; + case ELEMENT_TYPE : + decl = getElementFromMap(fUnparsedElementRegistry, declKey); + declDoc = getDocInfoFromMap(fUnparsedElementRegistrySub, declKey); + break; + case GROUP_TYPE : + decl = getElementFromMap(fUnparsedGroupRegistry, declKey); + declDoc = getDocInfoFromMap(fUnparsedGroupRegistrySub, declKey); + break; + case IDENTITYCONSTRAINT_TYPE : + decl = getElementFromMap(fUnparsedIdentityConstraintRegistry, declKey); + declDoc = getDocInfoFromMap(fUnparsedIdentityConstraintRegistrySub, declKey); + break; + case NOTATION_TYPE : + decl = getElementFromMap(fUnparsedNotationRegistry, declKey); + declDoc = getDocInfoFromMap(fUnparsedNotationRegistrySub, declKey); + break; + case TYPEDECL_TYPE : + decl = getElementFromMap(fUnparsedTypeRegistry, declKey); + declDoc = getDocInfoFromMap(fUnparsedTypeRegistrySub, declKey); + break; + default: + reportSchemaError("Internal-Error", new Object [] {"XSDHandler asked to locate component of type " + declType + "; it does not recognize this type!"}, elmNode); + } + + // no DOM element found, so the component can't be located + if (decl == null) { + if (retObj == null) { + reportSchemaError("src-resolve", new Object[]{declToTraverse.rawname, COMP_TYPE[declType]}, elmNode); + } + return retObj; + } + + // get the schema doc containing the component to be parsed + // it should always return non-null value, but since null-checking + // comes for free, let's be safe and check again + schemaWithDecl = findXSDocumentForDecl(currSchema, decl, declDoc); + if (schemaWithDecl == null) { + // cannot get to this schema from the one containing the requesting decl + if (retObj == null) { + String code = declToTraverse.uri == null ? "src-resolve.4.1" : "src-resolve.4.2"; + reportSchemaError(code, new Object[]{fDoc2SystemId.get(currSchema.fSchemaElement), declToTraverse.uri, declToTraverse.rawname}, elmNode); + } + return retObj; + } + + // a component is hidden, meaning either it's traversed, or being traversed. + // but we didn't find it in the grammar, so it's the latter case, and + // a circular reference. error! + if (DOMUtil.isHidden(decl, fHiddenNodes)) { + if (retObj == null) { + String code = CIRCULAR_CODES[declType]; + if (declType == TYPEDECL_TYPE) { + if (SchemaSymbols.ELT_COMPLEXTYPE.equals(DOMUtil.getLocalName(decl))) { + code = "ct-props-correct.3"; + } + } + // decl must not be null if we're here... + reportSchemaError(code, new Object [] {declToTraverse.prefix+":"+declToTraverse.localpart}, elmNode); + } + return retObj; + } + + return traverseGlobalDecl(declType, decl, schemaWithDecl, sGrammar); + } // getGlobalDecl(XSDocumentInfo, int, QName): Object + + // If we are tolerating duplicate declarations and allowing namespace growth + // use the declaration from the current schema load (if it exists) + protected Object getGlobalDecl(String declKey, int declType) { + Object retObj = null; + + switch (declType) { + case ATTRIBUTE_TYPE : + retObj = getGlobalAttributeDecl(declKey); + break; + case ATTRIBUTEGROUP_TYPE : + retObj = getGlobalAttributeGroupDecl(declKey); + break; + case ELEMENT_TYPE : + retObj = getGlobalElementDecl(declKey); + break; + case GROUP_TYPE : + retObj = getGlobalGroupDecl(declKey); + break; + case IDENTITYCONSTRAINT_TYPE : + retObj = getIDConstraintDecl(declKey); + break; + case NOTATION_TYPE : + retObj = getGlobalNotationDecl(declKey); + break; + case TYPEDECL_TYPE : + retObj = getGlobalTypeDecl(declKey); + break; + } + + return retObj; + } + + protected Object getGlobalDeclFromGrammar(SchemaGrammar sGrammar, int declType, String localpart) { + Object retObj = null; + + switch (declType) { + case ATTRIBUTE_TYPE : + retObj = sGrammar.getGlobalAttributeDecl(localpart); + break; + case ATTRIBUTEGROUP_TYPE : + retObj = sGrammar.getGlobalAttributeGroupDecl(localpart); + break; + case ELEMENT_TYPE : + retObj = sGrammar.getGlobalElementDecl(localpart); + break; + case GROUP_TYPE : + retObj = sGrammar.getGlobalGroupDecl(localpart); + break; + case IDENTITYCONSTRAINT_TYPE : + retObj = sGrammar.getIDConstraintDecl(localpart); + break; + case NOTATION_TYPE : + retObj = sGrammar.getGlobalNotationDecl(localpart); + break; + case TYPEDECL_TYPE : + retObj = sGrammar.getGlobalTypeDecl(localpart); + break; + } + + return retObj; + } + + protected Object getGlobalDeclFromGrammar(SchemaGrammar sGrammar, int declType, String localpart, String schemaLoc) { + Object retObj = null; + + switch (declType) { + case ATTRIBUTE_TYPE : + retObj = sGrammar.getGlobalAttributeDecl(localpart, schemaLoc); + break; + case ATTRIBUTEGROUP_TYPE : + retObj = sGrammar.getGlobalAttributeGroupDecl(localpart, schemaLoc); + break; + case ELEMENT_TYPE : + retObj = sGrammar.getGlobalElementDecl(localpart, schemaLoc); + break; + case GROUP_TYPE : + retObj = sGrammar.getGlobalGroupDecl(localpart, schemaLoc); + break; + case IDENTITYCONSTRAINT_TYPE : + retObj = sGrammar.getIDConstraintDecl(localpart, schemaLoc); + break; + case NOTATION_TYPE : + retObj = sGrammar.getGlobalNotationDecl(localpart, schemaLoc); + break; + case TYPEDECL_TYPE : + retObj = sGrammar.getGlobalTypeDecl(localpart, schemaLoc); + break; + } + + return retObj; + } + + protected Object traverseGlobalDecl(int declType, Element decl, XSDocumentInfo schemaDoc, SchemaGrammar grammar) { + Object retObj = null; + + DOMUtil.setHidden(decl, fHiddenNodes); + SchemaNamespaceSupport nsSupport = null; + // if the parent is <redefine> use the namespace delcs for it. + Element parent = DOMUtil.getParent(decl); + if (DOMUtil.getLocalName(parent).equals(SchemaSymbols.ELT_REDEFINE)) + nsSupport = (fRedefine2NSSupport!=null)?(SchemaNamespaceSupport)fRedefine2NSSupport.get(parent):null; + // back up the current SchemaNamespaceSupport, because we need to provide + // a fresh one to the traverseGlobal methods. + schemaDoc.backupNSSupport(nsSupport); + + // traverse the referenced global component + switch (declType) { + case TYPEDECL_TYPE : + if (DOMUtil.getLocalName(decl).equals(SchemaSymbols.ELT_COMPLEXTYPE)) { + retObj = fComplexTypeTraverser.traverseGlobal(decl, schemaDoc, grammar); + } + else { + retObj = fSimpleTypeTraverser.traverseGlobal(decl, schemaDoc, grammar); + } + break; + case ATTRIBUTE_TYPE : + retObj = fAttributeTraverser.traverseGlobal(decl, schemaDoc, grammar); + break; + case ELEMENT_TYPE : + retObj = fElementTraverser.traverseGlobal(decl, schemaDoc, grammar); + break; + case ATTRIBUTEGROUP_TYPE : + retObj = fAttributeGroupTraverser.traverseGlobal(decl, schemaDoc, grammar); + break; + case GROUP_TYPE : + retObj = fGroupTraverser.traverseGlobal(decl, schemaDoc, grammar); + break; + case NOTATION_TYPE : + retObj = fNotationTraverser.traverse(decl, schemaDoc, grammar); + break; + case IDENTITYCONSTRAINT_TYPE : + // identity constraints should have been parsed already... + // we should never get here + break; + } + + // restore the previous SchemaNamespaceSupport, so that the caller can get + // proper namespace binding. + schemaDoc.restoreNSSupport(); + + return retObj; + } + + public String schemaDocument2SystemId(XSDocumentInfo schemaDoc) { + return (String)fDoc2SystemId.get(schemaDoc.fSchemaElement); + } + + // This method determines whether there is a group + // (attributeGroup) which the given one has redefined by + // restriction. If so, it returns it; else it returns null. + // @param type: whether what's been redefined is an + // attributeGroup or a group; + // @param name: the QName of the component doing the redefining. + // @param currSchema: schema doc in which the redefining component lives. + // @return: Object representing decl redefined if present, null + // otherwise. + Object getGrpOrAttrGrpRedefinedByRestriction(int type, QName name, XSDocumentInfo currSchema, Element elmNode) { + String realName = name.uri != null?name.uri+","+name.localpart: + ","+name.localpart; + String nameToFind = null; + switch (type) { + case ATTRIBUTEGROUP_TYPE: + nameToFind = (String)fRedefinedRestrictedAttributeGroupRegistry.get(realName); + break; + case GROUP_TYPE: + nameToFind = (String)fRedefinedRestrictedGroupRegistry.get(realName); + break; + default: + return null; + } + if (nameToFind == null) return null; + int commaPos = nameToFind.indexOf(","); + QName qNameToFind = new QName(XMLSymbols.EMPTY_STRING, nameToFind.substring(commaPos+1), + nameToFind.substring(commaPos), (commaPos == 0)? null : nameToFind.substring(0, commaPos)); + Object retObj = getGlobalDecl(currSchema, type, qNameToFind, elmNode); + if(retObj == null) { + switch (type) { + case ATTRIBUTEGROUP_TYPE: + reportSchemaError("src-redefine.7.2.1", new Object []{name.localpart}, elmNode); + break; + case GROUP_TYPE: + reportSchemaError("src-redefine.6.2.1", new Object []{name.localpart}, elmNode); + break; + } + return null; + } + return retObj; + } // getGrpOrAttrGrpRedefinedByRestriction(int, QName, XSDocumentInfo): Object + + // Since ID constraints can occur in local elements, unless we + // wish to completely traverse all our DOM trees looking for ID + // constraints while we're building our global name registries, + // which seems terribly inefficient, we need to resolve keyrefs + // after all parsing is complete. This we can simply do by running through + // fIdentityConstraintRegistry and calling traverseKeyRef on all + // of the KeyRef nodes. This unfortunately removes this knowledge + // from the elementTraverser class (which must ignore keyrefs), + // but there seems to be no efficient way around this... + protected void resolveKeyRefs() { + for (int i=0; i<fKeyrefStackPos; i++) { + XSDocumentInfo keyrefSchemaDoc = fKeyrefsMapXSDocumentInfo[i]; + keyrefSchemaDoc.fNamespaceSupport.makeGlobal(); + keyrefSchemaDoc.fNamespaceSupport.setEffectiveContext( fKeyrefNamespaceContext[i] ); + SchemaGrammar keyrefGrammar = fGrammarBucket.getGrammar(keyrefSchemaDoc.fTargetNamespace); + // need to set <keyref> to hidden before traversing it, + // because it has global scope + DOMUtil.setHidden(fKeyrefs[i], fHiddenNodes); + fKeyrefTraverser.traverse(fKeyrefs[i], fKeyrefElems[i], keyrefSchemaDoc, keyrefGrammar); + } + } // end resolveKeyRefs + + // an accessor method. Just makes sure callers + // who want the Identity constraint registry vaguely know what they're about. + protected Map getIDRegistry() { + return fUnparsedIdentityConstraintRegistry; + } + // an accessor method. + protected Map getIDRegistry_sub() { + return fUnparsedIdentityConstraintRegistrySub; + } + + + + // This method squirrels away <keyref> declarations--along with the element + // decls and namespace bindings they might find handy. + protected void storeKeyRef (Element keyrefToStore, XSDocumentInfo schemaDoc, + XSElementDecl currElemDecl) { + String keyrefName = DOMUtil.getAttrValue(keyrefToStore, SchemaSymbols.ATT_NAME); + if (keyrefName.length() != 0) { + String keyrefQName = schemaDoc.fTargetNamespace == null? + "," + keyrefName: schemaDoc.fTargetNamespace+","+keyrefName; + checkForDuplicateNames(keyrefQName, IDENTITYCONSTRAINT_TYPE, fUnparsedIdentityConstraintRegistry, fUnparsedIdentityConstraintRegistrySub, keyrefToStore, schemaDoc); + } + // now set up all the registries we'll need... + + // check array sizes + if (fKeyrefStackPos == fKeyrefs.length) { + Element [] elemArray = new Element [fKeyrefStackPos + INC_KEYREF_STACK_AMOUNT]; + System.arraycopy(fKeyrefs, 0, elemArray, 0, fKeyrefStackPos); + fKeyrefs = elemArray; + XSElementDecl [] declArray = new XSElementDecl [fKeyrefStackPos + INC_KEYREF_STACK_AMOUNT]; + System.arraycopy(fKeyrefElems, 0, declArray, 0, fKeyrefStackPos); + fKeyrefElems = declArray; + String[][] stringArray = new String [fKeyrefStackPos + INC_KEYREF_STACK_AMOUNT][]; + System.arraycopy(fKeyrefNamespaceContext, 0, stringArray, 0, fKeyrefStackPos); + fKeyrefNamespaceContext = stringArray; + + XSDocumentInfo [] xsDocumentInfo = new XSDocumentInfo [fKeyrefStackPos + INC_KEYREF_STACK_AMOUNT]; + System.arraycopy(fKeyrefsMapXSDocumentInfo, 0, xsDocumentInfo, 0, fKeyrefStackPos); + fKeyrefsMapXSDocumentInfo = xsDocumentInfo; + + } + fKeyrefs[fKeyrefStackPos] = keyrefToStore; + fKeyrefElems[fKeyrefStackPos] = currElemDecl; + fKeyrefNamespaceContext[fKeyrefStackPos] = schemaDoc.fNamespaceSupport.getEffectiveLocalContext(); + + fKeyrefsMapXSDocumentInfo[fKeyrefStackPos++] = schemaDoc; + } // storeKeyref (Element, XSDocumentInfo, XSElementDecl): void + + + /** + * resolveSchema method is responsible for resolving location of the schema (using XMLEntityResolver), + * and if it was succefully resolved getting the schema Document. + * @param desc + * @param mustResolve + * @param referElement + * @return A schema Element or null. + */ + private Element resolveSchema(XSDDescription desc, boolean mustResolve, + Element referElement, boolean usePairs) { + XMLInputSource schemaSource = null; + try { + Map pairs = usePairs ? fLocationPairs : EMPTY_TABLE; + schemaSource = XMLSchemaLoader.resolveDocument(desc, pairs, fEntityResolver); + } + catch (IOException ex) { + if (mustResolve) { + reportSchemaError("schema_reference.4", + new Object[]{desc.getLocationHints()[0]}, + referElement); + } + else { + reportSchemaWarning("schema_reference.4", + new Object[]{desc.getLocationHints()[0]}, + referElement); + } + } + if (schemaSource instanceof DOMInputSource) { + return getSchemaDocument(desc.getTargetNamespace(), (DOMInputSource) schemaSource, mustResolve, desc.getContextType(), referElement); + } // DOMInputSource + else if (schemaSource instanceof SAXInputSource) { + return getSchemaDocument(desc.getTargetNamespace(), (SAXInputSource) schemaSource, mustResolve, desc.getContextType(), referElement); + } // SAXInputSource + else if (schemaSource instanceof StAXInputSource) { + return getSchemaDocument(desc.getTargetNamespace(), (StAXInputSource) schemaSource, mustResolve, desc.getContextType(), referElement); + } // StAXInputSource + else if (schemaSource instanceof XSInputSource) { + return getSchemaDocument((XSInputSource) schemaSource, desc); + } // XSInputSource + return getSchemaDocument(desc.getTargetNamespace(), schemaSource, mustResolve, desc.getContextType(), referElement); + } // getSchema(String, String, String, boolean, short): Document + + private Element resolveSchema(XMLInputSource schemaSource, XSDDescription desc, + boolean mustResolve, Element referElement) { + + if (schemaSource instanceof DOMInputSource) { + return getSchemaDocument(desc.getTargetNamespace(), (DOMInputSource) schemaSource, mustResolve, desc.getContextType(), referElement); + } // DOMInputSource + else if (schemaSource instanceof SAXInputSource) { + return getSchemaDocument(desc.getTargetNamespace(), (SAXInputSource) schemaSource, mustResolve, desc.getContextType(), referElement); + } // SAXInputSource + else if (schemaSource instanceof StAXInputSource) { + return getSchemaDocument(desc.getTargetNamespace(), (StAXInputSource) schemaSource, mustResolve, desc.getContextType(), referElement); + } // StAXInputSource + else if (schemaSource instanceof XSInputSource) { + return getSchemaDocument((XSInputSource) schemaSource, desc); + } // XSInputSource + return getSchemaDocument(desc.getTargetNamespace(), schemaSource, mustResolve, desc.getContextType(), referElement); + } + + private XMLInputSource resolveSchemaSource(XSDDescription desc, boolean mustResolve, + Element referElement, boolean usePairs) { + + XMLInputSource schemaSource = null; + try { + Map pairs = usePairs ? fLocationPairs : EMPTY_TABLE; + schemaSource = XMLSchemaLoader.resolveDocument(desc, pairs, fEntityResolver); + } + catch (IOException ex) { + if (mustResolve) { + reportSchemaError("schema_reference.4", + new Object[]{desc.getLocationHints()[0]}, + referElement); + } + else { + reportSchemaWarning("schema_reference.4", + new Object[]{desc.getLocationHints()[0]}, + referElement); + } + } + + return schemaSource; + } + + /** + * getSchemaDocument method uses XMLInputSource to parse a schema document. + * @param schemaNamespace + * @param schemaSource + * @param mustResolve + * @param referType + * @param referElement + * @return A schema Element. + */ + private Element getSchemaDocument(String schemaNamespace, XMLInputSource schemaSource, + boolean mustResolve, short referType, Element referElement) { + + boolean hasInput = true; + IOException exception = null; + // contents of this method will depend on the system we adopt for entity resolution--i.e., XMLEntityHandler, EntityHandler, etc. + Element schemaElement = null; + try { + // when the system id and byte stream and character stream + // of the input source are all null, it's + // impossible to find the schema document. so we skip in + // this case. otherwise we'll receive some NPE or + // file not found errors. but schemaHint=="" is perfectly + // legal for import. + if (schemaSource != null && + (schemaSource.getSystemId() != null || + schemaSource.getByteStream() != null || + schemaSource.getCharacterStream() != null)) { + + // When the system id of the input source is used, first try to + // expand it, and check whether the same document has been + // parsed before. If so, return the document corresponding to + // that system id. + XSDKey key = null; + String schemaId = null; + if (referType != XSDDescription.CONTEXT_PREPARSE){ + schemaId = XMLEntityManager.expandSystemId(schemaSource.getSystemId(), schemaSource.getBaseSystemId(), false); + key = new XSDKey(schemaId, referType, schemaNamespace); + if((schemaElement = (Element)fTraversed.get(key)) != null) { + fLastSchemaWasDuplicate = true; + return schemaElement; + } + } + + fSchemaParser.parse(schemaSource); + Document schemaDocument = fSchemaParser.getDocument(); + schemaElement = schemaDocument != null ? DOMUtil.getRoot(schemaDocument) : null; + return getSchemaDocument0(key, schemaId, schemaElement); + } + else { + hasInput = false; + } + } + catch (IOException ex) { + exception = ex; + } + return getSchemaDocument1(mustResolve, hasInput, schemaSource, referElement, exception); + } // getSchemaDocument(String, XMLInputSource, boolean, short, Element): Element + + /** + * getSchemaDocument method uses SAXInputSource to parse a schema document. + * @param schemaNamespace + * @param schemaSource + * @param mustResolve + * @param referType + * @param referElement + * @return A schema Element. + */ + private Element getSchemaDocument(String schemaNamespace, SAXInputSource schemaSource, + boolean mustResolve, short referType, Element referElement) { + XMLReader parser = schemaSource.getXMLReader(); + InputSource inputSource = schemaSource.getInputSource(); + boolean hasInput = true; + IOException exception = null; + Element schemaElement = null; + try { + if (inputSource != null && + (inputSource.getSystemId() != null || + inputSource.getByteStream() != null || + inputSource.getCharacterStream() != null)) { + + // check whether the same document has been parsed before. + // If so, return the document corresponding to that system id. + XSDKey key = null; + String schemaId = null; + if (referType != XSDDescription.CONTEXT_PREPARSE) { + schemaId = XMLEntityManager.expandSystemId(inputSource.getSystemId(), schemaSource.getBaseSystemId(), false); + key = new XSDKey(schemaId, referType, schemaNamespace); + if ((schemaElement = (Element) fTraversed.get(key)) != null) { + fLastSchemaWasDuplicate = true; + return schemaElement; + } + } + + boolean namespacePrefixes = false; + if (parser != null) { + try { + namespacePrefixes = parser.getFeature(NAMESPACE_PREFIXES); + } + catch (SAXException se) {} + } + else { + try { + parser = XMLReaderFactory.createXMLReader(); + } + // If something went wrong with the factory + // just use our own SAX parser. + catch (SAXException se) { + parser = new SAXParser(); + } + try { + parser.setFeature(NAMESPACE_PREFIXES, true); + namespacePrefixes = true; + // If this is a Xerces SAX parser set the security manager if there is one + if (parser instanceof SAXParser) { + Object securityManager = fSchemaParser.getProperty(SECURITY_MANAGER); + if (securityManager != null) { + parser.setProperty(SECURITY_MANAGER, securityManager); + } + } + } + catch (SAXException se) {} + } + // If XML names and Namespace URIs are already internalized we + // can avoid running them through the SymbolTable. + boolean stringsInternalized = false; + try { + stringsInternalized = parser.getFeature(STRING_INTERNING); + } + catch (SAXException exc) { + // The feature isn't recognized or getting it is not supported. + // In either case, assume that strings are not internalized. + } + if (fXSContentHandler == null) { + fXSContentHandler = new SchemaContentHandler(); + } + fXSContentHandler.reset(fSchemaParser, fSymbolTable, + namespacePrefixes, stringsInternalized); + parser.setContentHandler(fXSContentHandler); + parser.setErrorHandler(fErrorReporter.getSAXErrorHandler()); + + parser.parse(inputSource); + // Disconnect the schema loader and other objects from the XMLReader + try { + parser.setContentHandler(null); + parser.setErrorHandler(null); + } + // Ignore any exceptions thrown by the XMLReader. Old versions of SAX + // required an XMLReader to throw a NullPointerException if an attempt + // to set a handler to null was made. + catch (Exception e) {} + + Document schemaDocument = fXSContentHandler.getDocument(); + schemaElement = schemaDocument != null ? DOMUtil.getRoot(schemaDocument) : null; + return getSchemaDocument0(key, schemaId, schemaElement); + } + else { + hasInput = false; + } + } + catch (SAXParseException spe) { + throw SAX2XNIUtil.createXMLParseException0(spe); + } + catch (SAXException se) { + throw SAX2XNIUtil.createXNIException0(se); + } + catch (IOException ioe) { + exception = ioe; + } + return getSchemaDocument1(mustResolve, hasInput, schemaSource, referElement, exception); + } // getSchemaDocument(String, SAXInputSource, boolean, short, Element): Element + + /** + * getSchemaDocument method uses DOMInputSource to parse a schema document. + * @param schemaNamespace + * @param schemaSource + * @param mustResolve + * @param referType + * @param referElement + * @return A schema Element. + */ + private Element getSchemaDocument(String schemaNamespace, DOMInputSource schemaSource, + boolean mustResolve, short referType, Element referElement) { + boolean hasInput = true; + IOException exception = null; + Element schemaElement = null; + Element schemaRootElement = null; + + final Node node = schemaSource.getNode(); + short nodeType = -1; + if (node != null) { + nodeType = node.getNodeType(); + if (nodeType == Node.DOCUMENT_NODE) { + schemaRootElement = DOMUtil.getRoot((Document) node); + } + else if (nodeType == Node.ELEMENT_NODE) { + schemaRootElement = (Element) node; + } + } + + try { + if (schemaRootElement != null) { + // check whether the same document has been parsed before. + // If so, return the document corresponding to that system id. + XSDKey key = null; + String schemaId = null; + if (referType != XSDDescription.CONTEXT_PREPARSE) { + schemaId = XMLEntityManager.expandSystemId(schemaSource.getSystemId(), schemaSource.getBaseSystemId(), false); + boolean isDocument = (nodeType == Node.DOCUMENT_NODE); + if (!isDocument) { + Node parent = schemaRootElement.getParentNode(); + if (parent != null) { + isDocument = (parent.getNodeType() == Node.DOCUMENT_NODE); + } + } + if (isDocument) { + key = new XSDKey(schemaId, referType, schemaNamespace); + if ((schemaElement = (Element) fTraversed.get(key)) != null) { + fLastSchemaWasDuplicate = true; + return schemaElement; + } + } + } + + schemaElement = schemaRootElement; + return getSchemaDocument0(key, schemaId, schemaElement); + } + else { + hasInput = false; + } + } + catch (IOException ioe) { + exception = ioe; + } + return getSchemaDocument1(mustResolve, hasInput, schemaSource, referElement, exception); + } // getSchemaDocument(String, DOMInputSource, boolean, short, Element): Element + + /** + * getSchemaDocument method uses StAXInputSource to parse a schema document. + * @param schemaNamespace + * @param schemaSource + * @param mustResolve + * @param referType + * @param referElement + * @return A schema Element. + */ + private Element getSchemaDocument(String schemaNamespace, StAXInputSource schemaSource, + boolean mustResolve, short referType, Element referElement) { + IOException exception = null; + Element schemaElement = null; + try { + final boolean consumeRemainingContent = schemaSource.shouldConsumeRemainingContent(); + final XMLStreamReader streamReader = schemaSource.getXMLStreamReader(); + final XMLEventReader eventReader = schemaSource.getXMLEventReader(); + + // check whether the same document has been parsed before. + // If so, return the document corresponding to that system id. + XSDKey key = null; + String schemaId = null; + if (referType != XSDDescription.CONTEXT_PREPARSE) { + schemaId = XMLEntityManager.expandSystemId(schemaSource.getSystemId(), schemaSource.getBaseSystemId(), false); + boolean isDocument = consumeRemainingContent; + if (!isDocument) { + if (streamReader != null) { + isDocument = (streamReader.getEventType() == XMLStreamReader.START_DOCUMENT); + } + else { + isDocument = eventReader.peek().isStartDocument(); + } + } + if (isDocument) { + key = new XSDKey(schemaId, referType, schemaNamespace); + if ((schemaElement = (Element) fTraversed.get(key)) != null) { + fLastSchemaWasDuplicate = true; + return schemaElement; + } + } + } + + if (fStAXSchemaParser == null) { + fStAXSchemaParser = new StAXSchemaParser(); + } + fStAXSchemaParser.reset(fSchemaParser, fSymbolTable); + + if (streamReader != null) { + fStAXSchemaParser.parse(streamReader); + if (consumeRemainingContent) { + while (streamReader.hasNext()) { + streamReader.next(); + } + } + } + else { + fStAXSchemaParser.parse(eventReader); + if (consumeRemainingContent) { + while (eventReader.hasNext()) { + eventReader.nextEvent(); + } + } + } + Document schemaDocument = fStAXSchemaParser.getDocument(); + schemaElement = schemaDocument != null ? DOMUtil.getRoot(schemaDocument) : null; + return getSchemaDocument0(key, schemaId, schemaElement); + } + catch (XMLStreamException e) { + StAXLocationWrapper slw = new StAXLocationWrapper(); + slw.setLocation(e.getLocation()); + throw new XMLParseException(slw, e.getMessage(), e); + } + catch (IOException e) { + exception = e; + } + return getSchemaDocument1(mustResolve, true, schemaSource, referElement, exception); + } // getSchemaDocument(String, StAXInputSource, boolean, short, Element): Element + + /** + * Code shared between the various getSchemaDocument() methods which + * stores mapping information for the document. + */ + private Element getSchemaDocument0(XSDKey key, String schemaId, Element schemaElement) { + // now we need to store the mapping information from system id + // to the document. also from the document to the system id. + if (key != null) { + fTraversed.put(key, schemaElement); + } + if (schemaId != null) { + fDoc2SystemId.put(schemaElement, schemaId); + } + fLastSchemaWasDuplicate = false; + return schemaElement; + } // getSchemaDocument0(XSDKey, String, Element): Element + + /** + * Error handling code shared between the various getSchemaDocument() methods. + */ + private Element getSchemaDocument1(boolean mustResolve, boolean hasInput, + XMLInputSource schemaSource, Element referElement, IOException ioe) { + // either an error occured (exception), or empty input source was + // returned, we need to report an error or a warning + if (mustResolve) { + if (hasInput) { + reportSchemaError("schema_reference.4", + new Object[]{schemaSource.getSystemId()}, + referElement, ioe); + } + else { + reportSchemaError("schema_reference.4", + new Object[]{schemaSource == null ? "" : schemaSource.getSystemId()}, + referElement, ioe); + } + } + else if (hasInput) { + reportSchemaWarning("schema_reference.4", + new Object[]{schemaSource.getSystemId()}, + referElement, ioe); + } + + fLastSchemaWasDuplicate = false; + return null; + } // getSchemaDocument1(boolean, boolean, XMLInputSource, Element): Element + + /** + * getSchemaDocument method uses XMLInputSource to parse a schema document. + * @param schemaNamespace + * @param schemaSource + * @param mustResolve + * @param referType + * @param referElement + * @return A schema Element. + */ + private Element getSchemaDocument(XSInputSource schemaSource, XSDDescription desc) { + + SchemaGrammar[] grammars = schemaSource.getGrammars(); + short referType = desc.getContextType(); + + if (grammars != null && grammars.length > 0) { + Vector expandedGrammars = expandGrammars(grammars); + // check for existing grammars in our bucket + // and if there exist any, and namespace growth is + // not enabled - we do nothing + if (fNamespaceGrowth || !existingGrammars(expandedGrammars)) { + addGrammars(expandedGrammars); + if (referType == XSDDescription.CONTEXT_PREPARSE) { + desc.setTargetNamespace(grammars[0].getTargetNamespace()); + } + } + } + else { + XSObject[] components = schemaSource.getComponents(); + if (components != null && components.length > 0) { + Map<String, Vector> importDependencies = new HashMap(); + Vector expandedComponents = expandComponents(components, importDependencies); + if (fNamespaceGrowth || canAddComponents(expandedComponents)) { + addGlobalComponents(expandedComponents, importDependencies); + if (referType == XSDDescription.CONTEXT_PREPARSE) { + desc.setTargetNamespace(components[0].getNamespace()); + } + } + } + } + return null; + } // getSchemaDocument(String, XSInputSource, boolean, short, Element): Element + + private Vector expandGrammars(SchemaGrammar[] grammars) { + Vector currGrammars = new Vector(); + + for (int i=0; i<grammars.length; i++) { + if (!currGrammars.contains(grammars[i])) { + currGrammars.add(grammars[i]); + } + } + + // for all (recursively) imported grammars + SchemaGrammar sg1, sg2; + Vector gs; + for (int i = 0; i < currGrammars.size(); i++) { + // get the grammar + sg1 = (SchemaGrammar)currGrammars.elementAt(i); + // we need to add grammars imported by sg1 too + gs = sg1.getImportedGrammars(); + // for all grammars imported by sg2, but not in the vector + // we add them to the vector + if (gs == null) { + continue; + } + + for (int j = gs.size() - 1; j >= 0; j--) { + sg2 = (SchemaGrammar)gs.elementAt(j); + if (!currGrammars.contains(sg2)) { + currGrammars.addElement(sg2); + } + } + } + + return currGrammars; + } + + private boolean existingGrammars(Vector grammars) { + int length = grammars.size(); + final XSDDescription desc = new XSDDescription(); + + for (int i=0; i < length; i++) { + final SchemaGrammar sg1 = (SchemaGrammar)grammars.elementAt(i); + desc.setNamespace(sg1.getTargetNamespace()); + + final SchemaGrammar sg2 = findGrammar(desc, false); + if (sg2 != null) { + return true; + } + } + + return false; + } + + private boolean canAddComponents(Vector components) { + final int size = components.size(); + final XSDDescription desc = new XSDDescription(); + for (int i=0; i<size; i++) { + XSObject component = (XSObject) components.elementAt(i); + if (!canAddComponent(component, desc)) { + return false; + } + } + return true; + } + + private boolean canAddComponent(XSObject component, XSDDescription desc) { + desc.setNamespace(component.getNamespace()); + + final SchemaGrammar sg = findGrammar(desc, false); + if (sg == null) { + return true; + } + else if (sg.isImmutable()) { + return false; + } + + short componentType = component.getType(); + final String name = component.getName(); + + switch (componentType) { + case XSConstants.TYPE_DEFINITION : + if (sg.getGlobalTypeDecl(name) == component) { + return true; + } + break; + case XSConstants.ATTRIBUTE_DECLARATION : + if (sg.getGlobalAttributeDecl(name) == component) { + return true; + } + break; + case XSConstants.ATTRIBUTE_GROUP : + if (sg.getGlobalAttributeDecl(name) == component) { + return true; + } + break; + case XSConstants.ELEMENT_DECLARATION : + if (sg.getGlobalElementDecl(name) == component) { + return true; + } + break; + case XSConstants.MODEL_GROUP_DEFINITION : + if (sg.getGlobalGroupDecl(name) == component) { + return true; + } + break; + case XSConstants.NOTATION_DECLARATION : + if (sg.getGlobalNotationDecl(name) == component) { + return true; + } + break; + case XSConstants.IDENTITY_CONSTRAINT : + case XSConstants.ATTRIBUTE_USE : + default : + return true; + } + return false; + } + + private void addGrammars(Vector grammars) { + int length = grammars.size(); + XSDDescription desc = new XSDDescription(); + + for (int i=0; i < length; i++) { + final SchemaGrammar sg1 = (SchemaGrammar)grammars.elementAt(i); + desc.setNamespace(sg1.getTargetNamespace()); + + final SchemaGrammar sg2 = findGrammar(desc, fNamespaceGrowth); + if (sg1 != sg2) { + addGrammarComponents(sg1, sg2); + } + } + } + + private void addGrammarComponents(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) { + if (dstGrammar == null) { + createGrammarFrom(srcGrammar); + return; + } + + SchemaGrammar tmpGrammar = dstGrammar; + if (tmpGrammar.isImmutable()) { + tmpGrammar = createGrammarFrom(dstGrammar); + } + + // add any new locations + addNewGrammarLocations(srcGrammar, tmpGrammar); + + // add any new imported grammars + addNewImportedGrammars(srcGrammar, tmpGrammar); + + // add any new global components + addNewGrammarComponents(srcGrammar, tmpGrammar); + } + + private SchemaGrammar createGrammarFrom(SchemaGrammar grammar) { + SchemaGrammar newGrammar = new SchemaGrammar(grammar); + fGrammarBucket.putGrammar(newGrammar); + // update all the grammars in the bucket to point to the new grammar. + updateImportListWith(newGrammar); + // update import list of the new grammar + updateImportListFor(newGrammar); + return newGrammar; + } + + private void addNewGrammarLocations(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) { + final StringList locations = srcGrammar.getDocumentLocations(); + final int locSize = locations.size(); + final StringList locations2 = dstGrammar.getDocumentLocations(); + + for (int i=0; i<locSize; i++) { + String loc = locations.item(i); + if (!locations2.contains(loc)) { + dstGrammar.addDocument(null, loc); + } + } + } + + private void addNewImportedGrammars(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) { + final Vector igs1 = srcGrammar.getImportedGrammars(); + if (igs1 != null) { + Vector igs2 = dstGrammar.getImportedGrammars(); + + if (igs2 == null) { + igs2 = ((Vector) igs1.clone()); + dstGrammar.setImportedGrammars(igs2); + } + else { + updateImportList(igs1, igs2); + } + } + } + + private void updateImportList(Vector importedSrc, Vector importedDst) + { + final int size = importedSrc.size(); + + for (int i=0; i<size; i++) { + final SchemaGrammar sg = (SchemaGrammar) importedSrc.elementAt(i); + if (!containedImportedGrammar(importedDst, sg)) { + importedDst.add(sg); + } + } + } + + private void addNewGrammarComponents(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) { + dstGrammar.resetComponents(); + addGlobalElementDecls(srcGrammar, dstGrammar); + addGlobalAttributeDecls(srcGrammar, dstGrammar); + addGlobalAttributeGroupDecls(srcGrammar, dstGrammar); + addGlobalGroupDecls(srcGrammar, dstGrammar); + addGlobalTypeDecls(srcGrammar, dstGrammar); + addGlobalNotationDecls(srcGrammar, dstGrammar); + } + + private void addGlobalElementDecls(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) { + XSNamedMap components = srcGrammar.getComponents(XSConstants.ELEMENT_DECLARATION); + int len = components.getLength(); + XSElementDecl srcDecl, dstDecl; + + // add global components + for (int i=0; i<len; i++) { + srcDecl = (XSElementDecl) components.item(i); + dstDecl = dstGrammar.getGlobalElementDecl(srcDecl.getName()); + if (dstDecl == null) { + dstGrammar.addGlobalElementDecl(srcDecl); + } + else if (dstDecl != srcDecl){ + // TODO: if not tolerating duplicate, generate an error message + } + } + + // add any extended (duplicate) global components + ObjectList componentsExt = srcGrammar.getComponentsExt(XSConstants.ELEMENT_DECLARATION); + len = componentsExt.getLength(); + + for (int i=0; i<len; i+= 2) { + final String key = (String) componentsExt.item(i); + final int index = key.indexOf(','); + final String location = key.substring(0, index); + final String name = key.substring(index + 1, key.length()); + + srcDecl = (XSElementDecl)componentsExt.item(i+1); + dstDecl = dstGrammar.getGlobalElementDecl(name, location); + if ( dstDecl == null) { + dstGrammar.addGlobalElementDecl(srcDecl, location); + } + else if (dstDecl != srcDecl){ + // TODO: if not tolerating duplicate, generate an error message + } + } + } + + private void addGlobalAttributeDecls(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) { + XSNamedMap components = srcGrammar.getComponents(XSConstants.ATTRIBUTE_DECLARATION); + int len = components.getLength(); + XSAttributeDecl srcDecl, dstDecl; + + // add global components + for (int i=0; i<len; i++) { + srcDecl = (XSAttributeDecl) components.item(i); + dstDecl = dstGrammar.getGlobalAttributeDecl(srcDecl.getName()); + if (dstDecl == null) { + dstGrammar.addGlobalAttributeDecl(srcDecl); + } + else if (dstDecl != srcDecl && !fTolerateDuplicates) { + reportSharingError(srcDecl.getNamespace(), srcDecl.getName()); + } + } + + // add any extended (duplicate) global components + ObjectList componentsExt = srcGrammar.getComponentsExt(XSConstants.ATTRIBUTE_DECLARATION); + len = componentsExt.getLength(); + + for (int i=0; i<len; i+= 2) { + final String key = (String) componentsExt.item(i); + final int index = key.indexOf(','); + final String location = key.substring(0, index); + final String name = key.substring(index + 1, key.length()); + + srcDecl = (XSAttributeDecl)componentsExt.item(i+1); + dstDecl = dstGrammar.getGlobalAttributeDecl(name, location); + if (dstDecl == null) { + dstGrammar.addGlobalAttributeDecl(srcDecl, location); + } + // REVISIT - do we report an error? + else if (dstDecl != srcDecl) { + } + } + } + + private void addGlobalAttributeGroupDecls(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) { + XSNamedMap components = srcGrammar.getComponents(XSConstants.ATTRIBUTE_GROUP); + int len = components.getLength(); + XSAttributeGroupDecl srcDecl, dstDecl; + + // add global components + for (int i=0; i<len; i++) { + srcDecl = (XSAttributeGroupDecl) components.item(i); + dstDecl = dstGrammar.getGlobalAttributeGroupDecl(srcDecl.getName()); + if (dstDecl == null) { + dstGrammar.addGlobalAttributeGroupDecl(srcDecl); + } + else if (dstDecl != srcDecl && !fTolerateDuplicates) { + reportSharingError(srcDecl.getNamespace(), srcDecl.getName()); + } + } + + // add any extended (duplicate) global components + ObjectList componentsExt = srcGrammar.getComponentsExt(XSConstants.ATTRIBUTE_GROUP); + len = componentsExt.getLength(); + + for (int i=0; i<len; i+= 2) { + final String key = (String) componentsExt.item(i); + final int index = key.indexOf(','); + final String location = key.substring(0, index); + final String name = key.substring(index + 1, key.length()); + + srcDecl = (XSAttributeGroupDecl)componentsExt.item(i+1); + dstDecl = dstGrammar.getGlobalAttributeGroupDecl(name, location); + if (dstDecl == null) { + dstGrammar.addGlobalAttributeGroupDecl(srcDecl, location); + } + // REVISIT - do we report an error? + else if (dstDecl != srcDecl) { + } + } + } + + private void addGlobalNotationDecls(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) { + XSNamedMap components = srcGrammar.getComponents(XSConstants.NOTATION_DECLARATION); + int len = components.getLength(); + XSNotationDecl srcDecl, dstDecl; + + // add global components + for (int i=0; i<len; i++) { + srcDecl = (XSNotationDecl) components.item(i); + dstDecl = dstGrammar.getGlobalNotationDecl(srcDecl.getName()); + if (dstDecl == null) { + dstGrammar.addGlobalNotationDecl(srcDecl); + } + else if (dstDecl != srcDecl && !fTolerateDuplicates) { + reportSharingError(srcDecl.getNamespace(), srcDecl.getName()); + } + } + + // add any extended (duplicate) global components + ObjectList componentsExt = srcGrammar.getComponentsExt(XSConstants.NOTATION_DECLARATION); + len = componentsExt.getLength(); + + for (int i=0; i<len; i+= 2) { + final String key = (String) componentsExt.item(i); + final int index = key.indexOf(','); + final String location = key.substring(0, index); + final String name = key.substring(index + 1, key.length()); + + srcDecl = (XSNotationDecl)componentsExt.item(i+1); + dstDecl = dstGrammar.getGlobalNotationDecl(name, location); + if (dstDecl == null) { + dstGrammar.addGlobalNotationDecl(srcDecl, location); + } + // REVISIT - do we report an error? + else if (dstDecl != srcDecl) { + } + } + } + + private void addGlobalGroupDecls(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) { + XSNamedMap components = srcGrammar.getComponents(XSConstants.MODEL_GROUP_DEFINITION); + int len = components.getLength(); + XSGroupDecl srcDecl, dstDecl; + + // add global components + for (int i=0; i<len; i++) { + srcDecl = (XSGroupDecl) components.item(i); + dstDecl = dstGrammar.getGlobalGroupDecl(srcDecl.getName()); + if (dstDecl == null) { + dstGrammar.addGlobalGroupDecl(srcDecl); + } + else if (srcDecl != dstDecl && !fTolerateDuplicates) { + reportSharingError(srcDecl.getNamespace(), srcDecl.getName()); + } + } + + // add any extended (duplicate) global components + ObjectList componentsExt = srcGrammar.getComponentsExt(XSConstants.MODEL_GROUP_DEFINITION); + len = componentsExt.getLength(); + + for (int i=0; i<len; i+= 2) { + final String key = (String) componentsExt.item(i); + final int index = key.indexOf(','); + final String location = key.substring(0, index); + final String name = key.substring(index + 1, key.length()); + + srcDecl = (XSGroupDecl)componentsExt.item(i+1); + dstDecl = dstGrammar.getGlobalGroupDecl(name, location); + if (dstDecl == null) { + dstGrammar.addGlobalGroupDecl(srcDecl, location); + } + // REVIST - do we report an error? + else if (dstDecl != srcDecl) { + } + } + } + + private void addGlobalTypeDecls(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) { + XSNamedMap components = srcGrammar.getComponents(XSConstants.TYPE_DEFINITION); + int len = components.getLength(); + XSTypeDefinition srcDecl, dstDecl; + + // add global components + for (int i=0; i<len; i++) { + srcDecl = (XSTypeDefinition) components.item(i); + dstDecl = dstGrammar.getGlobalTypeDecl(srcDecl.getName()); + if (dstDecl == null) { + dstGrammar.addGlobalTypeDecl(srcDecl); + } + else if (dstDecl != srcDecl && !fTolerateDuplicates) { + reportSharingError(srcDecl.getNamespace(), srcDecl.getName()); + } + } + + // add any extended (duplicate) global components + ObjectList componentsExt = srcGrammar.getComponentsExt(XSConstants.TYPE_DEFINITION); + len = componentsExt.getLength(); + + for (int i=0; i<len; i+= 2) { + final String key = (String) componentsExt.item(i); + final int index = key.indexOf(','); + final String location = key.substring(0, index); + final String name = key.substring(index + 1, key.length()); + + srcDecl = (XSTypeDefinition)componentsExt.item(i+1); + dstDecl = dstGrammar.getGlobalTypeDecl(name, location); + if (dstDecl == null) { + dstGrammar.addGlobalTypeDecl(srcDecl, location); + } + // REVISIT - do we report an error? + else if (dstDecl != srcDecl) { + } + } + } + + private Vector expandComponents(XSObject[] components, Map<String, Vector> dependencies) { + Vector newComponents = new Vector(); + + for (int i=0; i<components.length; i++) { + if (!newComponents.contains(components[i])) { + newComponents.add(components[i]); + } + } + + for (int i=0; i<newComponents.size(); i++) { + final XSObject component = (XSObject) newComponents.elementAt(i); + expandRelatedComponents(component, newComponents, dependencies); + } + + return newComponents; + } + + private void expandRelatedComponents(XSObject component, Vector componentList, Map<String, Vector> dependencies) { + short componentType = component.getType(); + switch (componentType) { + case XSConstants.TYPE_DEFINITION : + expandRelatedTypeComponents((XSTypeDefinition) component, componentList, component.getNamespace(), dependencies); + break; + case XSConstants.ATTRIBUTE_DECLARATION : + expandRelatedAttributeComponents((XSAttributeDeclaration) component, componentList, component.getNamespace(), dependencies); + break; + case XSConstants.ATTRIBUTE_GROUP : + expandRelatedAttributeGroupComponents((XSAttributeGroupDefinition) component, componentList, component.getNamespace(), dependencies); + case XSConstants.ELEMENT_DECLARATION : + expandRelatedElementComponents((XSElementDeclaration) component, componentList, component.getNamespace(), dependencies); + break; + case XSConstants.MODEL_GROUP_DEFINITION : + expandRelatedModelGroupDefinitionComponents((XSModelGroupDefinition) component, componentList, component.getNamespace(), dependencies); + case XSConstants.ATTRIBUTE_USE : + //expandRelatedAttributeUseComponents((XSAttributeUse)component, componentList, dependencies); + case XSConstants.NOTATION_DECLARATION : + case XSConstants.IDENTITY_CONSTRAINT : + default : + break; + } + } + + private void expandRelatedAttributeComponents(XSAttributeDeclaration decl, Vector componentList, String namespace, Map<String, Vector> dependencies) { + addRelatedType(decl.getTypeDefinition(), componentList, namespace, dependencies); + + /*final XSComplexTypeDefinition enclosingType = decl.getEnclosingCTDefinition(); + if (enclosingType != null) { + addRelatedType(enclosingType, componentList, namespace, dependencies); + }*/ + } + + private void expandRelatedElementComponents(XSElementDeclaration decl, Vector componentList, String namespace, Map<String, Vector> dependencies) { + addRelatedType(decl.getTypeDefinition(), componentList, namespace, dependencies); + + /*final XSTypeDefinition enclosingType = decl.getEnclosingCTDefinition(); + if (enclosingType != null) { + addRelatedType(enclosingType, componentList, namespace, dependencies); + }*/ + + final XSElementDeclaration subElemDecl = decl.getSubstitutionGroupAffiliation(); + if (subElemDecl != null) { + addRelatedElement(subElemDecl, componentList, namespace, dependencies); + } + } + + private void expandRelatedTypeComponents(XSTypeDefinition type, Vector componentList, String namespace, Map<String, Vector> dependencies) { + if (type instanceof XSComplexTypeDecl) { + expandRelatedComplexTypeComponents((XSComplexTypeDecl) type, componentList, namespace, dependencies); + } + else if (type instanceof XSSimpleTypeDecl) { + expandRelatedSimpleTypeComponents((XSSimpleTypeDefinition) type, componentList, namespace, dependencies); + } + } + + private void expandRelatedModelGroupDefinitionComponents(XSModelGroupDefinition modelGroupDef, Vector componentList, + String namespace, Map<String, Vector> dependencies) { + expandRelatedModelGroupComponents(modelGroupDef.getModelGroup(), componentList, namespace, dependencies); + } + + private void expandRelatedAttributeGroupComponents(XSAttributeGroupDefinition attrGroup, Vector componentList + , String namespace, Map<String, Vector> dependencies) { + expandRelatedAttributeUsesComponents(attrGroup.getAttributeUses(), componentList, namespace, dependencies); + } + + private void expandRelatedComplexTypeComponents(XSComplexTypeDecl type, Vector componentList, String namespace, Map<String, Vector> dependencies) { + addRelatedType(type.getBaseType(), componentList, namespace, dependencies); + expandRelatedAttributeUsesComponents(type.getAttributeUses(), componentList, namespace, dependencies); + final XSParticle particle = type.getParticle(); + if (particle != null) { + expandRelatedParticleComponents(particle, componentList, namespace, dependencies); + } + } + + private void expandRelatedSimpleTypeComponents(XSSimpleTypeDefinition type, Vector componentList, String namespace, Map<String, Vector> dependencies) { + final XSTypeDefinition baseType = type.getBaseType(); + if (baseType != null) { + addRelatedType(baseType, componentList, namespace, dependencies); + } + + final XSTypeDefinition itemType = type.getItemType(); + if (itemType != null) { + addRelatedType(itemType, componentList, namespace, dependencies); + } + + final XSTypeDefinition primitiveType = type.getPrimitiveType(); + if (primitiveType != null) { + addRelatedType(primitiveType, componentList, namespace, dependencies); + } + + final XSObjectList memberTypes = type.getMemberTypes(); + if (memberTypes.size() > 0) { + for (int i=0; i<memberTypes.size(); i++) { + addRelatedType((XSTypeDefinition)memberTypes.item(i), componentList, namespace, dependencies); + } + } + } + + private void expandRelatedAttributeUsesComponents(XSObjectList attrUses, Vector componentList, + String namespace, Map<String, Vector> dependencies) { + final int attrUseSize = (attrUses == null) ? 0 : attrUses.size(); + for (int i=0; i<attrUseSize; i++) { + expandRelatedAttributeUseComponents((XSAttributeUse)attrUses.item(i), componentList, namespace, dependencies); + } + } + + private void expandRelatedAttributeUseComponents(XSAttributeUse component, Vector componentList, + String namespace, Map<String, Vector> dependencies) { + addRelatedAttribute(component.getAttrDeclaration(), componentList, namespace, dependencies); + } + + private void expandRelatedParticleComponents(XSParticle component, Vector componentList, + String namespace, Map<String, Vector> dependencies) { + XSTerm term = component.getTerm(); + switch (term.getType()) { + case XSConstants.ELEMENT_DECLARATION : + addRelatedElement((XSElementDeclaration) term, componentList, namespace, dependencies); + break; + case XSConstants.MODEL_GROUP : + expandRelatedModelGroupComponents((XSModelGroup) term, componentList, namespace, dependencies); + break; + default: + break; + } + } + + private void expandRelatedModelGroupComponents(XSModelGroup modelGroup, Vector componentList, + String namespace, Map<String, Vector> dependencies) { + XSObjectList particles = modelGroup.getParticles(); + final int length = (particles == null) ? 0 : particles.getLength(); + for (int i=0; i<length; i++) { + expandRelatedParticleComponents((XSParticle)particles.item(i), componentList, namespace, dependencies); + } + } + + private void addRelatedType(XSTypeDefinition type, Vector componentList, String namespace, Map<String, Vector> dependencies) { + if (!type.getAnonymous()) { + if (!type.getNamespace().equals(SchemaSymbols.URI_SCHEMAFORSCHEMA)) { //REVISIT - do we use == instead + if (!componentList.contains(type)) { + final Vector importedNamespaces = findDependentNamespaces(namespace, dependencies); + addNamespaceDependency(namespace, type.getNamespace(), importedNamespaces); + componentList.add(type); + } + } + } + else { + expandRelatedTypeComponents(type, componentList, namespace, dependencies); + } + } + + private void addRelatedElement(XSElementDeclaration decl, Vector componentList, String namespace, Map<String, Vector> dependencies) { + if (decl.getScope() == XSConstants.SCOPE_GLOBAL) { + if (!componentList.contains(decl)) { + Vector importedNamespaces = findDependentNamespaces(namespace, dependencies); + addNamespaceDependency(namespace, decl.getNamespace(), importedNamespaces); + componentList.add(decl); + } + } + else { + expandRelatedElementComponents(decl, componentList, namespace, dependencies); + } + } + + private void addRelatedAttribute(XSAttributeDeclaration decl, Vector componentList, String namespace, Map<String, Vector> dependencies) { + if (decl.getScope() == XSConstants.SCOPE_GLOBAL) { + if (!componentList.contains(decl)) { + Vector importedNamespaces = findDependentNamespaces(namespace, dependencies); + addNamespaceDependency(namespace, decl.getNamespace(), importedNamespaces); + componentList.add(decl); + } + } + else { + expandRelatedAttributeComponents(decl, componentList, namespace, dependencies); + } + } + + private void addGlobalComponents(Vector components, Map<String, Vector> importDependencies) { + final XSDDescription desc = new XSDDescription(); + final int size = components.size(); + + for (int i=0; i<size; i++) { + addGlobalComponent((XSObject) components.elementAt(i), desc); + } + updateImportDependencies(importDependencies); + } + + private void addGlobalComponent(XSObject component, XSDDescription desc) { + final String namespace = component.getNamespace(); + + desc.setNamespace(namespace); + final SchemaGrammar sg = getSchemaGrammar(desc); + + short componentType = component.getType(); + final String name = component.getName(); + + switch (componentType) { + case XSConstants.TYPE_DEFINITION : + if (!((XSTypeDefinition) component).getAnonymous()) { + if (sg.getGlobalTypeDecl(name) == null) { + sg.addGlobalTypeDecl((XSTypeDefinition) component); + } + // store the declaration in the extended map, using an empty location + if (sg.getGlobalTypeDecl(name, "") == null) { + sg.addGlobalTypeDecl((XSTypeDefinition) component, ""); + } + } + break; + case XSConstants.ATTRIBUTE_DECLARATION : + if (((XSAttributeDecl) component).getScope() == XSAttributeDecl.SCOPE_GLOBAL) { + if (sg.getGlobalAttributeDecl(name) == null) { + sg.addGlobalAttributeDecl((XSAttributeDecl) component); + } + // store the declaration in the extended map, using an empty location + if (sg.getGlobalAttributeDecl(name, "") == null) { + sg.addGlobalAttributeDecl((XSAttributeDecl) component, ""); + } + } + break; + case XSConstants.ATTRIBUTE_GROUP : + if (sg.getGlobalAttributeDecl(name) == null) { + sg.addGlobalAttributeGroupDecl((XSAttributeGroupDecl) component); + } + // store the declaration in the extended map, using an empty location + if (sg.getGlobalAttributeDecl(name, "") == null) { + sg.addGlobalAttributeGroupDecl((XSAttributeGroupDecl) component, ""); + } + break; + case XSConstants.ELEMENT_DECLARATION : + if (((XSElementDecl) component).getScope() == XSElementDecl.SCOPE_GLOBAL) { + sg.addGlobalElementDeclAll((XSElementDecl) component); + + if (sg.getGlobalElementDecl(name) == null) { + sg.addGlobalElementDecl((XSElementDecl) component); + } + // store the declaration in the extended map, using an empty location + if (sg.getGlobalElementDecl(name, "") == null) { + sg.addGlobalElementDecl((XSElementDecl) component, ""); + } + } + break; + case XSConstants.MODEL_GROUP_DEFINITION : + if (sg.getGlobalGroupDecl(name) == null) { + sg.addGlobalGroupDecl((XSGroupDecl) component); + } + // store the declaration in the extended map, using an empty location + if (sg.getGlobalGroupDecl(name, "") == null) { + sg.addGlobalGroupDecl((XSGroupDecl) component, ""); + } + break; + case XSConstants.NOTATION_DECLARATION : + if (sg.getGlobalNotationDecl(name) == null) { + sg.addGlobalNotationDecl((XSNotationDecl) component); + } + // store the declaration in the extended map, using an empty location + if (sg.getGlobalNotationDecl(name, "") == null) { + sg.addGlobalNotationDecl((XSNotationDecl) component, ""); + } + break; + case XSConstants.IDENTITY_CONSTRAINT : + case XSConstants.ATTRIBUTE_USE : + default : + break; + } + } + + private void updateImportDependencies(Map<String, Vector> table) { + if (table == null) return; + String namespace; + Vector importList; + + for(Map.Entry<String, Vector> entry : table.entrySet()){ + namespace = entry.getKey(); + importList = entry.getValue(); + if (importList.size() > 0) { + expandImportList(namespace, importList); + } + } + } + + private void expandImportList(String namespace, Vector namespaceList) { + SchemaGrammar sg = fGrammarBucket.getGrammar(namespace); + // shouldn't be null + if (sg != null) { + Vector isgs = sg.getImportedGrammars(); + if (isgs == null) { + isgs = new Vector(); + addImportList(sg, isgs, namespaceList); + sg.setImportedGrammars(isgs); + } + else { + updateImportList(sg, isgs, namespaceList); + } + } + } + + private void addImportList(SchemaGrammar sg, Vector importedGrammars, Vector namespaceList) { + final int size = namespaceList.size(); + SchemaGrammar isg; + + for (int i=0; i<size; i++) { + isg = fGrammarBucket.getGrammar((String)namespaceList.elementAt(i)); + if (isg != null) { + importedGrammars.add(isg); + } + else { + //REVIST: report an error message + } + } + } + + private void updateImportList(SchemaGrammar sg, Vector importedGrammars, Vector namespaceList) { + final int size = namespaceList.size(); + SchemaGrammar isg; + + for (int i=0; i<size; i++) { + isg = fGrammarBucket.getGrammar((String)namespaceList.elementAt(i)); + if (isg != null) { + if (!containedImportedGrammar(importedGrammars, isg)) { + importedGrammars.add(isg); + } + } + else { + //REVIST: report an error message + } + } + } + + private boolean containedImportedGrammar(Vector importedGrammar, SchemaGrammar grammar) { + final int size = importedGrammar.size(); + SchemaGrammar sg; + + for (int i=0; i<size; i++) { + sg = (SchemaGrammar) importedGrammar.elementAt(i); + if (null2EmptyString(sg.getTargetNamespace()).equals(null2EmptyString(grammar.getTargetNamespace()))) { + return true; + } + } + return false; + } + + // NOTE: always assuming that fNamespaceGrowth is enabled + // otherwise the grammar should have existed + private SchemaGrammar getSchemaGrammar(XSDDescription desc) { + SchemaGrammar sg = findGrammar(desc, fNamespaceGrowth); + + if (sg == null) { + sg = new SchemaGrammar(desc.getNamespace(), desc.makeClone(), fSymbolTable); + fGrammarBucket.putGrammar(sg); + } + else if (sg.isImmutable()){ + sg = createGrammarFrom(sg); + } + + return sg; + } + + private Vector findDependentNamespaces(String namespace, Map table) { + final String ns = null2EmptyString(namespace); + Vector namespaceList = (Vector) getFromMap(table, ns); + + if (namespaceList == null) { + namespaceList = new Vector(); + table.put(ns, namespaceList); + } + + return namespaceList; + } + + private void addNamespaceDependency(String namespace1, String namespace2, Vector list) { + final String ns1 = null2EmptyString(namespace1); + final String ns2 = null2EmptyString(namespace2); + if (!ns1.equals(ns2)) { + if (!list.contains(ns2)) { + list.add(ns2); + } + } + } + + private void reportSharingError(String namespace, String name) { + final String qName = (namespace == null) + ? "," + name : namespace + "," + name; + + reportSchemaError("sch-props-correct.2", new Object [] {qName}, null); + } + + // initialize all the traversers. + // this should only need to be called once during the construction + // of this object; it creates the traversers that will be used to + + // construct schemaGrammars. + private void createTraversers() { + fAttributeChecker = new XSAttributeChecker(this); + fAttributeGroupTraverser = new XSDAttributeGroupTraverser(this, fAttributeChecker); + fAttributeTraverser = new XSDAttributeTraverser(this, fAttributeChecker); + fComplexTypeTraverser = new XSDComplexTypeTraverser(this, fAttributeChecker); + fElementTraverser = new XSDElementTraverser(this, fAttributeChecker); + fGroupTraverser = new XSDGroupTraverser(this, fAttributeChecker); + fKeyrefTraverser = new XSDKeyrefTraverser(this, fAttributeChecker); + fNotationTraverser = new XSDNotationTraverser(this, fAttributeChecker); + fSimpleTypeTraverser = new XSDSimpleTypeTraverser(this, fAttributeChecker); + fUniqueOrKeyTraverser = new XSDUniqueOrKeyTraverser(this, fAttributeChecker); + fWildCardTraverser = new XSDWildcardTraverser(this, fAttributeChecker); + } // createTraversers() + + // before parsing a schema, need to clear registries associated with + // parsing schemas + void prepareForParse() { + fTraversed.clear(); + fDoc2SystemId.clear(); + fHiddenNodes.clear(); + fLastSchemaWasDuplicate = false; + } + + // before traversing a schema's parse tree, need to reset all traversers and + // clear all registries + void prepareForTraverse() { + if (!registryEmpty) { + fUnparsedAttributeRegistry.clear(); + fUnparsedAttributeGroupRegistry.clear(); + fUnparsedElementRegistry.clear(); + fUnparsedGroupRegistry.clear(); + fUnparsedIdentityConstraintRegistry.clear(); + fUnparsedNotationRegistry.clear(); + fUnparsedTypeRegistry.clear(); + + fUnparsedAttributeRegistrySub.clear(); + fUnparsedAttributeGroupRegistrySub.clear(); + fUnparsedElementRegistrySub.clear(); + fUnparsedGroupRegistrySub.clear(); + fUnparsedIdentityConstraintRegistrySub.clear(); + fUnparsedNotationRegistrySub.clear(); + fUnparsedTypeRegistrySub.clear(); + } + + for (int i=1; i<= TYPEDECL_TYPE; i++) { + if (fUnparsedRegistriesExt[i] != null) + fUnparsedRegistriesExt[i].clear(); + } + + fDependencyMap.clear(); + fDoc2XSDocumentMap.clear(); + if (fRedefine2XSDMap != null) fRedefine2XSDMap.clear(); + if (fRedefine2NSSupport != null) fRedefine2NSSupport.clear(); + fAllTNSs.removeAllElements(); + fImportMap.clear(); + fRoot = null; + + // clear local element stack + for (int i = 0; i < fLocalElemStackPos; i++) { + fParticle[i] = null; + fLocalElementDecl[i] = null; + fLocalElementDecl_schema[i] = null; + fLocalElemNamespaceContext[i] = null; + } + fLocalElemStackPos = 0; + + // and do same for keyrefs. + for (int i = 0; i < fKeyrefStackPos; i++) { + fKeyrefs[i] = null; + fKeyrefElems[i] = null; + fKeyrefNamespaceContext[i] = null; + fKeyrefsMapXSDocumentInfo[i] = null; + } + fKeyrefStackPos = 0; + + // create traversers if necessary + if (fAttributeChecker == null) { + createTraversers(); + } + + // reset traversers + Locale locale = fErrorReporter.getLocale(); + fAttributeChecker.reset(fSymbolTable); + fAttributeGroupTraverser.reset(fSymbolTable, fValidateAnnotations, locale); + fAttributeTraverser.reset(fSymbolTable, fValidateAnnotations, locale); + fComplexTypeTraverser.reset(fSymbolTable, fValidateAnnotations, locale); + fElementTraverser.reset(fSymbolTable, fValidateAnnotations, locale); + fGroupTraverser.reset(fSymbolTable, fValidateAnnotations, locale); + fKeyrefTraverser.reset(fSymbolTable, fValidateAnnotations, locale); + fNotationTraverser.reset(fSymbolTable, fValidateAnnotations, locale); + fSimpleTypeTraverser.reset(fSymbolTable, fValidateAnnotations, locale); + fUniqueOrKeyTraverser.reset(fSymbolTable, fValidateAnnotations, locale); + fWildCardTraverser.reset(fSymbolTable, fValidateAnnotations, locale); + + fRedefinedRestrictedAttributeGroupRegistry.clear(); + fRedefinedRestrictedGroupRegistry.clear(); + + fGlobalAttrDecls.clear(); + fGlobalAttrGrpDecls.clear(); + fGlobalElemDecls.clear(); + fGlobalGroupDecls.clear(); + fGlobalNotationDecls.clear(); + fGlobalIDConstraintDecls.clear(); + fGlobalTypeDecls.clear(); + } + public void setDeclPool (XSDeclarationPool declPool){ + fDeclPool = declPool; + } + public void setDVFactory(SchemaDVFactory dvFactory){ + fDVFactory = dvFactory; + } + public SchemaDVFactory getDVFactory(){ + return fDVFactory; + } + + public void reset(XMLComponentManager componentManager) { + + // set symbol table + fSymbolTable = (SymbolTable) componentManager.getProperty(SYMBOL_TABLE); + + fSecureProcessing = null; + if( componentManager!=null ) { + fSecureProcessing = (SecurityManager) componentManager.getProperty(SECURE_PROCESSING, null); + } + + //set entity resolver + fEntityResolver = (XMLEntityResolver) componentManager.getProperty(ENTITY_MANAGER); + XMLEntityResolver er = (XMLEntityResolver)componentManager.getProperty(ENTITY_RESOLVER); + if (er != null) + fSchemaParser.setEntityResolver(er); + + // set error reporter + fErrorReporter = + (XMLErrorReporter) componentManager.getProperty(ERROR_REPORTER); + try { + XMLErrorHandler currErrorHandler = fErrorReporter.getErrorHandler(); + // Setting a parser property can be much more expensive + // than checking its value. Don't set the ERROR_HANDLER + // or LOCALE properties unless they've actually changed. + if (currErrorHandler != fSchemaParser.getProperty(ERROR_HANDLER)) { + fSchemaParser.setProperty(ERROR_HANDLER, (currErrorHandler != null) ? currErrorHandler : new DefaultErrorHandler()); + if (fAnnotationValidator != null) { + fAnnotationValidator.setProperty(ERROR_HANDLER, (currErrorHandler != null) ? currErrorHandler : new DefaultErrorHandler()); + } + } + Locale currentLocale = fErrorReporter.getLocale(); + if (currentLocale != fSchemaParser.getProperty(LOCALE)) { + fSchemaParser.setProperty(LOCALE, currentLocale); + if (fAnnotationValidator != null) { + fAnnotationValidator.setProperty(LOCALE, currentLocale); + } + } + } + catch (XMLConfigurationException e) {} + + fValidateAnnotations = componentManager.getFeature(VALIDATE_ANNOTATIONS, false); + fHonourAllSchemaLocations = componentManager.getFeature(HONOUR_ALL_SCHEMALOCATIONS, false); + fNamespaceGrowth = componentManager.getFeature(NAMESPACE_GROWTH, false); + fTolerateDuplicates = componentManager.getFeature(TOLERATE_DUPLICATES, false); + + try { + fSchemaParser.setFeature( + CONTINUE_AFTER_FATAL_ERROR, + fErrorReporter.getFeature(CONTINUE_AFTER_FATAL_ERROR)); + } catch (XMLConfigurationException e) { + } + + try { + if (componentManager.getFeature(ALLOW_JAVA_ENCODINGS, false)) { + fSchemaParser.setFeature(ALLOW_JAVA_ENCODINGS, true); + } + } catch (XMLConfigurationException e) { + } + try { + if (componentManager.getFeature(STANDARD_URI_CONFORMANT_FEATURE, false)) { + fSchemaParser.setFeature(STANDARD_URI_CONFORMANT_FEATURE, true); + } + } catch (XMLConfigurationException e) { + } + + try { + fGrammarPool = + (XMLGrammarPool) componentManager.getProperty(XMLGRAMMAR_POOL); + } catch (XMLConfigurationException e) { + fGrammarPool = null; + } + // security features + try { + if (componentManager.getFeature(DISALLOW_DOCTYPE, false)) { + fSchemaParser.setFeature(DISALLOW_DOCTYPE, true); + } + } catch (XMLConfigurationException e) { + } + try { + Object security = componentManager.getProperty(SECURITY_MANAGER, null); + if (security != null){ + fSchemaParser.setProperty(SECURITY_MANAGER, security); + } + } catch (XMLConfigurationException e) { + } + + } // reset(XMLComponentManager) + + + /** + * Traverse all the deferred local elements. This method should be called + * by traverseSchemas after we've done with all the global declarations. + */ + void traverseLocalElements() { + fElementTraverser.fDeferTraversingLocalElements = false; + + for (int i = 0; i < fLocalElemStackPos; i++) { + Element currElem = fLocalElementDecl[i]; + //XSDocumentInfo currSchema = (XSDocumentInfo)fDoc2XSDocumentMap.get(DOMUtil.getDocument(currElem)); + //XSDocumentInfo currSchema = (XSDocumentInfo)fDoc2XSDocumentMap.get(DOMUtil.getRoot(DOMUtil.getDocument(currElem))); + XSDocumentInfo currSchema = fLocalElementDecl_schema[i]; + SchemaGrammar currGrammar = fGrammarBucket.getGrammar(currSchema.fTargetNamespace); + fElementTraverser.traverseLocal (fParticle[i], currElem, currSchema, currGrammar, fAllContext[i], fParent[i], fLocalElemNamespaceContext[i]); + // If it's an empty particle, remove it from the containing component. + if (fParticle[i].fType == XSParticleDecl.PARTICLE_EMPTY) { + XSModelGroupImpl group = null; + if (fParent[i] instanceof XSComplexTypeDecl) { + XSParticle p = ((XSComplexTypeDecl)fParent[i]).getParticle(); + if (p != null) + group = (XSModelGroupImpl)p.getTerm(); + } + else { + group = ((XSGroupDecl)fParent[i]).fModelGroup; + } + if (group != null) + removeParticle(group, fParticle[i]); + } + } + } + + private boolean removeParticle(XSModelGroupImpl group, XSParticleDecl particle) { + XSParticleDecl member; + for (int i = 0; i < group.fParticleCount; i++) { + member = group.fParticles[i]; + if (member == particle) { + for (int j = i; j < group.fParticleCount-1; j++) + group.fParticles[j] = group.fParticles[j+1]; + group.fParticleCount--; + return true; + } + if (member.fType == XSParticleDecl.PARTICLE_MODELGROUP) { + if (removeParticle((XSModelGroupImpl)member.fValue, particle)) + return true; + } + } + return false; + } + + // the purpose of this method is to keep up-to-date structures + // we'll need for the feferred traversal of local elements. + void fillInLocalElemInfo(Element elmDecl, + XSDocumentInfo schemaDoc, + int allContextFlags, + XSObject parent, + XSParticleDecl particle) { + + // if the stack is full, increase the size + if (fParticle.length == fLocalElemStackPos) { + // increase size + XSParticleDecl[] newStackP = new XSParticleDecl[fLocalElemStackPos+INC_STACK_SIZE]; + System.arraycopy(fParticle, 0, newStackP, 0, fLocalElemStackPos); + fParticle = newStackP; + Element[] newStackE = new Element[fLocalElemStackPos+INC_STACK_SIZE]; + System.arraycopy(fLocalElementDecl, 0, newStackE, 0, fLocalElemStackPos); + fLocalElementDecl = newStackE; + XSDocumentInfo [] newStackE_schema = new XSDocumentInfo[fLocalElemStackPos+INC_STACK_SIZE]; + System.arraycopy(fLocalElementDecl_schema, 0, newStackE_schema, 0, fLocalElemStackPos); + fLocalElementDecl_schema = newStackE_schema; + int[] newStackI = new int[fLocalElemStackPos+INC_STACK_SIZE]; + System.arraycopy(fAllContext, 0, newStackI, 0, fLocalElemStackPos); + fAllContext = newStackI; + XSObject[] newStackC = new XSObject[fLocalElemStackPos+INC_STACK_SIZE]; + System.arraycopy(fParent, 0, newStackC, 0, fLocalElemStackPos); + fParent = newStackC; + String [][] newStackN = new String [fLocalElemStackPos+INC_STACK_SIZE][]; + System.arraycopy(fLocalElemNamespaceContext, 0, newStackN, 0, fLocalElemStackPos); + fLocalElemNamespaceContext = newStackN; + } + + fParticle[fLocalElemStackPos] = particle; + fLocalElementDecl[fLocalElemStackPos] = elmDecl; + fLocalElementDecl_schema[fLocalElemStackPos] = schemaDoc; + fAllContext[fLocalElemStackPos] = allContextFlags; + fParent[fLocalElemStackPos] = parent; + fLocalElemNamespaceContext[fLocalElemStackPos++] = schemaDoc.fNamespaceSupport.getEffectiveLocalContext(); + } // end fillInLocalElemInfo(...) + + /** This method makes sure that + * if this component is being redefined that it lives in the + * right schema. It then renames the component correctly. If it + * detects a collision--a duplicate definition--then it complains. + * Note that redefines must be handled carefully: if there + * is a collision, it may be because we're redefining something we know about + * or because we've found the thing we're redefining. + */ + void checkForDuplicateNames(String qName, int declType, + Map<String,Element> registry, Map<String,XSDocumentInfo> registry_sub, Element currComp, + XSDocumentInfo currSchema) { + Object objElem = null; + // REVISIT: when we add derivation checking, we'll have to make + // sure that ID constraint collisions don't necessarily result in error messages. + if ((objElem = registry.get(qName)) == null) { + // need to check whether we have a global declaration in the corresponding + // grammar + if (fNamespaceGrowth && !fTolerateDuplicates) { + checkForDuplicateNames(qName, declType, currComp); + } + // just add it in! + registry.put(qName, currComp); + registry_sub.put(qName, currSchema); + } + else { + Element collidingElem = (Element)objElem; + XSDocumentInfo collidingElemSchema = (XSDocumentInfo)registry_sub.get(qName); + if (collidingElem == currComp) return; + Element elemParent = null; + XSDocumentInfo redefinedSchema = null; + // case where we've collided with a redefining element + // (the parent of the colliding element is a redefine) + boolean collidedWithRedefine = true; + if ((DOMUtil.getLocalName((elemParent = DOMUtil.getParent(collidingElem))).equals(SchemaSymbols.ELT_REDEFINE))) { + redefinedSchema = (fRedefine2XSDMap != null)?(XSDocumentInfo) (fRedefine2XSDMap.get(elemParent)): null; + // case where we're a redefining element. + } + else if ((DOMUtil.getLocalName(DOMUtil.getParent(currComp)).equals(SchemaSymbols.ELT_REDEFINE))) { + redefinedSchema = collidingElemSchema; + collidedWithRedefine = false; + } + if (redefinedSchema != null) { //redefinition involved somehow + // If both components belong to the same document then + // report an error and return. + if(collidingElemSchema == currSchema){ + reportSchemaError("sch-props-correct.2", new Object[]{qName}, currComp); + return; + } + + String newName = qName.substring(qName.lastIndexOf(',')+1)+REDEF_IDENTIFIER; + if (redefinedSchema == currSchema) { // object comp. okay here + // now have to do some renaming... + currComp.setAttribute(SchemaSymbols.ATT_NAME, newName); + if (currSchema.fTargetNamespace == null){ + registry.put(","+newName, currComp); + registry_sub.put(","+newName, currSchema); + } + else{ + registry.put(currSchema.fTargetNamespace+","+newName, currComp); + registry_sub.put(currSchema.fTargetNamespace+","+newName, currSchema); + } + // and take care of nested redefines by calling recursively: + if (currSchema.fTargetNamespace == null) + checkForDuplicateNames(","+newName, declType, registry, registry_sub, currComp, currSchema); + else + checkForDuplicateNames(currSchema.fTargetNamespace+","+newName, declType, registry, registry_sub, currComp, currSchema); + } + else { // we may be redefining the wrong schema + if (collidedWithRedefine) { + if (currSchema.fTargetNamespace == null) + checkForDuplicateNames(","+newName, declType, registry, registry_sub, currComp, currSchema); + else + checkForDuplicateNames(currSchema.fTargetNamespace+","+newName, declType, registry, registry_sub, currComp, currSchema); + } + else { + // error that redefined element in wrong schema + reportSchemaError("sch-props-correct.2", new Object [] {qName}, currComp); + } + } + } + else { + // we've just got a flat-out collision (we tolerate duplicate + // declarations, only if they are defined in different schema + // documents) + if (!fTolerateDuplicates) { + reportSchemaError("sch-props-correct.2", new Object []{qName}, currComp); + } else if (fUnparsedRegistriesExt[declType] != null) { + if (fUnparsedRegistriesExt[declType].get(qName) == currSchema) { + reportSchemaError("sch-props-correct.2", new Object []{qName}, currComp); + } + } + } + } + + // store the lastest current document info + if (fTolerateDuplicates) { + if (fUnparsedRegistriesExt[declType] == null) + fUnparsedRegistriesExt[declType] = new HashMap(); + fUnparsedRegistriesExt[declType].put(qName, currSchema); + } + + } // checkForDuplicateNames(String, Hashtable, Element, XSDocumentInfo):void + + void checkForDuplicateNames(String qName, int declType, Element currComp) { + int namespaceEnd = qName.indexOf(','); + String namespace = qName.substring(0, namespaceEnd); + SchemaGrammar grammar = fGrammarBucket.getGrammar(emptyString2Null(namespace)); + + if (grammar != null) { + Object obj = getGlobalDeclFromGrammar(grammar, declType, qName.substring(namespaceEnd + 1)); + if (obj != null) { + reportSchemaError("sch-props-correct.2", new Object []{qName}, currComp); + } + } + } + + // the purpose of this method is to take the component of the + // specified type and rename references to itself so that they + // refer to the object being redefined. It takes special care of + // <group>s and <attributeGroup>s to ensure that information + // relating to implicit restrictions is preserved for those + // traversers. + private void renameRedefiningComponents(XSDocumentInfo currSchema, + Element child, String componentType, + String oldName, String newName) { + if (componentType.equals(SchemaSymbols.ELT_SIMPLETYPE)) { + Element grandKid = DOMUtil.getFirstChildElement(child); + if (grandKid == null) { + reportSchemaError("src-redefine.5.a.a", null, child); + } + else { + String grandKidName = DOMUtil.getLocalName(grandKid); + if (grandKidName.equals(SchemaSymbols.ELT_ANNOTATION)) { + grandKid = DOMUtil.getNextSiblingElement(grandKid); + } + if (grandKid == null) { + reportSchemaError("src-redefine.5.a.a", null, child); + } + else { + grandKidName = DOMUtil.getLocalName(grandKid); + if (!grandKidName.equals(SchemaSymbols.ELT_RESTRICTION)) { + reportSchemaError("src-redefine.5.a.b", new Object[]{grandKidName}, child); + } + else { + Object[] attrs = fAttributeChecker.checkAttributes(grandKid, false, currSchema); + QName derivedBase = (QName)attrs[XSAttributeChecker.ATTIDX_BASE]; + if (derivedBase == null || + derivedBase.uri != currSchema.fTargetNamespace || + !derivedBase.localpart.equals(oldName)) { + reportSchemaError("src-redefine.5.a.c", + new Object[]{grandKidName, + (currSchema.fTargetNamespace==null?"":currSchema.fTargetNamespace) + + "," + oldName}, + child); + } + else { + // now we have to do the renaming... + if (derivedBase.prefix != null && derivedBase.prefix.length() > 0) + grandKid.setAttribute( SchemaSymbols.ATT_BASE, + derivedBase.prefix + ":" + newName ); + else + grandKid.setAttribute( SchemaSymbols.ATT_BASE, newName ); + // return true; + } + fAttributeChecker.returnAttrArray(attrs, currSchema); + } + } + } + } + else if (componentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) { + Element grandKid = DOMUtil.getFirstChildElement(child); + if (grandKid == null) { + reportSchemaError("src-redefine.5.b.a", null, child); + } + else { + if (DOMUtil.getLocalName(grandKid).equals(SchemaSymbols.ELT_ANNOTATION)) { + grandKid = DOMUtil.getNextSiblingElement(grandKid); + } + if (grandKid == null) { + reportSchemaError("src-redefine.5.b.a", null, child); + } + else { + // have to go one more level down; let another pass worry whether complexType is valid. + Element greatGrandKid = DOMUtil.getFirstChildElement(grandKid); + if (greatGrandKid == null) { + reportSchemaError("src-redefine.5.b.b", null, grandKid); + } + else { + String greatGrandKidName = DOMUtil.getLocalName(greatGrandKid); + if (greatGrandKidName.equals(SchemaSymbols.ELT_ANNOTATION)) { + greatGrandKid = DOMUtil.getNextSiblingElement(greatGrandKid); + } + if (greatGrandKid == null) { + reportSchemaError("src-redefine.5.b.b", null, grandKid); + } + else { + greatGrandKidName = DOMUtil.getLocalName(greatGrandKid); + if (!greatGrandKidName.equals(SchemaSymbols.ELT_RESTRICTION) && + !greatGrandKidName.equals(SchemaSymbols.ELT_EXTENSION)) { + reportSchemaError("src-redefine.5.b.c", new Object[]{greatGrandKidName}, greatGrandKid); + } + else { + Object[] attrs = fAttributeChecker.checkAttributes(greatGrandKid, false, currSchema); + QName derivedBase = (QName)attrs[XSAttributeChecker.ATTIDX_BASE]; + if (derivedBase == null || + derivedBase.uri != currSchema.fTargetNamespace || + !derivedBase.localpart.equals(oldName)) { + reportSchemaError("src-redefine.5.b.d", + new Object[]{greatGrandKidName, + (currSchema.fTargetNamespace==null?"":currSchema.fTargetNamespace) + + "," + oldName}, + greatGrandKid); + } + else { + // now we have to do the renaming... + if (derivedBase.prefix != null && derivedBase.prefix.length() > 0) + greatGrandKid.setAttribute( SchemaSymbols.ATT_BASE, + derivedBase.prefix + ":" + newName ); + else + greatGrandKid.setAttribute( SchemaSymbols.ATT_BASE, + newName ); + // return true; + } + } + } + } + } + } + } + else if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) { + String processedBaseName = (currSchema.fTargetNamespace == null)? + ","+oldName:currSchema.fTargetNamespace+","+oldName; + int attGroupRefsCount = changeRedefineGroup(processedBaseName, componentType, newName, child, currSchema); + if (attGroupRefsCount > 1) { + reportSchemaError("src-redefine.7.1", new Object []{new Integer(attGroupRefsCount)}, child); + } + else if (attGroupRefsCount == 1) { + // return true; + } + else + if (currSchema.fTargetNamespace == null) + fRedefinedRestrictedAttributeGroupRegistry.put(processedBaseName, ","+newName); + else + fRedefinedRestrictedAttributeGroupRegistry.put(processedBaseName, currSchema.fTargetNamespace+","+newName); + } + else if (componentType.equals(SchemaSymbols.ELT_GROUP)) { + String processedBaseName = (currSchema.fTargetNamespace == null)? + ","+oldName:currSchema.fTargetNamespace+","+oldName; + int groupRefsCount = changeRedefineGroup(processedBaseName, componentType, newName, child, currSchema); + if (groupRefsCount > 1) { + reportSchemaError("src-redefine.6.1.1", new Object []{new Integer(groupRefsCount)}, child); + } + else if (groupRefsCount == 1) { + // return true; + } + else { + if (currSchema.fTargetNamespace == null) + fRedefinedRestrictedGroupRegistry.put(processedBaseName, ","+newName); + else + fRedefinedRestrictedGroupRegistry.put(processedBaseName, currSchema.fTargetNamespace+","+newName); + } + } + else { + reportSchemaError("Internal-Error", new Object [] {"could not handle this particular <redefine>; please submit your schemas and instance document in a bug report!"}, child); + } + // if we get here then we must have reported an error and failed somewhere... + // return false; + } // renameRedefiningComponents(XSDocumentInfo, Element, String, String, String):void + + // this method takes a name of the form a:b, determines the URI mapped + // to by a in the current SchemaNamespaceSupport object, and returns this + // information in the form (nsURI,b) suitable for lookups in the global + // decl Hashtables. + // REVISIT: should have it return QName, instead of String. this would + // save lots of string concatenation time. we can use + // QName#equals() to compare two QNames, and use QName directly + // as a key to the SymbolHash. + // And when the DV's are ready to return compiled values from + // validate() method, we should just call QNameDV.validate() + // in this method. + private String findQName(String name, XSDocumentInfo schemaDoc) { + SchemaNamespaceSupport currNSMap = schemaDoc.fNamespaceSupport; + int colonPtr = name.indexOf(':'); + String prefix = XMLSymbols.EMPTY_STRING; + if (colonPtr > 0) + prefix = name.substring(0, colonPtr); + String uri = currNSMap.getURI(fSymbolTable.addSymbol(prefix)); + String localpart = (colonPtr == 0)?name:name.substring(colonPtr+1); + if (prefix == XMLSymbols.EMPTY_STRING && uri == null && schemaDoc.fIsChameleonSchema) + uri = schemaDoc.fTargetNamespace; + if (uri == null) + return ","+localpart; + return uri+","+localpart; + } // findQName(String, XSDocumentInfo): String + + // This function looks among the children of curr for an element of type elementSought. + // If it finds one, it evaluates whether its ref attribute contains a reference + // to originalQName. If it does, it returns 1 + the value returned by + // calls to itself on all other children. In all other cases it returns 0 plus + // the sum of the values returned by calls to itself on curr's children. + // It also resets the value of ref so that it will refer to the renamed type from the schema + // being redefined. + private int changeRedefineGroup(String originalQName, String elementSought, + String newName, Element curr, XSDocumentInfo schemaDoc) { + int result = 0; + for (Element child = DOMUtil.getFirstChildElement(curr); + child != null; child = DOMUtil.getNextSiblingElement(child)) { + String name = DOMUtil.getLocalName(child); + if (!name.equals(elementSought)) + result += changeRedefineGroup(originalQName, elementSought, newName, child, schemaDoc); + else { + String ref = child.getAttribute( SchemaSymbols.ATT_REF ); + if (ref.length() != 0) { + String processedRef = findQName(ref, schemaDoc); + if (originalQName.equals(processedRef)) { + String prefix = XMLSymbols.EMPTY_STRING; + int colonptr = ref.indexOf(":"); + if (colonptr > 0) { + prefix = ref.substring(0,colonptr); + child.setAttribute(SchemaSymbols.ATT_REF, prefix + ":" + newName); + } + else + child.setAttribute(SchemaSymbols.ATT_REF, newName); + result++; + if (elementSought.equals(SchemaSymbols.ELT_GROUP)) { + String minOccurs = child.getAttribute( SchemaSymbols.ATT_MINOCCURS ); + String maxOccurs = child.getAttribute( SchemaSymbols.ATT_MAXOCCURS ); + if (!((maxOccurs.length() == 0 || maxOccurs.equals("1")) + && (minOccurs.length() == 0 || minOccurs.equals("1")))) { + reportSchemaError("src-redefine.6.1.2", new Object [] {ref}, child); + } + } + } + } // if ref was null some other stage of processing will flag the error + } + } + return result; + } // changeRedefineGroup + + // this method returns the XSDocumentInfo object that contains the + // component corresponding to decl. If components from this + // document cannot be referred to from those of currSchema, this + // method returns null; it's up to the caller to throw an error. + // @param: currSchema: the XSDocumentInfo object containing the + // decl ref'ing us. + // @param: decl: the declaration being ref'd. + // this method is superficial now. ---Jack + private XSDocumentInfo findXSDocumentForDecl(XSDocumentInfo currSchema, + Element decl, XSDocumentInfo decl_Doc) { + + if (DEBUG_NODE_POOL) { + System.out.println("DOCUMENT NS:"+ currSchema.fTargetNamespace+" hashcode:"+ ((Object)currSchema.fSchemaElement).hashCode()); + } + Object temp = decl_Doc; + if (temp == null) { + // something went badly wrong; we don't know this doc? + return null; + } + XSDocumentInfo declDocInfo = (XSDocumentInfo)temp; + return declDocInfo; + /********* + Logic here is unnecessary after schema WG's recent decision to allow + schema components from one document to refer to components of any other, + so long as there's some include/import/redefine path amongst them. + If they rver reverse this decision the code's right here though... - neilg + // now look in fDependencyMap to see if this is reachable + if(((Vector)fDependencyMap.get(currSchema)).contains(declDocInfo)) { + return declDocInfo; + } + // obviously the requesting doc didn't include, redefine or + // import the one containing decl... + return null; + **********/ + } // findXSDocumentForDecl(XSDocumentInfo, Element): XSDocumentInfo + + // returns whether more than <annotation>s occur in children of elem + private boolean nonAnnotationContent(Element elem) { + for(Element child = DOMUtil.getFirstChildElement(elem); child != null; child = DOMUtil.getNextSiblingElement(child)) { + if(!(DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION))) return true; + } + return false; + } // nonAnnotationContent(Element): boolean + + private void setSchemasVisible(XSDocumentInfo startSchema) { + if (DOMUtil.isHidden(startSchema.fSchemaElement, fHiddenNodes)) { + // make it visible + DOMUtil.setVisible(startSchema.fSchemaElement, fHiddenNodes); + Vector dependingSchemas = (Vector)fDependencyMap.get(startSchema); + for (int i = 0; i < dependingSchemas.size(); i++) { + setSchemasVisible((XSDocumentInfo)dependingSchemas.elementAt(i)); + } + } + // if it's visible already than so must be its children + } // setSchemasVisible(XSDocumentInfo): void + + private SimpleLocator xl = new SimpleLocator(); + + /** + * Extract location information from an Element node, and create a + * new SimpleLocator object from such information. Returning null means + * no information can be retrieved from the element. + */ + public SimpleLocator element2Locator(Element e) { + if (!( e instanceof ElementImpl)) + return null; + + SimpleLocator l = new SimpleLocator(); + return element2Locator(e, l) ? l : null; + } + + /** + * Extract location information from an Element node, store such + * information in the passed-in SimpleLocator object, then return + * true. Returning false means can't extract or store such information. + */ + public boolean element2Locator(Element e, SimpleLocator l) { + if (l == null) + return false; + if (e instanceof ElementImpl) { + ElementImpl ele = (ElementImpl)e; + // get system id from document object + Document doc = ele.getOwnerDocument(); + String sid = (String)fDoc2SystemId.get(DOMUtil.getRoot(doc)); + // line/column numbers are stored in the element node + int line = ele.getLineNumber(); + int column = ele.getColumnNumber(); + l.setValues(sid, sid, line, column, ele.getCharacterOffset()); + return true; + } + return false; + } + + private Element getElementFromMap(Map<String, Element> registry, String declKey) { + if (registry == null) return null; + return registry.get(declKey); + } + + private XSDocumentInfo getDocInfoFromMap(Map<String, XSDocumentInfo> registry, String declKey) { + if (registry == null) return null; + return registry.get(declKey); + } + + private Object getFromMap(Map registry, String key) { + if (registry == null) return null; + return registry.get(key); + } + + void reportSchemaFatalError(String key, Object[] args, Element ele) { + reportSchemaErr(key, args, ele, XMLErrorReporter.SEVERITY_FATAL_ERROR, null); + } + + void reportSchemaError(String key, Object[] args, Element ele) { + reportSchemaErr(key, args, ele, XMLErrorReporter.SEVERITY_ERROR, null); + } + + void reportSchemaError(String key, Object[] args, Element ele, Exception exception) { + reportSchemaErr(key, args, ele, XMLErrorReporter.SEVERITY_ERROR, exception); + } + + void reportSchemaWarning(String key, Object[] args, Element ele) { + reportSchemaErr(key, args, ele, XMLErrorReporter.SEVERITY_WARNING, null); + } + + void reportSchemaWarning(String key, Object[] args, Element ele, Exception exception) { + reportSchemaErr(key, args, ele, XMLErrorReporter.SEVERITY_WARNING, exception); + } + + void reportSchemaErr(String key, Object[] args, Element ele, short type, Exception exception) { + if (element2Locator(ele, xl)) { + fErrorReporter.reportError(xl, XSMessageFormatter.SCHEMA_DOMAIN, + key, args, type, exception); + } + else { + fErrorReporter.reportError(XSMessageFormatter.SCHEMA_DOMAIN, + key, args, type, exception); + } + } + + /** + * Grammar pool used for validating annotations. This will return all of the + * grammars from the grammar bucket. It will also return an object for the + * schema for schemas which will contain at least the relevant declarations + * for annotations. + */ + private static class XSAnnotationGrammarPool implements XMLGrammarPool { + + private XSGrammarBucket fGrammarBucket; + private Grammar [] fInitialGrammarSet; + + public Grammar[] retrieveInitialGrammarSet(String grammarType) { + if (grammarType == XMLGrammarDescription.XML_SCHEMA) { + if (fInitialGrammarSet == null) { + if (fGrammarBucket == null) { + fInitialGrammarSet = new Grammar [] {SchemaGrammar.Schema4Annotations.INSTANCE}; + } + else { + SchemaGrammar [] schemaGrammars = fGrammarBucket.getGrammars(); + /** + * If the grammar bucket already contains the schema for schemas + * then we already have the definitions for the parts relevant + * to annotations. + */ + for (int i = 0; i < schemaGrammars.length; ++i) { + if (SchemaSymbols.URI_SCHEMAFORSCHEMA.equals(schemaGrammars[i].getTargetNamespace())) { + fInitialGrammarSet = schemaGrammars; + return fInitialGrammarSet; + } + } + Grammar [] grammars = new Grammar[schemaGrammars.length + 1]; + System.arraycopy(schemaGrammars, 0, grammars, 0, schemaGrammars.length); + grammars[grammars.length - 1] = SchemaGrammar.Schema4Annotations.INSTANCE; + fInitialGrammarSet = grammars; + } + } + return fInitialGrammarSet; + } + return new Grammar[0]; + } + + public void cacheGrammars(String grammarType, Grammar[] grammars) { + + } + + public Grammar retrieveGrammar(XMLGrammarDescription desc) { + if (desc.getGrammarType() == XMLGrammarDescription.XML_SCHEMA) { + final String tns = ((XMLSchemaDescription) desc).getTargetNamespace(); + if (fGrammarBucket != null) { + Grammar grammar = fGrammarBucket.getGrammar(tns); + if (grammar != null) { + return grammar; + } + } + if (SchemaSymbols.URI_SCHEMAFORSCHEMA.equals(tns)) { + return SchemaGrammar.Schema4Annotations.INSTANCE; + } + } + return null; + } + + public void refreshGrammars(XSGrammarBucket gBucket) { + fGrammarBucket = gBucket; + fInitialGrammarSet = null; + } + + public void lockPool() {} + + public void unlockPool() {} + + public void clear() {} + } + + /** + * used to identify a reference to a schema document + * if the same document is referenced twice with the same key, then + * we only need to parse it once. + * + * When 2 XSDKey's are compared, the following table can be used to + * determine whether they are equal: + * inc red imp pre ins + * inc N/L ? N/L N/L N/L + * red ? N/L ? ? ? + * imp N/L ? N/P N/P N/P + * pre N/L ? N/P N/P N/P + * ins N/L ? N/P N/P N/P + * + * Where: N/L: duplicate when they have the same namespace and location. + * ? : not clear from the spec. + * REVISIT: to simplify the process, also considering + * it's very rare, we treat them as not duplicate. + * N/P: not possible. imp/pre/ins are referenced by namespace. + * when the first time we encounter a schema document for a + * namespace, we create a grammar and store it in the grammar + * bucket. when we see another reference to the same namespace, + * we first check whether a grammar with the same namespace is + * already in the bucket, which is true in this case, so we + * won't create another XSDKey. + * + * Conclusion from the table: two XSDKey's are duplicate only when all of + * the following are true: + * 1. They are both "redefine", or neither is "redefine"; + * 2. They have the same namespace; + * 3. They have the same non-null location. + * + * About 3: if neither has a non-null location, then it's the case where + * 2 input streams are provided, but no system ID is provided. We can't tell + * whether the 2 streams have the same content, so we treat them as not + * duplicate. + */ + private static class XSDKey { + String systemId; + short referType; + // for inclue/redefine, this is the enclosing namespace + // for import/preparse/instance, this is the target namespace + String referNS; + + XSDKey(String systemId, short referType, String referNS) { + this.systemId = systemId; + this.referType = referType; + this.referNS = referNS; + } + + public int hashCode() { + // according to the description at the beginning of this class, + // we use the hashcode of the namespace as the hashcoe of this key. + return referNS == null ? 0 : referNS.hashCode(); + } + + public boolean equals(Object obj) { + if (!(obj instanceof XSDKey)) { + return false; + } + XSDKey key = (XSDKey)obj; + + // condition 1: both are redefine + /** if (referType == XSDDescription.CONTEXT_REDEFINE || + key.referType == XSDDescription.CONTEXT_REDEFINE) { + if (referType != key.referType) + return false; + }**/ + + // condition 2: same namespace + if (referNS != key.referNS) + return false; + + // condition 3: same non-null location + if (systemId == null || !systemId.equals(key.systemId)) { + return false; + } + + return true; + } + } + + private static final class SAX2XNIUtil extends ErrorHandlerWrapper { + public static XMLParseException createXMLParseException0(SAXParseException exception) { + return createXMLParseException(exception); + } + public static XNIException createXNIException0(SAXException exception) { + return createXNIException(exception); + } + } + + /** + * @param state + */ + public void setGenerateSyntheticAnnotations(boolean state) { + fSchemaParser.setFeature(GENERATE_SYNTHETIC_ANNOTATIONS, state); + } + +} // XSDHandler |