You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xerces.apache.org by je...@locus.apache.org on 2000/04/04 21:56:30 UTC
cvs commit: xml-xerces/java/src/org/apache/xerces/validators/schema Schema.java SchemaImporter.java SchemaParser.java
jeffreyr 00/04/04 12:56:29
Added: java/src/org/apache/xerces/validators/schema Schema.java
SchemaImporter.java SchemaParser.java
Log:
Validators Factoring for Schema
Revision Changes Path
1.1 xml-xerces/java/src/org/apache/xerces/validators/schema/Schema.java
Index: Schema.java
===================================================================
/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 1999 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/>.
*/
package org.apache.xerces.validators.schema;
import java.util.Hashtable;
import java.util.Vector;
import java.util.Enumeration;
import org.apache.xerces.framework.XMLErrorReporter;
import org.apache.xerces.validators.common.XMLValidator;
class Schema
{
//
// Schema Keywords
//
public static final String ELT_SCHEMA = "schema";
public static final String ELT_SIMPLETYPE = "simpleType";
public static final String ELT_COMPLEXTYPE = "complexType";
public static final String ELT_ELEMENT = "element";
public static final String ELT_ATTRIBUTE = "attribute";
public static final String ELT_GROUP = "group";
public static final String ELT_CHOICE = "choice";
public static final String ELT_SEQUENCE = "seq";
public static final String ELT_ALL = "all";
public static final String ELT_ATTRGROUP = "attributeGroup";
public static final String ELT_NOTATION = "notation";
public static final String ELT_ANY = "any";
public static final String ELT_ANYATTRIBUTE = "anyAttribute";
public static final String ELT_ANNOTATION = "annotation";
public static final String ELT_DOCUMENTATION = "documentation";
public static final String ELT_APPINFO = "appinfo";
public static final String ELT_MINEXCLUSIVE = "minExclusive";
public static final String ELT_MININCLUSIVE = "minInclusive";
public static final String ELT_MAXEXCLUSIVE = "maxExclusive";
public static final String ELT_MAXINCLUSIVE = "maxInclusive";
public static final String ELT_PATTERN = "pattern";
public static final String ELT_ENUMERATION = "enumeration";
public static final String ELT_PRECISION = "precision";
public static final String ELT_SCALE = "scale";
public static final String ELT_LENGTH = "length";
public static final String ELT_MINLENGTH = "minLength";
public static final String ELT_MAXLENGTH = "maxLength";
public static final String ELT_ENCODING = "encoding";
public static final String ELT_PERIOD = "period";
public static final String ATT_TARGETNAMESPACE = "targetNamespace";
public static final String ATT_IMPORT = "import";
public static final String ATT_INCLUDE = "include";
public static final String ATT_NAME = "name";
public static final String ATT_TYPE = "type";
public static final String ATT_REF = "ref";
public static final String ATT_CONTENT = "content";
public static final String ATT_ABSTRACT = "abstract";
public static final String ATT_NULLABLE = "nullable";
public static final String ATT_DEFAULT = "default";
public static final String ATT_FIXED = "fixed";
public static final String ATT_FINAL = "final";
public static final String ATT_BLOCK = "block";
public static final String ATT_BASE = "base";
public static final String ATT_DERIVEDBY = "derivedBy";
public static final String ATT_MINOCCURS = "minOccurs";
public static final String ATT_MAXOCCURS = "maxOccurs";
public static final String ATT_EQUIVCLASS = "equivClass";
public static final String ATT_VALUE = "value";
public static final String ATT_USE = "use";
public static final String ATT_SYSTEM = "system";
public static final String ATT_PUBLIC = "public";
public static final String VAL_TRUE = "true";
public static final String VAL_FALSE = "false";
public static final String VAL_EMPTY = "empty";
public static final String VAL_ELEMENTONLY = "elementOnly";
public static final String VAL_TEXTONLY = "textOnly";
public static final String VAL_MIXED = "mixed";
public static final String VAL_EXTENSION = "extension";
public static final String VAL_RESTRICTION = "restriction";
public static final String VAL_REPRODUCTION = "reproduction";
public static final String VAL_ENUMERATION = "enumeration";
public static final String VAL_EQUIVCLASS = "equivClass";
public static final String VAL_LIST = "list";
public static final String VAL_POUNDALL = "#all";
public static final String VAL_INFINITY = "*";
public static final String VAL_OPTIONAL = "optional";
public static final String VAL_REQUIRED = "required";
public static final String VAL_DEFAULT = "default";
public static final String VAL_FIXED = "fixed";
public static final String VAL_PROHIBITED = "prohibited";
//
// Schema Representation Data Values
//
static public final int EMPTY = 0; // content models
static public final int ELEMENT_ONLY = 1; // content models
static public final int TEXT_ONLY = 2; // content models
static public final int MIXED = 3; // content models
public static final int EMPTY_SET = 0;
public static final int EXTENSION = 1;
public static final int RESTRICTION = 2;
public static final int REPRODUCTION = 4;
public static final int LIST = 8;
public static final int ENUMERATION = 16;
public static final int EQUIVCLASS = 32;
public static final int CHOICE = 0; // group orders
public static final int SEQUENCE = 1; // group orders
public static final int ALL = 2; // group orders
public static final int OPTIONAL = 0;
public static final int REQUIRED = 1;
public static final int DEFAULT = 2;
public static final int FIXED = 3;
public static final int PROHIBITED = 4;
public static final int INFINITY = -1; // used for maxOccurs
//
// Helpers for toString methods
//
private static final String[] CONTENT_MAP = {
VAL_EMPTY,
VAL_ELEMENTONLY,
VAL_TEXTONLY,
VAL_MIXED
};
private static final String[] ORDER_MAP = {
ELT_CHOICE,
ELT_SEQUENCE,
ELT_ALL
};
private static final String[] USE_MAP = {
VAL_OPTIONAL,
VAL_REQUIRED,
VAL_DEFAULT,
VAL_FIXED,
VAL_PROHIBITED
};
private static final String[] DERIVEDBY_MAP = {
null,
VAL_EXTENSION, // 1
VAL_RESTRICTION, // 2
null,
VAL_REPRODUCTION, // 4
null, null, null,
VAL_LIST, // 8
null, null, null, null, null, null, null,
VAL_ENUMERATION // 16
};
//
// Schema Instance Data
//
private Hashtable fDocuments = new Hashtable ();
private Document fDefaultDocument = null;
private XMLValidator fValidator = null;
private XMLErrorReporter fErrorReporter = null;
//
// Constructor
//
public Schema (XMLErrorReporter errorReporter, XMLValidator validator) {
fErrorReporter = errorReporter;
fValidator = validator;
}
//
// Create a new Schema Document
//
public Document createDocument () {
return new Document ();
}
//
// Register a Schema document (associate it with a unique namespace)
//
public void registerDocument (String namespace, Document document)
{
if ( namespace == null ) {
fDefaultDocument = document;
} else {
fDocuments.put (namespace, document);
}
}
//
// Lookup a Schema document (given it's unique namespace)
//
public Document lookupDocument (String namespace) {
if ( namespace == null ) {
return fDefaultDocument;
} else {
return (Document)fDocuments.get (namespace);
}
}
//
// Debugging
//
public String toString ()
{
String s = "";
for ( Enumeration e = fDocuments.keys (); e.hasMoreElements();) {
String namespace = (String)e.nextElement ();
Document doc = (Document)fDocuments.get (namespace);
s += namespace + ":\n";
s += doc.toString () + "\n";
}
return s;
}
//****************************************************************************************
// Schema Interfaces
//
//****************************************************************************************
public interface HasSimpleType
{
public void setSimpleType (SimpleTypeDef type) throws Exception;
public void setSimpleType (String name, String namespace) throws Exception;
}
public interface HasType extends HasSimpleType
{
public void setType (TypeDef type) throws Exception;
public void setType (String name, String namespace) throws Exception;
}
//****************************************************************************************
// Schema Classes
//
//****************************************************************************************
//********************
//**** Schema.Ref ****
//********************
public abstract class Ref
{
//
// Getters
//
public abstract String getName ();
public abstract String getNamespace ();
public String getQName () {
String namespace = getNamespace ();
String qname = namespace == null? "" : namespace + ":";
qname += getName();
return qname;
}
//
// Ref Resolution
//
public abstract TypeDef resolveTypeDef ();
public abstract GroupDef resolveGroupDef ();
public abstract AttributeGroupDef resolveAttributeGroupDef ();
public abstract ElementDecl resolveElementDecl ();
public abstract AttributeDecl resolveAttributeDecl ();
public abstract NotationDecl resolveNotationDecl ();
}
//*************************
//**** Schema.LocalRef ****
//*************************
public class LocalRef extends Ref
{
private Component fComponent;
//
// Constructors
//
public LocalRef (Component component) {
fComponent = component;
}
//
// Getters
//
public String getName () {
return fComponent.getName ();
}
public String getNamespace () {
return fComponent.getNamespace ();
}
//
// Ref Resolution
//
public TypeDef resolveTypeDef () {
return (TypeDef)fComponent;
}
public GroupDef resolveGroupDef () {
return (GroupDef)fComponent;
}
public AttributeGroupDef resolveAttributeGroupDef () {
return (AttributeGroupDef)fComponent;
}
public ElementDecl resolveElementDecl () {
return (ElementDecl)fComponent;
}
public AttributeDecl resolveAttributeDecl () {
return (AttributeDecl)fComponent;
}
public NotationDecl resolveNotationDecl () {
return (NotationDecl)fComponent;
}
}
//*************************
//**** Schema.NamedRef ****
//*************************
public class NamedRef extends Ref
{
private String fName;
private String fNamespace;
//
// Constructors
//
public NamedRef (String name, String namespace) {
fName = name;
fNamespace = namespace;
}
//
// Getters
//
public String getName () {
return fName;
}
public String getNamespace () {
return fNamespace;
}
//
// Ref Resolution
//
public TypeDef resolveTypeDef () {
Document doc = lookupDocument (fNamespace);
return doc.lookupTypeDef (fName);
}
public GroupDef resolveGroupDef () {
Document doc = lookupDocument (fNamespace);
return doc.lookupGroupDef (fName);
}
public AttributeGroupDef resolveAttributeGroupDef () {
Document doc = lookupDocument (fNamespace);
return doc.lookupAttributeGroupDef (fName);
}
public ElementDecl resolveElementDecl () {
Document doc = lookupDocument (fNamespace);
return doc.lookupElementDecl (fName);
}
public AttributeDecl resolveAttributeDecl () {
Document doc = lookupDocument (fNamespace);
return doc.lookupAttributeDecl (fName);
}
public NotationDecl resolveNotationDecl () {
Document doc = lookupDocument (fNamespace);
return doc.lookupNotationDecl (fName);
}
}
//***************************
//**** Schema.Annotation ****
//***************************
public class Annotation
{
private Vector fDocumentation = null;
private Vector fAppInfo = null;
public void addDocumentation (String documentation) {
if ( fDocumentation == null ) fDocumentation = new Vector ();
fDocumentation.addElement (documentation);
}
public void addAppInfo (String appInfo) {
if ( fAppInfo == null ) fAppInfo = new Vector ();
fAppInfo.addElement (appInfo);
}
public String toString () {
String s = "<" + ELT_ANNOTATION + ">\n";
if ( fDocumentation != null ) {
for (int i=0; i<fDocumentation.size(); i++) {
String doc = (String)fDocumentation.elementAt (i);
s += " <" + ELT_DOCUMENTATION + ">" + doc + "</" + ELT_DOCUMENTATION + ">\n";
}
}
if ( fAppInfo != null ) {
for (int i=0; i<fAppInfo.size(); i++) {
String appInfo = (String)fAppInfo.elementAt (i);
s += " <" + ELT_APPINFO + ">" + appInfo + "</" + ELT_APPINFO + ">\n";
}
}
s += "</" + ELT_ANNOTATION + ">\n";
return s;
}
}
//**************************
//**** Schema.Component ****
//**************************
public class Component
{
private Document fDocument = null;
private String fName = null;
public Component (Document doc) {
fDocument = doc;
}
//
// Setters
//
public void setName (String name) {
fName = name;
}
//
// Getters
//
public String getName () {
return fName;
}
public String getQName () {
String namespace = getNamespace ();
String name = getName ();
if ( namespace != null ) {
return namespace + ":" + name;
} else {
return name;
}
}
public Document getDocument () {
return fDocument;
}
public String getNamespace () {
return fDocument.getNamespace ();
}
}
//***********************************
//**** Schema.AnnotatedComponent ****
//***********************************
public class AnnotatedComponent extends Component
{
private Annotation fAnnotation = null;
public AnnotatedComponent (Document doc) {
super (doc);
}
public void setAnnotation (Annotation annotation) {
fAnnotation = annotation;
}
public Annotation getAnnotation () {
return fAnnotation;
}
public String toString () {
return annotationToString ();
}
public String annotationToString () {
if ( fAnnotation != null ) {
return fAnnotation.toString ();
} else {
return "";
}
}
}
//*************************
//**** Schema.Document ****
//*************************
public class Document
{
// ISSUE: Should Schemas have multiple annotations?
// How is order and relationship to interspersed
// components maintained?
private String fNamespace = null;
private Vector fAnnotations = new Vector ();
private Hashtable fTypeDefs = new Hashtable ();
private Hashtable fGroupDefs = new Hashtable ();
private Hashtable fAttrGroupDefs = new Hashtable ();
private Hashtable fElementDecls = new Hashtable ();
private Hashtable fAttributeDecls = new Hashtable ();
private Hashtable fNotationDecls = new Hashtable ();
//
// Getters
//
public String getNamespace () {
return fNamespace;
}
//
// Factory methods for Schema components
//
public Annotation createAnnotation () {
return new Annotation ();
}
public ComplexTypeDef createComplexTypeDef () {
return new ComplexTypeDef (this);
}
public SimpleTypeDef createSimpleTypeDef () {
return new SimpleTypeDef (this);
}
public Facet createFacet (String name, String value) {
return new Facet (name, value, this);
}
public GroupDef createGroupDef () {
return new GroupDef (this);
}
public AttributeGroupDef createAttributeGroupDef () {
return new AttributeGroupDef (this);
}
public ElementDecl createElementDecl () {
return new ElementDecl (this);
}
public AttributeDecl createAttributeDecl () {
return new AttributeDecl (this);
}
public NotationDecl createNotationDecl () {
return new NotationDecl (this);
}
public AttributeGroupParticle createAttributeGroupParticle () {
return new AttributeGroupParticle (this);
}
public AttributeParticle createAttributeParticle () {
return new AttributeParticle (this);
}
public GroupParticle createGroupParticle () {
return new GroupParticle (this);
}
public ElementParticle createElementParticle () {
return new ElementParticle (this);
}
//
// Annotations
//
public void addAnnotation (Annotation annotation) {
fAnnotations.addElement (annotation);
}
//
// Add Schema components to their respective symbol spaces in this
// Schema document.
//
public void registerType (String name, TypeDef typeDef) {
fTypeDefs.put (name, typeDef);
}
public void registerGroupDef (String name, GroupDef groupDef) {
fGroupDefs.put (name, groupDef);
}
public void registerAttributeGroupDef (String name, AttributeGroupDef attrGroupDef) {
fAttrGroupDefs.put (name, attrGroupDef);
}
public void registerElementDecl (String name, ElementDecl elementDecl) {
fElementDecls.put (name, elementDecl);
}
public void registerAttributeDecl (String name, AttributeDecl attributeDecl) {
fAttributeDecls.put (name, attributeDecl);
}
public void registerNotationDecl (String name, NotationDecl notationDecl) {
fNotationDecls.put (name, notationDecl);
}
//
// Lookup Schema Components
//
public TypeDef lookupTypeDef (String name) {
return (TypeDef)fTypeDefs.get (name);
}
public GroupDef lookupGroupDef (String name) {
return (GroupDef)fGroupDefs.get (name);
}
public AttributeGroupDef lookupAttributeGroupDef (String name) {
return (AttributeGroupDef)fAttrGroupDefs.get (name);
}
public ElementDecl lookupElementDecl (String name) {
return (ElementDecl)fElementDecls.get (name);
}
public AttributeDecl lookupAttributeDecl (String name) {
return (AttributeDecl)fAttributeDecls.get (name);
}
public NotationDecl lookupNotationDecl (String name) {
return (NotationDecl)fNotationDecls.get (name);
}
//
// Validation
//
public void expandEquivClassReferences () {
for ( Enumeration e = fElementDecls.elements (); e.hasMoreElements();) {
ElementDecl element = (ElementDecl)e.nextElement ();
ElementDecl equivClass = element.getEquivClass ();
if ( equivClass != null ) {
equivClass.addEquivElementDecl (element);
}
}
}
//
// Debugging
//
public String toString ()
{
String s = "<" + ELT_SCHEMA;
// Target Namespace
if ( fNamespace != null ) {
s += " " + ATT_TARGETNAMESPACE + "=" + fNamespace;
}
s += ">\n";
// Global TypeDefs
for ( Enumeration e = fTypeDefs.elements (); e.hasMoreElements();) {
TypeDef t = (TypeDef)e.nextElement ();
s += t.toString ();
}
// Global GroupDefs
for ( Enumeration e = fGroupDefs.elements (); e.hasMoreElements();) {
GroupDef g = (GroupDef)e.nextElement ();
s += g.toString ();
}
// Global AttributeGroupDefs
for ( Enumeration e = fAttrGroupDefs.elements (); e.hasMoreElements();) {
AttributeGroupDef ag = (AttributeGroupDef)e.nextElement ();
s += ag.toString ();
}
// Global ElementDecls
for ( Enumeration e = fElementDecls.elements (); e.hasMoreElements();) {
ElementDecl elem = (ElementDecl)e.nextElement ();
s += elem.toString ();
}
// Global AttributeDecls
for ( Enumeration e = fAttributeDecls.elements (); e.hasMoreElements();) {
AttributeDecl attr = (AttributeDecl)e.nextElement ();
s += attr.toString ();
}
// Global NotationDecls
for ( Enumeration e = fNotationDecls.elements (); e.hasMoreElements();) {
NotationDecl not = (NotationDecl)e.nextElement ();
s += not.toString ();
}
s += "</" + ELT_SCHEMA + ">\n";
return s;
}
}
//************************
//**** Schema.TypeDef ****
//************************
public abstract class TypeDef extends AnnotatedComponent
{
private Ref fBaseType = null;
private int fDerivedBy = 0;
private boolean fIsAbstract = false;
private int fFinalSet = EMPTY_SET;
//
// Constructor
//
public TypeDef (Document doc) {
super (doc);
}
//
// Setters
//
public void setBase (String name, String namespace) {
fBaseType = new NamedRef (name, namespace);
}
public void setDerivedBy (int derivedBy) {
fDerivedBy = derivedBy;
}
public void setAbstract (boolean isAbstract) {
fIsAbstract = isAbstract;
}
public void setFinal (int finalSet) {
fFinalSet = finalSet;
}
//
// Getters
//
public TypeDef getBaseType () {
return fBaseType.resolveTypeDef ();
}
public int getDerivedBy () {
return fDerivedBy;
}
public boolean isDerivedBy (int derivedBy) {
return fDerivedBy == derivedBy;
}
public boolean isAbstract () {
return fIsAbstract;
}
public int getFinal () {
return fFinalSet;
}
public boolean canExtend () {
return (getFinal() & EXTENSION) == 0;
}
public boolean canRestrict () {
return (getFinal() & RESTRICTION) == 0;
}
public boolean canReproduce () {
return (getFinal() & REPRODUCTION) == 0;
}
public boolean canEnumerate () {
return (getFinal() & ENUMERATION) == 0;
}
public boolean canList () {
return (getFinal() & LIST) == 0;
}
//
// Debugging
//
public String toString () {
// This is an abstract base class for ComplexTypeDef and SimpleTypeDef
// so its string representation is just a portion of either of these.
// In particular, toString produces a portion of the attribute string
// for either.
String s = " ";
// base
if ( fBaseType != null ) {
s += " " + ATT_BASE + "=\'" + fBaseType.getQName() + "\'";
}
// derivedBy
s += " " + ATT_DERIVEDBY + "=\'" + DERIVEDBY_MAP[getDerivedBy()] + "\'";
// abstract
s += " " + ATT_ABSTRACT + "=";
s += isAbstract()? "\'" + VAL_TRUE + "\'" : "\'" + VAL_FALSE + "\'";
// final
s += " " + ATT_FINAL + "=\'";
boolean extend = canExtend ();
boolean restrict = canRestrict ();
boolean reproduce = canReproduce ();
boolean enumerate = canEnumerate ();
boolean list = canList ();
if ( (!extend && !restrict && !reproduce) || (!enumerate && !list && !restrict && !reproduce)) {
s += "#all";
} else {
if ( !extend ) {
s += " " + VAL_EXTENSION;
}
if ( !restrict ) {
s += " " + VAL_RESTRICTION;
}
if ( !reproduce ) {
s += " " + VAL_REPRODUCTION;
}
if ( !enumerate ) {
s += " " + VAL_ENUMERATION;
}
if ( !list ) {
s += " " + VAL_LIST;
}
}
s += "\'";
return s;
}
}
//********************
//**** INTERFACES ****
//********************
public interface AParticleHolder
{
public void add (AParticle particle);
}
public interface EParticleHolder
{
public void add (EParticle particle);
}
//*******************************
//**** Schema.ComplexTypeDef ****
//*******************************
public class ComplexTypeDef extends TypeDef
implements EParticleHolder, AParticleHolder
{
private int fContent = EMPTY;
private int fBlockSet = EMPTY_SET;
private AttributeGroupDef fAttrGroupDef = null;
private GroupDef fGroupDef = null;
//
// Constructor
//
public ComplexTypeDef (Document doc) {
super (doc);
setDerivedBy (EXTENSION);
}
//
// Setters
//
public void setContent (int content) {
fContent = content;
}
public void setBlock (int blockSet) {
fBlockSet = blockSet;
}
public void add (EParticle particle) {
if ( fGroupDef == null ) fGroupDef = new GroupDef (getDocument());
fGroupDef.add (particle);
}
public void add (AParticle particle) {
if ( fAttrGroupDef == null ) fAttrGroupDef = new AttributeGroupDef (getDocument());
fAttrGroupDef.add (particle);
}
//
// Getters
//
public int getContent () {
return fContent;
}
public boolean isContent (int content) {
return fContent == content;
}
public boolean canSubstituteExtension () {
return (fBlockSet & EXTENSION) == 0;
}
public boolean canSubstituteRestriction () {
return (fBlockSet & RESTRICTION) == 0;
}
public boolean canSubstituteReproduction () {
return (fBlockSet & REPRODUCTION) == 0;
}
//
// Debugging
//
public String toString () {
String s = "<" + ELT_COMPLEXTYPE + " ";
// name
String name = getName ();
if ( name != null ) {
s += ATT_NAME + "='" + getName() + "'";
}
s += super.toString ();
// content
s += " " + ATT_CONTENT + "='" + CONTENT_MAP[fContent] + "'";
// block
s += " " + ATT_BLOCK + "='";
boolean extend = canSubstituteExtension ();
boolean restrict = canSubstituteRestriction ();
boolean reproduce = canSubstituteReproduction ();
if ( !extend && !restrict && !reproduce ) {
s += VAL_POUNDALL;
} else {
if ( !extend ) {
s += " " + VAL_EXTENSION;
}
if ( !restrict ) {
s += " " + VAL_RESTRICTION;
}
if ( !reproduce ) {
s += " " + VAL_REPRODUCTION;
}
}
s += "'>\n";
// annotation
s += annotationToString ();
// particles
if ( fGroupDef != null ) {
s += fGroupDef.toString ();
}
// attributes
if ( fAttrGroupDef != null ) {
s += fAttrGroupDef.toString ();
}
s += "</" + ELT_COMPLEXTYPE + ">\n";
return s;
}
}
//******************************
//**** Schema.SimpleTypeDef ****
//******************************
public class SimpleTypeDef extends TypeDef
{
private Vector fFacets = null;
//
// Constructor
//
public SimpleTypeDef (Document doc) {
super (doc);
setDerivedBy (RESTRICTION);
}
//
// Setters
//
public void addFacet (Facet facet) {
if ( fFacets == null ) fFacets = new Vector ();
fFacets.addElement (facet);
}
//
// Debugging
//
public String toString () {
String s = "<" + ELT_SIMPLETYPE;
// name
String name = getName ();
if ( name != null ) {
s += " " + ATT_NAME + "=\'" + getName() + "\'";
}
s += super.toString ();
s += ">\n";
// annotations
s += annotationToString ();
// facets
if ( fFacets != null ) {
int numFacets = fFacets.size();
for (int f=0; f<numFacets; f++) {
Facet facet = (Facet)fFacets.elementAt (f);
s += facet.toString ();
}
}
s += "</" + ELT_SIMPLETYPE + ">\n";
return s;
}
}
//**********************
//**** Schema.Facet ****
//**********************
public class Facet extends AnnotatedComponent
{
private String fValue = null;
public Facet (String name, String value, Document doc) {
super (doc);
setName (name);
fValue = value;
}
public String getValue () {
return fValue;
}
//
// Debugging
//
public String toString () {
String name = getName ();
String s = "<" + name + " " + ATT_VALUE + "='" + fValue + "'" + ">\n";
s += annotationToString ();
s += "</" + name + ">\n";
return s;
}
}
//******************************
//**** Schema.AttributeDecl ****
//******************************
public class AttributeDecl extends AnnotatedComponent
implements HasSimpleType
{
private Ref fTypeDef = null;
private int fUse = OPTIONAL;
private String fValue = null;
//
// Constructor
//
public AttributeDecl (Document doc) {
super (doc);
}
//
// Setters
//
public void setSimpleType (SimpleTypeDef typeDef) throws Exception {
if ( fTypeDef == null ) {
fTypeDef = new LocalRef (typeDef);
} else {
reportGenericSchemaError ("Type def already set");
}
}
public void setSimpleType (String name, String namespace) throws Exception {
if ( fTypeDef == null ) {
fTypeDef = new NamedRef (name, namespace);
} else {
reportGenericSchemaError ("Type def already set");
}
}
public void setUse (int use) {
fUse = use;
}
public void setValue (String value) {
fValue = value;
}
//
// Getters
//
public SimpleTypeDef getType () {
return (SimpleTypeDef)fTypeDef.resolveTypeDef ();
}
public boolean hasTypeRef () {
return NamedRef.class.isInstance(fTypeDef);
}
public int getUse () {
return fUse;
}
public String getValue () {
return fValue;
}
public AttributeDecl createRestriction (AttributeDecl restrictions) {
// TODO: refine what is a valid restriction
AttributeDecl attrDecl = new AttributeDecl (getDocument());
attrDecl.setName(getName());
attrDecl.fTypeDef = fTypeDef;
attrDecl.fUse = restrictions.fUse;
attrDecl.fValue = (restrictions.fValue == null)? fValue : restrictions.fValue;
return attrDecl;
}
/*
public void collectAttributes (Hashtable attributes, boolean restrict) {
String name = getName ();
AttributeDecl attrDecl = (AttributeDecl)attributes.get (name);
if ( attrDecl == null ) {
attributes.put (name, this);
} else {
attributes.put (name, attrDecl.createRestriction(this));
}
}
*/
//
// Debugging
//
public String toString () {
String s = "<" + ELT_ATTRIBUTE;
String name = getName ();
if ( name != null ) {
s += " " + ATT_NAME + "='" + name + "'";
}
if ( hasTypeRef() ) {
s += " " + ATT_TYPE + "='" + getType().getQName() + "'";
}
s += " " + ATT_USE + "='" + USE_MAP[fUse] + "'";
if ( fValue != null ) {
s += " " + ATT_VALUE + "='" + fValue + "'";
}
s += ">\n";
s += annotationToString();
s += getType().toString ();
s += "</" + ELT_ATTRIBUTE + ">\n";
return s;
}
}
//**********************************
//**** Schema.AttributeGroupDef ****
//**********************************
public class AttributeGroupDef extends AnnotatedComponent
implements AParticleHolder
{
private Vector fParticles = new Vector ();
//
// Constructor
//
public AttributeGroupDef (Document doc) {
super (doc);
}
//
// Setters
//
public void add (AParticle particle) {
fParticles.addElement (particle);
}
//
// Getters
//
/*
public void collectAttributes (Hashtable attributes, boolean restrict) {
for (int i=0; i<fParticles.size(); i++) {
AttributeCollector collector = (AttributeCollector)fParticles.elementAt (i);
collector.collectAttributes (attributes, restrict);
}
}
*/
//
// Debugging
//
public String toString () {
String s = "<" + ELT_ATTRGROUP;
String name = getName ();
if ( name != null ) {
s += " " + ATT_NAME + "='" + name + "'";
}
s += ">\n";
s += annotationToString ();
s += bodyToString ();
s += "</" + ELT_ATTRGROUP + ">\n";
return s;
}
public String bodyToString () {
String s = "";
for (int i=0; i<fParticles.size(); i++) {
Object particle = fParticles.elementAt (i);
s += particle.toString ();
}
return s;
}
}
//****************************
//**** Schema.ElementDecl ****
//****************************
public class ElementDecl extends AnnotatedComponent
implements HasType
{
private Ref fTypeDef = null;
private Ref fEquivClass = null;
private Vector fEquivElementDecls = null;
private boolean fIsAbstract = false;
private boolean fIsNullable = false;
private int fFinalSet = EMPTY_SET; // equiv class
private int fBlockSet = EMPTY_SET; // substitutions
private int fValueConstraint = OPTIONAL;
private String fValue = null;
//
// Constructor
//
public ElementDecl (Document doc) {
super (doc);
}
//
// Setters
//
public void setType (String name, String namespace) throws Exception {
if ( fTypeDef == null ) {
fTypeDef = new NamedRef (name, namespace);
} else {
reportGenericSchemaError ("Type def already set");
}
}
public void setType (TypeDef typeDef) throws Exception {
if ( fTypeDef == null ) {
fTypeDef = new LocalRef (typeDef);
} else {
reportGenericSchemaError ("Type def already set");
}
}
public void setSimpleType (SimpleTypeDef typeDef) throws Exception {
setType (typeDef);
}
public void setSimpleType (String name, String namespace) throws Exception {
setType (name, namespace);
}
public void setEquivClass (String name, String namespace) {
fEquivClass = new NamedRef (name, namespace);
}
public void setAbstract (boolean isAbstract) {
fIsAbstract = isAbstract;
}
public void setNullable (boolean isNullable) {
fIsNullable = isNullable;
}
public void setFinal (int finalSet) {
fFinalSet = finalSet;
}
public void setBlock (int blockSet) {
fBlockSet = blockSet;
}
public void setDefaultValue (String defaultValue) {
fValueConstraint = DEFAULT;
fValue = defaultValue;
}
public void setFixedValue (String fixedValue) {
fValueConstraint = DEFAULT;
fValue = fixedValue;
}
//
// Getters
//
public TypeDef getType () {
return fTypeDef.resolveTypeDef ();
}
public boolean hasTypeRef () {
return NamedRef.class.isInstance(fTypeDef);
}
public ElementDecl getEquivClass () {
return fEquivClass.resolveElementDecl ();
}
public boolean isNullable () {
return fIsNullable;
}
public boolean isAbstract () {
return fIsAbstract;
}
public String getDefaultValue () {
if ( fValueConstraint == DEFAULT ) {
return fValue;
} else {
return null;
}
}
public String getFixedValue () {
if ( fValueConstraint == FIXED ) {
return fValue;
} else {
return null;
}
}
//
// Validation Support
//
public void addEquivElementDecl (ElementDecl elementDecl) {
fEquivElementDecls.addElement (elementDecl);
}
//
// Debugging
//
//
// Debugging
//
public String toString () {
String s = "< " + ELT_ELEMENT;
String name = getName ();
if ( name != null ) {
s += " " + ATT_NAME + "='" + name + "'";
}
if ( hasTypeRef() ) {
s += " " + ATT_TYPE + "='" + getType().getQName() + "'";
}
s += " " + ATT_ABSTRACT + "='" + (isAbstract()? "true'" : "false") + "'";
s += " " + ATT_NULLABLE + "='" + (isNullable()? "true'" : "false") + "'";
// default value
String defaultValue = getDefaultValue ();
if ( defaultValue != null ) {
s += " " + ATT_DEFAULT + "='" + defaultValue + "'";
}
// fixed value
String fixedValue = getFixedValue ();
if ( fixedValue != null ) {
s += " " + ATT_FIXED + "='" + fixedValue + "'";
}
// equiv class
if ( fEquivClass != null ) {
s += " " + ATT_EQUIVCLASS + "='" + fEquivClass.getQName () + "'";
}
s += annotationToString ();
// anonymous
if ( !hasTypeRef() ) {
getType().toString ();
}
return s;
}
}
//*************************
//**** Schema.GroupDef ****
//*************************
public class GroupDef extends AnnotatedComponent
implements EParticleHolder
{
private int fOrder = CHOICE;
private Vector fParticles = new Vector ();
//
// Constructor
//
public GroupDef (Document doc) {
super (doc);
}
//
// Setters
//
public void setOrder (int order) {
fOrder = order;
}
public void add (EParticle particle) {
fParticles.addElement (particle);
}
//
// Getters
//
public int getOrder () {
return fOrder;
}
/*
public void collectParticles (Hashtable particles, boolean restrict) {
for (int i=0; i<fParticles.size(); i++) {
ParticleCollector collector = (ParticleCollector)fParticles.elementAt (i);
collector.collectParticles (particles, restrict);
}
}
*/
//
// Debugging
//
public String toString () {
String s = "<" + ELT_GROUP;
String name = getName ();
if ( name != null ) {
s += " " + ATT_NAME + "='" + name + "'";
}
s += ">\n";
s += annotationToString ();
s += bodyToString ();
s += "</" + ELT_GROUP + ">\n";
return s;
}
public String bodyToString () {
String s = "<" + ORDER_MAP[fOrder] + ">\n";
for (int i=0; i<fParticles.size(); i++) {
Object particle = fParticles.elementAt (i);
s += particle.toString ();
}
s += "</" + ORDER_MAP[fOrder] + ">\n";
return s;
}
}
//*****************************
//**** Schema.NotationDecl ****
//*****************************
public class NotationDecl extends AnnotatedComponent
{
private String fSystemId = null;
private String fPublicId = null;
//
// Constructors
//
public NotationDecl (Document doc) {
super (doc);
}
//
// Setters
//
public void setSystemId (String systemId) {
fSystemId = systemId;
}
public void setPublicId (String publicId) {
fPublicId = publicId;
}
//
// Getters
//
public String getSystemId () {
return fSystemId;
}
public String getPublicId () {
return fPublicId;
}
//
// Debugging
//
public String toString () {
String s = "<" + ELT_NOTATION;
s += " " + ATT_NAME + "='" + getName() + "'";
s += " " + ATT_SYSTEM + "='" + getSystemId() + "'";
s += " " + ATT_PUBLIC + "='" + getPublicId() + "'";
s += ">\n";
s += annotationToString ();
s += "</" + ELT_NOTATION + ">\n";
return s;
}
}
//**************************
//**** Schema.AParticle ****
//**************************
public abstract class AParticle extends AnnotatedComponent
{
private Ref fComponentRef = null;
//
// Constructors
//
public AParticle (Document doc) {
super (doc);
}
//
// Setters
//
protected void setComponentRef (Ref componentRef) {
fComponentRef = componentRef;
}
//
// Getters
//
protected Ref getComponentRef () {
return fComponentRef;
}
public String getName () {
return fComponentRef.getName ();
}
public String getNamespace () {
return fComponentRef.getNamespace ();
}
// Does this particle reference a global component?
public boolean isRef () {
return NamedRef.class.isInstance (fComponentRef);
}
}
//***************************************
//**** Schema.AttributeGroupParticle ****
//***************************************
public class AttributeGroupParticle extends AParticle
{
//
// Constructors
//
public AttributeGroupParticle (Document doc) {
super (doc);
}
//
// Setters
//
public void setAttributeGroupDef (AttributeGroupDef attrGroupDef) {
setComponentRef (new LocalRef(attrGroupDef));
}
public void setAttributeGroupRef (String name, String namespace) {
setComponentRef (new NamedRef(name, namespace));
}
//
// Getters
//
public AttributeGroupDef getAttributeGroupDef () {
return getComponentRef().resolveAttributeGroupDef ();
}
//
// Debugging
//
public String toString () {
String s = "<" + ELT_ATTRGROUP;
if ( isRef() ) {
s += ATT_REF + "='" + getComponentRef().getQName() + "'";
}
s += ">\n";
s += annotationToString ();
if ( !isRef() ) {
s += getAttributeGroupDef().bodyToString();
}
s += "</" + ELT_ATTRGROUP + ">\n";
return s;
}
}
//**********************************
//**** Schema.AttributeParticle ****
//**********************************
public class AttributeParticle extends AParticle
{
private int fUse = OPTIONAL;
private String fValue = null;
//
// Constructors
//
public AttributeParticle (Document doc) {
super (doc);
}
//
// Setters
//
public void setAttributeDecl (AttributeDecl attributeDecl) {
setComponentRef (new LocalRef(attributeDecl));
}
public void setAttributeRef (String name, String namespace) {
setComponentRef (new NamedRef(name, namespace));
}
public void setSimpleType (SimpleTypeDef typeDef) throws Exception {
getAttributeDecl().setSimpleType (typeDef);
}
public void setSimpleType (String name, String namespace) throws Exception {
getAttributeDecl().setSimpleType (name, namespace);
}
public void setUse (int use) {
// TODO: merge use with attribute decl
fUse = use;
}
public void setValue (String value) {
// TODO: merge value with attribute decl
fValue = value;
}
//
// Getters
//
public AttributeDecl getAttributeDecl () {
// Faults in AttributeDecl if not already there.
Ref ref = getComponentRef ();
if ( ref == null ) {
setAttributeDecl (getDocument().createAttributeDecl());
ref = getComponentRef ();
}
return ref.resolveAttributeDecl ();
}
public String getName () {
return getAttributeDecl().getName ();
}
public boolean hasTypeRef () {
return getAttributeDecl().hasTypeRef ();
}
public SimpleTypeDef getType () {
return getAttributeDecl().getType ();
}
public int getUse () {
if ( fUse == OPTIONAL ) {
return getAttributeDecl().getUse ();
} else {
return fUse;
}
}
public String getValue () {
if ( fValue == null ) {
return getAttributeDecl().getValue ();
} else {
return fValue;
}
}
//
// Debugging
//
public String toString () {
String s = "<" + ELT_ATTRIBUTE;
if ( isRef() ) {
s += " " + ATT_REF + "='" + getComponentRef().getQName() + "'";
} else {
s += " " + ATT_NAME + "='" + getName() + "'";
if ( hasTypeRef() ) {
s += " " + ATT_TYPE + "='" + getType().getQName() + "'";
}
}
s += " " + ATT_USE + "='" + USE_MAP[getUse()] + "'";
String value = getValue ();
if ( value != null ) {
s += " " + ATT_VALUE + "='" + value + "'";
}
s += ">\n";
s += annotationToString ();
if ( !isRef() && !hasTypeRef() ) {
getType().toString ();
}
s += "</" + ELT_ATTRIBUTE + ">\n";
return s;
}
}
//**************************
//**** Schema.EParticle ****
//**************************
public class EParticle extends AnnotatedComponent
{
protected Ref fComponentRef = null;
private int fMinOccurs = 1;
private int fMaxOccurs = 1;
//
// Constructors
//
public EParticle (Document doc) {
super (doc);
}
//
// Setters
//
protected void setComponentRef (Ref componentRef) {
fComponentRef = componentRef;
}
public void setMinOccurs (int minOccurs) {
fMinOccurs = minOccurs;
}
public void setMaxOccurs (int maxOccurs) {
fMaxOccurs = maxOccurs;
}
//
// Getters
//
protected Ref getComponentRef () {
return fComponentRef;
}
public String getName () {
return fComponentRef.getName ();
}
public String getNamespace () {
return fComponentRef.getNamespace ();
}
public int getMinOccurs () {
return fMinOccurs;
}
public int getMaxOccurs () {
return fMaxOccurs;
}
// Does this particle reference a global component?
public boolean isRef () {
return NamedRef.class.isInstance (fComponentRef);
}
}
//******************************
//**** Schema.GroupParticle ****
//******************************
public class GroupParticle extends EParticle
{
//
// Constructors
//
public GroupParticle (Document doc) {
super (doc);
}
//
// Setters
//
public void setGroupDef (GroupDef groupDef) {
setComponentRef (new LocalRef(groupDef));
}
public void setGroupRef (String name, String namespace) {
setComponentRef (new NamedRef(name, namespace));
}
//
// Getters
//
public GroupDef getGroupDef () {
return getComponentRef().resolveGroupDef ();
}
//
// Debugging
//
public String toString () {
String s = "<" + ELT_GROUP;
if ( isRef() ) {
s += " " + ATT_REF + "'" + getComponentRef().getQName () + "'";
}
s += " " + ATT_MINOCCURS + "='" + getMinOccurs() + "'";
s += " " + ATT_MAXOCCURS + "='" + getMaxOccurs() + "'";
s += ">\n";
s += annotationToString ();
if ( !isRef() ) {
s += getGroupDef().bodyToString ();
}
s += "</" + ELT_GROUP + ">\n";
return s;
}
}
//********************************
//**** Schema.ElementParticle ****
//********************************
public class ElementParticle extends EParticle
implements HasType
{
// TODO: I currently don't use these. I just use the values from the
// associated elementdecl. Need to use and merge these later.
private boolean fIsAbstract = false;
private boolean fIsNullable = false;
private int fBlockSet = EMPTY_SET;
private String fDefaultValue = null;
private String fFixedValue = null;
//
// Constructors
//
public ElementParticle (Document doc) {
super (doc);
}
//
// Setters
//
public void setElementDecl (ElementDecl elementDecl) {
setComponentRef (new LocalRef(elementDecl));
}
public void setElementRef (String name, String namespace) {
setComponentRef (new NamedRef(name, namespace));
}
public void setType (TypeDef typeDef) throws Exception {
getElementDecl().setType (typeDef);
}
public void setType (String name, String namespace) throws Exception {
getElementDecl().setType (name, namespace);
}
public void setSimpleType (SimpleTypeDef typeDef) throws Exception {
setType (typeDef);
}
public void setSimpleType (String name, String namespace) throws Exception {
setType (name, namespace);
}
public void setAbstract (boolean isAbstract) {
fIsAbstract = isAbstract;
}
public void setNullable (boolean isNullable) {
fIsNullable = isNullable;
}
public void setBlock (int blockSet) {
fBlockSet = blockSet;
}
public void setDefaultValue (String defaultValue) {
fDefaultValue = defaultValue;
}
public void setFixedValue (String fixedValue) {
fFixedValue = fixedValue;
}
//
// Getters
//
public ElementDecl getElementDecl () {
Ref ref = getComponentRef ();
if ( ref == null ) {
setElementDecl (new ElementDecl(getDocument()));
ref = getComponentRef ();
}
return ref.resolveElementDecl ();
}
public TypeDef getType () {
return getElementDecl().getType ();
}
public boolean hasTypeRef () {
return getElementDecl().hasTypeRef ();
}
public boolean isNullable () {
// TODO: Merge local value with element decl
return getElementDecl().isNullable ();
}
public boolean isAbstract () {
return getElementDecl().isAbstract ();
}
public boolean canSubstituteExtension () {
return (fBlockSet & EXTENSION) == 0;
}
public boolean canSubstituteRestriction () {
return (fBlockSet & RESTRICTION) == 0;
}
public boolean canSubstituteReproduction () {
return (fBlockSet & REPRODUCTION) == 0;
}
public String getDefaultValue () {
String defaultValue = getElementDecl().getDefaultValue ();
if ( defaultValue != null && fDefaultValue != null ) {
return fDefaultValue;
} else {
return defaultValue;
}
}
public String getFixedValue () {
String fixedValue = getElementDecl().getFixedValue ();
if ( fixedValue != null && fFixedValue != null ) {
return fFixedValue;
} else {
return fixedValue;
}
}
/*
public void collectElements (Hashtable elements, boolean restrict) {
ElementDecl elementDecl = getElementDecl ();
String name = elementDecl.getName ();
ElementDecl e = (ElementDecl)elements.get (name);
if ( e == null ) {
elements.put (name, elementDecl);
} else {
}
}
*/
//
// Debugging
//
public String toString () {
String s = "<" + ELT_ELEMENT;
if ( isRef() ) {
s += " " + ATT_REF + "='" + getComponentRef().getQName () + "'";
} else {
s += " " + ATT_NAME + "='" + getName() + "'";
if ( hasTypeRef() ) {
s += " " + ATT_TYPE + "='" + getType().getQName() + "'";
}
}
s += " " + ATT_MINOCCURS + "='" + getMinOccurs() + "'";
s += " " + ATT_MAXOCCURS + "='" + getMaxOccurs() + "'";
s += " " + ATT_ABSTRACT + "='" + ( isAbstract()? "true" : "false" ) + "'";
s += " " + ATT_NULLABLE + "='" + ( isNullable()? "true" : "false" ) + "'";
s += " " + ATT_BLOCK + "='";
boolean extend = canSubstituteExtension ();
boolean restrict = canSubstituteRestriction ();
boolean reproduce = canSubstituteReproduction ();
if ( !extend && !restrict && !reproduce ) {
s += VAL_POUNDALL;
} else {
if ( !extend ) {
s += " " + VAL_EXTENSION;
}
if ( !restrict ) {
s += " " + VAL_RESTRICTION;
}
if ( !reproduce ) {
s += " " + VAL_REPRODUCTION;
}
}
s += "'";
if ( fDefaultValue != null ) {
s += " " + ATT_DEFAULT + "='" + fDefaultValue + "'";
}
if ( fFixedValue != null ) {
s += " " + ATT_FIXED + "='" + fFixedValue + "'";
}
s += ">\n";
s += annotationToString ();
if ( !isRef() ) {
s += getType().toString ();
}
s += "</" + ELT_ELEMENT + ">\n";
return s;
}
}
//
// Inner objects can call this to report errors
//
private void reportSchemaError(int major, Object args[]) {
try {
fErrorReporter.reportError(fErrorReporter.getLocator(),
SchemaMessageProvider.SCHEMA_DOMAIN,
major,
SchemaMessageProvider.MSG_NONE,
args,
XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
} catch (Exception e) {
e.printStackTrace();
}
}
private void reportGenericSchemaError (String error) throws Exception {
reportSchemaError (SchemaMessageProvider.GenericError, new Object[] { error });
}
}
1.1 xml-xerces/java/src/org/apache/xerces/validators/schema/SchemaImporter.java
Index: SchemaImporter.java
===================================================================
/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 1999 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/>.
*/
package org.apache.xerces.validators.schema;
import java.io.IOException;
import java.util.Hashtable; // REVISIT replace
import java.util.Vector; // REVISIT replace
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXParseException;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.apache.xerces.dom.DocumentImpl;
import org.apache.xerces.dom.DocumentTypeImpl;
import org.apache.xerces.framework.XMLContentSpec;
import org.apache.xerces.framework.XMLErrorReporter;
import org.apache.xerces.msg.SchemaMessages;
import org.apache.xerces.parsers.DOMParser;
import org.apache.xerces.readers.DefaultEntityHandler;
import org.apache.xerces.utils.StringPool;
import org.apache.xerces.validators.common.XMLValidator;
import org.apache.xerces.validators.common.XMLContentModel;
import org.apache.xerces.validators.datatype.DatatypeValidator;
import org.apache.xerces.validators.datatype.InvalidDatatypeValueException;
import org.apache.xerces.validators.datatype.IllegalFacetException;
import org.apache.xerces.validators.datatype.IllegalFacetValueException;
import org.apache.xerces.validators.datatype.UnknownFacetException;
import org.apache.xerces.validators.datatype.BooleanValidator;
import org.apache.xerces.validators.datatype.IntegerValidator;
import org.apache.xerces.validators.datatype.StringValidator;
import org.apache.xerces.validators.datatype.FloatValidator;
import org.apache.xerces.validators.datatype.DoubleValidator;
import org.apache.xerces.validators.datatype.DecimalValidator;
import org.apache.xerces.validators.datatype.TimeDurationValidator;
import org.apache.xerces.validators.datatype.TimeInstantValidator;
import org.apache.xerces.validators.datatype.BinaryValidator;
import org.apache.xerces.validators.datatype.URIValidator;
/**
* SchemaImporter is an <font color="red"><b>experimental</b></font> implementation
* of a validator for the W3C Schema Language. All of its implementation is subject
* to change.
*/
public class SchemaImporter {
//
//
//
private Schema fSchema = null;
private XMLValidator fValidator = null;
private XMLErrorReporter fErrorReporter = null;
private DefaultEntityHandler fEntityHandler = null;
private StringPool fStringPool = null;
private DatatypeValidatorRegistry fDatatypeRegistry = new DatatypeValidatorRegistry();
private int fTypeCount = 0;
private int fGroupCount = 0;
private int fModelGroupCount = 0;
private int fAttributeGroupCount = 0;
private int fDatatypeCount = 0;
private Hashtable fForwardRefs = new Hashtable(); // REVISIT w/ more efficient structure later
private Hashtable fAttrGroupUses = new Hashtable();
// constants
private static final String ELT_COMMENT = "comment";
private static final String ELT_DATATYPEDECL = "datatype";
private static final String ELT_ARCHETYPEDECL = "type";
private static final String ELT_ELEMENTDECL = "element";
private static final String ELT_GROUPDECL = "group";
private static final String ELT_ATTRGROUPDECL = "attributeGroup";
// private static final String ELT_TEXTENTITYDECL = "textEntity";
// private static final String ELT_EXTERNALENTITYDECL = "externalEntity";
// private static final String ELT_UNPARSEDENTITYDECL = "unparsedEntity";
private static final String ELT_NOTATIONDECL = "notation";
// private static final String ELT_REFINES = "refines";
private static final String ELT_RESTRICTIONS = "restrictions";
private static final String ELT_ATTRIBUTEDECL = "attribute";
private static final String ELT_ANNOTATION = "annotation";
private static final String ELT_ANY = "any";
private static final String ATT_NAME = "name";
private static final String ATT_CONTENT = "content";
private static final String ATT_MODEL = "model";
private static final String ATT_ORDER = "order";
private static final String ATT_TYPE = "type";
private static final String ATT_DEFAULT = "default";
private static final String ATT_FIXED = "fixed";
private static final String ATT_COLLECTION = "collection";
private static final String ATT_REF = "ref";
private static final String ATT_ARCHREF = "archRef";
private static final String ATT_SCHEMAABBREV = "schemaAbbrev";
private static final String ATT_SCHEMANAME = "schemaName";
private static final String ATT_MINOCCURS = "minOccurs";
private static final String ATT_MAXOCCURS = "maxOccurs";
// private static final String ATT_EXPORT = "export";
private static final String ATT_SOURCE = "source";
private static final String ATT_VALUE = "value";
private static final String ATTVAL_ANY = "any";
private static final String ATTVAL_MIXED = "mixed";
private static final String ATTVAL_EMPTY = "empty";
private static final String ATTVAL_CHOICE = "choice";
private static final String ATTVAL_SEQ = "seq";
private static final String ATTVAL_ALL = "all";
private static final String ATTVAL_ELEMONLY = "elementOnly";
private static final String ATTVAL_TEXTONLY = "textOnly";
private Document fSchemaDocument = null;
//
//
//
public SchemaImporter(StringPool stringPool,
XMLErrorReporter errorReporter,
DefaultEntityHandler entityHandler,
XMLValidator validator) {
fErrorReporter = errorReporter;
fEntityHandler = entityHandler;
fStringPool = stringPool;
fValidator = validator;
fDatatypeRegistry.initializeRegistry();
fSchema = new Schema (fErrorReporter, fValidator);
}
//
//
//
public void reset(StringPool stringPool) throws Exception {
fStringPool = stringPool;
// need to reset the datatype registry !!
fDatatypeRegistry = new DatatypeValidatorRegistry();
fDatatypeRegistry.initializeRegistry();
fSchema = new Schema (fErrorReporter, fValidator);
}
//
//
//
public Document getSchemaDocument() {
return fSchemaDocument;
}
//
//
//
private int getContentSpecHandleForElementType(int elementType) {
return fValidator.getContentSpecHandle(fStringPool.getDeclaration(elementType));
}
private int getContentSpecTypeForElementType(int elementType) {
return fValidator.getContentSpecType(fStringPool.getDeclaration(elementType));
}
// content spec node types
/** Occurrence count: [0, n]. */
private static final int CONTENTSPECNODE_ZERO_TO_N = XMLContentSpec.CONTENTSPECNODE_SEQ + 1;
/** Occurrence count: [m, n]. */
private static final int CONTENTSPECNODE_M_TO_N = CONTENTSPECNODE_ZERO_TO_N + 1;
/** Occurrence count: [m, *). */
private static final int CONTENTSPECNODE_M_OR_MORE = CONTENTSPECNODE_M_TO_N + 1;
private DOMParser fSchemaParser = null;
public void loadSchema(InputSource is) {
SchemaParser parser = new SchemaParser (fSchema);
try {
parser.setEntityResolver(new Resolver());
parser.setErrorHandler(new ErrorHandler());
//parser.setFeature("http://xml.org/sax/features/validation", true);
parser.parse (is);
}
catch (Exception e) {
e.printStackTrace();
System.exit (1);
}
// create parser for schema
if (fSchemaParser == null) {
fSchemaParser = new DOMParser() {
public void ignorableWhitespace(char ch[], int start, int length) {}
public void ignorableWhitespace(int dataIdx) {}
};
fSchemaParser.setEntityResolver(new Resolver());
fSchemaParser.setErrorHandler(new ErrorHandler());
}
// parser schema file
try {
fSchemaParser.setFeature("http://xml.org/sax/features/validation", true);
fSchemaParser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", false);
fSchemaParser.parse(is);
}
catch (SAXException se) {
se.getException().printStackTrace();
System.err.println("error parsing schema file");
// System.exit(1);
}
catch (Exception e) {
e.printStackTrace();
System.err.println("error parsing schema file");
// System.exit(1);
}
fSchemaDocument = fSchemaParser.getDocument();
if (fSchemaDocument == null) {
System.err.println("error: couldn't load schema file!");
return;
}
// traverse schema
try {
Element root = fSchemaDocument.getDocumentElement();
traverseSchema(root);
}
catch (Exception e) {
e.printStackTrace(System.err);
// System.exit(1);
}
}
private void traverseSchema(Element root) throws Exception {
// is there anything to do?
if (root == null) {
return;
}
// run through children
for (Element child = XUtil.getFirstChildElement(root);
child != null;
child = XUtil.getNextSiblingElement(child)) {
//System.out.println("child: "+child.getNodeName()+' '+child.getAttribute(ATT_NAME));
//
// Element type
//
String name = child.getNodeName();
if (name.equals(ELT_COMMENT)) {
traverseComment(child);
} else if (name.equals(ELT_DATATYPEDECL)) {
traverseDatatypeDecl(child);
} else if (name.equals(ELT_ARCHETYPEDECL)) {
traverseTypeDecl(child);
} else if (name.equals(ELT_ELEMENTDECL)) { // && child.getAttribute(ATT_REF).equals("")) {
traverseElementDecl(child);
} else if (name.equals(ELT_ATTRGROUPDECL)) {
traverseAttrGroup(child);
} else if (name.equals(ELT_GROUPDECL) && child.getAttribute(ATT_REF).equals("")) {
traverseGroup(child);
}
//
// Entities
//
/*
else if (name.equals(ELT_TEXTENTITYDECL) ||
name.equals(ELT_EXTERNALENTITYDECL) ||
name.equals(ELT_UNPARSEDENTITYDECL)) {
int entityName = fStringPool.addSymbol(child.getAttribute(ATT_NAME));
if (name.equals(ELT_TEXTENTITYDECL)) {
int value = fStringPool.addString(child.getFirstChild().getFirstChild().getNodeValue());
fEntityHandler.addInternalEntityDecl(entityName, value, true);
}
else {
int publicId = fStringPool.addString(child.getAttribute("public"));
int systemId = fStringPool.addString(child.getAttribute("system"));
if (name.equals(ELT_EXTERNALENTITYDECL)) {
fEntityHandler.addExternalEntityDecl(entityName, publicId, systemId, true);
}
else {
int notationName = fStringPool.addSymbol(child.getAttribute("notation"));
fEntityHandler.addUnparsedEntityDecl(entityName, publicId, systemId, notationName, true);
}
}
}
*/
//
// Notation
//
else if (name.equals(ELT_NOTATIONDECL)) {
int notationName = fStringPool.addSymbol(child.getAttribute(ATT_NAME));
int publicId = fStringPool.addString(child.getAttribute("public"));
int systemId = fStringPool.addString(child.getAttribute("system"));
fEntityHandler.addNotationDecl(notationName, publicId, systemId, true);
}
} // for each child node
cleanupForwardReferences();
} // traverseSchema(Element)
/**
* this method is going to be needed to handle any elementDecl derived constructs which
* need to copy back attributes that haven't been declared yet.
* right now that's just attributeGroups and types -- grrr.
*/
private void cleanupForwardReferences() {
for (java.util.Enumeration keys = fForwardRefs.keys(); keys.hasMoreElements();) {
Object k = keys.nextElement();
int ik = ((Integer) k).intValue();
cleanupForwardReferencesTo(ik);
}
}
private void cleanupForwardReferencesTo(int r) {
Vector referrers = (Vector) fForwardRefs.get(new Integer(r));
if (referrers == null) return;
// System.out.println("referee "+r+" csnIndex= "+getContentSpec(getElement(r)));
for (int i = 0; i < referrers.size(); i++) {
int ref = ((Integer) referrers.elementAt(i)).intValue();
// System.out.println("referrer "+referrers.elementAt(i)+ " csnIndex = "+getContentSpec(getElement(((Integer)referrers.elementAt(i)).intValue())));
// System.out.println("copying from "+fStringPool.toString(r)+" to "+fStringPool.toString(ref));
fValidator.copyAtts(r, ((Integer) referrers.elementAt(i)).intValue());
// try {
// fValidator.fixupDeclaredElements(ref, r);
// } catch (Exception e) {
// System.out.println("Error while cleaning up");
// }
// cleanupForwardReferencesTo(ref);
}
}
private void traverseComment(Element comment) {
return; // do nothing
}
private int traverseTypeDecl(Element typeDecl) throws Exception {
String typeName = typeDecl.getAttribute(ATT_NAME);
String content = typeDecl.getAttribute(ATT_CONTENT);
String source = typeDecl.getAttribute(ATT_SOURCE);
if (typeName.equals("")) { // gensym a unique name
typeName = "http://www.apache.org/xml/xerces/internalType"+fTypeCount++;
}
Element child = null;
int contentSpecType = 0;
int csnType = 0;
int left = -2;
int right = -2;
Vector uses = new Vector();
// skip refinement and annotations
child = null;
for (child = XUtil.getFirstChildElement(typeDecl);
child != null && (child.getNodeName().equals(ELT_RESTRICTIONS) ||
child.getNodeName().equals(ELT_ANNOTATION));
child = XUtil.getNextSiblingElement(child)) {
if (child.getNodeName().equals(ELT_RESTRICTIONS))
reportSchemaError(SchemaMessageProvider.FeatureUnsupported,
new Object [] { "Restriction" });
}
// if content = textonly, source is a datatype
if (content.equals(ATTVAL_TEXTONLY)) {
if (fDatatypeRegistry.getValidatorFor(source) == null) // must be datatype
reportSchemaError(SchemaMessageProvider.NotADatatype,
new Object [] { source }); //REVISIT check forward refs
//handle datatypes
contentSpecType = fStringPool.addSymbol("DATATYPE");
left = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_LEAF,
fStringPool.addSymbol(source),
-1, false);
} else {
contentSpecType = fStringPool.addSymbol("CHILDREN");
csnType = XMLContentSpec.CONTENTSPECNODE_SEQ;
boolean mixedContent = false;
boolean elementContent = false;
boolean textContent = false;
left = -2;
right = -2;
boolean hadContent = false;
if (content.equals(ATTVAL_EMPTY)) {
contentSpecType = fStringPool.addSymbol("EMPTY");
left = -1; // no contentSpecNode needed
} else if (content.equals(ATTVAL_MIXED) || content.equals("")) {
contentSpecType = fStringPool.addSymbol("MIXED");
mixedContent = true;
csnType = XMLContentSpec.CONTENTSPECNODE_CHOICE;
} else if (content.equals(ATTVAL_ELEMONLY)) {
elementContent = true;
} else if (content.equals(ATTVAL_TEXTONLY)) {
textContent = true;
}
if (mixedContent) {
// a dd #PCDATA leaf
left = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_LEAF,
-1, // -1 means "#PCDATA" is name
-1, false);
}
for (;
child != null;
child = XUtil.getNextSiblingElement(child)) {
int index = -2;
hadContent = true;
String childName = child.getNodeName();
if (childName.equals(ELT_ELEMENTDECL)) {
if (child.getAttribute(ATT_REF).equals("") &&
child.getAttribute(ATT_TYPE).equals("")) { // elt decl
if (elementContent) //R EVISIT: no support for nested type declarations
reportSchemaError(SchemaMessageProvider.FeatureUnsupported,
new Object [] { "Nesting element declarations" });
else
reportSchemaError(SchemaMessageProvider.NestedOnlyInElemOnly, null);
} else if (mixedContent || elementContent) {
if (!child.getAttribute(ATT_TYPE).equals("")) {
int elementNameIndex = traverseElementDecl(child);
index = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_LEAF,
elementNameIndex,
-1, false);
} else // ATT_REF != ""
index = traverseElementRef(child);
} else {
reportSchemaError(SchemaMessageProvider.EltRefOnlyInMixedElemOnly, null);
}
} else if (childName.equals(ELT_GROUPDECL)) {
if (elementContent) {
int groupNameIndex = 0;
if (child.getAttribute(ATT_REF).equals("")) {
groupNameIndex = traverseGroup(child);
} else
groupNameIndex = traverseGroupRef(child);
index = getContentSpecHandleForElementType(groupNameIndex);
} else if (!elementContent)
reportSchemaError(SchemaMessageProvider.OnlyInEltContent,
new Object [] { "group" });
else // buildAll
reportSchemaError(SchemaMessageProvider.OrderIsAll,
new Object [] { "group" } );
} else if (childName.equals(ELT_ATTRIBUTEDECL) ||
childName.equals(ELT_ATTRGROUPDECL)) {
break; // attr processing is done be low
} else if (childName.equals(ELT_ANY)) {
contentSpecType = fStringPool.addSymbol("ANY");
left = -1;
} else { // datatype qual
if (source.equals(""))
reportSchemaError(SchemaMessageProvider.DatatypeWithType, null);
else
reportSchemaError(SchemaMessageProvider.DatatypeQualUnsupported,
new Object [] { childName });
}
uses.addElement(new Integer(index));
if (left == -2) {
left = index;
} else if (right == -2) {
right = index;
} else {
left = fValidator.addContentSpecNode(csnType, left, right, false);
right = index;
}
}
if (hadContent && right != -2)
left = fValidator.addContentSpecNode(csnType, left, right, false);
if (mixedContent && hadContent) {
// set occurrence count
left = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE,
left, -1, false);
}
}
// stick in ElementDeclPool as a hack
int typeNameIndex = fStringPool.addSymbol(typeName); //REVISIT namespace clashes possible
int typeIndex = fValidator.addElementDecl(typeNameIndex, contentSpecType, left, false);
for (int x = 0; x < uses.size(); x++)
addUse(typeNameIndex, (Integer)uses.elementAt(x));
// (attribute | attrGroupRef)*
for (;
child != null;
child = XUtil.getNextSiblingElement(child)) {
String childName = child.getNodeName();
if (childName.equals(ELT_ATTRIBUTEDECL)) {
traverseAttributeDecl(child, typeIndex);
} else if (childName.equals(ELT_ATTRGROUPDECL) && !child.getAttribute(ATT_REF).equals("")) {
int index = traverseAttrGroupRef(child);
if (getContentSpecHandleForElementType(index) == -1) {
reportSchemaError(SchemaMessageProvider.FeatureUnsupported,
new Object [] { "Forward References to attrGroup" });
Vector v = null;
Integer i = new Integer(index);
if ((v = (Vector) fForwardRefs.get(i)) == null)
v = new Vector();
v.addElement(new Integer(typeNameIndex));
fForwardRefs.put(i,v);
addUse(typeNameIndex, index);
} else
fValidator.copyAtts(index, typeNameIndex);
}
}
return typeNameIndex;
}
private int traverseGroup(Element groupDecl) throws Exception {
String groupName = groupDecl.getAttribute(ATT_NAME);
String collection = groupDecl.getAttribute(ATT_COLLECTION);
String order = groupDecl.getAttribute(ATT_ORDER);
if (groupName.equals("")) { // gensym a unique name
groupName = "http://www.apache.org/xml/xerces/internalGroup"+fGroupCount++;
}
Element child = XUtil.getFirstChildElement(groupDecl);
while (child != null && child.getNodeName().equals(ELT_ANNOTATION))
child = XUtil.getNextSiblingElement(child);
int contentSpecType = 0;
int csnType = 0;
boolean buildAll = false;
int allChildren[] = null;
int allChildCount = 0;
if (order.equals(ATTVAL_CHOICE)) {
csnType = XMLContentSpec.CONTENTSPECNODE_CHOICE;
contentSpecType = fStringPool.addSymbol("CHILDREN");
} else if (order.equals(ATTVAL_SEQ)) {
csnType = XMLContentSpec.CONTENTSPECNODE_SEQ;
contentSpecType = fStringPool.addSymbol("CHILDREN");
} else if (order.equals(ATTVAL_ALL)) {
buildAll = true;
allChildren = new int[((org.apache.xerces.dom.NodeImpl)groupDecl).getLength()];
allChildCount = 0;
}
int left = -2;
int right = -2;
boolean hadContent = false;
int groupIndices[] = new int [((org.apache.xerces.dom.NodeImpl)groupDecl).getLength()];
int numGroups = 0;
for (;
child != null;
child = XUtil.getNextSiblingElement(child)) {
int index = -2;
hadContent = true;
String childName = child.getNodeName();
if (childName.equals(ELT_ELEMENTDECL)) {
if (child.getAttribute(ATT_REF).equals("") &&
child.getAttribute(ATT_TYPE).equals("")) { //elt decl
reportSchemaError(SchemaMessageProvider.FeatureUnsupported,
new Object [] { "Nesting element declarations" });
} else {
if (!child.getAttribute(ATT_TYPE).equals("")) {
int elementNameIndex = traverseElementDecl(child);
index = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_LEAF,
elementNameIndex,
-1, false);
} else {
index = traverseElementRef(child);
}
}
} else if (childName.equals(ELT_GROUPDECL)) {
if (!buildAll) {
int groupNameIndex = traverseGroup(child);
groupIndices[numGroups++] = groupNameIndex;
index = getContentSpecHandleForElementType(groupNameIndex);
} else
reportSchemaError(SchemaMessageProvider.OrderIsAll,
new Object [] { "group" } );
} else {
reportSchemaError(SchemaMessageProvider.GroupContentRestricted,
new Object [] { "group", childName });
}
if (buildAll) {
allChildren[allChildCount++] = index;
} else if (left == -2) {
left = index;
} else if (right == -2) {
right = index;
} else {
left = fValidator.addContentSpecNode(csnType, left, right, false);
right = index;
}
}
if (buildAll) {
left = buildAllModel(allChildren,allChildCount);
} else {
if (hadContent && right != -2)
left = fValidator.addContentSpecNode(csnType, left, right, false);
}
left = expandContentModel(left, groupDecl);
// stick in ElementDeclPool as a hack
int groupNameIndex = fStringPool.addSymbol(groupName); //REVISIT namespace clashes possible
int groupIndex = fValidator.addElementDecl(groupNameIndex, contentSpecType, left, false);
return groupNameIndex;
}
private int traverseGroupRef(Element groupRef) {
String name = groupRef.getAttribute(ATT_REF);
int index = fStringPool.addSymbol(name);
return index;
}
public int traverseDatatypeDecl(Element datatypeDecl) throws Exception {
int newTypeName;
if (datatypeDecl.getAttribute(ATT_NAME).equals("")) {
String newTypeString = "http://www.apache.org/xml/xerces/internalDatatype"+fGroupCount++;
newTypeName = fStringPool.addSymbol(newTypeString);
} else
newTypeName = fStringPool.addSymbol(datatypeDecl.getAttribute(ATT_NAME));
int basetype = fStringPool.addSymbol(datatypeDecl.getAttribute(ATT_SOURCE));
// check that base type is defined
//REVISIT: how do we do the extension mechanism? hardwired type name?
DatatypeValidator baseValidator = fDatatypeRegistry.getValidatorFor(datatypeDecl.getAttribute(ATT_SOURCE));
if (baseValidator == null) {
reportSchemaError(SchemaMessageProvider.UnknownBaseDatatype,
new Object [] { datatypeDecl.getAttribute(ATT_SOURCE), datatypeDecl.getAttribute(ATT_NAME) });
return -1;
}
// build facet list
int numFacets = 0;
int numEnumerationLiterals = 0;
Hashtable facetData = new Hashtable();
Vector enumData = new Vector();
// Skip annotations
Node facet = datatypeDecl.getFirstChild();
while (facet != null && facet.getNodeName().equals(ELT_ANNOTATION))
facet = facet.getNextSibling();
while (facet != null) {
if (facet.getNodeType() == Node.ELEMENT_NODE) {
Element facetElt = (Element) facet;
numFacets++;
if (facetElt.getNodeName().equals(DatatypeValidator.ENUMERATION)) {
numEnumerationLiterals++;
enumData.addElement(facetElt.getAttribute(ATT_VALUE));
} else {
facetData.put(facetElt.getNodeName(),facetElt.getAttribute(ATT_VALUE));
}
}
facet = facet.getNextSibling();
}
if (numEnumerationLiterals > 0) {
facetData.put(DatatypeValidator.ENUMERATION, enumData);
}
// create & register validator for "generated" type if it doesn't exist
try {
DatatypeValidator newValidator = (DatatypeValidator) baseValidator.getClass().newInstance();
if (numFacets > 0)
newValidator.setFacets(facetData);
fDatatypeRegistry.addValidator(fStringPool.toString(newTypeName),newValidator);
} catch (Exception e) {
reportSchemaError(SchemaMessageProvider.DatatypeError,
new Object [] { e.getMessage() });
}
return newTypeName;
}
private int traverseElementDecl(Element elementDecl) throws Exception {
int contentSpecType = -1;
int contentSpecNodeIndex = -1;
int typeNameIndex = -1;
String name = elementDecl.getAttribute(ATT_NAME);
String ref = elementDecl.getAttribute(ATT_REF);
String type = elementDecl.getAttribute(ATT_TYPE);
String minOccurs = elementDecl.getAttribute(ATT_MINOCCURS);
String maxOccurs = elementDecl.getAttribute(ATT_MAXOCCURS);
String dflt = elementDecl.getAttribute(ATT_DEFAULT);
String fixed = elementDecl.getAttribute(ATT_FIXED);
int attrCount = 0;
if (!ref.equals("")) attrCount++;
if (!type.equals("")) attrCount++;
//REVISIT top level check for ref & archref
if (attrCount > 1)
reportSchemaError(SchemaMessageProvider.OneOfTypeRefArchRef, null);
if (!ref.equals("")) {
if (XUtil.getFirstChildElement(elementDecl) != null)
reportSchemaError(SchemaMessageProvider.NoContentForRef, null);
int typeName = fStringPool.addSymbol(ref);
contentSpecNodeIndex = getContentSpecHandleForElementType(typeName);
contentSpecType = getContentSpecTypeForElementType(typeName);
int elementNameIndex = fStringPool.addSymbol(name);
int elementIndex = -1;
if (contentSpecNodeIndex == -1) {
contentSpecType = XMLContentSpec.CONTENTSPECNODE_LEAF;
contentSpecNodeIndex = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_LEAF,
elementNameIndex, -1, false);
fValidator.addElementDecl(elementNameIndex, contentSpecType, contentSpecNodeIndex, true);
reportSchemaError(SchemaMessageProvider.FeatureUnsupported,
new Object [] { "Forward references to archetypes" });
Vector v = null;
Integer i = new Integer(typeName);
if ((v = (Vector) fForwardRefs.get(i)) == null)
v = new Vector();
v.addElement(new Integer(elementNameIndex));
fForwardRefs.put(i,v);
addUse(elementNameIndex, typeName);
} else {
fValidator.addElementDecl(elementNameIndex, contentSpecType, contentSpecNodeIndex, true);
// copy up attribute decls from type object
fValidator.copyAtts(typeName, elementNameIndex);
}
return elementNameIndex;
}
// element has a single child element, either a datatype or a type, null if primitive
Element content = XUtil.getFirstChildElement(elementDecl);
while (content != null && content.getNodeName().equals(ELT_ANNOTATION))
content = XUtil.getNextSiblingElement(content);
if (content != null) {
String contentName = content.getNodeName();
if (contentName.equals(ELT_ARCHETYPEDECL)) {
typeNameIndex = traverseTypeDecl(content);
contentSpecNodeIndex = getContentSpecHandleForElementType(typeNameIndex);
contentSpecType = getContentSpecTypeForElementType(typeNameIndex);
} else if (contentName.equals(ELT_DATATYPEDECL)) {
reportSchemaError(SchemaMessageProvider.FeatureUnsupported,
new Object [] { "Nesting datatype declarations" });
// contentSpecNodeIndex = traverseDatatypeDecl(content);
// contentSpecType = fStringPool.addSymbol("DATATYPE");
} else if (!type.equals("")) { // datatype
contentSpecType = fStringPool.addSymbol("DATATYPE");
// set content spec node index to leaf
contentSpecNodeIndex = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_LEAF,
fStringPool.addSymbol(content.getAttribute(ATT_NAME)),
-1, false);
// set occurrance count
contentSpecNodeIndex = expandContentModel(contentSpecNodeIndex, content);
} else if (type.equals("")) { // "untyped" leaf
// untyped leaf element decl
contentSpecType = fStringPool.addSymbol("CHILDREN");
// add leaf
int leftIndex = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_LEAF,
fStringPool.addSymbol(content.getAttribute(ATT_NAME)),
-1, false);
// set occurrence count
contentSpecNodeIndex = expandContentModel(contentSpecNodeIndex, content);
} else {
System.out.println("unhandled case in element decl code");
}
} else if (!type.equals("")) { // type specified in attribute, not content
contentSpecType = fStringPool.addSymbol("DATATYPE");
// set content spec node index to leaf
contentSpecNodeIndex = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_LEAF,
fStringPool.addSymbol(type),
-1, false);
// set occurrance count
contentSpecNodeIndex = expandContentModel(contentSpecNodeIndex, elementDecl);
}
//
// Create element decl
//
int elementNameIndex = fStringPool.addSymbol(elementDecl.getAttribute(ATT_NAME));
// add element decl to pool
int elementIndex = fValidator.addElementDecl(elementNameIndex, contentSpecType, contentSpecNodeIndex, true);
// System.out.println("elementIndex:"+elementIndex+" "+elementDecl.getAttribute(ATT_NAME)+" eltType:"+elementName+" contentSpecType:"+contentSpecType+
// " SpecNodeIndex:"+ contentSpecNodeIndex);
// copy up attribute decls from type object
if (typeNameIndex != -1)
fValidator.copyAtts(typeNameIndex, elementNameIndex);
return elementNameIndex;
}
private int traverseElementRef(Element elementRef) {
String elementName = elementRef.getAttribute(ATT_REF);
int elementTypeIndex = fStringPool.addSymbol(elementName);
int contentSpecNodeIndex = 0;
try {
contentSpecNodeIndex = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_LEAF,
elementTypeIndex, -1, false);
contentSpecNodeIndex = expandContentModel(contentSpecNodeIndex, elementRef);
} catch (Exception e) {
//REVISIT: integrate w/ error handling
e.printStackTrace();
}
return contentSpecNodeIndex;
}
//REVISIT: elementIndex API is ugly
private void traverseAttributeDecl(Element attrDecl, int elementIndex) throws Exception {
// attribute name
int attName = fStringPool.addSymbol(attrDecl.getAttribute(ATT_NAME));
// attribute type
int attType = -1;
int enumeration = -1;
String datatype = attrDecl.getAttribute(ATT_TYPE);
if (datatype.equals("")) {
Element child = XUtil.getFirstChildElement(attrDecl);
while (child != null && !child.getNodeName().equals(ELT_DATATYPEDECL))
child = XUtil.getNextSiblingElement(child);
if (child != null && child.getNodeName().equals(ELT_DATATYPEDECL)) {
attType = fStringPool.addSymbol("DATATYPE");
enumeration = traverseDatatypeDecl(child);
} else
attType = fStringPool.addSymbol("CDATA");
} else {
if (datatype.equals("string")) {
attType = fStringPool.addSymbol("CDATA");
} else if (datatype.equals("ID")) {
attType = fStringPool.addSymbol("ID");
} else if (datatype.equals("IDREF")) {
attType = fStringPool.addSymbol("IDREF");
} else if (datatype.equals("IDREFS")) {
attType = fStringPool.addSymbol("IDREFS");
} else if (datatype.equals("ENTITY")) {
attType = fStringPool.addSymbol("ENTITY");
} else if (datatype.equals("ENTITIES")) {
attType = fStringPool.addSymbol("ENTITIES");
} else if (datatype.equals("NMTOKEN")) {
Element e = XUtil.getFirstChildElement(attrDecl, "enumeration");
if (e == null) {
attType = fStringPool.addSymbol("NMTOKEN");
} else {
attType = fStringPool.addSymbol("ENUMERATION");
enumeration = fStringPool.startStringList();
for (Element literal = XUtil.getFirstChildElement(e, "literal");
literal != null;
literal = XUtil.getNextSiblingElement(literal, "literal")) {
int stringIndex = fStringPool.addSymbol(literal.getFirstChild().getNodeValue());
fStringPool.addStringToList(enumeration, stringIndex);
}
fStringPool.finishStringList(enumeration);
}
} else if (datatype.equals("NMTOKENS")) {
attType = fStringPool.addSymbol("NMTOKENS");
} else if (datatype.equals(ELT_NOTATIONDECL)) {
attType = fStringPool.addSymbol("NOTATION");
} else { // REVISIT: Danger: assuming all other ATTR types are datatypes
//REVISIT check against list of validators to ensure valid type name
attType = fStringPool.addSymbol("DATATYPE");
enumeration = fStringPool.addSymbol(datatype);
}
}
// attribute default type
int attDefaultType = -1;
int attDefaultValue = -1;
boolean required = attrDecl.getAttribute("minOccurs").equals("1");
if (required) {
attDefaultType = fStringPool.addSymbol("#REQUIRED");
} else {
String fixed = attrDecl.getAttribute(ATT_FIXED);
if (!fixed.equals("")) {
attDefaultType = fStringPool.addSymbol("#FIXED");
attDefaultValue = fStringPool.addString(fixed);
} else {
// attribute default value
String defaultValue = attrDecl.getAttribute(ATT_DEFAULT);
if (!defaultValue.equals("")) {
attDefaultType = fStringPool.addSymbol("");
attDefaultValue = fStringPool.addString(defaultValue);
} else {
attDefaultType = fStringPool.addSymbol("#IMPLIED");
}
}
// check default value is valid for the datatype.
if (attType == fStringPool.addSymbol("DATATYPE") && attDefaultValue != -1) {
try { // REVISIT - integrate w/ error handling
String type = fStringPool.toString(enumeration);
DatatypeValidator v = fDatatypeRegistry.getValidatorFor(type);
if (v != null)
v.validate(fStringPool.toString(attDefaultValue));
else
reportSchemaError(SchemaMessageProvider.NoValidatorFor,
new Object [] { type });
} catch (InvalidDatatypeValueException idve) {
reportSchemaError(SchemaMessageProvider.IncorrectDefaultType,
new Object [] { attrDecl.getAttribute(ATT_NAME), idve.getMessage() });
} catch (Exception e) {
e.printStackTrace();
System.out.println("Internal error in attribute datatype validation");
}
}
}
// add attribute to element decl pool
fValidator.addAttDef(elementIndex, attName, attType, enumeration, attDefaultType, attDefaultValue, true);
}
private int traverseAttrGroup(Element attrGroupDecl) throws Exception {
String attrGroupName = attrGroupDecl.getAttribute(ATT_NAME);
if (attrGroupName.equals("")) { // gensym a unique name
attrGroupName = "http://www.apache.org/xml/xerces/internalGroup"+fGroupCount++;
}
Element child = XUtil.getFirstChildElement(attrGroupDecl);
while (child != null && child.getNodeName().equals(ELT_ANNOTATION))
child = XUtil.getNextSiblingElement(child);
int groupIndices[] = new int [((org.apache.xerces.dom.NodeImpl)attrGroupDecl).getLength()];
int numGroups = 0;
for (;
child != null;
child = XUtil.getNextSiblingElement(child)) {
String childName = child.getNodeName();
if (childName.equals(ELT_ATTRGROUPDECL) && !child.getAttribute(ATT_REF).equals("")) {
groupIndices[numGroups++] = traverseAttrGroupRef(child);
if (getContentSpecHandleForElementType(groupIndices[numGroups-1]) == -1) {
reportSchemaError(SchemaMessageProvider.FeatureUnsupported,
new Object [] { "Forward reference to AttrGroup" });
}
} else if (childName.equals(ELT_ATTRIBUTEDECL)) {
continue;
} else {
reportSchemaError(SchemaMessageProvider.IllegalAttContent,
new Object [] { childName });
}
}
// stick in ElementDeclPool as a hack
int attrGroupNameIndex = fStringPool.addSymbol(attrGroupName); //REVISIT namespace clashes possible
int attrGroupIndex = fValidator.addElementDecl(attrGroupNameIndex, 0, 0, false);
// System.out.println("elementIndex:"+groupIndex+" "+groupName+" eltType:"+groupNameIndex+" SpecType:"+contentSpecType+
// " SpecNodeIndex:"+ left);
// (attribute | attrGroupRef)*
for (child = XUtil.getFirstChildElement(attrGroupDecl); // start from the beginning to just do attrs
child != null;
child = XUtil.getNextSiblingElement(child)) {
String childName = child.getNodeName();
if (childName.equals(ELT_ATTRIBUTEDECL)) {
traverseAttributeDecl(child, attrGroupIndex);
} else if (childName.equals(ELT_ATTRGROUPDECL)) {
int index = traverseAttrGroupRef(child);
if (getContentSpecHandleForElementType(index) == -1) {
reportSchemaError(SchemaMessageProvider.FeatureUnsupported,
new Object [] { "Forward reference to AttrGroup" });
Vector v = null;
Integer i = new Integer(index);
if ((v = (Vector) fForwardRefs.get(i)) == null)
v = new Vector();
v.addElement(new Integer(attrGroupNameIndex));
fForwardRefs.put(i,v);
addUse(attrGroupNameIndex, index);
} else
groupIndices[numGroups++] = getContentSpecHandleForElementType(index);
}
}
// copy up attribute decls from nested groups
for (int i = 0; i < numGroups; i++) {
fValidator.copyAtts(groupIndices[i], attrGroupNameIndex);
}
return attrGroupNameIndex;
}
private int traverseAttrGroupRef(Element attrGroupRef) {
String name = attrGroupRef.getAttribute(ATT_REF);
int index = fStringPool.addSymbol(name);
return index;
}
private void addUse(int def, int use) {
addUse(def, new Integer(use));
}
private void addUse(int def, Integer use) {
Vector v = (Vector) fAttrGroupUses.get(new Integer(def));
if (v == null) v = new Vector();
v.addElement(use);
}
/** builds the all content model */
private int buildAllModel(int children[], int count) throws Exception {
// build all model
if (count > 1) {
// create and initialize singletons
XMLContentSpec.Node choice = new XMLContentSpec.Node();
choice.type = XMLContentSpec.CONTENTSPECNODE_CHOICE;
choice.value = -1;
choice.otherValue = -1;
// build all model
sort(children, 0, count);
int index = buildAllModel(children, 0, choice);
return index;
}
if (count > 0) {
return children[0];
}
return -1;
}
/** Builds the all model. */
private int buildAllModel(int src[], int offset,
XMLContentSpec.Node choice) throws Exception {
// swap last two places
if (src.length - offset == 2) {
int seqIndex = createSeq(src);
if (choice.value == -1) {
choice.value = seqIndex;
}
else {
if (choice.otherValue != -1) {
choice.value = fValidator.addContentSpecNode(choice.type, choice.value, choice.otherValue, false);
}
choice.otherValue = seqIndex;
}
swap(src, offset, offset + 1);
seqIndex = createSeq(src);
if (choice.value == -1) {
choice.value = seqIndex;
}
else {
if (choice.otherValue != -1) {
choice.value = fValidator.addContentSpecNode(choice.type, choice.value, choice.otherValue, false);
}
choice.otherValue = seqIndex;
}
return fValidator.addContentSpecNode(choice.type, choice.value, choice.otherValue, false);
}
// recurse
for (int i = offset; i < src.length - 1; i++) {
choice.value = buildAllModel(src, offset + 1, choice);
choice.otherValue = -1;
sort(src, offset, src.length - offset);
shift(src, offset, i + 1);
}
int choiceIndex = buildAllModel(src, offset + 1, choice);
sort(src, offset, src.length - offset);
return choiceIndex;
} // buildAllModel(int[],int,ContentSpecNode,ContentSpecNode):int
/** Creates a sequence. */
private int createSeq(int src[]) throws Exception {
int left = src[0];
int right = src[1];
for (int i = 2; i < src.length; i++) {
left = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_SEQ,
left, right, false);
right = src[i];
}
return fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_SEQ,
left, right, false);
} // createSeq(int[]):int
/** Shifts a value into position. */
private void shift(int src[], int pos, int offset) {
int temp = src[offset];
for (int i = offset; i > pos; i--) {
src[i] = src[i - 1];
}
src[pos] = temp;
} // shift(int[],int,int)
/** Simple sort. */
private void sort(int src[], final int offset, final int length) {
for (int i = offset; i < offset + length - 1; i++) {
int lowest = i;
for (int j = i + 1; j < offset + length; j++) {
if (src[j] < src[lowest]) {
lowest = j;
}
}
if (lowest != i) {
int temp = src[i];
src[i] = src[lowest];
src[lowest] = temp;
}
}
} // sort(int[],int,int)
/** Swaps two values. */
private void swap(int src[], int i, int j) {
int temp = src[i];
src[i] = src[j];
src[j] = temp;
} // swap(int[],int,int)
/***
private void print(int indexes[], int offset, boolean mark) {
for (int i = 0; i < indexes.length; i++) {
System.out.print(offset==i?'.':' ');
System.out.print(indexes[i]);
}
if (mark) {
System.out.print(" *");
}
System.out.println();
} // print(int[],int,boolean)
/***/
/** Builds the children content model. */
/* private int buildChildrenModel(Element model, int type) throws Exception {
// is there anything to do?
if (model == null) {
return -1;
}
// fill parent node
int parentValue = -1;
int parentOtherValue = -1;
// build content model bottom-up
int index = -1;
for (Element child = XUtil.getFirstChildElement(model);
child != null;
child = XUtil.getNextSiblingElement(child)) {
//
// leaf
//
String childName = child.getNodeName();
if (childName.equals("elementTypeRef")) {
// add element name to symbol table
String elementType = child.getAttribute(ATT_NAME);
int elementTypeIndex = fStringPool.addSymbol(elementType);
// create leaf node
index = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_LEAF,
elementTypeIndex, -1, false);
// set occurrence count
index = expandContentModel(index, child);
}
//
// all
//
else if (childName.equals(ATTVAL_ALL)) {
index = buildAllModel(child);
}
//
// choice or sequence
//
else {
int childType = childName.equals(ATTVAL_CHOICE)
? XMLContentSpec.CONTENTSPECNODE_CHOICE
: XMLContentSpec.CONTENTSPECNODE_SEQ;
index = buildChildrenModel(child, childType);
}
// add to parent node
if (parentValue == -1) {
parentValue = index;
}
else if (parentOtherValue == -1) {
parentOtherValue = index;
}
else {
parentValue = fValidator.addContentSpecNode(type, parentValue, parentOtherValue, false);
parentOtherValue = index;
}
} // for all children
// set model type
index = fValidator.addContentSpecNode(type, parentValue, parentOtherValue, false);
// set occurrence count
index = expandContentModel(index, model);
// return last content spec node
return index;
} // buildChildrenModel(Element,int):int
*/
private int expandContentModel(int contentSpecNodeIndex, Element element) throws Exception {
// set occurrence count
int occurs = getOccurrenceCount(element);
int m = 1, n = 1;
if (!isSimpleOccurrenceCount(occurs)) {
try { m = Integer.parseInt(element.getAttribute(ATT_MINOCCURS)); }
catch (NumberFormatException e) {
reportSchemaError(SchemaMessageProvider.ValueNotInteger,
new Object [] { ATT_MINOCCURS });
}
try { n = Integer.parseInt(element.getAttribute(ATT_MAXOCCURS)); }
catch (NumberFormatException e) {
reportSchemaError(SchemaMessageProvider.ValueNotInteger,
new Object [] { ATT_MAXOCCURS });
}
}
switch (occurs) {
//
// +
//
case XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE: {
//System.out.println("occurs = +");
contentSpecNodeIndex = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE,
contentSpecNodeIndex, -1, false);
break;
}
//
// *
//
case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE: {
//System.out.println("occurs = *");
contentSpecNodeIndex = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE,
contentSpecNodeIndex, -1, false);
break;
}
//
// ?
//
case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE: {
//System.out.println("occurs = ?");
contentSpecNodeIndex = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE,
contentSpecNodeIndex, -1, false);
break;
}
//
// M -> *
//
case CONTENTSPECNODE_M_OR_MORE: {
//System.out.println("occurs = "+m+" -> *");
// create sequence node
int value = contentSpecNodeIndex;
int otherValue = -1;
// add required number
for (int i = 1; i < m; i++) {
if (otherValue != -1) {
value = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_SEQ,
value, otherValue, false);
}
otherValue = contentSpecNodeIndex;
}
// create optional content model node
contentSpecNodeIndex = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE,
contentSpecNodeIndex, -1, false);
// add optional part
if (otherValue != -1) {
value = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_SEQ,
value, otherValue, false);
}
otherValue = contentSpecNodeIndex;
// set expanded content model index
contentSpecNodeIndex = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_SEQ,
value, otherValue, false);
break;
}
//
// M -> N
//
case CONTENTSPECNODE_M_TO_N: {
//System.out.println("occurs = "+m+" -> "+n);
// create sequence node
int value = contentSpecNodeIndex;
int otherValue = -1;
// add required number
for (int i = 1; i < m; i++) {
if (otherValue != -1) {
value = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_SEQ,
value, otherValue, false);
}
otherValue = contentSpecNodeIndex;
}
// create optional content model node
contentSpecNodeIndex = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE,
contentSpecNodeIndex, -1, false);
// add optional number
for (int i = n; i > m; i--) {
if (otherValue != -1) {
value = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_SEQ,
value, otherValue, false);
}
otherValue = contentSpecNodeIndex;
}
// set expanded content model index
contentSpecNodeIndex = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_SEQ,
value, otherValue, false);
break;
}
//
// 0 -> N
//
case CONTENTSPECNODE_ZERO_TO_N: {
//System.out.println("occurs = 0 -> "+n);
// create optional content model node
contentSpecNodeIndex = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE,
contentSpecNodeIndex, -1, false);
int value = contentSpecNodeIndex;
int otherValue = -1;
// add optional number
for (int i = 1; i < n; i++) {
if (otherValue != -1) {
value = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_SEQ,
value, otherValue, false);
}
otherValue = contentSpecNodeIndex;
}
// set expanded content model index
contentSpecNodeIndex = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_SEQ,
value, otherValue, false);
break;
}
} // switch
//System.out.println("content = "+getContentSpecNodeAsString(contentSpecNodeIndex));
return contentSpecNodeIndex;
} // expandContentModel(int,int,int,int):int
private boolean isSimpleOccurrenceCount(int occurs) {
return occurs == -1 ||
occurs == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE ||
occurs == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE ||
occurs == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE;
}
private int getOccurrenceCount(Element element) {
String minOccur = element.getAttribute(ATT_MINOCCURS);
String maxOccur = element.getAttribute(ATT_MAXOCCURS);
if (minOccur.equals("0")) {
if (maxOccur.equals("1") || maxOccur.length() == 0) {
return XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE;
}
else if (maxOccur.equals("*")) {
return XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE;
}
else {
return CONTENTSPECNODE_ZERO_TO_N;
}
}
else if (minOccur.equals("1") || minOccur.length() == 0) {
if (maxOccur.equals("*")) {
return XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE;
}
else if (!maxOccur.equals("1") && maxOccur.length() > 0) {
return CONTENTSPECNODE_M_TO_N;
}
}
else {
if (maxOccur.equals("*")) {
return CONTENTSPECNODE_M_OR_MORE;
}
else {
return CONTENTSPECNODE_M_TO_N;
}
}
// exactly one
return -1;
}
private void reportSchemaError(int major, Object args[]) throws Exception {
// try {
fErrorReporter.reportError(fErrorReporter.getLocator(),
SchemaMessageProvider.SCHEMA_DOMAIN,
major,
SchemaMessageProvider.MSG_NONE,
args,
XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
// } catch (Exception e) {
// e.printStackTrace();
// }
}
//
// Classes
//
static class Resolver implements EntityResolver {
private static final String SYSTEM[] = {
"http://www.w3.org/TR/2000/WD-xmlschema-1-20000225/structures.dtd",
"http://www.w3.org/TR/2000/WD-xmlschema-2-20000225/datatypes.dtd",
"http://www.w3.org/TR/2000/WD-xmlschema-1-20000225/versionInfo.ent",
};
private static final String PATH[] = {
"structures.dtd",
"datatypes.dtd",
"versionInfo.ent",
};
public InputSource resolveEntity(String publicId, String systemId)
throws IOException {
// looking for the schema DTDs?
for (int i = 0; i < SYSTEM.length; i++) {
if (systemId.equals(SYSTEM[i])) {
InputSource source = new InputSource(getClass().getResourceAsStream(PATH[i]));
source.setPublicId(publicId);
source.setSystemId(systemId);
return source;
}
}
// use default resolution
return null;
} // resolveEntity(String,String):InputSource
} // class Resolver
static class ErrorHandler implements org.xml.sax.ErrorHandler {
/** Warning. */
public void warning(SAXParseException ex) {
System.err.println("[Warning] "+
getLocationString(ex)+": "+
ex.getMessage());
}
/** Error. */
public void error(SAXParseException ex) {
System.err.println("[Error] "+
getLocationString(ex)+": "+
ex.getMessage());
}
/** Fatal error. */
public void fatalError(SAXParseException ex) throws SAXException {
System.err.println("[Fatal Error] "+
getLocationString(ex)+": "+
ex.getMessage());
throw ex;
}
//
// Private methods
//
/** Returns a string of the location. */
private String getLocationString(SAXParseException ex) {
StringBuffer str = new StringBuffer();
String systemId_ = ex.getSystemId();
if (systemId_ != null) {
int index = systemId_.lastIndexOf('/');
if (index != -1)
systemId_ = systemId_.substring(index + 1);
str.append(systemId_);
}
str.append(':');
str.append(ex.getLineNumber());
str.append(':');
str.append(ex.getColumnNumber());
return str.toString();
} // getLocationString(SAXParseException):String
}
class DatatypeValidatorRegistry {
Hashtable fRegistry = new Hashtable();
String integerSubtypeTable[][] = {
{ "non-negative-integer", DatatypeValidator.MININCLUSIVE , "0"},
{ "positive-integer", DatatypeValidator.MININCLUSIVE, "1"},
{ "non-positive-integer", DatatypeValidator.MAXINCLUSIVE, "0"},
{ "negative-integer", DatatypeValidator.MAXINCLUSIVE, "-1"}
};
void initializeRegistry() {
Hashtable facets = null;
fRegistry.put("boolean", new BooleanValidator());
DatatypeValidator integerValidator = new IntegerValidator();
fRegistry.put("integer", integerValidator);
fRegistry.put("string", new StringValidator());
fRegistry.put("decimal", new DecimalValidator());
fRegistry.put("float", new FloatValidator());
fRegistry.put("double", new DoubleValidator());
fRegistry.put("timeDuration", new TimeDurationValidator());
fRegistry.put("timeInstant", new TimeInstantValidator());
fRegistry.put("binary", new BinaryValidator());
fRegistry.put("uri", new URIValidator());
//REVISIT - enable the below
//fRegistry.put("date", new DateValidator());
//fRegistry.put("timePeriod", new TimePeriodValidator());
//fRegistry.put("time", new TimeValidator());
DatatypeValidator v = null;
for (int i = 0; i < integerSubtypeTable.length; i++) {
v = new IntegerValidator();
facets = new Hashtable();
facets.put(integerSubtypeTable[i][1],integerSubtypeTable[i][2]);
v.setBasetype(integerValidator);
try {
v.setFacets(facets);
} catch (IllegalFacetException ife) {
System.out.println("Internal error initializing registry - Illegal facet: "+integerSubtypeTable[i][0]);
} catch (IllegalFacetValueException ifve) {
System.out.println("Internal error initializing registry - Illegal facet value: "+integerSubtypeTable[i][0]);
} catch (UnknownFacetException ufe) {
System.out.println("Internal error initializing registry - Unknown facet: "+integerSubtypeTable[i][0]);
}
fRegistry.put(integerSubtypeTable[i][0], v);
}
}
DatatypeValidator getValidatorFor(String type) {
return (DatatypeValidator) fRegistry.get(type);
}
void addValidator(String name, DatatypeValidator v) {
fRegistry.put(name,v);
}
}
//
//
//
final class AttValidatorDATATYPE implements XMLValidator.AttributeValidator {
public int normalize(int elementType, int attrName, int attValueHandle, int attType, int enumHandle) throws Exception {
//
// Normalize attribute based upon attribute type...
//
try { // REVISIT - integrate w/ error handling
String type = fStringPool.toString(enumHandle);
DatatypeValidator v = fDatatypeRegistry.getValidatorFor(type);
if (v != null)
v.validate(fStringPool.toString(attValueHandle));
else
reportSchemaError(SchemaMessageProvider.NoValidatorFor,
new Object [] { type });
} catch (InvalidDatatypeValueException idve) {
reportSchemaError(SchemaMessageProvider.IncorrectDatatype,
new Object [] { idve.getMessage() });
} catch (Exception e) {
e.printStackTrace();
System.out.println("Internal error in attribute datatype validation");
}
return attValueHandle;
}
}
//
//
//
public XMLValidator.AttributeValidator createDatatypeAttributeValidator() {
return new AttValidatorDATATYPE();
}
public XMLContentModel createDatatypeContentModel(int elementIndex) {
return new DatatypeContentModel(fDatatypeRegistry, fValidator, fStringPool, elementIndex);
}
}
1.1 xml-xerces/java/src/org/apache/xerces/validators/schema/SchemaParser.java
Index: SchemaParser.java
===================================================================
/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 1999 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/>.
*/
// TODO - error messages
package org.apache.xerces.validators.schema;
import java.util.Stack;
import java.util.StringTokenizer;
import org.apache.xerces.framework.XMLAttrList;
import org.apache.xerces.framework.XMLContentSpec;
import org.apache.xerces.framework.XMLDocumentHandler;
import org.apache.xerces.framework.XMLParser;
import org.apache.xerces.readers.XMLEntityHandler;
import org.apache.xerces.framework.XMLErrorReporter;
import org.apache.xerces.utils.StringPool;
public class SchemaParser
extends XMLParser
implements XMLDocumentHandler, XMLDocumentHandler.DTDHandler {
private Schema fSchema;
private Schema.Document fSchemaDocument;
private Stack fComponentStack = new Stack ();
private boolean fIgnore = false;
private boolean fInSimpleType = false;
//
// Constructors
//
/** Default constructor. */
public SchemaParser (Schema schema) {
initHandlers(true, this, this);
fSchema = schema;
}
//
// Public methods
//
//
// XMLParser methods
//
/** Start document. */
public void startDocument() throws Exception {
System.out.println ("SchemaParser.startDocument\n");
}
/** End document. */
public void endDocument() throws Exception {
System.out.println ("SchemaParser.endDocument\n");
}
/** XML declaration. */
public void xmlDecl(int versionIndex, int encodingIndex, int standaloneIndex) throws Exception {
System.out.println ("SchemaParser.xmlDecl\n");
}
/**
* Report the start of the scope of a namespace declaration.
*/
public void startNamespaceDeclScope(int prefix, int uri) throws Exception {
System.out.println ("SchemaParser.startNamespaceDeclScope\n");
}
/**
* Report the end of the scope of a namespace declaration.
*/
public void endNamespaceDeclScope(int prefix) throws Exception {
System.out.println ("SchemaParser.endNamespaceDeclScope\n");
}
//
// The methods we care about!!!
//
/*
* DESCRIPTION:
*
* This handler is called for the start of each element. it assumes/requires that
* the root of a Schema document must be a <schema> element. The spec states that
* this need not be the case, but I can see no practical way to not have one in a
* Schema document. So, if fSchemaDocument is null (which indicates that we have
* not yet encountered the <schema> element, we won't accept any other element.
*
* Once the <schema> element has been encounteres, startSchema is called, which
* processes the element and created fSchemaDocument. After this, other valid
* Schema elements are accepted. Annotations are always possible. Otherwise, if
* processing children of a simpleType, all other child elements are processed as
* facets. Finally, if not an annotation and if not processing children of a
* simpleType, all other element types are processed.
*
* 3-27-00 watso First implementation completed.
*
*/
public void startElement(int elementType, XMLAttrList attrList, int attrListIndex) throws Exception
{
if ( fSchemaDocument == null ) {
if ( elementType == fStringPool.addSymbol(Schema.ELT_SCHEMA) ) {
startSchema (attrList, attrListIndex);
} else {
reportGenericSchemaError ( "Invalid root element" );
}
} else {
if ( elementType == fStringPool.addSymbol(Schema.ELT_ANNOTATION) ) {
startAnnotation ();
} else if ( elementType == fStringPool.addSymbol(Schema.ELT_DOCUMENTATION) ) {
startDocumentation ();
} else if ( elementType == fStringPool.addSymbol(Schema.ELT_APPINFO) ) {
startAppInfo ();
} else if ( fInSimpleType ) {
startFacet (elementType, attrList, attrListIndex);
} else {
if ( elementType == fStringPool.addSymbol(Schema.ELT_SIMPLETYPE) ) {
startSimpleTypeDef (attrList, attrListIndex);
} else if ( elementType == fStringPool.addSymbol(Schema.ELT_COMPLEXTYPE) ) {
startComplexTypeDef (attrList, attrListIndex);
} else if ( elementType == fStringPool.addSymbol(Schema.ELT_GROUP) ) {
startGroupDef (attrList, attrListIndex);
} else if ( elementType == fStringPool.addSymbol(Schema.ELT_CHOICE) ) {
startChoice (attrList, attrListIndex);
} else if ( elementType == fStringPool.addSymbol(Schema.ELT_SEQUENCE) ) {
startSeq (attrList, attrListIndex);
} else if ( elementType == fStringPool.addSymbol(Schema.ELT_ALL) ) {
startAll (attrList, attrListIndex);
} else if ( elementType == fStringPool.addSymbol(Schema.ELT_ATTRGROUP) ) {
startAttrGroupDef (attrList, attrListIndex);
} else if ( elementType == fStringPool.addSymbol(Schema.ELT_ELEMENT) ) {
startElementDecl (attrList, attrListIndex);
} else if ( elementType == fStringPool.addSymbol(Schema.ELT_ATTRIBUTE) ) {
startAttributeDecl (attrList, attrListIndex);
} else if ( elementType == fStringPool.addSymbol(Schema.ELT_NOTATION) ) {
startNotationDecl (attrList, attrListIndex);
} else {
reportGenericSchemaError ( "Invalid element(" + fStringPool.toString (elementType) + ")" );
}
}
}
}
/*
* DESCRIPTION:
*
* startElement should ensure that endElement will only be called once
* fSchemaDocument has been created. Annotations are always possible.
* Otherwise, if processing the children of a simpleType, look for either
* the end of the simpleType or process the element as a facet.
*
* Otherwise, process the acceptable elements.
*
* Note: endSchema must set fSchemaDocument to null again to avoid processing
* elements after the </schema> element.
*
* 3-27-00 watso First implementation completed.
*
*/
public void endElement(int elementType) throws Exception
{
if ( elementType == fStringPool.addSymbol(Schema.ELT_ANNOTATION) ) {
endAnnotation ();
} else if ( elementType == fStringPool.addSymbol(Schema.ELT_DOCUMENTATION) ) {
endDocumentation ();
} else if ( elementType == fStringPool.addSymbol(Schema.ELT_APPINFO) ) {
endAppInfo ();
} else if ( fInSimpleType ) {
if ( elementType == fStringPool.addSymbol(Schema.ELT_SIMPLETYPE) ) {
endSimpleTypeDef ();
} else {
endFacet ();
}
} else {
if ( elementType == fStringPool.addSymbol(Schema.ELT_COMPLEXTYPE) ) {
endComplexTypeDef ();
} else if ( elementType == fStringPool.addSymbol(Schema.ELT_GROUP) ) {
endGroupDef ();
} else if ( elementType == fStringPool.addSymbol(Schema.ELT_CHOICE) ) {
endChoice ();
} else if ( elementType == fStringPool.addSymbol(Schema.ELT_SEQUENCE) ) {
endSeq ();
} else if ( elementType == fStringPool.addSymbol(Schema.ELT_ALL) ) {
endAll ();
} else if ( elementType == fStringPool.addSymbol(Schema.ELT_ATTRGROUP) ) {
endAttrGroupDef ();
} else if ( elementType == fStringPool.addSymbol(Schema.ELT_ELEMENT) ) {
endElementDecl ();
} else if ( elementType == fStringPool.addSymbol(Schema.ELT_ATTRIBUTE) ) {
endAttributeDecl ();
} else if ( elementType == fStringPool.addSymbol(Schema.ELT_NOTATION) ) {
endNotationDecl ();
} else if ( elementType == fStringPool.addSymbol(Schema.ELT_SCHEMA) ) {
endSchema ();
} else {
reportGenericSchemaError ( "Invalid element (" + fStringPool.toString (elementType) + ")" );
}
}
}
/** Start entity reference. */
public void startEntityReference(int entityName, int entityType, int entityContext) throws Exception {
//System.out.println ("SchemaParser.startEntityReference\n");
}
/** End entity reference. */
public void endEntityReference(int entityName, int entityType, int entityContext) throws Exception {
//System.out.println ("SchemaParser.endEntityReference\n");
}
/** Start CDATA section. */
public void startCDATA() throws Exception {
System.out.println ("SchemaParser.startCDATA\n");
}
/** End CDATA section. */
public void endCDATA() throws Exception {
System.out.println ("SchemaParser.endCDATA\n");
}
/** Not called. */
public void characters(int dataIndex) throws Exception {
throw new RuntimeException("PAR017 cannot happen 5\n5");
}
/** Not called. */
public void ignorableWhitespace(int dataIndex) throws Exception {
throw new RuntimeException("PAR017 cannot happen 6\n6");
}
/** Processing instruction. */
/*
public void processingInstruction(int piTarget, int piData) throws Exception {
System.out.println ("SchemaParser.processingInstruction\n");
}
*/
/** Comment. */
/*
public void comment(int dataIndex) throws Exception {
}
*/
// ************************
// **** CHARACTER DATA ****
// ************************
/*
* characters
*
* Process the character data in an element.
*
*/
private static final int NONE = 0;
private static final int DOCUMENTATION = 1;
private static final int APPINFO = 2;
private static int fCharacterMode = 0;
/*
* DESCRIPTION:
*
* Character data is only valid in the 'documentation' and 'appinfo' children
* of annotations.
*
* 3-27-00 watso First implementation completed.
*
*/
public void characters (char ch[], int start, int length) throws Exception
{
String string = new String (ch, start, length);
switch (fCharacterMode) {
case DOCUMENTATION:
{
Schema.Annotation annotation = (Schema.Annotation)fComponentStack.peek ();
annotation.addDocumentation (string);
}
break;
case APPINFO:
{
Schema.Annotation annotation = (Schema.Annotation)fComponentStack.peek ();
annotation.addAppInfo (string);
}
break;
default:
reportGenericSchemaError ("Invalid CDATA");
}
}
/** Ignorable whitespace. */
public void ignorableWhitespace(char ch[], int start, int length) throws Exception {
}
//
// DTDHandler Methods (NOP)
//
public void startDTD (int rootElementType, int publicId, int systemId) throws Exception {}
public void internalSubset(int internalSubset) throws Exception {}
public void textDecl(int version, int encoding) throws Exception {}
public void endDTD() throws Exception {}
public void elementDecl(int elementType, XMLContentSpec contentSpec) throws Exception {}
public void attlistDecl(int elementType,int attrName, int attType, String enumString, int attDefaultType, int attDefaultValue) throws Exception {}
public void internalPEDecl(int entityName, int entityValue) throws Exception {}
public void externalPEDecl(int entityName, int publicId, int systemId) throws Exception {}
public void internalEntityDecl(int entityName, int entityValue) throws Exception {}
public void externalEntityDecl(int entityName, int publicId, int systemId) throws Exception {}
public void unparsedEntityDecl(int entityName, int publicId, int systemId, int notationName) throws Exception {}
public void notationDecl(int notationName, int publicId, int systemId) throws Exception {}
public void processingInstruction(int targetIndex, int dataIndex) throws Exception {}
public void comment(int dataIndex) throws Exception {}
//
// SchemaParser Methods - the meat!
//
// ***************************
// **** STRING CONVERTERS ****
// ***************************
/*
* DESCRIPTION
*
* These methods each convert string attribute values to the data representations
* used by the Schema objects.
*
* TODO: Tweak the values for the 'set' data, e.g. final, derivationSet, blockSet.
* I'm not sure if these are correct ... need to review latest spec schema.
*
* 3-27-00 watso First implementation completed.
*
*/
private boolean parseBoolean (String booleanString) throws Exception
{
if ( booleanString.equals("true") ) {
return true;
} else if ( booleanString.equals("false") ) {
return false;
} else {
reportGenericSchemaError ("Invalid boolean value");
return false;
}
}
private int parseSimpleDerivedBy (String derivedByString) throws Exception
{
if ( derivedByString.equals (Schema.VAL_LIST) ) {
return Schema.LIST;
} else if ( derivedByString.equals (Schema.VAL_RESTRICTION) ) {
return Schema.RESTRICTION;
} else if ( derivedByString.equals (Schema.VAL_REPRODUCTION) ) {
return Schema.REPRODUCTION;
} else {
reportGenericSchemaError ("Invalid value for 'derivedBy'");
return -1;
}
}
private int parseComplexDerivedBy (String derivedByString) throws Exception
{
if ( derivedByString.equals (Schema.VAL_EXTENSION) ) {
return Schema.EXTENSION;
} else if ( derivedByString.equals (Schema.VAL_RESTRICTION) ) {
return Schema.RESTRICTION;
} else if ( derivedByString.equals (Schema.VAL_REPRODUCTION) ) {
return Schema.REPRODUCTION;
} else {
reportGenericSchemaError ( "Invalid value for 'derivedBy'" );
return -1;
}
}
private int parseSimpleFinal (String finalString) throws Exception
{
if ( finalString.equals (Schema.VAL_POUNDALL) ) {
return Schema.ENUMERATION+Schema.RESTRICTION+Schema.LIST+Schema.REPRODUCTION;
} else {
int enumerate = 0;
int restrict = 0;
int list = 0;
int reproduce = 0;
StringTokenizer t = new StringTokenizer (finalString, " ");
while (t.hasMoreTokens()) {
String token = t.nextToken ();
if ( token.equals (Schema.VAL_ENUMERATION) ) {
if ( enumerate == 0 ) {
enumerate = Schema.ENUMERATION;
} else {
reportGenericSchemaError ("enumeration in set twice");
}
} else if ( token.equals (Schema.VAL_RESTRICTION) ) {
if ( restrict == 0 ) {
restrict = Schema.RESTRICTION;
} else {
reportGenericSchemaError ("restriction in set twice");
}
} else if ( token.equals (Schema.VAL_LIST) ) {
if ( list == 0 ) {
list = Schema.LIST;
} else {
reportGenericSchemaError ("list in set twice");
}
} else if ( token.equals (Schema.VAL_REPRODUCTION) ) {
if ( reproduce == 0 ) {
reproduce = Schema.REPRODUCTION;
} else {
reportGenericSchemaError ("reproduction in set twice");
}
} else {
reportGenericSchemaError ( "Invalid value (" +
finalString +
")" );
}
}
return enumerate+restrict+list+reproduce;
}
}
private int parseComplexContent (String contentString) throws Exception
{
if ( contentString.equals (Schema.VAL_EMPTY) ) {
return Schema.EMPTY;
} else if ( contentString.equals (Schema.VAL_ELEMENTONLY) ) {
return Schema.ELEMENT_ONLY;
} else if ( contentString.equals (Schema.VAL_TEXTONLY) ) {
return Schema.TEXT_ONLY;
} else if ( contentString.equals (Schema.VAL_MIXED) ) {
return Schema.MIXED;
} else {
reportGenericSchemaError ( "Invalid value for content" );
return -1;
}
}
private int parseDerivationSet (String finalString) throws Exception
{
if ( finalString.equals ("#all") ) {
return Schema.EXTENSION+Schema.RESTRICTION+Schema.REPRODUCTION;
} else {
int extend = 0;
int restrict = 0;
int reproduce = 0;
StringTokenizer t = new StringTokenizer (finalString, " ");
while (t.hasMoreTokens()) {
String token = t.nextToken ();
if ( token.equals (Schema.VAL_EXTENSION) ) {
if ( extend == 0 ) {
extend = Schema.EXTENSION;
} else {
reportGenericSchemaError ( "extension already in set" );
}
} else if ( token.equals (Schema.VAL_RESTRICTION) ) {
if ( restrict == 0 ) {
restrict = Schema.RESTRICTION;
} else {
reportGenericSchemaError ( "restriction already in set" );
}
} else if ( token.equals (Schema.VAL_REPRODUCTION) ) {
if ( reproduce == 0 ) {
reproduce = Schema.REPRODUCTION;
} else {
reportGenericSchemaError ( "reproduction already in set" );
}
} else {
reportGenericSchemaError ( "Invalid final value (" + finalString + ")" );
}
}
return extend+restrict+reproduce;
}
}
private int parseBlockSet (String finalString) throws Exception
{
if ( finalString.equals ("#all") ) {
return Schema.EQUIVCLASS+Schema.EXTENSION+Schema.LIST+Schema.RESTRICTION+Schema.REPRODUCTION;
} else {
int extend = 0;
int restrict = 0;
int reproduce = 0;
StringTokenizer t = new StringTokenizer (finalString, " ");
while (t.hasMoreTokens()) {
String token = t.nextToken ();
if ( token.equals (Schema.VAL_EQUIVCLASS) ) {
if ( extend == 0 ) {
extend = Schema.EQUIVCLASS;
} else {
reportGenericSchemaError ( "'equivClass' already in set" );
}
} else if ( token.equals (Schema.VAL_EXTENSION) ) {
if ( extend == 0 ) {
extend = Schema.EXTENSION;
} else {
reportGenericSchemaError ( "extension already in set" );
}
} else if ( token.equals (Schema.VAL_LIST) ) {
if ( extend == 0 ) {
extend = Schema.LIST;
} else {
reportGenericSchemaError ( "'list' already in set" );
}
} else if ( token.equals (Schema.VAL_RESTRICTION) ) {
if ( restrict == 0 ) {
restrict = Schema.RESTRICTION;
} else {
reportGenericSchemaError ( "restriction already in set" );
}
} else if ( token.equals (Schema.VAL_REPRODUCTION) ) {
if ( reproduce == 0 ) {
reproduce = Schema.REPRODUCTION;
} else {
reportGenericSchemaError ( "reproduction already in set" );
}
} else {
reportGenericSchemaError ( "Invalid final value (" + finalString + ")" );
}
}
return extend+restrict+reproduce;
}
}
// *************************
// **** SCHEMA DOCUMENT ****
// *************************
private void startSchema (XMLAttrList attrList, int attrListIndex) throws Exception
{
fSchemaDocument = fSchema.createDocument ();
}
private void endSchema () throws Exception
{
//
// TODO: add namespace
//
// Just for testing.
fSchema.registerDocument (null, fSchemaDocument);
fSchemaDocument = null;
System.out.print ("\n\n***************** SCHEMA *****************\n\n");
System.out.print (fSchema.toString ());
System.out.print ("\n\n***************** SCHEMA *****************\n\n");
}
// *********************
// **** ANNOTATIONS ****
// *********************
/*
* DESCRIPTION:
*
* Each Schema component may have one annotation and it must be the first
* child element of that component. The Schema document may have multiple
* annotations and they may appear anywhere. Each annotation may have one
* or more <documentation> and/or <appInfo> children.
*
* 3-27-00 watso First implementation completed.
*
*/
private void startAnnotation () throws Exception
{
if ( fSchemaDocument != null ) {
Schema.Annotation annotation = fSchemaDocument.createAnnotation ();
fComponentStack.push (annotation);
} else {
reportGenericSchemaError ("Invalid annotation placement");
}
}
private void endAnnotation () throws Exception
{
if ( fSchemaDocument != null ) {
Schema.Annotation annotation = (Schema.Annotation)fComponentStack.pop ();
if ( fComponentStack.size() == 0 ) {
fSchemaDocument.addAnnotation (annotation);
} else {
Schema.AnnotatedComponent annotated = (Schema.AnnotatedComponent)fComponentStack.peek ();
annotated.setAnnotation (annotation);
}
}
}
private void startDocumentation ()
{
fCharacterMode = DOCUMENTATION;
}
private void endDocumentation ()
{
fCharacterMode = NONE;
}
private void startAppInfo ()
{
fCharacterMode = APPINFO;
}
private void endAppInfo ()
{
fCharacterMode = NONE;
}
// **********************
// **** SIMPLE TYPES ****
// **********************
/*
* DESCRIPTION:
*
* Create a new simple type def and push on the component stack.
*
* 3-27-00 watso First implementation completed.
*
*/
//
// <simpleType [name={name}] [base={base}] [derivedBy={derivedBy}] [abstract={abstract}] [final={final}]>
//
private void startSimpleTypeDef (XMLAttrList attrList, int attrListIndex) throws Exception
{
Schema.SimpleTypeDef type = fSchemaDocument.createSimpleTypeDef ();
for (int i=attrList.getFirstAttr(attrListIndex); i != -1; i = attrList.getNextAttr(i) ) {
String value = fStringPool.toString (attrList.getAttValue(i));
if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_NAME) ) {
if ( fComponentStack.empty() ) {
type.setName (value);
} else {
reportGenericSchemaError ( "Non-global 'simpleType' cannot have name" );
}
} else if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_BASE) ) {
type.setBase (value, null);
} else if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_DERIVEDBY) ) {
type.setDerivedBy (parseSimpleDerivedBy(value));
} else if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_ABSTRACT) ) {
type.setAbstract (parseBoolean(value));
} else if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_FINAL) ) {
type.setFinal (parseSimpleFinal(value));
} else {
reportGenericSchemaError ("Invalid attribute for 'simpleType'");
}
}
fComponentStack.push (type);
fInSimpleType = true;
}
//
// </simpleType>
//
/*
* DESCRIPTION:
*
* Pop the finished simple type off of the component stack. If the resulting component
* stack is empty then register the simple type as a global type def with the document.
* Otherwise, the next component on the component stack should be something that can have
* a simple type (otherwise an error will result).
*
* 3-27-00 watso First implementation completed.
*
*/
private void endSimpleTypeDef () throws Exception
{
fInSimpleType = false;
Schema.SimpleTypeDef type = (Schema.SimpleTypeDef)fComponentStack.pop ();
if ( fComponentStack.size() == 0 ) {
fSchemaDocument.registerType (type.getName(), type);
} else {
try {
Schema.HasSimpleType component = (Schema.HasSimpleType)fComponentStack.peek ();
component.setSimpleType (type);
} catch (ClassCastException e) {
reportGenericSchemaError ("Invalid use of 'simpleType'");
}
}
}
//
// <{facet} value={value}>
//
// TODO - what about xmlns attributes?
/*
* DESCRIPTION:
*
* A generic facet adding mechanism to support extended primitive types. Basically,
* whenever we are in the body of a simple type def, the fInSimpleType flag is set.
* When this is the case, we attempt to process all non-annotations in this method.
* We accept any element name (the facet name) and require there to be a single
* 'value' attribute. We pass the pair to the enclosing simple type def to process.
*
* 3-27-00 watso First implementation completed.
*
*/
private void startFacet (int elementType, XMLAttrList attrList, int attrListIndex) throws Exception
{
// can only have one attribute, and must be "value"
for (int i=attrList.getFirstAttr(attrListIndex); i != -1; i = attrList.getNextAttr(i) ) {
if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_VALUE) ) {
try {
String name = fStringPool.toString (elementType);
String value = fStringPool.toString (attrList.getAttValue(i));
Schema.Facet facet = fSchemaDocument.createFacet (name, value);
fComponentStack.push (facet);
} catch (ClassCastException e) {
reportGenericSchemaError ("Unexpected error");
}
} else {
reportGenericSchemaError ("Invalid facet");
}
}
}
//
// </{facet}>
//
private void endFacet ()
{
Schema.Facet facet = (Schema.Facet)fComponentStack.pop ();
Schema.SimpleTypeDef type = (Schema.SimpleTypeDef)fComponentStack.peek ();
type.addFacet (facet);
}
// ***********************
// **** COMPLEX TYPES ****
// ***********************
//
// <complexType [name={name}] [content={content}] [base={base}] [derivedBy={derivedBy}]
// [abstract={abstract}] [final={final}] [block={block}]>
//
private void startComplexTypeDef (XMLAttrList attrList, int attrListIndex) throws Exception
{
Schema.ComplexTypeDef type = fSchemaDocument.createComplexTypeDef ();
for (int i=attrList.getFirstAttr(attrListIndex); i != -1; i = attrList.getNextAttr(i) ) {
String value = fStringPool.toString (attrList.getAttValue(i));
if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_NAME) ) {
if ( fComponentStack.empty() ) {
type.setName (value);
} else {
reportGenericSchemaError ("Non-global complexType cannot have name");
}
} else if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_CONTENT) ) {
type.setContent (parseComplexContent(value));
} else if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_BASE) ) {
type.setBase (value, null);
} else if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_DERIVEDBY) ) {
type.setDerivedBy (parseComplexDerivedBy(value));
} else if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_ABSTRACT) ) {
type.setAbstract (parseBoolean(value));
} else if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_FINAL) ) {
type.setFinal (parseDerivationSet(value));
} else if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_BLOCK) ) {
type.setBlock (parseDerivationSet(value));
} else {
reportGenericSchemaError ( "Invalid attribute (" +
fStringPool.toString (attrList.getAttrName(i)) +
")" );
}
}
fComponentStack.push (type);
}
//
// </complexType>
//
/*
* Pop the finished complex type off of the component stack. If the resulting component
* stack is empty then register the complex type as a global type def with the document.
* Otherwise, the next component on the component stack should be something that can have
* a complex type (otherwise an error will result).
*
* 3-27-00 watso First implementation completed.
*
*/
private void endComplexTypeDef () throws Exception
{
Schema.ComplexTypeDef type = (Schema.ComplexTypeDef)fComponentStack.pop ();
if ( fComponentStack.size() == 0 ) {
fSchemaDocument.registerType (type.getName(), type);
} else {
try {
Schema.HasType component = (Schema.HasType)fComponentStack.peek ();
component.setType (type);
} catch (ClassCastException e) {
reportGenericSchemaError ("Invalid use of 'complexType'");
}
}
}
// ****************
// **** GROUPS ****
// ****************
//
// <group [name={name}] [ref={ref}] [minOccurs={minOccurs}] [maxOccurs={maxOccurs}]>
//
// TODO: represent minOccurs and maxOccurs as BigDecimal
// TODO: use integer datatype class to parse integers
private void startGroupDef (XMLAttrList attrList, int attrListIndex) throws Exception
{
String name = null;
String ref = null;
String minOccurs = null;
String maxOccurs = null;
//
// Collect attributes
//
for (int i=attrList.getFirstAttr(attrListIndex); i != -1; i = attrList.getNextAttr(i) ) {
String value = fStringPool.toString (attrList.getAttValue(i));
if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_NAME) ) {
name = value;
} else if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_REF) ) {
ref = value;
} else if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_MINOCCURS) ) {
minOccurs = value;
} else if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_MAXOCCURS) ) {
maxOccurs = value;
} else {
reportGenericSchemaError ( "Invalid attribute (" +
fStringPool.toString (attrList.getAttrName(i)) +
")" );
}
}
//
// Global group def case
//
if ( fComponentStack.size() == 0 ) {
if ( name == null ) {
//reportSchemaError ( SchemaMessageProvider.GlobalGroupMustHaveName, null );
}
if ( ref != null ) {
//reportSchemaError ( SchemaMessageProvider.GlobalGroupCannotHaveRef, null );
}
if ( minOccurs != null ) {
//reportSchemaError ( SchemaMessageProvider.InvalidMinOccurs, null );
}
if ( maxOccurs != null ) {
//reportSchemaError ( SchemaMessageProvider.InvalidMaxOccurs, null );
}
Schema.GroupDef group = fSchemaDocument.createGroupDef ();
group.setName (name);
fComponentStack.push (group);
}
//
// Embedded group particle case
//
else {
Schema.GroupDef group = null;
Schema.GroupParticle particle = fSchemaDocument.createGroupParticle ();
if ( name != null ) {
//reportSchemaError ( SchemaMessageProvider.OnlyGlobalGroupCanHaveName, null );
}
if ( ref == null ) {
group = fSchemaDocument.createGroupDef ();
}
//
// Set particle minOccurs and maxOccurs
//
if ( minOccurs == null ) {
particle.setMinOccurs (1);
} else {
particle.setMinOccurs (Integer.parseInt(minOccurs));
}
if ( maxOccurs == null ) {
particle.setMaxOccurs (1);
} else if ( maxOccurs.equals (Schema.VAL_INFINITY) ) {
particle.setMaxOccurs (Schema.INFINITY);
} else {
particle.setMaxOccurs (Integer.parseInt(maxOccurs));
}
fComponentStack.push (particle);
fComponentStack.push (group);
}
}
//
// </group>
//
private void endGroupDef () throws Exception
{
/*
Schema.GroupDef group = (Schema.GroupDef)fComponentStack.pop ();
if ( group.isNamed() ) {
fSchemaDocument.register (group);
} else {
Schema.ComplexTypeDef type = (Schema.ComplexTypeDef)fComponentStack.peek ();
type.appendParticle (group);
}
*/
}
//
// <choice>
//
private void startChoice (XMLAttrList attrList, int attrListIndex)
{
Schema.GroupDef groupDef = (Schema.GroupDef)fComponentStack.peek();
groupDef.setOrder (Schema.CHOICE);
}
//
// </choice>
//
private void endChoice () { /* nothing to do */ }
//
// <seq>
//
private void startSeq (XMLAttrList attrList, int attrListIndex)
{
Schema.GroupDef groupDef = (Schema.GroupDef)fComponentStack.peek();
groupDef.setOrder (Schema.SEQUENCE);
}
//
// </seq>
//
private void endSeq () { /* nothing to do */ }
//
// <all>
//
private void startAll (XMLAttrList attrList, int attrListIndex)
{
Schema.GroupDef groupDef = (Schema.GroupDef)fComponentStack.peek();
groupDef.setOrder (Schema.ALL);
}
//
// </all>
//
private void endAll () { /* nothing to do */ }
// **************************
// **** ATTRIBUTE GROUPS ****
// **************************
//
// <attributeGroup [name=<name> | ref=<ref>]>
//
private void startAttrGroupDef (XMLAttrList attrList, int attrListIndex) throws Exception
{
String name = null;
String ref = null;
for (int i=attrList.getFirstAttr(attrListIndex); i != -1; i = attrList.getNextAttr(i) ) {
String value = fStringPool.toString (attrList.getAttValue(i));
if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_NAME) ) {
name = value;
} else if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_REF) ) {
ref = value;
} else {
reportGenericSchemaError ( "InvalidAttribute" );
}
}
if ( fComponentStack.size() == 0 ) {
if ( name != null ) {
if ( ref == null ) {
Schema.AttributeGroupDef attrGroup = fSchemaDocument.createAttributeGroupDef ();
fComponentStack.push (attrGroup);
} else {
reportGenericSchemaError ("Global def cannot have ref");
}
} else {
reportGenericSchemaError ("Global def must have name");
}
} else {
if ( name == null ) {
Schema.AttributeGroupParticle particle = fSchemaDocument.createAttributeGroupParticle ();
if ( ref != null ) {
// TODO: namespace
particle.setAttributeGroupRef (ref, null);
}
} else {
reportGenericSchemaError ("Non-global def cannot have name");
}
}
}
//
// </attributeGroup>
//
private void endAttrGroupDef () throws Exception
{
if ( fComponentStack.size() == 1 ) {
Schema.AttributeGroupDef attrGroupDef = (Schema.AttributeGroupDef)fComponentStack.pop ();
fSchemaDocument.registerAttributeGroupDef (attrGroupDef.getName(), attrGroupDef);
} else {
Schema.AttributeGroupParticle particle = (Schema.AttributeGroupParticle)fComponentStack.pop ();
Schema.AParticleHolder holder = (Schema.AParticleHolder)fComponentStack.peek ();
holder.add (particle);
}
}
// ******************
// **** ELEMENTS ****
// ******************
private void startElementDecl (XMLAttrList attrList, int attrListIndex) throws Exception
{
String name = null;
String ref = null;
String type = null;
String equivClass = null;
String minOccurs = null;
String maxOccurs = null;
String fixedValue = null;
String defaultValue = null;
String isNullable = null;
String isAbstract = null;
String finalSet = null;
String blockSet = null;
for (int i=attrList.getFirstAttr(attrListIndex); i != -1; i = attrList.getNextAttr(i) ) {
String attValue = fStringPool.toString (attrList.getAttValue(i));
if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_NAME) ) {
name = attValue;
} else if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_REF) ) {
ref = attValue;
} else if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_TYPE) ) {
type = attValue;
} else if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_EQUIVCLASS) ) {
equivClass = attValue;
} else if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_MINOCCURS) ) {
minOccurs = attValue;
} else if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_MAXOCCURS) ) {
maxOccurs = attValue;
} else if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_DEFAULT) ) {
defaultValue = attValue;
} else if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_FIXED) ) {
fixedValue = attValue;
} else if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_NULLABLE) ) {
isNullable = attValue;
} else if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_ABSTRACT) ) {
isAbstract = attValue;
} else if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_FINAL) ) {
finalSet = attValue;
} else if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_BLOCK) ) {
blockSet = attValue;
} else {
reportGenericSchemaError ("Invalid attribute for 'element'");
}
}
if ( fComponentStack.size() == 0 ) {
if ( name != null && ref == null && minOccurs == null && maxOccurs == null ) {
Schema.ElementDecl element = fSchemaDocument.createElementDecl ();
element.setName (name);
if ( type != null ) element.setType (type, null);
if ( equivClass != null ) element.setEquivClass (equivClass, null);
if ( isNullable != null ) element.setNullable (parseBoolean(isNullable));
if ( isAbstract != null ) element.setAbstract (parseBoolean(isAbstract));
if ( defaultValue != null ) element.setDefaultValue (defaultValue);
if ( fixedValue != null ) element.setFixedValue (fixedValue);
if ( finalSet != null ) element.setFinal (parseDerivationSet(finalSet));
if ( blockSet != null ) element.setBlock (parseBlockSet(blockSet));
fComponentStack.push (element);
} else {
reportGenericSchemaError ("Invalid global 'element' declaration");
}
} else {
Schema.ElementParticle particle = fSchemaDocument.createElementParticle ();
if (equivClass == null && finalSet == null ) {
if ( ref != null ) {
if ( name == null && type == null ) {
} else {
reportGenericSchemaError ("Invalid 'element' particle");
}
} else {
if ( name != null ) {
particle.setName (name);
} else {
reportGenericSchemaError ("Invalid 'element' particle");
}
}
if ( isNullable != null ) particle.setNullable (parseBoolean(isNullable));
if ( isAbstract != null ) particle.setAbstract (parseBoolean(isAbstract));
if ( defaultValue != null ) particle.setDefaultValue (defaultValue);
if ( fixedValue != null ) particle.setFixedValue (fixedValue);
} else {
reportGenericSchemaError ("Invalid 'element' particle");
}
fComponentStack.push (particle);
}
}
/*
* Description:
*
* The other side of starting an element. If it's a global element
* decl then it will be the only thing on the component stack by this
* point. In this case, remove the element decl from the component
* stack and register it at the global level with the schema document.
*
* Otherwise, an element particle will be on the component stack.
* Remove it and add it to the element particle holder (group def
* or complex type def) that should be on the stack below.
*
* Errors:
*
* A class cast exception indicatates that something on the component
* stack was not what we exptected it to be.
*
*/
private void endElementDecl () throws Exception
{
try {
if ( fComponentStack.size() == 1 ) {
// Global element decl
Schema.ElementDecl element = (Schema.ElementDecl)fComponentStack.pop ();
fSchemaDocument.registerElementDecl (element.getName(), element);
} else {
// Nested element decl (particle)
Schema.ElementParticle particle = (Schema.ElementParticle)fComponentStack.pop ();
Schema.EParticleHolder holder = (Schema.EParticleHolder)fComponentStack.peek ();
holder.add (particle);
}
} catch (ClassCastException e) {
reportGenericSchemaError ("Component stack error!");
}
}
// ********************
// **** ATTRIBUTES ****
// ********************
/*
* Description:
*
* An attribute decl can either be a global attribute decl or a an attribute
* particle that is contained in either a complex type def or an attribute
* group def. An attribute particle can either be an attribute decl or a
* reference to a global attribute decl.
*
* If it's a global attribute decl, we will put an attribute decl on the component
* stack. Subsequent element processing may lead to adding things to this, e.g.
* an annotation or simple type def, before it is closed. If it's not global, we
* will put an attribute particle on the component stack. Things can be added to
* this as well.
*
*/
private void startAttributeDecl (XMLAttrList attrList, int attrListIndex) throws Exception
{
String name = null;
String ref = null;
String type = null;
String use = null;
String value = null;
for (int i=attrList.getFirstAttr(attrListIndex); i != -1; i = attrList.getNextAttr(i) ) {
String attValue = fStringPool.toString (attrList.getAttValue(i));
if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_NAME) ) {
name = attValue;
} else if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_REF) ) {
ref = attValue;
} else if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_TYPE) ) {
type = attValue;
} else if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_USE) ) {
use = attValue;
} else if ( attrList.getAttrName(i) == fStringPool.addSymbol(Schema.ATT_VALUE) ) {
value = attValue;
} else {
reportGenericSchemaError ("Invalid attribute for 'attribute'");
}
}
if ( fComponentStack.size() == 0 ) {
if ( name != null ) {
if ( ref == null ) {
Schema.AttributeDecl attribute = fSchemaDocument.createAttributeDecl ();
// TODO: namespaces
if ( type != null ) attribute.setSimpleType (type, null);
if ( use != null ) attribute.setUse (parseUse(use));
if ( value != null ) attribute.setValue (value);
fComponentStack.push (attribute);
} else {
reportGenericSchemaError ("Global 'attribute' declaration may not have ref");
}
} else {
reportGenericSchemaError ("Global 'attribute' declaration must have name");
}
} else {
Schema.AttributeParticle particle = fSchemaDocument.createAttributeParticle ();
if ( ref != null ) particle.setAttributeRef (ref, null);
if ( type != null ) particle.setSimpleType (type, null);
if ( use != null ) particle.setUse (parseUse(use));
if ( value != null ) particle.setValue (value);
fComponentStack.push (particle);
}
}
/*
* Description:
*
* Translate a string value of the "use" attribute to its
* corresponding Schema integer representation.
*
* Errors:
*
* An invalid value for the use attribute.
*
*/
private int parseUse (String useString) throws Exception
{
if ( useString.equals (Schema.VAL_OPTIONAL) ) {
return Schema.OPTIONAL;
} else if ( useString.equals (Schema.VAL_REQUIRED) ) {
return Schema.REQUIRED;
} else if ( useString.equals (Schema.VAL_DEFAULT) ) {
return Schema.DEFAULT;
} else if ( useString.equals (Schema.VAL_FIXED) ) {
return Schema.FIXED;
} else if ( useString.equals (Schema.VAL_PROHIBITED) ) {
return Schema.PROHIBITED;
} else {
reportGenericSchemaError ("Invalid value for 'use'" );
return -1;
}
}
/*
* Description:
*
* The other side of starting an attribute. If it's a global attribute
* decl then it will be the only thing on the component stack by this
* point. In this case, remove the attribute decl from the component
* stack and register it at the global level with the schema document.
*
* Otherwise, an attribute particle will be on the component stack.
* Remove it and add it to the attribute particle holder (attribute
* group def or complex type def) that should be on the stack below.
*
* Errors:
*
* A class cast exception indicatates that something on the component
* stack was not what we exptected it to be.
*
*/
private void endAttributeDecl () throws Exception
{
try {
if ( fComponentStack.size() == 1 ) {
// Global attribute decl
Schema.AttributeDecl attribute = (Schema.AttributeDecl)fComponentStack.pop ();
fSchemaDocument.registerAttributeDecl (attribute.getName(), attribute);
} else {
// Nested attribute decl (particle)
Schema.AttributeParticle particle = (Schema.AttributeParticle)fComponentStack.pop ();
Schema.AParticleHolder holder = (Schema.AParticleHolder)fComponentStack.peek ();
holder.add (particle);
}
} catch (ClassCastException e) {
reportGenericSchemaError ("Component stack error!");
}
}
// *******************
// **** NOTATIONS ****
// *******************
private void startNotationDecl (XMLAttrList attrList, int attrListIndex)
{
}
private void endNotationDecl ()
{
//System.out.println ("</notation>\n");
}
// *************************
// **** ERROR REPORTING ****
// *************************
private void reportSchemaError(int major, Object args[]) throws Exception {
reportError( getLocator(),
SchemaMessageProvider.SCHEMA_DOMAIN,
major,
SchemaMessageProvider.MSG_NONE,
args,
XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR );
}
private void reportGenericSchemaError (String error) throws Exception {
reportSchemaError (SchemaMessageProvider.GenericError, new Object[] { error });
}
} // class SchemaParser