blob: 175bee8d04a39c44c2078b806ce66a6418576178 [file] [log] [blame]
/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 2000 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) 1999, International
* Business Machines, Inc., http://www.apache.org. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
/*
* @author Eric Ye
*
* @see
* @version $Id$
*/
package org.apache.xerces.validators.schema;
import org.apache.xerces.framework.XMLContentSpec;
import org.apache.xerces.utils.NamespacesScope;
import org.apache.xerces.utils.QName;
import org.apache.xerces.framework.XMLContentSpec;
import org.apache.xerces.validators.datatype.DatatypeValidator;
import org.apache.xerces.validators.datatype.DatatypeValidatorFactoryImpl;
import org.apache.xerces.validators.common.XMLAttributeDecl;
import org.apache.xerces.validators.common.XMLContentModel;
import org.apache.xerces.validators.common.XMLElementDecl;
import org.apache.xerces.validators.common.Grammar;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import java.util.Hashtable;
public class SchemaGrammar extends Grammar{
// Constants
//
private static final int CHUNK_SHIFT = 8; // 2^8 = 256
private static final int CHUNK_SIZE = (1 << CHUNK_SHIFT);
private static final int CHUNK_MASK = CHUNK_SIZE - 1;
private static final int INITIAL_CHUNK_COUNT = (1 << (10 - CHUNK_SHIFT)); // 2^10 = 1k
//Temp objects for decls structs.
private XMLContentSpec fTempContentSpecNode = new XMLContentSpec();
private XMLElementDecl fTempElementDecl = new XMLElementDecl();
private XMLAttributeDecl fTempAttributeDecl = new XMLAttributeDecl();
//
// Data
//
// basic information
// private int fTargetNamespace;
// private Element fGrammarDocument;
// element decl tables that used only by Schemas
// these arrays are indexed by elementdeclindex.
private int fScopeDefinedByElement[][] = new int[INITIAL_CHUNK_COUNT][];
private String fFromAnotherSchemaURI[][] = new String[INITIAL_CHUNK_COUNT][];
private TraverseSchema.ComplexTypeInfo fComplexTypeInfo[][] =
new TraverseSchema.ComplexTypeInfo[INITIAL_CHUNK_COUNT][];
private int fElementDeclDefaultType[][] = new int[INITIAL_CHUNK_COUNT][];
private String fElementDeclDefaultValue[][] = new String[INITIAL_CHUNK_COUNT][];
private String fElementDeclEquivClassFullName[][] = new String[INITIAL_CHUNK_COUNT][];
private int fElementDeclBlockSet[][] = new int[INITIAL_CHUNK_COUNT][];
private int fElementDeclFinalSet[][] = new int[INITIAL_CHUNK_COUNT][];
private int fElementDeclMiscFlags[][] = new int[INITIAL_CHUNK_COUNT][];
//ComplexType and SimpleTypeRegistries
private Hashtable fComplexTypeRegistry = null;
private Hashtable fAttributeDeclRegistry = null;
private DatatypeValidatorFactoryImpl fDatatypeRegistry = null;
Hashtable topLevelGroupDecls = new Hashtable();
Hashtable topLevelAttrDecls = new Hashtable();
Hashtable topLevelAttrGrpDecls = new Hashtable();
private NamespacesScope fNamespacesScope = null;
private String fTargetNamespaceURI = "";
//
// Public methods
//
public NamespacesScope getNamespacesScope(){
return fNamespacesScope;
}
public String getTargetNamespaceURI(){
return fTargetNamespaceURI;
}
public Hashtable getAttirubteDeclRegistry() {
return fAttributeDeclRegistry;
}
public Hashtable getComplexTypeRegistry(){
return fComplexTypeRegistry;
}
public DatatypeValidatorFactoryImpl getDatatypeRegistry(){
return fDatatypeRegistry;
}
public int getElementDefinedScope(int elementDeclIndex) {
if (elementDeclIndex < -1) {
return -1;
}
int chunk = elementDeclIndex >> CHUNK_SHIFT;
int index = elementDeclIndex & CHUNK_MASK;
return fScopeDefinedByElement[chunk][index];
}
public int getElementDefaultTYpe(int elementDeclIndex) {
if (elementDeclIndex < -1) {
return -1;
}
int chunk = elementDeclIndex >> CHUNK_SHIFT;
int index = elementDeclIndex & CHUNK_MASK;
return fElementDeclDefaultType[chunk][index];
}
public int getElementDeclBlockSet(int elementDeclIndex) {
if (elementDeclIndex < -1) {
return -1;
}
int chunk = elementDeclIndex >> CHUNK_SHIFT;
int index = elementDeclIndex & CHUNK_MASK;
return fElementDeclBlockSet[chunk][index];
}
public int getElementDeclFinalSet(int elementDeclIndex) {
if (elementDeclIndex < -1) {
return -1;
}
int chunk = elementDeclIndex >> CHUNK_SHIFT;
int index = elementDeclIndex & CHUNK_MASK;
return fElementDeclFinalSet[chunk][index];
}
public int getElementDeclMiscFlags(int elementDeclIndex) {
if (elementDeclIndex < -1) {
return -1;
}
int chunk = elementDeclIndex >> CHUNK_SHIFT;
int index = elementDeclIndex & CHUNK_MASK;
return fElementDeclMiscFlags[chunk][index];
}
public String getElementFromAnotherSchemaURI(int elementDeclIndex) {
if (elementDeclIndex < 0 ) {
return null;
}
int chunk = elementDeclIndex >> CHUNK_SHIFT;
int index = elementDeclIndex & CHUNK_MASK;
return fFromAnotherSchemaURI[chunk][index];
}
public String getElementDefaultValue(int elementDeclIndex) {
if (elementDeclIndex < 0 ) {
return null;
}
int chunk = elementDeclIndex >> CHUNK_SHIFT;
int index = elementDeclIndex & CHUNK_MASK;
return fElementDeclDefaultValue[chunk][index];
}
public String getElementDeclEquivClassElementFullName( int elementDeclIndex){
if (elementDeclIndex < 0 ) {
return null;
}
int chunk = elementDeclIndex >> CHUNK_SHIFT;
int index = elementDeclIndex & CHUNK_MASK;
return fElementDeclEquivClassFullName[chunk][index];
}
public TraverseSchema.ComplexTypeInfo getElementComplexTypeInfo(int elementDeclIndex){
if (elementDeclIndex <- 1) {
return null;
}
int chunk = elementDeclIndex >> CHUNK_SHIFT;
int index = elementDeclIndex & CHUNK_MASK;
return fComplexTypeInfo[chunk][index];
}
//
// Protected methods
//
protected void setAttributeDeclRegistry(Hashtable attrReg){
fAttributeDeclRegistry = attrReg;
}
protected void setComplexTypeRegistry(Hashtable cTypeReg){
fComplexTypeRegistry = cTypeReg;
}
protected void setDatatypeRegistry(DatatypeValidatorFactoryImpl dTypeReg){
fDatatypeRegistry = dTypeReg;
}
protected void setNamespacesScope(NamespacesScope nsScope) {
fNamespacesScope = nsScope;
}
protected void setTargetNamespaceURI(String targetNSUri) {
fTargetNamespaceURI = targetNSUri;
}
protected int createElementDecl() {
return super.createElementDecl();
}
protected void setElementDecl(int elementDeclIndex, XMLElementDecl elementDecl) {
super.setElementDecl(elementDeclIndex,elementDecl);
}
//public int addAttributeDeclByHead(int attributeDeclIndex, int attributeListHead) {
// return super.addAttributeDeclByHead(attributeDeclIndex, attributeListHead);
//}
protected int createContentSpec() {
return super.createContentSpec();
}
protected void setContentSpec(int contentSpecIndex, XMLContentSpec contentSpec) {
super.setContentSpec(contentSpecIndex, contentSpec);
}
protected int createAttributeDecl() {
return super.createAttributeDecl();
}
protected void setAttributeDecl(int elementDeclIndex, int attributeDeclIndex, XMLAttributeDecl attributeDecl) {
super.setAttributeDecl(elementDeclIndex, attributeDeclIndex, attributeDecl);
}
protected void setElementDefinedScope(int elementDeclIndex, int scopeDefined) {
int chunk = elementDeclIndex >> CHUNK_SHIFT;
int index = elementDeclIndex & CHUNK_MASK;
ensureElementDeclCapacity(chunk);
if (elementDeclIndex > -1 ) {
fScopeDefinedByElement[chunk][index] = scopeDefined;
}
}
protected void setElementFromAnotherSchemaURI(int elementDeclIndex, String anotherSchemaURI) {
int chunk = elementDeclIndex >> CHUNK_SHIFT;
int index = elementDeclIndex & CHUNK_MASK;
ensureElementDeclCapacity(chunk);
if (elementDeclIndex > -1 ) {
fFromAnotherSchemaURI[chunk][index] = anotherSchemaURI;
}
}
protected void setElementComplexTypeInfo(int elementDeclIndex, TraverseSchema.ComplexTypeInfo typeInfo){
int chunk = elementDeclIndex >> CHUNK_SHIFT;
int index = elementDeclIndex & CHUNK_MASK;
ensureElementDeclCapacity(chunk);
if (elementDeclIndex > -1 ) {
fComplexTypeInfo[chunk][index] = typeInfo;
}
}
protected void setElementDefault(int elementDeclIndex, int defaultType, String defaultValue) {
int chunk = elementDeclIndex >> CHUNK_SHIFT;
int index = elementDeclIndex & CHUNK_MASK;
ensureElementDeclCapacity(chunk);
if (elementDeclIndex > -1 ) {
fElementDeclDefaultType[chunk][index] = defaultType;
fElementDeclDefaultValue[chunk][index] = defaultValue;
}
}
protected void setElementDeclBlockSet(int elementDeclIndex, int blockSet) {
int chunk = elementDeclIndex >> CHUNK_SHIFT;
int index = elementDeclIndex & CHUNK_MASK;
ensureElementDeclCapacity(chunk);
if (elementDeclIndex > -1 ) {
fElementDeclBlockSet[chunk][index] = blockSet;
}
}
protected void setElementDeclFinalSet(int elementDeclIndex, int finalSet) {
int chunk = elementDeclIndex >> CHUNK_SHIFT;
int index = elementDeclIndex & CHUNK_MASK;
ensureElementDeclCapacity(chunk);
if (elementDeclIndex > -1 ) {
fElementDeclFinalSet[chunk][index] = finalSet;
}
}
protected void setElementDeclMiscFlags(int elementDeclIndex, int miscFlags) {
int chunk = elementDeclIndex >> CHUNK_SHIFT;
int index = elementDeclIndex & CHUNK_MASK;
ensureElementDeclCapacity(chunk);
if (elementDeclIndex > -1 ) {
fElementDeclMiscFlags[chunk][index] = miscFlags;
}
}
protected void setElementDeclEquivClassElementFullName( int elementDeclIndex, String equivClassFullName){
int chunk = elementDeclIndex >> CHUNK_SHIFT;
int index = elementDeclIndex & CHUNK_MASK;
ensureElementDeclCapacity(chunk);
if (elementDeclIndex > -1 ) {
fElementDeclEquivClassFullName[chunk][index] = equivClassFullName;
}
}
//add methods for TraverseSchema
/**
*@return elementDecl Index,
*/
protected int addElementDecl(QName eltQName, int enclosingScope, int scopeDefined,
int contentSpecType, int contentSpecIndex,
int attrListHead, DatatypeValidator dv){
int elementDeclIndex = getElementDeclIndex(eltQName, enclosingScope);
if (elementDeclIndex == -1) {
if (enclosingScope<-1 || scopeDefined < -1 ) {
//TO DO: report error here;
}
fTempElementDecl.name.setValues(eltQName);
fTempElementDecl.enclosingScope = enclosingScope;
fTempElementDecl.type = contentSpecType;
fTempElementDecl.contentSpecIndex = contentSpecIndex;
fTempElementDecl.datatypeValidator = dv;
//fTempElementDecl.firstAttributeDeclIndex = attrListHead;
elementDeclIndex = createElementDecl();
setElementDecl(elementDeclIndex,fTempElementDecl);
setFirstAttributeDeclIndex(elementDeclIndex, attrListHead);
//note, this is the scope defined by the element, not its enclosing scope
setElementDefinedScope(elementDeclIndex, scopeDefined);
}
//debugging
/*****
XMLElementDecl fTempElementDecl = new XMLElementDecl();
getElementDecl(elementDeclIndex, fTempElementDecl);
System.out.println("elementDeclIndex in addElementDecl : " + elementDeclIndex
+ " \n and itsName : '"
+ (fTempElementDecl.name.localpart)
+"' \n its ContentType:" + (fTempElementDecl.type)
+"\n its ContentSpecIndex : " + fTempElementDecl.contentSpecIndex +"\n");
/*****/
return elementDeclIndex;
}
/**
*@return the new attribute List Head
*/
protected void addAttDef( int templateElementIndex,
QName attQName, int attType,
int enumeration, int attDefaultType,
String attDefaultValue, DatatypeValidator dv, boolean isList){
int attrDeclIndex = createAttributeDecl();
fTempAttributeDecl.name.setValues(attQName);
fTempAttributeDecl.datatypeValidator = dv;
fTempAttributeDecl.type = attType;
fTempAttributeDecl.defaultType = attDefaultType;
fTempAttributeDecl.defaultValue = attDefaultValue;
fTempAttributeDecl.list = isList;
fTempAttributeDecl.enumeration = enumeration;
super.setAttributeDecl(templateElementIndex, attrDeclIndex, fTempAttributeDecl);
}
public int getAttributeDeclIndex(int elementIndex, QName attribute) {
if (elementIndex == -1) {
return -1;
}
int attDefIndex = getFirstAttributeDeclIndex(elementIndex);
while (attDefIndex != -1) {
getAttributeDecl(attDefIndex, fTempAttributeDecl);
if (fTempAttributeDecl.name.localpart == attribute.localpart &&
fTempAttributeDecl.name.uri == attribute.uri ) {
return attDefIndex;
}
attDefIndex = getNextAttributeDeclIndex(attDefIndex);
}
return -1;
} // getAttributeDeclIndex (int,QName)
/**
*@return the new contentSpec Index
*/
protected int addContentSpecNode(int contentSpecType, int value, int otherValue, boolean mustBeUnique) {
fTempContentSpecNode.type = contentSpecType;
fTempContentSpecNode.value = value;
fTempContentSpecNode.otherValue = otherValue;
int contentSpecIndex = createContentSpec();
setContentSpec(contentSpecIndex, fTempContentSpecNode);
return contentSpecIndex;
}
//
// Private methods
//
// ensure capacity
private boolean ensureElementDeclCapacity(int chunk) {
try {
return fScopeDefinedByElement[chunk][0] == -2;
}
catch (ArrayIndexOutOfBoundsException ex) {
fScopeDefinedByElement= resize(fScopeDefinedByElement, fScopeDefinedByElement.length * 2);
fFromAnotherSchemaURI = resize(fFromAnotherSchemaURI, fFromAnotherSchemaURI.length *2);
fComplexTypeInfo = resize(fComplexTypeInfo, fComplexTypeInfo.length *2);
fElementDeclDefaultType = resize(fElementDeclDefaultType,fElementDeclDefaultType.length*2);
fElementDeclDefaultValue = resize(fElementDeclDefaultValue,fElementDeclDefaultValue.length*2);
fElementDeclBlockSet = resize(fElementDeclBlockSet,fElementDeclBlockSet.length*2);
fElementDeclFinalSet = resize(fElementDeclFinalSet,fElementDeclFinalSet.length*2);
fElementDeclMiscFlags = resize(fElementDeclMiscFlags,fElementDeclMiscFlags.length*2);
fElementDeclEquivClassFullName = resize(fElementDeclEquivClassFullName,fElementDeclEquivClassFullName.length*2);
}
catch (NullPointerException ex) {
// ignore
}
fScopeDefinedByElement[chunk] = new int[CHUNK_SIZE];
for (int i=0; i<CHUNK_SIZE; i++) {
fScopeDefinedByElement[chunk][i] = -2; //-1, 0 are all valid scope value.
}
fFromAnotherSchemaURI[chunk] = new String[CHUNK_SIZE];
fComplexTypeInfo[chunk] = new TraverseSchema.ComplexTypeInfo[CHUNK_SIZE];
fElementDeclDefaultType[chunk] = new int[CHUNK_SIZE];
fElementDeclDefaultValue[chunk] = new String[CHUNK_SIZE];
fElementDeclEquivClassFullName[chunk] = new String[CHUNK_SIZE];
fElementDeclBlockSet[chunk] = new int[CHUNK_SIZE]; // initialized to 0
fElementDeclFinalSet[chunk] = new int[CHUNK_SIZE]; // initialized to 0
fElementDeclMiscFlags[chunk] = new int[CHUNK_SIZE]; // initialized to 0
return true;
}
// resize initial chunk
private int[][] resize(int array[][], int newsize) {
int newarray[][] = new int[newsize][];
System.arraycopy(array, 0, newarray, 0, array.length);
return newarray;
}
private DatatypeValidator[][] resize(DatatypeValidator array[][], int newsize) {
// TODO
return array;
}
private XMLContentModel[][] resize(XMLContentModel array[][], int newsize) {
// TODO
return array;
}
private QName[][] resize(QName array[][], int newsize) {
// TODO
return array;
}
private String[][] resize(String array[][], int newsize) {
String newarray[][] = new String[newsize][];
System.arraycopy(array, 0, newarray, 0, array.length);
return newarray;
}
private TraverseSchema.ComplexTypeInfo[][] resize(TraverseSchema.ComplexTypeInfo array[][], int newsize) {
TraverseSchema.ComplexTypeInfo newarray[][] = new TraverseSchema.ComplexTypeInfo[newsize][];
System.arraycopy(array, 0, newarray, 0, array.length);
return newarray;
}
} // class SchemaGrammar