Package org.apache.xerces.validators.schema

Source Code of org.apache.xerces.validators.schema.TraverseSchema$IgnoreWhitespaceParser

/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 2000,2001 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  org.apache.xerces.framework.XMLErrorReporter;
import  org.apache.xerces.validators.common.Grammar;
import  org.apache.xerces.validators.common.GrammarResolver;
import  org.apache.xerces.validators.common.GrammarResolverImpl;
import  org.apache.xerces.validators.common.XMLElementDecl;
import  org.apache.xerces.validators.common.XMLAttributeDecl;
import  org.apache.xerces.validators.schema.SchemaSymbols;
import  org.apache.xerces.validators.schema.XUtil;
import  org.apache.xerces.validators.schema.identity.Field;
import  org.apache.xerces.validators.schema.identity.IdentityConstraint;
import  org.apache.xerces.validators.schema.identity.Key;
import  org.apache.xerces.validators.schema.identity.KeyRef;
import  org.apache.xerces.validators.schema.identity.Selector;
import  org.apache.xerces.validators.schema.identity.Unique;
import  org.apache.xerces.validators.schema.identity.XPath;
import  org.apache.xerces.validators.schema.identity.XPathException;
import  org.apache.xerces.validators.datatype.DatatypeValidator;
import  org.apache.xerces.validators.datatype.DatatypeValidatorFactoryImpl;
import  org.apache.xerces.validators.datatype.NOTATIONDatatypeValidator;
import  org.apache.xerces.validators.datatype.UnionDatatypeValidator; 
import  org.apache.xerces.validators.datatype.InvalidDatatypeValueException;
import  org.apache.xerces.utils.StringPool;
import  org.w3c.dom.Element;

import java.io.IOException;
import java.util.*;
import java.net.URL;
import java.net.MalformedURLException;

//REVISIT: for now, import everything in the DOM package
import  org.w3c.dom.*;

//Unit Test
import  org.apache.xerces.parsers.DOMParser;
import  org.apache.xerces.validators.common.XMLValidator;
import  org.apache.xerces.validators.datatype.DatatypeValidator.*;
import  org.apache.xerces.validators.datatype.InvalidDatatypeValueException;
import  org.apache.xerces.framework.XMLContentSpec;
import  org.apache.xerces.utils.QName;
import  org.apache.xerces.utils.NamespacesScope;
import  org.apache.xerces.parsers.SAXParser;
import  org.apache.xerces.framework.XMLParser;
import  org.apache.xerces.framework.XMLDocumentScanner;

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.w3c.dom.Document;
/** Don't check the following code in because it creates a dependency on
    the serializer, preventing to package the parser without the serializer.
import  org.apache.xml.serialize.OutputFormat;
import  org.apache.xml.serialize.XMLSerializer;
**/
import  org.apache.xerces.validators.schema.SchemaSymbols;

/**
* Instances of this class get delegated to Traverse the Schema and
* to populate the Grammar internal representation by
* instances of Grammar objects.
* Traverse a Schema Grammar:
*
* @author Eric Ye, IBM
* @author Jeffrey Rodriguez, IBM
* @author Andy Clark, IBM
* @see org.apache.xerces.validators.common.Grammar
*
* @version $Id: TraverseSchema.java,v 1.116 2001/03/12 15:49:48 neilg Exp $
*/
public class TraverseSchema implements
                            NamespacesScope.NamespacesHandler{

   
    //CONSTANTS
    private static final int TOP_LEVEL_SCOPE = -1;

    /** Identity constraint keywords. */
    private static final String[] IDENTITY_CONSTRAINTS = {
        SchemaSymbols.ELT_UNIQUE,
        SchemaSymbols.ELT_KEY, SchemaSymbols.ELT_KEYREF
    };
    private static final String redefIdentifier = "#redefined";

    //debuggin
    private static final boolean DEBUGGING = false;

    /** Compile to true to debug identity constraints. */
    private static final boolean DEBUG_IDENTITY_CONSTRAINTS = false;
   
    /**
     * Compile to true to debug datatype validator lookup for
     * identity constraint support.
     */
    private static final boolean DEBUG_IC_DATATYPES = false;

    //CR Implementation
    private static final boolean DEBUG_UNION = false;
    private static final boolean CR_IMPL = true;
    //private data members


    private XMLErrorReporter    fErrorReporter = null;
    private StringPool          fStringPool    = null;

    private GrammarResolver fGrammarResolver = null;
    private SchemaGrammar fSchemaGrammar = null;

    private Element fSchemaRootElement;
    // this is always set to refer to the root of the linked list containing the root info of schemas under redefinition.
    private SchemaInfo fSchemaInfoListRoot = null;
    private SchemaInfo fCurrentSchemaInfo = null;
    private boolean fRedefineSucceeded;

    private DatatypeValidatorFactoryImpl fDatatypeRegistry = null;

    private Hashtable fComplexTypeRegistry = new Hashtable();
    private Hashtable fAttributeDeclRegistry = new Hashtable();
   
    // stores the names of groups that we've traversed so we can avoid multiple traversals
    // qualified group names are keys and their contentSpecIndexes are values. 
    private Hashtable fGroupNameRegistry = new Hashtable();

    // stores <notation> decl
    private Hashtable fNotationRegistry = new Hashtable();

    private Vector fIncludeLocations = new Vector();
    private Vector fImportLocations = new Vector();
    private Hashtable fRedefineLocations = new Hashtable();
    private Vector fTraversedRedefineElements = new Vector();


    private int fAnonTypeCount =0;
    private int fScopeCount=0;
    private int fCurrentScope=TOP_LEVEL_SCOPE;
    private int fSimpleTypeAnonCount = 0;
    private Stack fCurrentTypeNameStack = new Stack();
    private Hashtable fElementRecurseComplex = new Hashtable();

    private boolean fElementDefaultQualified = false;
    private boolean fAttributeDefaultQualified = false;

    private int fTargetNSURI;
    private String fTargetNSURIString = "";
    private NamespacesScope fNamespacesScope = null;
    private String fCurrentSchemaURL = "";

    private XMLAttributeDecl fTempAttributeDecl = new XMLAttributeDecl();
    private XMLElementDecl fTempElementDecl = new XMLElementDecl();

    private EntityResolver  fEntityResolver = null;
   
    private Hashtable fIdentityConstraints = new Hashtable();
   
   // REVISIT: maybe need to be moved into SchemaGrammar class
    public class ComplexTypeInfo {
        public String typeName;
       
        public DatatypeValidator baseDataTypeValidator;
        public ComplexTypeInfo baseComplexTypeInfo;

        public int derivedBy = 0;
        public int blockSet = 0;
        public int finalSet = 0;

        public boolean isAbstract = false;

        public int scopeDefined = -1;

        public int contentType;
        public int contentSpecHandle = -1;
        public int templateElementIndex = -1;
        public int attlistHead = -1;
        public DatatypeValidator datatypeValidator;
    }

    private class ComplexTypeRecoverableError extends Exception {
        ComplexTypeRecoverableError() {super();}
        ComplexTypeRecoverableError(String s) {super(s);}
    }

    //REVISIT: verify the URI.
    public final static String SchemaForSchemaURI = "http://www.w3.org/TR-1/Schema";

    private TraverseSchema( ) {
        // new TraverseSchema() is forbidden;
    }


    public void setGrammarResolver(GrammarResolver grammarResolver){
        fGrammarResolver = grammarResolver;
    }
    public void startNamespaceDeclScope(int prefix, int uri){
        //TO DO
    }
    public void endNamespaceDeclScope(int prefix){
        //TO DO, do we need to do anything here?
    }

   

    private String resolvePrefixToURI (String prefix) throws Exception  {
        String uriStr = fStringPool.toString(fNamespacesScope.getNamespaceForPrefix(fStringPool.addSymbol(prefix)));
        if (uriStr == null) {
            // REVISIT: Localize
            reportGenericSchemaError("prefix : [" + prefix +"] can not be resolved to a URI");
            return "";
        }

        //REVISIT, !!!! a hack: needs to be updated later, cause now we only use localpart to key build-in datatype.
        if ( prefix.length()==0 && uriStr.equals(SchemaSymbols.URI_SCHEMAFORSCHEMA)
             && fTargetNSURIString.length() == 0) {
            uriStr = "";
        }

        return uriStr;
    }

    public  TraverseSchema(Element root, StringPool stringPool,
                           SchemaGrammar schemaGrammar,
                           GrammarResolver grammarResolver,
                           XMLErrorReporter errorReporter,
                           String schemaURL,
                   EntityResolver entityResolver
                           ) throws Exception {
        fErrorReporter = errorReporter;
        fCurrentSchemaURL = schemaURL;
    fEntityResolver = entityResolver;
        doTraverseSchema(root, stringPool, schemaGrammar, grammarResolver);
    }

    public  TraverseSchema(Element root, StringPool stringPool,
                           SchemaGrammar schemaGrammar,
                           GrammarResolver grammarResolver,
                           XMLErrorReporter errorReporter,
                           String schemaURL
                           ) throws Exception {
        fErrorReporter = errorReporter;
        fCurrentSchemaURL = schemaURL;
        doTraverseSchema(root, stringPool, schemaGrammar, grammarResolver);
    }

    public  TraverseSchema(Element root, StringPool stringPool,
                           SchemaGrammar schemaGrammar,
                           GrammarResolver grammarResolver
                           ) throws Exception {
        doTraverseSchema(root, stringPool, schemaGrammar, grammarResolver);
    }

    public  void doTraverseSchema(Element root, StringPool stringPool,
                           SchemaGrammar schemaGrammar,
                           GrammarResolver grammarResolver) throws Exception {

        fNamespacesScope = new NamespacesScope(this);
       
        fSchemaRootElement = root;
        fStringPool = stringPool;
        fSchemaGrammar = schemaGrammar;
        fGrammarResolver = grammarResolver;
        fDatatypeRegistry = (DatatypeValidatorFactoryImpl) fGrammarResolver.getDatatypeRegistry();
        fDatatypeRegistry.expandRegistryToFullSchemaSet();//Expand to registry type to contain all primitive datatype

        if (root == null) {
            // REVISIT: Anything to do?
            return;
        }

        //Make sure namespace binding is defaulted
        String rootPrefix = root.getPrefix();
        if( rootPrefix == null || rootPrefix.length() == 0 ){
            String xmlns = root.getAttribute("xmlns");
            if( xmlns.length() == 0 )
                root.setAttribute("xmlns", SchemaSymbols.URI_SCHEMAFORSCHEMA );
        }

        //Retrieve the targetnamespace URI information
        fTargetNSURIString = root.getAttribute(SchemaSymbols.ATT_TARGETNAMESPACE);
        if (fTargetNSURIString==null) {
            fTargetNSURIString="";
        }
        fTargetNSURI = fStringPool.addSymbol(fTargetNSURIString);

        if (fGrammarResolver == null) {
            // REVISIT: Localize
            reportGenericSchemaError("Internal error: don't have a GrammarResolver for TraverseSchema");
        }
        else{
            // for complex type registry, attribute decl registry and
            // namespace mapping, needs to check whether the passed in
            // Grammar was a newly instantiated one.
            if (fSchemaGrammar.getComplexTypeRegistry() == null ) {
                fSchemaGrammar.setComplexTypeRegistry(fComplexTypeRegistry);
            }
            else {
                fComplexTypeRegistry = fSchemaGrammar.getComplexTypeRegistry();
            }

            if (fSchemaGrammar.getAttirubteDeclRegistry() == null ) {
                fSchemaGrammar.setAttributeDeclRegistry(fAttributeDeclRegistry);
            }
            else {
                fAttributeDeclRegistry = fSchemaGrammar.getAttirubteDeclRegistry();
            }

            if (fSchemaGrammar.getNamespacesScope() == null ) {
                fSchemaGrammar.setNamespacesScope(fNamespacesScope);
            }
            else {
                fNamespacesScope = fSchemaGrammar.getNamespacesScope();
            }

            fSchemaGrammar.setDatatypeRegistry(fDatatypeRegistry);
            fSchemaGrammar.setTargetNamespaceURI(fTargetNSURIString);
            fGrammarResolver.putGrammar(fTargetNSURIString, fSchemaGrammar);
        }
       


        // Retrived the Namespace mapping from the schema element.
        NamedNodeMap schemaEltAttrs = root.getAttributes();
        int i = 0;
        Attr sattr = null;

        boolean seenXMLNS = false;                                       
        while ((sattr = (Attr)schemaEltAttrs.item(i++)) != null) {
            String attName = sattr.getName();
            if (attName.startsWith("xmlns:")) {
                String attValue = sattr.getValue();
                String prefix = attName.substring(attName.indexOf(":")+1);
                fNamespacesScope.setNamespaceForPrefix( fStringPool.addSymbol(prefix),
                                                        fStringPool.addSymbol(attValue) );
            }
            if (attName.equals("xmlns")) {

                String attValue = sattr.getValue();
                fNamespacesScope.setNamespaceForPrefix( fStringPool.addSymbol(""),
                                                        fStringPool.addSymbol(attValue) );
                seenXMLNS = true;
            }

        }
        if (!seenXMLNS && fTargetNSURIString.length() == 0 ) {
            fNamespacesScope.setNamespaceForPrefix( fStringPool.addSymbol(""),
                                                    fStringPool.addSymbol("") );
        }

        fElementDefaultQualified =
            root.getAttribute(SchemaSymbols.ATT_ELEMENTFORMDEFAULT).equals(SchemaSymbols.ATTVAL_QUALIFIED);
        fAttributeDefaultQualified =
            root.getAttribute(SchemaSymbols.ATT_ATTRIBUTEFORMDEFAULT).equals(SchemaSymbols.ATTVAL_QUALIFIED);
       
        //REVISIT, really sticky when noTargetNamesapce, for now, we assume everyting is in the same name space);
        if (fTargetNSURI == StringPool.EMPTY_STRING) {
            //fElementDefaultQualified = true;
            //fAttributeDefaultQualified = true;
        }


        //fScopeCount++;
        fCurrentScope = -1;


        checkTopLevelDuplicateNames(root);

        //extract all top-level attribute, attributeGroup, and group Decls and put them in the 3 hasn table in the SchemaGrammar.
        extractTopLevel3Components(root);

        // process <redefine>, <include> and <import> info items.
        Element child = XUtil.getFirstChildElement(root);
        for (; child != null;
            child = XUtil.getNextSiblingElement(child)) {

            String name = child.getLocalName();
            if (name.equals(SchemaSymbols.ELT_ANNOTATION) ) {
                traverseAnnotationDecl(child);
            } else if (name.equals(SchemaSymbols.ELT_INCLUDE)) {
                traverseInclude(child);
            } else if (name.equals(SchemaSymbols.ELT_IMPORT)) {
                traverseImport(child);
            } else if (name.equals(SchemaSymbols.ELT_REDEFINE)) {
                fRedefineSucceeded = true; // presume worked until proven failed.
                traverseRedefine(child);
            } else
                break;
        }

        // child refers to the first info item which is not <annotation> or
        // one of the schema inclusion/importation declarations.
        for (; child != null;
            child = XUtil.getNextSiblingElement(child)) {

            String name = child.getLocalName();
            if (name.equals(SchemaSymbols.ELT_ANNOTATION) ) {
                traverseAnnotationDecl(child);
            } else if (name.equals(SchemaSymbols.ELT_SIMPLETYPE )) {
                traverseSimpleTypeDecl(child);
            } else if (name.equals(SchemaSymbols.ELT_COMPLEXTYPE )) {
                traverseComplexTypeDecl(child);
            } else if (name.equals(SchemaSymbols.ELT_ELEMENT )) {
                traverseElementDecl(child);
            } else if (name.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) {
                traverseAttributeGroupDecl(child, null, null);
            } else if (name.equals( SchemaSymbols.ELT_ATTRIBUTE ) ) {
                traverseAttributeDecl( child, null, false );
            } else if (name.equals(SchemaSymbols.ELT_GROUP)) {
                traverseGroupDecl(child);
            } else if (name.equals(SchemaSymbols.ELT_NOTATION)) {
                traverseNotationDecl(child); //TO DO
            } else {
                // REVISIT: Localize
                reportGenericSchemaError("error in content of <schema> element information item");
            }
        } // for each child node

        // handle identity constraints
        Enumeration elementIndexes = fIdentityConstraints.keys();
        while (elementIndexes.hasMoreElements()) {
            Integer elementIndexObj = (Integer)elementIndexes.nextElement();
            if (DEBUG_IC_DATATYPES) {
                System.out.println("<ICD>: traversing identity constraints for element: "+elementIndexObj);
            }
            Vector identityConstraints = (Vector)fIdentityConstraints.get(elementIndexObj);
            if (identityConstraints != null) {
                int elementIndex = elementIndexObj.intValue();
                traverseIdentityConstraintsFor(elementIndex, identityConstraints);
            }
        }

    } // traverseSchema(Element)

    private void checkTopLevelDuplicateNames(Element root) {
        //TO DO : !!!
    }

    private void extractTopLevel3Components(Element root){
       
        for (Element child = XUtil.getFirstChildElement(root); child != null;
            child = XUtil.getNextSiblingElement(child)) {

            String name = child.getLocalName();
            String compName = child.getAttribute(SchemaSymbols.ATT_NAME);
            if (name.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) {
                fSchemaGrammar.topLevelAttrGrpDecls.put(compName, child);
            } else if (name.equals( SchemaSymbols.ELT_ATTRIBUTE ) ) {
                fSchemaGrammar.topLevelAttrDecls.put(compName, child);
            } else if ( name.equals(SchemaSymbols.ELT_GROUP) ) {
                fSchemaGrammar.topLevelGroupDecls.put(compName, child);
            } else if ( name.equals(SchemaSymbols.ELT_NOTATION) ) {
                fSchemaGrammar.topLevelNotationDecls.put(compName, child);
            }
        } // for each child node
    }

    /**
     * Expands a system id and returns the system id as a URL, if
     * it can be expanded. A return value of null means that the
     * identifier is already expanded. An exception thrown
     * indicates a failure to expand the id.
     *
     * @param systemId The systemId to be expanded.
     *
     * @return Returns the URL object representing the expanded system
     *         identifier. A null value indicates that the given
     *         system identifier is already expanded.
     *
     */
    private String expandSystemId(String systemId, String currentSystemId) throws Exception{
     String id = systemId;

     // check for bad parameters id
     if (id == null || id.length() == 0) {
         return systemId;
     }

     // if id already expanded, return
     try {
         URL url = new URL(id);
         if (url != null) {
             return systemId;
         }
     }
     catch (MalformedURLException e) {
         // continue on...
     }

     // normalize id
     id = fixURI(id);

     // normalize base
     URL base = null;
     URL url = null;
     try {
         if (currentSystemId == null) {
             String dir;
             try {
                 dir = fixURI(System.getProperty("user.dir"));
             }
             catch (SecurityException se) {
                 dir = "";
             }
             if (!dir.endsWith("/")) {
                 dir = dir + "/";
             }
             base = new URL("file", "", dir);
         }
         else {
             base = new URL(currentSystemId);
         }

         // expand id
         url = new URL(base, id);
     }
     catch (Exception e) {
         // let it go through
     }
     if (url == null) {
         return systemId;
     }
     return url.toString();
    }
    /**
     * Fixes a platform dependent filename to standard URI form.
     *
     * @param str The string to fix.
     *
     * @return Returns the fixed URI string.
     */
    private static String fixURI(String str) {

        // handle platform dependent strings
        str = str.replace(java.io.File.separatorChar, '/');

        // Windows fix
        if (str.length() >= 2) {
            char ch1 = str.charAt(1);
            if (ch1 == ':') {
                char ch0 = Character.toUpperCase(str.charAt(0));
                if (ch0 >= 'A' && ch0 <= 'Z') {
                    str = "/" + str;
                }
            }
        }

        // done
        return str;
    }


    private void traverseInclude(Element includeDecl) throws Exception {

        Attr locationAttr = includeDecl.getAttributeNode(SchemaSymbols.ATT_SCHEMALOCATION);
      if (locationAttr == null) {
            // REVISIT: Localize
            reportGenericSchemaError("a schemaLocation attribute must be specified on an <include> element");
            return;
        }
        String location = locationAttr.getValue();
       
        // expand it before passing it to the parser
        InputSource source = null;
        if (fEntityResolver != null) {
            source = fEntityResolver.resolveEntity("", location);
        }
        if (source == null) {
            location = expandSystemId(location, fCurrentSchemaURL);
            source = new InputSource(location);
        }
        else {
            // create a string for uniqueness of this included schema in fIncludeLocations
            if (source.getPublicId () != null)
                location = source.getPublicId ();

            location += (',' + source.getSystemId ());
        }

        if (fIncludeLocations.contains((Object)location)) {
            return;
        }
        fIncludeLocations.addElement((Object)location);

        DOMParser parser = new IgnoreWhitespaceParser();
        parser.setEntityResolver( new Resolver() );
        parser.setErrorHandlernew ErrorHandler() );

        try {
            parser.setFeature("http://xml.org/sax/features/validation", false);
            parser.setFeature("http://xml.org/sax/features/namespaces", true);
            parser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", false);
        }catchorg.xml.sax.SAXNotRecognizedException e ) {
            e.printStackTrace();
        }catch( org.xml.sax.SAXNotSupportedException e ) {
            e.printStackTrace();
        }

        try {
            parser.parse( source );
        }catch( IOException e ) {
            e.printStackTrace();
        }catch( SAXException e ) {
            //e.printStackTrace();
        }

        Document     document   = parser.getDocument(); //Our Grammar
        Element root = null;
        if (document != null) {
            root = document.getDocumentElement();
        }

        if (root != null) {
            String targetNSURI = root.getAttribute(SchemaSymbols.ATT_TARGETNAMESPACE);
            if (targetNSURI.length() > 0 && !targetNSURI.equals(fTargetNSURIString) ) {
                // REVISIT: Localize
                reportGenericSchemaError("included schema '"+location+"' has a different targetNameSpace '"
                                         +targetNSURI+"'");
            }
            else {
                // We not creating another TraverseSchema object to compile
                // the included schema file, because the scope count, anon-type count
                // should not be reset for a included schema, this can be fixed by saving
                // the counters in the Schema Grammar,
                if (fSchemaInfoListRoot == null) {
                    fSchemaInfoListRoot = new SchemaInfo(fElementDefaultQualified, fAttributeDefaultQualified,
                        fCurrentScope, fCurrentSchemaURL, fSchemaRootElement, null, null);
                    fCurrentSchemaInfo = fSchemaInfoListRoot;
                }
                fSchemaRootElement = root;
                fCurrentSchemaURL = location;
                traverseIncludedSchemaHeader(root);
                // and now we'd better save this stuff! 
                fCurrentSchemaInfo = new SchemaInfo(fElementDefaultQualified, fAttributeDefaultQualified,
                        fCurrentScope, fCurrentSchemaURL, fSchemaRootElement, fCurrentSchemaInfo.getNext(), fCurrentSchemaInfo);
                (fCurrentSchemaInfo.getPrev()).setNext(fCurrentSchemaInfo);
                traverseIncludedSchema(root);
                // there must always be a previous element!
                fCurrentSchemaInfo = fCurrentSchemaInfo.getPrev();
                fCurrentSchemaInfo.restore();
            }

        }

    }

    private void traverseIncludedSchemaHeader(Element root) throws Exception {
        // Retrived the Namespace mapping from the schema element.
        NamedNodeMap schemaEltAttrs = root.getAttributes();
        int i = 0;
        Attr sattr = null;

        boolean seenXMLNS = false;                                       
        while ((sattr = (Attr)schemaEltAttrs.item(i++)) != null) {
            String attName = sattr.getName();
            if (attName.startsWith("xmlns:")) {
                String attValue = sattr.getValue();
                String prefix = attName.substring(attName.indexOf(":")+1);
                fNamespacesScope.setNamespaceForPrefix( fStringPool.addSymbol(prefix),
                                                        fStringPool.addSymbol(attValue) );
            }
            if (attName.equals("xmlns")) {

                String attValue = sattr.getValue();
                fNamespacesScope.setNamespaceForPrefix( fStringPool.addSymbol(""),
                                                        fStringPool.addSymbol(attValue) );
                seenXMLNS = true;
            }

        }
        if (!seenXMLNS && fTargetNSURIString.length() == 0 ) {
            fNamespacesScope.setNamespaceForPrefix( fStringPool.addSymbol(""),
                                                    fStringPool.addSymbol("") );
        }

        fElementDefaultQualified =
            root.getAttribute(SchemaSymbols.ATT_ELEMENTFORMDEFAULT).equals(SchemaSymbols.ATTVAL_QUALIFIED);
        fAttributeDefaultQualified =
            root.getAttribute(SchemaSymbols.ATT_ATTRIBUTEFORMDEFAULT).equals(SchemaSymbols.ATTVAL_QUALIFIED);
       
        //REVISIT, really sticky when noTargetNamesapce, for now, we assume everyting is in the same name space);
        if (fTargetNSURI == StringPool.EMPTY_STRING) {
            fElementDefaultQualified = true;
            //fAttributeDefaultQualified = true;
        }

        //fScopeCount++;
        fCurrentScope = -1;
    } // traverseIncludedSchemaHeader

    private void traverseIncludedSchema(Element root) throws Exception {
        checkTopLevelDuplicateNames(root);

        //extract all top-level attribute, attributeGroup, and group Decls and put them in the 3 hasn table in the SchemaGrammar.
        extractTopLevel3Components(root);

        // handle <redefine>, <include> and <import> elements.
        Element child = XUtil.getFirstChildElement(root);
        for (; child != null;
            child = XUtil.getNextSiblingElement(child)) {

            String name = child.getLocalName();

            if (name.equals(SchemaSymbols.ELT_ANNOTATION) ) {
                traverseAnnotationDecl(child);
            } else if (name.equals(SchemaSymbols.ELT_INCLUDE)) {
                traverseInclude(child);
            } else if (name.equals(SchemaSymbols.ELT_IMPORT)) {
                traverseImport(child);
            } else if (name.equals(SchemaSymbols.ELT_REDEFINE)) {
                fRedefineSucceeded = true; // presume worked until proven failed.
                traverseRedefine(child);
            } else
                break;
        }

        // handle the rest of the schema elements.
        for (; child != null;
            child = XUtil.getNextSiblingElement(child)) {

            String name = child.getLocalName();

            if (name.equals(SchemaSymbols.ELT_ANNOTATION) ) {
                traverseAnnotationDecl(child);
            } else if (name.equals(SchemaSymbols.ELT_SIMPLETYPE )) {
                traverseSimpleTypeDecl(child);
            } else if (name.equals(SchemaSymbols.ELT_COMPLEXTYPE )) {
                traverseComplexTypeDecl(child);
            } else if (name.equals(SchemaSymbols.ELT_ELEMENT )) {
                traverseElementDecl(child);
            } else if (name.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) {
                traverseAttributeGroupDecl(child, null, null);
            } else if (name.equals( SchemaSymbols.ELT_ATTRIBUTE ) ) {
                traverseAttributeDecl( child, null , false);
            } else if (name.equals(SchemaSymbols.ELT_GROUP)) {
                traverseGroupDecl(child);
            } else if (name.equals(SchemaSymbols.ELT_NOTATION)) {
                traverseNotationDecl(child); //TO DO
            } else {
                // REVISIT: Localize
                reportGenericSchemaError("error in content of included <schema> element information item");
            }
        } // for each child node

    }

    // This method's job is to open a redefined schema and store away its root element, defaultElementQualified and other
    // such info, in order that it can be available when redefinition actually takes place. 
    // It assumes that it will be called from the schema doing the redefining, and it assumes
    // that the other schema's info has already been saved, putting the info it finds into the
    // SchemaInfoList element that is passed in. 
    private void openRedefinedSchema(Element redefineDecl, SchemaInfo store) throws Exception {
        Attr locationAttr = redefineDecl.getAttributeNode(SchemaSymbols.ATT_SCHEMALOCATION);
      if (locationAttr == null) {
            // REVISIT: Localize
            fRedefineSucceeded = false;
            reportGenericSchemaError("a schemaLocation attribute must be specified on a <redefine> element");
            return;
        }
        String location = locationAttr.getValue();
       
        // expand it before passing it to the parser
        InputSource source = null;
        if (fEntityResolver != null) {
            source = fEntityResolver.resolveEntity("", location);
        }

        if (source == null) {
            location = expandSystemId(location, fCurrentSchemaURL);
            source = new InputSource(location);
        }
        else {
            // Make sure we don't redefine the same schema twice; it's allowed
      // but the specs encourage us to avoid it. 
            if (source.getPublicId () != null)
                location = source.getPublicId ();

            location += (',' + source.getSystemId ());
        }
        if (fRedefineLocations.get((Object)location) != null) {
            // then we'd better make sure we're directed at that schema...
            fCurrentSchemaInfo = (SchemaInfo)(fRedefineLocations.get((Object)location));
            fCurrentSchemaInfo.restore();
            return;
        }

        DOMParser parser = new IgnoreWhitespaceParser();
        parser.setEntityResolver( new Resolver() );
        parser.setErrorHandlernew ErrorHandler() );

        try {
            parser.setFeature("http://xml.org/sax/features/validation", false);
            parser.setFeature("http://xml.org/sax/features/namespaces", true);
            parser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", false);
        }catchorg.xml.sax.SAXNotRecognizedException e ) {
            e.printStackTrace();
        }catch( org.xml.sax.SAXNotSupportedException e ) {
            e.printStackTrace();
        }

        try {
            parser.parse( source );
        }catch( IOException e ) {
            e.printStackTrace();
        }catch( SAXException e ) {
            //e.printStackTrace();
        }

        Document     document   = parser.getDocument(); //Our Grammar to be redefined
        Element root = null;
        if (document != null) {
            root = document.getDocumentElement();
        }

    if (root == null) { // nothing to be redefined, so just continue; specs disallow an error here.
            fRedefineSucceeded = false;
            return;
        }

    // now if root isn't null, it'll contain the root of the schema we need to redefine. 
    // We do this in two phases:  first, we look through the children of
    // redefineDecl.  Each one will correspond to an element of the
    // redefined schema that we need to redefine.  To do this, we rename the
    // element of the redefined schema, and rework the base or ref tag of
    // the kid we're working on to refer to the renamed group or derive the
    // renamed type.  Once we've done this, we actually go through the
    // schema being redefined and convert it to a grammar.  Only then do we
    // run through redefineDecl's kids and put them in the grammar. 
    //
    // This approach is kosher with the specs.  It does raise interesting
    // questions about error reporting, and perhaps also about grammar
    // access, but it is comparatively efficient (we need make at most
    // only 2 traversals of any given information item) and moreover
    // we can use existing code to build the grammar structures once the
    // first pass is out of the way, so this should be quite robust. 

    // check to see if the targetNameSpace is right
        String redefinedTargetNSURIString = root.getAttribute(SchemaSymbols.ATT_TARGETNAMESPACE);
        if (redefinedTargetNSURIString.length() > 0 && !redefinedTargetNSURIString.equals(fTargetNSURIString) ) {
            // REVISIT: Localize
            fRedefineSucceeded = false;
            reportGenericSchemaError("redefined schema '"+location+"' has a different targetNameSpace '"
                                     +redefinedTargetNSURIString+"' from the original schema");
        }
        else {
      // targetNamespace is right, so let's do the renaming...
      // and let's keep in mind that the targetNamespace of the redefined
      // elements is that of the redefined schema! 
            fSchemaRootElement = root;
            fCurrentSchemaURL = location;
            // get default form xmlns bindings et al.
            traverseIncludedSchemaHeader(root);
            // and then save them...
            store.setNext(new SchemaInfo(fElementDefaultQualified, fAttributeDefaultQualified,
                    fCurrentScope, fCurrentSchemaURL, fSchemaRootElement, null, store));
            (store.getNext()).setPrev(store);
            fCurrentSchemaInfo = store.getNext();
            fRedefineLocations.put((Object)location, store.getNext());
        } // end if
    } // end openRedefinedSchema

  /****
   * <redefine
     *    schemaLocation = uriReference
     *    {any attributes with non-schema namespace . . .}>
     *    Content: (annotation | (
   *      attributeGroup | complexType | group | simpleType))*
   *  </redefine>
   */
    private void traverseRedefine(Element redefineDecl) throws Exception {

        // only case in which need to save contents is when fSchemaInfoListRoot is null; otherwise we'll have
        // done this already one way or another. 
        if (fSchemaInfoListRoot == null) {
            fSchemaInfoListRoot = new SchemaInfo(fElementDefaultQualified, fAttributeDefaultQualified,
                    fCurrentScope, fCurrentSchemaURL, fSchemaRootElement, null, null);
            openRedefinedSchema(redefineDecl, fSchemaInfoListRoot);
            if(!fRedefineSucceeded)
                return;
            fCurrentSchemaInfo = fSchemaInfoListRoot.getNext();
        renameRedefinedComponents(redefineDecl,fSchemaInfoListRoot.getNext().getRoot(), fSchemaInfoListRoot.getNext());
        } else {
            // may have a chain here; need to be wary! 
            SchemaInfo curr = fSchemaInfoListRoot;
            for(; curr.getNext() != null; curr = curr.getNext());
            fCurrentSchemaInfo = curr;
            fCurrentSchemaInfo.restore();
            openRedefinedSchema(redefineDecl, fCurrentSchemaInfo);
            if(!fRedefineSucceeded)
                return;
        renameRedefinedComponents(redefineDecl,fCurrentSchemaInfo.getRoot(), fCurrentSchemaInfo);
        }
        // Now we have to march through our nicely-renamed schemas from the
        // bottom up.  When we do these traversals other <redefine>'s may
        // perhaps be encountered; we leave recursion to sort this out. 

        traverseIncludedSchema(fSchemaRootElement);
        // and last but not least:  traverse our own <redefine>--the one all
        // this labour has been expended upon. 
        for (Element child = XUtil.getFirstChildElement(redefineDecl); child != null;
               child = XUtil.getNextSiblingElement(child)) {
             String name = child.getLocalName();

      // annotations can occur anywhere in <redefine>s!
             if (name.equals(SchemaSymbols.ELT_ANNOTATION) ) {
                 traverseAnnotationDecl(child);
             } else if (name.equals(SchemaSymbols.ELT_SIMPLETYPE )) {
                 traverseSimpleTypeDecl(child);
             } else if (name.equals(SchemaSymbols.ELT_COMPLEXTYPE )) {
                 traverseComplexTypeDecl(child);
             } else if (name.equals(SchemaSymbols.ELT_GROUP)) {
                 traverseGroupDecl(child);
             } else if (name.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) {
                 traverseAttributeGroupDecl(child, null, null);
      } // no else; error reported in the previous traversal
         } //for

        // and restore the original globals
        fCurrentSchemaInfo = fCurrentSchemaInfo.getPrev();
        fCurrentSchemaInfo.restore();
    } // traverseRedefine

  // the purpose of this method is twofold:  1.  To find and appropriately modify all information items
  // in redefinedSchema with names that are redefined by children of
  // redefineDecl.  2.  To make sure the redefine element represented by
  // redefineDecl is valid as far as content goes and with regard to
  // properly referencing components to be redefined.  No traversing is done here!
    // This method also takes actions to find and, if necessary, modify the names
    // of elements in <redefine>'s in the schema that's being redefined. 
  private void renameRedefinedComponents(Element redefineDecl, Element schemaToRedefine, SchemaInfo currSchemaInfo) throws Exception {
    for (Element child = XUtil.getFirstChildElement(redefineDecl);
        child != null;
        child = XUtil.getNextSiblingElement(child)) {
            String name = child.getLocalName();
            if (name.equals(SchemaSymbols.ELT_ANNOTATION) )
                continue;
            else if (name.equals(SchemaSymbols.ELT_SIMPLETYPE)) {
              String typeName = child.getAttribute( SchemaSymbols.ATT_NAME );
                if(fTraversedRedefineElements.contains(typeName))
                    continue;
                if(validateRedefineNameChange(SchemaSymbols.ELT_SIMPLETYPE, typeName, typeName+redefIdentifier, child)) {
          fixRedefinedSchema(SchemaSymbols.ELT_SIMPLETYPE,
            typeName, typeName+redefIdentifier,
            schemaToRedefine, currSchemaInfo);
        }
      } else if (name.equals(SchemaSymbols.ELT_COMPLEXTYPE)) {
              String typeName = child.getAttribute( SchemaSymbols.ATT_NAME );
                if(fTraversedRedefineElements.contains(typeName))
                    continue;
                if(validateRedefineNameChange(SchemaSymbols.ELT_COMPLEXTYPE, typeName, typeName+redefIdentifier, child)) {
            fixRedefinedSchema(SchemaSymbols.ELT_COMPLEXTYPE,
              typeName, typeName+redefIdentifier,
              schemaToRedefine, currSchemaInfo);
        }
            } else if (name.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) {
        String baseName = child.getAttribute( SchemaSymbols.ATT_NAME );
                if(fTraversedRedefineElements.contains(baseName))
                    continue;
                if(validateRedefineNameChange(SchemaSymbols.ELT_ATTRIBUTEGROUP, baseName, baseName+redefIdentifier, child)) {
          fixRedefinedSchema(SchemaSymbols.ELT_ATTRIBUTEGROUP,
            baseName, baseName+redefIdentifier,
            schemaToRedefine, currSchemaInfo);
        } else {
          // REVISIT (schema PR):  the case where must prove the attributeGroup restricts the redefined one.
        }
            } else if (name.equals(SchemaSymbols.ELT_GROUP)) {
        String baseName = child.getAttribute( SchemaSymbols.ATT_NAME );
                if(fTraversedRedefineElements.contains(baseName))
                    continue;
                if(validateRedefineNameChange(SchemaSymbols.ELT_GROUP, baseName, baseName+redefIdentifier, child)) {
          fixRedefinedSchema(SchemaSymbols.ELT_GROUP,
            baseName, baseName+redefIdentifier,
            schemaToRedefine, currSchemaInfo);
        } else {
          // REVISIT (schema PR):  the case where must prove the group restricts the redefined one.
        }
      } else {
                fRedefineSucceeded = false;
              // REVISIT: Localize
              reportGenericSchemaError("invalid top-level content for <redefine>");
        return;
      }
    } // for
  } // renameRedefinedComponents

  // This function looks among the children of curr for an element of type elementSought. 
  // If it finds one, it evaluates whether its ref attribute contains a reference
  // to originalName.  If it does, it returns 1 + the value returned by
  // calls to itself on all other children.  In all other cases it returns 0 plus
  // the sum of the values returned by calls to itself on curr's children.
  // It also resets the value of ref so that it will refer to the renamed type from the schema
  // being redefined.
  private int changeRedefineGroup(QName originalName, String elementSought, String newName, Element curr) throws Exception {
    int result = 0;
    for (Element child = XUtil.getFirstChildElement(curr);
        child != null; child = XUtil.getNextSiblingElement(child)) {
            String name = child.getLocalName();
            if (!name.equals(elementSought))
        result += changeRedefineGroup(originalName, elementSought, newName, child);
      else {
        String ref = child.getAttribute( SchemaSymbols.ATT_REF );
        if (!ref.equals("")) {
                String prefix = "";
                String localpart = ref;
                int colonptr = ref.indexOf(":");
                if ( colonptr > 0) {
                    prefix = ref.substring(0,colonptr);
                    localpart = ref.substring(colonptr+1);
                }
                String uriStr = resolvePrefixToURI(prefix);
          if(originalName.equals(new QName(-1, fStringPool.addSymbol(localpart), fStringPool.addSymbol(localpart), fStringPool.addSymbol(uriStr)))) {
                        if(prefix.equals(""))
                child.setAttribute(SchemaSymbols.ATT_REF, newName);
                        else
                child.setAttribute(SchemaSymbols.ATT_REF, prefix + ":" + newName);
            result++;
          }
        } // if ref was null some other stage of processing will flag the error
      }
    }
    return result;
  } // changeRedefineGroup

  // This simple function looks for the first occurrence of an eltLocalname
  // schema information item and appropriately changes the value of
  // its name or type attribute from oldName to newName. 
  // Root contains the root of the schema being operated upon. 
    // If it turns out that what we're looking for is in a <redefine> though, then we
    // just rename it--and it's reference--to be the same and wait until
    // renameRedefineDecls can get its hands on it and do it properly. 
  private void fixRedefinedSchema(String eltLocalname, String oldName, String newName, Element schemaToRedefine,
                SchemaInfo currSchema) throws Exception {

    boolean foundIt = false;
    for (Element child = XUtil.getFirstChildElement(schemaToRedefine);
        child != null;
        child = XUtil.getNextSiblingElement(child)) {
            String name = child.getLocalName();
            if(name.equals(SchemaSymbols.ELT_REDEFINE)) { // need to search the redefine decl...
            for (Element redefChild = XUtil.getFirstChildElement(child);
                redefChild != null;
                redefChild = XUtil.getNextSiblingElement(redefChild)) {
                    String redefName = redefChild.getLocalName();
                    if (redefName.equals(eltLocalname) ) {
                      String infoItemName = redefChild.getAttribute( SchemaSymbols.ATT_NAME );
                if(!infoItemName.equals(oldName))
                  continue;
                else { // found it!
                  foundIt = true;
                            openRedefinedSchema(child, currSchema);
                            if(!fRedefineSucceeded)
                                return;
                            if (validateRedefineNameChange(eltLocalname, oldName, newName+redefIdentifier, redefChild) &&
                                    (currSchema.getNext() != null))
                              fixRedefinedSchema(eltLocalname, oldName, newName+redefIdentifier, fSchemaRootElement, currSchema.getNext());
                        redefChild.setAttribute( SchemaSymbols.ATT_NAME, newName );
                            // and we now know we will traverse this, so set fTraversedRedefineElements appropriately...
                            fTraversedRedefineElements.addElement(newName);
                            currSchema.restore();
                            fCurrentSchemaInfo = currSchema;
                            break;
                }
              }
            } //for
                if (foundIt) break;
            }
            else if (name.equals(eltLocalname) ) {
              String infoItemName = child.getAttribute( SchemaSymbols.ATT_NAME );
        if(!infoItemName.equals(oldName))
          continue;
        else { // found it!
          foundIt = true;
                child.setAttribute( SchemaSymbols.ATT_NAME, newName );
                    break;
        }
      }
    } //for
    if(!foundIt) {
            fRedefineSucceeded = false;
            // REVISIT: localize
            reportGenericSchemaError("could not find a declaration in the schema to be redefined corresponding to " + oldName);
        }
  } // end fixRedefinedSchema

    // this method returns true if the redefine component is valid, and if
    // it was possible to revise it correctly.  The definition of
    // correctly will depend on whether renameRedefineDecls
    // or fixRedefineSchema is the caller.
    // this method also prepends a prefix onto newName if necessary; newName will never contain one.
    private boolean validateRedefineNameChange(String eltLocalname, String oldName, String newName, Element child) throws Exception {
        if (eltLocalname.equals(SchemaSymbols.ELT_SIMPLETYPE)) {
      QName processedTypeName = new QName(-1, fStringPool.addSymbol(oldName), fStringPool.addSymbol(oldName), fTargetNSURI);
      Element grandKid = XUtil.getFirstChildElement(child);
      if (grandKid == null) {
                fRedefineSucceeded = false;
              // REVISIT: Localize
              reportGenericSchemaError("a simpleType child of a <redefine> must have a restriction element as a child");
            } else {
                String grandKidName = grandKid.getLocalName();
        if(grandKidName.equals(SchemaSymbols.ELT_ANNOTATION)) {
            grandKid = XUtil.getNextSiblingElement(grandKid);
                     grandKidName = grandKid.getLocalName();
                }
          if (grandKid == null) {
                    fRedefineSucceeded = false;
                  // REVISIT: Localize
                  reportGenericSchemaError("a simpleType child of a <redefine> must have a restriction element as a child");
                } else if(!grandKidName.equals(SchemaSymbols.ELT_RESTRICTION)) {
                    fRedefineSucceeded = false;
                // REVISIT: Localize
                reportGenericSchemaError("a simpleType child of a <redefine> must have a restriction element as a child");
                } else {
                String derivedBase = grandKid.getAttribute( SchemaSymbols.ATT_BASE );
          QName processedDerivedBase = parseBase(derivedBase);
          if(!processedTypeName.equals(processedDerivedBase)) {
                        fRedefineSucceeded = false;
                  // REVISIT: Localize
                  reportGenericSchemaError("the base attribute of the restriction child of a simpleType child of a redefine must have the same value as the simpleType's type attribute");
                    } else {
            // now we have to do the renaming...
                        String prefix = "";
                        int colonptr = derivedBase.indexOf(":");
                        if ( colonptr > 0)
                            prefix = derivedBase.substring(0,colonptr) + ":";
                  grandKid.setAttribute( SchemaSymbols.ATT_BASE, prefix + newName );
                        return true;
          }
        }
      }
    } else if (eltLocalname.equals(SchemaSymbols.ELT_COMPLEXTYPE)) {
      QName processedTypeName = new QName(-1, fStringPool.addSymbol(oldName), fStringPool.addSymbol(oldName), fTargetNSURI);
      Element grandKid = XUtil.getFirstChildElement(child);
      if (grandKid == null) {
                fRedefineSucceeded = false;
               // REVISIT: Localize
               reportGenericSchemaError("a complexType child of a <redefine> must have a restriction or extension element as a grandchild");
            } else {
                if(grandKid.getLocalName().equals(SchemaSymbols.ELT_ANNOTATION)) {
                grandKid = XUtil.getNextSiblingElement(grandKid);
                }
            if (grandKid == null) {
                    fRedefineSucceeded = false;
                  // REVISIT: Localize
                  reportGenericSchemaError("a complexType child of a <redefine> must have a restriction or extension element as a grandchild");
                } else {
            // have to go one more level down; let another pass worry whether complexType is valid.
            Element greatGrandKid = XUtil.getFirstChildElement(grandKid);
            if (greatGrandKid == null) {
                        fRedefineSucceeded = false;
                    // REVISIT: Localize
                    reportGenericSchemaError("a complexType child of a <redefine> must have a restriction or extension element as a grandchild");
                    } else {
                    String greatGrandKidName = greatGrandKid.getLocalName();
                if(greatGrandKidName.equals(SchemaSymbols.ELT_ANNOTATION)) {
                      greatGrandKid = XUtil.getNextSiblingElement(greatGrandKid);
                            greatGrandKidName = greatGrandKid.getLocalName();
                        }
                  if (greatGrandKid == null) {
                            fRedefineSucceeded = false;
                            // REVISIT: Localize
                          reportGenericSchemaError("a complexType child of a <redefine> must have a restriction or extension element as a grandchild");
              } else if(!greatGrandKidName.equals(SchemaSymbols.ELT_RESTRICTION) &&
                  !greatGrandKidName.equals(SchemaSymbols.ELT_EXTENSION)) {
                            fRedefineSucceeded = false;
                      // REVISIT: Localize
                      reportGenericSchemaError("a complexType child of a <redefine> must have a restriction or extension element as a grandchild");
              } else {
                      String derivedBase = greatGrandKid.getAttribute( SchemaSymbols.ATT_BASE );
                QName processedDerivedBase = parseBase(derivedBase);
                if(!processedTypeName.equals(processedDerivedBase)) {
                                fRedefineSucceeded = false;
                        // REVISIT: Localize
                        reportGenericSchemaError("the base attribute of the restriction or extension grandchild of a complexType child of a redefine must have the same value as the complexType's type attribute");
                } else {
                  // now we have to do the renaming...
                                String prefix = "";
                                int colonptr = derivedBase.indexOf(":");
                                if ( colonptr > 0)
                                    prefix = derivedBase.substring(0,colonptr) + ":";
                        greatGrandKid.setAttribute( SchemaSymbols.ATT_BASE, prefix + newName );
                                return true;
                }
                        }
          }
        }
      }
        } else if (eltLocalname.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) {
      QName processedBaseName = new QName(-1, fStringPool.addSymbol(oldName), fStringPool.addSymbol(oldName), fTargetNSURI);
      int attGroupRefsCount = changeRedefineGroup(processedBaseName, eltLocalname, newName, child);
      if(attGroupRefsCount > 1) {
                fRedefineSucceeded = false;
        // REVISIT:  localize
        reportGenericSchemaError("if an attributeGroup child of a <redefine> element contains an attributeGroup ref'ing itself, it must have exactly 1; this one has " + attGroupRefsCount);
      } else if (attGroupRefsCount == 1) {
                return true;
      else
        // REVISIT:  localize and for PR:
        reportGenericSchemaError("an attributeGroup in a <redefine> must have exactly one ref attribute to itself in schema CR");
        } else if (eltLocalname.equals(SchemaSymbols.ELT_GROUP)) {
      QName processedBaseName = new QName(-1, fStringPool.addSymbol(oldName), fStringPool.addSymbol(oldName), fTargetNSURI);
      int groupRefsCount = changeRedefineGroup(processedBaseName, eltLocalname, newName, child);
      if(groupRefsCount > 1) {
                fRedefineSucceeded = false;
        // REVISIT:  localize
        reportGenericSchemaError("if a group child of a <redefine> element contains a group ref'ing itself, it must have exactly 1; this one has " + groupRefsCount);
      } else if (groupRefsCount == 1) {
                return true;
      else
        // REVISIT:  localize and for PR:
        reportGenericSchemaError("a group in a <redefine> must have exactly one ref attribute to itself in schema CR");
    } else {
            fRedefineSucceeded = false;
             // REVISIT: Localize
             reportGenericSchemaError("internal Xerces error; please submit a bug with schema as testcase");
    }
        // if we get here then we must have reported an error and failed somewhere...
        return false;
    } // validateRedefineNameChange

    private void traverseImport(Element importDeclthrows Exception {
        String location = importDecl.getAttribute(SchemaSymbols.ATT_SCHEMALOCATION);
        // expand it before passing it to the parser
        InputSource source = null;
        if (fEntityResolver != null) {
            source = fEntityResolver.resolveEntity("", location);
        }
        if (source == null) {
            location = expandSystemId(location, fCurrentSchemaURL);
            source = new InputSource(location);
        }
         else {
             // create a string for uniqueness of this imported schema in fImportLocations
             if (source.getPublicId () != null)
                 location = source.getPublicId ();

             location += (',' + source.getSystemId ());
         }

         if (fImportLocations.contains((Object)location)) {
             return;
         }
         fImportLocations.addElement((Object)location);

         String namespaceString = importDecl.getAttribute(SchemaSymbols.ATT_NAMESPACE);
         SchemaGrammar importedGrammar = (SchemaGrammar) fGrammarResolver.getGrammar(namespaceString);

         if (importedGrammar == null) {
             importedGrammar = new SchemaGrammar();
         }

         DOMParser parser = new IgnoreWhitespaceParser();
         parser.setEntityResolver( new Resolver() );
         parser.setErrorHandlernew ErrorHandler() );

         try {
             parser.setFeature("http://xml.org/sax/features/validation", false);
             parser.setFeature("http://xml.org/sax/features/namespaces", true);
             parser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", false);
         }catchorg.xml.sax.SAXNotRecognizedException e ) {
             e.printStackTrace();
         }catch( org.xml.sax.SAXNotSupportedException e ) {
             e.printStackTrace();
         }

         try {
             parser.parse( source );
         }catch( IOException e ) {
             e.printStackTrace();
         }catch( SAXException e ) {
             e.printStackTrace();
         }

         Document     document   = parser.getDocument(); //Our Grammar
         Element root = null;
         if (document != null) {
             root = document.getDocumentElement();
         }

         if (root != null) {
             String targetNSURI = root.getAttribute(SchemaSymbols.ATT_TARGETNAMESPACE);
             if (!targetNSURI.equals(namespaceString) ) {
                 // REVISIT: Localize
                 reportGenericSchemaError("imported schema '"+location+"' has a different targetNameSpace '"
                                          +targetNSURI+"' from what is declared '"+namespaceString+"'.");
             }
             else
                 new TraverseSchema(root, fStringPool, importedGrammar, fGrammarResolver, fErrorReporter, location, fEntityResolver);
         }
         else {
             reportGenericSchemaError("Could not get the doc root for imported Schema file: "+location);
         }
    }

    /**
    * <annotation>(<appinfo> | <documentation>)*</annotation>
    *
    * @param annotationDecl:  the DOM node corresponding to the <annotation> info item
    */
    private void traverseAnnotationDecl(Element annotationDecl) throws Exception {

        for(Element child = XUtil.getFirstChildElement(annotationDecl); child != null;
                 child = XUtil.getNextSiblingElement(child)) {
            String name = child.getLocalName();
            if(!((name.equals(SchemaSymbols.ELT_APPINFO)) ||
                    (name.equals(SchemaSymbols.ELT_DOCUMENTATION)))) {
                // REVISIT: Localize
                reportGenericSchemaError("an <annotation> can only contain <appinfo> and <documentation> elements");
            }
        }
    }

    //@param: elm - top element
    //@param: content - content must be annotation? or some other simple content
    //@param: isEmpty: -- true if (annotation?, smth_else), false if (annotation?)
    //check for Annotation if it is present
    //REVISIT: this function should be used in all traverse* methods!
   private Element checkContent( Element elm, Element content, boolean isEmpty ) throws Exception {
       //isEmpty = true-> means content can be null!
       if ( content == null) {
           if (!isEmpty) {
               reportSchemaError(SchemaMessageProvider.ContentError,
                                 new Object [] { elm.getAttribute( SchemaSymbols.ATT_NAME )});
           }
           return null;
       }
       if (content.getLocalName().equals(SchemaSymbols.ELT_ANNOTATION)) {
       traverseAnnotationDecl( content );  
       content = XUtil.getNextSiblingElement(content);
       if (content == null ) {   //must be followed by <simpleType?>
         if (!isEmpty) {
           reportSchemaError(SchemaMessageProvider.ContentError,
                   new Object [] { elm.getAttribute( SchemaSymbols.ATT_NAME )});
         }
         return null;
       }
       if (content.getLocalName().equals(SchemaSymbols.ELT_ANNOTATION)) {
         reportSchemaError(SchemaMessageProvider.AnnotationError,
                 new Object [] { elm.getAttribute( SchemaSymbols.ATT_NAME )});
         return null;
       }
       //return null if expected only annotation?, else returns updated content
     }
       return content; 
   }

  
   //@param: elm - top element
   //@param: baseTypeStr - type (base/itemType/memberTypes)
   //return DatatypeValidator available for the baseTypeStr.
   //REVISIT: this function should be used in some|all traverse* methods!
   private DatatypeValidator findDTValidator (Element elm, String baseTypeStr throws Exception{
            int baseType      = fStringPool.addSymbol( baseTypeStr );
            String prefix = "";
            DatatypeValidator baseValidator = null;
            String localpart = baseTypeStr;
            int colonptr = baseTypeStr.indexOf(":");
            if ( colonptr > 0) {
                prefix = baseTypeStr.substring(0,colonptr);
                localpart = baseTypeStr.substring(colonptr+1);
            }
            String uri = resolvePrefixToURI(prefix);
            baseValidator = getDatatypeValidator(uri, localpart);
            if (baseValidator == null) {
                Element baseTypeNode = getTopLevelComponentByName(SchemaSymbols.ELT_SIMPLETYPE, localpart);
                if (baseTypeNode != null) {
                    traverseSimpleTypeDecl( baseTypeNode );
                   
                    baseValidator = getDatatypeValidator(uri, localpart);
                }
            }
            if ( baseValidator == null ) {
                reportSchemaError(SchemaMessageProvider.UnknownBaseDatatype,
                                  new Object [] { elm.getAttribute( SchemaSymbols.ATT_BASE ),
                                      elm.getAttribute(SchemaSymbols.ATT_NAME)});
            }
       return baseValidator;
    }

   /**
     * Traverse SimpleType declaration:
     * <simpleType
     *         id = ID
     *         name = NCName>
     *         Content: (annotation? , ((list | restriction | union)))
     *       </simpleType>
     * traverse <list>|<restriction>|<union>
     *
     * @param simpleTypeDecl
     * @return
     */
    private int traverseSimpleTypeDecl( Element simpleTypeDecl ) throws Exception {
       
        //REVISIT: remove all DEBUG_UNION.
       
        String nameProperty          =  simpleTypeDecl.getAttribute( SchemaSymbols.ATT_NAME );
       
        String qualifiedName = nameProperty;
        if (fTargetNSURIString.length () != 0) {
            qualifiedName = fTargetNSURIString+","+nameProperty;
        }
        //check if we have already traversed the same simpleType decl
        if (fDatatypeRegistry.getDatatypeValidator(qualifiedName)!=null) {
            return fStringPool.addSymbol(qualifiedName);
        }
       
       
        boolean list = false;
        boolean union = false;
        boolean restriction = false;
        int     newSimpleTypeName    = -1;
        if ( nameProperty.equals("")) { // anonymous simpleType
            newSimpleTypeName = fStringPool.addSymbol(
                "#S#"+fSimpleTypeAnonCount++ );  
        }
        else
            newSimpleTypeName       = fStringPool.addSymbol( nameProperty );



        //annotation?,(list|restriction|union)
        Element content = XUtil.getFirstChildElement(simpleTypeDecl);
        content = checkContent(simpleTypeDecl, content, false);
        if (content == null) {
            return (-1);
        }
        //use content.getLocalName for the cases there "xsd:" is a prefix, ei. "xsd:list"
        String varietyProperty = content.getLocalName();
        String baseTypeQNameProperty = null;
        Vector dTValidators = null;
        int size = 0
        StringTokenizer unionMembers = null;
        int numOfTypes = 0; //list/restriction = 1, union = "+"
       
        if (DEBUG_UNION) {
            System.out.println("[varietyProperty]:"+   varietyProperty );
        }

        if (varietyProperty.equals(SchemaSymbols.ELT_LIST)) { //traverse List
           baseTypeQNameProperty =  content.getAttribute( SchemaSymbols.ATT_ITEMTYPE );
           list = true;
        }
        else if (varietyProperty.equals(SchemaSymbols.ELT_RESTRICTION)) { //traverse Restriction
            baseTypeQNameProperty =  content.getAttribute( SchemaSymbols.ATT_BASE );
            restriction= true;
        }
        else if (varietyProperty.equals(SchemaSymbols.ELT_UNION)) { //traverse union
            union = true;
            baseTypeQNameProperty = content.getAttribute( SchemaSymbols.ATT_MEMBERTYPES);
            if (!baseTypeQNameProperty.equals("")) {
                unionMembers = new StringTokenizer( baseTypeQNameProperty );
                size = unionMembers.countTokens();
            }
            else {
                size = 1; //at least one must be seen as <simpleType> decl
            }
            dTValidators = new Vector (size, 2);
        }
        else {
             reportSchemaError(SchemaMessageProvider.FeatureUnsupported,
                       new Object [] { varietyProperty });
                       return -1;
        }
        if(XUtil.getNextSiblingElement(content) != null) {
            // REVISIT: Localize
            reportGenericSchemaError("error in content of simpleType");
        }

        int typeNameIndex;
        DatatypeValidator baseValidator = null;
       
        if (DEBUG_UNION) {
            System.out.println("[nameProperty]= " +nameProperty);
            System.out.println("[base]= " +baseTypeQNameProperty+";");
            System.out.println("[size]= " +size);
            if (unionMembers!=null) {
                System.out.println("[unionMembers]= " +unionMembers.toString());
            }
        }
        if ( baseTypeQNameProperty.equals("") ) { //must 'see' <simpleType>
            //content = {annotation?,simpleType?...}
            content = XUtil.getFirstChildElement(content);
            //check content (annotation?, ...)
            content = checkContent(simpleTypeDecl, content, false);
            if (content == null) {
                return (-1);
            }
            if (content.getLocalName().equals( SchemaSymbols.ELT_SIMPLETYPE )) {  //Test...
              typeNameIndex = traverseSimpleTypeDecl(content);
              if (DEBUG_UNION) {
                System.out.println("[After traverseSimpleTypeDecl]: " +fStringPool.toString(typeNameIndex));
                System.out.println("[traverseSimpleTypeDecl]: " +  nameProperty)
              }
              if (typeNameIndex!=-1) {
                  baseValidator=fDatatypeRegistry.getDatatypeValidator(fStringPool.toString(typeNameIndex));
                  if (baseValidator !=null && union) { 
                      dTValidators.addElement((DatatypeValidator)baseValidator);
                  }
              }
              if ( typeNameIndex == -1 || baseValidator == null) {
                  reportSchemaError(SchemaMessageProvider.UnknownBaseDatatype,
                                        new Object [] { content.getAttribute( SchemaSymbols.ATT_BASE ),
                                            content.getAttribute(SchemaSymbols.ATT_NAME) });
                      return -1;
              }
            }
            else {
                 reportSchemaError(SchemaMessageProvider.ListUnionRestrictionError,
                        new Object [] { simpleTypeDecl.getAttribute( SchemaSymbols.ATT_NAME )});
                 return -1;
            }
        } //end - must see simpleType?
        else { //base was provided - get proper validator.
            numOfTypes = 1;
            if (union) {
                numOfTypes= size;
            }
            for (int i=0; i<numOfTypes; i++) {  //find all validators
                if (union) {
                    baseTypeQNameProperty = unionMembers.nextToken();
                }
                baseValidator = findDTValidator ( simpleTypeDecl, baseTypeQNameProperty);
                if ( baseValidator == null) {
                    return (-1);
                }
                if (union) {
                    dTValidators.addElement((DatatypeValidator)baseValidator); //add validator to structure
                }
                //REVISIT: Should we raise exception here?
                // if baseValidator.isInstanceOf(LIST) and UNION
                if ( list && (baseValidator instanceof UnionDatatypeValidator)) {
                    reportSchemaError(SchemaMessageProvider.UnknownBaseDatatype,
                                      new Object [] { simpleTypeDecl.getAttribute( SchemaSymbols.ATT_BASE ),
                                          simpleTypeDecl.getAttribute(SchemaSymbols.ATT_NAME)});
                    return -1;
                }
            }
        } //end - base is available
       
        // move to next child
        // restriction ->[simpleType]->[facets]  OR
        // restriction ->[facets]
        if (baseTypeQNameProperty.equals ("")) {  //we already got the first kid of union/list/restriction
            content = XUtil.getNextSiblingElement( content );
        }
        else { //we need to look at first kid of union/list/restriction
            content = XUtil.getFirstChildElement(content);
        }
       
        //get more types for union if any
        if (union) {
            int index=size;
            if (!baseTypeQNameProperty.equals ("")) {
                content = checkContent(simpleTypeDecl, content, true);
            }
            while (content!=null) {
                if (DEBUG_UNION) {
                    System.out.println("[start Union types traversal] + " + content.getNodeName());
                    System.out.println(index+"-Getting all other simpletypes");
                    System.out.println("content: " + content.getNodeName());
                }
                typeNameIndex = traverseSimpleTypeDecl(content);  
                if (typeNameIndex!=-1) {
                    baseValidator=fDatatypeRegistry.getDatatypeValidator(fStringPool.toString(typeNameIndex));
                    if (baseValidator != null) {
                        if (DEBUG_UNION) {
                            System.out.println("validator to add: " + baseValidator.toString());
                        }
                        dTValidators.addElement((DatatypeValidator)baseValidator);
                    }
                }
                if ( baseValidator == null || typeNameIndex == -1) {
                     reportSchemaError(SchemaMessageProvider.UnknownBaseDatatype,
                                      new Object [] { simpleTypeDecl.getAttribute( SchemaSymbols.ATT_BASE ),
                                          simpleTypeDecl.getAttribute(SchemaSymbols.ATT_NAME)});
                    return (-1);
                }
                content   = XUtil.getNextSiblingElement( content );
            }
        } // end - traverse Union
       
       
        Hashtable facetData =null;
        int numFacets=0;
        facetData        = new Hashtable();
        if (restriction && content != null) {
            int numEnumerationLiterals = 0;
            Vector enumData  = new Vector();
            content = checkContent(simpleTypeDecl, content , true);
            StringBuffer pattern = null;
            String facet;
            while (content != null) {
                if (content.getNodeType() == Node.ELEMENT_NODE) {
                        numFacets++;
                        facet =content.getLocalName();
                        if (facet.equals(SchemaSymbols.ELT_ENUMERATION)) {
                            numEnumerationLiterals++;
                            String enumVal = content.getAttribute(SchemaSymbols.ATT_VALUE);
                            String localName;
                            if (baseValidator instanceof NOTATIONDatatypeValidator) {
                                String prefix = "";
                                String localpart = enumVal;
                                int colonptr = enumVal.indexOf(":");
                                if ( colonptr > 0) {
                                        prefix = enumVal.substring(0,colonptr);
                                        localpart = enumVal.substring(colonptr+1);
                                }
                                String uriStr = (!prefix.equals(""))?resolvePrefixToURI(prefix):fTargetNSURIString;
                                qualifiedName=uriStr + ":" + localpart;
                                localName = (String)fNotationRegistry.get(qualifiedName);
                                if(localName == null){
                                       localName = traverseNotationFromAnotherSchema( localpart, uriStr);
                                       if (localName == null) {
                                            reportGenericSchemaError("Notation '" + localpart +
                                                                    "' not found in the grammar "+ uriStr);
                                                                   
                                       }
                                }
                                if (DEBUGGING) {
                                    System.out.println("[notation decl] fullName: = " + qualifiedName);
                                    System.out.println("[notation decl] enum value: =" +enumVal);
                                }
                                enumVal=qualifiedName;
                            }
                            enumData.addElement(enumVal);
                            checkContent(simpleTypeDecl, XUtil.getFirstChildElement( content ), true);
                        }
                        else if (facet.equals(SchemaSymbols.ELT_ANNOTATION)) {
                                  reportSchemaError(SchemaMessageProvider.ContentError,
                                                    new Object [] { simpleTypeDecl.getAttribute( SchemaSymbols.ATT_NAME )});
                        }
                        else if (facet.equals(SchemaSymbols.ELT_PATTERN)) {
                            if (pattern == null) {                               
                                pattern = new StringBuffer (content.getAttribute( SchemaSymbols.ATT_VALUE ));
                            }
                            else { //datatypes: 5.2.4 pattern
                                pattern.append("|");
                                pattern.append(content.getAttribute( SchemaSymbols.ATT_VALUE ));
                                checkContent(simpleTypeDecl, XUtil.getFirstChildElement( content ), true);
                            }
                        }
                        else {
                             facetData.put(facet,content.getAttribute( SchemaSymbols.ATT_VALUE ));
                             checkContent(simpleTypeDecl, XUtil.getFirstChildElement( content ), true);
                        }
                }
                    content = XUtil.getNextSiblingElement(content);
            }
            if (numEnumerationLiterals > 0) {
                  facetData.put(SchemaSymbols.ELT_ENUMERATION, enumData);
            }
            if (pattern !=null) {
                facetData.put(SchemaSymbols.ELT_PATTERN, pattern.toString());
            }
        }

       
        else if (list && content!=null) { // report error - must not have any children!
            if (!baseTypeQNameProperty.equals("")) {
                content = checkContent(simpleTypeDecl, content, true);
            }
            else {
                reportSchemaError(SchemaMessageProvider.ListUnionRestrictionError,
                        new Object [] { simpleTypeDecl.getAttribute( SchemaSymbols.ATT_NAME )});
                //REVISIT: should we return?
            }
        }
        else if (union && content!=null) { //report error - must not have any children!
             if (!baseTypeQNameProperty.equals("")) {
                content = checkContent(simpleTypeDecl, content, true);
            }
            else {
                reportSchemaError(SchemaMessageProvider.ListUnionRestrictionError,
                        new Object [] { simpleTypeDecl.getAttribute( SchemaSymbols.ATT_NAME )});
                //REVISIT: should we return?
            }
        }

        // create & register validator for "generated" type if it doesn't exist

        qualifiedName = fStringPool.toString(newSimpleTypeName);
        if (fTargetNSURIString.length () != 0) {
            qualifiedName = fTargetNSURIString+","+qualifiedName;
        }
        try {
           DatatypeValidator newValidator =
                 fDatatypeRegistry.getDatatypeValidator( qualifiedName );

           if( newValidator == null ) { // not previously registered
               if (list) {
                    fDatatypeRegistry.createDatatypeValidator( qualifiedName, baseValidator,
                                                               facetData,true);
               }
               else if (restriction) {
                   fDatatypeRegistry.createDatatypeValidator( qualifiedName, baseValidator,
                                                               facetData,false);
               }
               else { //union
                   fDatatypeRegistry.createDatatypeValidator( qualifiedName, dTValidators);
               }
                          
           }
           
           } catch (Exception e) {
               reportSchemaError(SchemaMessageProvider.DatatypeError,new Object [] { e.getMessage() });
           }
        return fStringPool.addSymbol(qualifiedName);
     }


    /*
    * <any
    *   id = ID
    *   maxOccurs = string
    *   minOccurs = nonNegativeInteger
    *   namespace = ##any | ##other | ##local | list of {uri, ##targetNamespace}
    *   processContents = lax | skip | strict>
    *   Content: (annotation?)
    * </any>
    */
    private int traverseAny(Element child) throws Exception {
        Element annotation = checkContent( child, XUtil.getFirstChildElement(child), true );
        if(annotation != null ) {
            // REVISIT: Localize
            reportGenericSchemaError("<any> elements can contain at most one <annotation> element in their children");
        }
        int anyIndex = -1;
        String namespace = child.getAttribute(SchemaSymbols.ATT_NAMESPACE).trim();
        String processContents = child.getAttribute("processContents").trim();

        int processContentsAny = XMLContentSpec.CONTENTSPECNODE_ANY;
        int processContentsAnyOther = XMLContentSpec.CONTENTSPECNODE_ANY_OTHER;
        int processContentsAnyLocal = XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL;

        if (processContents.length() > 0 && !processContents.equals("strict")) {
            if (processContents.equals("lax")) {
                processContentsAny = XMLContentSpec.CONTENTSPECNODE_ANY_LAX;
                processContentsAnyOther = XMLContentSpec.CONTENTSPECNODE_ANY_OTHER_LAX;
                processContentsAnyLocal = XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL_LAX;
            }
            else if (processContents.equals("skip")) {
                processContentsAny = XMLContentSpec.CONTENTSPECNODE_ANY_SKIP;
                processContentsAnyOther = XMLContentSpec.CONTENTSPECNODE_ANY_OTHER_SKIP;
                processContentsAnyLocal = XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL_SKIP;
            }
        }

        if (namespace.length() == 0 || namespace.equals("##any")) {
            // REVISIT: Should the "any" namespace signifier also be changed
            //          to StringPool.EMPTY_STRING instead of -1? -Ac
            // REVISIT: is this the right way to do it? EMPTY_STRING does not
            //          seem to work in this case -el
      // Simplify! - ng
            //String uri = child.getOwnerDocument().getDocumentElement().getAttribute("targetNamespace");
      String uri = fTargetNSURIString;
      int uriIndex = fStringPool.addSymbol(uri);
            anyIndex = fSchemaGrammar.addContentSpecNode(processContentsAny, -1, uriIndex, false);
        }
        else if (namespace.equals("##other")) {
      String uri = fTargetNSURIString;
            int uriIndex = fStringPool.addSymbol(uri);
            anyIndex = fSchemaGrammar.addContentSpecNode(processContentsAnyOther, -1, uriIndex, false);
        }
        else if (namespace.equals("##local")) {
            anyIndex = fSchemaGrammar.addContentSpecNode(processContentsAnyLocal, -1, StringPool.EMPTY_STRING, false);
        }
        else if (namespace.length() > 0) {
            StringTokenizer tokenizer = new StringTokenizer(namespace);
            Vector tokens = new Vector();
            while (tokenizer.hasMoreElements()) {
                String token = tokenizer.nextToken();
                if (token.equals("##targetNamespace")) {
              token = fTargetNSURIString;
                }
                tokens.addElement(token);
            }
            String uri = (String)tokens.elementAt(0);
            int uriIndex = fStringPool.addSymbol(uri);
            int leafIndex = fSchemaGrammar.addContentSpecNode(processContentsAny, -1, uriIndex, false);
            int valueIndex = leafIndex;
            int count = tokens.size();
            if (count > 1) {
                uri = (String)tokens.elementAt(1);
                uriIndex = fStringPool.addSymbol(uri);
                leafIndex = fSchemaGrammar.addContentSpecNode(processContentsAny, -1, uriIndex, false);
                int otherValueIndex = leafIndex;
                int choiceIndex = fSchemaGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_CHOICE, valueIndex, otherValueIndex, false);
                for (int i = 2; i < count; i++) {
                    uri = (String)tokens.elementAt(i);
                    uriIndex = fStringPool.addSymbol(uri);
                    leafIndex = fSchemaGrammar.addContentSpecNode(processContentsAny, -1, uriIndex, false);
                    otherValueIndex = leafIndex;
                    choiceIndex = fSchemaGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_CHOICE, choiceIndex, otherValueIndex, false);
                }
                anyIndex = choiceIndex;
            }
            else {
                anyIndex = leafIndex;
            }
        }
        else {
            // REVISIT: Localize
            reportGenericSchemaError("Empty namespace attribute for any element");
        }

        return anyIndex;
    }


    public DatatypeValidator getDatatypeValidator(String uri, String localpart) {

        DatatypeValidator dv = null;

        if (uri.length()==0 || uri.equals(SchemaSymbols.URI_SCHEMAFORSCHEMA)) {
            dv = fDatatypeRegistry.getDatatypeValidator( localpart );
        }
        else {
            dv = fDatatypeRegistry.getDatatypeValidator( uri+","+localpart );
        }

        return dv;
    }

    /*
    * <anyAttribute
    *   id = ID
    *   namespace = ##any | ##other | ##local | list of {uri, ##targetNamespace}>
    *   Content: (annotation?)
    * </anyAttribute>
    */
    private XMLAttributeDecl traverseAnyAttribute(Element anyAttributeDecl) throws Exception {
        Element annotation = checkContent( anyAttributeDecl, XUtil.getFirstChildElement(anyAttributeDecl), true );
        if(annotation != null ) {
            // REVISIT: Localize
            reportGenericSchemaError("<anyAttribute> elements can contain at most one <annotation> element in their children");
        }
        XMLAttributeDecl anyAttDecl = new XMLAttributeDecl();
        String processContents = anyAttributeDecl.getAttribute(SchemaSymbols.ATT_PROCESSCONTENTS).trim();
        String namespace = anyAttributeDecl.getAttribute(SchemaSymbols.ATT_NAMESPACE).trim();
        // simplify!  NG
        //String curTargetUri = anyAttributeDecl.getOwnerDocument().getDocumentElement().getAttribute("targetNamespace");
        String curTargetUri = fTargetNSURIString;

        if ( namespace.length() == 0 || namespace.equals(SchemaSymbols.ATTVAL_TWOPOUNDANY) ) {
            anyAttDecl.type = XMLAttributeDecl.TYPE_ANY_ANY;
        }
        else if (namespace.equals(SchemaSymbols.ATTVAL_TWOPOUNDOTHER)) {
            anyAttDecl.type = XMLAttributeDecl.TYPE_ANY_OTHER;
            anyAttDecl.name.uri = fStringPool.addSymbol(curTargetUri);
        }
        else if (namespace.equals(SchemaSymbols.ATTVAL_TWOPOUNDLOCAL)) {
            anyAttDecl.type = XMLAttributeDecl.TYPE_ANY_LOCAL;
        }
        else if (namespace.length() > 0){
            anyAttDecl.type = XMLAttributeDecl.TYPE_ANY_LIST;

            StringTokenizer tokenizer = new StringTokenizer(namespace);
            int aStringList = fStringPool.startStringList();
            Vector tokens = new Vector();
            while (tokenizer.hasMoreElements()) {
                String token = tokenizer.nextToken();
                if (token.equals("##targetNamespace")) {
                    token = curTargetUri;
                }
                if (!fStringPool.addStringToList(aStringList, fStringPool.addSymbol(token))){
                    reportGenericSchemaError("Internal StringPool error when reading the "+
                                             "namespace attribute for anyattribute declaration");
                }
            }
            fStringPool.finishStringList(aStringList);

            anyAttDecl.enumeration = aStringList;
        }
        else {
            // REVISIT: Localize
            reportGenericSchemaError("Empty namespace attribute for anyattribute declaration");
        }

        // default processContents is "strict";
        anyAttDecl.defaultType = XMLAttributeDecl.PROCESSCONTENTS_STRICT;

        if (processContents.equals(SchemaSymbols.ATTVAL_SKIP)){
            anyAttDecl.defaultType = XMLAttributeDecl.PROCESSCONTENTS_SKIP;
        }
        else if (processContents.equals(SchemaSymbols.ATTVAL_LAX)) {
            anyAttDecl.defaultType = XMLAttributeDecl.PROCESSCONTENTS_LAX;
        }

        return anyAttDecl;
    }

    private XMLAttributeDecl mergeTwoAnyAttribute(XMLAttributeDecl oneAny, XMLAttributeDecl anotherAny) {
        if (oneAny.type == -1) {
            return oneAny;
        }
        if (anotherAny.type == -1) {
            return anotherAny;
        }

        if (oneAny.type == XMLAttributeDecl.TYPE_ANY_ANY) {
            return anotherAny;
        }

        if (anotherAny.type == XMLAttributeDecl.TYPE_ANY_ANY) {
            return oneAny;
        }

        if (oneAny.type == XMLAttributeDecl.TYPE_ANY_OTHER) {
            if (anotherAny.type == XMLAttributeDecl.TYPE_ANY_OTHER) {

                if ( anotherAny.name.uri == oneAny.name.uri ) {
                    return oneAny;
                }
                else {
                    oneAny.type = -1;
                    return oneAny;
                }

            }
            else if (anotherAny.type == XMLAttributeDecl.TYPE_ANY_LOCAL) {
                return anotherAny;
            }
            else if (anotherAny.type == XMLAttributeDecl.TYPE_ANY_LIST) {
                if (!fStringPool.stringInList(anotherAny.enumeration, oneAny.name.uri) ) {
                    return anotherAny;
                }
                else {
                    int[] anotherAnyURIs = fStringPool.stringListAsIntArray(anotherAny.enumeration);
                    int newList = fStringPool.startStringList();
                    for (int i=0; i< anotherAnyURIs.length; i++) {
                        if (anotherAnyURIs[i] != oneAny.name.uri ) {
                            fStringPool.addStringToList(newList, anotherAnyURIs[i]);
                        }
                    }
                    fStringPool.finishStringList(newList);
                    anotherAny.enumeration = newList;
                    return anotherAny;
                }
            }
        }

        if (oneAny.type == XMLAttributeDecl.TYPE_ANY_LOCAL) {
            if ( anotherAny.type == XMLAttributeDecl.TYPE_ANY_OTHER
                || anotherAny.type == XMLAttributeDecl.TYPE_ANY_LOCAL) {
                return oneAny;
            }
            else if (anotherAny.type == XMLAttributeDecl.TYPE_ANY_LIST) {
                oneAny.type = -1;
                return oneAny;
            }
        }

        if (oneAny.type == XMLAttributeDecl.TYPE_ANY_LIST) {
            if ( anotherAny.type == XMLAttributeDecl.TYPE_ANY_OTHER){
                if (!fStringPool.stringInList(oneAny.enumeration, anotherAny.name.uri) ) {
                    return oneAny;
                }
                else {
                    int[] oneAnyURIs = fStringPool.stringListAsIntArray(oneAny.enumeration);
                    int newList = fStringPool.startStringList();
                    for (int i=0; i< oneAnyURIs.length; i++) {
                        if (oneAnyURIs[i] != anotherAny.name.uri ) {
                            fStringPool.addStringToList(newList, oneAnyURIs[i]);
                        }
                    }
                    fStringPool.finishStringList(newList);
                    oneAny.enumeration = newList;
                    return oneAny;
                }

            }
            else if ( anotherAny.type == XMLAttributeDecl.TYPE_ANY_LOCAL) {
                oneAny.type = -1;
                return oneAny;
            }
            else if (anotherAny.type == XMLAttributeDecl.TYPE_ANY_LIST) {
                int[] result = intersect2sets( fStringPool.stringListAsIntArray(oneAny.enumeration),
                                               fStringPool.stringListAsIntArray(anotherAny.enumeration));
                int newList = fStringPool.startStringList();
                for (int i=0; i<result.length; i++) {
                    fStringPool.addStringToList(newList, result[i]);
                }
                fStringPool.finishStringList(newList);
                oneAny.enumeration = newList;
                return oneAny;
            }
        }

        // should never go there;
        return oneAny;
    }

    int[] intersect2sets(int[] one, int[] theOther){
        int[] result = new int[(one.length>theOther.length?one.length:theOther.length)];

        // simple implemention,
        int count = 0;
        for (int i=0; i<one.length; i++) {
            for(int j=0; j<theOther.length; j++) {
                if (one[i]==theOther[j]) {
                    result[count++] = one[i];
                }
            }
        }

        int[] result2 = new int[count];
        System.arraycopy(result, 0, result2, 0, count);

        return result2;
    }

    /**
     * Traverse ComplexType Declaration - CR Implementation.
     * 
     *       <complexType
     *         abstract = boolean
     *         block = #all or (possibly empty) subset of {extension, restriction}
     *         final = #all or (possibly empty) subset of {extension, restriction}
     *         id = ID
     *         mixed = boolean : false
     *         name = NCName>
     *         Content: (annotation? , (simpleContent | complexContent |
     *                    ( (group | all | choice | sequence)? ,
     *                    ( (attribute | attributeGroup)* , anyAttribute?)))) 
     *       </complexType>
     * @param complexTypeDecl
     * @return
     */
   
    private int traverseComplexTypeDecl( Element complexTypeDecl ) throws Exception {
       
        // ------------------------------------------------------------------
        // Get the attributes of the type
        // ------------------------------------------------------------------
        String isAbstract = complexTypeDecl.getAttribute( SchemaSymbols.ATT_ABSTRACT );
        String blockSet = complexTypeDecl.getAttribute( SchemaSymbols.ATT_BLOCK );
        String finalSet = complexTypeDecl.getAttribute( SchemaSymbols.ATT_FINAL );
        String typeId = complexTypeDecl.getAttribute( SchemaSymbols.ATTVAL_ID );
        String typeName = complexTypeDecl.getAttribute(SchemaSymbols.ATT_NAME);
        String mixed = complexTypeDecl.getAttribute(SchemaSymbols.ATT_MIXED);
        boolean isNamedType = false;

        // ------------------------------------------------------------------
        // Generate a type name, if one wasn't specified
        // ------------------------------------------------------------------
        if (typeName.equals("")) { // gensym a unique name
            typeName = genAnonTypeName(complexTypeDecl);
        }

        if ( DEBUGGING )
            System.out.println("traversing complex Type : " + typeName);

        fCurrentTypeNameStack.push(typeName);

        int typeNameIndex = fStringPool.addSymbol(typeName);

        // ------------------------------------------------------------------
        // Check if the type has already been registered
        // ------------------------------------------------------------------
        if (isTopLevel(complexTypeDecl)) {
       
            String fullName = fTargetNSURIString+","+typeName;
            ComplexTypeInfo temp = (ComplexTypeInfo) fComplexTypeRegistry.get(fullName);
            if (temp != null ) {
                return fStringPool.addSymbol(fullName);
            }
        }

        int scopeDefined = fScopeCount++;
        int previousScope = fCurrentScope;
        fCurrentScope = scopeDefined;

        Element child = null;
        ComplexTypeInfo typeInfo = new ComplexTypeInfo();

        try {

          // ------------------------------------------------------------------
          // First, handle any ANNOTATION declaration and get next child
          // ------------------------------------------------------------------
          child = checkContent(complexTypeDecl,XUtil.getFirstChildElement(complexTypeDecl),
                               true);

          // ------------------------------------------------------------------
          // Process the content of the complex type declaration
          // ------------------------------------------------------------------
          if (child==null) {
              //
              // EMPTY complexType with complexContent
              //
              processComplexContent(typeNameIndex, child, typeInfo, null, false);
          }
          else {
              String childName = child.getLocalName();
              int index = -2;

              if (childName.equals(SchemaSymbols.ELT_SIMPLECONTENT)) {
                  //
                  // SIMPLE CONTENT element
                  //
                  traverseSimpleContentDecl(typeNameIndex, child, typeInfo);
                  if (XUtil.getNextSiblingElement(child) != null)
                     throw new ComplexTypeRecoverableError(
                      "Invalid child following the simpleContent child in the complexType");
              }
              else if (childName.equals(SchemaSymbols.ELT_COMPLEXCONTENT)) {
                  //
                  // COMPLEX CONTENT element
                  //
                  traverseComplexContentDecl(typeNameIndex, child, typeInfo,  
                        mixed.equals(SchemaSymbols.ATTVAL_TRUE) ? true:false);
                  if (XUtil.getNextSiblingElement(child) != null)
                     throw new ComplexTypeRecoverableError(
                      "Invalid child following the complexContent child in the complexType");
              }
              else {
                  //
                  // We must have ....
                  // GROUP, ALL, SEQUENCE or CHOICE, followed by optional attributes
                  // Note that it's possible that only attributes are specified.
                  //
                  processComplexContent(typeNameIndex, child, typeInfo, null,
                        mixed.equals(SchemaSymbols.ATTVAL_TRUE) ? true:false);
      
              }
          }
        }
        catch (ComplexTypeRecoverableError e) {
           String message = e.getMessage();
           handleComplexTypeError(message,typeNameIndex,typeInfo);
        }
               
           
        // ------------------------------------------------------------------
        // Finish the setup of the typeInfo and register the type
        // ------------------------------------------------------------------
        typeInfo.scopeDefined = scopeDefined;
        typeInfo.blockSet = parseBlockSet(blockSet);
        typeInfo.finalSet = parseFinalSet(finalSet);
        typeInfo.isAbstract = isAbstract.equals(SchemaSymbols.ATTVAL_TRUE) ? true:false ;
        typeName = fTargetNSURIString + "," + typeName;
        typeInfo.typeName = new String(typeName);

        if ( DEBUGGING )
            System.out.println(">>>add complex Type to Registry: " + typeName +
                               " baseDTValidator=" + typeInfo.baseDataTypeValidator +
                               " baseCTInfo=" + typeInfo.baseComplexTypeInfo +
                               " derivedBy=" + typeInfo.derivedBy +
                             " contentType=" + typeInfo.contentType +
                               " contentSpecHandle=" + typeInfo.contentSpecHandle +
                               " datatypeValidator=" + typeInfo.datatypeValidator);

        fComplexTypeRegistry.put(typeName,typeInfo);

        // ------------------------------------------------------------------
        // Before exiting, restore the scope, mainly for nested anonymous types
        // ------------------------------------------------------------------
        fCurrentScope = previousScope;
        fCurrentTypeNameStack.pop();
        checkRecursingComplexType();

        //set template element's typeInfo
        fSchemaGrammar.setElementComplexTypeInfo(typeInfo.templateElementIndex, typeInfo);

        typeNameIndex = fStringPool.addSymbol(typeName);
        return typeNameIndex;

    } // end traverseComplexTypeDecl

     
    /**
     * Traverse SimpleContent Declaration                         
     * 
     *       <simpleContent
     *         id = ID
     *         {any attributes with non-schema namespace...}>
     *
     *         Content: (annotation? , (restriction | extension))
     *       </simpleContent>
     *
     *       <restriction
     *         base = QNAME
     *         id = ID          
     *         {any attributes with non-schema namespace...}>
     *
     *         Content: (annotation?,(simpleType?, (minExclusive|minInclusive|maxExclusive
     *                    | maxInclusive | precision | scale | length | minLength
     *                    | maxLength | encoding | period | duration | enumeration
     *                    | pattern | whiteSpace)*) ? , 
     *                    ((attribute | attributeGroup)* , anyAttribute?))
     *       </restriction>
     *
     *       <extension
     *         base = QNAME
     *         id = ID          
     *         {any attributes with non-schema namespace...}>
     *         Content: (annotation? , ((attribute | attributeGroup)* , anyAttribute?))
     *       </extension>
     *
     * @param typeNameIndex
     * @param simpleContentTypeDecl
     * @param typeInfo                  
     * @return
     */
   
    private void traverseSimpleContentDecl(int typeNameIndex,
               Element simpleContentDecl, ComplexTypeInfo typeInfo)
               throws Exception {

       
        String typeName = fStringPool.toString(typeNameIndex);

        // -----------------------------------------------------------------------
        // Get attributes.  
        // -----------------------------------------------------------------------
        String simpleContentTypeId = simpleContentDecl.getAttribute(SchemaSymbols.ATTVAL_ID);

        // -----------------------------------------------------------------------
        // Set the content type to be simple, and initialize content spec handle
        // -----------------------------------------------------------------------
        typeInfo.contentType = XMLElementDecl.TYPE_SIMPLE;
        typeInfo.contentSpecHandle = -1;

        Element simpleContent = checkContent(simpleContentDecl,
                                     XUtil.getFirstChildElement(simpleContentDecl),false);
       
        // If there are no children, return
        if (simpleContent==null) {
          throw new ComplexTypeRecoverableError();
        }

        // -----------------------------------------------------------------------
        // The content should be either "restriction" or "extension"
        // -----------------------------------------------------------------------
        String simpleContentName = simpleContent.getLocalName();
        if (simpleContentName.equals(SchemaSymbols.ELT_RESTRICTION))
          typeInfo.derivedBy = SchemaSymbols.RESTRICTION;
        else if (simpleContentName.equals(SchemaSymbols.ELT_EXTENSION))
          typeInfo.derivedBy = SchemaSymbols.EXTENSION;
        else {
         
          throw new ComplexTypeRecoverableError(
                     "The content of the simpleContent element is invalid.  The " +
                     "content must be RESTRICTION or EXTENSION");
        }

        // -----------------------------------------------------------------------
        // Get the attributes of the restriction/extension element
        // -----------------------------------------------------------------------
        String base = simpleContent.getAttribute(SchemaSymbols.ATT_BASE);
        String typeId = simpleContent.getAttribute(SchemaSymbols.ATTVAL_ID);


        // -----------------------------------------------------------------------
        // Skip over any annotations in the restriction or extension elements
        // todo - check whether the content can be empty...
        // -----------------------------------------------------------------------
        Element content = checkContent(simpleContent,
                              XUtil.getFirstChildElement(simpleContent),true);

        // -----------------------------------------------------------------------
        // Handle the base type name
        // -----------------------------------------------------------------------
        if (base.length() == 0)  {
          throw new ComplexTypeRecoverableError(
                  "The BASE attribute must be specified for the " +
                  "RESTRICTION or EXTENSION element");
        }

        QName baseQName = parseBase(base);
        processBaseTypeInfo(baseQName,typeInfo);
      
        // check that the base isn't a complex type with complex content
        if (typeInfo.baseComplexTypeInfo != null)  {
             if (typeInfo.baseComplexTypeInfo.contentSpecHandle > -1) {
                 throw new ComplexTypeRecoverableError(
                 "The type '"+ base +"' specified as the " +
                 "base in the simpleContent element must not have complexContent");
             }
        }
          
        // -----------------------------------------------------------------------
        // Process the content of the derivation
        // -----------------------------------------------------------------------
        Element attrNode = null;
        //
        // RESTRICTION
        //
        if (typeInfo.derivedBy==SchemaSymbols.RESTRICTION) {
            //
            //Schema Spec : 5.11: Complex Type Definition Properties Correct : 2
            //
            if (typeInfo.baseDataTypeValidator != null) {
                throw new ComplexTypeRecoverableError(
                 "The type '" + base +"' is a simple type.  It cannot be used in a "+
                 "derivation by RESTRICTION for a complexType");
            }
            else {
               typeInfo.baseDataTypeValidator = typeInfo.baseComplexTypeInfo.datatypeValidator;
            }

            // -----------------------------------------------------------------------
            // There may be a simple type definition in the restriction element
            // The data type validator will be based on it, if specified         
            // -----------------------------------------------------------------------
            if (content.getLocalName().equals(SchemaSymbols.ELT_SIMPLETYPE )) {
                int simpleTypeNameIndex = traverseSimpleTypeDecl(content);
                if (simpleTypeNameIndex!=-1) {
                    typeInfo.baseDataTypeValidator=fDatatypeRegistry.getDatatypeValidator(
                       fStringPool.toString(simpleTypeNameIndex));
                    content = XUtil.getNextSiblingElement(content);
                }
                else {
                    throw new ComplexTypeRecoverableError();
                }
            }

            //
            // Build up facet information
            //
            int numEnumerationLiterals = 0;
            int numFacets = 0;
            Hashtable facetData        = new Hashtable();
            Vector enumData            = new Vector();
            Element child;

            //REVISIT: there is a better way to do this,
            for (child = content;
                 child != null && (child.getLocalName().equals(SchemaSymbols.ELT_MINEXCLUSIVE) ||
                           child.getLocalName().equals(SchemaSymbols.ELT_MININCLUSIVE) ||
                           child.getLocalName().equals(SchemaSymbols.ELT_MAXEXCLUSIVE) ||
                           child.getLocalName().equals(SchemaSymbols.ELT_MAXINCLUSIVE) ||
                           child.getLocalName().equals(SchemaSymbols.ELT_PRECISION) ||
                           child.getLocalName().equals(SchemaSymbols.ELT_SCALE) ||
                           child.getLocalName().equals(SchemaSymbols.ELT_LENGTH) ||
                           child.getLocalName().equals(SchemaSymbols.ELT_MINLENGTH) ||
                           child.getLocalName().equals(SchemaSymbols.ELT_MAXLENGTH) ||
                           child.getLocalName().equals(SchemaSymbols.ELT_ENCODING) ||
                           child.getLocalName().equals(SchemaSymbols.ELT_PERIOD) ||
                           child.getLocalName().equals(SchemaSymbols.ELT_DURATION) ||
                           child.getLocalName().equals(SchemaSymbols.ELT_ENUMERATION) ||
                           child.getLocalName().equals(SchemaSymbols.ELT_PATTERN) ||
                           child.getLocalName().equals(SchemaSymbols.ELT_ANNOTATION));
                 child = XUtil.getNextSiblingElement(child))
            {
                if ( child.getNodeType() == Node.ELEMENT_NODE ) {
                    Element facetElt = (Element) child;
                    numFacets++;
                    if (facetElt.getLocalName().equals(SchemaSymbols.ELT_ENUMERATION)) {
                        numEnumerationLiterals++;
                        enumData.addElement(facetElt.getAttribute(SchemaSymbols.ATT_VALUE));
                        //Enumerations can have annotations ? ( 0 | 1 )
                        Element enumContent =  XUtil.getFirstChildElement( facetElt );
                        if( enumContent != null &&
                            enumContent.getLocalName().equals
                                  ( SchemaSymbols.ELT_ANNOTATION )){
                            traverseAnnotationDecl( child );  
                        }
                        // TO DO: if Jeff check in new changes to TraverseSimpleType, copy them over
                    }
                    else {
                        facetData.put(facetElt.getLocalName(),
                              facetElt.getAttribute( SchemaSymbols.ATT_VALUE ));
                    }
                }
            } // end of for loop thru facets

            if (numEnumerationLiterals > 0) {
                facetData.put(SchemaSymbols.ELT_ENUMERATION, enumData);
            }

            //
            // If there were facets, create a new data type validator, otherwise
            // the data type validator is from the base
            //
            if (numFacets > 0) {
                typeInfo.datatypeValidator = fDatatypeRegistry.createDatatypeValidator(
                                      typeName,
                                      typeInfo.baseDataTypeValidator, facetData, false);
            }
            else
                typeInfo.datatypeValidator =
                             typeInfo.baseDataTypeValidator;

            if (child != null) {
               //
               // Check that we have attributes
               //
               if (!isAttrOrAttrGroup(child)) {
                  throw new ComplexTypeRecoverableError(
                     "Invalid child in the RESTRICTION element of simpleContent");
               }
               else
                  attrNode = child;
            }
           
        } // end RESTRICTION

        //
        // EXTENSION
        //
        else {
            if (typeInfo.baseComplexTypeInfo != null)
               typeInfo.baseDataTypeValidator = typeInfo.baseComplexTypeInfo.datatypeValidator;

            typeInfo.datatypeValidator = typeInfo.baseDataTypeValidator;

            //
            // Look for attributes
            //
            if (content != null)  {
               //
               // Check that we have attributes
               //
               if (!isAttrOrAttrGroup(content)) {
                   throw new ComplexTypeRecoverableError(
                             "Only annotations and attributes are allowed in the " +
                             "content of an EXTENSION element for a complexType with simpleContent");
               }
               else {
                   attrNode = content;
               }
            }
             
        }

        // -----------------------------------------------------------------------
        // add a template element to the grammar element decl pool for the type
        // -----------------------------------------------------------------------
        int templateElementNameIndex = fStringPool.addSymbol("$"+typeName);

        typeInfo.templateElementIndex = fSchemaGrammar.addElementDecl(
             new QName(-1, templateElementNameIndex,typeNameIndex,fTargetNSURI),
             (fTargetNSURI==StringPool.EMPTY_STRING) ? StringPool.EMPTY_STRING : fCurrentScope, typeInfo.scopeDefined,
             typeInfo.contentType,
             typeInfo.contentSpecHandle, -1, typeInfo.datatypeValidator);
        typeInfo.attlistHead = fSchemaGrammar.getFirstAttributeDeclIndex(
                                typeInfo.templateElementIndex);

        // -----------------------------------------------------------------------
        // Process attributes                                         
        // -----------------------------------------------------------------------
        processAttributes(attrNode,baseQName,typeInfo);

        if (XUtil.getNextSiblingElement(simpleContent) != null)
            throw new ComplexTypeRecoverableError(
               "Invalid child following the RESTRICTION or EXTENSION element in the " +
               "complex type definition");

    // end traverseSimpleContentDecl

    /**
     * Traverse complexContent Declaration                         
     * 
     *       <complexContent
     *         id = ID
     *         mixed = boolean
     *         {any attributes with non-schema namespace...}>
     *
     *         Content: (annotation? , (restriction | extension))
     *       </complexContent>
     *
     *       <restriction
     *         base = QNAME
     *         id = ID          
     *         {any attributes with non-schema namespace...}>
     *
     *         Content: (annotation? , (group | all | choice | sequence)?,
     *                  ((attribute | attributeGroup)* , anyAttribute?))
     *       </restriction>
     *
     *       <extension
     *         base = QNAME
     *         id = ID          
     *         {any attributes with non-schema namespace...}>
     *         Content: (annotation? , (group | all | choice | sequence)?,
     *                  ((attribute | attributeGroup)* , anyAttribute?))
     *       </extension>
     *
     * @param typeNameIndex
     * @param simpleContentTypeDecl
     * @param typeInfo                  
     * @param mixedOnComplexTypeDecl                  
     * @return
     */
   
    private void traverseComplexContentDecl(int typeNameIndex, 
               Element complexContentDecl, ComplexTypeInfo typeInfo,
               boolean mixedOnComplexTypeDecl) throws Exception {

        String typeName = fStringPool.toString(typeNameIndex);

        // -----------------------------------------------------------------------
        // Get the attributes                                                     
        // -----------------------------------------------------------------------
        String typeId = complexContentDecl.getAttribute(SchemaSymbols.ATTVAL_ID);
        String mixed = complexContentDecl.getAttribute(SchemaSymbols.ATT_MIXED);
       
        // -----------------------------------------------------------------------
        // Determine whether the content is mixed, or element-only
        // Setting here overrides any setting on the complex type decl
        // -----------------------------------------------------------------------
        boolean isMixed = mixedOnComplexTypeDecl;
        if (mixed.equals(SchemaSymbols.ATTVAL_TRUE))
           isMixed = true;
        else if (mixed.equals(SchemaSymbols.ATTVAL_FALSE))
           isMixed = false;
       
        // -----------------------------------------------------------------------
        // Since the type must have complex content, set the simple type validators
        // to null
        // -----------------------------------------------------------------------
        typeInfo.datatypeValidator = null;
        typeInfo.baseDataTypeValidator = null;

        Element complexContent = checkContent(complexContentDecl,
                                 XUtil.getFirstChildElement(complexContentDecl),false);
       
        // If there are no children, return
        if (complexContent==null) {
           throw new ComplexTypeRecoverableError();
        }

        // -----------------------------------------------------------------------
        // The content should be either "restriction" or "extension"
        // -----------------------------------------------------------------------
        String complexContentName = complexContent.getLocalName();
        if (complexContentName.equals(SchemaSymbols.ELT_RESTRICTION))
          typeInfo.derivedBy = SchemaSymbols.RESTRICTION;
        else if (complexContentName.equals(SchemaSymbols.ELT_EXTENSION))
          typeInfo.derivedBy = SchemaSymbols.EXTENSION;
        else {
           throw new ComplexTypeRecoverableError(
                     "The content of the complexContent element is invalid. " +
                     "The content must be RESTRICTION or EXTENSION");
        }

        // Get the attributes of the restriction/extension element
        String base = complexContent.getAttribute(SchemaSymbols.ATT_BASE);
        String complexContentTypeId=complexContent.getAttribute(SchemaSymbols.ATTVAL_ID);


        // Skip over any annotations in the restriction or extension elements
        // TODO - check whether the content can be empty...
        Element content = checkContent(complexContent,
                              XUtil.getFirstChildElement(complexContent),true);

        // -----------------------------------------------------------------------
        // Handle the base type name
        // -----------------------------------------------------------------------
        if (base.length() == 0)  {
           throw new ComplexTypeRecoverableError(
                  "The BASE attribute must be specified for the " +
                  "RESTRICTION or EXTENSION element");
        }

        QName baseQName = parseBase(base);

        // -------------------------------------------------------------
        // check if the base is "anyType"                      
        // -------------------------------------------------------------
        String baseTypeURI = fStringPool.toString(baseQName.uri);
        String baseLocalName = fStringPool.toString(baseQName.localpart);
        if (!(baseTypeURI.equals(SchemaSymbols.URI_SCHEMAFORSCHEMA) &&
            baseLocalName.equals("anyType"))) {

            processBaseTypeInfo(baseQName,typeInfo);
      
            //Check that the base is a complex type                                 
            if (typeInfo.baseComplexTypeInfo == null)  {
                 throw new ComplexTypeRecoverableError(
                   "The base type specified in the complexContent element must be a complexType");
            }
        }

        // -----------------------------------------------------------------------
        // Process the elements that make up the content
        // -----------------------------------------------------------------------
        processComplexContent(typeNameIndex,content,typeInfo,baseQName,isMixed);

        if (XUtil.getNextSiblingElement(complexContent) != null)
            throw new ComplexTypeRecoverableError(
               "Invalid child following the RESTRICTION or EXTENSION element in the " +
               "complex type definition");

    // end traverseComplexContentDecl


    /**
     * Handle complexType error                                           
     * 
     * @param message
     * @param typeNameIndex
     * @param typeInfo
     * @return
     */
    private void handleComplexTypeError(String message, int typeNameIndex, 
                                        ComplexTypeInfo typeInfo) throws Exception {

        String typeName = fStringPool.toString(typeNameIndex);
        if (message != null) {
          if (typeName.startsWith("#"))
            reportGenericSchemaError("Anonymous complexType: " + message);
          else
            reportGenericSchemaError("ComplexType '" + typeName + "': " + message);
        }

        //
        //  Mock up the typeInfo structure so that there won't be problems during    
        //  validation     
        //
        typeInfo.contentType = XMLElementDecl.TYPE_ANY;  // this should match anything
        typeInfo.contentSpecHandle = -1;
        typeInfo.derivedBy = 0;
        typeInfo.datatypeValidator = null;
        typeInfo.attlistHead = -1;

        int templateElementNameIndex = fStringPool.addSymbol("$"+typeName);
        typeInfo.templateElementIndex = fSchemaGrammar.addElementDecl(
            new QName(-1, templateElementNameIndex,typeNameIndex,fTargetNSURI),
            (fTargetNSURI==StringPool.EMPTY_STRING) ? StringPool.EMPTY_STRING : fCurrentScope, typeInfo.scopeDefined,
            typeInfo.contentType,
            typeInfo.contentSpecHandle, -1, typeInfo.datatypeValidator);
        return;
    }

    /**
     * Generate a name for an anonymous type                       
     * 
     * @param Element
     * @return String
     */
    private String genAnonTypeName(Element complexTypeDecl) throws Exception {

        String typeName;

        // If the anonymous type is not nested within another type, we can
        // simply assign the type a numbered name
        //
        if (fCurrentTypeNameStack.empty())
            typeName = "#"+fAnonTypeCount++;
         
        // Otherwise, we must generate a name that can be looked up later
        // Do this by concatenating outer type names with the name of the parent
        // element
        else {
            String parentName = ((Element)complexTypeDecl.getParentNode()).getAttribute(
                                SchemaSymbols.ATT_NAME);
            typeName = parentName + "_AnonType";
            int index=fCurrentTypeNameStack.size() -1;
      for (int i = index; i > -1; i--) {
               String parentType = (String)fCurrentTypeNameStack.elementAt(i);
               typeName = parentType + "_" + typeName;
               if (!(parentType.startsWith("#")))
                  break;
            }
            typeName = "#" + typeName;
        }
          
        return typeName;
    }
    /**
     * Parse base string                                           
     * 
     * @param base
     * @return QName
     */
    private QName parseBase(String base) throws Exception {

        String prefix = "";
        String localpart = base;
        int colonptr = base.indexOf(":");
        if ( colonptr > 0) {
            prefix = base.substring(0,colonptr);
            localpart = base.substring(colonptr+1);
        }

        int nameIndex = fStringPool.addSymbol(base);
        int prefixIndex = fStringPool.addSymbol(prefix);
        int localpartIndex = fStringPool.addSymbol(localpart);
        int URIindex = fStringPool.addSymbol(resolvePrefixToURI(prefix));
        return new QName(prefixIndex,localpartIndex,nameIndex,URIindex);
    }
   
    /**
     * Check if base is from another schema                        
     * 
     * @param baseName
     * @return boolean
     */
    private boolean baseFromAnotherSchema(QName baseName) throws Exception {

        String typeURI = fStringPool.toString(baseName.uri);
        if ( ! typeURI.equals(fTargetNSURIString)
             && ! typeURI.equals(SchemaSymbols.URI_SCHEMAFORSCHEMA)
             && typeURI.length() != 0 )
             //REVISIT, !!!! a hack: for schema that has no
             //target namespace, e.g. personal-schema.xml
          return true;
        else
          return false;
                                       
    }
   
    /**
     * Process "base" information for a complexType
     * 
     * @param baseTypeInfo       
     * @param baseName
     * @param typeInfo
     * @return
     */
   
    private void processBaseTypeInfo(QName baseName, ComplexTypeInfo typeInfo) throws Exception {

        ComplexTypeInfo baseComplexTypeInfo = null;
        DatatypeValidator baseDTValidator = null;
       
        String typeURI = fStringPool.toString(baseName.uri);
        String localpart = fStringPool.toString(baseName.localpart);
        String base = fStringPool.toString(baseName.rawname);


        // -------------------------------------------------------------
        // check if the base type is from another schema
        // -------------------------------------------------------------
        if (baseFromAnotherSchema(baseName)) {
            baseComplexTypeInfo = getTypeInfoFromNS(typeURI, localpart);
            if (baseComplexTypeInfo == null) {
                baseDTValidator = getTypeValidatorFromNS(typeURI, localpart);
                if (baseDTValidator == null) {
                    throw new ComplexTypeRecoverableError(
                       "Could not find base type " +localpart
                       + " in schema " + typeURI);
                }
            }
        }

        // -------------------------------------------------------------
        // type must be from same schema
        // -------------------------------------------------------------
        else {
            String fullBaseName = typeURI+","+localpart;

            // assume the base is a complexType and try to locate the base type first
            baseComplexTypeInfo= (ComplexTypeInfo) fComplexTypeRegistry.get(fullBaseName);

            // if not found, 2 possibilities:
            //           1: ComplexType in question has not been compiled yet;
            //           2: base is SimpleTYpe;
            if (baseComplexTypeInfo == null) {
                baseDTValidator = getDatatypeValidator(typeURI, localpart);

                if (baseDTValidator == null) {
                    int baseTypeSymbol;
                    Element baseTypeNode = getTopLevelComponentByName(
                                   SchemaSymbols.ELT_COMPLEXTYPE,localpart);
                    if (baseTypeNode != null) {
                        baseTypeSymbol = traverseComplexTypeDecl( baseTypeNode );
                        baseComplexTypeInfo = (ComplexTypeInfo)
                        fComplexTypeRegistry.get(fStringPool.toString(baseTypeSymbol));
                        //REVISIT: should it be fullBaseName;
                    }
                    else {
                        baseTypeNode = getTopLevelComponentByName(
                                   SchemaSymbols.ELT_SIMPLETYPE, localpart);
                        if (baseTypeNode != null) {
                            baseTypeSymbol = traverseSimpleTypeDecl( baseTypeNode );
                            baseDTValidator = getDatatypeValidator(typeURI, localpart);
                            if (baseDTValidator == null)  {
                                        //TO DO: signal error here.
                            }
                        }
                        else {
                            throw new ComplexTypeRecoverableError(
                                 "Base type could not be found : " + base);
                        }
                    }
                }
            }
        } // end else (type must be from same schema)

        typeInfo.baseComplexTypeInfo = baseComplexTypeInfo;
        typeInfo.baseDataTypeValidator = baseDTValidator;


    } // end processBaseTypeInfo

    /**
     * Process content which is complex                            
     * 
     *     (group | all | choice | sequence) ? ,
     *     ((attribute | attributeGroup)* , anyAttribute?))
     *
     * @param typeNameIndex
     * @param complexContentChild
     * @param typeInfo                  
     * @return
     */
   
    private void processComplexContent(int typeNameIndex,
               Element complexContentChild, ComplexTypeInfo typeInfo, QName baseName,
               boolean isMixed) throws Exception {

       Element attrNode = null;
       int index=-2;

       if (complexContentChild != null) {
           // -------------------------------------------------------------
           // GROUP, ALL, SEQUENCE or CHOICE, followed by attributes, if specified.
           // Note that it's possible that only attributes are specified.
           // -------------------------------------------------------------


          String childName = complexContentChild.getLocalName();

          if (childName.equals(SchemaSymbols.ELT_GROUP)) {
               index = expandContentModel(traverseGroupDecl(complexContentChild),
                                          complexContentChild);
               attrNode = XUtil.getNextSiblingElement(complexContentChild);
           }
           else if (childName.equals(SchemaSymbols.ELT_SEQUENCE)) {
               index = expandContentModel(traverseSequence(complexContentChild),
                                         complexContentChild);
               attrNode = XUtil.getNextSiblingElement(complexContentChild);
           }
           else if (childName.equals(SchemaSymbols.ELT_CHOICE)) {
               index = expandContentModel(traverseChoice(complexContentChild),
                                          complexContentChild);
               attrNode = XUtil.getNextSiblingElement(complexContentChild);
           }
           else if (childName.equals(SchemaSymbols.ELT_ALL)) {
               index = expandContentModel(traverseAll(complexContentChild),
                                      complexContentChild);
               attrNode = XUtil.getNextSiblingElement(complexContentChild);
               //TO DO: REVISIT
               //check that minOccurs = 1 and maxOccurs = 1 
           }
           else if (isAttrOrAttrGroup(complexContentChild)) {
               // reset the contentType
               typeInfo.contentType = XMLElementDecl.TYPE_ANY;
               attrNode = complexContentChild;
           }
           else {
               throw new ComplexTypeRecoverableError(
                "Invalid child '"+ childName +"' in the complex type");              
           }
       }
    
       if (isMixed) {
            //
            // TODO - check to see if we MUST have an element.  What if only attributes
            // were specified??


            // add #PCDATA leaf
            int pcdataNode = fSchemaGrammar.addContentSpecNode(
                             XMLContentSpec.CONTENTSPECNODE_LEAF,
                             -1, // -1 means "#PCDATA" is name
                             -1, false);
            //
            // If there was an element, the content spec becomes a choice of PCDATA and
            // the element
            //
            if (index != -2)
                index = fSchemaGrammar.addContentSpecNode(
                    XMLContentSpec.CONTENTSPECNODE_CHOICE,pcdataNode,index,false);
            else
                index = pcdataNode;

       }

       typeInfo.contentSpecHandle = index;

       // -----------------------------------------------------------------------
       // Merge in information from base, if it exists          
       // -----------------------------------------------------------------------
       if (typeInfo.baseComplexTypeInfo != null) {
           int baseContentSpecHandle = typeInfo.baseComplexTypeInfo.contentSpecHandle;

           if (typeInfo.derivedBy == SchemaSymbols.RESTRICTION) {
              //
              //REVISIT: !!!really hairy stuff to check the particle derivation OK in 5.10
              //checkParticleDerivationOK();
           }
           else {
               //
               // Compose the final content model by concatenating the base and the
               // current in sequence
               //
               if (baseFromAnotherSchema(baseName)) {
                   String baseSchemaURI = fStringPool.toString(baseName.uri);
                   SchemaGrammar aGrammar= (SchemaGrammar) fGrammarResolver.getGrammar(
                                    baseSchemaURI);
                   baseContentSpecHandle = importContentSpec(aGrammar, baseContentSpecHandle);
               }
               if (typeInfo.contentSpecHandle == -2) {
                   typeInfo.contentSpecHandle = baseContentSpecHandle;
               }
               else if (baseContentSpecHandle > -1) {
                   typeInfo.contentSpecHandle =
                   fSchemaGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_SEQ,
                                                     baseContentSpecHandle,
                                                     typeInfo.contentSpecHandle,
                                                     false);
               }
           }
       }
       else {
           typeInfo.derivedBy = 0;
       }

       // -------------------------------------------------------------
       // Set the content type                                                    
       // -------------------------------------------------------------
       if (isMixed)
           typeInfo.contentType = XMLElementDecl.TYPE_MIXED;
       else if (typeInfo.contentSpecHandle == -2)
           typeInfo.contentType = XMLElementDecl.TYPE_EMPTY;
       else
           typeInfo.contentType = XMLElementDecl.TYPE_CHILDREN;


       // -------------------------------------------------------------
       // add a template element to the grammar element decl pool.
       // -------------------------------------------------------------
       String typeName = fStringPool.toString(typeNameIndex);
       int templateElementNameIndex = fStringPool.addSymbol("$"+typeName);

       typeInfo.templateElementIndex = fSchemaGrammar.addElementDecl(
            new QName(-1, templateElementNameIndex,typeNameIndex,fTargetNSURI),
            (fTargetNSURI==StringPool.EMPTY_STRING) ? StringPool.EMPTY_STRING : fCurrentScope, typeInfo.scopeDefined,
            typeInfo.contentType,
            typeInfo.contentSpecHandle, -1, typeInfo.datatypeValidator);
       typeInfo.attlistHead = fSchemaGrammar.getFirstAttributeDeclIndex(
                               typeInfo.templateElementIndex);

       // -------------------------------------------------------------
       // Now, check attributes and handle
       // -------------------------------------------------------------
       if (attrNode !=null) {
           if (!isAttrOrAttrGroup(attrNode)) {
              throw new ComplexTypeRecoverableError(
                  "Invalid child "+ attrNode.getLocalName() + " in the complexType or complexContent");
           }
           else
              processAttributes(attrNode,baseName,typeInfo);
       }
       else if (typeInfo.baseComplexTypeInfo != null)
           processAttributes(null,baseName,typeInfo);


    } // end processComplexContent

    /**
     * Process attributes of a complex type                             
     * 
     * @param attrNode
     * @param typeInfo                  
     * @return
     */
   
    private void processAttributes(Element attrNode, QName baseName,           
               ComplexTypeInfo typeInfo) throws Exception {


        XMLAttributeDecl attWildcard = null;
        Vector anyAttDecls = new Vector();

        Element child;
        for (child = attrNode;
             child != null;
             child = XUtil.getNextSiblingElement(child)) {

            String childName = child.getLocalName();

            if (childName.equals(SchemaSymbols.ELT_ATTRIBUTE)) {
                traverseAttributeDecl(child, typeInfo, false);
            }
            else if ( childName.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP) ) {
                traverseAttributeGroupDecl(child,typeInfo,anyAttDecls);

            }
            else if ( childName.equals(SchemaSymbols.ELT_ANYATTRIBUTE) ) {
                attWildcard = traverseAnyAttribute(child);
            }
            else {
                throw new ComplexTypeRecoverableError( "Invalid child among the children of the complexType definition");
            }
        }

        if (attWildcard != null) {
            XMLAttributeDecl fromGroup = null;
            final int count = anyAttDecls.size();
            if ( count > 0) {
                fromGroup = (XMLAttributeDecl) anyAttDecls.elementAt(0);
                for (int i=1; i<count; i++) {
                    fromGroup = mergeTwoAnyAttribute(
                                fromGroup,(XMLAttributeDecl)anyAttDecls.elementAt(i));
                }
            }
            if (fromGroup != null) {
                int saveProcessContents = attWildcard.defaultType;
                attWildcard = mergeTwoAnyAttribute(attWildcard, fromGroup);
                attWildcard.defaultType = saveProcessContents;
            }
        }
        else {
            //REVISIT: unclear in the Scheme Structures 4.3.3 what to do in this case
            if (anyAttDecls.size()>0) {
                attWildcard = (XMLAttributeDecl)anyAttDecls.elementAt(0);
            }
        }
        //
        // merge in base type's attribute decls
        //
        XMLAttributeDecl baseAttWildcard = null;
        ComplexTypeInfo baseTypeInfo = typeInfo.baseComplexTypeInfo;

        if (baseTypeInfo != null && baseTypeInfo.attlistHead > -1 ) {
            int attDefIndex = baseTypeInfo.attlistHead;
            SchemaGrammar aGrammar = fSchemaGrammar;
            String baseTypeSchemaURI = baseFromAnotherSchema(baseName)?
                           fStringPool.toString(baseName.uri):null;
            if (baseTypeSchemaURI != null) {
                aGrammar = (SchemaGrammar) fGrammarResolver.getGrammar(baseTypeSchemaURI);
            }
            if (aGrammar == null) {
                //reportGenericSchemaError("In complexType "+typeName+", can NOT find the grammar "+
                  //                       "with targetNamespace" + baseTypeSchemaURI+
                    //                     "for the base type");
            }
            else
            while ( attDefIndex > -1 ) {
                fTempAttributeDecl.clear();
                aGrammar.getAttributeDecl(attDefIndex, fTempAttributeDecl);
                if (fTempAttributeDecl.type == XMLAttributeDecl.TYPE_ANY_ANY
                    ||fTempAttributeDecl.type == XMLAttributeDecl.TYPE_ANY_LIST
                    ||fTempAttributeDecl.type == XMLAttributeDecl.TYPE_ANY_LOCAL
                    ||fTempAttributeDecl.type == XMLAttributeDecl.TYPE_ANY_OTHER ) {
                    if (attWildcard == null) {
                        baseAttWildcard = fTempAttributeDecl;
                    }
                    attDefIndex = aGrammar.getNextAttributeDeclIndex(attDefIndex);
                    continue;
                }
                // if found a duplicate, if it is derived by restriction,
                // then skip the one from the base type
               
                int temp = fSchemaGrammar.getAttributeDeclIndex(typeInfo.templateElementIndex, fTempAttributeDecl.name);
                if ( temp > -1) {
                    if (typeInfo.derivedBy==SchemaSymbols.RESTRICTION) {
                        attDefIndex = fSchemaGrammar.getNextAttributeDeclIndex(attDefIndex);
                        continue;
                    }
                }

              
                fSchemaGrammar.addAttDef( typeInfo.templateElementIndex,
                                          fTempAttributeDecl.name, fTempAttributeDecl.type,
                                          fTempAttributeDecl.enumeration, fTempAttributeDecl.defaultType,
                                          fTempAttributeDecl.defaultValue,
                                          fTempAttributeDecl.datatypeValidator,
                                          fTempAttributeDecl.list);
                attDefIndex = aGrammar.getNextAttributeDeclIndex(attDefIndex);
            }
        }

        // att wildcard will inserted after all attributes were processed
        if (attWildcard != null) {
            if (attWildcard.type != -1) {
                fSchemaGrammar.addAttDef( typeInfo.templateElementIndex,
                                          attWildcard.name, attWildcard.type,
                                          attWildcard.enumeration, attWildcard.defaultType,
                                          attWildcard.defaultValue,
                                          attWildcard.datatypeValidator,
                                          attWildcard.list);
            }
            else {
                //REVISIT: unclear in Schema spec if should report error here.
            }
        }
        else if (baseAttWildcard != null) {
            fSchemaGrammar.addAttDef( typeInfo.templateElementIndex,
                                      baseAttWildcard.name, baseAttWildcard.type,
                                      baseAttWildcard.enumeration, baseAttWildcard.defaultType,
                                      baseAttWildcard.defaultValue,
                                      baseAttWildcard.datatypeValidator,
                                      baseAttWildcard.list);
        }

        typeInfo.attlistHead = fSchemaGrammar.getFirstAttributeDeclIndex
                                              (typeInfo.templateElementIndex);
    } // end processAttributes

    private boolean isAttrOrAttrGroup(Element e)
    {
        String elementName = e.getLocalName();

        if (elementName.equals(SchemaSymbols.ELT_ATTRIBUTE) ||
            elementName.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP) ||
            elementName.equals(SchemaSymbols.ELT_ANYATTRIBUTE))
          return true;
        else
          return false;
    }

    private void checkRecursingComplexType() throws Exception {
        if ( fCurrentTypeNameStack.empty() ) {
            if (! fElementRecurseComplex.isEmpty() ) {
                Enumeration e = fElementRecurseComplex.keys();
                while( e.hasMoreElements() ) {
                    QName nameThenScope = (QName) e.nextElement();
                    String typeName = (String) fElementRecurseComplex.get(nameThenScope);

                    int eltUriIndex = nameThenScope.uri;
                    int eltNameIndex = nameThenScope.localpart;
                    int enclosingScope = nameThenScope.prefix;
                    ComplexTypeInfo typeInfo =
                        (ComplexTypeInfo) fComplexTypeRegistry.get(fTargetNSURIString+","+typeName);
                    if (typeInfo==null) {
                        throw new Exception ( "Internal Error in void checkRecursingComplexType(). " );
                    }
                    else {
                        int elementIndex = fSchemaGrammar.addElementDecl(new QName(-1, eltNameIndex, eltNameIndex, eltUriIndex),
                                                                         enclosingScope, typeInfo.scopeDefined,
                                                                         typeInfo.contentType,
                                                                         typeInfo.contentSpecHandle,
                                                                         typeInfo.attlistHead,
                                                                         typeInfo.datatypeValidator);
                        fSchemaGrammar.setElementComplexTypeInfo(elementIndex, typeInfo);
                    }

                }
                fElementRecurseComplex.clear();
            }
        }
    }

    private void checkParticleDerivationOK(Element derivedTypeNode, Element baseTypeNode) {
        //TO DO: !!!
    }

    private int importContentSpec(SchemaGrammar aGrammar, int contentSpecHead ) throws Exception {
        XMLContentSpec ctsp = new XMLContentSpec();
        aGrammar.getContentSpec(contentSpecHead, ctsp);
        int left = -1;
        int right = -1;
        if ( ctsp.type == ctsp.CONTENTSPECNODE_LEAF
             || (ctsp.type & 0x0f) == ctsp.CONTENTSPECNODE_ANY
             || (ctsp.type & 0x0f) == ctsp.CONTENTSPECNODE_ANY_LOCAL
             || (ctsp.type & 0x0f) == ctsp.CONTENTSPECNODE_ANY_OTHER ) {
            return fSchemaGrammar.addContentSpecNode(ctsp.type, ctsp.value, ctsp.otherValue, false);
        }
    else if (ctsp.type == -1)
      // case where type being extended has no content
      return -2;
        else {
            if ( ctsp.value == -1 ) {
                left = -1;
            }
            else {
                left = importContentSpec(aGrammar, ctsp.value);
            }
           
            if ( ctsp.otherValue == -1 ) {
                right = -1;
            }
            else {
                right = importContentSpec(aGrammar, ctsp.otherValue);
            }
            return fSchemaGrammar.addContentSpecNode(ctsp.type, left, right, false);
       
        }
    }
   
    private int expandContentModel ( int index, Element particle) throws Exception {
       
        String minOccurs = particle.getAttribute(SchemaSymbols.ATT_MINOCCURS).trim();
        String maxOccurs = particle.getAttribute(SchemaSymbols.ATT_MAXOCCURS).trim();   

        int min=1, max=1;

        if(minOccurs.equals("0") && maxOccurs.equals("0")){
            return -2;
        }

        if (minOccurs.equals("")) {
            minOccurs = "1";
        }
        if (maxOccurs.equals("")) {
                maxOccurs = "1";
        }


        int leafIndex = index;
        //REVISIT: !!! minoccurs, maxoccurs.
        if (minOccurs.equals("1")&& maxOccurs.equals("1")) {

        }
        else if (minOccurs.equals("0")&& maxOccurs.equals("1")) {
            //zero or one
            index = fSchemaGrammar.addContentSpecNode( XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE,
                                                   index,
                                                   -1,
                                                   false);
        }
        else if (minOccurs.equals("0")&& maxOccurs.equals("unbounded")) {
            //zero or more
            index = fSchemaGrammar.addContentSpecNode( XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE,
                                                   index,
                                                   -1,
                                                   false);
        }
        else if (minOccurs.equals("1")&& maxOccurs.equals("unbounded")) {
            //one or more
            index = fSchemaGrammar.addContentSpecNode( XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE,
                                                   index,
                                                   -1,
                                                   false);
        }
        else if (maxOccurs.equals("unbounded") ) {
            // >=2 or more
            try {
                min = Integer.parseInt(minOccurs);
            }
            catch (Exception e) {
                reportSchemaError(SchemaMessageProvider.GenericError,
                                  new Object [] { "illegal value for minOccurs : '" +e.getMessage()+ "' " });
            }
            if (min<2) {
                //REVISIT: report Error here
            }

            // => a,a,..,a+
            index = fSchemaGrammar.addContentSpecNode( XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE,
                   index,
                   -1,
                   false);

            for (int i=0; i < (min-1); i++) {
                index = fSchemaGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_SEQ,
                                                      leafIndex,
                                                      index,
                                                      false);
            }

        }
        else {
            // {n,m} => a,a,a,...(a),(a),...
            try {
                min = Integer.parseInt(minOccurs);
                max = Integer.parseInt(maxOccurs);
            }
            catch (Exception e){
                reportSchemaError(SchemaMessageProvider.GenericError,
                                  new Object [] { "illegal value for minOccurs or maxOccurs : '" +e.getMessage()+ "' "});
            }
            if (min==0) {
                int optional = fSchemaGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE,
                                                                 leafIndex,
                                                                 -1,
                                                                 false);
                index = optional;
                for (int i=0; i < (max-min-1); i++) {
                    index = fSchemaGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_SEQ,
                                                              index,
                                                              optional,
                                                              false);
                }
            }
            else {
                for (int i=0; i<(min-1); i++) {
                    index = fSchemaGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_SEQ,
                                                          index,
                                                          leafIndex,
                                                          false);
                }

                int optional = fSchemaGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE,
                                                                 leafIndex,
                                                                 -1,
                                                                 false);
                for (int i=0; i < (max-min); i++) {
                    index = fSchemaGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_SEQ,
                                                              index,
                                                              optional,
                                                              false);
                }
            }
        }

        return index;
    }

    /**
     * Traverses Schema attribute declaration.
     *  
     *       <attribute
     *         form = qualified | unqualified
     *         id = ID
     *         name = NCName
     *         ref = QName
     *         type = QName
     *         use = default | fixed | optional | prohibited | required
     *         value = string>
     *         Content: (annotation? , simpleType?)
     *       <attribute/>
     *
     * @param attributeDecl: the declaration of the attribute under
   *     consideration
   * @param typeInfo: Contains the index of the element to which
   *     the attribute declaration is attached.
   * @param referredTo:  true iff traverseAttributeDecl was called because
   *    of encountering a ``ref''property (used
   *    to suppress error-reporting).
     * @return
     * @exception Exception
     */
    private int traverseAttributeDecl( Element attrDecl, ComplexTypeInfo typeInfo, boolean referredTo ) throws Exception {
        String attNameStr    = attrDecl.getAttribute(SchemaSymbols.ATT_NAME);
        int attName          = fStringPool.addSymbol(attNameStr);// attribute name
        String isQName       = attrDecl.getAttribute(SchemaSymbols.ATT_FORM);//form attribute
    boolean isAttrTopLevel = isTopLevel(attrDecl);
   
        DatatypeValidator dv = null;
        // attribute type
        int attType          = -1;
        boolean attIsList    = false;
        int dataTypeSymbol   = -1;

        String ref       = attrDecl.getAttribute(SchemaSymbols.ATT_REF);
        String datatype  = attrDecl.getAttribute(SchemaSymbols.ATT_TYPE);
    // various tests if 'ref' is present:
    if(!ref.equals("")) {
      if(isAttrTopLevel)
        // REVISIT:  localize
               reportGenericSchemaError ( "An attribute with \"ref\" present must not have <schema> as its parent");
      if(!attNameStr.equals(""))
        // REVISIT:  localize
               reportGenericSchemaError ( "Attribute " + attNameStr + " cannot refer to another attribute, but it refers to " + ref);
      if(!datatype.equals(""))
        // REVISIT:  localize
                 reportGenericSchemaError ( "Attribute with reference " + ref + " cannot also contain a type");
          if(!attrDecl.getAttribute(SchemaSymbols.ATT_FORM).equals(""))
        // REVISIT:  localize
                 reportGenericSchemaError ( "Attribute with reference " + ref + " cannot also contain a \"form\" property");
          if(!attrDecl.getAttribute(SchemaSymbols.ATT_VALUE).equals(""))
        // REVISIT:  localize
                 reportGenericSchemaError ( "Attribute with reference " + ref + " cannot also contain a value");
    }
    Element simpleTypeChild = findAttributeSimpleType(attrDecl);

        String localpart = null;

        String  use      = attrDecl.getAttribute(SchemaSymbols.ATT_USE);
        boolean prohibited = use.equals(SchemaSymbols.ATTVAL_PROHIBITED);
        boolean required = use.equals(SchemaSymbols.ATTVAL_REQUIRED);

    if (!ref.equals("")) {
            if(simpleTypeChild != null)
        // REVISIT:  localize
                 reportGenericSchemaError ( "an attribute with ref present cannot contain a simpleType");
            String prefix = "";
            localpart = ref;
            int colonptr = ref.indexOf(":");
            if ( colonptr > 0) {
                prefix = ref.substring(0,colonptr);
                localpart = ref.substring(colonptr+1);
            }
            String uriStr = resolvePrefixToURI(prefix);

            if (!uriStr.equals(fTargetNSURIString)) {
                addAttributeDeclFromAnotherSchema(localpart, uriStr, typeInfo);

                return -1;
            }

            Element referredAttribute = getTopLevelComponentByName(SchemaSymbols.ELT_ATTRIBUTE,localpart);
            if (referredAttribute != null) {
        if (typeInfo != null) {
          // don't need to traverse ref'd attribute if we're global; just make sure it's there...
                    traverseAttributeDecl(referredAttribute, typeInfo, true);
          // this nasty hack needed to ``override'' the "use" on the
          // global attribute with that on the ref'ing attribute.
          int referredAttName = fStringPool.addSymbol(referredAttribute.getAttribute(SchemaSymbols.ATT_NAME));
              int uriIndex = StringPool.EMPTY_STRING;
              if ( fTargetNSURIString.length() > 0) {
                      uriIndex = fTargetNSURI;
              }
              QName referredAttQName = new QName(-1,referredAttName,referredAttName,uriIndex);
          if (prohibited) {
                    int tempIndex = fSchemaGrammar.getAttributeDeclIndex(typeInfo.templateElementIndex, referredAttQName);
            XMLAttributeDecl referredAttrDecl = new XMLAttributeDecl();
            fSchemaGrammar.getAttributeDecl(tempIndex, referredAttrDecl);
            referredAttrDecl.defaultType = XMLAttributeDecl.DEFAULT_TYPE_PROHIBITED;
            fSchemaGrammar.setAttributeDecl(typeInfo.templateElementIndex, tempIndex, referredAttrDecl);
          }
          else if (required) {
            int tempIndex = fSchemaGrammar.getAttributeDeclIndex(typeInfo.templateElementIndex, referredAttQName);
            XMLAttributeDecl referredAttrDecl = new XMLAttributeDecl();
            fSchemaGrammar.getAttributeDecl(tempIndex, referredAttrDecl);
            // now two cases:  if it's othre than fixed, no problem, just overwrite. 
            // but if it is *it* fixed, specs demand attr be treated as both fixed and required.
            if(referredAttrDecl.defaultType == XMLAttributeDecl.DEFAULT_TYPE_FIXED)
              referredAttrDecl.defaultType = XMLAttributeDecl.DEFAULT_TYPE_REQUIRED_AND_FIXED;
            else
              referredAttrDecl.defaultType = XMLAttributeDecl.DEFAULT_TYPE_REQUIRED;
            fSchemaGrammar.setAttributeDecl(typeInfo.templateElementIndex, tempIndex, referredAttrDecl);
          }
              }
      }
            else {

                if (fAttributeDeclRegistry.get(localpart) != null) {
                    addAttributeDeclFromAnotherSchema(localpart, uriStr, typeInfo);
                }
                else
                    // REVISIT: Localize
                    reportGenericSchemaError ( "Couldn't find top level attribute " + ref);
            }
            return -1;
        } else if (attNameStr.equals(""))
      // REVISIT:  localize
             reportGenericSchemaError ( "An attribute must have a ref or a name!");

        if (datatype.equals("")) {
            if (simpleTypeChild != null) {
                attType        = XMLAttributeDecl.TYPE_SIMPLE;
                dataTypeSymbol = traverseSimpleTypeDecl(simpleTypeChild);
                localpart = fStringPool.toString(dataTypeSymbol);
            }
            else {
                attType        = XMLAttributeDecl.TYPE_SIMPLE;
                localpart      = "string";
                dataTypeSymbol = fStringPool.addSymbol(localpart);
            }
            localpart = fStringPool.toString(dataTypeSymbol);

            dv = fDatatypeRegistry.getDatatypeValidator(localpart);

        } else {
      if(simpleTypeChild != null && !referredTo)
              reportGenericSchemaError("Attribute declarations may not contain both a type and a simpleType declaration");

            String prefix = "";
            localpart = datatype;
            dataTypeSymbol = fStringPool.addSymbol(localpart);

            int  colonptr = datatype.indexOf(":");
            if ( colonptr > 0) {
                prefix = datatype.substring(0,colonptr);
                localpart = datatype.substring(colonptr+1);
            }
            String typeURI = resolvePrefixToURI(prefix);

            if ( typeURI.equals(SchemaSymbols.URI_SCHEMAFORSCHEMA)
                 || typeURI.length()==0) {

                dv = getDatatypeValidator("", localpart);

                if (localpart.equals("ID")) {
                    attType = XMLAttributeDecl.TYPE_ID;
                } else if (localpart.equals("IDREF")) {
                    attType = XMLAttributeDecl.TYPE_IDREF;
                } else if (localpart.equals("IDREFS")) {
                    attType = XMLAttributeDecl.TYPE_IDREF;
                    attIsList = true;
                } else if (localpart.equals("ENTITY")) {
                    attType = XMLAttributeDecl.TYPE_ENTITY;
                } else if (localpart.equals("ENTITIES")) {
                    attType = XMLAttributeDecl.TYPE_ENTITY;
                    attIsList = true;
                } else if (localpart.equals("NMTOKEN")) {
                    attType = XMLAttributeDecl.TYPE_NMTOKEN;
                } else if (localpart.equals("NMTOKENS")) {
                    attType = XMLAttributeDecl.TYPE_NMTOKEN;
                    attIsList = true;
                } else if (localpart.equals(SchemaSymbols.ELT_NOTATION)) {
                    attType = XMLAttributeDecl.TYPE_NOTATION;
                }
                else {
                    attType = XMLAttributeDecl.TYPE_SIMPLE;
                    if (dv == null && typeURI.length() == 0) {
                        Element topleveltype = getTopLevelComponentByName(SchemaSymbols.ELT_SIMPLETYPE, localpart);
                        if (topleveltype != null) {
                            traverseSimpleTypeDecl( topleveltype );
                            dv = getDatatypeValidator(typeURI, localpart);
                        }else if (!referredTo) {
                            // REVISIT: Localize
                            reportGenericSchemaError("simpleType not found : " + "("+typeURI+":"+localpart+")");
                        }
                    }
                }
            } else { //isn't of the schema for schemas namespace...

                // check if the type is from the same Schema

                dv = getDatatypeValidator(typeURI, localpart);
                if (dv == null && typeURI.equals(fTargetNSURIString) ) {
                    Element topleveltype = getTopLevelComponentByName(SchemaSymbols.ELT_SIMPLETYPE, localpart);
                    if (topleveltype != null) {
                        traverseSimpleTypeDecl( topleveltype );
                        dv = getDatatypeValidator(typeURI, localpart);
                    }else if (!referredTo) {
                        // REVISIT: Localize
                        reportGenericSchemaError("simpleType not found : " + "("+typeURI+":"+ localpart+")");
                    }
                }

                attType = XMLAttributeDecl.TYPE_SIMPLE;
            }

        }


        // attribute default type
        int attDefaultType = -1;
        int attDefaultValue = -1;

        if (dv == null && !referredTo) {
            // REVISIT: Localize
            reportGenericSchemaError("could not resolve the type or get a null validator for datatype : "
                                     + fStringPool.toString(dataTypeSymbol));
        }

        String fixed = attrDecl.getAttribute(SchemaSymbols.ATT_VALUE);
    if (isAttrTopLevel) {
            if (!fixed.equals("")) {
        if((required || prohibited
            || use.equals(SchemaSymbols.ATTVAL_OPTIONAL)) && !referredTo)
                // REVISIT: Localize
                reportGenericSchemaError("Globally-declared attributes containing values must have \"use\" set to \"FIXED\" or \"DEFAULT\", not " +
            use);
        else if (use.equals("") && !referredTo)
                // REVISIT: Localize
          reportGenericSchemaError("Globally-declared attributes containing values MUST have \"use\" present and set to \"FIXED\" or \"DEFAULT\"");
              else if (use.equals(SchemaSymbols.ATTVAL_FIXED))  {
                     attDefaultType = XMLAttributeDecl.DEFAULT_TYPE_FIXED;
                     attDefaultValue = fStringPool.addString(fixed);
        }
        else {
                     attDefaultType = XMLAttributeDecl.DEFAULT_TYPE_DEFAULT;
                     attDefaultValue = fStringPool.addString(fixed);
        }
      }
      else { // no value and we're at top level.
              if (!use.equals("") && !referredTo
                // REVISIT: Localize
          reportGenericSchemaError("Globally-declared attributes containing no value may not have \"use\" present");
              else
                   attDefaultType = XMLAttributeDecl.DEFAULT_TYPE_IMPLIED;
      }
    }
    else { // not at top-level...
      // case where "ref" present taken care of above.
            if (!fixed.equals("")) {
        if(required || prohibited
            || use.equals(SchemaSymbols.ATTVAL_OPTIONAL))
                reportGenericSchemaError("Locally-declared attributes containing values must have \"use\" set to \"FIXED\" or \"DEFAULT\", not " +
            use);
        else if (use.equals(""))
                // REVISIT: Localize
          reportGenericSchemaError("Locally-declared attributes containing values MUST have \"use\" present and set to \"FIXED\" or \"DEFAULT\"");
              else if (use.equals(SchemaSymbols.ATTVAL_FIXED))  {
                     attDefaultType = XMLAttributeDecl.DEFAULT_TYPE_FIXED;
                     attDefaultValue = fStringPool.addString(fixed);
        }
        else {
                     attDefaultType = XMLAttributeDecl.DEFAULT_TYPE_DEFAULT;
                     attDefaultValue = fStringPool.addString(fixed);
        }
      }
      else { // no value and we're not at top level.
        if(required)
                     attDefaultType = XMLAttributeDecl.DEFAULT_TYPE_REQUIRED;
        else if (prohibited
                     attDefaultType = XMLAttributeDecl.DEFAULT_TYPE_PROHIBITED;
        // no other case is defined by the specs, so treat as implied...
              else
                   attDefaultType = XMLAttributeDecl.DEFAULT_TYPE_IMPLIED;
      }
    }

        // check default value is valid for the datatype. 
        if (attType == XMLAttributeDecl.TYPE_SIMPLE && attDefaultValue != -1) {
            try {
                if (dv != null)
                    //REVISIT
                    dv.validate(fStringPool.toString(attDefaultValue), null);
                else if (!referredTo)
                    reportSchemaError(SchemaMessageProvider.NoValidatorFor,
                            new Object [] { datatype });
            } catch (InvalidDatatypeValueException idve) {
        if (!referredTo)
                  reportSchemaError(SchemaMessageProvider.IncorrectDefaultType,
                        new Object [] { attrDecl.getAttribute(SchemaSymbols.ATT_NAME), idve.getMessage() });
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("Internal error in attribute datatype validation");
            }
        }

        /***/
        // REVISIT: I don't think this code is right. The attribute
        //          should take on the target namespace of the grammar
        //          if present. -Ac
        int uriIndex = StringPool.EMPTY_STRING;
        // refer to 4.3.1 in "XML Schema Part 1: Structures"
        if ( fTargetNSURIString.length() > 0) {
                if ( isAttrTopLevel ||
                    (( !isQName.equals(SchemaSymbols.ATTVAL_UNQUALIFIED)) &&
                        ( isQName.equals(SchemaSymbols.ATTVAL_QUALIFIED)||
                         fAttributeDefaultQualified )))
                    uriIndex = fTargetNSURI;
        }
        /***
        int uriIndex = fTargetNSURI;
        /***/

        QName attQName = new QName(-1,attName,attName,uriIndex);
        if ( DEBUGGING )
            System.out.println(" the dataType Validator for " + fStringPool.toString(attName) + " is " + dv);

        //put the top-levels in the attribute decl registry.
        if (isAttrTopLevel) {
            fTempAttributeDecl.datatypeValidator = dv;
            fTempAttributeDecl.name.setValues(attQName);
            fTempAttributeDecl.type = attType;
            fTempAttributeDecl.defaultType = attDefaultType;
            fTempAttributeDecl.list = attIsList;
            if (attDefaultValue != -1 ) {
                fTempAttributeDecl.defaultValue = new String(fStringPool.toString(attDefaultValue));
            }
            fAttributeDeclRegistry.put(attNameStr, new XMLAttributeDecl(fTempAttributeDecl));
        }

        // add attribute to attr decl pool in fSchemaGrammar,
        if (typeInfo != null) {
            fSchemaGrammar.addAttDef( typeInfo.templateElementIndex,
                                      attQName, attType,
                                      dataTypeSymbol, attDefaultType,
                                      fStringPool.toString( attDefaultValue), dv, attIsList);
        }
        return -1;
    } // end of method traverseAttribute

    private int addAttributeDeclFromAnotherSchema( String name, String uriStr, ComplexTypeInfo typeInfo) throws Exception {
        SchemaGrammar aGrammar = (SchemaGrammar) fGrammarResolver.getGrammar(uriStr);
        if (uriStr == null || ! (aGrammar instanceof SchemaGrammar) ) {
            // REVISIT: Localize
            reportGenericSchemaError("!!Schema not found in #addAttributeDeclFromAnotherSchema, schema uri : " + uriStr);
            return -1;
        }

        Hashtable attrRegistry = aGrammar.getAttirubteDeclRegistry();
        if (attrRegistry == null) {
            // REVISIT: Localize
            reportGenericSchemaError("no attribute was defined in schema : " + uriStr);
            return -1;
        }

        XMLAttributeDecl tempAttrDecl = (XMLAttributeDecl) attrRegistry.get(name);

        if (tempAttrDecl == null) {
            // REVISIT: Localize
            reportGenericSchemaError( "no attribute named \"" + name
                                      + "\" was defined in schema : " + uriStr);
            return -1;
        }


        if (typeInfo!= null) {
            fSchemaGrammar.addAttDef( typeInfo.templateElementIndex,
                                      tempAttrDecl.name, tempAttrDecl.type,
                                      -1, tempAttrDecl.defaultType,
                                      tempAttrDecl.defaultValue,
                                      tempAttrDecl.datatypeValidator,
                                      tempAttrDecl.list);
        }


        return 0;
    }

    /*
    *
    * <attributeGroup
    *   id = ID
    *   name = NCName
    *   ref = QName>
    *   Content: (annotation?, (attribute|attributeGroup)*, anyAttribute?)
    * </>
    *
    */
    private int traverseAttributeGroupDecl( Element attrGrpDecl, ComplexTypeInfo typeInfo, Vector anyAttDecls ) throws Exception {
        // attributeGroup name
        String attGrpNameStr = attrGrpDecl.getAttribute(SchemaSymbols.ATT_NAME);
        int attGrpName = fStringPool.addSymbol(attGrpNameStr);
       
        String ref = attrGrpDecl.getAttribute(SchemaSymbols.ATT_REF);
    Element child = checkContent( attrGrpDecl, XUtil.getFirstChildElement(attrGrpDecl), true );

        if (!ref.equals("")) {
      if(isTopLevel(attrGrpDecl))
        // REVISIT:  localize
               reportGenericSchemaError ( "An attributeGroup with \"ref\" present must not have <schema> or <redefine> as its parent");
      if(!attGrpNameStr.equals(""))
        // REVISIT:  localize
               reportGenericSchemaError ( "attributeGroup " + attGrpNameStr + " cannot refer to another attributeGroup, but it refers to " + ref);
           
            String prefix = "";
            String localpart = ref;
            int colonptr = ref.indexOf(":");
            if ( colonptr > 0) {
                prefix = ref.substring(0,colonptr);
                localpart = ref.substring(colonptr+1);
            }
            String uriStr = resolvePrefixToURI(prefix);
            if (!uriStr.equals(fTargetNSURIString)) {
               
                traverseAttributeGroupDeclFromAnotherSchema(localpart, uriStr, typeInfo, anyAttDecls);

                return -1;
                // TO DO
                // REVISIST: different NS, not supported yet.
                // REVISIT: Localize
                //reportGenericSchemaError("Feature not supported: see an attribute from different NS");
            }
      if(typeInfo != null) {
         // only do this if we're traversing because we were ref'd here; when we come
        // upon this decl by itself we're just validating.
              Element referredAttrGrp = getTopLevelComponentByName(SchemaSymbols.ELT_ATTRIBUTEGROUP,localpart);
              if (referredAttrGrp != null) {
                  traverseAttributeGroupDecl(referredAttrGrp, typeInfo, anyAttDecls);
              }
              else {
                  // REVISIT: Localize
                  reportGenericSchemaError ( "Couldn't find top level attributeGroup " + ref);
              }
         return -1;
      }
        } else if (attGrpNameStr.equals(""))
        // REVISIT:  localize
                reportGenericSchemaError ( "an attributeGroup must have a name or a ref attribute present");

        for (;
             child != null ; child = XUtil.getNextSiblingElement(child)) {
      
            if ( child.getLocalName().equals(SchemaSymbols.ELT_ATTRIBUTE) ){
                traverseAttributeDecl(child, typeInfo, false);
            }
            else if ( child.getLocalName().equals(SchemaSymbols.ELT_ATTRIBUTEGROUP) ) {
        if(typeInfo != null)
           // only do this if we're traversing because we were ref'd here; when we come
          // upon this decl by itself we're just validating.
                  traverseAttributeGroupDecl(child, typeInfo,anyAttDecls);
            }
            else
        break;
        }
    if (child != null) {
      if ( child.getLocalName().equals(SchemaSymbols.ELT_ANYATTRIBUTE) ) {
                if (anyAttDecls != null) {
                     anyAttDecls.addElement(traverseAnyAttribute(child));
                }
        if (XUtil.getNextSiblingElement(child) != null)
          // REVISIT:  localize
                  reportGenericSchemaError ( "An attributeGroup declaration cannot have any children after an anyAttribute declaration");
        return -1;
      }
      else
        // REVISIT:  localize
                 reportGenericSchemaError ( "An attributeGroup declaration must only contain attribute, attributeGroup and anyAttribute elements");
    }
        return -1;
    } // end of method traverseAttributeGroup
   
    private int traverseAttributeGroupDeclFromAnotherSchema( String attGrpName , String uriStr,
                                                             ComplexTypeInfo typeInfo,
                                                             Vector anyAttDecls ) throws Exception {
       
        SchemaGrammar aGrammar = (SchemaGrammar) fGrammarResolver.getGrammar(uriStr);
        if (uriStr == null || aGrammar == null || ! (aGrammar instanceof SchemaGrammar) ) {
            // REVISIT: Localize
            reportGenericSchemaError("!!Schema not found in #traverseAttributeGroupDeclFromAnotherSchema, schema uri : " + uriStr);
            return -1;
        }
        // attribute name
        Element attGrpDecl = (Element) aGrammar.topLevelAttrGrpDecls.get((Object)attGrpName);
        if (attGrpDecl == null) {
            // REVISIT: Localize
            reportGenericSchemaError( "no attribute group named \"" + attGrpName
                                      + "\" was defined in schema : " + uriStr);
            return -1;
        }
       
        NamespacesScope saveNSMapping = fNamespacesScope;
        int saveTargetNSUri = fTargetNSURI;
        fTargetNSURI = fStringPool.addSymbol(aGrammar.getTargetNamespaceURI());
        fNamespacesScope = aGrammar.getNamespacesScope();

        // attribute type
        int attType = -1;
        int enumeration = -1;


        Element child = checkContent(attGrpDecl, XUtil.getFirstChildElement(attGrpDecl), true);
        for (;
             child != null ; child = XUtil.getNextSiblingElement(child)) {

            //child attribute couldn't be a top-level attribute DEFINITION,
            if ( child.getLocalName().equals(SchemaSymbols.ELT_ATTRIBUTE) ){
                String childAttName = child.getAttribute(SchemaSymbols.ATT_NAME);
                if ( childAttName.length() > 0 ) {
                    Hashtable attDeclRegistry = aGrammar.getAttirubteDeclRegistry();
                    if (attDeclRegistry != null) {
                        if (attDeclRegistry.get((Object)childAttName) != null ){
                            addAttributeDeclFromAnotherSchema(childAttName, uriStr, typeInfo);
                            return -1;
                        }
                    }      
                }
                else
                    traverseAttributeDecl(child, typeInfo, false);
            }
            else if ( child.getLocalName().equals(SchemaSymbols.ELT_ATTRIBUTEGROUP) ) {
                traverseAttributeGroupDecl(child, typeInfo, anyAttDecls);
            }
            else if ( child.getLocalName().equals(SchemaSymbols.ELT_ANYATTRIBUTE) ) {
                anyAttDecls.addElement(traverseAnyAttribute(child));
                break;
            }
            else {
                // REVISIT: Localize
                reportGenericSchemaError("Invalid content for attributeGroup");
            }
        }

        fNamespacesScope = saveNSMapping;
        fTargetNSURI = saveTargetNSUri;
        if(child != null) {
            // REVISIT: Localize
            reportGenericSchemaError("Invalid content for attributeGroup");
        }
        return -1;
    } // end of method traverseAttributeGroupFromAnotherSchema
   
  // This simple method takes an attribute declaration as a parameter and
  // returns null if there is no simpleType defined or the simpleType
  // declaration if one exists.  It also throws an error if more than one
  // <annotation> or <simpleType> group is present.
  private Element findAttributeSimpleType(Element attrDecl) throws Exception {
    Element child = XUtil.getFirstChildElement(attrDecl);
       if (child == null)
         return null;
    if (child.getLocalName().equals(SchemaSymbols.ELT_SIMPLETYPE))
      return child;
    if (child.getLocalName().equals(SchemaSymbols.ELT_ANNOTATION)) {
          traverseAnnotationDecl(child);
      child = XUtil.getNextSiblingElement(child);
    }
       if (child == null)
         return null;
    if (child.getLocalName().equals(SchemaSymbols.ELT_SIMPLETYPE) &&
        XUtil.getNextSiblingElement(child) == null)
      return child;
    //REVISIT: localize
    reportGenericSchemaError ( "An attribute declaration must contain at most one annotation preceding at most one simpleType");
    return null;
  } // end findAttributeSimpleType

    /**
     * Traverse element declaration:
     *  <element
     *         abstract = boolean
     *         block = #all or (possibly empty) subset of {substitutionGroup, extension, restriction}
     *         default = string
     *         substitutionGroup = QName
     *         final = #all or (possibly empty) subset of {extension, restriction}
     *         fixed = string
     *         form = qualified | unqualified
     *         id = ID
     *         maxOccurs = string
     *         minOccurs = nonNegativeInteger
     *         name = NCName
     *         nullable = boolean
     *         ref = QName
     *         type = QName>
     *   Content: (annotation? , (simpleType | complexType)? , (unique | key | keyref)*)
     *   </element>
     *
     *
     *       The following are identity-constraint definitions
     *        <unique
     *         id = ID
     *         name = NCName>
     *         Content: (annotation? , (selector , field+))
     *       </unique>
     *      
     *       <key
     *         id = ID
     *         name = NCName>
     *         Content: (annotation? , (selector , field+))
     *       </key>
     *      
     *       <keyref
     *         id = ID
     *         name = NCName
     *         refer = QName>
     *         Content: (annotation? , (selector , field+))
     *       </keyref>
     *      
     *       <selector>
     *         Content: XPathExprApprox : An XPath expression
     *       </selector>
     *      
     *       <field>
     *         Content: XPathExprApprox : An XPath expression
     *       </field>
     *      
     *
     * @param elementDecl
     * @return
     * @exception Exception
     */
    private QName traverseElementDecl(Element elementDecl) throws Exception {

        int contentSpecType      = -1;
        int contentSpecNodeIndex = -1;
        int typeNameIndex = -1;
        int scopeDefined = -2; //signal a error if -2 gets gets through
                                //cause scope can never be -2.
        DatatypeValidator dv = null;



        String name = elementDecl.getAttribute(SchemaSymbols.ATT_NAME);

        if ( DEBUGGING )
            System.out.println("traversing element decl : " + name );

        String ref = elementDecl.getAttribute(SchemaSymbols.ATT_REF);
        String type = elementDecl.getAttribute(SchemaSymbols.ATT_TYPE);
        String minOccurs = elementDecl.getAttribute(SchemaSymbols.ATT_MINOCCURS);
        String maxOccurs = elementDecl.getAttribute(SchemaSymbols.ATT_MAXOCCURS);
        String dflt = elementDecl.getAttribute(SchemaSymbols.ATT_DEFAULT);
        String fixed = elementDecl.getAttribute(SchemaSymbols.ATT_FIXED);
    if(!(dflt.equals("") || fixed.equals("")))
      // REVISIT:  localize
      reportGenericSchemaError("an element cannot have both \"fixed\" and \"default\" present at the same time");
        String substitutionGroup = elementDecl.getAttribute(SchemaSymbols.ATT_SUBSTITUTIONGROUP);
        // form attribute
        String isQName = elementDecl.getAttribute(SchemaSymbols.ATT_FORM);

        String fromAnotherSchema = null;

        if (isTopLevel(elementDecl)) {
      if(name.equals(""))
        // REVISIT:  localize
                reportGenericSchemaError("globally-declared element must have a name");
      else if (!ref.equals(""))
        // REVISIT:  localize
                reportGenericSchemaError("globally-declared element " + name + " cannot have a ref attribute");
       
            int nameIndex = fStringPool.addSymbol(name);
            int eltKey = fSchemaGrammar.getElementDeclIndex(fTargetNSURI, nameIndex,TOP_LEVEL_SCOPE);
            if (eltKey > -1 ) {
                return new QName(-1,nameIndex,nameIndex,fTargetNSURI);
            }
        }
       
        // parse out 'block', 'final', 'nullable', 'abstract'
        int blockSet = parseBlockSet(elementDecl.getAttribute(SchemaSymbols.ATT_BLOCK));
        int finalSet = parseFinalSet(elementDecl.getAttribute(SchemaSymbols.ATT_FINAL));
        boolean isNullable = elementDecl.getAttribute
            (SchemaSymbols.ATT_NULLABLE).equals(SchemaSymbols.ATTVAL_TRUE)? true:false;
        boolean isAbstract = elementDecl.getAttribute
            (SchemaSymbols.ATT_ABSTRACT).equals(SchemaSymbols.ATTVAL_TRUE)? true:false;
        int elementMiscFlags = 0;
        if (isNullable) {
            elementMiscFlags += SchemaSymbols.NULLABLE;
        }
        if (isAbstract) {
            elementMiscFlags += SchemaSymbols.ABSTRACT;
        }

        //if this is a reference to a global element
        if (!ref.equals("")) {
            //REVISIT top level check for ref
          if (!type.equals("") || (elementMiscFlags > 0)
          || (finalSet > 0) || (blockSet > 0)
          || !dflt.equals("") || !fixed.equals(""))
              reportSchemaError(SchemaMessageProvider.BadAttWithRef, null);
      if (!name.equals(""))
                // REVISIT: Localize
                reportGenericSchemaError("element " + name + " cannot also have a ref attribute");

            Element child = XUtil.getFirstChildElement(elementDecl);
          if(child != null && child.getLocalName().equals(SchemaSymbols.ELT_ANNOTATION)) {
              if (XUtil.getNextSiblingElement(child) != null)
                  reportSchemaError(SchemaMessageProvider.NoContentForRef, null);
        else
          traverseAnnotationDecl(child);
      }
      else if (child != null)
                reportSchemaError(SchemaMessageProvider.NoContentForRef, null);
            String prefix = "";
            String localpart = ref;
            int colonptr = ref.indexOf(":");
            if ( colonptr > 0) {
                prefix = ref.substring(0,colonptr);
                localpart = ref.substring(colonptr+1);
            }
            int localpartIndex = fStringPool.addSymbol(localpart);
            String uriString = resolvePrefixToURI(prefix);
            QName eltName = new QName(prefix != null ? fStringPool.addSymbol(prefix) : -1,
                                      localpartIndex,
                                      fStringPool.addSymbol(ref),
                                      uriString != null ? fStringPool.addSymbol(uriString) : StringPool.EMPTY_STRING);

            //if from another schema, just return the element QName
            if (! uriString.equals(fTargetNSURIString) ) {
                return eltName;
            }

            int elementIndex = fSchemaGrammar.getElementDeclIndex(eltName, TOP_LEVEL_SCOPE);
            //if not found, traverse the top level element that if referenced

            if (elementIndex == -1 ) {
                Element targetElement = getTopLevelComponentByName(SchemaSymbols.ELT_ELEMENT,localpart);
                if (targetElement == null ) {
                    // REVISIT: Localize
                    reportGenericSchemaError("Element " + localpart + " not found in the Schema");
                    //REVISIT, for now, the QName anyway
                    return eltName;
                    //return new QName(-1,fStringPool.addSymbol(localpart), -1, fStringPool.addSymbol(uriString));
                }
                else {
                    // do nothing here, other wise would cause infinite loop for
                    //   <element name="recur"><complexType><element ref="recur"> ...
                    //eltName= traverseElementDecl(targetElement);
                }
            }
            return eltName;
        } else if (name.equals(""))
            // REVISIT: Localize
            reportGenericSchemaError("a local element must have a name or a ref attribute present");

               
        // Handle the substitutionGroup
        Element substitutionGroupElementDecl = null;
        int substitutionGroupElementDeclIndex = -1;
        boolean noErrorSoFar = true;
        String substitutionGroupUri = null;
        String substitutionGroupLocalpart = null;
        String substitutionGroupFullName = null;
        ComplexTypeInfo substitutionGroupEltTypeInfo = null;
        DatatypeValidator substitutionGroupEltDV = null;

        if ( substitutionGroup.length() > 0 ) {
            if(!ref.equals(""))
                // REVISIT: Localize
                reportGenericSchemaError("a local element cannot have a substitutionGroup");
            substitutionGroupUri =  resolvePrefixToURI(getPrefix(substitutionGroup));
            substitutionGroupLocalpart = getLocalPart(substitutionGroup);
            substitutionGroupFullName = substitutionGroupUri+","+substitutionGroupLocalpart;
          
            if ( !substitutionGroupUri.equals(fTargetNSURIString) ) { 
                substitutionGroupEltTypeInfo = getElementDeclTypeInfoFromNS(substitutionGroupUri, substitutionGroupLocalpart);
                if (substitutionGroupEltTypeInfo == null) {
                    substitutionGroupEltDV = getElementDeclTypeValidatorFromNS(substitutionGroupUri, substitutionGroupLocalpart);
                    if (substitutionGroupEltDV == null) {
                        //TO DO: report error here;
                        noErrorSoFar = false;
                        reportGenericSchemaError("Could not find type for element '" +substitutionGroupLocalpart
                                                 + "' in schema '" + substitutionGroupUri+"'");
                    }
                }
            }
            else {
                substitutionGroupElementDecl = getTopLevelComponentByName(SchemaSymbols.ELT_ELEMENT, substitutionGroupLocalpart);
                if (substitutionGroupElementDecl == null) {
                    substitutionGroupElementDeclIndex =
                        fSchemaGrammar.getElementDeclIndex(fTargetNSURI, getLocalPartIndex(substitutionGroup),TOP_LEVEL_SCOPE);
                    if ( substitutionGroupElementDeclIndex == -1) {
                        noErrorSoFar = false;
                        // REVISIT: Localize
                        reportGenericSchemaError("substitutionGroup affiliation element "
                                                  +substitutionGroup
                                                  +" in element declaration "
                                                  +name)
                    }
                }
                else {
                    substitutionGroupElementDeclIndex =
                        fSchemaGrammar.getElementDeclIndex(fTargetNSURI, getLocalPartIndex(substitutionGroup),TOP_LEVEL_SCOPE);

                    if ( substitutionGroupElementDeclIndex == -1) {
                        traverseElementDecl(substitutionGroupElementDecl);
                        substitutionGroupElementDeclIndex =
                            fSchemaGrammar.getElementDeclIndex(fTargetNSURI, getLocalPartIndex(substitutionGroup),TOP_LEVEL_SCOPE);
                    }
                }

                if (substitutionGroupElementDeclIndex != -1) {
                    substitutionGroupEltTypeInfo = fSchemaGrammar.getElementComplexTypeInfo( substitutionGroupElementDeclIndex );
                    if (substitutionGroupEltTypeInfo == null) {
                        fSchemaGrammar.getElementDecl(substitutionGroupElementDeclIndex, fTempElementDecl);
                        substitutionGroupEltDV = fTempElementDecl.datatypeValidator;
                        if (substitutionGroupEltDV == null) {
                            //TO DO: report error here;
                            noErrorSoFar = false;
                            reportGenericSchemaError("Could not find type for element '" +substitutionGroupLocalpart
                                                     + "' in schema '" + substitutionGroupUri+"'");
                        }
                    }
                }
            }
        }
       

        //
        // resolving the type for this element right here
        //

        ComplexTypeInfo typeInfo = null;

        // element has a single child element, either a datatype or a type, null if primitive
        Element child = XUtil.getFirstChildElement(elementDecl);
       
        if(child != null && child.getLocalName().equals(SchemaSymbols.ELT_ANNOTATION)) {
      traverseAnnotationDecl(child);
            child = XUtil.getNextSiblingElement(child);
    }
        if(child != null && child.getLocalName().equals(SchemaSymbols.ELT_ANNOTATION))
            // REVISIT: Localize
            reportGenericSchemaError("element declarations can contain at most one annotation Element Information Item");
       
        boolean haveAnonType = false;

        // Handle Anonymous type if there is one
        if (child != null) {
           
            String childName = child.getLocalName();
           
            if (childName.equals(SchemaSymbols.ELT_COMPLEXTYPE)) {
                if (child.getAttribute(SchemaSymbols.ATT_NAME).length() > 0) {
                    noErrorSoFar = false;
                    // REVISIT: Localize
                    reportGenericSchemaError("anonymous complexType in element '" + name +"' has a name attribute");
                }

                else {
                    // Determine what the type name will be
                    String anonTypeName = genAnonTypeName(child);
                    if (fCurrentTypeNameStack.search((Object)anonTypeName) > - 1) {
                        // A recursing element using an anonymous type

                        int uriInd = StringPool.EMPTY_STRING;
                        if ( isQName.equals(SchemaSymbols.ATTVAL_QUALIFIED)||
                             fElementDefaultQualified) {
                             uriInd = fTargetNSURI;
                        }
                        int nameIndex = fStringPool.addSymbol(name);
                        QName tempQName = new QName(fCurrentScope, nameIndex, nameIndex, uriInd);
                        fElementRecurseComplex.put(tempQName, anonTypeName);
                        return new QName(-1, nameIndex, nameIndex, uriInd);

                    }
                    else {
                        typeNameIndex = traverseComplexTypeDecl(child);
                        if (typeNameIndex != -1 ) {
                            typeInfo = (ComplexTypeInfo)
                                fComplexTypeRegistry.get(fStringPool.toString(typeNameIndex));
                        }
                        else {
                            noErrorSoFar = false;
                            // REVISIT: Localize
                            reportGenericSchemaError("traverse complexType error in element '" + name +"'");
                        }
                    }
                }

                haveAnonType = true;
              child = XUtil.getNextSiblingElement(child);
            }
            else if (childName.equals(SchemaSymbols.ELT_SIMPLETYPE)) {
                //   TO DO:  the Default and fixed attribute handling should be here.               
                if (child.getAttribute(SchemaSymbols.ATT_NAME).length() > 0) {
                    noErrorSoFar = false;
                    // REVISIT: Localize
                    reportGenericSchemaError("anonymous simpleType in element '" + name +"' has a name attribute");
                }
                else
                    typeNameIndex = traverseSimpleTypeDecl(child);
                if (typeNameIndex != -1) {
                    dv = fDatatypeRegistry.getDatatypeValidator(fStringPool.toString(typeNameIndex));
                }
                else {
                    noErrorSoFar = false;
                    // REVISIT: Localize
                    reportGenericSchemaError("traverse simpleType error in element '" + name +"'");
                }
                contentSpecType = XMLElementDecl.TYPE_SIMPLE;
                haveAnonType = true;
              child = XUtil.getNextSiblingElement(child);
            } else if (type.equals("")) { // "ur-typed" leaf
                contentSpecType = XMLElementDecl.TYPE_ANY;
                    //REVISIT: is this right?
                //contentSpecType = fStringPool.addSymbol("UR_TYPE");
                // set occurrence count
                contentSpecNodeIndex = -1;
            }
      // see if there's something here; it had better be key, keyref or unique.
      if (child != null)
              childName = child.getLocalName();
      while ((child != null) && ((childName.equals(SchemaSymbols.ELT_KEY))
          || (childName.equals(SchemaSymbols.ELT_KEYREF))
          || (childName.equals(SchemaSymbols.ELT_UNIQUE)))) {
              child = XUtil.getNextSiblingElement(child);
                if (child != null) {
                    childName = child.getLocalName();
                }
      }
      if (child != null) {
                 // REVISIT: Localize
              noErrorSoFar = false;
                reportGenericSchemaError("the content of an element information item must match (annotation?, (simpleType | complexType)?, (unique | key | keyref)*)");
      }
        }

        // handle type="" here
        if (haveAnonType && (type.length()>0)) {
            noErrorSoFar = false;
            // REVISIT: Localize
            reportGenericSchemaError( "Element '"+ name +
                                      "' have both a type attribute and a annoymous type child" );
        }
        // type specified as an attribute and no child is type decl.
        else if (!type.equals("")) {
            if (substitutionGroupElementDecl != null) {
                checkSubstitutionGroupOK(elementDecl, substitutionGroupElementDecl);
            }
            String prefix = "";
            String localpart = type;
            int colonptr = type.indexOf(":");
            if ( colonptr > 0) {
                prefix = type.substring(0,colonptr);
                localpart = type.substring(colonptr+1);
            }
            String typeURI = resolvePrefixToURI(prefix);
           
            // check if the type is from the same Schema
            if ( !typeURI.equals(fTargetNSURIString)
                 && !typeURI.equals(SchemaSymbols.URI_SCHEMAFORSCHEMA)
                 && typeURI.length() != 0) {  // REVISIT, only needed because of resolvePrifixToURI.
                fromAnotherSchema = typeURI;
                typeInfo = getTypeInfoFromNS(typeURI, localpart);
                if (typeInfo == null) {
                    dv = getTypeValidatorFromNS(typeURI, localpart);
                    if (dv == null) {
                        //TO DO: report error here;
                        noErrorSoFar = false;
                        reportGenericSchemaError("Could not find type " +localpart
                                           + " in schema " + typeURI);
                    }
                }
            }
            else {
                typeInfo = (ComplexTypeInfo) fComplexTypeRegistry.get(typeURI+","+localpart);
                if (typeInfo == null) {
                    dv = getDatatypeValidator(typeURI, localpart);
                    if (dv == null )
                    if (typeURI.equals(SchemaSymbols.URI_SCHEMAFORSCHEMA)
                        && !fTargetNSURIString.equals(SchemaSymbols.URI_SCHEMAFORSCHEMA))
                    {
                        noErrorSoFar = false;
                        // REVISIT: Localize
                        reportGenericSchemaError("type not found : " + typeURI+":"+localpart);
                    }
                    else {
                        Element topleveltype = getTopLevelComponentByName(SchemaSymbols.ELT_COMPLEXTYPE,localpart);
                        if (topleveltype != null) {
                            if (fCurrentTypeNameStack.search((Object)localpart) > - 1) {
                                //then we found a recursive element using complexType.
                                // REVISIT: this will be broken when recursing happens between 2 schemas
                                int uriInd = StringPool.EMPTY_STRING;
                                if ( isQName.equals(SchemaSymbols.ATTVAL_QUALIFIED)||
                                     fElementDefaultQualified) {
                                    uriInd = fTargetNSURI;
                                }
                                int nameIndex = fStringPool.addSymbol(name);
                                QName tempQName = new QName(fCurrentScope, nameIndex, nameIndex, uriInd);
                                fElementRecurseComplex.put(tempQName, localpart);
                                return new QName(-1, nameIndex, nameIndex, uriInd);
                            }
                            else {
                                typeNameIndex = traverseComplexTypeDecl( topleveltype );
                                typeInfo = (ComplexTypeInfo)
                                    fComplexTypeRegistry.get(fStringPool.toString(typeNameIndex));
                            }
                        }
                        else {
                            topleveltype = getTopLevelComponentByName(SchemaSymbols.ELT_SIMPLETYPE, localpart);
                            if (topleveltype != null) {
                                typeNameIndex = traverseSimpleTypeDecl( topleveltype );
                                dv = getDatatypeValidator(typeURI, localpart);
                                //   TO DO:  the Default and fixed attribute handling should be here.
                            }
                            else {
                                noErrorSoFar = false;
                                // REVISIT: Localize
                                reportGenericSchemaError("type not found : " + typeURI+":"+localpart);
                            }

                        }

                    }
                }
            }
  
        }
        else if (haveAnonType){
            if (substitutionGroupElementDecl != null ) {
                checkSubstitutionGroupOK(elementDecl, substitutionGroupElementDecl);
            }

        }
        // this element is ur-type, check its substitutionGroup afficliation.
        else {
            // if there is substitutionGroup affiliation and not type defition found for this element,
            // then grab substitutionGroup affiliation's type and give it to this element
            if ( typeInfo == null && dv == null ) {
        typeInfo = substitutionGroupEltTypeInfo;
        dv = substitutionGroupEltDV;
      }
        }

        if (typeInfo == null && dv==null) {
            if (noErrorSoFar) {
                // Actually this Element's type definition is ur-type;
                contentSpecType = XMLElementDecl.TYPE_ANY;
                // REVISIT, need to wait till we have wildcards implementation.
                // ADD attribute wildcards here
            }
            else {
                noErrorSoFar = false;
                // REVISIT: Localize
                reportGenericSchemaError ("untyped element : " + name );
            }
        }
        // if element belongs to a compelx type
        if (typeInfo!=null) {
            contentSpecNodeIndex = typeInfo.contentSpecHandle;
            contentSpecType = typeInfo.contentType;
            scopeDefined = typeInfo.scopeDefined;
            dv = typeInfo.datatypeValidator;
        }

        // if element belongs to a simple type
        if (dv!=null) {
            contentSpecType = XMLElementDecl.TYPE_SIMPLE;
            if (typeInfo == null) {
                fromAnotherSchema = null; // not to switch schema in this case
            }
        }

        //
        // Create element decl
        //

        int elementNameIndex     = fStringPool.addSymbol(name);
        int localpartIndex = elementNameIndex;
        int uriIndex = StringPool.EMPTY_STRING;
        int enclosingScope = fCurrentScope;

        //refer to 4.3.2 in "XML Schema Part 1: Structures"
        if ( isTopLevel(elementDecl)) {
            uriIndex = fTargetNSURI;
            enclosingScope = TOP_LEVEL_SCOPE;
        }
        else if ( !isQName.equals(SchemaSymbols.ATTVAL_UNQUALIFIED) &&
                  (( isQName.equals(SchemaSymbols.ATTVAL_QUALIFIED)||
                       fElementDefaultQualified ))) {
           
            uriIndex = fTargetNSURI;
        }
        //There can never be two elements with the same name and different type in the same scope.
        int existSuchElementIndex = fSchemaGrammar.getElementDeclIndex(uriIndex, localpartIndex, enclosingScope);
        if ( existSuchElementIndex > -1) {
            fSchemaGrammar.getElementDecl(existSuchElementIndex, fTempElementDecl);
            DatatypeValidator edv = fTempElementDecl.datatypeValidator;
            ComplexTypeInfo eTypeInfo = fSchemaGrammar.getElementComplexTypeInfo(existSuchElementIndex);
            if ( ((eTypeInfo != null)&&(eTypeInfo!=typeInfo))
                 || ((edv != null)&&(edv != dv)) )  {
                noErrorSoFar = false;
                // REVISIT: Localize
                reportGenericSchemaError("duplicate element decl in the same scope : " +
                                         fStringPool.toString(localpartIndex));

            }
        }

        QName eltQName = new QName(-1,localpartIndex,elementNameIndex,uriIndex);
       
        // add element decl to pool
       
        int attrListHead = -1 ;

        // copy up attribute decls from type object
        if (typeInfo != null) {
            attrListHead = typeInfo.attlistHead;
        }
        int elementIndex = fSchemaGrammar.addElementDecl(eltQName, enclosingScope, scopeDefined,
                                                         contentSpecType, contentSpecNodeIndex,
                                                         attrListHead, dv);
        if ( DEBUGGING ) {
            /***/
            System.out.println("########elementIndex:"+elementIndex+" ("+fStringPool.toString(eltQName.uri)+","
                               + fStringPool.toString(eltQName.localpart) + ")"+
                               " eltType:"+type+" contentSpecType:"+contentSpecType+
                               " SpecNodeIndex:"+ contentSpecNodeIndex +" enclosingScope: " +enclosingScope +
                               " scopeDefined: " +scopeDefined+"\n");
             /***/
        }

        fSchemaGrammar.setElementComplexTypeInfo(elementIndex, typeInfo);
        // REVISIT: should we report error if typeInfo was null?

        // mark element if its type belongs to different Schema.
        fSchemaGrammar.setElementFromAnotherSchemaURI(elementIndex, fromAnotherSchema);

        // set BlockSet, FinalSet, Nullable and Abstract for this element decl
        fSchemaGrammar.setElementDeclBlockSet(elementIndex, blockSet);
        fSchemaGrammar.setElementDeclFinalSet(elementIndex, finalSet);
        fSchemaGrammar.setElementDeclMiscFlags(elementIndex, elementMiscFlags);

        // setSubstitutionGroupElementFullName
        fSchemaGrammar.setElementDeclSubstitutionGroupElementFullName(elementIndex, substitutionGroupFullName);

        //
        // key/keyref/unique processing
        //

        Element ic = XUtil.getFirstChildElement(elementDecl, IDENTITY_CONSTRAINTS);
        if (ic != null) {
            Integer elementIndexObj = new Integer(elementIndex);
            Vector identityConstraints = (Vector)fIdentityConstraints.get(elementIndexObj);
            if (identityConstraints == null) {
                identityConstraints = new Vector();
                fIdentityConstraints.put(elementIndexObj, identityConstraints);
            }
            while (ic != null) {
                if (DEBUG_IC_DATATYPES) {
                    System.out.println("<ICD>: adding ic for later traversal: "+ic);
                }
                identityConstraints.addElement(ic);
                ic = XUtil.getNextSiblingElement(ic, IDENTITY_CONSTRAINTS);
            }
        }
       
        return eltQName;

    }// end of method traverseElementDecl(Element)

    private void traverseIdentityConstraintsFor(int elementIndex,
                                                Vector identityConstraints)
        throws Exception {


        // iterate over identity constraints for this element
        int size = identityConstraints != null ? identityConstraints.size() : 0;
        if (size > 0) {
            // REVISIT: Use cached copy. -Ac
            XMLElementDecl edecl = new XMLElementDecl();
            fSchemaGrammar.getElementDecl(elementIndex, edecl);
            for (int i = 0; i < size; i++) {
                Element ic = (Element)identityConstraints.elementAt(i);
                String icName = ic.getLocalName();
                if ( icName.equals(SchemaSymbols.ELT_KEY) ) {
                    traverseKey(ic, edecl);
                }
                else if ( icName.equals(SchemaSymbols.ELT_KEYREF) ) {
                    traverseKeyRef(ic, edecl);
                }
                else if ( icName.equals(SchemaSymbols.ELT_UNIQUE) ) {
                    traverseUnique(ic, edecl);
                }
                else {
                    // should never get here
                    throw new RuntimeException("identity constraint must be one of "+
                                               "\""+SchemaSymbols.ELT_UNIQUE+"\", "+
                                               "\""+SchemaSymbols.ELT_KEY+"\", or "+
                                               "\""+SchemaSymbols.ELT_KEYREF+'"');
                }
                fSchemaGrammar.setElementDecl(elementIndex, edecl);

            } // loop over vector elements

        } // if size > 0

    } // traverseIdentityConstraints(Vector)

    private void traverseUnique(Element uelem, XMLElementDecl edecl)
        throws Exception {

        // create identity constraint
        String uname = uelem.getAttribute(SchemaSymbols.ATT_NAME);
        if (DEBUG_IDENTITY_CONSTRAINTS) {
            System.out.println("<IC>: traverseUnique(\""+uelem.getNodeName()+"\") ["+uname+']');
        }
        String ename = getElementNameFor(uelem);
        Unique unique = new Unique(uname, ename);

        // get selector and fields
        traverseIdentityConstraint(unique, uelem);

        // add to element decl
        edecl.unique.addElement(unique);

    } // traverseUnique(Element,XMLElementDecl)

    private void traverseKey(Element kelem, XMLElementDecl edecl)
        throws Exception {

        // create identity constraint
        String kname = kelem.getAttribute(SchemaSymbols.ATT_NAME);
        if (DEBUG_IDENTITY_CONSTRAINTS) {
            System.out.println("<IC>: traverseKey(\""+kelem.getNodeName()+"\") ["+kname+']');
        }
        String ename = getElementNameFor(kelem);
        Key key = new Key(kname, ename);

        // get selector and fields
        traverseIdentityConstraint(key, kelem);

        // add to element decl
        edecl.key.addElement(key);

    } // traverseKey(Element,XMLElementDecl)

    private void traverseKeyRef(Element krelem, XMLElementDecl edecl)
        throws Exception {

        // create identity constraint
        String krname = krelem.getAttribute(SchemaSymbols.ATT_NAME);
        String kname = krelem.getAttribute(SchemaSymbols.ATT_REFER);
        if (DEBUG_IDENTITY_CONSTRAINTS) {
            System.out.println("<IC>: traverseKeyRef(\""+krelem.getNodeName()+"\") ["+krname+','+kname+']');
        }

        // verify that key reference "refer" attribute is valid
        Element element = (Element)krelem.getParentNode();
        Element kelem = XUtil.getFirstChildElement(element,
                                                   SchemaSymbols.ELT_KEY,
                                                   SchemaSymbols.ATT_NAME,
                                                   kname);
        if (kelem == null) {
            reportSchemaError(SchemaMessageProvider.KeyRefReferNotFound,
                              new Object[]{krname,kname});
            return;
        }
       
        String ename = getElementNameFor(krelem);
        KeyRef keyRef = new KeyRef(krname, kname, ename);

        // add to element decl
        traverseIdentityConstraint(keyRef, krelem);

        // add key reference to element decl
        edecl.keyRef.addElement(keyRef);

    } // traverseKeyRef(Element,XMLElementDecl)

    private void traverseIdentityConstraint(IdentityConstraint ic,
                                            Element icelem) throws Exception {
       
        // get selector
        Element selem = XUtil.getFirstChildElement(icelem, SchemaSymbols.ELT_SELECTOR);
        String stext = CR_IMPL
                     ? selem.getAttribute(SchemaSymbols.ATT_XPATH)
                     : XUtil.getChildText(selem);
        stext = stext.trim();
        Selector.XPath sxpath = null;
        try {
            // REVISIT: Must get ruling from XML Schema working group
            //          regarding whether steps in the XPath must be
            //          fully qualified if the grammar has a target
            //          namespace.
            //
            //          For now, I'm going to follow the identity
            //          constraint example in the XML Schema CR that
            //          doesn't fully qualify the steps (with the
            //          implied assumption that the URI for unqualified
            //          steps is equal to the target namespace). -Ac
            sxpath = new Selector.XPath(stext, fStringPool,
                                        fNamespacesScope);
            Selector selector = new Selector(sxpath, ic);
            if (DEBUG_IDENTITY_CONSTRAINTS) {
                System.out.println("<IC>:   selector: "+selector);
            }
            ic.setSelector(selector);
        }
        catch (XPathException e) {
            // REVISIT: Add error message.
            reportGenericSchemaError(e.getMessage());
            return;
        }

        // get fields
        Element parent = (Element)icelem.getParentNode();
        Element felem = XUtil.getNextSiblingElement(selem, SchemaSymbols.ELT_FIELD);
        while (felem != null) {
            String ftext = CR_IMPL
                         ? felem.getAttribute(SchemaSymbols.ATT_XPATH)
                         : XUtil.getChildText(felem);
            ftext = ftext.trim();
            try {
                // REVISIT: Must get ruling from XML Schema working group
                //          regarding whether steps in the XPath must be
                //          fully qualified if the grammar has a target
                //          namespace.
                //
                //          For now, I'm going to follow the identity
                //          constraint example in the XML Schema CR that
                //          doesn't fully qualify the steps (with the
                //          implied assumption that the URI for unqualified
                //          steps is equal to the target namespace). -Ac
                Field.XPath fxpath = new Field.XPath(ftext, fStringPool,
                                                     fNamespacesScope);
                // REVISIT: Get datatype validator. -Ac
                DatatypeValidator validator = getDatatypeValidatorFor(parent, sxpath, fxpath);
                if (DEBUG_IC_DATATYPES) {
                    System.out.println("<ICD>: datatype validator: "+validator);
                }
                Field field = new Field(fxpath, validator, ic);
                if (DEBUG_IDENTITY_CONSTRAINTS) {
                    System.out.println("<IC>:   field:    "+field);
                }
                ic.addField(field);
            }
            catch (XPathException e) {
                // REVISIT: Add error message.
                reportGenericSchemaError(e.getMessage());
                return;
            }
            felem = XUtil.getNextSiblingElement(felem, SchemaSymbols.ELT_FIELD);
        }

    } // traverseIdentityConstraint(IdentityConstraint,Element)

    private DatatypeValidator getDatatypeValidatorFor(Element element,
                                                      Selector.XPath sxpath,
                                                      Field.XPath fxpath)
        throws Exception {

        // variables
        String ename = element.getAttribute("name");
        if (DEBUG_IC_DATATYPES) {
            System.out.println("<ICD>: XMLValidator#getDatatypeValidatorFor("+
                               ename+','+sxpath+','+fxpath+')');
        }
        int localpart = fStringPool.addSymbol(ename);
        String targetNamespace = fSchemaRootElement.getAttribute("targetNamespace");
        int uri = fStringPool.addSymbol(targetNamespace);
        int edeclIndex = fSchemaGrammar.getElementDeclIndex(uri, localpart,
                                                            Grammar.TOP_LEVEL_SCOPE);

        // walk selector
        XPath.LocationPath spath = sxpath.getLocationPath();
        XPath.Step[] ssteps = spath.steps;
        for (int i = 0; i < ssteps.length; i++) {
            XPath.Step step = ssteps[i];
            XPath.Axis axis = step.axis;
            XPath.NodeTest nodeTest = step.nodeTest;
            switch (axis.type) {
                case XPath.Axis.ATTRIBUTE: {
                    // REVISIT: Add message. -Ac
                    reportGenericSchemaError("not allowed to select attribute");
                    return null;
                }
                case XPath.Axis.CHILD: {
                    int index = fSchemaGrammar.getElementDeclIndex(nodeTest.name, edeclIndex);
                    if (index == -1) {
                        index = fSchemaGrammar.getElementDeclIndex(nodeTest.name, Grammar.TOP_LEVEL_SCOPE);
                    }
                    if (index == -1) {
                        // REVISIT: Add message. -Ac
                        reportGenericSchemaError("no such element \""+fStringPool.toString(nodeTest.name.rawname)+'"');
                        return null;
                    }
                    edeclIndex = index;
                    break;
                }
                case XPath.Axis.SELF: {
                    // no-op
                    break;
                }
                default: {
                    // REVISIT: Add message. -Ac
                    reportGenericSchemaError("invalid selector axis");
                    return null;
                }
            }
        }

        // walk field
        XPath.LocationPath fpath = fxpath.getLocationPath();
        XPath.Step[] fsteps = fpath.steps;
        for (int i = 0; i < fsteps.length; i++) {
            XPath.Step step = fsteps[i];
            XPath.Axis axis = step.axis;
            XPath.NodeTest nodeTest = step.nodeTest;
            switch (axis.type) {
                case XPath.Axis.ATTRIBUTE: {
                    if (i != fsteps.length - 1) {
                        // REVISIT: Add message. -Ac
                        reportGenericSchemaError("attribute must be last step");
                        return null;
                    }
                    // look up validator
                    int adeclIndex = fSchemaGrammar.getAttributeDeclIndex(edeclIndex, nodeTest.name);
                    if (adeclIndex == -1) {
                        // REVISIT: Add message. -Ac
                        reportGenericSchemaError("no such attribute \""+fStringPool.toString(nodeTest.name.rawname)+'"');
                    }
                    XMLAttributeDecl adecl = new XMLAttributeDecl();
                    fSchemaGrammar.getAttributeDecl(adeclIndex, adecl);
                    DatatypeValidator validator = adecl.datatypeValidator;
                    return validator;
                }
                case XPath.Axis.CHILD: {
                    int index = fSchemaGrammar.getElementDeclIndex(nodeTest.name, edeclIndex);
                    if (index == -1) {
                        index = fSchemaGrammar.getElementDeclIndex(nodeTest.name, -1);
                    }
                    if (index == -1) {
                        // REVISIT: Add message. -Ac
                        reportGenericSchemaError("no such element \""+fStringPool.toString(nodeTest.name.rawname)+'"');
                        return null;
                    }
                    edeclIndex = index;
                    if (i < fsteps.length - 1) {
                        break;
                    }
                    // NOTE: Let fall through to self case so that we
                    //       avoid duplicating code. -Ac
                }
                case XPath.Axis.SELF: {
                    // look up validator, if needed
                    if (i == fsteps.length - 1) {
                        XMLElementDecl edecl = new XMLElementDecl();
                        fSchemaGrammar.getElementDecl(edeclIndex, edecl);
                        if (edecl.type != XMLElementDecl.TYPE_SIMPLE) {
                            // REVISIT: Add message. -Ac
                            reportGenericSchemaError("selected element is not of simple type");
                            return null;
                        }
                        DatatypeValidator validator = edecl.datatypeValidator;
                        return validator;
                    }
                    break;
                }
                default: {
                    // REVISIT: Add message. -Ac
                    reportGenericSchemaError("invalid selector axis");
                    return null;
                }
            }
        }

        // no validator!
        // REVISIT: Add message. -Ac
        reportGenericSchemaError("No datatype validator for field "+fxpath+
                                 " of element "+ename);
        return null;

    } // getDatatypeValidatorFor(XPath):DatatypeValidator

    private String getElementNameFor(Element icnode) {
        Element enode = (Element)icnode.getParentNode();
        String ename = enode.getAttribute("name");
        if (ename.length() == 0) {
            ename = enode.getAttribute("ref");
        }
        return ename;
    } // getElementNameFor(Element):String

    int getLocalPartIndex(String fullName){
        int colonAt = fullName.indexOf(":");
        String localpart = fullName;
        if colonAt > -1 ) {
            localpart = fullName.substring(colonAt+1);
        }
        return fStringPool.addSymbol(localpart);
    }
   
    String getLocalPart(String fullName){
        int colonAt = fullName.indexOf(":");
        String localpart = fullName;
        if colonAt > -1 ) {
            localpart = fullName.substring(colonAt+1);
        }
        return localpart;
    }
   
    int getPrefixIndex(String fullName){
        int colonAt = fullName.indexOf(":");
        String prefix = "";
        if colonAt > -1 ) {
            prefix = fullName.substring(0,colonAt);
        }
        return fStringPool.addSymbol(prefix);
    }

    String getPrefix(String fullName){
        int colonAt = fullName.indexOf(":");
        String prefix = "";
        if colonAt > -1 ) {
            prefix = fullName.substring(0,colonAt);
        }
        return prefix;
    }
   
    private void checkSubstitutionGroupOK(Element elementDecl, Element substitutionGroupElementDecl){
        //TO DO!!
    }
   
    // this originally-simple method is much -complicated by the fact that, when we're
    // redefining something, we've not only got to look at the space of the thing
    // we're redefining but at the original schema too.
    // The idea is to start from the top, then go down through
    // our list of schemas until we find what we aant. 
    // This should not often be necessary, because we've processed
    // all redefined schemas, but three are conditions in which
    // not all elements so redefined may have been promoted to
    // the topmost level. 
    private Element getTopLevelComponentByName(String componentCategory, String name) throws Exception {
        Element child = null;
        SchemaInfo curr = fSchemaInfoListRoot;
        for (; curr != null || curr == fSchemaInfoListRoot; curr = curr.getNext()) {
            if (curr != null) curr.restore();
            if ( componentCategory.equals(SchemaSymbols.ELT_GROUP) ) {
                child = (Element) fSchemaGrammar.topLevelGroupDecls.get(name);
            }
            else if ( componentCategory.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP ) ) {
                child = (Element) fSchemaGrammar.topLevelAttrGrpDecls.get(name);
            }
            else if ( componentCategory.equals(SchemaSymbols.ELT_ATTRIBUTE ) ) {
                child = (Element) fSchemaGrammar.topLevelAttrDecls.get(name);
            }

            if (child != null ) {
                break;
            }
           
            child = XUtil.getFirstChildElement(fSchemaRootElement);

            if (child == null) {
                continue;
            }

            while (child != null ){
                if ( child.getLocalName().equals(componentCategory)) {
                    if (child.getAttribute(SchemaSymbols.ATT_NAME).equals(name)) {
                        break;
                    }
                } else if (fRedefineSucceeded && child.getLocalName().equals(SchemaSymbols.ELT_REDEFINE)) {
                    Element gChild = XUtil.getFirstChildElement(child);
                    while (gChild != null ){
                        if (gChild.getLocalName().equals(componentCategory)) {
                            if (gChild.getAttribute(SchemaSymbols.ATT_NAME).equals(name)) {
                                break;
                            }
                        }
                        gChild = XUtil.getNextSiblingElement(gChild);
                    }
                    if (gChild != null) {
                        child = gChild;
                        break;
                    }
                }
                child = XUtil.getNextSiblingElement(child);
            }
            if (child != null || fSchemaInfoListRoot == null) break;
        }
        // have to reset fSchemaInfoList
        if(curr != null)
            curr.restore();
        else
            if (fSchemaInfoListRoot != null)
                fSchemaInfoListRoot.restore();
        return child;
    }

    private boolean isTopLevel(Element component) {
        String parentName = component.getParentNode().getLocalName();
    return (parentName.endsWith(SchemaSymbols.ELT_SCHEMA))
        || (parentName.endsWith(SchemaSymbols.ELT_REDEFINE)) ;
    }
   
    DatatypeValidator getTypeValidatorFromNS(String newSchemaURI, String localpart) throws Exception {
        // The following impl is for the case where every Schema Grammar has its own instance of DatatypeRegistry.
        // Now that we have only one DataTypeRegistry used by all schemas. this is not needed.
        /*****
        Grammar grammar = fGrammarResolver.getGrammar(newSchemaURI);
        if (grammar != null && grammar instanceof SchemaGrammar) {
            SchemaGrammar sGrammar = (SchemaGrammar) grammar;
            DatatypeValidator dv = (DatatypeValidator) fSchemaGrammar.getDatatypeRegistry().getDatatypeValidator(localpart);
            return dv;
        }
        else {
            reportGenericSchemaError("could not resolve URI : " + newSchemaURI + " to a SchemaGrammar in getTypeValidatorFromNS");
        }
        return null;
        /*****/
        return getDatatypeValidator(newSchemaURI, localpart);
    }

    ComplexTypeInfo getTypeInfoFromNS(String newSchemaURI, String localpart) throws Exception {
        Grammar grammar = fGrammarResolver.getGrammar(newSchemaURI);
        if (grammar != null && grammar instanceof SchemaGrammar) {
            SchemaGrammar sGrammar = (SchemaGrammar) grammar;
            ComplexTypeInfo typeInfo = (ComplexTypeInfo) sGrammar.getComplexTypeRegistry().get(newSchemaURI+","+localpart);
            return typeInfo;
        }
        else {
            reportGenericSchemaError("could not resolve URI : " + newSchemaURI + " to a SchemaGrammar in getTypeInfoFromNS");
        }
        return null;
    }
   
    DatatypeValidator getElementDeclTypeValidatorFromNS(String newSchemaURI, String localpart) throws Exception {
        Grammar grammar = fGrammarResolver.getGrammar(newSchemaURI);
        if (grammar != null && grammar instanceof SchemaGrammar) {
            SchemaGrammar sGrammar = (SchemaGrammar) grammar;
            int eltIndex = sGrammar.getElementDeclIndex(fStringPool.addSymbol(newSchemaURI),
                                                        fStringPool.addSymbol(localpart),
                                                        TOP_LEVEL_SCOPE);

            DatatypeValidator dv = null;
            if (eltIndex>-1) {
                sGrammar.getElementDecl(eltIndex, fTempElementDecl);
                dv = fTempElementDecl.datatypeValidator;
            }
            else {
                reportGenericSchemaError("could not find global element : '" + localpart
                                         + " in the SchemaGrammar "+newSchemaURI);
            }
            return dv;
        }
        else {
            reportGenericSchemaError("could not resolve URI : " + newSchemaURI
                                      + " to a SchemaGrammar in getELementDeclTypeValidatorFromNS");
        }
        return null;
    }

    ComplexTypeInfo getElementDeclTypeInfoFromNS(String newSchemaURI, String localpart) throws Exception {
        Grammar grammar = fGrammarResolver.getGrammar(newSchemaURI);
        if (grammar != null && grammar instanceof SchemaGrammar) {
            SchemaGrammar sGrammar = (SchemaGrammar) grammar;
            int eltIndex = sGrammar.getElementDeclIndex(fStringPool.addSymbol(newSchemaURI),
                                                              fStringPool.addSymbol(localpart),
                                                              TOP_LEVEL_SCOPE);
            ComplexTypeInfo typeInfo = null;
            if (eltIndex>-1) {
                 typeInfo = sGrammar.getElementComplexTypeInfo(eltIndex);
            }
            else {
                reportGenericSchemaError("could not find global element : '" + localpart
                                         + " in the SchemaGrammar "+newSchemaURI);

            }
            return typeInfo;
        }
        else {
            reportGenericSchemaError("could not resolve URI : " + newSchemaURI
                                     + " to a SchemaGrammar in getElementDeclTypeInfoFromNS");
        }
        return null;
    }



    /**
     * Traverses notation declaration
     * and saves it in a registry.
     * Notations are stored in registry with the following
     * key: "uri:localname"
     *
     * @param notation child <notation>
     * @return  local name of notation
     * @exception Exception
     */
    private String traverseNotationDecl( Element notation ) throws Exception {
        String name = notation.getAttribute(SchemaSymbols.ATT_NAME);
        String qualifiedName =name;
        if (fTargetNSURIString.length () != 0) {
            qualifiedName = fTargetNSURIString+":"+name;
        }
        if (fNotationRegistry.get(qualifiedName)!=null) {
            return name;
        }
        String publicId = notation.getAttribute(SchemaSymbols.ATT_PUBLIC);
        String systemId = notation.getAttribute(SchemaSymbols.ATT_SYSTEM);
        if (publicId.equals("") && systemId.equals("")) {
            //REVISIT: update error messages
            reportGenericSchemaError("<notation> declaration is invalid");
        }
        if (name.equals("")) {
            //REVISIT: update error messages
            reportGenericSchemaError("<notation> declaration does not have a name");

        }
       
        fNotationRegistry.put(qualifiedName, name);

        //we don't really care if something inside <notation> is wrong..
        checkContent( notation, XUtil.getFirstChildElement(notation), true );
       
        //REVISIT: wait for DOM L3 APIs to pass info to application
        //REVISIT: SAX2 does not support notations. API should be changed.
        return name;
    }
   
    /**
     * This methods will traverse notation from current schema,
     * as well as from included or imported schemas
     *
     * @param notationName
     *               localName of notation
     * @param uriStr uriStr for schema grammar
     * @return  return local name for Notation (if found), otherwise
     *         return empty string;
     * @exception Exception
     */
    private String traverseNotationFromAnotherSchema( String notationName , String uriStr ) throws Exception {
       
        SchemaGrammar aGrammar = (SchemaGrammar) fGrammarResolver.getGrammar(uriStr);
        if (uriStr == null || aGrammar==null ||! (aGrammar instanceof SchemaGrammar) ) {
            // REVISIT: Localize
            reportGenericSchemaError("!!Schema not found in #traverseNotationDeclFromAnotherSchema, "+
                                     "schema uri: " + uriStr
                                     +", groupName: " + notationName);
            return "";
        }


        String savedNSURIString = fTargetNSURIString;
        fTargetNSURIString = fStringPool.toString(fStringPool.addSymbol(aGrammar.getTargetNamespaceURI()));
        if (DEBUGGING) {
            System.out.println("[traverseFromAnotherSchema]: " + fTargetNSURIString);
        }

        String qualifiedName = fTargetNSURIString + ":" + notationName;
        String localName = (String)fNotationRegistry.get(qualifiedName);

        if(localName != null )   // we've already traversed this notation
            return localName;

        //notation decl has not been traversed yet
        Element notationDecl = (Element) aGrammar.topLevelNotationDecls.get((Object)notationName);
        if (notationDecl == null) {
            // REVISIT: Localize
            reportGenericSchemaError( "no notation named \"" + notationName
                                      + "\" was defined in schema : " + uriStr);
            return "";
        }

        localName = traverseNotationDecl(notationDecl);
        fTargetNSURIString = savedNSURIString;
        return localName;

    } // end of method traverseNotationFromAnotherSchema


    /**
     * Traverse Group Declaration.
     *
     * <group
     *         id = ID
     *         maxOccurs = string
     *         minOccurs = nonNegativeInteger
     *         name = NCName
     *         ref = QName>
     *   Content: (annotation? , (all | choice | sequence)?)
     * <group/>
     *
     * @param elementDecl
     * @return
     * @exception Exception
     */
    private int traverseGroupDecl( Element groupDecl ) throws Exception {

        String groupName = groupDecl.getAttribute(SchemaSymbols.ATT_NAME);
        String ref = groupDecl.getAttribute(SchemaSymbols.ATT_REF);
    Element child = checkContent( groupDecl, XUtil.getFirstChildElement(groupDecl), true );

        if (!ref.equals("")) {
      if(isTopLevel(groupDecl))
        // REVISIT:  localize
               reportGenericSchemaError ( "A group with \"ref\" present must not have <schema> or <redefine> as its parent");
      if(!groupName.equals(""))
        // REVISIT:  localize
               reportGenericSchemaError ( "group " + groupName + " cannot refer to another group, but it refers to " + ref);
            String prefix = "";
            String localpart = ref;
            int colonptr = ref.indexOf(":");
            if ( colonptr > 0) {
                prefix = ref.substring(0,colonptr);
                localpart = ref.substring(colonptr+1);
            }
            int localpartIndex = fStringPool.addSymbol(localpart);
           
            String uriStr = resolvePrefixToURI(prefix);

            if (!uriStr.equals(fTargetNSURIString)) {
                return traverseGroupDeclFromAnotherSchema(localpart, uriStr);
            }
      Object contentSpecHolder = fGroupNameRegistry.get(uriStr + "," + localpart);
      if(contentSpecHolder != null )   // we've already traversed this group
        return ((Integer)contentSpecHolder).intValue();
            int contentSpecIndex = -1;
            Element referredGroup = getTopLevelComponentByName(SchemaSymbols.ELT_GROUP,localpart);
            if (referredGroup == null) {
                // REVISIT: Localize
                reportGenericSchemaError("Group " + localpart + " not found in the Schema");
                //REVISIT, this should be some custom Exception
                //throw new RuntimeException("Group " + localpart + " not found in the Schema");
            }
            else {
                contentSpecIndex = traverseGroupDecl(referredGroup);
            }
           
            return contentSpecIndex;
        } else if (groupName.equals(""))
            // REVISIT: Localize
            reportGenericSchemaError("a <group> must have a name or a ref present");
    String qualifiedGroupName = fTargetNSURIString + "," + groupName;
    Object contentSpecHolder = fGroupNameRegistry.get(qualifiedGroupName);
    if(contentSpecHolder != null )   // we've already traversed this group
      return ((Integer)contentSpecHolder).intValue();

    // if we're here then we're traversing a top-level group that we've never seen before.
        int index = -2;

        boolean illegalChild = false;
    String childName =
          (child != null) ? child.getLocalName() : "";
        if (childName.equals(SchemaSymbols.ELT_ALL)) {
            index = traverseAll(child);
        }
        else if (childName.equals(SchemaSymbols.ELT_CHOICE)) {
            index = traverseChoice(child);
        }
        else if (childName.equals(SchemaSymbols.ELT_SEQUENCE)) {
            index = traverseSequence(child);
        }
        else if (!childName.equals("") || (child != null && XUtil.getNextSiblingElement(child) != null)) {
            illegalChild = true;
            reportSchemaError(SchemaMessageProvider.GroupContentRestricted,
                              new Object [] { "group", childName });
        }
        if (child != null && XUtil.getNextSiblingElement(child) != null) {
            illegalChild = true;
            reportSchemaError(SchemaMessageProvider.GroupContentRestricted,
                              new Object [] { "group", childName });
        }
        if ( ! illegalChild && child != null) {
            index = expandContentModel( index, child);
        }

    contentSpecHolder = new Integer(index);
    fGroupNameRegistry.put(qualifiedGroupName, contentSpecHolder);
        return index;
    }

    private int traverseGroupDeclFromAnotherSchema( String groupName , String uriStr ) throws Exception {
       
        SchemaGrammar aGrammar = (SchemaGrammar) fGrammarResolver.getGrammar(uriStr);
        if (uriStr == null || aGrammar==null ||! (aGrammar instanceof SchemaGrammar) ) {
            // REVISIT: Localize
            reportGenericSchemaError("!!Schema not found in #traverseGroupDeclFromAnotherSchema, "+
                                     "schema uri: " + uriStr
                                     +", groupName: " + groupName);
            return -1;
        }


        Element groupDecl = (Element) aGrammar.topLevelGroupDecls.get((Object)groupName);
        if (groupDecl == null) {
            // REVISIT: Localize
            reportGenericSchemaError( "no group named \"" + groupName
                                      + "\" was defined in schema : " + uriStr);
            return -1;
        }

        NamespacesScope saveNSMapping = fNamespacesScope;
        int saveTargetNSUri = fTargetNSURI;
        fTargetNSURI = fStringPool.addSymbol(aGrammar.getTargetNamespaceURI());
        fNamespacesScope = aGrammar.getNamespacesScope();

  Element child = checkContent( groupDecl, XUtil.getFirstChildElement(groupDecl), true );

  String qualifiedGroupName = fTargetNSURIString + "," + groupName;
  Object contentSpecHolder = fGroupNameRegistry.get(qualifiedGroupName);
  if(contentSpecHolder != null )   // we've already traversed this group
    return ((Integer)contentSpecHolder).intValue();

    // if we're here then we're traversing a top-level group that we've never seen before.
        int index = -2;

        boolean illegalChild = false;
  String childName = (child != null) ? child.getLocalName() : "";
        if (childName.equals(SchemaSymbols.ELT_ALL)) {
            index = traverseAll(child);
        }
        else if (childName.equals(SchemaSymbols.ELT_CHOICE)) {
            index = traverseChoice(child);
        }
        else if (childName.equals(SchemaSymbols.ELT_SEQUENCE)) {
            index = traverseSequence(child);
        }
        else if (!childName.equals("") || (child != null && XUtil.getNextSiblingElement(child) != null)) {
            illegalChild = true;
            reportSchemaError(SchemaMessageProvider.GroupContentRestricted,
                              new Object [] { "group", childName });
        }
        if ( ! illegalChild && child != null) {
            index = expandContentModel( index, child);
        }

  contentSpecHolder = new Integer(index);
  fGroupNameRegistry.put(qualifiedGroupName, contentSpecHolder);
  fNamespacesScope = saveNSMapping;
  fTargetNSURI = saveTargetNSUri;
        return index;


    } // end of method traverseGroupDeclFromAnotherSchema
   
    /**
    *
    * Traverse the Sequence declaration
    *
    * <sequence
    *   id = ID
    *   maxOccurs = string
    *   minOccurs = nonNegativeInteger>
    *   Content: (annotation? , (element | group | choice | sequence | any)*)
    * </sequence>
    *
    **/
    int traverseSequence (Element sequenceDecl) throws Exception {
           
        Element child = checkContent(sequenceDecl, XUtil.getFirstChildElement(sequenceDecl), true);

        int contentSpecType = 0;
        int csnType = 0;

        csnType = XMLContentSpec.CONTENTSPECNODE_SEQ;
        contentSpecType = XMLElementDecl.TYPE_CHILDREN;

        int left = -2;
        int right = -2;
        boolean hadContent = false;

        for (;
             child != null;
             child = XUtil.getNextSiblingElement(child)) {
            int index = -2;
            hadContent = true;

            boolean seeParticle = false;
            String childName = child.getLocalName();
            if (childName.equals(SchemaSymbols.ELT_ELEMENT)) {
                QName eltQName = traverseElementDecl(child);
                index = fSchemaGrammar.addContentSpecNode( XMLContentSpec.CONTENTSPECNODE_LEAF,
                                                       eltQName.localpart,
                                                       eltQName.uri,
                                                       false);
                seeParticle = true;

            }
            else if (childName.equals(SchemaSymbols.ELT_GROUP)) {
                index = traverseGroupDecl(child);
                if (index == -1)
                    continue;
                seeParticle = true;

            }
            else if (childName.equals(SchemaSymbols.ELT_CHOICE)) {
                index = traverseChoice(child);
                seeParticle = true;

            }
            else if (childName.equals(SchemaSymbols.ELT_SEQUENCE)) {
                index = traverseSequence(child);
                seeParticle = true;

            }
            else if (childName.equals(SchemaSymbols.ELT_ANY)) {
                index = traverseAny(child);
                seeParticle = true;
            }
            else {
                reportSchemaError(SchemaMessageProvider.GroupContentRestricted,
                                  new Object [] { "group", childName });
            }

            if (seeParticle) {
                index = expandContentModel( index, child);
            }
            if (left == -2) {
                left = index;
            } else if (right == -2) {
                right = index;
            } else {
                left = fSchemaGrammar.addContentSpecNode(csnType, left, right, false);
                right = index;
            }
        }

        if (hadContent && right != -2)
            left = fSchemaGrammar.addContentSpecNode(csnType, left, right, false);

        return left;
    }
   
    /**
    *
    * Traverse the Choice declaration
    *
    * <choice
    *   id = ID
    *   maxOccurs = string
    *   minOccurs = nonNegativeInteger>
    *   Content: (annotation? , (element | group | choice | sequence | any)*)
    * </choice>
    *
    **/
    int traverseChoice (Element choiceDecl) throws Exception {
           
        // REVISIT: traverseChoice, traverseSequence can be combined
        Element child = checkContent(choiceDecl, XUtil.getFirstChildElement(choiceDecl), true);

        int contentSpecType = 0;
        int csnType = 0;

        csnType = XMLContentSpec.CONTENTSPECNODE_CHOICE;
        contentSpecType = XMLElementDecl.TYPE_CHILDREN;

        int left = -2;
        int right = -2;
        boolean hadContent = false;

        for (;
             child != null;
             child = XUtil.getNextSiblingElement(child)) {
            int index = -2;
            hadContent = true;

            boolean seeParticle = false;
            String childName = child.getLocalName();
            if (childName.equals(SchemaSymbols.ELT_ELEMENT)) {
                QName eltQName = traverseElementDecl(child);
                index = fSchemaGrammar.addContentSpecNode( XMLContentSpec.CONTENTSPECNODE_LEAF,
                                                       eltQName.localpart,
                                                       eltQName.uri,
                                                       false);
                seeParticle = true;

            }
            else if (childName.equals(SchemaSymbols.ELT_GROUP)) {
                index = traverseGroupDecl(child);
                if (index == -1)
                    continue;
                seeParticle = true;

            }
            else if (childName.equals(SchemaSymbols.ELT_CHOICE)) {
                index = traverseChoice(child);
                seeParticle = true;

            }
            else if (childName.equals(SchemaSymbols.ELT_SEQUENCE)) {
                index = traverseSequence(child);
                seeParticle = true;

            }
            else if (childName.equals(SchemaSymbols.ELT_ANY)) {
                index = traverseAny(child);
                seeParticle = true;
            }
            else {
                reportSchemaError(SchemaMessageProvider.GroupContentRestricted,
                                  new Object [] { "group", childName });
            }

            if (seeParticle) {
                index = expandContentModel( index, child);
            }
            if (left == -2) {
                left = index;
            } else if (right == -2) {
                right = index;
            } else {
                left = fSchemaGrammar.addContentSpecNode(csnType, left, right, false);
                right = index;
            }
        }

        if (hadContent && right != -2)
            left = fSchemaGrammar.addContentSpecNode(csnType, left, right, false);

        return left;
    }
   

   /**
    *
    * Traverse the "All" declaration
    *
    * <all
    *   id = ID
    *   maxOccurs = string
    *   minOccurs = nonNegativeInteger>
    *   Content: (annotation? , (element | group | choice | sequence | any)*)
    * </all>
    *  
    **/

    int traverseAll( Element allDecl) throws Exception {

        Element child = checkContent(allDecl, XUtil.getFirstChildElement(allDecl), true);
    if (child == null) return -2;

        int allChildren[] = null;
        int allChildCount = 0;

        int left = -2;

        for (;
             child != null;
             child = XUtil.getNextSiblingElement(child)) {

            int index = -2;
            boolean seeParticle = false;

            String childName = child.getLocalName();

            if (childName.equals(SchemaSymbols.ELT_ELEMENT)) {
                QName eltQName = traverseElementDecl(child);
                index = fSchemaGrammar.addContentSpecNode( XMLContentSpec.CONTENTSPECNODE_LEAF,
                                                       eltQName.localpart,
                                                       eltQName.uri,
                                                       false);
                seeParticle = true;

            }
            else {
                reportGenericSchemaError("Content of all group is restricted to elements only.  '"
              
                childName + "' was seen and is being ignored");
                break;
            }

            if (seeParticle) {
                index = expandContentModel( index, child);
            }
      if (index != -2)  {
              try {
                  allChildren[allChildCount] = index;
              }
              catch (NullPointerException ne) {
                  allChildren = new int[32];
                  allChildren[allChildCount] = index;
              }
              catch (ArrayIndexOutOfBoundsException ae) {
                  int[] newArray = new int[allChildren.length*2];
                  System.arraycopy(allChildren, 0, newArray, 0, allChildren.length);
                  allChildren[allChildCount] = index;
              }
              allChildCount++;
      }
        }

        // if there were no children, or only invalid children, return...
        if (allChildCount==0)
          return left;

        try {
           left = allCalcWrapper(allChildren, allChildCount);
        } catch (java.lang.OutOfMemoryError e) {
            reportGenericSchemaError("The size of the <all>"
                + " declaration in your schema is too large for this parser"
                + " and elements using it will not validate correctly.");
        }
        return left;
    }
   
    // allCalcWrapper initiates the recursive calculation of the purmutations
    // of targetArray.
    // @param initialArray:  the wrray we're passed, whose size may
    // not reflect the real number of elements to be permuted.
    // @param size:  te true size of this array.
    private int allCalcWrapper (int[] initialArray, int size)
            throws Exception {
        int permSize = size/2;
        int[] targetArray = new int[size];
        System.arraycopy(initialArray, 0, targetArray, 0, size);
       
        if(targetArray.length == 1) {
            return targetArray[0];
        } else if (targetArray.length < 1) {
            return -2;
        } else if (permSize > targetArray.length) {
            reportGenericSchemaError("The size of the permutations "
                + permSize +
                " cannot be greater than the length of the array to be permuted; error in processing of <all>!");
            return -2;
        } else if (targetArray.length <= 3) {
            return allCombo(targetArray);
        } else {
            return allCalc (targetArray, 0, permSize, 0, new
                int[targetArray.length-permSize], -2);
        }
    } // allCalcWrapper

    // allCombo generates all combinations of the given array.  It
    // assumes the array has either 2 or 3 elements, and is hardcoded
    // for speed. 
    private int allCombo(int[] targetArray)
            throws Exception {
        if(targetArray.length == 2) {
            int left, right; 
            int[] lA = {targetArray[0], targetArray[1]};
            int[] rA = {targetArray[1], targetArray[0]};
            left = createSeq(lA);
            right = createSeq(rA);
            return fSchemaGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_CHOICE, left, right, false);
        } else if (targetArray.length == 3) {
            int tempChoice;
            int[] a1 = {targetArray[0], targetArray[1], targetArray[2]};
            int[] a2 = {targetArray[0], targetArray[2], targetArray[1]};
            int[] a3 = {targetArray[1], targetArray[0], targetArray[2]};
            int[] a4 = {targetArray[1], targetArray[2], targetArray[0]};
            int[] a5 = {targetArray[2], targetArray[1], targetArray[0]};
            int[] a6 = {targetArray[2], targetArray[0], targetArray[1]};
            int s1 = createSeq(a1);
            int s2 = createSeq(a2);
            int s3 = createSeq(a3);
            int s4 = createSeq(a4);
            int s5 = createSeq(a5);
            int s6 = createSeq(a6);
            tempChoice = fSchemaGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_CHOICE,
                    s1, s2, false);
            tempChoice = fSchemaGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_CHOICE,
                    tempChoice, s3, false);
            tempChoice = fSchemaGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_CHOICE,
                    tempChoice, s4, false);
            tempChoice = fSchemaGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_CHOICE,
                    tempChoice, s5, false);
            return fSchemaGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_CHOICE,
                    tempChoice, s6, false);
        } else {
            return -2;
        }
    } // end allCombo
   
    // The purpose of allCalc is to produce all permutations of
    // permSize elements that can be derived from targetArray.
    // @param targetArray:  the array from which permutations
    // must be extracted;
    // @param targetPosition:  position in the target array of the
    // last element in targetArray that was completely processed;
    // @param permSize:  the size of the permutation set
    // @param progressIndicator:  indication of the number of meaningful
    // elements in complementArray;
    // @param complementArray:  contains the set of elements that were
    // contained in the global targetArray array and are not
    // present in this invocation's targetArray.
    // @param choiceHead:  index of the head of curretn <choice>
    // linked list.
    private int allCalc(int[] targetArray, int targetPosition, int
            permSize, int progressIndicator, int[]
            complementArray, int choiceHead)
                    throws Exception {
        if (targetArray.length-permSize-targetPosition == 1) { //base case
            int[] newTargetArray = new int[permSize+targetPosition];
            int allSeq;     // pointer to sequence of <all>'s
            for (int i=targetPosition; i<targetArray.length; i++){
                arrayProducer(targetArray, i,
                    newTargetArray, complementArray,
                    progressIndicator);
                // newTargetArray and complementArray must be recursed
                // upon...
                int c1 = allCalcWrapper(newTargetArray, newTargetArray.length);
                int c2 = allCalcWrapper(complementArray, complementArray.length);
                allSeq = fSchemaGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_SEQ,
                    c1, c2, false);
                if (choiceHead != -2) {
                    choiceHead =
                        fSchemaGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_CHOICE,
                        choiceHead, allSeq, false);
                } else {
                    choiceHead = allSeq;
                }
            }
            return choiceHead;
        } else { // recursive case
            for (int i=targetPosition; i<targetArray.length; i++){
                int[] newTargetArray = new
                    int[targetArray.length-1];
                arrayProducer(targetArray, i,
                    newTargetArray, complementArray,
                    progressIndicator);
                choiceHead = allCalc(newTargetArray, targetPosition, permSize,
                    progressIndicator+1, complementArray, choiceHead);
                targetPosition++;
                permSize--;
            }
            return choiceHead;
        } // end else...if
    }// allCalc

    // The purpose of arrayProducer is to create two arrays out of
    // targetArray:  the first, newTargetArray, will contain all the
    // elements of targetArray except the tPos-th; complementArray
    // will have its cPos-th element set to targetArray[tPos]. 
    // It is assumed that tPos, cPos and targetArray have meaningful
    // values; complementArray should already have been allocated and
    // newTargetArray should also have been allocated previously.
    private void arrayProducer(int [] targetArray, int tPos,
            int[] newTargetArray, int[] complementArray,
            int cPos) {
        complementArray[cPos] = targetArray[tPos];
        if (tPos > 0)
            System.arraycopy(targetArray, 0, newTargetArray, 0, tPos);
        if (tPos < targetArray.length-1)
            System.arraycopy(targetArray, tPos+1, newTargetArray, tPos, targetArray.length-tPos-1);
    } // end arrayProducer

       
       
    /** 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 = fSchemaGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_SEQ,
                                                       left, right, false);
            right = src[i];
        }

        return fSchemaGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_SEQ,
                                                   left, right, false);

    }    

    // utilities from Tom Watson's SchemaParser class
    // TO DO: Need to make this more conformant with Schema int type parsing

    private int parseInt (String intString) throws Exception
    {
            if ( intString.equals("*") ) {
                    return SchemaSymbols.INFINITY;
            } else {
                    return Integer.parseInt (intString);
            }
    }
   
      
    private int parseSimpleFinal (String finalString) throws Exception
    {
            if ( finalString.equals (SchemaSymbols.ATTVAL_POUNDALL) ) {
                    return SchemaSymbols.ENUMERATION+SchemaSymbols.RESTRICTION+SchemaSymbols.LIST+SchemaSymbols.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 (SchemaSymbols.ATTVAL_RESTRICTION) ) {
                                    if ( restrict == 0 ) {
                                            restrict = SchemaSymbols.RESTRICTION;
                                    } else {
                                        // REVISIT: Localize
                                            reportGenericSchemaError ("restriction in set twice");
                                    }
                            } else if ( token.equals (SchemaSymbols.ELT_LIST) ) {
                                    if ( list == 0 ) {
                                            list = SchemaSymbols.LIST;
                                    } else {
                                        // REVISIT: Localize
                                            reportGenericSchemaError ("list in set twice");
                                    }
                            }
                            else {
                                // REVISIT: Localize
                                reportGenericSchemaError "Invalid value (" +
                                                            finalString +
                                                            ")" );
                            }
                    }

                    return enumerate+restrict+list+reproduce;
            }
    }

    private int parseComplexContent (String contentStringthrows Exception
    {
            if ( contentString.equals (SchemaSymbols.ATTVAL_EMPTY) ) {
                    return XMLElementDecl.TYPE_EMPTY;
            } else if ( contentString.equals (SchemaSymbols.ATTVAL_ELEMENTONLY) ) {
                    return XMLElementDecl.TYPE_CHILDREN;
            } else if ( contentString.equals (SchemaSymbols.ATTVAL_TEXTONLY) ) {
                    return XMLElementDecl.TYPE_SIMPLE;
            } else if ( contentString.equals (SchemaSymbols.ATTVAL_MIXED) ) {
                    return XMLElementDecl.TYPE_MIXED;
            } else {
                // REVISIT: Localize
                    reportGenericSchemaError ( "Invalid value for content" );
                    return -1;
            }
    }

    private int parseDerivationSet (String finalStringthrows Exception
    {
            if ( finalString.equals ("#all") ) {
                    return SchemaSymbols.EXTENSION+SchemaSymbols.RESTRICTION+SchemaSymbols.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 (SchemaSymbols.ATTVAL_EXTENSION) ) {
                                    if ( extend == 0 ) {
                                            extend = SchemaSymbols.EXTENSION;
                                    } else {
                                        // REVISIT: Localize
                                            reportGenericSchemaError ( "extension already in set" );
                                    }
                            } else if ( token.equals (SchemaSymbols.ATTVAL_RESTRICTION) ) {
                                    if ( restrict == 0 ) {
                                            restrict = SchemaSymbols.RESTRICTION;
                                    } else {
                                        // REVISIT: Localize
                                            reportGenericSchemaError ( "restriction already in set" );
                                    }
                            } else {
                                // REVISIT: Localize
                                    reportGenericSchemaError ( "Invalid final value (" + finalString + ")" );
                            }
                    }

                    return extend+restrict+reproduce;
            }
    }

    private int parseBlockSet (String finalStringthrows Exception
    {
            if ( finalString.equals ("#all") ) {
                    return SchemaSymbols.SUBSTITUTIONGROUP+SchemaSymbols.EXTENSION+SchemaSymbols.LIST+SchemaSymbols.RESTRICTION+SchemaSymbols.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 (SchemaSymbols.ATTVAL_SUBSTITUTIONGROUP) ) {
                                    if ( extend == 0 ) {
                                            extend = SchemaSymbols.SUBSTITUTIONGROUP;
                                    } else {
                                        // REVISIT: Localize
                                            reportGenericSchemaError ( "'substitutionGroup' already in set" );
                                    }
                            } else if ( token.equals (SchemaSymbols.ATTVAL_EXTENSION) ) {
                                    if ( extend == 0 ) {
                                            extend = SchemaSymbols.EXTENSION;
                                    } else {
                                        // REVISIT: Localize
                                            reportGenericSchemaError ( "extension already in set" );
                                    }
                            } else if ( token.equals (SchemaSymbols.ELT_LIST) ) {
                                    if ( extend == 0 ) {
                                            extend = SchemaSymbols.LIST;
                                    } else {
                                        // REVISIT: Localize
                                            reportGenericSchemaError ( "'list' already in set" );
                                    }
                            } else if ( token.equals (SchemaSymbols.ATTVAL_RESTRICTION) ) {
                                    if ( restrict == 0 ) {
                                            restrict = SchemaSymbols.RESTRICTION;
                                    } else {
                                        // REVISIT: Localize
                                            reportGenericSchemaError ( "restriction already in set" );
                                    }
                            } else {
                                // REVISIT: Localize
                                    reportGenericSchemaError ( "Invalid final value (" + finalString + ")" );
                            }
                    }

                    return extend+restrict+reproduce;
            }
    }

    private int parseFinalSet (String finalStringthrows Exception
    {
            if ( finalString.equals ("#all") ) {
                    return SchemaSymbols.SUBSTITUTIONGROUP+SchemaSymbols.EXTENSION+SchemaSymbols.LIST+SchemaSymbols.RESTRICTION+SchemaSymbols.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 (SchemaSymbols.ATTVAL_SUBSTITUTIONGROUP) ) {
                                    if ( extend == 0 ) {
                                            extend = SchemaSymbols.SUBSTITUTIONGROUP;
                                    } else {
                                        // REVISIT: Localize
                                            reportGenericSchemaError ( "'substitutionGroup' already in set" );
                                    }
                            } else if ( token.equals (SchemaSymbols.ATTVAL_EXTENSION) ) {
                                    if ( extend == 0 ) {
                                            extend = SchemaSymbols.EXTENSION;
                                    } else {
                                        // REVISIT: Localize
                                            reportGenericSchemaError ( "extension already in set" );
                                    }
                            } else if ( token.equals (SchemaSymbols.ELT_LIST) ) {
                                    if ( extend == 0 ) {
                                            extend = SchemaSymbols.LIST;
                                    } else {
                                        // REVISIT: Localize
                                            reportGenericSchemaError ( "'list' already in set" );
                                    }
                            } else if ( token.equals (SchemaSymbols.ATTVAL_RESTRICTION) ) {
                                    if ( restrict == 0 ) {
                                            restrict = SchemaSymbols.RESTRICTION;
                                    } else {
                                        // REVISIT: Localize
                                            reportGenericSchemaError ( "restriction already in set" );
                                    }
                            } else {
                                // REVISIT: Localize
                                    reportGenericSchemaError ( "Invalid final value (" + finalString + ")" );
                            }
                    }

                    return extend+restrict+reproduce;
            }
    }

    private void reportGenericSchemaError (String error) throws Exception {
        if (fErrorReporter == null) {
            System.err.println("__TraverseSchemaError__ : " + error);      
        }
        else {
            reportSchemaError (SchemaMessageProvider.GenericError, new Object[] { error });
        }       
    }


    private void reportSchemaError(int major, Object args[]) throws Exception {
        if (fErrorReporter == null) {
            System.out.println("__TraverseSchemaError__ : " + SchemaMessageProvider.fgMessageKeys[major]);
            for (int i=0; i< args.length ; i++) {
                System.out.println((String)args[i]);   
            }
        }
        else {
            fErrorReporter.reportError(fErrorReporter.getLocator(),
                                       SchemaMessageProvider.SCHEMA_DOMAIN,
                                       major,
                                       SchemaMessageProvider.MSG_NONE,
                                       args,
                                       XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
        }
    }

    /** Don't check the following code in because it creates a dependency on
        the serializer, preventing to package the parser without the serializer
    //Unit Test here
    public static void main(String args[] ) {

        if( args.length != 1 ) {
            System.out.println( "Error: Usage java TraverseSchema yourFile.xsd" );
            System.exit(0);
        }

        DOMParser parser = new IgnoreWhitespaceParser();
        parser.setEntityResolver( new Resolver() );
        parser.setErrorHandler(  new ErrorHandler() );

        try {
        parser.setFeature("http://xml.org/sax/features/validation", false);
        parser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", false);
        }catch(  org.xml.sax.SAXNotRecognizedException e ) {
            e.printStackTrace();
        }catch( org.xml.sax.SAXNotSupportedException e ) {
            e.printStackTrace();
        }

        try {
        parser.parse( args[0]);
        }catch( IOException e ) {
            e.printStackTrace();
        }catch( SAXException e ) {
            e.printStackTrace();
        }

        Document     document   = parser.getDocument(); //Our Grammar

        OutputFormat    format  = new OutputFormat( document );
        java.io.StringWriter outWriter = new java.io.StringWriter();
        XMLSerializer    serial = new XMLSerializer( outWriter,format);

        TraverseSchema tst = null;
        try {
            Element root   = document.getDocumentElement();// This is what we pass to TraverserSchema
            //serial.serialize( root );
            //System.out.println(outWriter.toString());

            tst = new TraverseSchema( root, new StringPool(), new SchemaGrammar(), (GrammarResolver) new GrammarResolverImpl() );
            }
            catch (Exception e) {
                e.printStackTrace(System.err);
            }
           
            parser.getDocument();
    }
    **/

    static class Resolver implements EntityResolver {
        private static final String SYSTEM[] = {
            "http://www.w3.org/TR/2000/WD-xmlschema-1-20000407/structures.dtd",
            "http://www.w3.org/TR/2000/WD-xmlschema-1-20000407/datatypes.dtd",
            "http://www.w3.org/TR/2000/WD-xmlschema-1-20000407/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
    }

    static class IgnoreWhitespaceParser
        extends DOMParser {
        public void ignorableWhitespace(char ch[], int start, int length) {}
        public void ignorableWhitespace(int dataIdx) {}
    } // class IgnoreWhitespaceParser

    // When in a <redefine>, type definitions being used (and indeed
    // refs to <group>'s and <attributeGroup>'s) may refer to info
    // items either in the schema being redefined, in the <redefine>,
    // or else in the schema doing the redefining.  Because of this
    // latter we have to be prepared sometimes to look for our type
    // definitions outside the schema stored in fSchemaRootElement. 
    // This simple class does this; it's just a linked list that
    // lets us look at the <schema>'s on the queue; note also that this
    // should provide us with a mechanism to handle nested <redefine>'s. 
    // It's also a handy way of saving schema info when importing/including; saves some code.
    public class SchemaInfo {
        private Element saveRoot;
        private boolean saveElementDefaultQualified = fElementDefaultQualified;
        private boolean saveAttributeDefaultQualified = fAttributeDefaultQualified;
        private int saveScope = fCurrentScope;
        private String savedSchemaURL = fCurrentSchemaURL;
        private SchemaInfo nextRoot;
        private SchemaInfo prevRoot;

        public SchemaInfo ( boolean saveElementDefaultQualified, boolean saveAttributeDefaultQualified,
                int saveScope, String savedSchemaURL, Element saveRoot, SchemaInfo nextRoot, SchemaInfo prevRoot) {
            this.saveElementDefaultQualified = saveElementDefaultQualified;
            this.saveAttributeDefaultQualified = saveAttributeDefaultQualified;
            this.saveScope  = saveScope ;
            this.savedSchemaURL = savedSchemaURL;
            this.saveRoot  = saveRoot ;
            this.nextRoot = nextRoot;
            this.prevRoot = prevRoot;
        }
        public void setNext (SchemaInfo next) {
            nextRoot = next;
        }
        public SchemaInfo getNext () {
            return nextRoot;
        }
        public void setPrev (SchemaInfo prev) {
            prevRoot = prev;
        }
        public String getCurrentSchemaURL() { return savedSchemaURL; }
        public SchemaInfo getPrev () {
            return prevRoot;
        }
        public Element getRoot() { return saveRoot; }
        // NOTE:  this has side-effects!!!
        public void restore() {
            fCurrentSchemaURL = savedSchemaURL;
            fCurrentScope = saveScope;
            fElementDefaultQualified = saveElementDefaultQualified;
            fAttributeDefaultQualified = saveAttributeDefaultQualified;
            fSchemaRootElement = saveRoot;
        }
    } // class SchemaInfo

} // class TraverseSchema
TOP

Related Classes of org.apache.xerces.validators.schema.TraverseSchema$IgnoreWhitespaceParser

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.