/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 2002-2004 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Xerces" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
* originally based on software copyright (c) 2001, International
* Business Machines, Inc., http://www.apache.org. For more
* information on the Apache Software Foundation, please see
* .
*/
package com.sun.org.apache.xerces.internal.impl.xs;
import java.util.Vector;
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.XSConstants;
import com.sun.org.apache.xerces.internal.xs.XSElementDeclaration;
import com.sun.org.apache.xerces.internal.xs.XSModel;
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.XSNamespaceItemList;
import com.sun.org.apache.xerces.internal.xs.XSNotationDeclaration;
import com.sun.org.apache.xerces.internal.xs.XSObjectList;
import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition;
import com.sun.org.apache.xerces.internal.impl.xs.util.NSItemListImpl;
import com.sun.org.apache.xerces.internal.impl.xs.util.StringListImpl;
import com.sun.org.apache.xerces.internal.impl.xs.util.XSNamedMap4Types;
import com.sun.org.apache.xerces.internal.impl.xs.util.XSNamedMapImpl;
import com.sun.org.apache.xerces.internal.impl.xs.util.XSObjectListImpl;
import com.sun.org.apache.xerces.internal.util.SymbolHash;
import com.sun.org.apache.xerces.internal.util.XMLSymbols;
/**
* @author elitani
*
* To change this generated comment edit the template variable "typecomment":
* Window>Preferences>Java>Templates.
* To enable and disable the creation of type comments go to
* Window>Preferences>Java>Code Generation.
*/
/**
* @author elitani
*
* To change this generated comment edit the template variable "typecomment":
* Window>Preferences>Java>Templates.
* To enable and disable the creation of type comments go to
* Window>Preferences>Java>Code Generation.
*/
/**
* Implements XSModel: a read-only interface that represents an XML Schema,
* which could be components from different namespaces.
*
* @author Sandy Gao, IBM
*
* @version $Id: XSModelImpl.java,v 1.12 2004/02/03 17:10:38 sandygao Exp $
*/
public class XSModelImpl implements XSModel {
// the max index / the max value of XSObject type
private static final short MAX_COMP_IDX = XSTypeDefinition.SIMPLE_TYPE;
private static final boolean[] GLOBAL_COMP = {false, // null
true, // attribute
true, // element
true, // type
false, // attribute use
true, // attribute group
true, // group
false, // model group
false, // particle
false, // wildcard
false, // idc
true, // notation
false, // annotation
false, // facet
false, // multi value facet
true, // complex type
true // simple type
};
// number of grammars/namespaces stored here
private int fGrammarCount;
// all target namespaces
private String[] fNamespaces;
// all schema grammar objects (for each namespace)
private SchemaGrammar[] fGrammarList;
// a map from namespace to schema grammar
private SymbolHash fGrammarMap;
// a map from element declaration to its substitution group
private SymbolHash fSubGroupMap;
// store a certain kind of components from all namespaces
private XSNamedMap[] fGlobalComponents;
// store a certain kind of components from one namespace
private XSNamedMap[][] fNSComponents;
// store all annotations
private XSObjectListImpl fAnnotations = null;
// whether there is any IDC in this XSModel
private boolean fHasIDC = false;
/**
* Construct an XSModelImpl, by storing some grammars and grammars imported
* by them to this object.
*
* @param grammars the array of schema grammars
*/
public XSModelImpl(SchemaGrammar[] grammars) {
// copy namespaces/grammars from the array to our arrays
int len = grammars.length;
fNamespaces = new String[Math.max(len+1, 5)];
fGrammarList = new SchemaGrammar[Math.max(len+1, 5)];
boolean hasS4S = false;
for (int i = 0; i < len; i++) {
fNamespaces[i] = grammars[i].getTargetNamespace();
fGrammarList[i] = grammars[i];
if (fNamespaces[i] == SchemaSymbols.URI_SCHEMAFORSCHEMA)
hasS4S = true;
}
// If a schema for the schema namespace isn't included, include it here.
if (!hasS4S) {
fNamespaces[len] = SchemaSymbols.URI_SCHEMAFORSCHEMA;
fGrammarList[len++] = SchemaGrammar.SG_SchemaNS;
}
SchemaGrammar sg1, sg2;
Vector gs;
int i, j, k;
// and recursively get all imported grammars, add them to our arrays
for (i = 0; i < len; i++) {
// get the grammar
sg1 = fGrammarList[i];
gs = sg1.getImportedGrammars();
// for each imported grammar
for (j = gs == null ? -1 : gs.size() - 1; j >= 0; j--) {
sg2 = (SchemaGrammar)gs.elementAt(j);
// check whether this grammar is already in the list
for (k = 0; k < len; k++) {
if (sg2 == fGrammarList[k])
break;
}
// if it's not, add it to the list
if (k == len) {
// ensure the capacity of the arrays
if (len == fGrammarList.length) {
String[] newSA = new String[len*2];
System.arraycopy(fNamespaces, 0, newSA, 0, len);
fNamespaces = newSA;
SchemaGrammar[] newGA = new SchemaGrammar[len*2];
System.arraycopy(fGrammarList, 0, newGA, 0, len);
fGrammarList = newGA;
}
fNamespaces[len] = sg2.getTargetNamespace();
fGrammarList[len] = sg2;
len++;
}
}
}
// establish the mapping from namespace to grammars
fGrammarMap = new SymbolHash(len*2);
for (i = 0; i < len; i++) {
fGrammarMap.put(null2EmptyString(fNamespaces[i]), fGrammarList[i]);
// update the idc field
if (fGrammarList[i].hasIDConstraints())
fHasIDC = true;
}
fGrammarCount = len;
fGlobalComponents = new XSNamedMap[MAX_COMP_IDX+1];
fNSComponents = new XSNamedMap[len][MAX_COMP_IDX+1];
// build substitution groups
buildSubGroups();
}
private void buildSubGroups() {
SubstitutionGroupHandler sgHandler = new SubstitutionGroupHandler(null);
for (int i = 0 ; i < fGrammarCount; i++) {
sgHandler.addSubstitutionGroup(fGrammarList[i].getSubstitutionGroups());
}
XSNamedMap elements = getComponents(XSConstants.ELEMENT_DECLARATION);
int len = elements.getLength();
fSubGroupMap = new SymbolHash(len*2);
XSElementDecl head;
XSElementDeclaration[] subGroup;
for (int i = 0; i < len; i++) {
head = (XSElementDecl)elements.item(i);
subGroup = sgHandler.getSubstitutionGroup(head);
fSubGroupMap.put(head, new XSObjectListImpl(subGroup, subGroup.length));
}
}
/**
* Convenience method. Returns a list of all namespaces that belong to
* this schema.
* @return A list of all namespaces that belong to this schema or
* null
if all components don't have a targetNamespace.
*/
public StringList getNamespaces() {
// REVISIT: should the type of fNamespace be StringListImpl?
return new StringListImpl(fNamespaces, fGrammarCount);
}
public XSNamespaceItemList getNamespaceItems() {
// REVISIT: should the type of fGrammarList be NSItemListImpl?
return new NSItemListImpl(fGrammarList, fGrammarCount);
}
/**
* Returns a list of top-level components, i.e. element declarations,
* attribute declarations, etc.
* @param objectType The type of the declaration, i.e.
* ELEMENT_DECLARATION, ATTRIBUTE_DECLARATION, etc.
* @return A list of top-level definition of the specified type in
* objectType
or null
.
*/
public synchronized XSNamedMap getComponents(short objectType) {
if (objectType <= 0 || objectType > MAX_COMP_IDX ||
!GLOBAL_COMP[objectType]) {
return null;
}
SymbolHash[] tables = new SymbolHash[fGrammarCount];
// get all hashtables from all namespaces for this type of components
if (fGlobalComponents[objectType] == null) {
for (int i = 0; i < fGrammarCount; i++) {
switch (objectType) {
case XSConstants.TYPE_DEFINITION:
case XSTypeDefinition.COMPLEX_TYPE:
case XSTypeDefinition.SIMPLE_TYPE:
tables[i] = fGrammarList[i].fGlobalTypeDecls;
break;
case XSConstants.ATTRIBUTE_DECLARATION:
tables[i] = fGrammarList[i].fGlobalAttrDecls;
break;
case XSConstants.ELEMENT_DECLARATION:
tables[i] = fGrammarList[i].fGlobalElemDecls;
break;
case XSConstants.ATTRIBUTE_GROUP:
tables[i] = fGrammarList[i].fGlobalAttrGrpDecls;
break;
case XSConstants.MODEL_GROUP_DEFINITION:
tables[i] = fGrammarList[i].fGlobalGroupDecls;
break;
case XSConstants.NOTATION_DECLARATION:
tables[i] = fGrammarList[i].fGlobalNotationDecls;
break;
}
}
// for complex/simple types, create a special implementation,
// which take specific types out of the hash table
if (objectType == XSTypeDefinition.COMPLEX_TYPE ||
objectType == XSTypeDefinition.SIMPLE_TYPE) {
fGlobalComponents[objectType] = new XSNamedMap4Types(fNamespaces, tables, fGrammarCount, objectType);
}
else {
fGlobalComponents[objectType] = new XSNamedMapImpl(fNamespaces, tables, fGrammarCount);
}
}
return fGlobalComponents[objectType];
}
/**
* Convenience method. Returns a list of top-level component declarations
* that are defined within the specified namespace, i.e. element
* declarations, attribute declarations, etc.
* @param objectType The type of the declaration, i.e.
* ELEMENT_DECLARATION, ATTRIBUTE_DECLARATION, etc.
* @param namespace The namespace to which declaration belong or
* null
(for components with no targetNamespace).
* @return A list of top-level definition of the specified type in
* objectType
and defined in the specified
* namespace
or null
.
*/
public synchronized XSNamedMap getComponentsByNamespace(short objectType,
String namespace) {
if (objectType <= 0 || objectType > MAX_COMP_IDX ||
!GLOBAL_COMP[objectType]) {
return null;
}
// try to find the grammar
int i = 0;
for (; i < fGrammarCount; i++) {
if (fNamespaces[i] == namespace)
break;
}
if (i == fGrammarCount)
return null;
// get the hashtable for this type of components
if (fNSComponents[i][objectType] == null) {
SymbolHash table = null;
switch (objectType) {
case XSConstants.TYPE_DEFINITION:
case XSTypeDefinition.COMPLEX_TYPE:
case XSTypeDefinition.SIMPLE_TYPE:
table = fGrammarList[i].fGlobalTypeDecls;
break;
case XSConstants.ATTRIBUTE_DECLARATION:
table = fGrammarList[i].fGlobalAttrDecls;
break;
case XSConstants.ELEMENT_DECLARATION:
table = fGrammarList[i].fGlobalElemDecls;
break;
case XSConstants.ATTRIBUTE_GROUP:
table = fGrammarList[i].fGlobalAttrGrpDecls;
break;
case XSConstants.MODEL_GROUP_DEFINITION:
table = fGrammarList[i].fGlobalGroupDecls;
break;
case XSConstants.NOTATION_DECLARATION:
table = fGrammarList[i].fGlobalNotationDecls;
break;
}
// for complex/simple types, create a special implementation,
// which take specific types out of the hash table
if (objectType == XSTypeDefinition.COMPLEX_TYPE ||
objectType == XSTypeDefinition.SIMPLE_TYPE) {
fNSComponents[i][objectType] = new XSNamedMap4Types(namespace, table, objectType);
}
else {
fNSComponents[i][objectType] = new XSNamedMapImpl(namespace, table);
}
}
return fNSComponents[i][objectType];
}
/**
* Convenience method. Returns a top-level simple or complex type
* definition.
* @param name The name of the definition.
* @param namespace The namespace of the definition, otherwise null.
* @return An XSTypeDefinition
or null if such definition
* does not exist.
*/
public XSTypeDefinition getTypeDefinition(String name,
String namespace) {
SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace));
if (sg == null)
return null;
return (XSTypeDefinition)sg.fGlobalTypeDecls.get(name);
}
/**
* Convenience method. Returns a top-level attribute declaration.
* @param name The name of the declaration.
* @param namespace The namespace of the definition, otherwise null.
* @return A top-level attribute declaration or null if such declaration
* does not exist.
*/
public XSAttributeDeclaration getAttributeDeclaration(String name,
String namespace) {
SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace));
if (sg == null)
return null;
return (XSAttributeDeclaration)sg.fGlobalAttrDecls.get(name);
}
/**
* Convenience method. Returns a top-level element declaration.
* @param name The name of the declaration.
* @param namespace The namespace of the definition, otherwise null.
* @return A top-level element declaration or null if such declaration
* does not exist.
*/
public XSElementDeclaration getElementDeclaration(String name,
String namespace) {
SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace));
if (sg == null)
return null;
return (XSElementDeclaration)sg.fGlobalElemDecls.get(name);
}
/**
* Convenience method. Returns a top-level attribute group definition.
* @param name The name of the definition.
* @param namespace The namespace of the definition, otherwise null.
* @return A top-level attribute group definition or null if such
* definition does not exist.
*/
public XSAttributeGroupDefinition getAttributeGroup(String name,
String namespace) {
SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace));
if (sg == null)
return null;
return (XSAttributeGroupDefinition)sg.fGlobalAttrGrpDecls.get(name);
}
/**
* Convenience method. Returns a top-level model group definition.
*
* @param name The name of the definition.
* @param namespace The namespace of the definition, otherwise null.
* @return A top-level model group definition definition or null if such
* definition does not exist.
*/
public XSModelGroupDefinition getModelGroupDefinition(String name,
String namespace) {
SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace));
if (sg == null)
return null;
return (XSModelGroupDefinition)sg.fGlobalGroupDecls.get(name);
}
/**
* @see com.sun.org.apache.xerces.internal.xs.XSModel#getNotationDeclaration(String, String)
*/
public XSNotationDeclaration getNotationDeclaration(String name,
String namespace) {
SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace));
if (sg == null)
return null;
return (XSNotationDeclaration)sg.fGlobalNotationDecls.get(name);
}
/**
* {annotations} A set of annotations.
*/
public synchronized XSObjectList getAnnotations() {
if(fAnnotations != null)
return fAnnotations;
// do this in two passes to avoid inaccurate array size
int totalAnnotations = 0;
for (int i = 0; i < fGrammarCount; i++) {
totalAnnotations += fGrammarList[i].fNumAnnotations;
}
XSAnnotationImpl [] annotations = new XSAnnotationImpl [totalAnnotations];
int currPos = 0;
for (int i = 0; i < fGrammarCount; i++) {
SchemaGrammar currGrammar = fGrammarList[i];
System.arraycopy(currGrammar.fAnnotations, 0, annotations, currPos, currGrammar.fNumAnnotations);
currPos += currGrammar.fNumAnnotations;
}
fAnnotations = new XSObjectListImpl(annotations, annotations.length);
return fAnnotations;
}
private static final String null2EmptyString(String str) {
return str == null ? XMLSymbols.EMPTY_STRING : str;
}
/**
* REVISIT: to expose identity constraints from XSModel.
* For now, we only expose whether there are any IDCs.
* We also need to add these methods to the public
* XSModel interface.
*/
public boolean hasIDConstraints() {
return fHasIDC;
}
/**
* REVISIT: to expose substitution group of a given element.
* We need to add this to the XSModel interface.
*/
public XSObjectList getSubstitutionGroup(XSElementDeclaration head) {
return (XSObjectList)fSubGroupMap.get(head);
}
} // class XSModelImpl