You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xerces.apache.org by je...@locus.apache.org on 2000/05/17 20:33:36 UTC

cvs commit: xml-xerces/java/src/org/apache/xerces/validators/schema SchemaGrammar.java SchemaSymbols.java TraverseSchema.java DatatypeContentModel.java Makefile SchemaImporter.java SchemaMessageProvider.java SchemaParser.java datatypes.dtd structures.dtd versionInfo.ent

jeffreyr    00/05/17 11:33:34

  Modified:    java/data personal.xsd
               java/samples/dom DOMAddLines.java
               java/src Makefile.incl
               java/src/org/apache/xerces/dom DeferredAttrNSImpl.java
                        DeferredDocumentImpl.java
                        DeferredElementNSImpl.java
               java/src/org/apache/xerces/framework XMLAttrList.java
                        XMLContentSpec.java XMLDTDScanner.java
                        XMLDocumentHandler.java XMLDocumentScanner.java
                        XMLParser.java
               java/src/org/apache/xerces/msg XMLMessages.java
               java/src/org/apache/xerces/parsers DOMParser.java
                        SAXParser.java
               java/src/org/apache/xerces/readers AbstractCharReader.java
                        DefaultEntityHandler.java StreamingCharReader.java
                        StringReader.java UCSReader.java UTF8Reader.java
                        UTF8Recognizer.java XMLEntityHandler.java
               java/src/org/apache/xerces/utils Base64.java Makefile
                        StringPool.java XMLMessages.java
               java/src/org/apache/xerces/utils/regex REUtil.java
                        RegexParser.java RegularExpression.java Token.java
               java/src/org/apache/xerces/validators/common CMLeaf.java
                        DFAContentModel.java InsertableElementsInfo.java
                        Makefile MixedContentModel.java
                        SimpleContentModel.java XMLContentModel.java
                        XMLValidator.java
               java/src/org/apache/xerces/validators/datatype
                        BinaryValidator.java BooleanValidator.java
                        DatatypeMessageProvider.java DatatypeValidator.java
                        DecimalValidator.java DoubleValidator.java
                        FloatValidator.java Makefile StringValidator.java
                        TimeDurationValidator.java
               java/src/org/apache/xerces/validators/dtd DTDImporter.java
                        Makefile
               java/src/org/apache/xerces/validators/schema
                        DatatypeContentModel.java Makefile
                        SchemaImporter.java SchemaMessageProvider.java
                        SchemaParser.java datatypes.dtd structures.dtd
                        versionInfo.ent
  Added:       java/src/org/apache/xerces/utils Hash2intTable.java
                        QName.java
               java/src/org/apache/xerces/validators/common Grammar.java
                        GrammarPool.java GrammarResolver.java
                        GrammarResolverImpl.java XMLAttributeDecl.java
                        XMLElementDecl.java
               java/src/org/apache/xerces/validators/datatype
                        ConstrainException.java
                        DatatypeValidatorRegistry.java ENTITYValidator.java
                        IDREFValidator.java IDValidator.java
                        NOTATIONValidator.java QNameValidator.java
                        RecurringDurationValidator.java
                        URIReferenceValidator.java
               java/src/org/apache/xerces/validators/dtd DTDGrammar.java
               java/src/org/apache/xerces/validators/schema
                        SchemaGrammar.java SchemaSymbols.java
                        TraverseSchema.java
  Removed:     java/src/org/apache/xerces/validators/datatype
                        IntegerValidator.java
                        InternalDatatypeValidator.java RealValidator.java
                        TimeInstantValidator.java URIValidator.java
  Log:
  Merge schemawork branch into trunk
  
  Revision  Changes    Path
  1.5       +1 -1      xml-xerces/java/data/personal.xsd
  
  Index: personal.xsd
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/data/personal.xsd,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- personal.xsd	2000/02/16 22:00:41	1.4
  +++ personal.xsd	2000/05/17 18:31:26	1.5
  @@ -1,6 +1,6 @@
   <?xml version="1.0" encoding="UTF-8"?>
   <!DOCTYPE schema PUBLIC "-//W3C//DTD XMLSCHEMA 19991216//EN"
  -                        "http://www.w3.org/TR/1999/WD-xmlschema-1-19991217/structures.dtd">
  +                        "http://www.w3.org/TR/2000/WD-xmlschema-1-20000407/structures.dtd">
   <schema>
   
    <element name="personnel">
  
  
  
  1.3       +3 -2      xml-xerces/java/samples/dom/DOMAddLines.java
  
  Index: DOMAddLines.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/samples/dom/DOMAddLines.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- DOMAddLines.java	2000/04/04 22:48:01	1.2
  +++ DOMAddLines.java	2000/05/17 18:31:29	1.3
  @@ -70,6 +70,7 @@
   import org.apache.xerces.dom.NodeImpl;
   import org.apache.xerces.framework.XMLAttrList;
   import org.apache.xerces.parsers.DOMParser;
  +import org.apache.xerces.utils.QName;
   
   /**
    * A sample of Adding lines to the DOM Node. This sample program illustrates:
  @@ -226,9 +227,9 @@
   
      /*   We override startElement callback  from DocumentHandler */
   
  -   public void startElement(int elementNameIndex, XMLAttrList attrList, int attrListIndex) throws Exception 
  +   public void startElement(QName elementQName, XMLAttrList attrList, int attrListIndex) throws Exception 
      {
  -      super.startElement(elementNameIndex, attrList, attrListIndex);
  +      super.startElement(elementQName, attrList, attrListIndex);
   
         NodeImpl node = null;
         try {
  
  
  
  1.26      +3 -1      xml-xerces/java/src/Makefile.incl
  
  Index: Makefile.incl
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/Makefile.incl,v
  retrieving revision 1.25
  retrieving revision 1.26
  diff -u -r1.25 -r1.26
  --- Makefile.incl	2000/05/05 22:25:25	1.25
  +++ Makefile.incl	2000/05/17 18:31:32	1.26
  @@ -90,8 +90,10 @@
   
   dirs::
   	@if [ -n "$(DIRS)" ]; \
  -	then for i in $(DIRS);do \
  +	then for i in $(DIRS) __bogus__; do \
  +	       if [ $$i != __bogus__ ] ; then \
   		echo "$(MAKE) -C $$i"; $(MAKE) -C $$i; \
  +		fi \
   	     done; \
   	fi
   
  
  
  
  1.8       +20 -8     xml-xerces/java/src/org/apache/xerces/dom/DeferredAttrNSImpl.java
  
  Index: DeferredAttrNSImpl.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/dom/DeferredAttrNSImpl.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- DeferredAttrNSImpl.java	2000/05/03 02:06:43	1.7
  +++ DeferredAttrNSImpl.java	2000/05/17 18:31:35	1.8
  @@ -1,9 +1,8 @@
  -/* $Id: DeferredAttrNSImpl.java,v 1.7 2000/05/03 02:06:43 lehors Exp $ */
   /*
    * The Apache Software License, Version 1.1
    *
    *
  - * Copyright (c) 1999 The Apache Software Foundation.  All rights
  + * Copyright (c) 1999, 2000 The Apache Software Foundation.  All rights
    * reserved.
    *
    * Redistribution and use in source and binary forms, with or without
  @@ -62,6 +61,9 @@
    * DeferredAttrImpl.java at the same time.
    */
   
  +/* $Id: DeferredAttrNSImpl.java,v 1.8 2000/05/17 18:31:35 jeffreyr Exp $ */
  +
  +
   package org.apache.xerces.dom;
   
   import org.w3c.dom.*;
  @@ -130,13 +132,24 @@
           // fluff data
           DeferredDocumentImpl ownerDocument =
   	    (DeferredDocumentImpl) this.ownerDocument;
  -        int elementTypeName = ownerDocument.getNodeName(fNodeIndex);
  +        int attrQName = ownerDocument.getNodeName(fNodeIndex);
           StringPool pool = ownerDocument.getStringPool();
  -        name = pool.toString(elementTypeName);
  -        specified(ownerDocument.getNodeValue(fNodeIndex) == 1);
  +        name = pool.toString(attrQName);
   
  -	String prefix = pool.toString(pool.getPrefixForQName(elementTypeName));
  -	namespaceURI = pool.toString(pool.getURIForQName(elementTypeName));
  +        // extract prefix and local part from QName
  +        int index = name.indexOf(':');
  +        String prefix;
  +        if (index < 0) {
  +            prefix = null;
  +            localName = name;
  +        } 
  +        else {
  +            prefix = name.substring(0, index); 
  +            localName = name.substring(index + 1);
  +        }
  +
  +        specified(ownerDocument.getNodeValue(fNodeIndex) == 1);
  +	namespaceURI = pool.toString(ownerDocument.getNodeURI(attrQName));
   	// DOM Level 2 wants all namespace declaration attributes
   	// to be bound to "http://www.w3.org/2000/xmlns/"
   	// So as long as the XML parser doesn't do it, it needs to
  @@ -150,7 +163,6 @@
   		namespaceURI = "http://www.w3.org/2000/xmlns/";
   	    }
   	}
  -	localName = pool.toString(pool.getLocalPartForQName(elementTypeName));
   
       } // synchronizeData()
   
  
  
  
  1.16      +58 -8     xml-xerces/java/src/org/apache/xerces/dom/DeferredDocumentImpl.java
  
  Index: DeferredDocumentImpl.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/dom/DeferredDocumentImpl.java,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- DeferredDocumentImpl.java	2000/05/05 18:42:40	1.15
  +++ DeferredDocumentImpl.java	2000/05/17 18:31:35	1.16
  @@ -142,6 +142,9 @@
       /** Node prev siblings. */
       protected transient int fNodePrevSib[][];
   
  +    /** Node namespace URI. */
  +    protected transient int fNodeURI[][];
  +
       /** Identifier count. */
       protected transient int fIdCount;
   
  @@ -311,13 +314,21 @@
       } // createEntityReference(int):int
   
       /** Creates an element node in the table. */
  -    public int createElement(int elementNameIndex, XMLAttrList attrList, int attrListIndex) {
  +    public int createElement(int elementNameIndex,
  +                             XMLAttrList attrList, int attrListIndex) {
  +        return createElement(elementNameIndex, -1, attrList, attrListIndex);
  +    }
  +
  +    /** Creates an element node with a URI in the table. */
  +    public int createElement(int elementNameIndex, int elementURIIndex,
  +                             XMLAttrList attrList, int attrListIndex) {
   
           // create node
           int elementNodeIndex = createNode(Node.ELEMENT_NODE);
           int elementChunk     = elementNodeIndex >> CHUNK_SHIFT;
           int elementIndex     = elementNodeIndex & CHUNK_MASK;
           setChunkIndex(fNodeName, elementNameIndex, elementChunk, elementIndex);
  +        setChunkIndex(fNodeURI, elementURIIndex, elementChunk, elementIndex);
   
           // create attributes
           if (attrListIndex != -1) {
  @@ -330,9 +341,11 @@
                    index = attrList.getNextAttr(index)) {
   
                   // create attribute
  -                int attrNodeIndex = createAttribute(attrList.getAttrName(index),
  -                                                    attrList.getAttValue(index),
  -                                                    attrList.isSpecified(index));
  +                int attrNodeIndex =
  +                    createAttribute(attrList.getAttrName(index),
  +                                    attrList.getAttrURI(index),
  +                                    attrList.getAttValue(index),
  +                                    attrList.isSpecified(index));
                   int attrChunk = attrNodeIndex >> CHUNK_SHIFT;
                   int attrIndex  = attrNodeIndex & CHUNK_MASK;
                   setChunkIndex(fNodeParent, elementNodeIndex, attrChunk, attrIndex);
  @@ -357,15 +370,22 @@
   
       } // createElement(int,XMLAttrList,int):int
   
  -    /** Creates an attributes in the table. */
  -    public int createAttribute(int attrNameIndex, int attrValueIndex,
  -                               boolean specified) {
  +    /** Creates an attribute in the table. */
  +    public int createAttribute(int attrNameIndex,
  +                               int attrValueIndex, boolean specified) {
  +        return createAttribute(attrNameIndex, -1, attrValueIndex, specified);
  +    }
  +
  +    /** Creates an attribute with a URI in the table. */
  +    public int createAttribute(int attrNameIndex, int attrURIIndex,
  +                               int attrValueIndex, boolean specified) {
   
           // create node
           int nodeIndex = createNode(NodeImpl.ATTRIBUTE_NODE);
           int chunk = nodeIndex >> CHUNK_SHIFT;
           int index = nodeIndex & CHUNK_MASK;
           setChunkIndex(fNodeName, attrNameIndex, chunk, index);
  +        setChunkIndex(fNodeURI, attrURIIndex, chunk, index);
           setChunkIndex(fNodeValue, specified ? 1 : 0, chunk, index);
   
           // append value as text node
  @@ -1039,6 +1059,30 @@
   
       } // getNodeType(int):int
   
  +    /** Returns the URI of the given node. */
  +    public short getNodeURI(int nodeIndex) {
  +        return getNodeURI(nodeIndex, true);
  +    }
  +
  +    /** 
  +     * Returns the URI of the given node. 
  +     * @param True to free URI index.
  +     */
  +    public short getNodeURI(int nodeIndex, boolean free) {
  +
  +        if (nodeIndex == -1) {
  +            return -1;
  +        }
  +
  +        int chunk = nodeIndex >> CHUNK_SHIFT;
  +        int index = nodeIndex & CHUNK_MASK;
  +        if (free) {
  +            return (short)clearChunkIndex(fNodeURI, chunk, index);
  +        }
  +        return (short)getChunkIndex(fNodeURI, chunk, index);
  +
  +    } // getNodeURI(int):int
  +
       // identifier maintenance
   
       /** Registers an identifier name with a specified element node. */
  @@ -1356,8 +1400,9 @@
               fNodeName       = new int[INITIAL_CHUNK_COUNT][];
               fNodeValue      = new int[INITIAL_CHUNK_COUNT][];
               fNodeParent     = new int[INITIAL_CHUNK_COUNT][];
  -            fNodeLastChild = new int[INITIAL_CHUNK_COUNT][];
  +            fNodeLastChild  = new int[INITIAL_CHUNK_COUNT][];
               fNodePrevSib    = new int[INITIAL_CHUNK_COUNT][];
  +            fNodeURI        = new int[INITIAL_CHUNK_COUNT][];
           }
   
           // return true if table is already big enough
  @@ -1392,6 +1437,10 @@
               newArray = new int[newsize][];
               System.arraycopy(fNodePrevSib, 0, newArray, 0, chunk);
               fNodePrevSib = newArray;
  +
  +            newArray = new int[newsize][];
  +            System.arraycopy(fNodeURI, 0, newArray, 0, chunk);
  +            fNodeURI = newArray;
           }
   
           catch (NullPointerException ex) {
  @@ -1405,6 +1454,7 @@
           createChunk(fNodeParent, chunk);
           createChunk(fNodeLastChild, chunk);
           createChunk(fNodePrevSib, chunk);
  +        createChunk(fNodeURI, chunk);
   
           // success
           return true;
  
  
  
  1.6       +22 -11    xml-xerces/java/src/org/apache/xerces/dom/DeferredElementNSImpl.java
  
  Index: DeferredElementNSImpl.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/dom/DeferredElementNSImpl.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- DeferredElementNSImpl.java	2000/05/03 02:06:43	1.5
  +++ DeferredElementNSImpl.java	2000/05/17 18:31:36	1.6
  @@ -1,4 +1,3 @@
  -/* $Id: DeferredElementNSImpl.java,v 1.5 2000/05/03 02:06:43 lehors Exp $ */
   /*
    * The Apache Software License, Version 1.1
    *
  @@ -56,6 +55,9 @@
    * <http://www.apache.org/>.
    */
   
  +
  +/* $Id: DeferredElementNSImpl.java,v 1.6 2000/05/17 18:31:36 jeffreyr Exp $ */
  +
   /*
    * WARNING: because java doesn't support multi-inheritance some code is
    * duplicated. If you're changing this file you probably want to change
  @@ -132,23 +134,32 @@
           // fluff data
           DeferredDocumentImpl ownerDocument =
               (DeferredDocumentImpl) this.ownerDocument;
  -        int elementTypeName = ownerDocument.getNodeName(fNodeIndex);
  +        int elementQName = ownerDocument.getNodeName(fNodeIndex);
           StringPool pool = ownerDocument.getStringPool();
  -        name = pool.toString(elementTypeName);
  -	String prefix = pool.toString(pool.getPrefixForQName(elementTypeName));
  -	namespaceURI = pool.toString(pool.getURIForQName(elementTypeName));
  -	localName = pool.toString(pool.getLocalPartForQName(elementTypeName));
  +        name = pool.toString(elementQName);
  +
  +        // extract local part from QName
  +        int index = name.indexOf(':');
  +        if (index < 0) {
  +            localName = name;
  +        } 
  +        else {
  +            localName = name.substring(index + 1);
  +        }
  +
  +	namespaceURI = pool.toString(ownerDocument.getNodeURI(fNodeIndex));
   
           // attributes
           setupDefaultAttributes();
  -        int index = ownerDocument.getNodeValue(fNodeIndex);
  -        if (index != -1) {
  +        int attrIndex = ownerDocument.getNodeValue(fNodeIndex);
  +        if (attrIndex != -1) {
               NamedNodeMap attrs = getAttributes();
               do {
  -                NodeImpl attr = (NodeImpl)ownerDocument.getNodeObject(index);
  +                NodeImpl attr =
  +                    (NodeImpl)ownerDocument.getNodeObject(attrIndex);
                   attrs.setNamedItem(attr);
  -                index = ownerDocument.getPrevSibling(index);
  -            } while (index != -1);
  +                attrIndex = ownerDocument.getPrevSibling(attrIndex);
  +            } while (attrIndex != -1);
           }
   
       } // synchronizeData()
  
  
  
  1.3       +139 -13   xml-xerces/java/src/org/apache/xerces/framework/XMLAttrList.java
  
  Index: XMLAttrList.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/framework/XMLAttrList.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- XMLAttrList.java	2000/04/04 21:14:20	1.2
  +++ XMLAttrList.java	2000/05/17 18:32:18	1.3
  @@ -57,6 +57,7 @@
   
   package org.apache.xerces.framework;
   
  +import org.apache.xerces.utils.QName;
   import org.apache.xerces.utils.StringPool;
   
   import org.xml.sax.AttributeList;
  @@ -93,34 +94,50 @@
    * may be used to access the attribute list through the SAX <code>AttributeList</code>
    * interface.
    *
  - * @version $Id: XMLAttrList.java,v 1.2 2000/04/04 21:14:20 andyc Exp $
  + * @version $Id: XMLAttrList.java,v 1.3 2000/05/17 18:32:18 jeffreyr Exp $
    */
  -public final class XMLAttrList implements AttributeList {
  +public final class XMLAttrList 
  +    implements AttributeList {
  +
       //
  -    // Chunk size constants
  +    // Constants
       //
  +
  +    // Chunk size constants
  +
       private static final int CHUNK_SHIFT = 5;           // 2^5 = 32
       private static final int CHUNK_SIZE = (1 << CHUNK_SHIFT);
       private static final int CHUNK_MASK = CHUNK_SIZE - 1;
       private static final int INITIAL_CHUNK_COUNT = (1 << (10 - CHUNK_SHIFT));   // 2^10 = 1k
  -    //
  +
       // Flags (bits)
  -    //
  +
       private static final int ATTFLAG_SPECIFIED = 1;
       private static final int ATTFLAG_LASTATTR  = 2;
  +
       //
  -    // Instance variables
  +    // Data
       //
  +
  +    // Instance variables
  +
       private StringPool fStringPool = null;
       private int fCurrentHandle = -1;
       private int fAttributeListHandle = -1;
       private int fAttributeListLength = 0;
       private int fAttrCount = 0;
  +    private int[][] fAttPrefix = new int[INITIAL_CHUNK_COUNT][];
  +    private int[][] fAttLocalpart = new int[INITIAL_CHUNK_COUNT][];
       private int[][] fAttName = new int[INITIAL_CHUNK_COUNT][];
  +    private int[][] fAttURI = new int[INITIAL_CHUNK_COUNT][];
       private int[][] fAttValue = new int[INITIAL_CHUNK_COUNT][];
       private int[][] fAttType = new int[INITIAL_CHUNK_COUNT][];
       private byte[][] fAttFlags = new byte[INITIAL_CHUNK_COUNT][];
   
  +    // utility
  +
  +    private QName fAttributeQName = new QName();
  +
       /**
        * Constructor
        *
  @@ -143,6 +160,12 @@
           fAttrCount = 0;
       }
   
  +    public int addAttr(int attrName, int attValue, 
  +                       int attType, boolean specified, boolean search) throws Exception
  +    {
  +        fAttributeQName.setValues(-1, attrName, attrName);
  +        return addAttr(fAttributeQName, attValue, attType, specified, search);
  +    }
       /**
        * Add an attribute to the current set.
        *
  @@ -155,15 +178,18 @@
        * @return The index of this attribute; or -1 is <code>search</code> was <code>true</code>
        *         and <code>attrName</code> was already present.
        */
  -    public int addAttr(int attrName, int attValue, int attType, boolean specified, boolean search) throws Exception
  -    {
  +    public int addAttr(QName attribute, 
  +                       int attValue, int attType, 
  +                       boolean specified, boolean search) throws Exception {
  +
           int chunk;
           int index;
           if (search) {
               chunk = fCurrentHandle >> CHUNK_SHIFT;
               index = fCurrentHandle & CHUNK_MASK;
               for (int attrIndex = fCurrentHandle; attrIndex < fAttrCount; attrIndex++) {
  -                if (fStringPool.equalNames(fAttName[chunk][index], attrName)) {
  +                // REVISIT: Should this be localpart?
  +                if (fStringPool.equalNames(fAttName[chunk][index], attribute.rawname)) {
                       return -1;
                   }
                   if (++index == CHUNK_SIZE) {
  @@ -176,13 +202,17 @@
               index = fAttrCount & CHUNK_MASK;
           }
           ensureCapacity(chunk, index);
  -        fAttName[chunk][index] = attrName;
  +        fAttPrefix[chunk][index] = attribute.prefix;
  +        fAttLocalpart[chunk][index] = attribute.localpart;
  +        fAttName[chunk][index] = attribute.rawname;
  +        fAttURI[chunk][index] = attribute.uri;
           fAttValue[chunk][index] = attValue;
           fAttType[chunk][index] = attType;
           fAttFlags[chunk][index] = (byte)(specified ? ATTFLAG_SPECIFIED : 0);
           return fAttrCount++;
  -    }
   
  +    } // addAttr(QName,int,int,boolean,boolean):int
  +
       /**
        * Start a new set of attributes.
        *
  @@ -205,6 +235,29 @@
       }
   
       /**
  +     * Get the prefix of the attribute.
  +     */
  +    public int getAttrPrefix(int attrIndex) {
  +        if (attrIndex < 0 || attrIndex >= fAttrCount)
  +            return -1;
  +        int chunk = attrIndex >> CHUNK_SHIFT;
  +        int index = attrIndex & CHUNK_MASK;
  +        return fAttPrefix[chunk][index];
  +    }
  +
  +    /**
  +     * Return the localpart of the attribute.
  +     */
  +    public int getAttrLocalpart(int attrIndex) {
  +        if (attrIndex < 0 || attrIndex >= fAttrCount)
  +            return -1;
  +        int chunk = attrIndex >> CHUNK_SHIFT;
  +        int index = attrIndex & CHUNK_MASK;
  +        return fAttLocalpart[chunk][index];
  +    }
  +
  +    // REVISIT: Should this be renamed "getAttrRawname" to match?
  +    /**
        * Get the name of the attribute
        *
        * @param attrIndex The index of the attribute.
  @@ -217,6 +270,24 @@
           int index = attrIndex & CHUNK_MASK;
           return fAttName[chunk][index];
       }
  +    
  +    /** Sets the uri of the attribute. */
  +    public void setAttrURI(int attrIndex, int uri) {
  +        if (attrIndex < 0 || attrIndex >= fAttrCount)
  +            return;
  +        int chunk = attrIndex >> CHUNK_SHIFT;
  +        int index = attrIndex & CHUNK_MASK;
  +        fAttURI[chunk][index] = uri;
  +    }
  +
  +    /** Return the uri of the attribute. */
  +    public int getAttrURI(int attrIndex) {
  +        if (attrIndex < 0 || attrIndex >= fAttrCount)
  +            return -1;
  +        int chunk = attrIndex >> CHUNK_SHIFT;
  +        int index = attrIndex & CHUNK_MASK;
  +        return fAttURI[chunk][index];
  +    }
   
       /**
        * Get the value of the attribute
  @@ -273,7 +344,10 @@
           int index = attrListHandle & CHUNK_MASK;
           while (true) {
               boolean last = (fAttFlags[chunk][index] & ATTFLAG_LASTATTR) != 0;
  +            fAttPrefix[chunk][index] = -1;
  +            fAttLocalpart[chunk][index] = -1;
               fAttName[chunk][index] = -1;
  +            fAttURI[chunk][index] = -1;
               if ((fAttFlags[chunk][index] & ATTFLAG_SPECIFIED) != 0)
                   fStringPool.releaseString(fAttValue[chunk][index]);
               fAttValue[chunk][index] = -1;
  @@ -368,6 +442,30 @@
       }
   
       /**
  +     * Return the prefix of an attribute in this list (by position).
  +     */
  +    public String getPrefix(int i) {
  +        if (i < 0 || i >= fAttributeListLength) {
  +            return null;
  +        }
  +        int chunk = (fAttributeListHandle + i) >> CHUNK_SHIFT;
  +        int index = (fAttributeListHandle + i) & CHUNK_MASK;
  +        return fStringPool.toString(fAttPrefix[chunk][index]);
  +    }
  +
  +    /**
  +     * Return the local part of an attribute in this list (by position).
  +     */
  +    public String getLocalpart(int i) {
  +        if (i < 0 || i >= fAttributeListLength) {
  +            return null;
  +        }
  +        int chunk = (fAttributeListHandle + i) >> CHUNK_SHIFT;
  +        int index = (fAttributeListHandle + i) & CHUNK_MASK;
  +        return fStringPool.toString(fAttLocalpart[chunk][index]);
  +    }
  +
  +    /**
        * Return the name of an attribute in this list (by position).
        *
        * <p>The names must be unique: the SAX parser shall not include the
  @@ -391,6 +489,15 @@
           return fStringPool.toString(fAttName[chunk][index]);
       }
   
  +    /** Returns the URI of an attribute in this list (by position). */
  +    public String getURI(int i) {
  +        if (i < 0 || i >= fAttributeListLength)
  +            return null;
  +        int chunk = (fAttributeListHandle + i) >> CHUNK_SHIFT;
  +        int index = (fAttributeListHandle + i) & CHUNK_MASK;
  +        return fStringPool.toString(fAttURI[chunk][index]);
  +    }
  +
       /**
        * Return the type of an attribute in the list (by position).
        *
  @@ -510,15 +617,29 @@
           return null;
       }
   
  +    //
  +    // Private methods
  +    //
  +
       /* Expand our internal data structures as needed. */
       private boolean ensureCapacity(int chunk, int index) {
  +
           try {
               return fAttName[chunk][index] != 0;
           } catch (ArrayIndexOutOfBoundsException ex) {
               int[][] newIntArray = new int[chunk * 2][];
  +            System.arraycopy(fAttPrefix, 0, newIntArray, 0, chunk);
  +            fAttPrefix = newIntArray;
  +            newIntArray = new int[chunk * 2][];
  +            System.arraycopy(fAttLocalpart, 0, newIntArray, 0, chunk);
  +            fAttLocalpart = newIntArray;
  +            newIntArray = new int[chunk * 2][];
               System.arraycopy(fAttName, 0, newIntArray, 0, chunk);
               fAttName = newIntArray;
               newIntArray = new int[chunk * 2][];
  +            System.arraycopy(fAttURI, 0, newIntArray, 0, chunk);
  +            fAttURI = newIntArray;
  +            newIntArray = new int[chunk * 2][];
               System.arraycopy(fAttValue, 0, newIntArray, 0, chunk);
               fAttValue = newIntArray;
               newIntArray = new int[chunk * 2][];
  @@ -529,10 +650,15 @@
               fAttFlags = newByteArray;
           } catch (NullPointerException ex) {
           }
  +        fAttPrefix[chunk] = new int[CHUNK_SIZE];
  +        fAttLocalpart[chunk] = new int[CHUNK_SIZE];
           fAttName[chunk] = new int[CHUNK_SIZE];
  +        fAttURI[chunk] = new int[CHUNK_SIZE];
           fAttValue[chunk] = new int[CHUNK_SIZE];
           fAttType[chunk] = new int[CHUNK_SIZE];
           fAttFlags[chunk] = new byte[CHUNK_SIZE];
           return true;
  -    }
  -}
  +
  +    } // ensureCapacity(int,int):boolean
  +
  +} // class XMLAttrList
  
  
  
  1.3       +350 -38   xml-xerces/java/src/org/apache/xerces/framework/XMLContentSpec.java
  
  Index: XMLContentSpec.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/framework/XMLContentSpec.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- XMLContentSpec.java	2000/04/04 21:14:20	1.2
  +++ XMLContentSpec.java	2000/05/17 18:32:20	1.3
  @@ -57,6 +57,8 @@
   
   package org.apache.xerces.framework;
   
  +import org.apache.xerces.utils.StringPool;
  +
   /**
    * ContentSpec really exists to aid the parser classes in implementing
    * access to the grammar.
  @@ -107,60 +109,370 @@
    * string pool index, as the "#PCDATA" leaf is not used in the declarations
    * for element content models.
    *
  - * @version $Id: XMLContentSpec.java,v 1.2 2000/04/04 21:14:20 andyc Exp $
  + * @version $Id: XMLContentSpec.java,v 1.3 2000/05/17 18:32:20 jeffreyr Exp $
    */
  +public class XMLContentSpec {
   
  -public interface XMLContentSpec {
  -    /**
  -     * return this ContentSpec as a string
  +    //
  +    // Constants
  +    //
  +
  +    /** 
  +     * Name or #PCDATA. Leaf nodes that represent parsed character
  +     * data (#PCDATA) have values of -1.
  +     */
  +    public static final int CONTENTSPECNODE_LEAF = 0;
  +
  +    /** Represents a zero or one occurence count, '?'. */
  +    public static final int CONTENTSPECNODE_ZERO_OR_ONE = 1;
  +
  +    /** Represents a zero or more occurence count, '*'. */
  +    public static final int CONTENTSPECNODE_ZERO_OR_MORE = 2;
  +    
  +    /** Represents a one or more occurence count, '+'. */
  +    public static final int CONTENTSPECNODE_ONE_OR_MORE = 3;
  +    
  +    /** Represents choice, '|'. */
  +    public static final int CONTENTSPECNODE_CHOICE = 4;
  +    
  +    /** Represents sequence, ','. */
  +    public static final int CONTENTSPECNODE_SEQ = 5;
  +
  +    //
  +    // Data
  +    //
  +
  +    /** 
  +     * The content spec node type. 
        *
  -     * @return the content spec as a string
  +     * @see CONTENTSPECNODE_LEAF
  +     * @see CONTENTSPECNODE_ZERO_OR_ONE
  +     * @see CONTENTSPECNODE_ZERO_OR_MORE
  +     * @see CONTENTSPECNODE_ONE_OR_MORE
  +     * @see CONTENTSPECNODE_CHOICE
  +     * @see CONTENTSPECNODE_SEQ
        */
  -    public String toString();
  +    public int type;
  +
       /**
  -     * return the type of this ContentSpec
  -     *
  -     * @return The string pool handle for the type of this ContentSpec
  +     * The "left hand" value of the content spec node.
  +     * // leaf index, single child for unary ops, left child for binary ops.
        */
  -    public int getType();
  +    public int value;
  +
       /**
  -     * get this ContentSpec's handle
  -     *
  -     * @return handle for this ContentSpec
  +     * The "right hand" value of the content spec node.
  +     * // right child for binary ops
  +     */
  +    public int otherValue;
  +
  +    //
  +    // Constructors
  +    //
  +
  +    /** Default constructor. */
  +    public XMLContentSpec() {
  +        clear();
  +    }
  +
  +    /** Constructs a content spec with the specified values. */
  +    public XMLContentSpec(int type, int value, int otherValue) {
  +        setValues(type, value, otherValue);
  +    }
  +
  +    /** 
  +     * Constructs a content spec from the values in the specified content spec.
        */
  -    public int getHandle();
  +    public XMLContentSpec(XMLContentSpec contentSpec) {
  +        setValues(contentSpec);
  +    }
  +
       /**
  -     * fill in XMLContentSpec.Node node with the information for
  -     * ContentSpec in handle
  -     * 
  -     * @param handle ContentSpec handle
  -     * @param node result XMLContentSpec.Node
  +     * Constructs a content spec from the values specified by the given
  +     * content spec provider and identifier.
        */
  -    public void getNode(int handle, XMLContentSpec.Node node);
  +    public XMLContentSpec(XMLContentSpec.Provider provider,
  +                          int contentSpecIndex) {
  +        setValues(provider, contentSpecIndex);
  +    }
   
       //
  -    // node type
  +    // Public methods
       //
  -    // Note: The #PCDATA leaf in a MIXED content spec is indicated by a type
  -    //       of CONTENTSPECNODE_LEAF and an value of -1.
  +
  +    /** Clears the values. */
  +    public void clear() {
  +        type = -1;
  +        value = -1;
  +        otherValue = -1;
  +    }
  +
  +    /** Sets the values. */
  +    public void setValues(int type, int value, int otherValue) {
  +        this.type = type;
  +        this.value = value;
  +        this.otherValue = otherValue;
  +    }
  +    
  +    /** Sets the values of the specified content spec. */
  +    public void setValues(XMLContentSpec contentSpec) {
  +        type = contentSpec.type;
  +        value = contentSpec.value;
  +        otherValue = contentSpec.otherValue;
  +    }
  +
  +    /**
  +     * Sets the values from the values specified by the given content spec
  +     * provider and identifier. If the specified content spec cannot be
  +     * provided, the values of this content spec are cleared.
  +     */
  +    public void setValues(XMLContentSpec.Provider provider,
  +                          int contentSpecIndex) {
  +        if (!provider.getContentSpec(contentSpecIndex, this)) {
  +            clear();
  +        }
  +    }
  +
  +    //
  +    // Public static methods
  +    //
  +
  +    /** 
  +     * Returns a string representation of the specified content spec 
  +     * identifier in the form of a DTD element content model.
  +     * <p>
  +     * <strong>Note:</strong> This method is not namespace aware.
  +     */
  +    public static String toString(XMLContentSpec.Provider provider, 
  +                                  StringPool stringPool, 
  +                                  int contentSpecIndex) {
  +
  +        // lookup content spec node
  +        XMLContentSpec contentSpec = new XMLContentSpec();
  +        if (provider.getContentSpec(contentSpecIndex, contentSpec)) {
  +
  +            // build string
  +            StringBuffer str = new StringBuffer();
  +            switch (contentSpec.type) {
  +                case XMLContentSpec.CONTENTSPECNODE_LEAF: {
  +                    str.append('(');
  +                    if (contentSpec.value == -1) {
  +                        str.append("#PCDATA");
  +                    }
  +                    else {
  +                        str.append(stringPool.toString(contentSpec.value));
  +                    }
  +                    str.append(')');
  +                    break;
  +                }
  +                case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE: {
  +                    provider.getContentSpec(contentSpec.value, contentSpec);
  +                    if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
  +                        str.append('(');
  +                        if (contentSpec.value == -1) {
  +                            str.append("#PCDATA");
  +                        }
  +                        else {
  +                            str.append(stringPool.toString(contentSpec.value));
  +                        }
  +                        str.append(")?");
  +                    }
  +                    else {
  +                        appendContentSpec(provider, stringPool, contentSpec, str, true);
  +                    }
  +                    break;
  +                }
  +                case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE: {
  +                    provider.getContentSpec(contentSpec.value, contentSpec);
  +                    if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
  +                        str.append('(');
  +                        if (contentSpec.value == -1) {
  +                            str.append("#PCDATA");
  +                        }
  +                        else {
  +                            str.append(stringPool.toString(contentSpec.value));
  +                        }
  +                        str.append(")*");
  +                    }
  +                    else {
  +                        appendContentSpec(provider, stringPool, contentSpec, str, true);
  +                    }
  +                    break;
  +                }
  +                case XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE: {
  +                    provider.getContentSpec(contentSpec.value, contentSpec);
  +                    if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
  +                        str.append('(');
  +                        if (contentSpec.value == -1) {
  +                            str.append("#PCDATA");
  +                        }
  +                        else {
  +                            str.append(stringPool.toString(contentSpec.value));
  +                        }
  +                        str.append(")+");
  +                    }
  +                    else {
  +                        appendContentSpec(provider, stringPool, contentSpec, str, true);
  +                    }
  +                    break;
  +                }
  +                case XMLContentSpec.CONTENTSPECNODE_CHOICE:
  +                case XMLContentSpec.CONTENTSPECNODE_SEQ: {
  +                    appendContentSpec(provider, stringPool,
  +                                      contentSpec, str, true);
  +                    break;
  +                }
  +                default: {
  +                    return null;
  +                }
  +
  +            } // switch type
  +
  +            // return string
  +            return str.toString();
  +        }
  +
  +        // not found
  +        return null;
  +
  +    } // toString(XMLContentSpec.Provider):String
  +
  +    //
  +    // Object methods
       //
  -    public static final int
  -        CONTENTSPECNODE_LEAF           = 0,            // Name or #PCDATA (-1)
  -        CONTENTSPECNODE_ZERO_OR_ONE    = 1,            // '?'
  -        CONTENTSPECNODE_ZERO_OR_MORE   = 2,            // '*'
  -        CONTENTSPECNODE_ONE_OR_MORE    = 3,            // '+'
  -        CONTENTSPECNODE_CHOICE         = 4,            // '|'
  -        CONTENTSPECNODE_SEQ            = 5;            // ','
  +
  +    /** Returns a hash code for this node. */
  +    public int hashCode() {
  +        return type << 16 | 
  +               value << 8 |
  +               otherValue;
  +    }
  +
  +    /** Returns true if the two objects are equal. */
  +    public boolean equals(Object object) {
  +        if (object != null && object instanceof XMLContentSpec) {
  +            XMLContentSpec contentSpec = (XMLContentSpec)object;
  +            return type == contentSpec.type &&
  +                   value == contentSpec.value &&
  +                   otherValue == contentSpec.otherValue;
  +        }
  +        return false;
  +    }
   
       //
  -    // Node record
  +    // Private static methods
       //
  -    public final class Node {
  +
  +    /**
  +     * Appends more information to the current string buffer.
  +     * <p>
  +     * <strong>Note:</strong> This method does <em>not</em> preserve the
  +     * contents of the content spec node.
  +     */
  +    private static void appendContentSpec(XMLContentSpec.Provider provider,
  +                                          StringPool stringPool,
  +                                          XMLContentSpec contentSpec, 
  +                                          StringBuffer str, 
  +                                          boolean parens) {
  +
  +        switch (contentSpec.type) {
  +            case XMLContentSpec.CONTENTSPECNODE_LEAF: {
  +                if (contentSpec.value == -1) {
  +                    str.append("#PCDATA");
  +                }
  +                else {
  +                    str.append(stringPool.toString(contentSpec.value));
  +                }
  +                break;
  +            }
  +            case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE: {
  +                provider.getContentSpec(contentSpec.value, contentSpec);
  +                appendContentSpec(provider, stringPool, 
  +                                  contentSpec, str, true);
  +                str.append('?');
  +                break;
  +            }
  +            case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE: {
  +                provider.getContentSpec(contentSpec.value, contentSpec);
  +                appendContentSpec(provider, stringPool,
  +                                  contentSpec, str, true);
  +                str.append('*');
  +                break;
  +            }
  +            case XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE: {
  +                provider.getContentSpec(contentSpec.value, contentSpec);
  +                appendContentSpec(provider, stringPool,
  +                                  contentSpec, str, true);
  +                str.append('+');
  +                break;
  +            }
  +            case XMLContentSpec.CONTENTSPECNODE_CHOICE:
  +            case XMLContentSpec.CONTENTSPECNODE_SEQ: {
  +                if (parens) {
  +                    str.append('(');
  +                }
  +                int type = contentSpec.type;
  +                int otherValue = contentSpec.otherValue;
  +                provider.getContentSpec(contentSpec.value, contentSpec);
  +                appendContentSpec(provider, stringPool,
  +                                  contentSpec, str, contentSpec.type != type);
  +                if (type == XMLContentSpec.CONTENTSPECNODE_CHOICE) {
  +                    str.append('|');
  +                }
  +                else {
  +                    str.append(',');
  +                }
  +                /***
  +                // REVISIT: Do we need this? -Ac
  +                if (++index == CHUNK_SIZE) {
  +                    chunk++;
  +                    index = 0;
  +                }
  +                /***/
  +                provider.getContentSpec(otherValue, contentSpec);
  +                appendContentSpec(provider, stringPool,
  +                                  contentSpec, str, true);
  +                if (parens) {
  +                    str.append(')');
  +                }
  +                break;
  +            }
  +
  +        } // switch type
  +
  +    } // appendContentSpec(XMLContentSpec.Provider,StringPool,XMLContentSpec,StringBuffer,boolean)
  +
  +    //
  +    // Interfaces
  +    //
  +
  +    /**
  +     * Provides a means for walking the structure built out of 
  +     * content spec "nodes". The user of this provider interface is
  +     * responsible for knowing what the content spec node values
  +     * "mean". If those values refer to content spec identifiers,
  +     * then the user can call back into the provider to get the
  +     * next content spec node in the structure.
  +     */
  +    public interface Provider {
  +
           //
  -        // Public instance variables - filled in on each call to getNode().
  +        // XMLContentSpec.Provider methods
           //
  -        public int type;                    // node type (see above)
  -        public int value;                   // leaf index, single child for unary ops, left child for binary ops.
  -        public int otherValue;              // right child for binary ops
  -    }
  -}
  +
  +        /**
  +         * Fills in the provided content spec structure with content spec
  +         * information for a unique identifier.
  +         *
  +         * @param contentSpecIndex The content spec identifier. All content
  +         *                         spec "nodes" have a unique identifier.
  +         * @param contentSpec      The content spec struct to fill in with
  +         *                         the information.
  +         *
  +         * @return Returns true if the contentSpecIndex was found.
  +         */
  +        public boolean getContentSpec(int contentSpecIndex, XMLContentSpec contentSpec);
  +
  +    } // interface Provider
  +
  +} // class XMLContentSpec
  
  
  
  1.7       +803 -288  xml-xerces/java/src/org/apache/xerces/framework/XMLDTDScanner.java
  
  Index: XMLDTDScanner.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/framework/XMLDTDScanner.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- XMLDTDScanner.java	2000/04/04 21:14:20	1.6
  +++ XMLDTDScanner.java	2000/05/17 18:32:20	1.7
  @@ -58,12 +58,21 @@
   package org.apache.xerces.framework;
   
   import org.apache.xerces.readers.XMLEntityHandler;
  +import org.apache.xerces.readers.DefaultEntityHandler;
  +import org.apache.xerces.utils.QName;
   import org.apache.xerces.utils.StringPool;
  +import org.apache.xerces.utils.XMLCharacterProperties;
   import org.apache.xerces.utils.XMLMessages;
  +import org.apache.xerces.validators.common.Grammar;
  +import org.apache.xerces.validators.common.GrammarResolver;
  +import org.apache.xerces.validators.common.XMLAttributeDecl;
  +import org.apache.xerces.validators.common.XMLElementDecl;
  +import org.apache.xerces.validators.dtd.DTDGrammar;
   
   import org.xml.sax.Locator;
   import org.xml.sax.SAXParseException;
   
  +import java.util.StringTokenizer;
   /**
    * Default implementation of an XML DTD scanner.
    * <p>
  @@ -81,7 +90,7 @@
    * </ol>
    *
    * @see XMLDTDScanner.EventHandler
  - * @version $Id: XMLDTDScanner.java,v 1.6 2000/04/04 21:14:20 andyc Exp $
  + * @version $Id: XMLDTDScanner.java,v 1.7 2000/05/17 18:32:20 jeffreyr Exp $
    */
   public final class XMLDTDScanner {
       //
  @@ -172,6 +181,15 @@
       //
       // Instance Variables
       //
  +    private DTDGrammar fDTDGrammar = null;
  +    private GrammarResolver fGrammarResolver = null;
  +    private boolean fNamespacesEnabled = false;
  +    private boolean fValidationEnabled = false;
  +    private XMLElementDecl fTempElementDecl = new XMLElementDecl();
  +    private XMLAttributeDecl fTempAttributeDecl = new XMLAttributeDecl();
  +    private QName fElementQName = new QName();
  +    private QName fAttributeQName = new QName();
  +    private QName fElementRefQName = new QName();
       private EventHandler fEventHandler = null;
       private StringPool fStringPool = null;
       private XMLErrorReporter fErrorReporter = null;
  @@ -195,24 +213,6 @@
       private int fDefaultAttValueMark = -1;
       private int fEntityValueReader = -1;
       private int fEntityValueMark = -1;
  -    private int fEMPTY = -1;
  -    private int fANY = -1;
  -    private int fMIXED = -1;
  -    private int fCHILDREN = -1;
  -    private int fCDATA = -1;
  -    private int fID = -1;
  -    private int fIDREF = -1;
  -    private int fIDREFS = -1;
  -    private int fENTITY = -1;
  -    private int fENTITIES = -1;
  -    private int fNMTOKEN = -1;
  -    private int fNMTOKENS = -1;
  -    private int fNOTATION = -1;
  -    private int fENUMERATION = -1;
  -    private int fREQUIRED = -1;
  -    private int fIMPLIED = -1;
  -    private int fFIXED = -1;
  -    private int fDEFAULT = -1;
       private int fXMLSpace = -1;
       private int fDefault = -1;
       private int fPreserve = -1;
  @@ -240,6 +240,17 @@
       public void setEventHandler(XMLDTDScanner.EventHandler eventHandler) {
           fEventHandler = eventHandler;
       }
  +
  +    /** Sets the grammar resolver. */
  +    public void setGrammarResolver(GrammarResolver resolver) {
  +        fGrammarResolver = resolver;
  +    }
  +
  +    /** set fValidationEnabled  **/
  +    public void setValidationEnabled(boolean enabled) {
  +        fValidationEnabled = enabled;
  +    }
  +
       /**
        * Is the XMLDTDScanner reading from an external entity?
        *
  @@ -329,24 +340,6 @@
           init();
       }
       private void init() {
  -        fEMPTY = fStringPool.addSymbol("EMPTY");
  -        fANY = fStringPool.addSymbol("ANY");
  -        fMIXED = fStringPool.addSymbol("MIXED");
  -        fCHILDREN = fStringPool.addSymbol("CHILDREN");
  -        fCDATA = fStringPool.addSymbol("CDATA");
  -        fID = fStringPool.addSymbol("ID");
  -        fIDREF = fStringPool.addSymbol("IDREF");
  -        fIDREFS = fStringPool.addSymbol("IDREFS");
  -        fENTITY = fStringPool.addSymbol("ENTITY");
  -        fENTITIES = fStringPool.addSymbol("ENTITIES");
  -        fNMTOKEN = fStringPool.addSymbol("NMTOKEN");
  -        fNMTOKENS = fStringPool.addSymbol("NMTOKENS");
  -        fNOTATION = fStringPool.addSymbol("NOTATION");
  -        fENUMERATION = fStringPool.addSymbol("ENUMERATION");
  -        fREQUIRED = fStringPool.addSymbol("#REQUIRED");
  -        fIMPLIED = fStringPool.addSymbol("#IMPLIED");
  -        fFIXED = fStringPool.addSymbol("#FIXED");
  -        fDEFAULT = fStringPool.addSymbol("");
           fXMLSpace = fStringPool.addSymbol("xml:space");
           fDefault = fStringPool.addSymbol("default");
           fPreserve = fStringPool.addSymbol("preserve");
  @@ -362,30 +355,13 @@
        * more generic task of scanning the DTD-specific XML grammar.
        */
       public interface EventHandler {
  -        /**
  -         * Determine whether a string is a valid XML version number
  -         *  
  -         * @param version string to be checked
  -         * @return true if version is a valid XML version number
  -         * @exception java.lang.Exception
  -         */
  -        public boolean validVersionNum(String version) throws Exception;
  -        /**
  -         * Determine whether a string is a valid encoding name
  -         *
  -         * @param encoding string to be checked
  -         * @return true if encoding is a valid encoding name
  -         * @exception java.lang.Exception
  -         */
  -        public boolean validEncName(String encoding) throws Exception;
  -        /**
  -         * Determine if a string is a valid public identifier
  -         *
  -         * @param publicId string to be checked
  -         * @return true if publicId is a valid public identifier
  -         * @exception java.lang.Exception
  -         */
  -        public int validPublicId(String publicId) throws Exception;
  +
  +        /** Start of DTD. */
  +        public void callStartDTD() throws Exception;
  +
  +        /** End of DTD. */
  +        public void callEndDTD() throws Exception;
  +
           /**
            * Signal the Text declaration of an external entity.
            *
  @@ -402,7 +378,7 @@
            * @param systemId StringPool handle of the system id
            * @exception java.lang.Exception
            */
  -        public void doctypeDecl(int rootElementType, int publicId, int systemId) throws Exception;
  +        public void doctypeDecl(QName rootElement, int publicId, int systemId) throws Exception;
           /**
            * Called when the DTDScanner starts reading from the external subset
            *
  @@ -424,7 +400,7 @@
            * @return handle to the element whose declaration was added
            * @exception java.lang.Exception
            */
  -        public int addElementDecl(int elementType) throws Exception;
  +        public int addElementDecl(QName elementDecl) throws Exception;
           /**
            * Add an element declaration
            *
  @@ -434,7 +410,7 @@
            * @return handle to the element declaration that was added 
            * @exception java.lang.Exception
            */
  -        public int addElementDecl(int elementType, int contentSpecType, int contentSpec) throws Exception;
  +        public int addElementDecl(QName elementDecl, int contentSpecType, int contentSpec, boolean isExternal) throws Exception;
           /**
            * Add an attribute definition
            *
  @@ -447,38 +423,40 @@
            * @return handle to the attribute definition
            * @exception java.lang.Exception
            */
  -        public int addAttDef(int elementIndex, int attName, int attType, int enumeration, int attDefaultType, int attDefaultValue) throws Exception;
  +        public int addAttDef(QName elementDecl, QName attributeDecl, 
  +                             int attType, boolean attList, int enumeration, 
  +                             int attDefaultType, int attDefaultValue, boolean isExternal) throws Exception;
           /**
  -         * create an XMLContentSpec.Node for a leaf
  +         * create an XMLContentSpec for a leaf
            *
            * @param nameIndex StringPool handle to the name (Element) for the node
  -         * @return handle to the newly create XMLContentSpec.Node
  +         * @return handle to the newly create XMLContentSpec
            * @exception java.lang.Exception
            */
           public int addUniqueLeafNode(int nameIndex) throws Exception;
           /**
  -         * Create an XMLContentSpec.Node for a single non-leaf
  +         * Create an XMLContentSpec for a single non-leaf
            * 
  -         * @param nodeType the type of XMLContentSpec.Node to create - from XMLContentSpec.CONTENTSPECNODE_*
  -         * @param nodeValue handle to an XMLContentSpec.Node
  -         * @return handle to the newly create XMLContentSpec.Node
  +         * @param nodeType the type of XMLContentSpec to create - from XMLContentSpec.CONTENTSPECNODE_*
  +         * @param nodeValue handle to an XMLContentSpec
  +         * @return handle to the newly create XMLContentSpec
            * @exception java.lang.Exception
            */
           public int addContentSpecNode(int nodeType, int nodeValue) throws Exception;
           /**
  -         * Create an XMLContentSpec.Node for a two child leaf
  +         * Create an XMLContentSpec for a two child leaf
            *
  -         * @param nodeType the type of XMLContentSpec.Node to create - from XMLContentSpec.CONTENTSPECNODE_*
  -         * @param leftNodeIndex handle to an XMLContentSpec.Node
  -         * @param rightNodeIndex handle to an XMLContentSpec.Node
  -         * @return handle to the newly create XMLContentSpec.Node
  +         * @param nodeType the type of XMLContentSpec to create - from XMLContentSpec.CONTENTSPECNODE_*
  +         * @param leftNodeIndex handle to an XMLContentSpec
  +         * @param rightNodeIndex handle to an XMLContentSpec
  +         * @return handle to the newly create XMLContentSpec
            * @exception java.lang.Exception
            */
           public int addContentSpecNode(int nodeType, int leftNodeIndex, int rightNodeIndex) throws Exception;
           /**
  -         * Create a string representation of an XMLContentSpec.Node tree
  +         * Create a string representation of an XMLContentSpec tree
            * 
  -         * @param handle to an XMLContentSpec.Node
  +         * @param handle to an XMLContentSpec
            * @return String representation of the content spec tree
            * @exception java.lang.Exception
            */
  @@ -593,78 +571,6 @@
            */
           public void callProcessingInstruction(int piTarget, int piData) throws Exception;
           /**
  -         * Scan an element type
  -         *
  -         * @param entityReader reader to read from
  -         * @param fastchar hint - character likely to terminate the element type
  -         * @return StringPool handle for the element type
  -         * @exception java.lang.Exception
  -         */
  -        public int scanElementType(XMLEntityHandler.EntityReader entityReader, char fastchar) throws Exception;
  -        /**
  -         * Scan for an element type at a point in the grammar where parameter
  -         * entity references are allowed.  If such a reference is encountered,
  -         * the replacement text will be scanned, skipping any white space that
  -         * may be found, expanding references in this manner until an element
  -         * type is scanned, or we fail to find one.
  -         *
  -         * @param entityReader reader to read from
  -         * @param fastchar hint - character likely to terminate the element type
  -         * @return StringPool handle for the element type
  -         * @exception java.lang.Exception
  -         */
  -        public int checkForElementTypeWithPEReference(XMLEntityHandler.EntityReader entityReader, char fastchar) throws Exception;
  -        /**
  -         * Scan for an attribute name at a point in the grammar where parameter
  -         * entity references are allowed.  If such a reference is encountered,
  -         * the replacement text will be scanned, skipping any white space that
  -         * may be found, expanding references in this manner until an attribute
  -         * name is scanned, or we fail to find one.
  -         *
  -         * @param entityReader reader to read from
  -         * @param fastchar hint - character likely to terminate the attribute name
  -         * @return StringPool handle for the attribute name
  -         * @exception java.lang.Exception
  -         */
  -        public int checkForAttributeNameWithPEReference(XMLEntityHandler.EntityReader entityReader, char fastcheck) throws Exception;
  -        /**
  -         * Scan for a Name at a point in the grammar where parameter entity
  -         * references are allowed.  If such a reference is encountered, the
  -         * replacement text will be scanned, skipping any white space that
  -         * may be found, expanding references in this manner until a name
  -         * is scanned, or we fail to find one.
  -         *
  -         * @param entityReader reader to read from
  -         * @param fastcheck hint - character likely to terminate the name
  -         * @return StringPool handle for the name
  -         * @exception java.lang.Exception
  -         */
  -        public int checkForNameWithPEReference(XMLEntityHandler.EntityReader entityReader, char fastcheck) throws Exception;
  -        /**
  -         * Scan for a name token at a point in the grammar where parameter
  -         * entity references are allowed.  If such a reference is encountered,
  -         * the replacement text will be scanned, skipping any white space that
  -         * may be found, expanding references in this manner until a name
  -         * token is scanned, or we fail to find one.
  -         *
  -         * @param entityReader reader to read from
  -         * @param fastcheck hint - character likely to terminate the name token
  -         * @return StringPool handle for the name token
  -         * @exception java.lang.Exception
  -         */
  -        public int checkForNmtokenWithPEReference(XMLEntityHandler.EntityReader entityReader, char fastcheck) throws Exception;
  -        /**
  -         * Scan the default value for an attribute
  -         * 
  -         * @param elementType handle to the element type that owns the attribute
  -         * @param attrName StringPool handle to the name of the attribute
  -         * @param attType the attribute type
  -         * @param enumeration StringPool handle to a string list containing enumeration values
  -         * @return StringPool handle to the default value
  -         * @exception java.lang.Exception
  -         */
  -        public int scanDefaultAttValue(int elementType, int attrName, int attType, int enumeration) throws Exception;
  -        /**
            * Supports DOM Level 2 internalSubset additions.
            * Called when the internal subset is completely scanned.
            */
  @@ -673,6 +579,52 @@
       //
       //
       //
  +    
  +    /** Report a recoverable xml error. */
  +    protected void reportRecoverableXMLError(int majorCode, int minorCode, 
  +                                             int stringIndex1) 
  +        throws Exception {
  +
  +        Object[] args = { fStringPool.toString(stringIndex1) };
  +        fErrorReporter.reportError(fErrorReporter.getLocator(),
  +                                   XMLMessages.XML_DOMAIN,
  +                                   majorCode,
  +                                   minorCode,
  +                                   args,
  +                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
  +
  +    } // reportRecoverableXMLError(int,int,int)
  +
  +    /** Report a recoverable xml error. */
  +    protected void reportRecoverableXMLError(int majorCode, int minorCode, 
  +                                         String string1) throws Exception {
  +
  +        Object[] args = { string1 };
  +        fErrorReporter.reportError(fErrorReporter.getLocator(),
  +                                   XMLMessages.XML_DOMAIN,
  +                                   majorCode,
  +                                   minorCode,
  +                                   args,
  +                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
  +
  +    } // reportRecoverableXMLError(int,int,String)
  +    
  +    /** Report a recoverable xml error. */
  +    protected void reportRecoverableXMLError(int majorCode, int minorCode, 
  +                                             String string1, String string2) 
  +        throws Exception {
  +
  +        Object[] args = { string1, string2 };
  +        fErrorReporter.reportError(fErrorReporter.getLocator(),
  +                                   XMLMessages.XML_DOMAIN,
  +                                   majorCode,
  +                                   minorCode,
  +                                   args,
  +                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
  +
  +    } // reportRecoverableXMLError(int,int,String,String)
  +    
  + 
       private void reportFatalXMLError(int majorCode, int minorCode) throws Exception {
           fErrorReporter.reportError(fErrorReporter.getLocator(),
                                      XMLMessages.XML_DOMAIN,
  @@ -801,7 +753,28 @@
        * @exception java.lang.Exception
        */
       public void endOfInput(int entityNameIndex, boolean moreToFollow) throws Exception {
  +        if (fValidationEnabled ) {
  +            int readerDepth = fEntityHandler.getReaderDepth();
  +            if (getReadingContentSpec()) {
  +                int parenDepth = parenDepth();
  +                if (readerDepth != parenDepth) {
  +                    reportRecoverableXMLError(XMLMessages.MSG_IMPROPER_GROUP_NESTING,
  +                                                XMLMessages.VC_PROPER_GROUP_PE_NESTING,
  +                                                entityNameIndex);
  +                }
  +            } else {
  +                int markupDepth = markupDepth();
  +                if (readerDepth != markupDepth) {
  +                    reportRecoverableXMLError(XMLMessages.MSG_IMPROPER_DECLARATION_NESTING,
  +                                                XMLMessages.VC_PROPER_DECLARATION_PE_NESTING,
  +                                                entityNameIndex);
  +                }
  +            }
  +        }
  +        //REVISIT, why are we doing this?
           moreToFollow = fReaderId != fExternalSubsetReader;
  +
  +//      System.out.println("current Scanner state " + getScannerState() +","+ fScannerState + moreToFollow);
           switch (fScannerState) {
           case SCANNER_STATE_INVALID:
               throw new RuntimeException("FWK004 XMLDTDScanner.endOfInput: cannot happen: 2"+"\n2");
  @@ -960,7 +933,7 @@
                               sawDashDash = true;
                           }
                           decreaseMarkupDepth();
  -                        fEventHandler.callComment(fEntityReader.addString(commentOffset, endOffset - commentOffset));
  +                        fDTDGrammar.callComment(fEntityReader.addString(commentOffset, endOffset - commentOffset));
                           restoreScannerState(previousState);
                           return;
                       } else if (!sawDashDash) {
  @@ -1048,7 +1021,7 @@
           }
           int piData = piDataLength == 0 ?
                        StringPool.EMPTY_STRING : fEntityReader.addString(piDataOffset, piDataLength);
  -        fEventHandler.callProcessingInstruction(piTarget, piData);
  +        fDTDGrammar.callProcessingInstruction(piTarget, piData);
       }
       //
       // From the standard:
  @@ -1071,6 +1044,10 @@
        */
       public boolean scanDoctypeDecl() throws Exception
       {
  +        //System.out.println("XMLDTDScanner#scanDoctypeDecl()");
  +
  +        fDTDGrammar = new DTDGrammar(fStringPool, fEventHandler);
  +        fDTDGrammar.callStartDTD();
           increaseMarkupDepth();
           fEntityReader = fEntityHandler.getEntityReader();
           fReaderId = fEntityHandler.getReaderId();
  @@ -1082,8 +1059,8 @@
               return false;
           }
           fEntityReader.skipPastSpaces();
  -        int rootElementType = fEventHandler.scanElementType(fEntityReader, ' ');
  -        if (rootElementType == -1) {
  +        scanElementType(fEntityReader, ' ', fElementQName);
  +        if (fElementQName.rawname == -1) {
               abortMarkup(XMLMessages.MSG_ROOT_ELEMENT_TYPE_REQUIRED,
                           XMLMessages.P28_ROOT_ELEMENT_TYPE_REQUIRED);
               return false;
  @@ -1107,7 +1084,7 @@
               }
           } else
               lbrkt = fEntityReader.lookingAtChar('[', true);
  -        fEventHandler.doctypeDecl(rootElementType, publicId, systemId);
  +        fDTDGrammar.doctypeDecl(fElementQName, publicId, systemId);
           if (lbrkt) {
               scanDecls(false);
               fEntityReader.skipPastSpaces();
  @@ -1116,14 +1093,23 @@
               if (fScannerState != SCANNER_STATE_END_OF_INPUT) {
                   abortMarkup(XMLMessages.MSG_DOCTYPEDECL_UNTERMINATED,
                               XMLMessages.P28_UNTERMINATED,
  -                            rootElementType);
  +                            fElementQName.rawname);
               }
               return false;
           }
  +
           decreaseMarkupDepth();
  +
  +        //System.out.println("  scanExternalSubset: "+scanExternalSubset);
  +        if (scanExternalSubset) {
  +            ((DefaultEntityHandler) fEntityHandler).startReadingFromExternalSubset( fStringPool.toString(publicId),
  +                                                                                    fStringPool.toString(systemId),
  +                                                                                    markupDepth());
  +            fDTDGrammar.startReadingFromExternalSubset(publicId, systemId);
  +        }
  +
  +        fGrammarResolver.putGrammar("", fDTDGrammar);
   
  -        if (scanExternalSubset)
  -            fEventHandler.startReadingFromExternalSubset(publicId, systemId);
   
           return true;
       }
  @@ -1197,9 +1183,12 @@
           boolean dataok = true;
           boolean fragment = false;
           while (!fEntityReader.lookingAtChar(qchar, false)) {
  +//ericye
  +//System.out.println("XMLDTDScanner#scanDoctypeDecl() 3333333, "+fReaderId+", " + fScannerState+", " +fExternalSubsetReader);
               if (fEntityReader.lookingAtChar('#', true)) {
                   fragment = true;
               } else if (!fEntityReader.lookingAtValidChar(true)) {
  +//System.out.println("XMLDTDScanner#scanDoctypeDecl() 555555 scan state: " + fScannerState);
                   dataok = false;
                   int invChar = fEntityReader.scanInvalidChar();
                   if (fScannerState == SCANNER_STATE_END_OF_INPUT)
  @@ -1307,7 +1296,7 @@
               int dataLength = fLiteralData.length() - dataOffset;
               fPubidLiteral = fLiteralData.addString(dataOffset, dataLength);
               String publicId = fStringPool.toString(fPubidLiteral);
  -            int invCharIndex = fEventHandler.validPublicId(publicId);
  +            int invCharIndex = validPublicId(publicId);
               if (invCharIndex >= 0) {
                   reportFatalXMLError(XMLMessages.MSG_PUBIDCHAR_ILLEGAL,
                                       XMLMessages.P12_INVALID_CHARACTER,
  @@ -1363,10 +1352,11 @@
           boolean parseTextDecl = extSubset;
           int prevState = setScannerState(SCANNER_STATE_MARKUP_DECL);
           while (fScannerState == SCANNER_STATE_MARKUP_DECL) {
  +
               boolean newParseTextDecl = false;
               if (!extSubset && fEntityReader.lookingAtChar(']', false)) {
                   int subsetLength = fEntityReader.currentOffset() - subsetOffset;
  -                fEventHandler.internalSubset(fEntityReader.addString(subsetOffset, subsetLength));
  +                fDTDGrammar.internalSubset(fEntityReader.addString(subsetOffset, subsetLength));
                   fEntityReader.lookingAtChar(']', true);
                   restoreScannerState(prevState);
                   return;
  @@ -1403,8 +1393,9 @@
                               abortMarkup(XMLMessages.MSG_MARKUP_NOT_RECOGNIZED_IN_DTD,
                                           XMLMessages.P29_NOT_RECOGNIZED);
                           }
  -                    } else if (fEntityReader.skippedString(element_string))
  +                    } else if (fEntityReader.skippedString(element_string)) {
                           scanElementDecl();
  +                    }
                       else if (fEntityReader.skippedString(attlist_string))
                           scanAttlistDecl();
                       else if (fEntityReader.skippedString(entity_string))
  @@ -1489,8 +1480,15 @@
               }
               parseTextDecl = newParseTextDecl;
           }
  -        if (extSubset)
  -            fEventHandler.stopReadingFromExternalSubset();
  +        if (extSubset) {
  +
  +            ((DefaultEntityHandler) fEntityHandler).stopReadingFromExternalSubset();
  +
  +            fDTDGrammar.stopReadingFromExternalSubset();
  +            fDTDGrammar.callEndDTD();
  +            // REVISIT: What should the namspace URI of a DTD be?
  +            fGrammarResolver.putGrammar("", fDTDGrammar);
  +        }
       }
       //
       // [64] ignoreSectContents ::= Ignore ('<![' ignoreSectContents ']]>' Ignore)*
  @@ -1613,7 +1611,7 @@
                   version = result;
                   String versionString = fStringPool.toString(version);
                   if (!"1.0".equals(versionString)) {
  -                    if (!fEventHandler.validVersionNum(versionString)) {
  +                    if (!validVersionNum(versionString)) {
                           abortMarkup(XMLMessages.MSG_VERSIONINFO_INVALID,
                                       XMLMessages.P26_INVALID_VALUE,
                                       versionString);
  @@ -1645,7 +1643,7 @@
                   //
                   encoding = result;
                   String encodingString = fStringPool.toString(encoding);
  -                if (!fEventHandler.validEncName(encodingString)) {
  +                if (!validEncName(encodingString)) {
                       abortMarkup(XMLMessages.MSG_ENCODINGDECL_INVALID,
                                   XMLMessages.P81_INVALID_VALUE,
                                   encodingString);
  @@ -1664,21 +1662,25 @@
               return;
           }
           decreaseMarkupDepth();
  -        fEventHandler.callTextDecl(version, encoding);
  +        fDTDGrammar.callTextDecl(version, encoding);
           restoreScannerState(prevState);
       }
  -    //
  -    // [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'
  -    //
  -    private void scanElementDecl() throws Exception
  -    {
  +
  +    /**
  +     * Scans an element declaration.
  +     * <pre>
  +     * [45] elementdecl ::= '&lt;!ELEMENT' S Name S contentspec S? '&gt;'
  +     * </pre>
  +     */
  +    private void scanElementDecl() throws Exception {
  +        
           if (!checkForPEReference(true)) {
               abortMarkup(XMLMessages.MSG_SPACE_REQUIRED_BEFORE_ELEMENT_TYPE_IN_ELEMENTDECL,
                           XMLMessages.P45_SPACE_REQUIRED);
               return;
           }
  -        int elementType = fEventHandler.checkForElementTypeWithPEReference(fEntityReader, ' ');
  -        if (elementType == -1) {
  +        checkForElementTypeWithPEReference(fEntityReader, ' ', fElementQName);
  +        if (fElementQName.rawname == -1) {
               abortMarkup(XMLMessages.MSG_ELEMENT_TYPE_REQUIRED_IN_ELEMENTDECL,
                           XMLMessages.P45_ELEMENT_TYPE_REQUIRED);
               return;
  @@ -1686,19 +1688,19 @@
           if (!checkForPEReference(true)) {
               abortMarkup(XMLMessages.MSG_SPACE_REQUIRED_BEFORE_CONTENTSPEC_IN_ELEMENTDECL,
                           XMLMessages.P45_SPACE_REQUIRED,
  -                        elementType);
  +                        fElementQName.rawname);
               return;
           }
           int contentSpecType = -1;
           int contentSpec = -1;
           if (fEntityReader.skippedString(empty_string)) {
  -            contentSpecType = fEMPTY;
  +            contentSpecType = XMLElementDecl.TYPE_EMPTY;
           } else if (fEntityReader.skippedString(any_string)) {
  -            contentSpecType = fANY;
  +            contentSpecType = XMLElementDecl.TYPE_ANY;
           } else if (!fEntityReader.lookingAtChar('(', true)) {
               abortMarkup(XMLMessages.MSG_CONTENTSPEC_REQUIRED_IN_ELEMENTDECL,
                           XMLMessages.P45_CONTENTSPEC_REQUIRED,
  -                        elementType);
  +                        fElementQName.rawname);
               return;
           } else {
               int contentSpecReader = fReaderId;
  @@ -1710,11 +1712,13 @@
               checkForPEReference(false);
               boolean skippedPCDATA = fEntityReader.skippedString(pcdata_string);
               if (skippedPCDATA) {
  -                contentSpecType = fMIXED;
  -                contentSpec = scanMixed(elementType);
  +                contentSpecType = XMLElementDecl.TYPE_MIXED;
  +                // REVISIT: Validation. Should we pass in QName?
  +                contentSpec = scanMixed(fElementQName);
               } else {
  -                contentSpecType = fCHILDREN;
  -                contentSpec = scanChildren(elementType);
  +                contentSpecType = XMLElementDecl.TYPE_CHILDREN;
  +                // REVISIT: Validation. Should we pass in QName?
  +                contentSpec = scanChildren(fElementQName);
               }
               boolean success = contentSpec != -1;
               restoreScannerState(prevState);
  @@ -1733,74 +1737,146 @@
           if (!fEntityReader.lookingAtChar('>', true)) {
               abortMarkup(XMLMessages.MSG_ELEMENTDECL_UNTERMINATED,
                           XMLMessages.P45_UNTERMINATED,
  -                        elementType);
  +                        fElementQName.rawname);
               return;
           }
           decreaseMarkupDepth();
  -        int elementIndex = fEventHandler.addElementDecl(elementType, contentSpecType, contentSpec);
  -    }
  -    //
  -    // [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' | '(' S? '#PCDATA' S? ')'
  -    //
  -    // Called after scanning past '(' S? '#PCDATA'
  -    //
  -    private int scanMixed(int elementType) throws Exception
  -    {
  +        int elementIndex = fDTDGrammar.getElementDeclIndex(fElementQName.localpart, -1);
  +        boolean elementDeclIsExternal = getReadingExternalEntity();
  +        if (elementIndex == -1) {
  +            elementIndex = fDTDGrammar.addElementDecl(fElementQName, contentSpecType, contentSpec, elementDeclIsExternal);
  +            //System.out.println("XMLDTDScanner#scanElementDecl->DTDGrammar#addElementDecl: "+elementIndex+" ("+fElementQName.localpart+","+fStringPool.toString(fElementQName.localpart)+')');
  +        }
  +        else {
  +            //now check if we already add this element Decl by foward reference
  +            fDTDGrammar.getElementDecl(elementIndex, fTempElementDecl);
  +            if (fTempElementDecl.type == -1) {
  +                fTempElementDecl.type = contentSpecType;
  +                fTempElementDecl.contentSpecIndex = contentSpec;
  +                fDTDGrammar.setElementDeclDTD(elementIndex, fTempElementDecl);
  +                fDTDGrammar.setElementDeclIsExternal(elementIndex, elementDeclIsExternal);
  +            }
  +            else {
  +                //REVISIT, valiate VC duplicate element type. 
  +                if ( fValidationEnabled )
  +                    //&& 
  +                    // (elemenetDeclIsExternal==fDTDGrammar.getElementDeclIsExternal(elementIndex)
  +                {
  +
  +                    reportRecoverableXMLError(
  +                        XMLMessages.MSG_ELEMENT_ALREADY_DECLARED,
  +                        XMLMessages.VC_UNIQUE_ELEMENT_TYPE_DECLARATION,
  +                        fStringPool.toString(fElementQName.rawname)
  +                        );
  +                }
  +            }
  +        }
  +
  +    } // scanElementDecl()
  +
  +    
  +    /**
  +     * Scans mixed content model. Called after scanning past '(' S? '#PCDATA'
  +     * <pre>
  +     * [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' | '(' S? '#PCDATA' S? ')'
  +     * </pre>
  +     */
  +    private int scanMixed(QName element) throws Exception {
  +
           int valueIndex = -1;  // -1 is special value for #PCDATA
           int prevNodeIndex = -1;
           boolean starRequired = false;
  +        int[] valueSeen = new int[32];
  +        int valueCount = 0;
  +        boolean dupAttrType = false;
  +        int nodeIndex = -1;
  +
           while (true) {
  -            int nodeIndex = fEventHandler.addUniqueLeafNode(valueIndex);
  +            if (fValidationEnabled) {
  +                for (int i=0; i<valueCount;i++) {
  +                    if ( valueSeen[i] == valueIndex) {
  +                        dupAttrType = true;
  +                        break;
  +                    }
  +                }
  +            }
  +            if (dupAttrType && fValidationEnabled) {
  +                reportRecoverableXMLError(XMLMessages.MSG_DUPLICATE_TYPE_IN_MIXED_CONTENT,
  +                                          XMLMessages.VC_NO_DUPLICATE_TYPES,
  +                                          valueIndex);
  +                dupAttrType = false;
  +
  +            }
  +            else {
  +                try {
  +                    valueSeen[valueCount] = valueIndex;
  +                }
  +                catch (ArrayIndexOutOfBoundsException ae) {
  +                    int[] newArray = new int[valueSeen.length*2];
  +                    System.arraycopy(valueSeen,0,newArray,0,valueSeen.length);
  +                    valueSeen[valueCount] = valueIndex;
  +                }
  +                valueCount++;
  +
  +                nodeIndex = fDTDGrammar.addUniqueLeafNode(valueIndex);
  +            }
  +
               checkForPEReference(false);
               if (!fEntityReader.lookingAtChar('|', true)) {
                   if (!fEntityReader.lookingAtChar(')', true)) {
                       reportFatalXMLError(XMLMessages.MSG_CLOSE_PAREN_REQUIRED_IN_MIXED,
                                           XMLMessages.P51_CLOSE_PAREN_REQUIRED,
  -                                        elementType);
  +                                        element.rawname);
                       return -1;
                   }
                   decreaseParenDepth();
                   if (nodeIndex == -1) {
                       nodeIndex = prevNodeIndex;
                   } else if (prevNodeIndex != -1) {
  -                    nodeIndex = fEventHandler.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_CHOICE, prevNodeIndex, nodeIndex);
  +                    nodeIndex = fDTDGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_CHOICE, prevNodeIndex, nodeIndex);
                   }
                   if (fEntityReader.lookingAtChar('*', true)) {
  -                    nodeIndex = fEventHandler.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE, nodeIndex);
  +                    nodeIndex = fDTDGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE, nodeIndex);
                   } else if (starRequired) {
                       reportFatalXMLError(XMLMessages.MSG_MIXED_CONTENT_UNTERMINATED,
                                           XMLMessages.P51_UNTERMINATED,
  -                                        fStringPool.toString(elementType),
  -                                        fEventHandler.getContentSpecNodeAsString(nodeIndex));
  +                                        fStringPool.toString(element.rawname),
  +                                        fDTDGrammar.getContentSpecNodeAsString(nodeIndex));
                       return -1;
                   }
                   return nodeIndex;
               }
               if (nodeIndex != -1) {
                   if (prevNodeIndex != -1) {
  -                    nodeIndex = fEventHandler.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_CHOICE, prevNodeIndex, nodeIndex);
  +                    nodeIndex = fDTDGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_CHOICE, prevNodeIndex, nodeIndex);
                   }
                   prevNodeIndex = nodeIndex;
               }
               starRequired = true;
               checkForPEReference(false);
  -            valueIndex = fEventHandler.checkForElementTypeWithPEReference(fEntityReader, ')');
  +            checkForElementTypeWithPEReference(fEntityReader, ')', fElementRefQName);
  +            valueIndex = fElementRefQName.rawname;
               if (valueIndex == -1) {
                   reportFatalXMLError(XMLMessages.MSG_ELEMENT_TYPE_REQUIRED_IN_MIXED_CONTENT,
                                       XMLMessages.P51_ELEMENT_TYPE_REQUIRED,
  -                                    elementType);
  +                                    element.rawname);
                   return -1;
               }
           }
  -    }
  -    //
  -    // [47] children ::= (choice | seq) ('?' | '*' | '+')?
  -    // [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
  -    // [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
  -    // [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
  -    //
  -    private int scanChildren(int elementType) throws Exception
  -    {
  +
  +    } // scanMixed(QName):int
  +    
  +    /**
  +     * Scans a children content model.
  +     * <pre>
  +     * [47] children ::= (choice | seq) ('?' | '*' | '+')?
  +     * [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
  +     * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
  +     * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
  +     * </pre>
  +     */
  +    private int scanChildren(QName element) throws Exception {
  +        
           int depth = 1;
           initializeContentModelStack(depth);
           while (true) {
  @@ -1811,33 +1887,34 @@
                   initializeContentModelStack(depth);
                   continue;
               }
  -            int valueIndex = fEventHandler.checkForElementTypeWithPEReference(fEntityReader, ')');
  +            checkForElementTypeWithPEReference(fEntityReader, ')', fElementRefQName);
  +            int valueIndex = fElementRefQName.rawname;
               if (valueIndex == -1) {
                   reportFatalXMLError(XMLMessages.MSG_OPEN_PAREN_OR_ELEMENT_TYPE_REQUIRED_IN_CHILDREN,
                                       XMLMessages.P47_OPEN_PAREN_OR_ELEMENT_TYPE_REQUIRED,
  -                                    elementType);
  +                                    element.rawname);
                   return -1;
               }
  -            fNodeIndexStack[depth] = fEventHandler.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_LEAF, valueIndex);
  +            fNodeIndexStack[depth] = fDTDGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_LEAF, valueIndex);
               if (fEntityReader.lookingAtChar('?', true)) {
  -                fNodeIndexStack[depth] = fEventHandler.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE, fNodeIndexStack[depth]);
  +                fNodeIndexStack[depth] = fDTDGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE, fNodeIndexStack[depth]);
               } else if (fEntityReader.lookingAtChar('*', true)) {
  -                fNodeIndexStack[depth] = fEventHandler.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE, fNodeIndexStack[depth]);
  +                fNodeIndexStack[depth] = fDTDGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE, fNodeIndexStack[depth]);
               } else if (fEntityReader.lookingAtChar('+', true)) {
  -                fNodeIndexStack[depth] = fEventHandler.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE, fNodeIndexStack[depth]);
  +                fNodeIndexStack[depth] = fDTDGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE, fNodeIndexStack[depth]);
               }
               while (true) {
                   checkForPEReference(false);
                   if (fOpStack[depth] != XMLContentSpec.CONTENTSPECNODE_SEQ && fEntityReader.lookingAtChar('|', true)) {
                       if (fPrevNodeIndexStack[depth] != -1) {
  -                        fNodeIndexStack[depth] = fEventHandler.addContentSpecNode(fOpStack[depth], fPrevNodeIndexStack[depth], fNodeIndexStack[depth]);
  +                        fNodeIndexStack[depth] = fDTDGrammar.addContentSpecNode(fOpStack[depth], fPrevNodeIndexStack[depth], fNodeIndexStack[depth]);
                       }
                       fPrevNodeIndexStack[depth] = fNodeIndexStack[depth];
                       fOpStack[depth] = XMLContentSpec.CONTENTSPECNODE_CHOICE;
                       break;
                   } else if (fOpStack[depth] != XMLContentSpec.CONTENTSPECNODE_CHOICE && fEntityReader.lookingAtChar(',', true)) {
                       if (fPrevNodeIndexStack[depth] != -1) {
  -                        fNodeIndexStack[depth] = fEventHandler.addContentSpecNode(fOpStack[depth], fPrevNodeIndexStack[depth], fNodeIndexStack[depth]);
  +                        fNodeIndexStack[depth] = fDTDGrammar.addContentSpecNode(fOpStack[depth], fPrevNodeIndexStack[depth], fNodeIndexStack[depth]);
                       }
                       fPrevNodeIndexStack[depth] = fNodeIndexStack[depth];
                       fOpStack[depth] = XMLContentSpec.CONTENTSPECNODE_SEQ;
  @@ -1846,20 +1923,20 @@
                       if (!fEntityReader.lookingAtChar(')', true)) {
                           reportFatalXMLError(XMLMessages.MSG_CLOSE_PAREN_REQUIRED_IN_CHILDREN,
                                               XMLMessages.P47_CLOSE_PAREN_REQUIRED,
  -                                            elementType);
  +                                            element.rawname);
                       }
                       decreaseParenDepth();
                       if (fPrevNodeIndexStack[depth] != -1) {
  -                        fNodeIndexStack[depth] = fEventHandler.addContentSpecNode(fOpStack[depth], fPrevNodeIndexStack[depth], fNodeIndexStack[depth]);
  +                        fNodeIndexStack[depth] = fDTDGrammar.addContentSpecNode(fOpStack[depth], fPrevNodeIndexStack[depth], fNodeIndexStack[depth]);
                       }
                       int nodeIndex = fNodeIndexStack[depth--];
                       fNodeIndexStack[depth] = nodeIndex;
                       if (fEntityReader.lookingAtChar('?', true)) {
  -                        fNodeIndexStack[depth] = fEventHandler.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE, fNodeIndexStack[depth]);
  +                        fNodeIndexStack[depth] = fDTDGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE, fNodeIndexStack[depth]);
                       } else if (fEntityReader.lookingAtChar('*', true)) {
  -                        fNodeIndexStack[depth] = fEventHandler.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE, fNodeIndexStack[depth]);
  +                        fNodeIndexStack[depth] = fDTDGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE, fNodeIndexStack[depth]);
                       } else if (fEntityReader.lookingAtChar('+', true)) {
  -                        fNodeIndexStack[depth] = fEventHandler.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE, fNodeIndexStack[depth]);
  +                        fNodeIndexStack[depth] = fDTDGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE, fNodeIndexStack[depth]);
                       }
                       if (depth == 0) {
                           return fNodeIndexStack[0];
  @@ -1868,7 +1945,9 @@
               }
               checkForPEReference(false);
           }
  -    }
  +
  +    } // scanChildren(QName):int
  +
       //
       // [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
       // [53] AttDef ::= S Name S AttType S DefaultDecl
  @@ -1881,13 +1960,18 @@
                           XMLMessages.P52_SPACE_REQUIRED);
               return;
           }
  -        int elementTypeIndex = fEventHandler.checkForElementTypeWithPEReference(fEntityReader, ' ');
  +        checkForElementTypeWithPEReference(fEntityReader, ' ', fElementQName);
  +        int elementTypeIndex = fElementQName.rawname;
           if (elementTypeIndex == -1) {
               abortMarkup(XMLMessages.MSG_ELEMENT_TYPE_REQUIRED_IN_ATTLISTDECL,
                           XMLMessages.P52_ELEMENT_TYPE_REQUIRED);
               return;
           }
  -        int elementIndex = fEventHandler.addElementDecl(elementTypeIndex);
  +        int elementIndex = fDTDGrammar.getElementDeclIndex(fElementQName.localpart, -1);
  +        if (elementIndex == -1) {
  +            elementIndex = fDTDGrammar.addElementDecl(fElementQName);
  +            //System.out.println("XMLDTDScanner#scanAttListDecl->DTDGrammar#addElementDecl: "+elementIndex+" ("+fElementQName.localpart+","+fStringPool.toString(fElementQName.localpart)+')');
  +        }
           boolean sawSpace = checkForPEReference(true);
           if (fEntityReader.lookingAtChar('>', true)) {
               decreaseMarkupDepth();
  @@ -1910,11 +1994,12 @@
               return;
           }
           while (true) {
  -            int attDefName = fEventHandler.checkForAttributeNameWithPEReference(fEntityReader, ' ');
  +            checkForAttributeNameWithPEReference(fEntityReader, ' ', fAttributeQName);
  +            int attDefName = fAttributeQName.rawname;
               if (attDefName == -1) {
                   abortMarkup(XMLMessages.MSG_ATTRIBUTE_NAME_REQUIRED_IN_ATTDEF,
                               XMLMessages.P53_NAME_REQUIRED,
  -                            elementTypeIndex);
  +                            fElementQName.rawname);
                   return;
               }
               if (!checkForPEReference(true)) {
  @@ -1923,22 +2008,25 @@
                   return;
               }
               int attDefType = -1;
  +            boolean attDefList = false;
               int attDefEnumeration = -1;
               if (fEntityReader.skippedString(cdata_string)) {
  -                attDefType = fCDATA;
  +                attDefType = XMLAttributeDecl.TYPE_CDATA;
               } else if (fEntityReader.skippedString(id_string)) {
                   if (!fEntityReader.skippedString(ref_string)) {
  -                    attDefType = fID;
  +                    attDefType = XMLAttributeDecl.TYPE_ID;
                   } else if (!fEntityReader.lookingAtChar('S', true)) {
  -                    attDefType = fIDREF;
  +                    attDefType = XMLAttributeDecl.TYPE_IDREF;
                   } else {
  -                    attDefType = fIDREFS;
  +                    attDefType = XMLAttributeDecl.TYPE_IDREF;
  +                    attDefList = true;
                   }
               } else if (fEntityReader.skippedString(entit_string)) {
                   if (fEntityReader.lookingAtChar('Y', true)) {
  -                    attDefType = fENTITY;
  +                    attDefType = XMLAttributeDecl.TYPE_ENTITY;
                   } else if (fEntityReader.skippedString(ies_string)) {
  -                    attDefType = fENTITIES;
  +                    attDefType = XMLAttributeDecl.TYPE_ENTITY;
  +                    attDefList = true;
                   } else {
                       abortMarkup(XMLMessages.MSG_ATTTYPE_REQUIRED_IN_ATTDEF,
                                   XMLMessages.P53_ATTTYPE_REQUIRED,
  @@ -1947,9 +2035,10 @@
                   }
               } else if (fEntityReader.skippedString(nmtoken_string)) {
                   if (fEntityReader.lookingAtChar('S', true)) {
  -                    attDefType = fNMTOKENS;
  +                    attDefType = XMLAttributeDecl.TYPE_NMTOKEN;
  +                    attDefList = true;
                   } else {
  -                    attDefType = fNMTOKEN;
  +                    attDefType = XMLAttributeDecl.TYPE_NMTOKEN;
                   }
               } else if (fEntityReader.skippedString(notation_string)) {
                   if (!checkForPEReference(true)) {
  @@ -1965,7 +2054,7 @@
                       return;
                   }
                   increaseParenDepth();
  -                attDefType = fNOTATION;
  +                attDefType = XMLAttributeDecl.TYPE_NOTATION;
                   attDefEnumeration = scanEnumeration(elementTypeIndex, attDefName, true);
                   if (attDefEnumeration == -1) {
                       skipPastEndOfCurrentMarkup();
  @@ -1973,7 +2062,7 @@
                   }
               } else if (fEntityReader.lookingAtChar('(', true)) {
                   increaseParenDepth();
  -                attDefType = fENUMERATION;
  +                attDefType = XMLAttributeDecl.TYPE_ENUMERATION;
                   attDefEnumeration = scanEnumeration(elementTypeIndex, attDefName, false);
                   if (attDefEnumeration == -1) {
                       skipPastEndOfCurrentMarkup();
  @@ -1994,9 +2083,9 @@
               int attDefDefaultType = -1;
               int attDefDefaultValue = -1;
               if (fEntityReader.skippedString(required_string)) {
  -                attDefDefaultType = fREQUIRED;
  +                attDefDefaultType = XMLAttributeDecl.DEFAULT_TYPE_REQUIRED;
               } else if (fEntityReader.skippedString(implied_string)) {
  -                attDefDefaultType = fIMPLIED;
  +                attDefDefaultType = XMLAttributeDecl.DEFAULT_TYPE_IMPLIED;
               } else {
                   if (fEntityReader.skippedString(fixed_string)) {
                       if (!fEntityReader.lookingAtSpace(true)) {
  @@ -2006,10 +2095,22 @@
                           return;
                       }
                       fEntityReader.skipPastSpaces();
  -                    attDefDefaultType = fFIXED;
  +                    attDefDefaultType = XMLAttributeDecl.DEFAULT_TYPE_FIXED;
                   } else
  -                    attDefDefaultType = fDEFAULT;
  -                attDefDefaultValue = fEventHandler.scanDefaultAttValue(elementTypeIndex, attDefName, attDefType, attDefEnumeration);
  +                    attDefDefaultType = XMLAttributeDecl.DEFAULT_TYPE_DEFAULT;
  +                fElementQName.setValues(-1, elementTypeIndex, elementTypeIndex);
  +                fAttributeQName.setValues(-1, attDefName, attDefName);
  +                attDefDefaultValue = scanDefaultAttValue(fElementQName, fAttributeQName, 
  +                                                         attDefType, 
  +                                                         attDefEnumeration);
  +
  +                //normalize and check VC: Attribute Default Legal
  +                if (attDefDefaultValue != -1 && attDefType != XMLAttributeDecl.TYPE_CDATA ) {
  +                    attDefDefaultValue = normalizeDefaultAttValue( fAttributeQName, attDefDefaultValue, 
  +                                                                attDefType, attDefEnumeration,
  +                                                                attDefList);
  +                }
  +
                   if (attDefDefaultValue == -1) {
                       skipPastEndOfCurrentMarkup();
                       return;
  @@ -2017,7 +2118,7 @@
               }
               if (attDefName == fXMLSpace) {
                   boolean ok = false;
  -                if (attDefType == fENUMERATION) {
  +                if (attDefType == XMLAttributeDecl.TYPE_ENUMERATION) {
                       int index = attDefEnumeration;
                       if (index != -1) {
                           ok = fStringPool.stringListLength(index) == 2 &&
  @@ -2033,7 +2134,13 @@
               }
               sawSpace = checkForPEReference(true);
               if (fEntityReader.lookingAtChar('>', true)) {
  -                int attDefIndex = fEventHandler.addAttDef(elementIndex, attDefName, attDefType, attDefEnumeration, attDefDefaultType, attDefDefaultValue);
  +                int attDefIndex = addAttDef(fElementQName, fAttributeQName, 
  +                                                        attDefType, attDefList, attDefEnumeration, 
  +                                                        attDefDefaultType, attDefDefaultValue, 
  +                                                        getReadingExternalEntity());
  +                //System.out.println("XMLDTDScanner#scanAttlistDecl->DTDGrammar#addAttDef: "+attDefIndex+
  +                //                   " ("+fElementQName.localpart+","+fStringPool.toString(fElementQName.rawname)+')'+
  +                //                   " ("+fAttributeQName.localpart+","+fStringPool.toString(fAttributeQName.rawname)+')');
                   decreaseMarkupDepth();
                   return;
               }
  @@ -2050,25 +2157,116 @@
                   }
               }
               if (fEntityReader.lookingAtChar('>', true)) {
  -                int attDefIndex = fEventHandler.addAttDef(elementIndex, attDefName, attDefType, attDefEnumeration, attDefDefaultType, attDefDefaultValue);
  +                int attDefIndex = addAttDef(fElementQName, fAttributeQName, 
  +                                                        attDefType, attDefList, attDefEnumeration, 
  +                                                        attDefDefaultType, attDefDefaultValue,
  +                                                        getReadingExternalEntity() );
  +                //System.out.println("XMLDTDScanner#scanAttlistDecl->DTDGrammar#addAttDef: "+attDefIndex+
  +                //                   " ("+fElementQName.localpart+","+fStringPool.toString(fElementQName.rawname)+')'+
  +                //                   " ("+fAttributeQName.localpart+","+fStringPool.toString(fAttributeQName.rawname)+')');
                   decreaseMarkupDepth();
                   return;
               }
  -            int attDefIndex = fEventHandler.addAttDef(elementIndex, attDefName, attDefType, attDefEnumeration, attDefDefaultType, attDefDefaultValue);
  +            int attDefIndex = addAttDef(fElementQName, fAttributeQName, 
  +                                                    attDefType, attDefList, attDefEnumeration, 
  +                                                    attDefDefaultType, attDefDefaultValue,
  +                                                    getReadingExternalEntity());
  +            //System.out.println("XMLDTDScanner#scanAttlistDecl->DTDGrammar#addAttDef: "+attDefIndex+
  +            //                   " ("+fElementQName.localpart+","+fStringPool.toString(fElementQName.rawname)+')'+
  +            //                   " ("+fAttributeQName.localpart+","+fStringPool.toString(fAttributeQName.rawname)+')');
           }
       }
  +
  +    private int addAttDef(QName element, QName attribute, 
  +                          int attDefType, boolean attDefList, int attDefEnumeration, 
  +                          int attDefDefaultType, int attDefDefaultValue,
  +                          boolean isExternal ) throws Exception {
  +
  +        int elementIndex = fDTDGrammar.getElementDeclIndex(element.localpart, -1);
  +        if (elementIndex == -1) {
  +            // REPORT Internal error here
  +        }
  +        else {
  +            int attlistIndex = fDTDGrammar.getFirstAttributeDeclIndex(elementIndex);
  +            int dupID = -1;
  +            int dupNotation = -1;
  +            while (attlistIndex != -1) {
  +                fDTDGrammar.getAttributeDecl(attlistIndex, fTempAttributeDecl);
  +
  +                // REVISIT: Validation. Attributes are also tuples.
  +                if (fStringPool.equalNames(fTempAttributeDecl.name.rawname, attribute.rawname)) {
  +                    /******
  +                    if (fWarningOnDuplicateAttDef) {
  +                        Object[] args = { fStringPool.toString(fElementType[elemChunk][elemIndex]),
  +                                          fStringPool.toString(attributeDecl.rawname) };
  +                        fErrorReporter.reportError(fErrorReporter.getLocator(),
  +                                                   XMLMessages.XML_DOMAIN,
  +                                                   XMLMessages.MSG_DUPLICATE_ATTDEF,
  +                                                   XMLMessages.P53_DUPLICATE,
  +                                                   args,
  +                                                   XMLErrorReporter.ERRORTYPE_WARNING);
  +                    }
  +                    ******/
  +                    return -1;
  +                }
  +
  +                if (fValidationEnabled) {
  +                    if (attDefType == XMLAttributeDecl.TYPE_ID && 
  +                        fTempAttributeDecl.type == XMLAttributeDecl.TYPE_ID ) {
  +                        dupID = fTempAttributeDecl.name.rawname;
  +                    }
  +                    if (attDefType == XMLAttributeDecl.TYPE_NOTATION 
  +                        && fTempAttributeDecl.type == XMLAttributeDecl.TYPE_NOTATION) {
  +                        dupNotation = fTempAttributeDecl.name.rawname;
  +                    }
  +                }
  +                attlistIndex = fDTDGrammar.getNextAttributeDeclIndex(attlistIndex);
  +            }
  +            if (fValidationEnabled) {
  +                if (dupID != -1) {
  +                    Object[] args = { fStringPool.toString(element.rawname),
  +                                      fStringPool.toString(dupID),
  +                                      fStringPool.toString(attribute.rawname) };
  +                    fErrorReporter.reportError(fErrorReporter.getLocator(),
  +                                               XMLMessages.XML_DOMAIN,
  +                                               XMLMessages.MSG_MORE_THAN_ONE_ID_ATTRIBUTE,
  +                                               XMLMessages.VC_ONE_ID_PER_ELEMENT_TYPE,
  +                                               args,
  +                                               XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
  +                    return -1;
  +                }
  +                if (dupNotation != -1) {
  +                    Object[] args = { fStringPool.toString(element.rawname),
  +                                      fStringPool.toString(dupNotation),
  +                                      fStringPool.toString(attribute.rawname) };
  +                    fErrorReporter.reportError(fErrorReporter.getLocator(),
  +                                               XMLMessages.XML_DOMAIN,
  +                                               XMLMessages.MSG_MORE_THAN_ONE_NOTATION_ATTRIBUTE,
  +                                               XMLMessages.VC_ONE_NOTATION_PER_ELEMENT_TYPE,
  +                                               args,
  +                                               XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
  +                    return -1;
  +                }
  +            }
  +        }
  +        return fDTDGrammar.addAttDef(element, attribute, 
  +                                     attDefType, attDefList, attDefEnumeration, 
  +                                     attDefDefaultType, attDefDefaultValue,
  +                                     isExternal);
  +
  +    }
       //
       // [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
       // [59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'
       //
       private int scanEnumeration(int elementType, int attrName, boolean isNotationType) throws Exception
       {
  -        int enumIndex = fEventHandler.startEnumeration();
  +        int enumIndex = fDTDGrammar.startEnumeration();
           while (true) {
               checkForPEReference(false);
               int nameIndex = isNotationType ?
  -                            fEventHandler.checkForNameWithPEReference(fEntityReader, ')') :
  -                            fEventHandler.checkForNmtokenWithPEReference(fEntityReader, ')');
  +                            checkForNameWithPEReference(fEntityReader, ')') :
  +                            checkForNmtokenWithPEReference(fEntityReader, ')');
               if (nameIndex == -1) {
                   if (isNotationType) {
                       reportFatalXMLError(XMLMessages.MSG_NAME_REQUIRED_IN_NOTATIONTYPE,
  @@ -2081,13 +2279,25 @@
                                           elementType,
                                           attrName);
                   }
  -                fEventHandler.endEnumeration(enumIndex);
  +                fDTDGrammar.endEnumeration(enumIndex);
                   return -1;
  +            }
  +            fDTDGrammar.addNameToEnumeration(enumIndex, elementType, attrName, nameIndex, isNotationType);
  +            /*****/
  +            if (isNotationType && !((DefaultEntityHandler)fEntityHandler).isNotationDeclared(nameIndex)) {
  +                Object[] args = { fStringPool.toString(elementType),
  +                    fStringPool.toString(attrName),
  +                    fStringPool.toString(nameIndex) };
  +                    ((DefaultEntityHandler)fEntityHandler).addRequiredNotation(nameIndex,
  +                                                       fErrorReporter.getLocator(),
  +                                                       XMLMessages.MSG_NOTATION_NOT_DECLARED_FOR_NOTATIONTYPE_ATTRIBUTE,
  +                                                       XMLMessages.VC_NOTATION_DECLARED,
  +                                                       args);
               }
  -            fEventHandler.addNameToEnumeration(enumIndex, elementType, attrName, nameIndex, isNotationType);
  +            /*****/
               checkForPEReference(false);
               if (!fEntityReader.lookingAtChar('|', true)) {
  -                fEventHandler.endEnumeration(enumIndex);
  +                fDTDGrammar.endEnumeration(enumIndex);
                   if (!fEntityReader.lookingAtChar(')', true)) {
                       if (isNotationType) {
                           reportFatalXMLError(XMLMessages.MSG_NOTATIONTYPE_UNTERMINATED,
  @@ -2119,21 +2329,21 @@
        * @return handle in the string pool for the default attribute value
        * @exception java.lang.Exception
        */
  -    public int scanDefaultAttValue(int elementType, int attrName) throws Exception
  +    public int scanDefaultAttValue(QName element, QName attribute) throws Exception
       {
           boolean single;
           if (!(single = fEntityReader.lookingAtChar('\'', true)) && !fEntityReader.lookingAtChar('\"', true)) {
               reportFatalXMLError(XMLMessages.MSG_QUOTE_REQUIRED_IN_ATTVALUE,
                                   XMLMessages.P10_QUOTE_REQUIRED,
  -                                elementType,
  -                                attrName);
  +                                element.rawname,
  +                                attribute.rawname);
               return -1;
           }
           int previousState = setScannerState(SCANNER_STATE_DEFAULT_ATTRIBUTE_VALUE);
           char qchar = single ? '\'' : '\"';
           fDefaultAttValueReader = fReaderId;
  -        fDefaultAttValueElementType = elementType;
  -        fDefaultAttValueAttrName = attrName;
  +        fDefaultAttValueElementType = element.rawname;
  +        fDefaultAttValueAttrName = attribute.rawname;
           boolean setMark = true;
           int dataOffset = fLiteralData.length();
           while (true) {
  @@ -2204,8 +2414,8 @@
                   setMark = true;
                   reportFatalXMLError(XMLMessages.MSG_LESSTHAN_IN_ATTVALUE,
                                       XMLMessages.WFC_NO_LESSTHAN_IN_ATTVALUE,
  -                                    elementType,
  -                                    attrName);
  +                                    element.rawname,
  +                                    attribute.rawname);
                   continue;
               }
               //
  @@ -2235,8 +2445,8 @@
                   if (invChar >= 0) {
                       reportFatalXMLError(XMLMessages.MSG_INVALID_CHAR_IN_ATTVALUE,
                                           XMLMessages.P10_INVALID_CHARACTER,
  -                                        fStringPool.toString(elementType),
  -                                        fStringPool.toString(attrName),
  +                                        fStringPool.toString(element.rawname),
  +                                        fStringPool.toString(attribute.rawname),
                                           Integer.toHexString(invChar));
                   }
                   continue;
  @@ -2263,7 +2473,7 @@
                           XMLMessages.P82_SPACE_REQUIRED);
               return;
           }
  -        int notationName = fEventHandler.checkForNameWithPEReference(fEntityReader, ' ');
  +        int notationName = checkForNameWithPEReference(fEntityReader, ' ');
           if (notationName == -1) {
               abortMarkup(XMLMessages.MSG_NOTATION_NAME_REQUIRED_IN_NOTATIONDECL,
                           XMLMessages.P82_NAME_REQUIRED);
  @@ -2287,7 +2497,18 @@
               return;
           }
           decreaseMarkupDepth();
  -        int notationIndex = fEventHandler.addNotationDecl(notationName, fPubidLiteral, fSystemLiteral);
  +        /****
  +        System.out.println(fStringPool.toString(notationName)+","
  +                           +fStringPool.toString(fPubidLiteral) + ","
  +                           +fStringPool.toString(fSystemLiteral) + ","
  +                           +getReadingExternalEntity());
  +        /****/
  +
  +        int notationIndex = ((DefaultEntityHandler) fEntityHandler).addNotationDecl( notationName, 
  +                                                                                     fPubidLiteral, 
  +                                                                                     fSystemLiteral,
  +                                                                                     getReadingExternalEntity());
  +        fDTDGrammar.addNotationDecl(notationName, fPubidLiteral, fSystemLiteral);
       }
       //
       // [70] EntityDecl ::= GEDecl | PEDecl
  @@ -2367,13 +2588,13 @@
                   }
               }
           }
  -        int entityName = fEventHandler.checkForNameWithPEReference(fEntityReader, ' ');
  +        int entityName = checkForNameWithPEReference(fEntityReader, ' ');
           if (entityName == -1) {
               abortMarkup(XMLMessages.MSG_ENTITY_NAME_REQUIRED_IN_ENTITYDECL,
                           XMLMessages.P70_REQUIRED_NAME);
               return;
           }
  -        if (!fEventHandler.startEntityDecl(isPEDecl, entityName)) {
  +        if (!fDTDGrammar.startEntityDecl(isPEDecl, entityName)) {
               skipPastEndOfCurrentMarkup();
               return;
           }
  @@ -2381,7 +2602,7 @@
               abortMarkup(XMLMessages.MSG_SPACE_REQUIRED_AFTER_ENTITY_NAME_IN_ENTITYDECL,
                           XMLMessages.P70_REQUIRED_SPACE,
                           entityName);
  -            fEventHandler.endEntityDecl();
  +            fDTDGrammar.endEntityDecl();
               return;
           }
           if (isPEDecl) {
  @@ -2390,7 +2611,7 @@
                   int value = scanEntityValue(single);
                   if (value == -1) {
                       skipPastEndOfCurrentMarkup();
  -                    fEventHandler.endEntityDecl();
  +                    fDTDGrammar.endEntityDecl();
                       return;
                   }
                   checkForPEReference(false);
  @@ -2398,16 +2619,23 @@
                       abortMarkup(XMLMessages.MSG_ENTITYDECL_UNTERMINATED,
                                   XMLMessages.P72_UNTERMINATED,
                                   entityName);
  -                    fEventHandler.endEntityDecl();
  +                    fDTDGrammar.endEntityDecl();
                       return;
                   }
                   decreaseMarkupDepth();
  -                fEventHandler.endEntityDecl();
  -                int entityIndex = fEventHandler.addInternalPEDecl(entityName, value);
  +                fDTDGrammar.endEntityDecl();
  +
  +                // a hack by Eric
  +                //REVISIT
  +                fDTDGrammar.addInternalPEDecl(entityName, value);
  +                int entityIndex = ((DefaultEntityHandler) fEntityHandler).addInternalPEDecl(entityName, 
  +                                                                                            value, 
  +                                                                                            getReadingExternalEntity());
  +
               } else {
                   if (!scanExternalID(false)) {
                       skipPastEndOfCurrentMarkup();
  -                    fEventHandler.endEntityDecl();
  +                    fDTDGrammar.endEntityDecl();
                       return;
                   }
                   checkForPEReference(false);
  @@ -2415,12 +2643,18 @@
                       abortMarkup(XMLMessages.MSG_ENTITYDECL_UNTERMINATED,
                                   XMLMessages.P72_UNTERMINATED,
                                   entityName);
  -                    fEventHandler.endEntityDecl();
  +                    fDTDGrammar.endEntityDecl();
                       return;
                   }
                   decreaseMarkupDepth();
  -                fEventHandler.endEntityDecl();
  -                int entityIndex = fEventHandler.addExternalPEDecl(entityName, fPubidLiteral, fSystemLiteral);
  +                fDTDGrammar.endEntityDecl();
  +
  +                //a hack by Eric
  +                //REVISIT
  +                fDTDGrammar.addExternalPEDecl(entityName, fPubidLiteral, fSystemLiteral);
  +                int entityIndex = ((DefaultEntityHandler) fEntityHandler).addExternalPEDecl(entityName, 
  +                                                                                            fPubidLiteral, 
  +                                                                                            fSystemLiteral, getReadingExternalEntity());
               }
           } else {
               boolean single;
  @@ -2428,7 +2662,7 @@
                   int value = scanEntityValue(single);
                   if (value == -1) {
                       skipPastEndOfCurrentMarkup();
  -                    fEventHandler.endEntityDecl();
  +                    fDTDGrammar.endEntityDecl();
                       return;
                   }
                   checkForPEReference(false);
  @@ -2436,16 +2670,22 @@
                       abortMarkup(XMLMessages.MSG_ENTITYDECL_UNTERMINATED,
                                   XMLMessages.P71_UNTERMINATED,
                                   entityName);
  -                    fEventHandler.endEntityDecl();
  +                    fDTDGrammar.endEntityDecl();
                       return;
                   }
                   decreaseMarkupDepth();
  -                fEventHandler.endEntityDecl();
  -                int entityIndex = fEventHandler.addInternalEntityDecl(entityName, value);
  +                fDTDGrammar.endEntityDecl();
  +
  +                //a hack by Eric
  +                //REVISIT
  +                fDTDGrammar.addInternalEntityDecl(entityName, value);
  +                int entityIndex = ((DefaultEntityHandler) fEntityHandler).addInternalEntityDecl(entityName, 
  +                                                                                                value, 
  +                                                                                                getReadingExternalEntity());
               } else {
                   if (!scanExternalID(false)) {
                       skipPastEndOfCurrentMarkup();
  -                    fEventHandler.endEntityDecl();
  +                    fDTDGrammar.endEntityDecl();
                       return;
                   }
                   boolean unparsed = false;
  @@ -2459,18 +2699,26 @@
                           abortMarkup(XMLMessages.MSG_ENTITYDECL_UNTERMINATED,
                                       XMLMessages.P72_UNTERMINATED,
                                       entityName);
  -                        fEventHandler.endEntityDecl();
  +                        fDTDGrammar.endEntityDecl();
                           return;
                       }
                       decreaseMarkupDepth();
  -                    fEventHandler.endEntityDecl();
  -                    int entityIndex = fEventHandler.addExternalEntityDecl(entityName, fPubidLiteral, fSystemLiteral);
  +                    fDTDGrammar.endEntityDecl();
  +
  +                    //a hack by Eric
  +                    //REVISIT
  +                    fDTDGrammar.addExternalEntityDecl(entityName, fPubidLiteral, fSystemLiteral);
  +                    int entityIndex = ((DefaultEntityHandler) fEntityHandler).addExternalEntityDecl(entityName, 
  +                                                                                                    fPubidLiteral, 
  +                                                                                                    fSystemLiteral, 
  +                                                                                                    getReadingExternalEntity());
  +
                   } else {
                       if (!fEntityReader.lookingAtSpace(true)) {
                           abortMarkup(XMLMessages.MSG_SPACE_REQUIRED_BEFORE_NOTATION_NAME_IN_UNPARSED_ENTITYDECL,
                                       XMLMessages.P76_SPACE_REQUIRED,
                                       entityName);
  -                        fEventHandler.endEntityDecl();
  +                        fDTDGrammar.endEntityDecl();
                           return;
                       }
                       fEntityReader.skipPastSpaces();
  @@ -2481,7 +2729,7 @@
                           abortMarkup(XMLMessages.MSG_NOTATION_NAME_REQUIRED_FOR_UNPARSED_ENTITYDECL,
                                       XMLMessages.P76_REQUIRED,
                                       entityName);
  -                        fEventHandler.endEntityDecl();
  +                        fDTDGrammar.endEntityDecl();
                           return;
                       }
                       int notationName = fEntityReader.addSymbol(ndataOffset, ndataLength);
  @@ -2490,12 +2738,27 @@
                           abortMarkup(XMLMessages.MSG_ENTITYDECL_UNTERMINATED,
                                       XMLMessages.P72_UNTERMINATED,
                                       entityName);
  -                        fEventHandler.endEntityDecl();
  +                        fDTDGrammar.endEntityDecl();
                           return;
                       }
                       decreaseMarkupDepth();
  -                    fEventHandler.endEntityDecl();
  -                    int entityIndex = fEventHandler.addUnparsedEntityDecl(entityName, fPubidLiteral, fSystemLiteral, notationName);
  +                    fDTDGrammar.endEntityDecl();
  +                    
  +                    //a hack by Eric
  +                    //REVISIT
  +                    fDTDGrammar.addUnparsedEntityDecl(entityName, fPubidLiteral, fSystemLiteral, notationName);
  +                    /****
  +                    System.out.println("----addUnparsedEntity--- "+ fStringPool.toString(entityName)+","
  +                                       +fStringPool.toString(notationName)+","
  +                                       +fStringPool.toString(fPubidLiteral) + ","
  +                                       +fStringPool.toString(fSystemLiteral) + ","
  +                                       +getReadingExternalEntity());
  +                    /****/
  +                    int entityIndex = ((DefaultEntityHandler) fEntityHandler).addUnparsedEntityDecl(entityName, 
  +                                                                                                    fPubidLiteral, 
  +                                                                                                    fSystemLiteral, 
  +                                                                                                    notationName, 
  +                                                                                                    getReadingExternalEntity());
                   }
               }
           }
  @@ -2691,5 +2954,257 @@
           fOpStack[depth] = -1;
           fNodeIndexStack[depth] = -1;
           fPrevNodeIndexStack[depth] = -1;
  +    }
  +
  +    private boolean validVersionNum(String version) {
  +        return XMLCharacterProperties.validVersionNum(version);
  +    }
  +
  +    private boolean validEncName(String encoding) {
  +        return XMLCharacterProperties.validEncName(encoding);
  +    }
  +
  +    private int validPublicId(String publicId) {
  +        return XMLCharacterProperties.validPublicId(publicId);
  +    }
  +
  +    private void scanElementType(XMLEntityHandler.EntityReader entityReader, 
  +                                char fastchar, QName element) throws Exception {
  +
  +        if (!fNamespacesEnabled) {
  +            element.clear();
  +            element.localpart = entityReader.scanName(fastchar);
  +            element.rawname = element.localpart;
  +            return;
  +        }
  +        entityReader.scanQName(fastchar, element);
  +        if (entityReader.lookingAtChar(':', false)) {
  +            fErrorReporter.reportError(fErrorReporter.getLocator(),
  +                                       XMLMessages.XML_DOMAIN,
  +                                       XMLMessages.MSG_TWO_COLONS_IN_QNAME,
  +                                       XMLMessages.P5_INVALID_CHARACTER,
  +                                       null,
  +                                       XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
  +            entityReader.skipPastNmtoken(' ');
  +        }
  +
  +    } // scanElementType(XMLEntityHandler.EntityReader,char,QName)
  +
  +    public void checkForElementTypeWithPEReference(XMLEntityHandler.EntityReader entityReader, 
  +                                                   char fastchar, QName element) throws Exception {
  +
  +        if (!fNamespacesEnabled) {
  +            element.clear();
  +            element.localpart = entityReader.scanName(fastchar);
  +            element.rawname = element.localpart;
  +            return;
  +        }
  +        entityReader.scanQName(fastchar, element);
  +        if (entityReader.lookingAtChar(':', false)) {
  +            fErrorReporter.reportError(fErrorReporter.getLocator(),
  +                                       XMLMessages.XML_DOMAIN,
  +                                       XMLMessages.MSG_TWO_COLONS_IN_QNAME,
  +                                       XMLMessages.P5_INVALID_CHARACTER,
  +                                       null,
  +                                       XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
  +            entityReader.skipPastNmtoken(' ');
  +        }
  +
  +    } // checkForElementTypeWithPEReference(XMLEntityHandler.EntityReader,char,QName)
  +
  +    public void checkForAttributeNameWithPEReference(XMLEntityHandler.EntityReader entityReader, 
  +                                                     char fastchar, QName attribute) throws Exception {
  +
  +        if (!fNamespacesEnabled) {
  +            attribute.clear();
  +            attribute.localpart = entityReader.scanName(fastchar);
  +            attribute.rawname = attribute.localpart;
  +            return;
  +        }
  +
  +        entityReader.scanQName(fastchar, attribute);
  +        if (entityReader.lookingAtChar(':', false)) {
  +            fErrorReporter.reportError(fErrorReporter.getLocator(),
  +                                       XMLMessages.XML_DOMAIN,
  +                                       XMLMessages.MSG_TWO_COLONS_IN_QNAME,
  +                                       XMLMessages.P5_INVALID_CHARACTER,
  +                                       null,
  +                                       XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
  +            entityReader.skipPastNmtoken(' ');
  +        }
  +
  +    } // checkForAttributeNameWithPEReference(XMLEntityHandler.EntityReader,char,QName)
  +
  +    public int checkForNameWithPEReference(XMLEntityHandler.EntityReader entityReader, char fastcheck) throws Exception {
  +        //
  +        // REVISIT - what does this have to do with PE references?
  +        //
  +        int valueIndex = entityReader.scanName(fastcheck);
  +        return valueIndex;
  +    }
  +
  +    public int checkForNmtokenWithPEReference(XMLEntityHandler.EntityReader entityReader, char fastcheck) throws Exception {
  +        //
  +        // REVISIT - what does this have to do with PE references?
  +        //
  +        int nameOffset = entityReader.currentOffset();
  +        entityReader.skipPastNmtoken(fastcheck);
  +        int nameLength = entityReader.currentOffset() - nameOffset;
  +        if (nameLength == 0)
  +            return -1;
  +        int valueIndex = entityReader.addSymbol(nameOffset, nameLength);
  +        return valueIndex;
  +    }
  +
  +    public int scanDefaultAttValue(QName element, QName attribute, 
  +                                   int attType, int enumeration) throws Exception {
  +        /***/
  +        if (fValidationEnabled && attType == XMLAttributeDecl.TYPE_ID) {
  +            reportRecoverableXMLError(XMLMessages.MSG_ID_DEFAULT_TYPE_INVALID,
  +                                      XMLMessages.VC_ID_ATTRIBUTE_DEFAULT,
  +                                      fStringPool.toString(attribute.rawname));
  +        }
  +        /***/
  +        int defaultAttValue = scanDefaultAttValue(element, attribute);
  +        if (defaultAttValue == -1)
  +            return -1;
  +        // REVISIT
  +        /***
  +        if (attType != fCDATASymbol) {
  +            // REVISIT: Validation. Should we pass in the element or is this
  +            //          default attribute value normalization?
  +            defaultAttValue = fValidator.normalizeAttValue(null, attribute, defaultAttValue, attType, enumeration);
  +        }
  +        /***/
  +        return defaultAttValue;
       }
  -}
  +
  +    public int normalizeDefaultAttValue( QName attribute, int defaultAttValue, 
  +                                         int attType, int enumeration, 
  +                                         boolean list) throws Exception {
  +            //
  +            // Normalize attribute based upon attribute type...
  +            //
  +            String attValue = fStringPool.toString(defaultAttValue);
  +
  +            if (list) {
  +                StringTokenizer tokenizer = new StringTokenizer(attValue);
  +                StringBuffer sb = new StringBuffer(attValue.length());
  +                boolean ok = true;
  +                if (tokenizer.hasMoreTokens()) {
  +                    while (true) {
  +                        String nmtoken = tokenizer.nextToken();
  +                        if (attType == XMLAttributeDecl.TYPE_NMTOKEN) {
  +                            if (fValidationEnabled && !XMLCharacterProperties.validNmtoken(nmtoken)) {
  +                                ok = false;
  +                            }
  +                        }
  +                        else if (attType == XMLAttributeDecl.TYPE_IDREF || attType == XMLAttributeDecl.TYPE_ENTITY) {
  +                            if (fValidationEnabled && !XMLCharacterProperties.validName(nmtoken)) {
  +                                ok = false;
  +                            }
  +                            // REVISIT: a Hack!!! THis is to pass SUN test /invalid/attr11.xml and attr12.xml
  +                            // not consistent with XML1.0 spec VC: Attribute Default Legal
  +                            if (fValidationEnabled && attType == XMLAttributeDecl.TYPE_ENTITY)
  +                            if (! ((DefaultEntityHandler) fEntityHandler).isUnparsedEntity(defaultAttValue)) {
  +                                reportRecoverableXMLError(XMLMessages.MSG_ENTITY_INVALID,
  +                                                          XMLMessages.VC_ENTITY_NAME,
  +                                                          fStringPool.toString(attribute.rawname), nmtoken);
  +                            }
  +
  +                        }
  +                        sb.append(nmtoken);
  +                        if (!tokenizer.hasMoreTokens()) {
  +                            break;
  +                        }
  +                        sb.append(' ');
  +                    }
  +                }
  +                String newAttValue = sb.toString();
  +                if (fValidationEnabled && (!ok || newAttValue.length() == 0)) {
  +                    reportRecoverableXMLError(XMLMessages.MSG_ATT_DEFAULT_INVALID,
  +                                              XMLMessages.VC_ATTRIBUTE_DEFAULT_LEGAL,
  +                                              fStringPool.toString(attribute.rawname), newAttValue);
  +                }
  +                if (!newAttValue.equals(attValue)) {
  +                    defaultAttValue = fStringPool.addString(newAttValue);
  +                }
  +                return defaultAttValue;
  +            }
  +            else {
  +                String newAttValue = attValue.trim();
  +
  +                if (fValidationEnabled) {
  +                    // REVISIT - can we release the old string?
  +                    if (newAttValue != attValue) {
  +                       defaultAttValue = fStringPool.addSymbol(newAttValue);
  +                    } 
  +                    else {
  +                       defaultAttValue = fStringPool.addSymbol(defaultAttValue);
  +                    }
  +                    if (attType == XMLAttributeDecl.TYPE_ENTITY ||
  +                        attType == XMLAttributeDecl.TYPE_ID ||
  +                        attType == XMLAttributeDecl.TYPE_IDREF ||
  +                        attType == XMLAttributeDecl.TYPE_NOTATION)  {
  +
  +                        // REVISIT: A Hack!!! THis is to pass SUN test /invalid/attr11.xml and attr12.xml
  +                        // not consistent with XML1.0 spec VC: Attribute Default Legal
  +                        if (attType == XMLAttributeDecl.TYPE_ENTITY)
  +                        if (! ((DefaultEntityHandler) fEntityHandler).isUnparsedEntity(defaultAttValue)) {
  +                            reportRecoverableXMLError(XMLMessages.MSG_ENTITY_INVALID,
  +                                                      XMLMessages.VC_ENTITY_NAME,
  +                                                      fStringPool.toString(attribute.rawname), newAttValue);
  +                        }
  +                        
  +                        if (!XMLCharacterProperties.validName(newAttValue)) {
  +                            reportRecoverableXMLError(XMLMessages.MSG_ATT_DEFAULT_INVALID,
  +                                                      XMLMessages.VC_ATTRIBUTE_DEFAULT_LEGAL,
  +                                                      fStringPool.toString(attribute.rawname), newAttValue);
  +                        }
  +
  +                    }
  +                    else if (attType == XMLAttributeDecl.TYPE_NMTOKEN ||
  +                             attType == XMLAttributeDecl.TYPE_ENUMERATION ) {
  +
  +                        if (!XMLCharacterProperties.validNmtoken(newAttValue)) {
  +                            reportRecoverableXMLError(XMLMessages.MSG_ATT_DEFAULT_INVALID,
  +                                                      XMLMessages.VC_ATTRIBUTE_DEFAULT_LEGAL,
  +                                                      fStringPool.toString(attribute.rawname), newAttValue);
  +                        }
  +                    }
  +                    
  +                    if (attType == XMLAttributeDecl.TYPE_NOTATION ||
  +                        attType == XMLAttributeDecl.TYPE_ENUMERATION ) {
  +
  +                        if ( !fStringPool.stringInList(enumeration, defaultAttValue) ) {
  +                            reportRecoverableXMLError(XMLMessages.MSG_ATT_DEFAULT_INVALID,
  +                                                      XMLMessages.VC_ATTRIBUTE_DEFAULT_LEGAL,
  +                                                      fStringPool.toString(attribute.rawname), newAttValue);
  +                        }
  +                    }
  +
  +                } 
  +                else if (newAttValue != attValue) {
  +                    // REVISIT - can we release the old string?
  +                    defaultAttValue = fStringPool.addSymbol(newAttValue);
  +                }
  +            }
  +
  +            return defaultAttValue;
  +    }
  +    /***
  +    public boolean scanDoctypeDecl(boolean standalone) throws Exception {
  +        fStandaloneReader = standalone ? fEntityHandler.getReaderId() : -1;
  +        fDeclsAreExternal = false;
  +        if (!fDTDScanner.scanDoctypeDecl()) {
  +            return false;
  +        }
  +        if (fDTDScanner.getReadingExternalEntity()) {
  +            fDTDScanner.scanDecls(true);
  +        }
  +        fDTDHandler.endDTD();
  +        return true;
  +    }
  +    /***/
  +
  +} // class XMLDTDScanner
  
  
  
  1.3       +10 -9     xml-xerces/java/src/org/apache/xerces/framework/XMLDocumentHandler.java
  
  Index: XMLDocumentHandler.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/framework/XMLDocumentHandler.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- XMLDocumentHandler.java	2000/04/04 21:14:21	1.2
  +++ XMLDocumentHandler.java	2000/05/17 18:32:24	1.3
  @@ -57,6 +57,8 @@
   
   package org.apache.xerces.framework;
   
  +import org.apache.xerces.utils.QName;
  +
   /**
    * XMLValidator defines the interface that XMLDocumentScanner and XML
    * EntityHandler have with an object that serves as a pluggable validator.
  @@ -69,7 +71,7 @@
    * the grammar specification file (which contains markup declarations and entity
    * declarations)
    *
  - * @version $Id: XMLDocumentHandler.java,v 1.2 2000/04/04 21:14:21 andyc Exp $
  + * @version $Id: XMLDocumentHandler.java,v 1.3 2000/05/17 18:32:24 jeffreyr Exp $
    */
   
   public interface XMLDocumentHandler {
  @@ -133,7 +135,8 @@
        * @param attrListHandle handle into attrList.  Allows attributes to be retreived.
        * @exception java.lang.Exception
        */
  -    public void startElement(int elementType, XMLAttrList attrList, int attrListHandle) throws Exception;
  +    public void startElement(QName element, 
  +                             XMLAttrList attrList, int attrListHandle) throws Exception;
   
       /**
        * callback for end of element.
  @@ -141,7 +144,7 @@
        * @param elementType element handle for the element being scanned
        * @exception java.lang.Exception
        */
  -    public void endElement(int elementType) throws Exception;
  +    public void endElement(QName element) throws Exception;
   
       /**
        * callback for start of entity reference.
  @@ -252,7 +255,7 @@
            * @param systemId string pool index of the DTD's system ID
            * @exception java.lang.Exception
            */
  -        public void startDTD(int rootElementType, int publicId, int systemId) throws Exception;
  +        public void startDTD(QName rootElement, int publicId, int systemId) throws Exception;
   
           /**
            * Supports DOM Level 2 internalSubset additions.
  @@ -281,7 +284,7 @@
            * @see org.apache.xerces.framework.XMLContentSpec
            * @exception java.lang.Exception
            */
  -        public void elementDecl(int elementType, XMLContentSpec contentSpec) throws Exception;
  +        public void elementDecl(QName elementDecl, XMLContentSpec contentSpec) throws Exception;
   
           /**
            * callback for an attribute list declaration. 
  @@ -296,10 +299,8 @@
            *        or -1 if there is no defaultvalue 
            * @exception java.lang.Exception
            */
  -        public void attlistDecl(int elementType,
  -                                int attrName,
  -                                int attType,
  -                                String enumString,
  +        public void attlistDecl(QName elementDecl, QName attributeDecl,
  +                                int attType, String enumString,
                                   int attDefaultType,
                                   int attDefaultValue) throws Exception;
   
  
  
  
  1.4       +370 -123  xml-xerces/java/src/org/apache/xerces/framework/XMLDocumentScanner.java
  
  Index: XMLDocumentScanner.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/framework/XMLDocumentScanner.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- XMLDocumentScanner.java	2000/04/04 21:14:21	1.3
  +++ XMLDocumentScanner.java	2000/05/17 18:32:25	1.4
  @@ -58,8 +58,13 @@
   package org.apache.xerces.framework;
   
   import org.apache.xerces.readers.XMLEntityHandler;
  +import org.apache.xerces.readers.DefaultEntityHandler;
  +import org.apache.xerces.utils.ChunkyCharArray;
  +import org.apache.xerces.utils.QName;
   import org.apache.xerces.utils.StringPool;
  +import org.apache.xerces.utils.XMLCharacterProperties;
   import org.apache.xerces.utils.XMLMessages;
  +import org.apache.xerces.validators.common.GrammarResolver;
   
   import org.xml.sax.Locator;
   import org.xml.sax.SAXParseException;
  @@ -76,7 +81,7 @@
    * "connecting" that method to the corresponding method provided
    * by the XMLDTDScanner class.
    *
  - * @version $Id: XMLDocumentScanner.java,v 1.3 2000/04/04 21:14:21 andyc Exp $
  + * @version $Id: XMLDocumentScanner.java,v 1.4 2000/05/17 18:32:25 jeffreyr Exp $
    */
   public final class XMLDocumentScanner {
       //
  @@ -146,6 +151,19 @@
       //
       // Instance Variables
       //
  +    /***/
  +    // NOTE: Used by old implementation of scanElementType method. -Ac
  +    private StringPool.CharArrayRange fCurrentElementCharArrayRange = null;
  +    /***/
  +    int fAttrListHandle = -1;
  +    XMLAttrList fAttrList = null;
  +    GrammarResolver fGrammarResolver = null;
  +    XMLDTDScanner fDTDScanner = null;
  +    boolean fNamespacesEnabled = false;
  +    boolean fValidationEnabled = false;
  +    QName fElementQName = new QName();
  +    QName fAttributeQName = new QName();
  +    QName fCurrentElementQName = new QName();
       ScannerDispatcher fDispatcher = null;
       EventHandler fEventHandler = null;
       StringPool fStringPool = null;
  @@ -157,6 +175,7 @@
       boolean fSeenDoctypeDecl = false;
       boolean fStandalone = false;
       boolean fParseTextDecl = false;
  +    boolean fScanningDTD = false;
       int fScannerState = SCANNER_STATE_XML_DECL;
       int fReaderId = -1;
       int fAttValueReader = -1;
  @@ -177,46 +196,12 @@
        */
       public interface EventHandler {
           /**
  -         * Scan an element type.
  +         * Signal standalone = "yes"
            *
  -         * If namespaces are supported, this method should scan a QName instead of a
  -         * Name and report any related well-formedness errors.
  -         *
  -         * @param entityReader The entity reader.
  -         * @param fastchar A likely non-name character that might terminate the element type.
  -         * @return The handle in the string pool for the element type scanned, or -1 if
  -         *         we were not able to scan an element type at the current location.
  -         * @exception java.lang.Exception
  -         */
  -        public int scanElementType(XMLEntityHandler.EntityReader entityReader, char fastchar) throws Exception;
  -        /**
  -         * Scan the expected element type.
  -         *
  -         * This method is used to scan the matching end tag for the element type at the current
  -         * nesting depth of the document.
  -         *
  -         * @param entityReader The entity reader.
  -         * @param fastchar A likely non-name character that might terminate the element type.
  -         * @return <code>true</code> if we scanned the expected element type; otherwise
  -         *         <code>false</code> if we were not able to scan an element type at the
  -         *         current location, or if that element type was not the one we expected to
  -         *         find.
            * @exception java.lang.Exception
            */
  -        public boolean scanExpectedElementType(XMLEntityHandler.EntityReader entityReader, char fastchar) throws Exception;
  -        /**
  -         * Scan an attribute name.
  -         *
  -         * If namespaces are supported, this method should scan a QName instead of a
  -         * Name and report any related well-formedness errors.
  -         *
  -         * @param entityReader The entity reader.
  -         * @param elementType The element type for this attribute.
  -         * @return The handle in the string pool for the attribute name scanned, or -1 if
  -         *         we were not able to scan an attribute name at the current location.
  -         * @exception java.lang.Exception
  -         */
  -        public int scanAttributeName(XMLEntityHandler.EntityReader entityReader, int elementType) throws Exception;
  +        public void callStandaloneIsYes() throws Exception;
  +
           /**
            * Signal the start of a document
            *
  @@ -249,33 +234,32 @@
           /**
            * signal the scanning of a start element tag
            * 
  -         * @param elementType handle to the elementType being scanned
  +         * @param element Element name scanned.
            * @exception java.lang.Exception
            */
  -        public void callStartElement(int elementType) throws Exception;
  +        public void callStartElement(QName element) throws Exception;
           /**
  -         * signal the scanning of an end element tag
  +         * Signal the scanning of an element name in a start element tag.
            *
  -         * @param readerId the Id of the reader being used to scan the end tag.
  -         * @exception java.lang.Exception
  +         * @param element Element name scanned.
            */
  -        public void callEndElement(int readerId) throws Exception;
  +        public void element(QName element) throws Exception;
           /**
  -         * Check for a valid XML version number
  +         * Signal the scanning of an attribute associated to the previous
  +         * start element tag.
            *
  -         * @param version a string representing an XML version number
  -         * @return true if the parser can process this version of XML
  -         * @exception java.lang.Exception
  +         * @param element Element name scanned.
  +         * @param attrName Attribute name scanned.
  +         * @param attrValue The string pool index of the attribute value.
            */
  -        public boolean validVersionNum(String version) throws Exception;
  +        public boolean attribute(QName element, QName attrName, int attrValue) throws Exception;
           /**
  -         * Check for a valid encoding name
  +         * signal the scanning of an end element tag
            *
  -         * @param encoding a string containing an encoding naem
  -         * @return true if the encoding name is valid
  +         * @param readerId the Id of the reader being used to scan the end tag.
            * @exception java.lang.Exception
            */
  -        public boolean validEncName(String encoding) throws Exception;
  +        public void callEndElement(int readerId) throws Exception;
           /**
            * Signal the start of a CDATA section
            * @exception java.lang.Exception
  @@ -308,26 +292,6 @@
            * @exception java.lang.Exception
            */
           public void callComment(int data) throws Exception;
  -        /**
  -         * Scan the document type declaration
  -         *
  -         * @param standalone true if there was a standalone document declaration in
  -         *        the XMLDecl
  -         * @exception java.lang.Exception
  -         */
  -        public void scanDoctypeDecl(boolean standalone) throws Exception;
  -        /**
  -         * Scan the value of an attribute and include it in the set of specified
  -         * attributes for the element.
  -         *
  -         * @param elementType handle for the element type of the attribute.
  -         * @param attrName handle for the attribute name.
  -         * @return XMLDocumentScanner.RESULT_SUCCESS if the attribute was created,
  -         *         XMLDocumentScanner.RESULT_NOT_WELL_FORMED if the scan failed, or
  -         *         XMLDocumentScanner.RESULT_DUPLICATE_ATTR if the attribute is a duplicate.
  -         * @exception java.lang.Exception
  -         */
  -        public int scanAttValue(int elementType, int attrName) throws Exception;
       }
   
       /**
  @@ -342,6 +306,7 @@
           fEntityHandler = entityHandler;
           fLiteralData = literalData;
           fDispatcher = new XMLDeclDispatcher();
  +        fAttrList = new XMLAttrList(fStringPool);
       }
   
       /**
  @@ -353,6 +318,11 @@
           fEventHandler = eventHandler;
       }
   
  +    /** Sets the grammar resolver. */
  +    public void setGrammarResolver(GrammarResolver resolver) {
  +        fGrammarResolver = resolver;
  +    }
  +
       /**
        * reset the parser so that the instance can be reused
        *
  @@ -365,9 +335,11 @@
           fSeenRootElement = false;
           fSeenDoctypeDecl = false;
           fStandalone = false;
  +        fScanningDTD = false;
           fDispatcher = new XMLDeclDispatcher();
           fScannerState = SCANNER_STATE_XML_DECL;
           fScannerMarkupDepth = 0;
  +        fAttrList = new XMLAttrList(fStringPool);
       }
   
       //
  @@ -419,6 +391,10 @@
               fAttValueOffset = fEntityReader.currentOffset();
               fAttValueMark = fAttValueOffset;
           }
  +
  +        //also propagate the change to DTDScanner if there is one
  +        if (fDTDScanner != null && fScanningDTD)
  +            fDTDScanner.readerChange(nextReader, nextReaderId);
       }
   
       /**
  @@ -429,6 +405,9 @@
        * @exception java.lang.Exception
        */
       public void endOfInput(int entityName, boolean moreToFollow) throws Exception {
  +        if (fDTDScanner != null && fScanningDTD){
  +            fDTDScanner.endOfInput(entityName, moreToFollow);
  +        }
           fDispatcher.endOfInput(entityName, moreToFollow);
       }
   
  @@ -452,13 +431,13 @@
        * @return handle in the string pool of the scanned value
        * @exception java.lang.Exception
        */
  -    public int scanAttValue(int elementType, int attrName, boolean asSymbol) throws Exception {
  +    public int scanAttValue(QName element, QName attribute, boolean asSymbol) throws Exception {
           boolean single;
           if (!(single = fEntityReader.lookingAtChar('\'', true)) && !fEntityReader.lookingAtChar('\"', true)) {
               reportFatalXMLError(XMLMessages.MSG_QUOTE_REQUIRED_IN_ATTVALUE,
                                   XMLMessages.P10_QUOTE_REQUIRED,
  -                                elementType,
  -                                attrName);
  +                                element.rawname,
  +                                attribute.rawname);
               return -1;
           }
           char qchar = single ? '\'' : '\"';
  @@ -468,8 +447,10 @@
               return attValue;
           int previousState = setScannerState(SCANNER_STATE_ATTRIBUTE_VALUE);
           fAttValueReader = fReaderId;
  -        fAttValueElementType = elementType;
  -        fAttValueAttrName = attrName;
  +        // REVISIT: What should this be?
  +        fAttValueElementType = element.rawname;
  +        // REVISIT: What should this be?
  +        fAttValueAttrName = attribute.rawname;
           fAttValueOffset = fEntityReader.currentOffset();
           int dataOffset = fLiteralData.length();
           if (fAttValueOffset - fAttValueMark > 0)
  @@ -539,8 +520,8 @@
                   setMark = true;
                   reportFatalXMLError(XMLMessages.MSG_LESSTHAN_IN_ATTVALUE,
                                       XMLMessages.WFC_NO_LESSTHAN_IN_ATTVALUE,
  -                                    elementType,
  -                                    attrName);
  +                                    element.rawname,
  +                                    attribute.rawname);
               } else if (!fEntityReader.lookingAtValidChar(true)) {
                   if (fAttValueOffset - fAttValueMark > 0)
                       fEntityReader.append(fLiteralData, fAttValueMark, fAttValueOffset - fAttValueMark);
  @@ -551,8 +532,8 @@
                   if (invChar >= 0) {
                       reportFatalXMLError(XMLMessages.MSG_INVALID_CHAR_IN_ATTVALUE,
                                           XMLMessages.P10_INVALID_CHARACTER,
  -                                        fStringPool.toString(elementType),
  -                                        fStringPool.toString(attrName),
  +                                        fStringPool.toString(element.rawname),
  +                                        fStringPool.toString(attribute.rawname),
                                           Integer.toHexString(invChar));
                   }
               }
  @@ -571,7 +552,8 @@
               fEntityReader.append(fLiteralData, fAttValueMark, fAttValueOffset - fAttValueMark);
               dataLength = fLiteralData.length() - dataOffset;
           }
  -        return fLiteralData.addString(dataOffset, dataLength);
  +        int value = fLiteralData.addString(dataOffset, dataLength);
  +        return value;
       }
   
       /**
  @@ -784,7 +766,7 @@
                           if (fEntityReader.skippedString(doctype_string)) {
                               setScannerState(SCANNER_STATE_DOCTYPE);
                               fSeenDoctypeDecl = true;
  -                            fEventHandler.scanDoctypeDecl(fStandalone); // scan through the closing '>'
  +                            scanDoctypeDecl(fStandalone); // scan through the closing '>'
                               fScannerMarkupDepth--;
                               fDispatcher = new PrologDispatcher();
                               restoreScannerState(SCANNER_STATE_PROLOG);
  @@ -891,7 +873,7 @@
                               if (!fSeenDoctypeDecl && fEntityReader.skippedString(doctype_string)) {
                                   setScannerState(SCANNER_STATE_DOCTYPE);
                                   fSeenDoctypeDecl = true;
  -                                fEventHandler.scanDoctypeDecl(fStandalone); // scan through the closing '>'
  +                                scanDoctypeDecl(fStandalone); // scan through the closing '>'
                                   fScannerMarkupDepth--;
                               } else {
                                   abortMarkup(XMLMessages.MSG_MARKUP_NOT_RECOGNIZED_IN_PROLOG,
  @@ -984,8 +966,8 @@
                   switch (fScannerState) {
                   case SCANNER_STATE_ROOT_ELEMENT:
                   {
  -                    int elementType = fEventHandler.scanElementType(fEntityReader, '>');
  -                    if (elementType != -1) {
  +                    scanElementType(fEntityReader, '>', fElementQName);
  +                    if (fElementQName.rawname != -1) {
                           //
                           // root element
                           //
  @@ -998,18 +980,18 @@
                               //
                               // we have more content
                               //
  -                            fEventHandler.callStartElement(elementType);
  +                            fEventHandler.callStartElement(fElementQName);
                               fScannerMarkupDepth--;
                               if (fElementDepth == fElementTypeStack.length) {
                                   int[] newStack = new int[fElementDepth * 2];
                                   System.arraycopy(fElementTypeStack, 0, newStack, 0, fElementDepth);
                                   fElementTypeStack = newStack;
                               }
  -                            fCurrentElementType = elementType;
  -                            fElementTypeStack[fElementDepth] = elementType;
  +                            fCurrentElementType = fElementQName.rawname;
  +                            fElementTypeStack[fElementDepth] = fElementQName.rawname;
                               fElementDepth++;
                               restoreScannerState(SCANNER_STATE_CONTENT);
  -                        } else if (scanElement(elementType)) {
  +                        } else if (scanElement(fElementQName)) {
                               //
                               // we have more content
                               //
  @@ -1018,8 +1000,8 @@
                                   System.arraycopy(fElementTypeStack, 0, newStack, 0, fElementDepth);
                                   fElementTypeStack = newStack;
                               }
  -                            fCurrentElementType = elementType;
  -                            fElementTypeStack[fElementDepth] = elementType;
  +                            fCurrentElementType = fElementQName.rawname;
  +                            fElementTypeStack[fElementDepth] = fElementQName.rawname;
                               fElementDepth++;
                               restoreScannerState(SCANNER_STATE_CONTENT);
                           } else {
  @@ -1081,7 +1063,7 @@
                               //
                               // [42] ETag ::= '</' Name S? '>'
                               //
  -                            if (!fEventHandler.scanExpectedElementType(fEntityReader, '>')) {
  +                            if (!scanExpectedElementType(fEntityReader, '>', fCurrentElementType)) {
                                   abortMarkup(XMLMessages.MSG_ETAG_REQUIRED,
                                               XMLMessages.P39_UNTERMINATED,
                                               fCurrentElementType);
  @@ -1109,31 +1091,31 @@
                                   }
                               }
                           } else {
  -                            int elementType = fEventHandler.scanElementType(fEntityReader, '>');
  -                            if (elementType != -1) {
  +                            scanElementType(fEntityReader, '>', fElementQName);
  +                            if (fElementQName.rawname != -1) {
                                   //
                                   // element
                                   //
                                   if (fEntityReader.lookingAtChar('>', true)) {
  -                                    fEventHandler.callStartElement(elementType);
  +                                    fEventHandler.callStartElement(fElementQName);
                                       fScannerMarkupDepth--;
                                       if (fElementDepth == fElementTypeStack.length) {
                                           int[] newStack = new int[fElementDepth * 2];
                                           System.arraycopy(fElementTypeStack, 0, newStack, 0, fElementDepth);
                                           fElementTypeStack = newStack;
                                       }
  -                                    fCurrentElementType = elementType;
  -                                    fElementTypeStack[fElementDepth] = elementType;
  +                                    fCurrentElementType = fElementQName.rawname;
  +                                    fElementTypeStack[fElementDepth] = fElementQName.rawname;
                                       fElementDepth++;
                                   } else {
  -                                    if (scanElement(elementType)) {
  +                                    if (scanElement(fElementQName)) {
                                           if (fElementDepth == fElementTypeStack.length) {
                                               int[] newStack = new int[fElementDepth * 2];
                                               System.arraycopy(fElementTypeStack, 0, newStack, 0, fElementDepth);
                                               fElementTypeStack = newStack;
                                           }
  -                                        fCurrentElementType = elementType;
  -                                        fElementTypeStack[fElementDepth] = elementType;
  +                                        fCurrentElementType = fElementQName.rawname;
  +                                        fElementTypeStack[fElementDepth] = fElementQName.rawname;
                                           fElementDepth++;
                                       }
                                   }
  @@ -1151,7 +1133,10 @@
                           setScannerState(SCANNER_STATE_START_OF_MARKUP);
                           continue;
                       }
  -                    switch (fEntityReader.scanContent(fCurrentElementType)) {
  +                    // REVISIT: Is this the right thing to do? Do we need to
  +                    //          save more information on the stack?
  +                    fCurrentElementQName.setValues(-1, -1, fCurrentElementType);
  +                    switch (fEntityReader.scanContent(fCurrentElementQName)) {
                       case XMLEntityHandler.CONTENT_RESULT_START_OF_PI:
                           fScannerMarkupDepth++;
                           int piTarget = fEntityReader.scanName(' ');
  @@ -1192,7 +1177,7 @@
                           //
                           // [42] ETag ::= '</' Name S? '>'
                           //
  -                        if (!fEventHandler.scanExpectedElementType(fEntityReader, '>')) {
  +                        if (!scanExpectedElementType(fEntityReader, '>', fCurrentElementType)) {
                               abortMarkup(XMLMessages.MSG_ETAG_REQUIRED,
                                           XMLMessages.P39_UNTERMINATED,
                                           fCurrentElementType);
  @@ -1225,28 +1210,28 @@
                       {
                           fScannerMarkupDepth++;
                           fParseTextDecl = false;
  -                        int elementType = fEventHandler.scanElementType(fEntityReader, '>');
  -                        if (elementType != -1) {
  +                        scanElementType(fEntityReader, '>', fElementQName);
  +                        if (fElementQName.rawname != -1) {
                               if (fEntityReader.lookingAtChar('>', true)) {
  -                                fEventHandler.callStartElement(elementType);
  +                                fEventHandler.callStartElement(fElementQName);
                                   fScannerMarkupDepth--;
                                   if (fElementDepth == fElementTypeStack.length) {
                                       int[] newStack = new int[fElementDepth * 2];
                                       System.arraycopy(fElementTypeStack, 0, newStack, 0, fElementDepth);
                                       fElementTypeStack = newStack;
                                   }
  -                                fCurrentElementType = elementType;
  -                                fElementTypeStack[fElementDepth] = elementType;
  +                                fCurrentElementType = fElementQName.rawname;
  +                                fElementTypeStack[fElementDepth] = fElementQName.rawname;
                                   fElementDepth++;
                               } else {
  -                                if (scanElement(elementType)) {
  +                                if (scanElement(fElementQName)) {
                                       if (fElementDepth == fElementTypeStack.length) {
                                           int[] newStack = new int[fElementDepth * 2];
                                           System.arraycopy(fElementTypeStack, 0, newStack, 0, fElementDepth);
                                           fElementTypeStack = newStack;
                                       }
  -                                    fCurrentElementType = elementType;
  -                                    fElementTypeStack[fElementDepth] = elementType;
  +                                    fCurrentElementType = fElementQName.rawname;
  +                                    fElementTypeStack[fElementDepth] = fElementQName.rawname;
                                       fElementDepth++;
                                   }
                               }
  @@ -1673,7 +1658,7 @@
                   version = result;
                   String versionString = fStringPool.toString(version);
                   if (!"1.0".equals(versionString)) {
  -                    if (!fEventHandler.validVersionNum(versionString)) {
  +                    if (!validVersionNum(versionString)) {
                           abortMarkup(XMLMessages.MSG_VERSIONINFO_INVALID,
                                               XMLMessages.P26_INVALID_VALUE,
                                               versionString);
  @@ -1706,7 +1691,7 @@
                   //
                   encoding = result;
                   String encodingString = fStringPool.toString(encoding);
  -                if (!fEventHandler.validEncName(encodingString)) {
  +                if (!validEncName(encodingString)) {
                       abortMarkup(XMLMessages.MSG_ENCODINGDECL_INVALID,
                                   XMLMessages.P81_INVALID_VALUE,
                                   encodingString);
  @@ -1759,6 +1744,10 @@
               // handler before returning.
               //
               fEventHandler.callXMLDecl(version, encoding, standalone);
  +            // if we see standalone = 'yes', call the eventHandler - XMLValidator
  +            if (fStandalone) {
  +                fEventHandler.callStandaloneIsYes();
  +            }
           }
       }
       //
  @@ -1777,7 +1766,7 @@
       //
       // Note: We have already scanned Name.
       //
  -    boolean scanElement(int elementType) throws Exception
  +    boolean scanElement(QName element) throws Exception
       {
           //
           // Scan for attributes
  @@ -1799,8 +1788,8 @@
                   // Name
                   //
                   setScannerState(SCANNER_STATE_ATTRIBUTE_NAME);
  -                int attrName = fEventHandler.scanAttributeName(fEntityReader, elementType);
  -                if (attrName == -1) {
  +                scanAttributeName(fEntityReader, element, fAttributeQName);
  +                if (fAttributeQName.rawname == -1) {
                       break;
                   }
                   //
  @@ -1811,13 +1800,13 @@
                       if (fScannerState != SCANNER_STATE_END_OF_INPUT) {
                           abortMarkup(XMLMessages.MSG_EQ_REQUIRED_IN_ATTRIBUTE,
                                       XMLMessages.P41_EQ_REQUIRED,
  -                                    elementType, attrName);
  +                                    element.rawname, fAttributeQName.rawname);
                           restoreScannerState(previousState);
                       }
                       return false;
                   }
                   fEntityReader.skipPastSpaces();
  -                int result = fEventHandler.scanAttValue(elementType, attrName);
  +                int result = scanAttValue(element, fAttributeQName, false);
                   if (result == RESULT_FAILURE) {
                       if (fScannerState != SCANNER_STATE_END_OF_INPUT) {
                           skipPastEndOfCurrentMarkup();
  @@ -1826,8 +1815,14 @@
                       return false;
                   } else if (result == RESULT_DUPLICATE_ATTR) {
                       reportFatalXMLError(XMLMessages.MSG_ATTRIBUTE_NOT_UNIQUE,
  +                                        XMLMessages.WFC_UNIQUE_ATT_SPEC,
  +                                        element.rawname, fAttributeQName.rawname);
  +                }
  +                //The validator will check whether we have a duplicate attr in the start tag.
  +                if ( fEventHandler.attribute(element, fAttributeQName, result) ) {
  +                    reportFatalXMLError(XMLMessages.MSG_ATTRIBUTE_NOT_UNIQUE,
                                           XMLMessages.WFC_UNIQUE_ATT_SPEC,
  -                                        elementType, attrName);
  +                                        element.rawname, fAttributeQName.rawname);
                   }
                   restoreScannerState(SCANNER_STATE_ATTRIBUTE_LIST);
                   if (!fEntityReader.lookingAtSpace(true)) {
  @@ -1844,11 +1839,11 @@
               if (fScannerState != SCANNER_STATE_END_OF_INPUT) {
                   abortMarkup(XMLMessages.MSG_ELEMENT_UNTERMINATED,
                               XMLMessages.P40_UNTERMINATED,
  -                            elementType);
  +                            element.rawname);
               }
               return false;
           }
  -        fEventHandler.callStartElement(elementType);
  +        fEventHandler.callStartElement(element);
           fScannerMarkupDepth--;
           if (slash) { // '/>'
               fEventHandler.callEndElement(fReaderId);
  @@ -2020,5 +2015,257 @@
           int piData = piDataLength == 0 ?
                        StringPool.EMPTY_STRING : fEntityReader.addString(piDataOffset, piDataLength);
           fEventHandler.callProcessingInstruction(piTarget, piData);
  +    }
  +
  +    /** Sets whether the parser preprocesses namespaces. */
  +    public void setNamespacesEnabled(boolean enabled) {
  +        fNamespacesEnabled = enabled;
  +    }
  +
  +    /** Returns whether the parser processes namespaces. */
  +    public boolean getNamespacesEnabled() {
  +        return fNamespacesEnabled;
  +    }
  +
  +    /** Sets whether the parser validates. */
  +    public void setValidationEnabled(boolean enabled) {
  +        fValidationEnabled = enabled;
  +        if (fDTDScanner != null) {
  +            fDTDScanner.setValidationEnabled(enabled);
  +        }
  +    }
  +
  +    /** Returns true if validation is turned on. */
  +    public boolean getValidationEnabled() {
  +        return fValidationEnabled;
       }
  -}
  +
  +    // old EventHandler methods pushed back into scanner
  +
  +    /** Scans element type. */
  +    private void scanElementType(XMLEntityHandler.EntityReader entityReader, 
  +                                char fastchar, QName element) throws Exception {
  +
  +        if (!fNamespacesEnabled) {
  +            element.clear();
  +            element.localpart = entityReader.scanName(fastchar);
  +            element.rawname = element.localpart;
  +        } 
  +        else {
  +            entityReader.scanQName(fastchar, element);
  +            if (entityReader.lookingAtChar(':', false)) {
  +                fErrorReporter.reportError(fErrorReporter.getLocator(),
  +                                           XMLMessages.XML_DOMAIN,
  +                                           XMLMessages.MSG_TWO_COLONS_IN_QNAME,
  +                                           XMLMessages.P5_INVALID_CHARACTER,
  +                                           null,
  +                                           XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
  +                 entityReader.skipPastNmtoken(' ');
  +            }
  +        }
  +
  +        fEventHandler.element(element);
  +
  +    } // scanElementType(XMLEntityHandler.EntityReader,char,QName)
  +
  +    /** Scans expected element type. */
  +    private boolean scanExpectedElementType(XMLEntityHandler.EntityReader entityReader, 
  +                                           char fastchar, int elementType) 
  +        throws Exception {
  +
  +        /***/
  +        // REVISIT: Why aren't we using the 'element' parameter? -Ac
  +        // REVISIT: I replaced the 'fCurrentElement' with 'element' parameter, still working, 
  +        //          just wondering Why are we using CharArrayRange in the first place? -ericye
  +        if (fCurrentElementCharArrayRange == null) {
  +            fCurrentElementCharArrayRange = fStringPool.createCharArrayRange();
  +        }
  +        fStringPool.getCharArrayRange(elementType, fCurrentElementCharArrayRange);
  +        return entityReader.scanExpectedName(fastchar, fCurrentElementCharArrayRange);
  +        /***
  +        entityReader.scanQName(fastchar, element);
  +        return true;
  +        /***/
  +
  +    } // scanExpectedElementType(XMLEntityHandler.EntityReader,char,QName)
  +
  +    /** Scans attribute name. */
  +    private void scanAttributeName(XMLEntityHandler.EntityReader entityReader, 
  +                                  QName element, QName attribute) 
  +        throws Exception {
  +
  +        /***
  +        // REVISIT: What's this check for?
  +        if (!fSeenRootElement) {
  +            fSeenRootElement = true;
  +            rootElementSpecified(element);
  +            fStringPool.resetShuffleCount();
  +        }
  +        /***/
  +
  +        if (!fNamespacesEnabled) {
  +            attribute.clear();
  +            attribute.localpart = entityReader.scanName('=');
  +            attribute.rawname = attribute.localpart;
  +        } 
  +        else {
  +            entityReader.scanQName('=', attribute);
  +            if (entityReader.lookingAtChar(':', false)) {
  +                fErrorReporter.reportError(fErrorReporter.getLocator(),
  +                                           XMLMessages.XML_DOMAIN,
  +                                           XMLMessages.MSG_TWO_COLONS_IN_QNAME,
  +                                           XMLMessages.P5_INVALID_CHARACTER,
  +                                           null,
  +                                           XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
  +                entityReader.skipPastNmtoken(' ');
  +            }
  +        }
  +
  +    } // scanAttributeName(XMLEntityHandler.EntityReader,QName,QName)
  +
  +    /** Scan doctype declaration. */
  +    private void scanDoctypeDecl(boolean standalone) throws Exception {
  +        
  +        fScanningDTD = true;
  +
  +        /***
  +        fScanningDTD = true;
  +        fCheckedForSchema = true;
  +        /***/
  +        fSeenDoctypeDecl = true;
  +        /***
  +        fStandaloneReader = standalone ? fEntityHandler.getReaderId() : -1;
  +        fDeclsAreExternal = false;
  +        if (fDTDImporter == null) {
  +            fDTDImporter = new DTDImporter(fStringPool, fErrorReporter, fEntityHandler, this);
  +        } 
  +        else {
  +            fDTDImporter.reset(fStringPool);
  +        }
  +        fDTDImporter.initHandlers(fDTDHandler);
  +        fDTDImporter.setValidating(fValidating);
  +        fDTDImporter.setNamespacesEnabled(fNamespacesEnabled);
  +        if (fDTDImporter.scanDoctypeDecl(standalone) && fValidating) {
  +            // check declared elements
  +            if (fWarningOnUndeclaredElements) {
  +                // REVISIT: comment out because won't compile 
  +                // checkDeclaredElements();
  +            }
  +
  +            // check required notations
  +            fEntityHandler.checkRequiredNotations();
  +        }
  +        fScanningDTD = false;
  +        /***/
  +        if (fDTDScanner == null) {
  +            fDTDScanner = new XMLDTDScanner(fStringPool, fErrorReporter, fEntityHandler, new ChunkyCharArray(fStringPool));
  +            fDTDScanner.setValidationEnabled(fValidationEnabled);
  +        }
  +        else {
  +            fDTDScanner.reset(fStringPool, new ChunkyCharArray(fStringPool));
  +        }
  +        fDTDScanner.setGrammarResolver(fGrammarResolver);
  +        // REVISIT: What about standalone?
  +        if (fDTDScanner.scanDoctypeDecl()) {
  +            if (fDTDScanner.getReadingExternalEntity()) {
  +                fDTDScanner.scanDecls(true);
  +            }
  +            // REVISIT: What about validation and checking stuff?
  +        }
  +        //VC_NOTATION_DECLARED
  +        if (fValidationEnabled) {
  +            ((DefaultEntityHandler)fEntityHandler).checkRequiredNotations();
  +        }
  +        /***/
  +        fScanningDTD = false;
  +
  +    } // scanDoctypeDecl(boolean)
  +
  +    /** Scan attribute value. */
  +    private int scanAttValue(QName element, QName attribute) throws Exception {
  +
  +        //fAttrNameLocator = getLocatorImpl(fAttrNameLocator);
  +        int attValue = scanAttValue(element, attribute, fValidationEnabled);
  +        if (attValue == -1) {
  +            return XMLDocumentScanner.RESULT_FAILURE;
  +        }
  +
  +
  +        /***
  +        // REVISIT: This is validation related.
  +        if (!fValidating && fAttDefCount == 0) {
  +            int attType = fCDATASymbol;
  +            if (fAttrListHandle == -1)
  +                fAttrListHandle = fAttrList.startAttrList();
  +            // REVISIT: Should this be localpart or rawname?
  +            if (fAttrList.addAttr(attribute, attValue, attType, true, true) == -1) {
  +                return XMLDocumentScanner.RESULT_DUPLICATE_ATTR;
  +            }
  +            return XMLDocumentScanner.RESULT_SUCCESS;
  +        }
  +        /****/
  +
  +        /****
  +        // REVISIT: Validation. What should these be?
  +        int attDefIndex = getAttDef(element, attribute);
  +        if (attDefIndex == -1) {
  +
  +            if (fValidating) {
  +                // REVISIT - cache the elem/attr tuple so that we only give
  +                //  this error once for each unique occurrence
  +                Object[] args = { fStringPool.toString(element.rawname),
  +                                  fStringPool.toString(attribute.rawname) };
  +                fErrorReporter.reportError(fAttrNameLocator,
  +                                           XMLMessages.XML_DOMAIN,
  +                                           XMLMessages.MSG_ATTRIBUTE_NOT_DECLARED,
  +                                           XMLMessages.VC_ATTRIBUTE_VALUE_TYPE,
  +                                           args,
  +                                           XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
  +            }
  +
  +            int attType = fCDATASymbol;
  +            if (fAttrListHandle == -1) {
  +                fAttrListHandle = fAttrList.startAttrList();
  +            }
  +            // REVISIT: Validation. What should the name be?
  +            if (fAttrList.addAttr(attribute, attValue, attType, true, true) == -1) {
  +                return XMLDocumentScanner.RESULT_DUPLICATE_ATTR;
  +            }
  +            return XMLDocumentScanner.RESULT_SUCCESS;
  +        }
  +        /****/
  +
  +        /****
  +        int attType = getAttType(attDefIndex);
  +        if (attType != fCDATASymbol) {
  +            AttributeValidator av = getAttributeValidator(attDefIndex);
  +            int enumHandle = getEnumeration(attDefIndex);
  +            // REVISIT: Validation. What should these be?
  +            attValue = av.normalize(element, attribute, 
  +                                    attValue, attType, enumHandle);
  +        }
  +
  +        if (fAttrListHandle == -1) {
  +            fAttrListHandle = fAttrList.startAttrList();
  +        }
  +        // REVISIT: Validation. What should the name be?
  +        if (fAttrList.addAttr(attribute, attValue, attType, true, true) == -1) {
  +            return XMLDocumentScanner.RESULT_DUPLICATE_ATTR;
  +        }
  +        /***/
  +
  +        return XMLDocumentScanner.RESULT_SUCCESS;
  +
  +    } // scanAttValue(QName,QName):int
  +
  +    /** Returns true if the version number is valid. */
  +    private boolean validVersionNum(String version) {
  +        return XMLCharacterProperties.validVersionNum(version);
  +    }
  +
  +    /** Returns true if the encoding name is valid. */
  +    private boolean validEncName(String encoding) {
  +        return XMLCharacterProperties.validEncName(encoding);
  +    }
  +
  +} // class XMLDocumentScanner
  
  
  
  1.16      +19 -4     xml-xerces/java/src/org/apache/xerces/framework/XMLParser.java
  
  Index: XMLParser.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/framework/XMLParser.java,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- XMLParser.java	2000/04/04 21:14:21	1.15
  +++ XMLParser.java	2000/05/17 18:32:27	1.16
  @@ -68,15 +68,15 @@
   import org.apache.xerces.readers.XMLEntityReaderFactory;
   import org.apache.xerces.utils.ChunkyCharArray;
   import org.apache.xerces.utils.StringPool;
  -
   import org.apache.xerces.utils.XMLMessageProvider;
   import org.apache.xerces.utils.XMLMessages;
   import org.apache.xerces.utils.ImplementationMessages;
  +import org.apache.xerces.validators.common.GrammarResolver;
  +import org.apache.xerces.validators.common.GrammarResolverImpl;
  +import org.apache.xerces.validators.common.XMLValidator;
   import org.apache.xerces.validators.datatype.DatatypeMessageProvider;
   import org.apache.xerces.validators.schema.SchemaMessageProvider;
   
  -import org.apache.xerces.validators.common.XMLValidator;
  -
   import org.xml.sax.EntityResolver;
   import org.xml.sax.ErrorHandler;
   import org.xml.sax.InputSource;
  @@ -89,7 +89,7 @@
   /**
    * This is the base class of all standard parsers.
    *
  - * @version $Id: XMLParser.java,v 1.15 2000/04/04 21:14:21 andyc Exp $
  + * @version $Id: XMLParser.java,v 1.16 2000/05/17 18:32:27 jeffreyr Exp $
    */
   public class XMLParser implements XMLErrorReporter {
   
  @@ -148,6 +148,8 @@
       // Data
       //
   
  +    protected GrammarResolver fGrammarResolver = null;
  +
       // state
   
       protected boolean fParseInProgress = false;
  @@ -196,6 +198,9 @@
           fEntityHandler = new DefaultEntityHandler(fStringPool, fErrorReporter);
           fScanner = new XMLDocumentScanner(fStringPool, fErrorReporter, fEntityHandler, new ChunkyCharArray(fStringPool));
           fValidator = new XMLValidator(fStringPool, fErrorReporter, fEntityHandler, fScanner);
  +        fGrammarResolver = new GrammarResolverImpl();
  +        fScanner.setGrammarResolver(fGrammarResolver);
  +        fValidator.setGrammarResolver(fGrammarResolver);
       }
   
       /**
  @@ -305,6 +310,7 @@
   
       /** Reset parser instance so that it can be reused. */
       public void reset() throws Exception {
  +        fGrammarResolver.clearGrammarResolver();
           fStringPool.reset();
           fEntityHandler.reset(fStringPool);
           fScanner.reset(fStringPool, new ChunkyCharArray(fStringPool));
  @@ -365,6 +371,9 @@
                                                  "http://xml.org/sax/features/validation");
           }
           try {
  +            // REVISIT: [Q] Should the scanner tell the validator that
  +            //              validation is on? -Ac
  +            fScanner.setValidationEnabled(validate);
               fValidator.setValidationEnabled(validate);
           }
           catch (Exception ex) {
  @@ -483,6 +492,9 @@
               throw new SAXNotSupportedException("PAR004 Cannot setFeature(http://xml.org/sax/features/namespaces): parse is in progress.\n"+
                                                  "http://xml.org/sax/features/namespaces");
           }
  +        fScanner.setNamespacesEnabled(process);
  +        // REVISIT: [Q] Should the scanner tell the validator that namespace
  +        //              processing is on? -Ac
           fValidator.setNamespacesEnabled(process);
       }
   
  @@ -728,6 +740,9 @@
           fScanner.reset(fStringPool, new ChunkyCharArray(fStringPool));
           fValidator.resetOrCopy(fStringPool);
           fNeedReset = false;
  +        fGrammarResolver = new GrammarResolverImpl();
  +        fScanner.setGrammarResolver(fGrammarResolver);
  +        fValidator.setGrammarResolver(fGrammarResolver);
       }
   
       //
  
  
  
  1.2       +1 -0      xml-xerces/java/src/org/apache/xerces/msg/XMLMessages.java
  
  Index: XMLMessages.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/msg/XMLMessages.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- XMLMessages.java	1999/11/09 01:12:53	1.1
  +++ XMLMessages.java	2000/05/17 18:32:30	1.2
  @@ -276,6 +276,7 @@
   // Namespaces support
       // 4. Using Qualified Names
           { "PrefixDeclared", "The namespace prefix \"{0}\" was not declared." },
  +        { "MSG_ATT_DEFAULT_INVALID", "The defaultValue \"{1}\" of attribute \"{0}\" is not legal as for the lexical constraints of this attribute type." },
       };
   
       /** Returns the list resource bundle contents. */
  
  
  
  1.16      +77 -41    xml-xerces/java/src/org/apache/xerces/parsers/DOMParser.java
  
  Index: DOMParser.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/parsers/DOMParser.java,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- DOMParser.java	2000/05/01 19:19:37	1.15
  +++ DOMParser.java	2000/05/17 18:32:33	1.16
  @@ -67,6 +67,7 @@
   import org.apache.xerces.framework.XMLDocumentHandler;
   import org.apache.xerces.framework.XMLParser;
   import org.apache.xerces.readers.XMLEntityHandler;
  +import org.apache.xerces.utils.QName;
   import org.apache.xerces.utils.StringPool;
   import org.apache.xerces.validators.schema.XUtil;
   
  @@ -103,7 +104,8 @@
   /**
    * DOMParser provides a parser which produces a W3C DOM tree as its output
    *
  - * @version $Id: DOMParser.java,v 1.15 2000/05/01 19:19:37 lehors Exp $
  + * 
  + * @version $Id: DOMParser.java,v 1.16 2000/05/17 18:32:33 jeffreyr Exp $
    */
   public class DOMParser
       extends XMLParser
  @@ -967,14 +969,18 @@
       
   
       /** Start element. */
  -    public void startElement(int elementTypeIndex,
  +    public void startElement(QName elementQName,
                                XMLAttrList xmlAttrList, int attrListIndex)
           throws Exception {
   
           // deferred expansion
           if (fDeferredDocumentImpl != null) {
   
  -            int element = fDeferredDocumentImpl.createElement(elementTypeIndex, xmlAttrList, attrListIndex);
  +            int element =
  +                fDeferredDocumentImpl.createElement(elementQName.rawname,
  +                                                    elementQName.uri,
  +                                                    xmlAttrList,
  +                                                    attrListIndex);
               fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, element);
               fCurrentNodeIndex = element;
               fWithinElement = true;
  @@ -992,11 +998,12 @@
               // copy schema grammar, if needed
               if (!fSeenRootElement) {
                   fSeenRootElement = true;
  +                /*REVISIT - Grammar Access revisit
                   if (fGrammarAccess) {
                       Document schemaDocument = fValidator.getSchemaDocument();
                       if (schemaDocument != null) {
                           if (fDocumentTypeIndex == -1) {
  -                            fDocumentTypeIndex = fDeferredDocumentImpl.createDocumentType(elementTypeIndex, -1, -1);
  +                            fDocumentTypeIndex = fDeferredDocumentImpl.createDocumentType(elementQName.rawname, -1, -1);
                               fDeferredDocumentImpl.appendChild(0, fDocumentTypeIndex);
                           }
   
  @@ -1004,6 +1011,7 @@
                           copyInto(schema, fDocumentTypeIndex);
                       }
                   }
  +              */
               }
           }
   
  @@ -1014,12 +1022,13 @@
               try { nsEnabled = getNamespaces(); }
               catch (SAXException s) {}
   
  -            String elementName = fStringPool.toString(elementTypeIndex);
  +            String elementName = fStringPool.toString(elementQName.rawname);
               Element e;
               if (nsEnabled) {
                   e = fDocument.createElementNS(
  -                        fStringPool.toString(fStringPool.getURIForQName(elementTypeIndex)),
  -                        fStringPool.toString(elementTypeIndex)
  +                        // REVISIT: Make sure uri is filled in by caller.
  +                        fStringPool.toString(elementQName.uri),
  +                        fStringPool.toString(elementQName.localpart)
                       );
               } else {
                   e = fDocument.createElement(elementName);
  @@ -1029,13 +1038,13 @@
                   if (nsEnabled) {
                       int attName = xmlAttrList.getAttrName(attrHandle);
                       String attNameStr = fStringPool.toString(attName);
  -		    int nsURIIndex = fStringPool.getURIForQName(attName);
  +		    int nsURIIndex = xmlAttrList.getAttrURI(attrHandle);
   		    String namespaceURI = fStringPool.toString(nsURIIndex);
   		    // DOM Level 2 wants all namespace declaration attributes
   		    // to be bound to "http://www.w3.org/2000/xmlns/"
   		    // So as long as the XML parser doesn't do it, it needs to
   		    // done here.
  -		    int prefixIndex = fStringPool.getPrefixForQName(attName);
  +		    int prefixIndex = xmlAttrList.getAttrPrefix(attrHandle);
   		    String prefix = fStringPool.toString(prefixIndex);
   		    if (namespaceURI == null) {
   			if (prefix != null) {
  @@ -1048,13 +1057,15 @@
   		    }
                       e.setAttributeNS(namespaceURI,
   				     attNameStr,
  -                                     fStringPool.toString(xmlAttrList.getAttValue(attrHandle)));
  +                                     xmlAttrList.getValue(attrHandle));
                   } else {
                       String attrName = fStringPool.toString(xmlAttrList.getAttrName(attrHandle));
                       String attrValue = fStringPool.toString(xmlAttrList.getAttValue(attrHandle));
                       e.setAttribute(attrName, attrValue);
  -                    if (fDocumentImpl != null && !xmlAttrList.isSpecified(attrHandle)) {
  -                        ((AttrImpl)e.getAttributeNode(attrName)).setSpecified(false);
  +                    if (fDocumentImpl != null
  +                        && !xmlAttrList.isSpecified(attrHandle)) {
  +                        ((AttrImpl)e.getAttributeNode(attrName))
  +                            .setSpecified(false);
                       }
                   }
                   attrHandle = xmlAttrList.getNextAttr(attrHandle);
  @@ -1080,7 +1091,8 @@
               // copy schema grammar, if needed
               if (!fSeenRootElement) {
                   fSeenRootElement = true;
  -                if (fDocumentImpl != null && fGrammarAccess) {
  +                /* REVISIT Grammar Access
  +                if (fDocumentImpl != null && fGrammarAccess)  {
                       Document schemaDocument = fValidator.getSchemaDocument();
                       if (schemaDocument != null) {
                           if (fDocumentType == null) {
  @@ -1095,13 +1107,14 @@
                           XUtil.copyInto(schema, fDocumentType);
                       }
                   }
  +               */
               }
           }
   
  -    } // startElement(int,XMLAttrList,int)
  +    } // startElement(QName,XMLAttrList,int)
   
       /** End element. */
  -    public void endElement(int elementTypeIndex)
  +    public void endElement(QName elementQName)
           throws Exception {
   
           // deferred node expansion
  @@ -1116,7 +1129,7 @@
               fWithinElement = false;
           }
   
  -    } // endElement(int)
  +    } // endElement(QName)
   
       /** Characters. */
       public void characters(int dataIndex)
  @@ -1441,18 +1454,20 @@
        *  This function will be called when a &lt;!DOCTYPE...&gt; declaration is
        *  encountered.
        */
  -    public void startDTD(int rootElementType, int publicId, int systemId)
  +    public void startDTD(QName rootElement, int publicId, int systemId)
           throws Exception {
   
           // full expansion
           if (fDocumentImpl != null) {
  -            String rootElementName = fStringPool.toString(rootElementType);
  +            String rootElementName = fStringPool.toString(rootElement.rawname);
               String publicString = fStringPool.toString(publicId);
               String systemString = fStringPool.toString(systemId);
               fDocumentType = fDocumentImpl.
                   createDocumentType(rootElementName, publicString, systemString);
               fDocumentImpl.appendChild(fDocumentType);
   
  +            /*  TODO - Grammar Access revisit
  +
               if (fGrammarAccess) {
                   Element schema = fDocument.createElement("schema");
                   // REVISIT: What should the namespace be? -Ac
  @@ -1463,16 +1478,18 @@
                   schema.setAttribute("exactDefault", "");
                   ((AttrImpl)schema.getAttributeNode("exactDefault")).setSpecified(false);
                   fDocumentType.appendChild(schema);
  -            }
  +            } */
  +
           }
   
           // deferred expansion
           else if (fDeferredDocumentImpl != null) {
               fDocumentTypeIndex =
                   fDeferredDocumentImpl.
  -                    createDocumentType(rootElementType, publicId, systemId);
  +                    createDocumentType(rootElement.rawname, publicId, systemId);
               fDeferredDocumentImpl.appendChild(fDocumentIndex, fDocumentTypeIndex);
   
  +            /*REVISIT - Grammar Access
               if (fGrammarAccess) {
                   int handle = fAttrList.startAttrList();
                   fAttrList.addAttr(
  @@ -1498,6 +1515,7 @@
                   // REVISIT: What should the namespace be? -Ac
                   fDeferredDocumentImpl.appendChild(fDocumentTypeIndex, schemaIndex);
               }
  +            */
           }
   
       } // startDTD(int,int,int)
  @@ -1531,19 +1549,19 @@
       /**
        * &lt;!ELEMENT Name contentspec&gt;
        */
  -    public void elementDecl(int elementTypeIndex, XMLContentSpec contentSpec)
  +    public void elementDecl(QName elementDecl, XMLContentSpec contentSpec)
           throws Exception {
   
           if (DEBUG_ATTLIST_DECL) {
               String contentModel = contentSpec.toString();
  -            System.out.println("elementDecl(" + fStringPool.toString(elementTypeIndex) + ", " +
  +            System.out.println("elementDecl(" + fStringPool.toString(elementDecl.rawname) + ", " +
                                                   contentModel + ")");
           }
   
           //
           // Create element declaration
           //
  -
  +        /*REVISIT  Grammar Access
           if (fGrammarAccess) {
   
               if (fDeferredDocumentImpl != null) {
  @@ -1554,7 +1572,7 @@
   
                   // get element declaration; create if necessary
                   int schemaIndex = getLastChildElement(fDocumentTypeIndex, "schema");
  -                String elementName = fStringPool.toString(elementTypeIndex);
  +                String elementName = fStringPool.toString(elementDecl.rawname);
                   int elementIndex = getLastChildElement(schemaIndex, "element", "name", elementName);
                   if (elementIndex == -1) {
                       int handle = fAttrList.startAttrList();
  @@ -1693,7 +1711,7 @@
   
                   // get element declaration; create if necessary
                   Element schema = XUtil.getFirstChildElement(fDocumentType, "schema");
  -                String elementName = fStringPool.toString(elementTypeIndex);
  +                String elementName = fStringPool.toString(elementDecl.rawname);
                   Element element = XUtil.getFirstChildElement(schema, "element", "name", elementName);
                   if (element == null) {
                       element = fDocument.createElement("element");
  @@ -1790,21 +1808,21 @@
               } // if NOT defer-node-expansion
   
           } // if grammar-access
  +       */
   
       } // elementDecl(int,String)
   
       /**
        * &lt;!ATTLIST Name AttDef&gt;
        */
  -    public void attlistDecl(int elementTypeIndex,
  -                            int attrNameIndex, int attType,
  -                            String enumString,
  +    public void attlistDecl(QName elementDecl, QName attributeDecl, 
  +                            int attType, String enumString,
                               int attDefaultType, int attDefaultValue)
           throws Exception {
   
           if (DEBUG_ATTLIST_DECL) {
  -            System.out.println("attlistDecl(" + fStringPool.toString(elementTypeIndex) + ", " +
  -                                                fStringPool.toString(attrNameIndex) + ", " +
  +            System.out.println("attlistDecl(" + fStringPool.toString(elementDecl.rawname) + ", " +
  +                                                fStringPool.toString(attributeDecl.rawname) + ", " +
                                                   fStringPool.toString(attType) + ", " +
                                                   enumString + ", " +
                                                   fStringPool.toString(attDefaultType) + ", " +
  @@ -1822,16 +1840,20 @@
                   }
   
                   // get element definition
  -                int elementDefIndex  = fDeferredDocumentImpl.lookupElementDefinition(elementTypeIndex);
  +                int elementDefIndex  = fDeferredDocumentImpl.lookupElementDefinition(elementDecl.rawname);
   
                   // create element definition if not already there
                   if (elementDefIndex == -1) {
  -                    elementDefIndex = fDeferredDocumentImpl.createElementDefinition(elementTypeIndex);
  +                    elementDefIndex = fDeferredDocumentImpl.createElementDefinition(elementDecl.rawname);
                       fDeferredDocumentImpl.appendChild(fDocumentTypeIndex, elementDefIndex);
                   }
   
                   // add default attribute
  -                int attrIndex = fDeferredDocumentImpl.createAttribute(attrNameIndex, attDefaultValue, false);
  +                int attrIndex =
  +                   fDeferredDocumentImpl.createAttribute(attributeDecl.rawname,
  +                                                         attributeDecl.uri,
  +                                                         attDefaultValue,
  +                                                         false);
                   fDeferredDocumentImpl.appendChild(elementDefIndex, attrIndex);
   
               }
  @@ -1839,12 +1861,12 @@
               //
               // Create attribute declaration
               //
  -
  +            /*REVISIT- Grammar Access
               if (fGrammarAccess) {
   
                   // get element declaration; create it if necessary
                   int schemaIndex = getLastChildElement(fDocumentTypeIndex, "schema");
  -                String elementName = fStringPool.toString(elementTypeIndex);
  +                String elementName = fStringPool.toString(elementDecl.rawname);
                   int elementIndex = getLastChildElement(schemaIndex, "element", "name", elementName);
                   if (elementIndex == -1) {
                       int handle = fAttrList.startAttrList();
  @@ -1873,7 +1895,7 @@
                   }
   
                   // create attribute and set its attributes
  -                String attributeName = fStringPool.toString(attrNameIndex);
  +                String attributeName = fStringPool.toString(attributeDecl.rawname);
                   int attributeIndex = getLastChildElement(elementIndex, "attribute", "name", attributeName);
                   if (attributeIndex == -1) {
                       int handle = fAttrList.startAttrList();
  @@ -1891,6 +1913,7 @@
                           true,
                           false); // search
                       /***/
  +            /*
                       fAttrList.addAttr(
                           fStringPool.addSymbol("minOccurs"),
                           fStringPool.addString("0"),
  @@ -1969,6 +1992,7 @@
                       }
                   }
               }
  +            */
   
           }
   
  @@ -1983,7 +2007,7 @@
                   }
   
                   // get element name
  -                String elementName = fStringPool.toString(elementTypeIndex);
  +                String elementName = fStringPool.toString(elementDecl.rawname);
   
                   // get element definition node
                   NamedNodeMap elements = ((DocumentTypeImpl)fDocumentType).getElements();
  @@ -1994,9 +2018,10 @@
                   }
   
                   // REVISIT: Check for uniqueness of element name? -Ac
  +                // REVISIT: what about default attributes with URI? -ALH
   
                   // get attribute name and value index
  -                String attrName      = fStringPool.toString(attrNameIndex);
  +                String attrName      = fStringPool.toString(attributeDecl.rawname);
                   String attrValue     = fStringPool.toString(attDefaultValue);
   
                   // create attribute and set properties
  @@ -2011,12 +2036,12 @@
               //
               // Create attribute declaration
               //
  -
  +            /*REVISIT  Grammar Access
               if (fGrammarAccess) {
   
                   // get element declaration; create it if necessary
                   Element schema = XUtil.getFirstChildElement(fDocumentType, "schema");
  -                String elementName = fStringPool.toString(elementTypeIndex);
  +                String elementName = fStringPool.toString(elementDecl.rawname);
                   Element element = XUtil.getFirstChildElement(schema, "element", "name", elementName);
                   if (element == null) {
                       element = fDocument.createElement("element");
  @@ -2035,7 +2060,7 @@
                   }
   
                   // create attribute and set its attributes
  -                String attributeName = fStringPool.toString(attrNameIndex);
  +                String attributeName = fStringPool.toString(attributeDecl.rawname);
                   Element attribute = XUtil.getFirstChildElement(element, "attribute", "name", attributeName);
                   if (attribute == null) {
                       attribute = fDocument.createElement("attribute");
  @@ -2091,6 +2116,7 @@
                       }
                   }
               }
  +           */
   
           } // if NOT defer-node-expansion
   
  @@ -2415,6 +2441,7 @@
               fDeferredDocumentImpl.appendChild(fDocumentTypeIndex, newNotationIndex);
   
               // create notation declaration
  +            /*REVISIT  Grammar Access
               if (fGrammarAccess) {
                   int schemaIndex = getLastChildElement(fDocumentTypeIndex, "schema");
                   String notationName = fStringPool.toString(notationNameIndex);
  @@ -2435,6 +2462,7 @@
                           false,
                           false); // search
                       /***/
  +            /*
                       if (publicIdIndex == -1) {
                           publicIdIndex = 0; // empty string in string pool
                       }
  @@ -2457,6 +2485,7 @@
                       fDeferredDocumentImpl.appendChild(schemaIndex, notationIndex);
                   }
               }
  +            */
           }
   
           // full expansion
  @@ -2478,6 +2507,7 @@
               fDocumentType.getNotations().setNamedItem(notationImpl);
   
               // create notation declaration
  +            /*REVISIT Grammar access
               if (fGrammarAccess) {
                   Element schema = XUtil.getFirstChildElement(fDocumentType, "schema");
                   Element notation = XUtil.getFirstChildElement(schema, "notation", "name", notationName);
  @@ -2496,6 +2526,7 @@
                       schema.appendChild(notation);
                   }
               }
  +            */
           }
   
       } // notationDecl(int,int,int)
  @@ -2510,6 +2541,7 @@
        * containing element, even when the content model contains a
        * single element reference.
        */
  +    /*REVISIT Grammar access
       private Element createContentModel(XMLContentSpec contentSpec, XMLContentSpec.Node node) {
   
           Element model = createContentModel(contentSpec, node, 
  @@ -2518,10 +2550,13 @@
   
       } // createContentModel(XMLContentSpec.Node):Element
   
  +    */
  +
       /**
        * This is the real <em>createContentModel</em> method. This is a
        * recursive solution.
        */
  +    /*REVISIT Grammar Access
       private Element createContentModel(XMLContentSpec contentSpec,
                                          XMLContentSpec.Node node, 
                                          Document factory, 
  @@ -2622,6 +2657,7 @@
   
       } // createContentModel(XMLContentSpec.Node,Element):Element
   
  +      */
       /**
        * Sets the appropriate occurrence count attributes on the specified
        * model element.
  
  
  
  1.11      +27 -26    xml-xerces/java/src/org/apache/xerces/parsers/SAXParser.java
  
  Index: SAXParser.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/parsers/SAXParser.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- SAXParser.java	2000/04/04 21:14:23	1.10
  +++ SAXParser.java	2000/05/17 18:32:34	1.11
  @@ -62,6 +62,7 @@
   import org.apache.xerces.framework.XMLDocumentHandler;
   import org.apache.xerces.framework.XMLParser;
   import org.apache.xerces.readers.XMLEntityHandler;
  +import org.apache.xerces.utils.QName;
   import org.apache.xerces.utils.StringPool;
   
   import org.xml.sax.Attributes;
  @@ -85,7 +86,7 @@
    * SAXParser provides a parser which implements the SAX1 and SAX2
    * parser APIs.
    *
  - * @version $Id: SAXParser.java,v 1.10 2000/04/04 21:14:23 andyc Exp $
  + * @version $Id: SAXParser.java,v 1.11 2000/05/17 18:32:34 jeffreyr Exp $
    */
   public class SAXParser
       extends XMLParser
  @@ -893,11 +894,11 @@
        * This function will be called when a &lt;!DOCTYPE...&gt; declaration is
        * encountered.
        */
  -    public void startDTD(int rootElementType, int publicId, int systemId) throws Exception {
  +    public void startDTD(QName rootElement, int publicId, int systemId) throws Exception {
           if (fLexicalHandler != null || DEBUG_CALLBACKS) {
   
               // strings
  -            String name = fStringPool.toString(rootElementType);
  +            String name = fStringPool.toString(rootElement.rawname);
               String pubid = fStringPool.toString(publicId);
               String sysid = fStringPool.toString(systemId);
   
  @@ -935,12 +936,12 @@
        * @param model The content model as a normalized string.
        * @exception SAXException The application may raise an exception.
        */
  -    public void elementDecl(int elementType, XMLContentSpec contentSpec) throws Exception {
  +    public void elementDecl(QName elementDecl, XMLContentSpec contentSpec) throws Exception {
   
           if (fDeclHandler != null || DEBUG_CALLBACKS) {
   
               // strings
  -            String name = fStringPool.toString(elementType);
  +            String name = fStringPool.toString(elementDecl.rawname);
               String contentModel = contentSpec.toString();
   
               // perform callback
  @@ -973,18 +974,16 @@
        *        or null if there is none.
        * @exception SAXException The application may raise an exception.
        */
  -    public void attlistDecl(int elementTypeIndex,
  -                            int attrNameIndex,
  -                            int attType,
  -                            String enumString,
  +    public void attlistDecl(QName elementDecl, QName attributeDecl,
  +                            int attType, String enumString,
                               int attDefaultType,
                               int attDefaultValue) throws Exception
       {
           if (fDeclHandler != null || DEBUG_CALLBACKS) {
   
               // strings
  -            String eName = fStringPool.toString(elementTypeIndex);
  -            String aName = fStringPool.toString(attrNameIndex);
  +            String eName = fStringPool.toString(elementDecl.rawname);
  +            String aName = fStringPool.toString(attributeDecl.rawname);
               String aType;
               if (attType == fStringPool.addSymbol("ENUMERATION"))
                   aType = enumString;
  @@ -1272,11 +1271,12 @@
       }
   
       /** Start element */
  -    public void startElement(int elementType, XMLAttrList attrList, int attrListIndex)
  +    public void startElement(QName element, 
  +                             XMLAttrList attrList, int attrListIndex)
           throws Exception {
   
           // parameters
  -        String name = fStringPool.toString(elementType);
  +        String name = fStringPool.toString(element.rawname);
           AttributeList attrs = attrList.getAttributeList(attrListIndex);
   
           // perform callback
  @@ -1292,10 +1292,10 @@
           }
           if (fContentHandler != null) {
               boolean namespaces = getNamespaces();
  -            int uriIndex = fStringPool.getURIForQName(elementType);
  +            int uriIndex = element.uri;
               String uri = uriIndex != -1 && namespaces
                          ? fStringPool.toString(uriIndex) : "";
  -            int localIndex = fStringPool.getLocalPartForQName(elementType);
  +            int localIndex = element.localpart;
               String local = localIndex != -1 && namespaces
                            ? fStringPool.toString(localIndex) : "";
               String raw = name;
  @@ -1304,16 +1304,17 @@
                    attrIndex != -1; 
                    attrIndex = attrList.getNextAttr(attrIndex)) {
                   int attrNameIndex = attrList.getAttrName(attrIndex);
  -                int attrUriIndex = fStringPool.getURIForQName(attrNameIndex);
  +                int attrUriIndex = attrList.getAttrURI(attrIndex);
                   String attrUri = attrUriIndex != -1 && namespaces
                                  ? fStringPool.toString(attrUriIndex) : "";
  -                int attrLocalIndex = fStringPool.getLocalPartForQName(attrNameIndex);
  +                int attrLocalIndex = attrList.getAttrLocalpart(attrIndex);
                   String attrLocal = attrLocalIndex != -1 && namespaces
                                    ? fStringPool.toString(attrLocalIndex) : "";
                   String attrRaw = fStringPool.toString(attrNameIndex);
                   String attrType = fStringPool.toString(attrList.getAttType(attrIndex));
                   String attrValue = fStringPool.toString(attrList.getAttValue(attrIndex));
  -                int attrPrefix = fStringPool.getPrefixForQName(attrNameIndex);
  +                //int attrPrefix = fStringPool.getPrefixForQName(attrNameIndex);
  +                int attrPrefix = attrList.getAttrPrefix(attrIndex);
                   boolean namespacePrefixes = getNamespacePrefixes();
                   if (!namespaces || namespacePrefixes || 
                       (attrPrefix != fStringPool.addSymbol("xmlns")
  @@ -1329,31 +1330,31 @@
           // free attribute list
           attrList.releaseAttrList(attrListIndex);
   
  -    } // startElement(int,int)
  +    } // startElement(QName,XMLAttrList,int)
   
       /** End element. */
  -    public void endElement(int elementType) throws Exception {
  +    public void endElement(QName element) throws Exception {
   
           // perform callback
           if (DEBUG_CALLBACKS) {
  -            System.err.println("endElement(" + fStringPool.toString(elementType) + ")");
  +            System.err.println("endElement(" + fStringPool.toString(element.rawname) + ")");
           }
           if (fDocumentHandler != null) {
  -            fDocumentHandler.endElement(fStringPool.toString(elementType));
  +            fDocumentHandler.endElement(fStringPool.toString(element.rawname));
           }
           if (fContentHandler != null) {
               boolean namespaces = getNamespaces();
  -            int uriIndex = fStringPool.getURIForQName(elementType);
  +            int uriIndex = element.uri;
               String uri = uriIndex != -1 && namespaces
                          ? fStringPool.toString(uriIndex) : "";
  -            int localIndex = fStringPool.getLocalPartForQName(elementType);
  +            int localIndex = element.localpart;
               String local = localIndex != -1 && namespaces
                            ? fStringPool.toString(localIndex) : "";
  -            String raw = fStringPool.toString(elementType);
  +            String raw = fStringPool.toString(element.rawname);
               fContentHandler.endElement(uri, local, raw);
           }
   
  -    } // endElement(int)
  +    } // endElement(QName)
   
       /** Start entity reference. */
       public void startEntityReference(int entityName, int entityType, int entityContext) throws Exception {
  
  
  
  1.4       +22 -14    xml-xerces/java/src/org/apache/xerces/readers/AbstractCharReader.java
  
  Index: AbstractCharReader.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/readers/AbstractCharReader.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- AbstractCharReader.java	2000/04/04 20:34:33	1.3
  +++ AbstractCharReader.java	2000/05/17 18:32:37	1.4
  @@ -59,6 +59,7 @@
   
   import org.apache.xerces.framework.XMLErrorReporter;
   import org.apache.xerces.utils.CharDataChunk;
  +import org.apache.xerces.utils.QName;
   import org.apache.xerces.utils.StringHasher;
   import org.apache.xerces.utils.StringPool;
   import org.apache.xerces.utils.XMLCharacterProperties;
  @@ -74,7 +75,7 @@
    * a character stream (java.io.Reader).  The UTF8CharReader performs
    * its own UTF-8 transcoding to fill in the data from an InputStream.
    *
  - * @version $Id: AbstractCharReader.java,v 1.3 2000/04/04 20:34:33 andyc Exp $
  + * @version $Id: AbstractCharReader.java,v 1.4 2000/05/17 18:32:37 jeffreyr Exp $
    */
   abstract class AbstractCharReader extends XMLEntityReader {
   
  @@ -771,20 +772,26 @@
       /**
        *
        */
  -    public int scanQName(char fastcheck) throws Exception {
  +    public void scanQName(char fastcheck, QName qname) throws Exception {
           int ch = fMostRecentChar;
           if (ch < 0x80) {
  -            if (XMLCharacterProperties.fgAsciiInitialNameChar[ch] == 0)
  -                return -1;
  -            if (ch == ':')
  -                return -1;
  +            if (XMLCharacterProperties.fgAsciiInitialNameChar[ch] == 0) {
  +                qname.clear();
  +                return;
  +            }
  +            if (ch == ':') {
  +                qname.clear();
  +                return;
  +            }
           } else {
               if (!fCalledCharPropInit) {
                   XMLCharacterProperties.initCharFlags();
                   fCalledCharPropInit = true;
               }
  -            if ((XMLCharacterProperties.fgCharFlags[ch] & XMLCharacterProperties.E_InitialNameCharFlag) == 0)
  -                return -1;
  +            if ((XMLCharacterProperties.fgCharFlags[ch] & XMLCharacterProperties.E_InitialNameCharFlag) == 0) {
  +                qname.clear();
  +                return;
  +            }
           }
           int offset = fCurrentOffset;
           int index = fCurrentIndex;
  @@ -864,11 +871,12 @@
           fMostRecentChar = ch;
           hashcode = StringHasher.finishHash(hashcode);
           int length = fCurrentOffset - offset;
  -        int nameIndex = fCurrentChunk.addSymbol(offset, length, hashcode);
  -        int prefixIndex = prefixend == -1 ? -1 : addSymbol(offset, prefixend - offset);
  -        int localpartIndex = prefixend == -1 ? nameIndex : addSymbol(prefixend + 1, fCurrentOffset - (prefixend + 1));
  -        return fStringPool.addQName(nameIndex, prefixIndex, localpartIndex);
  -    }
  +        qname.rawname = fCurrentChunk.addSymbol(offset, length, hashcode);
  +        qname.prefix = prefixend == -1 ? -1 : addSymbol(offset, prefixend - offset);
  +        qname.localpart = prefixend == -1 ? qname.rawname : addSymbol(prefixend + 1, fCurrentOffset - (prefixend + 1));
  +        qname.uri = -1;
  +
  +    } // scanQName(char,QName)
   
       //
       // [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
  @@ -876,7 +884,7 @@
       /**
        *
        */
  -    public int scanContent(int elementType) throws Exception {
  +    public int scanContent(QName element) throws Exception {
           if (fCallClearPreviousChunk && fCurrentChunk.clearPreviousChunk())
               fCallClearPreviousChunk = false;
           int charDataOffset = fCurrentOffset;
  
  
  
  1.2       +5 -4      xml-xerces/java/src/org/apache/xerces/readers/DefaultEntityHandler.java
  
  Index: DefaultEntityHandler.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/readers/DefaultEntityHandler.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- DefaultEntityHandler.java	2000/04/04 20:35:57	1.1
  +++ DefaultEntityHandler.java	2000/05/17 18:32:38	1.2
  @@ -66,6 +66,7 @@
   
   import org.apache.xerces.framework.XMLErrorReporter;
   import org.apache.xerces.utils.ImplementationMessages;
  +import org.apache.xerces.utils.QName;
   import org.apache.xerces.utils.StringPool;
   import org.apache.xerces.utils.XMLCharacterProperties;
   import org.apache.xerces.utils.XMLMessages;
  @@ -78,7 +79,7 @@
   /**
    * Default entity handler implementation.
    *
  - * @version $Id: DefaultEntityHandler.java,v 1.1 2000/04/04 20:35:57 andyc Exp $
  + * @version $Id: DefaultEntityHandler.java,v 1.2 2000/05/17 18:32:38 jeffreyr Exp $
    */
   public class DefaultEntityHandler 
       implements XMLEntityHandler, XMLEntityHandler.DTDHandler {
  @@ -1080,13 +1081,13 @@
           public boolean scanExpectedName(char fastcheck, StringPool.CharArrayRange expectedName) {
               return false;
           }
  -        public int scanQName(char fastcheck) {
  -            return -1;
  +        public void scanQName(char fastcheck, QName qname) {
  +            qname.clear();
           }
           public int scanName(char fastcheck) {
               return -1;
           }
  -        public int scanContent(int elementType) throws Exception {
  +        public int scanContent(QName element) throws Exception {
               return XMLEntityHandler.CONTENT_RESULT_INVALID_CHAR;
           }
       }
  
  
  
  1.4       +22 -14    xml-xerces/java/src/org/apache/xerces/readers/StreamingCharReader.java
  
  Index: StreamingCharReader.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/readers/StreamingCharReader.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- StreamingCharReader.java	2000/04/04 21:14:24	1.3
  +++ StreamingCharReader.java	2000/05/17 18:32:40	1.4
  @@ -59,6 +59,7 @@
   
   import org.apache.xerces.framework.XMLErrorReporter;
   import org.apache.xerces.utils.CharDataChunk;
  +import org.apache.xerces.utils.QName;
   import org.apache.xerces.utils.StringHasher;
   import org.apache.xerces.utils.StringPool;
   import org.apache.xerces.utils.XMLCharacterProperties;
  @@ -71,7 +72,7 @@
    * An reader class for applications that need to process input data as 
    * it arrives on the stream.
    * 
  - * @version $Id: StreamingCharReader.java,v 1.3 2000/04/04 21:14:24 andyc Exp $
  + * @version $Id: StreamingCharReader.java,v 1.4 2000/05/17 18:32:40 jeffreyr Exp $
    */
   public class StreamingCharReader extends XMLEntityReader {
   
  @@ -694,20 +695,26 @@
       /**
        *
        */
  -    public int scanQName(char fastcheck) throws Exception {
  +    public void scanQName(char fastcheck, QName qname) throws Exception {
           int ch = fMostRecentChar;
           if (ch < 0x80) {
  -            if (XMLCharacterProperties.fgAsciiInitialNameChar[ch] == 0)
  -                return -1;
  -            if (ch == ':')
  -                return -1;
  +            if (XMLCharacterProperties.fgAsciiInitialNameChar[ch] == 0) {
  +                qname.clear();
  +                return;
  +            }
  +            if (ch == ':') {
  +                qname.clear();
  +                return;
  +            }
           } else {
               if (!fCalledCharPropInit) {
                   XMLCharacterProperties.initCharFlags();
                   fCalledCharPropInit = true;
               }
  -            if ((XMLCharacterProperties.fgCharFlags[ch] & XMLCharacterProperties.E_InitialNameCharFlag) == 0)
  -                return -1;
  +            if ((XMLCharacterProperties.fgCharFlags[ch] & XMLCharacterProperties.E_InitialNameCharFlag) == 0) {
  +                qname.clear();
  +                return;
  +            }
           }
           int offset = fCurrentOffset;
           fCharacterCounter++;
  @@ -771,11 +778,12 @@
           }
           hashcode = StringHasher.finishHash(hashcode);
           int length = fCurrentOffset - offset;
  -        int nameIndex = fCurrentChunk.addSymbol(offset, length, hashcode);
  -        int prefixIndex = prefixend == -1 ? -1 : addSymbol(offset, prefixend - offset);
  -        int localpartIndex = prefixend == -1 ? nameIndex : addSymbol(prefixend + 1, fCurrentOffset - (prefixend + 1));
  -        return fStringPool.addQName(nameIndex, prefixIndex, localpartIndex);
  -    }
  +        qname.rawname = fCurrentChunk.addSymbol(offset, length, hashcode);
  +        qname.prefix = prefixend == -1 ? -1 : addSymbol(offset, prefixend - offset);
  +        qname.localpart = prefixend == -1 ? qname.rawname : addSymbol(prefixend + 1, fCurrentOffset - (prefixend + 1));
  +        qname.uri = -1;
  +
  +    } // scanQName(char,QName)
   
       //
       // [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
  @@ -783,7 +791,7 @@
       /**
        *
        */
  -    public int scanContent(int elementType) throws Exception {
  +    public int scanContent(QName element) throws Exception {
           if (fCallClearPreviousChunk && fCurrentChunk.clearPreviousChunk())
               fCallClearPreviousChunk = false;
           int charDataOffset = fCurrentOffset;
  
  
  
  1.5       +24 -16    xml-xerces/java/src/org/apache/xerces/readers/StringReader.java
  
  Index: StringReader.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/readers/StringReader.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- StringReader.java	2000/05/05 20:29:41	1.4
  +++ StringReader.java	2000/05/17 18:32:41	1.5
  @@ -58,6 +58,7 @@
   package org.apache.xerces.readers;
   
   import org.apache.xerces.framework.XMLErrorReporter;
  +import org.apache.xerces.utils.QName;
   import org.apache.xerces.utils.StringPool;
   import org.apache.xerces.utils.XMLCharacterProperties;
   
  @@ -79,7 +80,7 @@
    * free list and reuse those instances to process other
    * strings.
    *
  - * @version $Id: StringReader.java,v 1.4 2000/05/05 20:29:41 lehors Exp $
  + * @version $id$
    */
   final class StringReader extends XMLEntityReader {
       /**
  @@ -649,18 +650,21 @@
       //
       //
       //
  -    public int scanQName(char fastcheck) throws Exception {
  +    public void scanQName(char fastcheck, QName qname) throws Exception {
           int ch = fMostRecentChar;
           if (ch == -1) {
  -            return changeReaders().scanQName(fastcheck);
  +            changeReaders().scanQName(fastcheck, qname);
  +            return;
           }
           if (!fCalledCharPropInit) {
               XMLCharacterProperties.initCharFlags();
               fCalledCharPropInit = true;
           }
           int nameOffset = fCurrentOffset;
  -        if ((XMLCharacterProperties.fgCharFlags[ch] & XMLCharacterProperties.E_InitialNameCharFlag) == 0)
  -            return -1;
  +        if ((XMLCharacterProperties.fgCharFlags[ch] & XMLCharacterProperties.E_InitialNameCharFlag) == 0) {
  +            qname.clear();
  +            return;
  +        }
           while (true) {
               ch = loadNextChar();
               if (fastcheck == ch)
  @@ -670,13 +674,17 @@
               if ((XMLCharacterProperties.fgCharFlags[ch] & XMLCharacterProperties.E_NameCharFlag) == 0)
                   break;
           }
  -        int nameIndex = fStringPool.addSymbol(fData.substring(nameOffset, fCurrentOffset));
  +
  +        qname.clear();
  +        qname.rawname = fStringPool.addSymbol(fData.substring(nameOffset, fCurrentOffset));
           int index = fData.indexOf(':', nameOffset);
  -        int prefixIndex = index == -1 ? -1 : fStringPool.addSymbol(fData.substring(nameOffset, index));
  -        int localpartIndex = index == -1 ? nameIndex : fStringPool.addSymbol(fData.substring(index, fCurrentOffset));
  -        nameIndex = fStringPool.addQName(nameIndex, prefixIndex, localpartIndex);
  -        return nameIndex;
  -    }
  +        if (index != -1) {
  +            qname.prefix = fStringPool.addSymbol(fData.substring(nameOffset, index));
  +        }
  +        qname.localpart = fStringPool.addSymbol(fData.substring(index, fCurrentOffset));
  +
  +    } // scanQName(char,QName)
  +
       //
       //
       //
  @@ -783,10 +791,10 @@
               return XMLEntityHandler.CONTENT_RESULT_START_OF_ENTITYREF;
           }
       }
  -    public int scanContent(int elementType) throws Exception {
  +    public int scanContent(QName element) throws Exception {
           int ch = fMostRecentChar;
           if (ch == -1) {
  -            return changeReaders().scanContent(elementType);
  +            return changeReaders().scanContent(element);
           }
           int offset = fCurrentOffset;
           if (ch < 0x80) {
  @@ -821,7 +829,7 @@
                       ch = loadNextChar();
                       if (ch == -1) {
                           callCharDataHandler(offset, fEndOffset, true);
  -                        return changeReaders().scanContent(elementType);
  +                        return changeReaders().scanContent(element);
                       }
                   } while (ch == 0x20 || ch == 0x0A || ch == 0x0D || ch == 0x09);
                   if (ch < 0x80) {
  @@ -874,7 +882,7 @@
           while (true) {
               if (ch == -1) {
                   callCharDataHandler(offset, fEndOffset, false);
  -                return changeReaders().scanContent(elementType);
  +                return changeReaders().scanContent(element);
               }
               if (ch >= 0x80)
                   break;
  @@ -924,7 +932,7 @@
               }
               if (ch == -1) {
                   callCharDataHandler(offset, fCurrentOffset, false);
  -                return changeReaders().scanContent(elementType);
  +                return changeReaders().scanContent(element);
               }
           }
       }
  
  
  
  1.4       +21 -12    xml-xerces/java/src/org/apache/xerces/readers/UCSReader.java
  
  Index: UCSReader.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/readers/UCSReader.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- UCSReader.java	2000/04/04 21:14:24	1.3
  +++ UCSReader.java	2000/05/17 18:32:41	1.4
  @@ -60,6 +60,7 @@
   import org.apache.xerces.framework.XMLErrorReporter;
   import org.apache.xerces.utils.ChunkyByteArray;
   import org.apache.xerces.utils.ChunkyCharArray;
  +import org.apache.xerces.utils.QName;
   import org.apache.xerces.utils.StringHasher;
   import org.apache.xerces.utils.StringPool;
   import org.apache.xerces.utils.XMLCharacterProperties;
  @@ -74,7 +75,7 @@
    * could take advantage of the system design to improve performance and reduce
    * resource consumption, but the actual performance tuning remains to be done.
    *
  - * @version $Id: UCSReader.java,v 1.3 2000/04/04 21:14:24 andyc Exp $
  + * @version $Id: UCSReader.java,v 1.4 2000/05/17 18:32:41 jeffreyr Exp $
    */
   final class UCSReader extends XMLEntityReader implements StringPool.StringProducer {
   
  @@ -656,16 +657,24 @@
           // DEFECT !! check name against expected name
           return true;
       }
  -    public int scanQName(char fastcheck) throws Exception {
  -        // DEFECT !! no code
  +
  +    public void scanQName(char fastcheck, QName qname) throws Exception {
  +
  +        // DEFECT !! no code // Defect #126
           int nameOffset = fCurrentOffset;
           skipPastName(fastcheck);
           int nameLength = fCurrentOffset - nameOffset;
  -        if (nameLength == 0)
  -            return -1;
  -        int nameIndex = addSymbol(nameOffset, nameLength);
  -        return nameIndex;
  -    }
  +        if (nameLength == 0) {
  +            qname.clear();
  +            return;
  +        }
  +        qname.prefix = -1;
  +        qname.localpart = -1;
  +        qname.rawname = addSymbol(nameOffset, nameLength);
  +        qname.uri = -1;
  +
  +    } // scanQName(char,QName)
  +
       public int scanName(char fastcheck) throws Exception {
           int nameOffset = fCurrentOffset;
           skipPastName(fastcheck);
  @@ -759,7 +768,7 @@
               return XMLEntityHandler.CONTENT_RESULT_START_OF_ENTITYREF;
           }
       }
  -    public int scanContent(int elementType) throws Exception {
  +    public int scanContent(QName element) throws Exception {
           int offset = fCurrentOffset;
           int ch = getChar(fCurrentOffset);
           fCurrentOffset += fBytesPerChar;
  @@ -771,7 +780,7 @@
           if (ch < 0x80) {
               if (ch == -1) {
                   fCurrentOffset -= fBytesPerChar;
  -                return changeReaders().scanContent(elementType); // REVISIT - not quite...
  +                return changeReaders().scanContent(element); // REVISIT - not quite...
               }
               prop = XMLCharacterProperties.fgCharFlags[ch];
               if ((prop & XMLCharacterProperties.E_CharDataFlag) == 0 && ch != 0x0A && ch != 0x0D) {
  @@ -813,7 +822,7 @@
                       if (ch == -1) {
                           fCurrentOffset -= fBytesPerChar;
                           callCharDataHandler(offset, fCurrentOffset - offset, true);
  -                        return changeReaders().scanContent(elementType); // REVISIT - not quite...
  +                        return changeReaders().scanContent(element); // REVISIT - not quite...
                       }
                       prop = XMLCharacterProperties.fgCharFlags[ch];
                       if ((prop & XMLCharacterProperties.E_CharDataFlag) == 0) {
  @@ -886,7 +895,7 @@
                   if (ch == -1) {
                       fCurrentOffset -= fBytesPerChar;
                       callCharDataHandler(offset, fCurrentOffset - offset, false);
  -                    return changeReaders().scanContent(elementType); // REVISIT - not quite...
  +                    return changeReaders().scanContent(element); // REVISIT - not quite...
                   }
                   prop = XMLCharacterProperties.fgCharFlags[ch];
                   if ((prop & XMLCharacterProperties.E_CharDataFlag) == 0) {
  
  
  
  1.5       +30 -20    xml-xerces/java/src/org/apache/xerces/readers/UTF8Reader.java
  
  Index: UTF8Reader.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/readers/UTF8Reader.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- UTF8Reader.java	2000/04/04 21:14:24	1.4
  +++ UTF8Reader.java	2000/05/17 18:32:41	1.5
  @@ -58,6 +58,7 @@
   package org.apache.xerces.readers;
   
   import org.apache.xerces.framework.XMLErrorReporter;
  +import org.apache.xerces.utils.QName;
   import org.apache.xerces.utils.StringPool;
   import org.apache.xerces.utils.SymbolCache;
   import org.apache.xerces.utils.UTF8DataChunk;
  @@ -87,7 +88,7 @@
    * the SUN java runtime compiler (JIT) and the code here has been
    * carefully "crafted" to avoid those problems.
    * 
  - * @version $Id: UTF8Reader.java,v 1.4 2000/04/04 21:14:24 andyc Exp $
  + * @version $Id: UTF8Reader.java,v 1.5 2000/05/17 18:32:41 jeffreyr Exp $
    */
   final class UTF8Reader extends XMLEntityReader {
       //
  @@ -1287,20 +1288,28 @@
           skipPastNmtoken(fastcheck);
           return false;
       }
  -    public int scanQName(char fastcheck) throws Exception {
  +
  +    public void scanQName(char fastcheck, QName qname) throws Exception {
  +
           int ch = fMostRecentByte;
           if (ch < 0x80) {
  -            if (XMLCharacterProperties.fgAsciiInitialNameChar[ch] == 0)
  -                return -1;
  -            if (ch == ':')
  -                return -1;
  +            if (XMLCharacterProperties.fgAsciiInitialNameChar[ch] == 0) {
  +                qname.clear();
  +                return;
  +            }
  +            if (ch == ':') {
  +                qname.clear();
  +                return;
  +            }
           } else {
               if (!fCalledCharPropInit) {
                   XMLCharacterProperties.initCharFlags();
                   fCalledCharPropInit = true;
               }
  -            if ((XMLCharacterProperties.fgCharFlags[ch] & XMLCharacterProperties.E_InitialNameCharFlag) == 0)
  -                return -1;
  +            if ((XMLCharacterProperties.fgCharFlags[ch] & XMLCharacterProperties.E_InitialNameCharFlag) == 0) {
  +                qname.clear();
  +                return;
  +            }
           }
           int offset = fCurrentOffset;
           int index = fCurrentIndex;
  @@ -1373,12 +1382,13 @@
           fCurrentIndex = index;
           fMostRecentByte = ch;
           int length = fCurrentOffset - offset;
  -        int nameIndex = addSymbol(offset, length);
  -        int prefixIndex = prefixend == -1 ? -1 : addSymbol(offset, prefixend - offset);
  -        int localpartIndex = prefixend == -1 ? nameIndex : addSymbol(prefixend + 1, fCurrentOffset - (prefixend + 1));
  -        nameIndex = fStringPool.addQName(nameIndex, prefixIndex, localpartIndex);
  -        return nameIndex;
  -    }
  +        qname.rawname = addSymbol(offset, length);
  +        qname.prefix = prefixend == -1 ? -1 : addSymbol(offset, prefixend - offset);
  +        qname.localpart = prefixend == -1 ? qname.rawname : addSymbol(prefixend + 1, fCurrentOffset - (prefixend + 1));
  +        qname.uri = -1;
  +
  +    } // scanQName(char,QName)
  +
       private int getMultiByteSymbolChar(int b0) throws Exception {
           //
           // REVISIT - optimize this with in-buffer lookahead.
  @@ -1804,7 +1814,7 @@
       //
       // [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
       //
  -    private int recognizeMarkup(int b0, int elementType) throws Exception {
  +    private int recognizeMarkup(int b0, QName element) throws Exception {
           switch (b0) {
           case 0:
               return XMLEntityHandler.CONTENT_RESULT_MARKUP_END_OF_INPUT;
  @@ -1873,7 +1883,7 @@
                           b0 = (fMostRecentByte = fMostRecentData[fCurrentIndex] & 0xFF);
                   }
               }
  -            int expectedName = elementType;
  +            int expectedName = element.rawname;
               fStringPool.getCharArrayRange(expectedName, fCharArrayRange);
               char[] expected = fCharArrayRange.chars;
               int offset = fCharArrayRange.offset;
  @@ -2027,7 +2037,7 @@
               return XMLEntityHandler.CONTENT_RESULT_START_OF_ENTITYREF;
           }
       }
  -    public int scanContent(int elementType) throws Exception {
  +    public int scanContent(QName element) throws Exception {
           if (fCallClearPreviousChunk && fCurrentChunk.clearPreviousChunk())
               fCallClearPreviousChunk = false;
           fCharDataLength = 0;
  @@ -2085,7 +2095,7 @@
                       }
                   }
                   if (!fInCDSect) {
  -                    return recognizeMarkup(ch, elementType);
  +                    return recognizeMarkup(ch, element);
                   }
                   if (fSendCharDataAsCharArray)
                       appendCharData('<');
  @@ -2238,7 +2248,7 @@
                                           ch = (fMostRecentByte = fMostRecentData[fCurrentIndex] & 0xFF);
                                   }
                               }
  -                            return recognizeMarkup(ch, elementType);
  +                            return recognizeMarkup(ch, element);
                           }
                           if (fSendCharDataAsCharArray)
                               appendCharData('<');
  @@ -2367,7 +2377,7 @@
                                       ch = (fMostRecentByte = fMostRecentData[fCurrentIndex] & 0xFF);
                               }
                           }
  -                        return recognizeMarkup(ch, elementType);
  +                        return recognizeMarkup(ch, element);
                       }
                       if (fSendCharDataAsCharArray)
                           appendCharData('<');
  
  
  
  1.4       +3 -2      xml-xerces/java/src/org/apache/xerces/readers/UTF8Recognizer.java
  
  Index: UTF8Recognizer.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/readers/UTF8Recognizer.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- UTF8Recognizer.java	2000/02/08 02:43:57	1.3
  +++ UTF8Recognizer.java	2000/05/17 18:32:42	1.4
  @@ -59,6 +59,7 @@
   
   import org.apache.xerces.framework.XMLErrorReporter;
   import org.apache.xerces.utils.ChunkyByteArray;
  +import org.apache.xerces.utils.QName;
   import org.apache.xerces.utils.StringPool;
   
   import java.io.InputStreamReader;
  @@ -247,13 +248,13 @@
           public boolean scanExpectedName(char fastcheck, StringPool.CharArrayRange expectedName) throws IOException {
               throw new IOException("RDR002 cannot happen");
           }
  -        public int scanQName(char fastcheck) throws IOException {
  +        public void scanQName(char fastcheck, QName qname) throws IOException {
               throw new IOException("RDR002 cannot happen");
           }
           public int scanName(char fastcheck) throws IOException {
               throw new IOException("RDR002 cannot happen");
           }
  -        public int scanContent(int elementType) throws IOException {
  +        public int scanContent(QName element) throws IOException {
               throw new IOException("RDR002 cannot happen");
           }
       }
  
  
  
  1.3       +6 -3      xml-xerces/java/src/org/apache/xerces/readers/XMLEntityHandler.java
  
  Index: XMLEntityHandler.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/readers/XMLEntityHandler.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- XMLEntityHandler.java	2000/04/04 21:14:25	1.2
  +++ XMLEntityHandler.java	2000/05/17 18:32:44	1.3
  @@ -58,6 +58,7 @@
   package org.apache.xerces.readers;
   
   import org.apache.xerces.framework.XMLErrorReporter;
  +import org.apache.xerces.utils.QName;
   import org.apache.xerces.utils.StringPool;
   import org.xml.sax.EntityResolver;
   import org.xml.sax.InputSource;
  @@ -69,7 +70,7 @@
    * is typically implemented by the "parser" class to provide entity
    * management services for the scanner classes.
    *
  - * @version $Id: XMLEntityHandler.java,v 1.2 2000/04/04 21:14:25 andyc Exp $
  + * @version $Id: XMLEntityHandler.java,v 1.3 2000/05/17 18:32:44 jeffreyr Exp $
    */
   public interface XMLEntityHandler extends Locator {
   
  @@ -639,11 +640,13 @@
            *
            * @param fastcheck A character that is not a legal name character that is provided as a
            *                  hint to the reader of a character likely to terminate the Name.
  +         * <!--
            * @return The <code>StringPool</code> handle for the QName that was scanned,
            *         or -1 if a name was not found at the current position within the input data.
  +         * -->
            * @exception java.lang.Exception
            */
  -        public int scanQName(char fastcheck) throws Exception;
  +        public void scanQName(char fastcheck, QName qname) throws Exception;
   
           /**
            * Skip through the input while we are looking at character data.
  @@ -666,6 +669,6 @@
            *   CONTENT_RESULT_REFERENCE_END_OF_INPUT
            * @exception java.lang.Exception
            */
  -        public int scanContent(int elementType) throws Exception;
  +        public int scanContent(QName element) throws Exception;
       }
   }
  
  
  
  1.2       +6 -2      xml-xerces/java/src/org/apache/xerces/utils/Base64.java
  
  Index: Base64.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/utils/Base64.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- Base64.java	2000/04/04 19:32:51	1.1
  +++ Base64.java	2000/05/17 18:32:51	1.2
  @@ -116,14 +116,18 @@
   
       }
   
  +    public static boolean isBase64( String isValidString ){
  +        return( isArrayByteBase64( isValidString.getBytes()));
  +    }
  +
   
  -    static boolean isBase64( byte octect ) {
  +    public static boolean isBase64( byte octect ) {
           //shall we ignore white space? JEFF??
           return(octect == PAD || base64Alphabet[octect] != -1 ); 
       }
   
   
  -    static boolean isArrayByteBase64( byte[] arrayOctect ) {
  +    public static boolean isArrayByteBase64( byte[] arrayOctect ) {
           int length = arrayOctect.length;
           if ( length == 0 )
               return false;
  
  
  
  1.5       +2 -0      xml-xerces/java/src/org/apache/xerces/utils/Makefile
  
  Index: Makefile
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/utils/Makefile,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- Makefile	2000/04/04 18:53:00	1.4
  +++ Makefile	2000/05/17 18:32:51	1.5
  @@ -5,10 +5,12 @@
   	CharDataChunk.class\
   	ChunkyByteArray.class\
   	ChunkyCharArray.class\
  +	Hash2intTable.class\
   	HexBin.class\
   	ImplementationMessages.class\
   	ISO8601Format.class\
   	NamespacesScope.class\
  +	QName.class\
   	StringHasher.class\
   	StringPool.class\
   	SymbolCache.class\
  
  
  
  1.6       +1 -227    xml-xerces/java/src/org/apache/xerces/utils/StringPool.java
  
  Index: StringPool.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/utils/StringPool.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- StringPool.java	2000/02/08 02:47:28	1.5
  +++ StringPool.java	2000/05/17 18:32:52	1.6
  @@ -110,18 +110,7 @@
       private int[][] fOffset = new int[INITIAL_CHUNK_COUNT][];
       private int[][] fLength = new int[INITIAL_CHUNK_COUNT][];
       private int[][] fCharsOffset = new int[INITIAL_CHUNK_COUNT][];
  -    private int[][] fDeclaration = new int[INITIAL_CHUNK_COUNT][];
       //
  -    // QName arrays
  -    //
  -    private static final int QNAME_MASK = 0x60000000;
  -    private static final int QNAME_FLAG = 0x40000000;
  -    private int fQNameCount = 0;
  -    private int[][] fFullName = new int[INITIAL_CHUNK_COUNT][];
  -    private int[][] fPrefix = new int[INITIAL_CHUNK_COUNT][];
  -    private int[][] fLocalPart = new int[INITIAL_CHUNK_COUNT][];
  -    private int[][] fURI = new int[INITIAL_CHUNK_COUNT][];
  -    //
       // String Lists
       //
       private int fStringListCount = 0;
  @@ -165,7 +154,6 @@
               fSymbolTable[i] = null;
           fStringCount = 0;
           fStringFreeList = -1;
  -        fQNameCount = 0;
           fStringListCount = 0;
           fActiveStringList = -1;
           fSymbolCache.reset();
  @@ -196,9 +184,6 @@
                   newInt = new int[chunk * 2][];
                   System.arraycopy(fCharsOffset, 0, newInt, 0, chunk);
                   fCharsOffset = newInt;
  -                newInt = new int[chunk * 2][];
  -                System.arraycopy(fDeclaration, 0, newInt, 0, chunk);
  -                fDeclaration = newInt;
               } else {
                   String[] newString = new String[index * 2];
                   System.arraycopy(fString[chunk], 0, newString, 0, index);
  @@ -215,9 +200,6 @@
                   newInt = new int[index * 2];
                   System.arraycopy(fCharsOffset[chunk], 0, newInt, 0, index);
                   fCharsOffset[chunk] = newInt;
  -                newInt = new int[index * 2];
  -                System.arraycopy(fDeclaration[chunk], 0, newInt, 0, index);
  -                fDeclaration[chunk] = newInt;
                   return true;
               }
           } catch (NullPointerException ex) {
  @@ -227,7 +209,6 @@
           fOffset[chunk] = new int[INITIAL_CHUNK_SIZE];
           fLength[chunk] = new int[INITIAL_CHUNK_SIZE];
           fCharsOffset[chunk] = new int[INITIAL_CHUNK_SIZE];
  -        fDeclaration[chunk] = new int[INITIAL_CHUNK_SIZE];
           return true;
       }
       public int addString(String str) {
  @@ -250,7 +231,6 @@
           fOffset[chunk][index] = 0;
           fLength[chunk][index] = str.length();
           fCharsOffset[chunk][index] = -1;
  -        fDeclaration[chunk][index] = -1;
           if (DEBUG_ADDITIONS)
               System.err.println("addString(" + str + ") " + stringIndex);
           return stringIndex;
  @@ -276,7 +256,6 @@
           fOffset[chunk][index] = offset;
           fLength[chunk][index] = length;
           fCharsOffset[chunk][index] = -1;
  -        fDeclaration[chunk][index] = -1;
           if (DEBUG_ADDITIONS)
               System.err.println("addString(" + stringProducer.toString(offset, length) + ") " + stringIndex);
           return stringIndex;
  @@ -330,7 +309,6 @@
           fOffset[chunk][index] = -1;
           fLength[chunk][index] = slen;
           fCharsOffset[chunk][index] = startOffset;
  -        fDeclaration[chunk][index] = -1;
   
           int hashcode = StringHasher.hashString(str, slen);
           int hc = hashcode % HASHTABLE_SIZE;
  @@ -413,7 +391,6 @@
           fStringProducer[chunk][index] = null;
           fOffset[chunk][index] = -1;
           fLength[chunk][index] = slen;
  -        fDeclaration[chunk][index] = -1;
           fCharsOffset[chunk][index] = fSymbolCache.addSymbolToCache(str, slen, stringIndex);
   
           hashSymbol(bucket, hashcode, chunk, index);
  @@ -460,7 +437,6 @@
           fStringProducer[chunk][index] = null;
           fOffset[chunk][index] = -1;
           fLength[chunk][index] = slen;
  -        fDeclaration[chunk][index] = -1;
           fCharsOffset[chunk][index] = fSymbolCache.addSymbolToCache(str, slen, stringIndex);
   
           hashSymbol(bucket, hashcode, chunk, index);
  @@ -509,7 +485,6 @@
           fStringProducer[chunk][index] = null;
           fOffset[chunk][index] = -1;
           fLength[chunk][index] = slen;
  -        fDeclaration[chunk][index] = -1;
           fCharsOffset[chunk][index] = fSymbolCache.addSymbolToCache(str, slen, stringIndex);
   
           hashSymbol(bucket, hashcode, chunk, index);
  @@ -518,8 +493,6 @@
           return stringIndex;
       }
       public int addSymbol(int stringIndex) {
  -        if ((stringIndex & QNAME_MASK) == QNAME_FLAG)
  -            return stringIndex;
           if (stringIndex < 0 || stringIndex >= fStringCount)
               return -1;
           int chunk = stringIndex >> CHUNK_SHIFT;
  @@ -535,41 +508,6 @@
           }
           return addSymbol(s);
       }
  -    public void setDeclaration(int stringIndex, int decl) {
  -        if ((stringIndex & QNAME_MASK) == QNAME_FLAG) {
  -            int qnameIndex = stringIndex & (~QNAME_FLAG);
  -            if (qnameIndex < 0 || qnameIndex >= fQNameCount) {
  -                return;
  -            }
  -            int chunk = qnameIndex >> CHUNK_SHIFT;
  -            int index = qnameIndex & CHUNK_MASK;
  -            setDeclaration(fFullName[chunk][index], decl);
  -            return;
  -        }
  -        if (stringIndex < 0 || stringIndex >= fStringCount) {
  -            return;
  -        }
  -        int chunk = stringIndex >> CHUNK_SHIFT;
  -        int index = stringIndex & CHUNK_MASK;
  -        fDeclaration[chunk][index] = decl;
  -    }
  -    public int getDeclaration(int stringIndex) {
  -        if ((stringIndex & QNAME_MASK) == QNAME_FLAG) {
  -            int qnameIndex = stringIndex & (~QNAME_FLAG);
  -            if (qnameIndex < 0 || qnameIndex >= fQNameCount) {
  -                return -1;
  -            }
  -            int chunk = qnameIndex >> CHUNK_SHIFT;
  -            int index = qnameIndex & CHUNK_MASK;
  -            return getDeclaration(fFullName[chunk][index]);
  -        }
  -        if (stringIndex < 0 || stringIndex >= fStringCount) {
  -            return -1;
  -        }
  -        int chunk = stringIndex >> CHUNK_SHIFT;
  -        int index = stringIndex & CHUNK_MASK;
  -        return fDeclaration[chunk][index];
  -    }
       //
       // Get characters for defined symbols
       //
  @@ -582,19 +520,6 @@
           return new CharArrayRange();
       }
       public void getCharArrayRange(int symbolIndex, CharArrayRange r) {
  -        if ((symbolIndex & QNAME_MASK) == QNAME_FLAG) {
  -            int qnameIndex = symbolIndex & (~QNAME_FLAG);
  -            if (qnameIndex < 0 || qnameIndex >= fQNameCount) {
  -                r.chars = null;
  -                r.offset = -1;
  -                r.length = -1;
  -                return;
  -            }
  -            int chunk = qnameIndex >> CHUNK_SHIFT;
  -            int index = qnameIndex & CHUNK_MASK;
  -            getCharArrayRange(fFullName[chunk][index], r);
  -            return;
  -        }
           if (symbolIndex < 0 || symbolIndex >= fStringCount) {
               r.chars = null;
               r.offset = -1;
  @@ -607,143 +532,10 @@
           r.offset = fCharsOffset[chunk][index];
           r.length = fLength[chunk][index];
       }
  -    //
  -    // QName support
  -    //
  -    private boolean ensureQNameCapacity(int chunk, int index) {
  -        try {
  -            return fFullName[chunk][index] == 0;
  -        } catch (ArrayIndexOutOfBoundsException ex) {
  -            if (index == 0) {
  -                int[][] newInt = new int[chunk * 2][];
  -                System.arraycopy(fFullName, 0, newInt, 0, chunk);
  -                fFullName = newInt;
  -                newInt = new int[chunk * 2][];
  -                System.arraycopy(fPrefix, 0, newInt, 0, chunk);
  -                fPrefix = newInt;
  -                newInt = new int[chunk * 2][];
  -                System.arraycopy(fLocalPart, 0, newInt, 0, chunk);
  -                fLocalPart = newInt;
  -                newInt = new int[chunk * 2][];
  -                System.arraycopy(fURI, 0, newInt, 0, chunk);
  -                fURI = newInt;
  -            } else {
  -                int[] newInt = new int[index * 2];
  -                System.arraycopy(fFullName[chunk], 0, newInt, 0, index);
  -                fFullName[chunk] = newInt;
  -                newInt = new int[index * 2];
  -                System.arraycopy(fPrefix[chunk], 0, newInt, 0, index);
  -                fPrefix[chunk] = newInt;
  -                newInt = new int[index * 2];
  -                System.arraycopy(fLocalPart[chunk], 0, newInt, 0, index);
  -                fLocalPart[chunk] = newInt;
  -                newInt = new int[index * 2];
  -                System.arraycopy(fURI[chunk], 0, newInt, 0, index);
  -                fURI[chunk] = newInt;
  -                return true;
  -            }
  -        } catch (NullPointerException ex) {
  -        }
  -        fFullName[chunk] = new int[INITIAL_CHUNK_SIZE];
  -        fPrefix[chunk] = new int[INITIAL_CHUNK_SIZE];
  -        fLocalPart[chunk] = new int[INITIAL_CHUNK_SIZE];
  -        fURI[chunk] = new int[INITIAL_CHUNK_SIZE];
  -        return true;
  -    }
  -    public int addQName(int fullname, int prefix, int localpart) {
  -        int qnameIndex;
  -        int chunk;
  -        int index;
  -        qnameIndex = fQNameCount++;
  -        chunk = qnameIndex >> CHUNK_SHIFT;
  -        index = qnameIndex & CHUNK_MASK;
  -        ensureQNameCapacity(chunk, index);
  -        fFullName[chunk][index] = fullname;
  -        fPrefix[chunk][index] = prefix;
  -        fLocalPart[chunk][index] = localpart;
  -        fURI[chunk][index] = -1;
  -        if (DEBUG_ADDITIONS)
  -            System.err.println("addQName(" + toString(fullname) + ", " + toString(prefix) + ", " + toString(localpart) + ") " + qnameIndex);
  -        return qnameIndex | QNAME_FLAG;
  -    }
  -    public int getFullNameForQName(int nameIndex) {
  -        if ((nameIndex & QNAME_MASK) != QNAME_FLAG)
  -            return nameIndex;
  -        int qnameIndex = nameIndex & (~QNAME_FLAG);
  -        if (qnameIndex < 0 || qnameIndex >= fQNameCount)
  -            return -1;
  -        int chunk = qnameIndex >> CHUNK_SHIFT;
  -        int index = qnameIndex & CHUNK_MASK;
  -        return fFullName[chunk][index];
  -    }
  -    public int getPrefixForQName(int nameIndex) {
  -        if ((nameIndex & QNAME_MASK) != QNAME_FLAG)
  -            return -1;
  -        int qnameIndex = nameIndex & (~QNAME_FLAG);
  -        if (qnameIndex < 0 || qnameIndex >= fQNameCount)
  -            return -1;
  -        int chunk = qnameIndex >> CHUNK_SHIFT;
  -        int index = qnameIndex & CHUNK_MASK;
  -        return fPrefix[chunk][index];
  -    }
  -    public int getLocalPartForQName(int nameIndex) {
  -        if ((nameIndex & QNAME_MASK) != QNAME_FLAG)
  -            return nameIndex;
  -        int qnameIndex = nameIndex & (~QNAME_FLAG);
  -        if (qnameIndex < 0 || qnameIndex >= fQNameCount)
  -            return -1;
  -        int chunk = qnameIndex >> CHUNK_SHIFT;
  -        int index = qnameIndex & CHUNK_MASK;
  -        return fLocalPart[chunk][index];
  -    }
  -    public void setURIForQName(int nameIndex, int uriIndex) {
  -        if ((nameIndex & QNAME_MASK) != QNAME_FLAG)
  -            return;
  -        int qnameIndex = nameIndex & (~QNAME_FLAG);
  -        if (qnameIndex < 0 || qnameIndex >= fQNameCount)
  -            return;
  -        int chunk = qnameIndex >> CHUNK_SHIFT;
  -        int index = qnameIndex & CHUNK_MASK;
  -        fURI[chunk][index] = uriIndex;
  -    }
  -    public int getURIForQName(int nameIndex) {
  -        if ((nameIndex & QNAME_MASK) != QNAME_FLAG)
  -            return -1;
  -        int qnameIndex = nameIndex & (~QNAME_FLAG);
  -        if (qnameIndex < 0 || qnameIndex >= fQNameCount)
  -            return -1;
  -        int chunk = qnameIndex >> CHUNK_SHIFT;
  -        int index = qnameIndex & CHUNK_MASK;
  -        return fURI[chunk][index];
  -    }
  -    public boolean equalQNames(int qname1, int qname2) {
  -        if ((qname1 & QNAME_MASK) != QNAME_FLAG || (qname2 & QNAME_MASK) != QNAME_FLAG)
  -            return false;
  -        int qnameIndex = qname1 & (~QNAME_FLAG);
  -        int chunk1 = qnameIndex >> CHUNK_SHIFT;
  -        int index1 = qnameIndex & CHUNK_MASK;
  -        qnameIndex = qname2 & (~QNAME_FLAG);
  -        int chunk2 = qnameIndex >> CHUNK_SHIFT;
  -        int index2 = qnameIndex & CHUNK_MASK;
  -        return (fFullName[chunk1][index1] == fFullName[chunk2][index2]);
  -    }
       public boolean equalNames(int stringIndex1, int stringIndex2) {
           if (stringIndex1 == stringIndex2)
               return true;
  -        boolean string1isQName = (stringIndex1 & QNAME_MASK) == QNAME_FLAG;
  -        if (!string1isQName && (stringIndex2 & QNAME_MASK) != QNAME_FLAG)
  -            return false;
  -        if (string1isQName && (stringIndex2 & QNAME_MASK) == QNAME_FLAG)
  -            return equalQNames(stringIndex1, stringIndex2);
  -        int qnameIndex = stringIndex1;
  -        if (!string1isQName) {
  -            qnameIndex = stringIndex2;
  -            stringIndex2 = stringIndex1;
  -        }
  -        qnameIndex = qnameIndex & (~QNAME_FLAG);
  -        int chunk = qnameIndex >> CHUNK_SHIFT;
  -        int index = qnameIndex & CHUNK_MASK;
  -        return (fFullName[chunk][index] == stringIndex2);
  +        return false;
       }
       //
       // String list support
  @@ -855,8 +647,6 @@
       //
       //
       public void releaseString(int stringIndex) {
  -        if ((stringIndex & QNAME_MASK) == QNAME_FLAG)
  -            return;
           if (stringIndex < 0 || stringIndex >= fStringCount)
               return;
           int chunk = stringIndex >> CHUNK_SHIFT;
  @@ -878,14 +668,6 @@
               }
           }
   
  -        if ((stringIndex & QNAME_MASK) == QNAME_FLAG) {
  -            int qnameIndex = stringIndex & (~QNAME_FLAG);
  -            if (qnameIndex < 0 || qnameIndex >= fQNameCount)
  -                return null;
  -            int chunk = qnameIndex >> CHUNK_SHIFT;
  -            int index = qnameIndex & CHUNK_MASK;
  -            return toString(fFullName[chunk][index]);
  -        }
           if (stringIndex < 0 || stringIndex >= fStringCount)
               return null;
           int chunk = stringIndex >> CHUNK_SHIFT;
  @@ -903,14 +685,6 @@
       //
       //
       public String orphanString(int stringIndex) {
  -        if ((stringIndex & QNAME_MASK) == QNAME_FLAG) {
  -            int qnameIndex = stringIndex & (~QNAME_FLAG);
  -            if (qnameIndex < 0 || qnameIndex >= fQNameCount)
  -                return null;
  -            int chunk = qnameIndex >> CHUNK_SHIFT;
  -            int index = qnameIndex & CHUNK_MASK;
  -            return toString(fFullName[chunk][index]);
  -        }
           if (stringIndex < 0 || stringIndex >= fStringCount)
               return null;
           int chunk = stringIndex >> CHUNK_SHIFT;
  
  
  
  1.2       +3 -0      xml-xerces/java/src/org/apache/xerces/utils/XMLMessages.java
  
  Index: XMLMessages.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/utils/XMLMessages.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- XMLMessages.java	1999/11/09 01:12:27	1.1
  +++ XMLMessages.java	2000/05/17 18:32:52	1.2
  @@ -309,6 +309,7 @@
           MSG_PI_NOT_IN_ONE_ENTITY = 165,
           MSG_REFERENCE_UNTERMINATED = 166,
           MSG_PREFIX_DECLARED = 167,
  +        MSG_ATT_DEFAULT_INVALID = 168,
   
           // ...
           MSG_MAX_CODE = 200;
  @@ -482,6 +483,7 @@
           "PINotInOneEntity",             // 165, "MSG_PI_MUST_BEGIN_AND_END_IN_THE_SAME_ENTITY"
           "ReferenceUnterminated",        // 166, "MSG_REFERENCE_UNTERMINATED"
           "PrefixDeclared",               // 167, "MSG_PREFIX_DECLARED"
  +        "MSG_ATT_DEFAULT_INVALID",      // 168, "MSG_ATT_DEFAULT_INVALID"
   
           // ...
           ""                              //
  @@ -633,6 +635,7 @@
           P11_URI_FRAGMENT = 142,
           VC_ONE_NOTATION_PER_ELEMENT_TYPE = 143,
           NC_PREFIX_DECLARED = 144,
  +        VC_ATTRIBUTE_DEFAULT_LEGAL = 145,
   
           // ...
           CONSTRAINT_MAX_CODE = 200;
  
  
  
  1.2       +152 -0    xml-xerces/java/src/org/apache/xerces/utils/Hash2intTable.java
  
  
  
  
  1.2       +179 -0    xml-xerces/java/src/org/apache/xerces/utils/QName.java
  
  
  
  
  1.2       +9 -5      xml-xerces/java/src/org/apache/xerces/utils/regex/REUtil.java
  
  Index: REUtil.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/utils/regex/REUtil.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- REUtil.java	2000/04/04 19:31:31	1.1
  +++ REUtil.java	2000/05/17 18:32:54	1.2
  @@ -206,13 +206,17 @@
   
       /**
        * Sample entry.
  -     * <div>Usage: <KBD>com.ibm.regex.REUtil &lt;regex&gt; &lt;string&gt;</KBD></div>
  +     * <div>Usage: <KBD>org.apache.xerces.utils.regex.REUtil &lt;regex&gt; &lt;string&gt;</KBD></div>
        */
       public static void main(String[] argv) {
           String pattern = null;
           try {
               String options = "";
               String target = null;
  +            if( argv.length == 0 ) {
  +                System.out.println( "Error:Usage: java REUtil -i|-m|-s|-u|-w|-X regularExpression String" );
  +                System.exit( 0 );
  +            }
               for (int i = 0;  i < argv.length;  i ++) {
                   if (argv[i].length() == 0 || argv[i].charAt(0) != '-') {
                       if (pattern == null)
  @@ -255,7 +259,7 @@
               if (pattern == null) {
                   pe.printStackTrace();
               } else {
  -                System.err.println("com.ibm.regex.ParseException: "+pe.getMessage());
  +                System.err.println("org.apache.xerces.utils.regex.ParseException: "+pe.getMessage());
                   String indent = "        ";
                   System.err.println(indent+pattern);
                   int loc = pe.getLocation();
  @@ -276,7 +280,7 @@
        * Creates a RegularExpression instance.
        * This method caches created instances.
        *
  -     * @see com.ibm.regex.RegularExpression#RegularExpression(java.lang.String, java.lang.String)
  +     * @see org.apache.xerces.utils.regex.RegularExpression#RegularExpression(java.lang.String, java.lang.String)
        */
       public static RegularExpression createRegex(String pattern, String options)
           throws ParseException {
  @@ -309,7 +313,7 @@
   
       /**
        *
  -     * @see com.ibm.regex.RegularExpression#matches(java.lang.String)
  +     * @see org.apache.xerces.utils.regex.RegularExpression#matches(java.lang.String)
        */
       public static boolean matches(String regex, String target) throws ParseException {
           return REUtil.createRegex(regex, null).matches(target);
  @@ -317,7 +321,7 @@
   
       /**
        *
  -     * @see com.ibm.regex.RegularExpression#matches(java.lang.String)
  +     * @see org.apache.xerces.utils.regex.RegularExpression#matches(java.lang.String)
        */
       public static boolean matches(String regex, String options, String target) throws ParseException {
           return REUtil.createRegex(regex, options).matches(target);
  
  
  
  1.2       +3 -3      xml-xerces/java/src/org/apache/xerces/utils/regex/RegexParser.java
  
  Index: RegexParser.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/utils/regex/RegexParser.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- RegexParser.java	2000/04/04 19:31:31	1.1
  +++ RegexParser.java	2000/05/17 18:32:55	1.2
  @@ -116,15 +116,15 @@
       Vector references = null;
   
       public RegexParser() {
  -        this.setLocale(Locale.getDefault());
  +        //TODO IBM-JR this.setLocale(Locale.getDefault());
       }
       public RegexParser(Locale locale) {
  -        this.setLocale(locale);
  +        //TODO IBM-JR this.setLocale(locale);
       }
   
       public void setLocale(Locale locale) {
           try {
  -            this.resources = ResourceBundle.getBundle("com.ibm.regex.message", locale);
  +            this.resources = ResourceBundle.getBundle("org.apache.xerces.utils.regex.message", locale);
           } catch (MissingResourceException mre) {
               throw new RuntimeException("Installation Problem???  Couldn't load messages: "
                                          +mre.getMessage());
  
  
  
  1.2       +1697 -1800xml-xerces/java/src/org/apache/xerces/utils/regex/RegularExpression.java
  
  Index: RegularExpression.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/utils/regex/RegularExpression.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- RegularExpression.java	2000/04/04 19:31:31	1.1
  +++ RegularExpression.java	2000/05/17 18:32:55	1.2
  @@ -355,7 +355,7 @@
    *       <dd>Grouping with capturing.
    * It make a group and applications can know
    * where in target text a group matched with methods of a <code>Match</code> instance
  - * after <code><a href="#matches(java.lang.String, com.ibm.regex.Match)">matches(String,Match)</a></code>.
  + * after <code><a href="#matches(java.lang.String, org.apache.xerces.utils.regex.Match)">matches(String,Match)</a></code>.
    * The 0th group means whole of this regular expression.
    * The <VAR>N</VAR>th gorup is the inside of the <VAR>N</VAR>th left parenthesis.
    * 
  @@ -533,28 +533,28 @@
       private Op compile(Token tok, Op next, boolean reverse) {
           Op ret;
           switch (tok.type) {
  -          case Token.DOT:
  +        case Token.DOT:
               ret = Op.createDot();
               ret.next = next;
               break;
   
  -          case Token.CHAR:
  +        case Token.CHAR:
               ret = Op.createChar(tok.getChar());
               ret.next = next;
               break;
   
  -          case Token.ANCHOR:
  +        case Token.ANCHOR:
               ret = Op.createAnchor(tok.getChar());
               ret.next = next;
               break;
   
  -          case Token.RANGE:
  -          case Token.NRANGE:
  +        case Token.RANGE:
  +        case Token.NRANGE:
               ret = Op.createRange(tok);
               ret.next = next;
               break;
   
  -          case Token.CONCAT:
  +        case Token.CONCAT:
               ret = next;
               if (!reverse) {
                   for (int i = tok.size()-1;  i >= 0;  i --) {
  @@ -567,7 +567,7 @@
               }
               break;
   
  -          case Token.UNION:
  +        case Token.UNION:
               Op.UnionOp uni = Op.createUnion(tok.size());
               for (int i = 0;  i < tok.size();  i ++) {
                   uni.addElement(compile(tok.getChild(i), next, reverse));
  @@ -575,8 +575,8 @@
               ret = uni;                          // ret.next is null.
               break;
   
  -          case Token.CLOSURE:
  -          case Token.NONGREEDYCLOSURE:
  +        case Token.CLOSURE:
  +        case Token.NONGREEDYCLOSURE:
               Token child = tok.getChild(0);
               int min = tok.getMin();
               int max = tok.getMax();
  @@ -590,7 +590,7 @@
               if (min > 0 && max > 0)
                   max -= min;
               if (max > 0) {
  -                                                // X{2,6} -> XX(X(X(XX?)?)?)?
  +                // X{2,6} -> XX(X(X(XX?)?)?)?
                   ret = next;
                   for (int i = 0;  i < max;  i ++) {
                       Op.ChildOp q = Op.createQuestion(tok.type == Token.NONGREEDYCLOSURE);
  @@ -619,21 +619,21 @@
               }
               break;
   
  -          case Token.EMPTY:
  +        case Token.EMPTY:
               ret = next;
               break;
   
  -          case Token.STRING:
  +        case Token.STRING:
               ret = Op.createString(tok.getString());
               ret.next = next;
               break;
   
  -          case Token.BACKREFERENCE:
  +        case Token.BACKREFERENCE:
               ret = Op.createBackReference(tok.getReferenceNumber());
               ret.next = next;
               break;
   
  -          case Token.PAREN:
  +        case Token.PAREN:
               if (tok.getParenNumber() == 0) {
                   ret = compile(tok.getChild(0), next, reverse);
               } else if (reverse) {
  @@ -647,30 +647,30 @@
               }
               break;
   
  -          case Token.LOOKAHEAD:
  +        case Token.LOOKAHEAD:
               ret = Op.createLook(Op.LOOKAHEAD, next, compile(tok.getChild(0), null, false));
               break;
  -          case Token.NEGATIVELOOKAHEAD:
  +        case Token.NEGATIVELOOKAHEAD:
               ret = Op.createLook(Op.NEGATIVELOOKAHEAD, next, compile(tok.getChild(0), null, false));
               break;
  -          case Token.LOOKBEHIND:
  +        case Token.LOOKBEHIND:
               ret = Op.createLook(Op.LOOKBEHIND, next, compile(tok.getChild(0), null, true));
               break;
  -          case Token.NEGATIVELOOKBEHIND:
  +        case Token.NEGATIVELOOKBEHIND:
               ret = Op.createLook(Op.NEGATIVELOOKBEHIND, next, compile(tok.getChild(0), null, true));
               break;
   
  -          case Token.INDEPENDENT:
  +        case Token.INDEPENDENT:
               ret = Op.createIndependent(next, compile(tok.getChild(0), null, reverse));
               break;
   
  -          case Token.MODIFIERGROUP:
  +        case Token.MODIFIERGROUP:
               ret = Op.createModifier(next, compile(tok.getChild(0), null, reverse),
                                       ((Token.ModifierToken)tok).getOptions(),
                                       ((Token.ModifierToken)tok).getOptionsMask());
               break;
   
  -          case Token.CONDITION:
  +        case Token.CONDITION:
               Token.ConditionToken ctok = (Token.ConditionToken)tok;
               int ref = ctok.refNumber;
               Op condition = ctok.condition == null ? null : compile(ctok.condition, null, reverse);
  @@ -679,68 +679,39 @@
               ret = Op.createCondition(next, ref, condition, yes, no);
               break;
   
  -          default:
  +        default:
               throw new RuntimeException("Unknown token type: "+tok.type);
           } // switch (tok.type)
           return ret;
       }
   
  -    // ================================================================
  -
  -/* -*- java -*-
  - *
  - * (C) Copyright IBM Corp. 1998-2000  All rights reserved.
  - *
  - * US Government Users Restricted Rights Use, duplication or
  - * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  - *
  - * The program is provided "as is" without any warranty express or
  - * implied, including the warranty of non-infringement and the implied
  - * warranties of merchantibility and fitness for a particular purpose.
  - * IBM will not be liable for any damages suffered by you as a result
  - * of using the Program. In no event will IBM be liable for any
  - * special, indirect or consequential damages or lost profits even if
  - * IBM has been advised of the possibility of their occurrence. IBM
  - * will not be liable for any third party claims against you.
  - */
  -
  -
  -
  -
  -
  -
   
  +//Public
   
  -
  -
  -
  -
  -
  -
   /**
    *
    * @return true if the target is matched to this regular expression.
    */
  -public boolean matches(char[]  target) {
  -    return this.matches(target, 0,  target .length , (Match)null);
  -}
  +    public boolean matches(char[]  target) {
  +        return this.matches(target, 0,  target .length , (Match)null);
  +    }
   
   /**
    *
    * @return true if the target is matched to this regular expression.
    */
  -public boolean matches(char[]  target, int start, int end) {
  -    return this.matches(target, start, end, (Match)null);
  -}
  +    public boolean matches(char[]  target, int start, int end) {
  +        return this.matches(target, start, end, (Match)null);
  +    }
   
   /**
    *
    * @param match A Match instance for storing matching result.
    * @return Offset of the start position in <VAR>target</VAR>; or -1 if not match.
    */
  -public boolean matches(char[]  target, Match match) {
  -    return this.matches(target, 0,  target .length , match);
  -}
  +    public boolean matches(char[]  target, Match match) {
  +        return this.matches(target, 0,  target .length , match);
  +    }
   
   
   /**
  @@ -749,743 +720,697 @@
    * @return Offset of the start position in <VAR>target</VAR>; or -1 if not match.
    */
   
  -
  -
   
  +    public boolean matches(char[]  target, int start, int end, Match match) {
   
  -public boolean matches(char[]  target, int start, int end, Match match) {
  -
  -    synchronized (this) {
  -        if (this.operations == null)
  -            this.prepare();
  -        if (this.context == null)
  -            this.context = new Context();
  -    }
  -    Context con = null;
  -    synchronized (this.context) {
  -        con = this.context.inuse ? new Context() : this.context;
  -        con.reset(target, start, end, this.numberOfClosures);
  -    }
  -    if (match != null) {
  -        match.setNumberOfGroups(this.nofparen);
  -        match.setSource(target);
  -    } else if (this.hasBackReferences) {
  -        match = new Match();
  -        match.setNumberOfGroups(this.nofparen);
  -                                                // Need not to call setSource() because
  -                                                // a caller can not access this match instance.
  -    }
  -    con.match = match;
  -
  -    if (this.isSet(this.options, XMLSCHEMA_MODE)) {
  -        int matchEnd = this. matchCharArray (con, this.operations, con.start, 1, this.options);
  -        //System.err.println("DEBUG: matchEnd="+matchEnd);
  -        if (matchEnd == con.limit) {
  -            if (con.match != null) {
  -                con.match.setBeginning(0, con.start);
  -                con.match.setEnd(0, matchEnd);
  +        synchronized (this) {
  +            if (this.operations == null)
  +                this.prepare();
  +            if (this.context == null)
  +                this.context = new Context();
  +        }
  +        Context con = null;
  +        synchronized (this.context) {
  +            con = this.context.inuse ? new Context() : this.context;
  +            con.reset(target, start, end, this.numberOfClosures);
  +        }
  +        if (match != null) {
  +            match.setNumberOfGroups(this.nofparen);
  +            match.setSource(target);
  +        } else if (this.hasBackReferences) {
  +            match = new Match();
  +            match.setNumberOfGroups(this.nofparen);
  +            // Need not to call setSource() because
  +            // a caller can not access this match instance.
  +        }
  +        con.match = match;
  +
  +        if (this.isSet(this.options, XMLSCHEMA_MODE)) {
  +            int matchEnd = this. matchCharArray (con, this.operations, con.start, 1, this.options);
  +            //System.err.println("DEBUG: matchEnd="+matchEnd);
  +            if (matchEnd == con.limit) {
  +                if (con.match != null) {
  +                    con.match.setBeginning(0, con.start);
  +                    con.match.setEnd(0, matchEnd);
  +                }
  +                con.inuse = false;
  +                return true;
               }
  -            con.inuse = false;
  -            return true;
  +            return false;
           }
  -        return false;
  -    }
   
  -    /*
  -     * The pattern has only fixed string.
  -     * The engine uses Boyer-Moore.
  -     */
  -    if (this.fixedStringOnly) {
  -        //System.err.println("DEBUG: fixed-only: "+this.fixedString);
  -        int o = this.fixedStringTable.matches(target, con.start, con.limit);
  -        if (o >= 0) {
  -            if (con.match != null) {
  -                con.match.setBeginning(0, o);
  -                con.match.setEnd(0, o+this.fixedString.length());
  +        /*
  +         * The pattern has only fixed string.
  +         * The engine uses Boyer-Moore.
  +         */
  +        if (this.fixedStringOnly) {
  +            //System.err.println("DEBUG: fixed-only: "+this.fixedString);
  +            int o = this.fixedStringTable.matches(target, con.start, con.limit);
  +            if (o >= 0) {
  +                if (con.match != null) {
  +                    con.match.setBeginning(0, o);
  +                    con.match.setEnd(0, o+this.fixedString.length());
  +                }
  +                con.inuse = false;
  +                return true;
               }
               con.inuse = false;
  -            return true;
  +            return false;
           }
  -        con.inuse = false;
  -        return false;
  -    }
   
  -    /*
  -     * The pattern contains a fixed string.
  -     * The engine checks with Boyer-Moore whether the text contains the fixed string or not.
  -     * If not, it return with false.
  -     */
  -    if (this.fixedString != null) {
  -        int o = this.fixedStringTable.matches(target, con.start, con.limit);
  -        if (o < 0) {
  -            //System.err.println("Non-match in fixed-string search.");
  -            con.inuse = false;
  -            return false;
  +        /*
  +         * The pattern contains a fixed string.
  +         * The engine checks with Boyer-Moore whether the text contains the fixed string or not.
  +         * If not, it return with false.
  +         */
  +        if (this.fixedString != null) {
  +            int o = this.fixedStringTable.matches(target, con.start, con.limit);
  +            if (o < 0) {
  +                //System.err.println("Non-match in fixed-string search.");
  +                con.inuse = false;
  +                return false;
  +            }
           }
  -    }
   
  -    int limit = con.limit-this.minlength;
  -    int matchStart;
  -    int matchEnd = -1;
  -
  -    /*
  -     * Checks whether the expression starts with ".*".
  -     */
  -    if (this.operations.type == Op.CLOSURE && this.operations.getChild().type == Op.DOT) {
  -        if (isSet(this.options, SINGLE_LINE)) {
  -            matchStart = con.start;
  -            matchEnd = this. matchCharArray (con, this.operations, con.start, 1, this.options);
  -        } else {
  -            boolean previousIsEOL = true;
  -            for (matchStart = con.start;  matchStart <= limit;  matchStart ++) {
  -                int ch =  target [  matchStart ] ;
  -                if (isEOLChar(ch)) {
  -                    previousIsEOL = true;
  -                } else {
  -                    if (previousIsEOL) {
  -                        if (0 <= (matchEnd = this. matchCharArray (con, this.operations,
  -                                                        matchStart, 1, this.options)))
  -                            break;
  +        int limit = con.limit-this.minlength;
  +        int matchStart;
  +        int matchEnd = -1;
  +
  +        /*
  +         * Checks whether the expression starts with ".*".
  +         */
  +        if (this.operations.type == Op.CLOSURE && this.operations.getChild().type == Op.DOT) {
  +            if (isSet(this.options, SINGLE_LINE)) {
  +                matchStart = con.start;
  +                matchEnd = this. matchCharArray (con, this.operations, con.start, 1, this.options);
  +            } else {
  +                boolean previousIsEOL = true;
  +                for (matchStart = con.start;  matchStart <= limit;  matchStart ++) {
  +                    int ch =  target [  matchStart ] ;
  +                    if (isEOLChar(ch)) {
  +                        previousIsEOL = true;
  +                    } else {
  +                        if (previousIsEOL) {
  +                            if (0 <= (matchEnd = this. matchCharArray (con, this.operations,
  +                                                                       matchStart, 1, this.options)))
  +                                break;
  +                        }
  +                        previousIsEOL = false;
                       }
  -                    previousIsEOL = false;
                   }
               }
           }
  -    }
   
  -    /*
  -     * Optimization against the first character.
  -     */
  -    else if (this.firstChar != null) {
  -        //System.err.println("DEBUG: with firstchar-matching: "+this.firstChar);
  -        RangeToken range = this.firstChar;
  -        if (this.isSet(this.options, IGNORE_CASE)) {
  -            range = this.firstChar.getCaseInsensitiveToken();
  -            for (matchStart = con.start;  matchStart <= limit;  matchStart ++) {
  -                int ch =  target [  matchStart ] ;
  -                if (REUtil.isHighSurrogate(ch) && matchStart+1 < con.limit) {
  -                    ch = REUtil.composeFromSurrogates(ch,  target [  matchStart+1 ] );
  -                    if (!range.match(ch))  continue;
  -                } else {
  -                    if (!range.match(ch)) {
  -                        char ch1 = Character.toUpperCase((char)ch);
  -                        if (!range.match(ch1))
  -                            if (!range.match(Character.toLowerCase(ch1)))
  -                                continue;
  +        /*
  +         * Optimization against the first character.
  +         */
  +        else if (this.firstChar != null) {
  +            //System.err.println("DEBUG: with firstchar-matching: "+this.firstChar);
  +            RangeToken range = this.firstChar;
  +            if (this.isSet(this.options, IGNORE_CASE)) {
  +                range = this.firstChar.getCaseInsensitiveToken();
  +                for (matchStart = con.start;  matchStart <= limit;  matchStart ++) {
  +                    int ch =  target [  matchStart ] ;
  +                    if (REUtil.isHighSurrogate(ch) && matchStart+1 < con.limit) {
  +                        ch = REUtil.composeFromSurrogates(ch,  target [  matchStart+1 ] );
  +                        if (!range.match(ch))  continue;
  +                    } else {
  +                        if (!range.match(ch)) {
  +                            char ch1 = Character.toUpperCase((char)ch);
  +                            if (!range.match(ch1))
  +                                if (!range.match(Character.toLowerCase(ch1)))
  +                                    continue;
  +                        }
                       }
  +                    if (0 <= (matchEnd = this. matchCharArray (con, this.operations,
  +                                                               matchStart, 1, this.options)))
  +                        break;
                   }
  -                if (0 <= (matchEnd = this. matchCharArray (con, this.operations,
  -                                                matchStart, 1, this.options)))
  -                    break;
  +            } else {
  +                for (matchStart = con.start;  matchStart <= limit;  matchStart ++) {
  +                    int ch =  target [  matchStart ] ;
  +                    if (REUtil.isHighSurrogate(ch) && matchStart+1 < con.limit)
  +                        ch = REUtil.composeFromSurrogates(ch,  target [  matchStart+1 ] );
  +                    if (!range.match(ch))  continue;
  +                    if (0 <= (matchEnd = this. matchCharArray (con, this.operations,
  +                                                               matchStart, 1, this.options)))
  +                        break;
  +                }
               }
  -        } else {
  +        }
  +
  +        /*
  +         * Straightforward matching.
  +         */
  +        else {
               for (matchStart = con.start;  matchStart <= limit;  matchStart ++) {
  -                int ch =  target [  matchStart ] ;
  -                if (REUtil.isHighSurrogate(ch) && matchStart+1 < con.limit)
  -                    ch = REUtil.composeFromSurrogates(ch,  target [  matchStart+1 ] );
  -                if (!range.match(ch))  continue;
  -                if (0 <= (matchEnd = this. matchCharArray (con, this.operations,
  -                                                matchStart, 1, this.options)))
  +                if (0 <= (matchEnd = this. matchCharArray (con, this.operations, matchStart, 1, this.options)))
                       break;
               }
           }
  -    }
  -
  -    /*
  -     * Straightforward matching.
  -     */
  -    else {
  -        for (matchStart = con.start;  matchStart <= limit;  matchStart ++) {
  -            if (0 <= (matchEnd = this. matchCharArray (con, this.operations, matchStart, 1, this.options)))
  -                break;
  -        }
  -    }
   
  -    if (matchEnd >= 0) {
  -        if (con.match != null) {
  -            con.match.setBeginning(0, matchStart);
  -            con.match.setEnd(0, matchEnd);
  +        if (matchEnd >= 0) {
  +            if (con.match != null) {
  +                con.match.setBeginning(0, matchStart);
  +                con.match.setEnd(0, matchEnd);
  +            }
  +            con.inuse = false;
  +            return true;
  +        } else {
  +            con.inuse = false;
  +            return false;
           }
  -        con.inuse = false;
  -        return true;
  -    } else {
  -        con.inuse = false;
  -        return false;
       }
  -}
   
   /**
    * @return -1 when not match; offset of the end of matched string when match.
    */
  -private int matchCharArray (Context con, Op op, int offset, int dx, int opts) {
  -
  -
  +    private int matchCharArray (Context con, Op op, int offset, int dx, int opts) {
   
  +        char[] target = con.charTarget;
   
   
  -
  -    char[] target = con.charTarget;
  -
  -
  -    while (true) {
  -        if (op == null)
  -            return offset;
  -        if (offset > con.limit || offset < con.start)
  -            return -1;
  -        switch (op.type) {
  -          case Op.CHAR:
  -            if (isSet(opts, IGNORE_CASE)) {
  -                int ch = op.getData();
  -                if (dx > 0) {
  -                    if (offset >= con.limit || !matchIgnoreCase(ch,  target [  offset ] ))
  -                        return -1;
  -                    offset ++;
  +        while (true) {
  +            if (op == null)
  +                return offset;
  +            if (offset > con.limit || offset < con.start)
  +                return -1;
  +            switch (op.type) {
  +            case Op.CHAR:
  +                if (isSet(opts, IGNORE_CASE)) {
  +                    int ch = op.getData();
  +                    if (dx > 0) {
  +                        if (offset >= con.limit || !matchIgnoreCase(ch,  target [  offset ] ))
  +                            return -1;
  +                        offset ++;
  +                    } else {
  +                        int o1 = offset-1;
  +                        if (o1 >= con.limit || o1 < 0 || !matchIgnoreCase(ch,  target [  o1 ] ))
  +                            return -1;
  +                        offset = o1;
  +                    }
                   } else {
  -                    int o1 = offset-1;
  -                    if (o1 >= con.limit || o1 < 0 || !matchIgnoreCase(ch,  target [  o1 ] ))
  -                        return -1;
  -                    offset = o1;
  +                    int ch = op.getData();
  +                    if (dx > 0) {
  +                        if (offset >= con.limit || ch !=  target [  offset ] )
  +                            return -1;
  +                        offset ++;
  +                    } else {
  +                        int o1 = offset-1;
  +                        if (o1 >= con.limit || o1 < 0 || ch !=  target [  o1 ] )
  +                            return -1;
  +                        offset = o1;
  +                    }
                   }
  -            } else {
  -                int ch = op.getData();
  +                op = op.next;
  +                break;
  +
  +            case Op.DOT:
                   if (dx > 0) {
  -                    if (offset >= con.limit || ch !=  target [  offset ] )
  +                    if (offset >= con.limit)
  +                        return -1;
  +                    int ch =  target [  offset ] ;
  +                    if (isSet(opts, SINGLE_LINE)) {
  +                        if (REUtil.isHighSurrogate(ch) && offset+1 < con.limit)
  +                            offset ++;
  +                    } else {
  +                        if (REUtil.isHighSurrogate(ch) && offset+1 < con.limit)
  +                            ch = REUtil.composeFromSurrogates(ch,  target [  ++offset ] );
  +                        if (isEOLChar(ch))
                               return -1;
  +                    }
                       offset ++;
                   } else {
                       int o1 = offset-1;
  -                    if (o1 >= con.limit || o1 < 0 || ch !=  target [  o1 ] )
  +                    if (o1 >= con.limit || o1 < 0)
                           return -1;
  +                    int ch =  target [  o1 ] ;
  +                    if (isSet(opts, SINGLE_LINE)) {
  +                        if (REUtil.isLowSurrogate(ch) && o1-1 >= 0)
  +                            o1 --;
  +                    } else {
  +                        if (REUtil.isLowSurrogate(ch) && o1-1 >= 0)
  +                            ch = REUtil.composeFromSurrogates( target [  --o1 ] , ch);
  +                        if (!isEOLChar(ch))
  +                            return -1;
  +                    }
                       offset = o1;
                   }
  -            }
  -            op = op.next;
  -            break;
  +                op = op.next;
  +                break;
   
  -          case Op.DOT:
  -            if (dx > 0) {
  -                if (offset >= con.limit)
  -                    return -1;
  -                int ch =  target [  offset ] ;
  -                if (isSet(opts, SINGLE_LINE)) {
  -                    if (REUtil.isHighSurrogate(ch) && offset+1 < con.limit)
  -                        offset ++;
  -                } else {
  +            case Op.RANGE:
  +            case Op.NRANGE:
  +                if (dx > 0) {
  +                    if (offset >= con.limit)
  +                        return -1;
  +                    int ch =  target [  offset ] ;
                       if (REUtil.isHighSurrogate(ch) && offset+1 < con.limit)
                           ch = REUtil.composeFromSurrogates(ch,  target [  ++offset ] );
  -                    if (isEOLChar(ch))
  -                        return -1;
  -                }
  -                offset ++;
  -            } else {
  -                int o1 = offset-1;
  -                if (o1 >= con.limit || o1 < 0)
  -                    return -1;
  -                int ch =  target [  o1 ] ;
  -                if (isSet(opts, SINGLE_LINE)) {
  -                    if (REUtil.isLowSurrogate(ch) && o1-1 >= 0)
  -                        o1 --;
  +                    RangeToken tok = op.getToken();
  +                    if (isSet(opts, IGNORE_CASE)) {
  +                        tok = tok.getCaseInsensitiveToken();
  +                        if (!tok.match(ch)) {
  +                            if (ch >= 0x10000)  return -1;
  +                            char uch;
  +                            if (!tok.match(uch = Character.toUpperCase((char)ch))
  +                                && !tok.match(Character.toLowerCase(uch)))
  +                                return -1;
  +                        }
  +                    } else {
  +                        if (!tok.match(ch))  return -1;
  +                    }
  +                    offset ++;
                   } else {
  +                    int o1 = offset-1;
  +                    if (o1 >= con.limit || o1 < 0)
  +                        return -1;
  +                    int ch =  target [  o1 ] ;
                       if (REUtil.isLowSurrogate(ch) && o1-1 >= 0)
                           ch = REUtil.composeFromSurrogates( target [  --o1 ] , ch);
  -                    if (!isEOLChar(ch))
  -                        return -1;
  -                }
  -                offset = o1;
  -            }
  -            op = op.next;
  -            break;
  -            
  -          case Op.RANGE:
  -          case Op.NRANGE:
  -            if (dx > 0) {
  -                if (offset >= con.limit)
  -                    return -1;
  -                int ch =  target [  offset ] ;
  -                if (REUtil.isHighSurrogate(ch) && offset+1 < con.limit)
  -                    ch = REUtil.composeFromSurrogates(ch,  target [  ++offset ] );
  -                RangeToken tok = op.getToken();
  -                if (isSet(opts, IGNORE_CASE)) {
  -                    tok = tok.getCaseInsensitiveToken();
  -                    if (!tok.match(ch)) {
  -                        if (ch >= 0x10000)  return -1;
  -                        char uch;
  -                        if (!tok.match(uch = Character.toUpperCase((char)ch))
  -                            && !tok.match(Character.toLowerCase(uch)))
  -                            return -1;
  +                    RangeToken tok = op.getToken();
  +                    if (isSet(opts, IGNORE_CASE)) {
  +                        tok = tok.getCaseInsensitiveToken();
  +                        if (!tok.match(ch)) {
  +                            if (ch >= 0x10000)  return -1;
  +                            char uch;
  +                            if (!tok.match(uch = Character.toUpperCase((char)ch))
  +                                && !tok.match(Character.toLowerCase(uch)))
  +                                return -1;
  +                        }
  +                    } else {
  +                        if (!tok.match(ch))  return -1;
                       }
  -                } else {
  -                    if (!tok.match(ch))  return -1;
  +                    offset = o1;
                   }
  -                offset ++;
  -            } else {
  -                int o1 = offset-1;
  -                if (o1 >= con.limit || o1 < 0)
  -                    return -1;
  -                int ch =  target [  o1 ] ;
  -                if (REUtil.isLowSurrogate(ch) && o1-1 >= 0)
  -                    ch = REUtil.composeFromSurrogates( target [  --o1 ] , ch);
  -                RangeToken tok = op.getToken();
  -                if (isSet(opts, IGNORE_CASE)) {
  -                    tok = tok.getCaseInsensitiveToken();
  -                    if (!tok.match(ch)) {
  -                        if (ch >= 0x10000)  return -1;
  -                        char uch;
  -                        if (!tok.match(uch = Character.toUpperCase((char)ch))
  -                            && !tok.match(Character.toLowerCase(uch)))
  +                op = op.next;
  +                break;
  +
  +            case Op.ANCHOR:
  +                boolean go = false;
  +                switch (op.getData()) {
  +                case '^':
  +                    if (isSet(opts, MULTIPLE_LINES)) {
  +                        if (!(offset == con.start
  +                              || offset > con.start && isEOLChar( target [  offset-1 ] )))
  +                            return -1;
  +                    } else {
  +                        if (offset != con.start)
                               return -1;
                       }
  -                } else {
  -                    if (!tok.match(ch))  return -1;
  -                }
  -                offset = o1;
  -            }
  -            op = op.next;
  -            break;
  +                    break;
   
  -          case Op.ANCHOR:
  -            boolean go = false;
  -            switch (op.getData()) {
  -              case '^':
  -                if (isSet(opts, MULTIPLE_LINES)) {
  +                case '@':                         // Internal use only.
  +                    // The @ always matches line beginnings.
                       if (!(offset == con.start
                             || offset > con.start && isEOLChar( target [  offset-1 ] )))
  -                        return -1;
  -                } else {
  -                    if (offset != con.start)
                           return -1;
  -                }
  -                break;
  +                    break;
   
  -              case '@':                         // Internal use only.
  -                                                // The @ always matches line beginnings.
  -                if (!(offset == con.start
  -                      || offset > con.start && isEOLChar( target [  offset-1 ] )))
  -                    return -1;
  -                break;
  +                case '$':
  +                    if (isSet(opts, MULTIPLE_LINES)) {
  +                        if (!(offset == con.limit
  +                              || offset < con.limit && isEOLChar( target [  offset ] )))
  +                            return -1;
  +                    } else {
  +                        if (!(offset == con.limit
  +                              || offset+1 == con.limit && isEOLChar( target [  offset ] )
  +                              || offset+2 == con.limit &&  target [  offset ]  == CARRIAGE_RETURN
  +                              &&  target [  offset+1 ]  == LINE_FEED))
  +                            return -1;
  +                    }
  +                    break;
   
  -              case '$':
  -                if (isSet(opts, MULTIPLE_LINES)) {
  -                    if (!(offset == con.limit
  -                          || offset < con.limit && isEOLChar( target [  offset ] )))
  -                        return -1;
  -                } else {
  +                case 'A':
  +                    if (offset != con.start)  return -1;
  +                    break;
  +
  +                case 'Z':
                       if (!(offset == con.limit
                             || offset+1 == con.limit && isEOLChar( target [  offset ] )
                             || offset+2 == con.limit &&  target [  offset ]  == CARRIAGE_RETURN
  -                                                   &&  target [  offset+1 ]  == LINE_FEED))
  +                          &&  target [  offset+1 ]  == LINE_FEED))
  +                        return -1;
  +                    break;
  +
  +                case 'z':
  +                    if (offset != con.limit)  return -1;
  +                    break;
  +
  +                case 'b':
  +                    if (con.length == 0)  return -1;
  +                    {
  +                        int after = getWordType(target, con.start, con.limit, offset, opts);
  +                        if (after == WT_IGNORE)  return -1;
  +                        int before = getPreviousWordType(target, con.start, con.limit, offset, opts);
  +                        if (after == before)  return -1;
  +                    }
  +                    break;
  +
  +                case 'B':
  +                    if (con.length == 0)
  +                        go = true;
  +                    else {
  +                        int after = getWordType(target, con.start, con.limit, offset, opts);
  +                        go = after == WT_IGNORE
  +                             || after == getPreviousWordType(target, con.start, con.limit, offset, opts);
  +                    }
  +                    if (!go)  return -1;
  +                    break;
  +
  +                case '<':
  +                    if (con.length == 0 || offset == con.limit)  return -1;
  +                    if (getWordType(target, con.start, con.limit, offset, opts) != WT_LETTER
  +                        || getPreviousWordType(target, con.start, con.limit, offset, opts) != WT_OTHER)
  +                        return -1;
  +                    break;
  +
  +                case '>':
  +                    if (con.length == 0 || offset == con.start)  return -1;
  +                    if (getWordType(target, con.start, con.limit, offset, opts) != WT_OTHER
  +                        || getPreviousWordType(target, con.start, con.limit, offset, opts) != WT_LETTER)
                           return -1;
  +                    break;
  +                } // switch anchor type
  +                op = op.next;
  +                break;
  +
  +            case Op.BACKREFERENCE:
  +                {
  +                    int refno = op.getData();
  +                    if (refno <= 0 || refno >= this.nofparen)
  +                        throw new RuntimeException("Internal Error: Reference number must be more than zero: "+refno);
  +                    if (con.match.getBeginning(refno) < 0
  +                        || con.match.getEnd(refno) < 0)
  +                        return -1;                // ********
  +                    int o2 = con.match.getBeginning(refno);
  +                    int literallen = con.match.getEnd(refno)-o2;
  +                    if (!isSet(opts, IGNORE_CASE)) {
  +                        if (dx > 0) {
  +                            if (!regionMatches(target, offset, con.limit, o2, literallen))
  +                                return -1;
  +                            offset += literallen;
  +                        } else {
  +                            if (!regionMatches(target, offset-literallen, con.limit, o2, literallen))
  +                                return -1;
  +                            offset -= literallen;
  +                        }
  +                    } else {
  +                        if (dx > 0) {
  +                            if (!regionMatchesIgnoreCase(target, offset, con.limit, o2, literallen))
  +                                return -1;
  +                            offset += literallen;
  +                        } else {
  +                            if (!regionMatchesIgnoreCase(target, offset-literallen, con.limit,
  +                                                         o2, literallen))
  +                                return -1;
  +                            offset -= literallen;
  +                        }
  +                    }
                   }
  +                op = op.next;
                   break;
  -                
  -              case 'A':
  -                if (offset != con.start)  return -1;
  +            case Op.STRING:
  +                {
  +                    String literal = op.getString();
  +                    int literallen = literal.length();
  +                    if (!isSet(opts, IGNORE_CASE)) {
  +                        if (dx > 0) {
  +                            if (!regionMatches(target, offset, con.limit, literal, literallen))
  +                                return -1;
  +                            offset += literallen;
  +                        } else {
  +                            if (!regionMatches(target, offset-literallen, con.limit, literal, literallen))
  +                                return -1;
  +                            offset -= literallen;
  +                        }
  +                    } else {
  +                        if (dx > 0) {
  +                            if (!regionMatchesIgnoreCase(target, offset, con.limit, literal, literallen))
  +                                return -1;
  +                            offset += literallen;
  +                        } else {
  +                            if (!regionMatchesIgnoreCase(target, offset-literallen, con.limit,
  +                                                         literal, literallen))
  +                                return -1;
  +                            offset -= literallen;
  +                        }
  +                    }
  +                }
  +                op = op.next;
                   break;
  +
  +            case Op.CLOSURE:
  +                {
  +                    /*
  +                     * Saves current position to avoid
  +                     * zero-width repeats.
  +                     */
  +                    int id = op.getData();
  +                    if (id >= 0) {
  +                        int previousOffset = con.offsets[id];
  +                        if (previousOffset < 0 || previousOffset != offset) {
  +                            con.offsets[id] = offset;
  +                        } else {
  +                            con.offsets[id] = -1;
  +                            op = op.next;
  +                            break;
  +                        }
  +                    }
   
  -              case 'Z':
  -                if (!(offset == con.limit
  -                      || offset+1 == con.limit && isEOLChar( target [  offset ] )
  -                      || offset+2 == con.limit &&  target [  offset ]  == CARRIAGE_RETURN
  -                                               &&  target [  offset+1 ]  == LINE_FEED))
  -                    return -1;
  +                    int ret = this. matchCharArray (con, op.getChild(), offset, dx, opts);
  +                    if (id >= 0)  con.offsets[id] = -1;
  +                    if (ret >= 0)  return ret;
  +                    op = op.next;
  +                }
                   break;
   
  -              case 'z':
  -                if (offset != con.limit)  return -1;
  +            case Op.QUESTION:
  +                {
  +                    int ret = this. matchCharArray (con, op.getChild(), offset, dx, opts);
  +                    if (ret >= 0)  return ret;
  +                    op = op.next;
  +                }
                   break;
   
  -              case 'b':
  -                if (con.length == 0)  return -1;
  +            case Op.NONGREEDYCLOSURE:
  +            case Op.NONGREEDYQUESTION:
                   {
  -                    int after = getWordType(target, con.start, con.limit, offset, opts);
  -                    if (after == WT_IGNORE)  return -1;
  -                    int before = getPreviousWordType(target, con.start, con.limit, offset, opts);
  -                    if (after == before)  return -1;
  +                    int ret = this. matchCharArray (con, op.next, offset, dx, opts);
  +                    if (ret >= 0)  return ret;
  +                    op = op.getChild();
                   }
                   break;
   
  -              case 'B':
  -                if (con.length == 0)
  -                    go = true;
  -                else {
  -                    int after = getWordType(target, con.start, con.limit, offset, opts);
  -                    go = after == WT_IGNORE
  -                        || after == getPreviousWordType(target, con.start, con.limit, offset, opts);
  +            case Op.UNION:
  +                for (int i = 0;  i < op.size();  i ++) {
  +                    int ret = this. matchCharArray (con, op.elementAt(i), offset, dx, opts);
  +                    //System.err.println("UNION: "+i+", ret="+ret);
  +                    if (ret >= 0)  return ret;
  +                }
  +                return -1;
  +
  +            case Op.CAPTURE:
  +                int refno = op.getData();
  +                if (con.match != null && refno > 0) {
  +                    int save = con.match.getBeginning(refno);
  +                    con.match.setBeginning(refno, offset);
  +                    int ret = this. matchCharArray (con, op.next, offset, dx, opts);
  +                    if (ret < 0)  con.match.setBeginning(refno, save);
  +                    return ret;
  +                } else if (con.match != null && refno < 0) {
  +                    int index = -refno;
  +                    int save = con.match.getEnd(index);
  +                    con.match.setEnd(index, offset);
  +                    int ret = this. matchCharArray (con, op.next, offset, dx, opts);
  +                    if (ret < 0)  con.match.setEnd(index, save);
  +                    return ret;
                   }
  -                if (!go)  return -1;
  +                op = op.next;
                   break;
   
  -              case '<':
  -                if (con.length == 0 || offset == con.limit)  return -1;
  -                if (getWordType(target, con.start, con.limit, offset, opts) != WT_LETTER
  -                    || getPreviousWordType(target, con.start, con.limit, offset, opts) != WT_OTHER)
  -                    return -1;
  +            case Op.LOOKAHEAD:
  +                if (0 > this. matchCharArray (con, op.getChild(), offset, 1, opts))  return -1;
  +                op = op.next;
  +                break;
  +            case Op.NEGATIVELOOKAHEAD:
  +                if (0 <= this. matchCharArray (con, op.getChild(), offset, 1, opts))  return -1;
  +                op = op.next;
  +                break;
  +            case Op.LOOKBEHIND:
  +                if (0 > this. matchCharArray (con, op.getChild(), offset, -1, opts))  return -1;
  +                op = op.next;
  +                break;
  +            case Op.NEGATIVELOOKBEHIND:
  +                if (0 <= this. matchCharArray (con, op.getChild(), offset, -1, opts))  return -1;
  +                op = op.next;
                   break;
   
  -              case '>':
  -                if (con.length == 0 || offset == con.start)  return -1;
  -                if (getWordType(target, con.start, con.limit, offset, opts) != WT_OTHER
  -                    || getPreviousWordType(target, con.start, con.limit, offset, opts) != WT_LETTER)
  -                    return -1;
  +            case Op.INDEPENDENT:
  +                {
  +                    int ret = this. matchCharArray (con, op.getChild(), offset, dx, opts);
  +                    if (ret < 0)  return ret;
  +                    offset = ret;
  +                    op = op.next;
  +                }
                   break;
  -            } // switch anchor type
  -            op = op.next;
  -            break;
   
  -          case Op.BACKREFERENCE:
  -            {
  -                int refno = op.getData();
  -                if (refno <= 0 || refno >= this.nofparen)
  -                    throw new RuntimeException("Internal Error: Reference number must be more than zero: "+refno);
  -                if (con.match.getBeginning(refno) < 0
  -                    || con.match.getEnd(refno) < 0)
  -                    return -1;                // ********
  -                int o2 = con.match.getBeginning(refno);
  -                int literallen = con.match.getEnd(refno)-o2;
  -                if (!isSet(opts, IGNORE_CASE)) {
  -                    if (dx > 0) {
  -                        if (!regionMatches(target, offset, con.limit, o2, literallen))
  -                            return -1;
  -                        offset += literallen;
  -                    } else {
  -                        if (!regionMatches(target, offset-literallen, con.limit, o2, literallen))
  -                            return -1;
  -                        offset -= literallen;
  -                    }
  -                } else {
  -                    if (dx > 0) {
  -                        if (!regionMatchesIgnoreCase(target, offset, con.limit, o2, literallen))
  -                            return -1;
  -                        offset += literallen;
  -                    } else {
  -                        if (!regionMatchesIgnoreCase(target, offset-literallen, con.limit,
  -                                                     o2, literallen))
  -                            return -1;
  -                        offset -= literallen;
  -                    }
  +            case Op.MODIFIER:
  +                {
  +                    int localopts = opts;
  +                    localopts |= op.getData();
  +                    localopts &= ~op.getData2();
  +                    //System.err.println("MODIFIER: "+Integer.toString(opts, 16)+" -> "+Integer.toString(localopts, 16));
  +                    int ret = this. matchCharArray (con, op.getChild(), offset, dx, localopts);
  +                    if (ret < 0)  return ret;
  +                    offset = ret;
  +                    op = op.next;
                   }
  -            }
  -            op = op.next;
  -            break;
  -          case Op.STRING:
  -            {
  -                String literal = op.getString();
  -                int literallen = literal.length();
  -                if (!isSet(opts, IGNORE_CASE)) {
  -                    if (dx > 0) {
  -                        if (!regionMatches(target, offset, con.limit, literal, literallen))
  -                            return -1;
  -                        offset += literallen;
  -                    } else {
  -                        if (!regionMatches(target, offset-literallen, con.limit, literal, literallen))
  -                            return -1;
  -                        offset -= literallen;
  -                    }
  -                } else {
  -                    if (dx > 0) {
  -                        if (!regionMatchesIgnoreCase(target, offset, con.limit, literal, literallen))
  -                            return -1;
  -                        offset += literallen;
  +                break;
  +
  +            case Op.CONDITION:
  +                {
  +                    Op.ConditionOp cop = (Op.ConditionOp)op;
  +                    boolean matchp = false;
  +                    if (cop.refNumber > 0) {
  +                        if (cop.refNumber >= this.nofparen)
  +                            throw new RuntimeException("Internal Error: Reference number must be more than zero: "+cop.refNumber);
  +                        matchp = con.match.getBeginning(cop.refNumber) >= 0
  +                                 && con.match.getEnd(cop.refNumber) >= 0;
                       } else {
  -                        if (!regionMatchesIgnoreCase(target, offset-literallen, con.limit,
  -                                                     literal, literallen))
  -                            return -1;
  -                        offset -= literallen;
  +                        matchp = 0 <= this. matchCharArray (con, cop.condition, offset, dx, opts);
                       }
  -                }
  -            }
  -            op = op.next;
  -            break;
   
  -          case Op.CLOSURE:
  -            {
  -                /*
  -                 * Saves current position to avoid
  -                 * zero-width repeats.
  -                 */
  -                int id = op.getData();
  -                if (id >= 0) {
  -                    int previousOffset = con.offsets[id];
  -                    if (previousOffset < 0 || previousOffset != offset) {
  -                        con.offsets[id] = offset;
  +                    if (matchp) {
  +                        op = cop.yes;
  +                    } else if (cop.no != null) {
  +                        op = cop.no;
                       } else {
  -                        con.offsets[id] = -1;
  -                        op = op.next;
  -                        break;
  +                        op = cop.next;
                       }
                   }
  -
  -                int ret = this. matchCharArray (con, op.getChild(), offset, dx, opts);
  -                if (id >= 0)  con.offsets[id] = -1;
  -                if (ret >= 0)  return ret;
  -                op = op.next;
  -            }
  -            break;
  -
  -          case Op.QUESTION:
  -            {
  -                int ret = this. matchCharArray (con, op.getChild(), offset, dx, opts);
  -                if (ret >= 0)  return ret;
  -                op = op.next;
  -            }
  -            break;
  -
  -          case Op.NONGREEDYCLOSURE:
  -          case Op.NONGREEDYQUESTION:
  -            {
  -                int ret = this. matchCharArray (con, op.next, offset, dx, opts);
  -                if (ret >= 0)  return ret;
  -                op = op.getChild();
  -            }
  -            break;
  -
  -          case Op.UNION:
  -            for (int i = 0;  i < op.size();  i ++) {
  -                int ret = this. matchCharArray (con, op.elementAt(i), offset, dx, opts);
  -                //System.err.println("UNION: "+i+", ret="+ret);
  -                if (ret >= 0)  return ret;
  -            }
  -            return -1;
  -
  -          case Op.CAPTURE:
  -            int refno = op.getData();
  -            if (con.match != null && refno > 0) {
  -                int save = con.match.getBeginning(refno);
  -                con.match.setBeginning(refno, offset);
  -                int ret = this. matchCharArray (con, op.next, offset, dx, opts);
  -                if (ret < 0)  con.match.setBeginning(refno, save);
  -                return ret;
  -            } else if (con.match != null && refno < 0) {
  -                int index = -refno;
  -                int save = con.match.getEnd(index);
  -                con.match.setEnd(index, offset);
  -                int ret = this. matchCharArray (con, op.next, offset, dx, opts);
  -                if (ret < 0)  con.match.setEnd(index, save);
  -                return ret;
  -            }
  -            op = op.next;
  -            break;
  -
  -          case Op.LOOKAHEAD:
  -            if (0 > this. matchCharArray (con, op.getChild(), offset, 1, opts))  return -1;
  -            op = op.next;
  -            break;
  -          case Op.NEGATIVELOOKAHEAD:
  -            if (0 <= this. matchCharArray (con, op.getChild(), offset, 1, opts))  return -1;
  -            op = op.next;
  -            break;
  -          case Op.LOOKBEHIND:
  -            if (0 > this. matchCharArray (con, op.getChild(), offset, -1, opts))  return -1;
  -            op = op.next;
  -            break;
  -          case Op.NEGATIVELOOKBEHIND:
  -            if (0 <= this. matchCharArray (con, op.getChild(), offset, -1, opts))  return -1;
  -            op = op.next;
  -            break;
  -
  -          case Op.INDEPENDENT:
  -            {
  -                int ret = this. matchCharArray (con, op.getChild(), offset, dx, opts);
  -                if (ret < 0)  return ret;
  -                offset = ret;
  -                op = op.next;
  -            }
  -            break;
  -
  -          case Op.MODIFIER:
  -            {
  -                int localopts = opts;
  -                localopts |= op.getData();
  -                localopts &= ~op.getData2();
  -                //System.err.println("MODIFIER: "+Integer.toString(opts, 16)+" -> "+Integer.toString(localopts, 16));
  -                int ret = this. matchCharArray (con, op.getChild(), offset, dx, localopts);
  -                if (ret < 0)  return ret;
  -                offset = ret;
  -                op = op.next;
  -            }
  -            break;
  +                break;
   
  -          case Op.CONDITION:
  -            {
  -                Op.ConditionOp cop = (Op.ConditionOp)op;
  -                boolean matchp = false;
  -                if (cop.refNumber > 0) {
  -                    if (cop.refNumber >= this.nofparen)
  -                        throw new RuntimeException("Internal Error: Reference number must be more than zero: "+cop.refNumber);
  -                    matchp = con.match.getBeginning(cop.refNumber) >= 0
  -                        && con.match.getEnd(cop.refNumber) >= 0;
  -                } else {
  -                    matchp = 0 <= this. matchCharArray (con, cop.condition, offset, dx, opts);
  -                }
  +            default:
  +                throw new RuntimeException("Unknown operation type: "+op.type);
  +            } // switch (op.type)
  +        } // while
  +    }
   
  -                if (matchp) {
  -                    op = cop.yes;
  -                } else if (cop.no != null) {
  -                    op = cop.no;
  -                } else {
  -                    op = cop.next;
  -                }
  -            }
  -            break;
  +    private static final int getPreviousWordType(char[]  target, int begin, int end,
  +                                                 int offset, int opts) {
  +        int ret = getWordType(target, begin, end, --offset, opts);
  +        while (ret == WT_IGNORE)
  +            ret = getWordType(target, begin, end, --offset, opts);
  +        return ret;
  +    }
   
  -          default:
  -            throw new RuntimeException("Unknown operation type: "+op.type);
  -        } // switch (op.type)
  -    } // while
  -}
  -    
  -private static final int getPreviousWordType(char[]  target, int begin, int end,
  -                                             int offset, int opts) {
  -    int ret = getWordType(target, begin, end, --offset, opts);
  -    while (ret == WT_IGNORE)
  -        ret = getWordType(target, begin, end, --offset, opts);
  -    return ret;
  -}
  -
  -private static final int getWordType(char[]  target, int begin, int end,
  -                                     int offset, int opts) {
  -    if (offset < begin || offset >= end)  return WT_OTHER;
  -    return getWordType0( target [  offset ] , opts);
  -}
  +    private static final int getWordType(char[]  target, int begin, int end,
  +                                         int offset, int opts) {
  +        if (offset < begin || offset >= end)  return WT_OTHER;
  +        return getWordType0( target [  offset ] , opts);
  +    }
   
   
   
  -private static final boolean regionMatches(char[]  target, int offset, int limit,
  -                                           String part, int partlen) {
  -    if (offset < 0)  return false;
  -    if (limit-offset < partlen)
  -        return false;
  -    int i = 0;
  -    while (partlen-- > 0) {
  -        if ( target [  offset++ ]  != part.charAt(i++))
  +    private static final boolean regionMatches(char[]  target, int offset, int limit,
  +                                               String part, int partlen) {
  +        if (offset < 0)  return false;
  +        if (limit-offset < partlen)
               return false;
  +        int i = 0;
  +        while (partlen-- > 0) {
  +            if ( target [  offset++ ]  != part.charAt(i++))
  +                return false;
  +        }
  +        return true;
       }
  -    return true;
  -}
   
  -private static final boolean regionMatches(char[]  target, int offset, int limit,
  -                                           int offset2, int partlen) {
  -    if (offset < 0)  return false;
  -    if (limit-offset < partlen)
  -        return false;
  -    int i = offset2;
  -    while (partlen-- > 0) {
  -        if ( target [  offset++ ]  !=  target [  i++ ] )
  +    private static final boolean regionMatches(char[]  target, int offset, int limit,
  +                                               int offset2, int partlen) {
  +        if (offset < 0)  return false;
  +        if (limit-offset < partlen)
               return false;
  +        int i = offset2;
  +        while (partlen-- > 0) {
  +            if ( target [  offset++ ]  !=  target [  i++ ] )
  +                return false;
  +        }
  +        return true;
       }
  -    return true;
  -}
   
   /**
    * @see java.lang.String#regionMatches
    */
  -private static final boolean regionMatchesIgnoreCase(char[]  target, int offset, int limit,
  -                                                     String part, int partlen) {
  -    if (offset < 0)  return false;
  -    if (limit-offset < partlen)
  -        return false;
  -    int i = 0;
  -    while (partlen-- > 0) {
  -        char ch1 =  target [  offset++ ] ;
  -        char ch2 = part.charAt(i++);
  -        if (ch1 == ch2)
  -            continue;
  -        char uch1 = Character.toUpperCase(ch1);
  -        char uch2 = Character.toUpperCase(ch2);
  -        if (uch1 == uch2)
  -            continue;
  -        if (Character.toLowerCase(uch1) != Character.toLowerCase(uch2))
  +    private static final boolean regionMatchesIgnoreCase(char[]  target, int offset, int limit,
  +                                                         String part, int partlen) {
  +        if (offset < 0)  return false;
  +        if (limit-offset < partlen)
               return false;
  +        int i = 0;
  +        while (partlen-- > 0) {
  +            char ch1 =  target [  offset++ ] ;
  +            char ch2 = part.charAt(i++);
  +            if (ch1 == ch2)
  +                continue;
  +            char uch1 = Character.toUpperCase(ch1);
  +            char uch2 = Character.toUpperCase(ch2);
  +            if (uch1 == uch2)
  +                continue;
  +            if (Character.toLowerCase(uch1) != Character.toLowerCase(uch2))
  +                return false;
  +        }
  +        return true;
       }
  -    return true;
  -}
   
  -private static final boolean regionMatchesIgnoreCase(char[]  target, int offset, int limit,
  -                                                     int offset2, int partlen) {
  -    if (offset < 0)  return false;
  -    if (limit-offset < partlen)
  -        return false;
  -    int i = offset2;
  -    while (partlen-- > 0) {
  -        char ch1 =  target [  offset++ ] ;
  -        char ch2 =  target [  i++ ] ;
  -        if (ch1 == ch2)
  -            continue;
  -        char uch1 = Character.toUpperCase(ch1);
  -        char uch2 = Character.toUpperCase(ch2);
  -        if (uch1 == uch2)
  -            continue;
  -        if (Character.toLowerCase(uch1) != Character.toLowerCase(uch2))
  +    private static final boolean regionMatchesIgnoreCase(char[]  target, int offset, int limit,
  +                                                         int offset2, int partlen) {
  +        if (offset < 0)  return false;
  +        if (limit-offset < partlen)
               return false;
  +        int i = offset2;
  +        while (partlen-- > 0) {
  +            char ch1 =  target [  offset++ ] ;
  +            char ch2 =  target [  i++ ] ;
  +            if (ch1 == ch2)
  +                continue;
  +            char uch1 = Character.toUpperCase(ch1);
  +            char uch2 = Character.toUpperCase(ch2);
  +            if (uch1 == uch2)
  +                continue;
  +            if (Character.toLowerCase(uch1) != Character.toLowerCase(uch2))
  +                return false;
  +        }
  +        return true;
       }
  -    return true;
  -}
  -
  -
  -
  -/* -*- java -*-
  - *
  - * (C) Copyright IBM Corp. 1998-2000  All rights reserved.
  - *
  - * US Government Users Restricted Rights Use, duplication or
  - * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  - *
  - * The program is provided "as is" without any warranty express or
  - * implied, including the warranty of non-infringement and the implied
  - * warranties of merchantibility and fitness for a particular purpose.
  - * IBM will not be liable for any damages suffered by you as a result
  - * of using the Program. In no event will IBM be liable for any
  - * special, indirect or consequential damages or lost profits even if
  - * IBM has been advised of the possibility of their occurrence. IBM
  - * will not be liable for any third party claims against you.
  - */
  -
  -
  -
  -
  -
  -
  -
  -
  -
  -
  -
   
   
   
   
  -
  -
  -
  -
  -
  -
  -
  -
   /**
    *
    * @return true if the target is matched to this regular expression.
    */
  -public boolean matches(String  target) {
  -    return this.matches(target, 0,  target .length() , (Match)null);
  -}
  +    public boolean matches(String  target) {
  +        return this.matches(target, 0,  target .length() , (Match)null);
  +    }
   
   /**
    *
    * @return true if the target is matched to this regular expression.
    */
  -public boolean matches(String  target, int start, int end) {
  -    return this.matches(target, start, end, (Match)null);
  -}
  +    public boolean matches(String  target, int start, int end) {
  +        return this.matches(target, start, end, (Match)null);
  +    }
   
   /**
    *
    * @param match A Match instance for storing matching result.
    * @return Offset of the start position in <VAR>target</VAR>; or -1 if not match.
    */
  -public boolean matches(String  target, Match match) {
  -    return this.matches(target, 0,  target .length() , match);
  -}
  +    public boolean matches(String  target, Match match) {
  +        return this.matches(target, 0,  target .length() , match);
  +    }
   
   
   /**
  @@ -1498,652 +1423,624 @@
   
   
   
  -public boolean matches(String  target, int start, int end, Match match) {
  +    public boolean matches(String  target, int start, int end, Match match) {
   
  -    synchronized (this) {
  -        if (this.operations == null)
  -            this.prepare();
  -        if (this.context == null)
  -            this.context = new Context();
  -    }
  -    Context con = null;
  -    synchronized (this.context) {
  -        con = this.context.inuse ? new Context() : this.context;
  -        con.reset(target, start, end, this.numberOfClosures);
  -    }
  -    if (match != null) {
  -        match.setNumberOfGroups(this.nofparen);
  -        match.setSource(target);
  -    } else if (this.hasBackReferences) {
  -        match = new Match();
  -        match.setNumberOfGroups(this.nofparen);
  -                                                // Need not to call setSource() because
  -                                                // a caller can not access this match instance.
  -    }
  -    con.match = match;
  -
  -    if (this.isSet(this.options, XMLSCHEMA_MODE)) {
  -        int matchEnd = this. matchString (con, this.operations, con.start, 1, this.options);
  -        //System.err.println("DEBUG: matchEnd="+matchEnd);
  -        if (matchEnd == con.limit) {
  -            if (con.match != null) {
  -                con.match.setBeginning(0, con.start);
  -                con.match.setEnd(0, matchEnd);
  +        synchronized (this) {
  +            if (this.operations == null)
  +                this.prepare();
  +            if (this.context == null)
  +                this.context = new Context();
  +        }
  +        Context con = null;
  +        synchronized (this.context) {
  +            con = this.context.inuse ? new Context() : this.context;
  +            con.reset(target, start, end, this.numberOfClosures);
  +        }
  +        if (match != null) {
  +            match.setNumberOfGroups(this.nofparen);
  +            match.setSource(target);
  +        } else if (this.hasBackReferences) {
  +            match = new Match();
  +            match.setNumberOfGroups(this.nofparen);
  +            // Need not to call setSource() because
  +            // a caller can not access this match instance.
  +        }
  +        con.match = match;
  +
  +        if (this.isSet(this.options, XMLSCHEMA_MODE)) {
  +            int matchEnd = this. matchString (con, this.operations, con.start, 1, this.options);
  +            //System.err.println("DEBUG: matchEnd="+matchEnd);
  +            if (matchEnd == con.limit) {
  +                if (con.match != null) {
  +                    con.match.setBeginning(0, con.start);
  +                    con.match.setEnd(0, matchEnd);
  +                }
  +                con.inuse = false;
  +                return true;
               }
  -            con.inuse = false;
  -            return true;
  +            return false;
           }
  -        return false;
  -    }
   
  -    /*
  -     * The pattern has only fixed string.
  -     * The engine uses Boyer-Moore.
  -     */
  -    if (this.fixedStringOnly) {
  -        //System.err.println("DEBUG: fixed-only: "+this.fixedString);
  -        int o = this.fixedStringTable.matches(target, con.start, con.limit);
  -        if (o >= 0) {
  -            if (con.match != null) {
  -                con.match.setBeginning(0, o);
  -                con.match.setEnd(0, o+this.fixedString.length());
  +        /*
  +         * The pattern has only fixed string.
  +         * The engine uses Boyer-Moore.
  +         */
  +        if (this.fixedStringOnly) {
  +            //System.err.println("DEBUG: fixed-only: "+this.fixedString);
  +            int o = this.fixedStringTable.matches(target, con.start, con.limit);
  +            if (o >= 0) {
  +                if (con.match != null) {
  +                    con.match.setBeginning(0, o);
  +                    con.match.setEnd(0, o+this.fixedString.length());
  +                }
  +                con.inuse = false;
  +                return true;
               }
               con.inuse = false;
  -            return true;
  +            return false;
           }
  -        con.inuse = false;
  -        return false;
  -    }
   
  -    /*
  -     * The pattern contains a fixed string.
  -     * The engine checks with Boyer-Moore whether the text contains the fixed string or not.
  -     * If not, it return with false.
  -     */
  -    if (this.fixedString != null) {
  -        int o = this.fixedStringTable.matches(target, con.start, con.limit);
  -        if (o < 0) {
  -            //System.err.println("Non-match in fixed-string search.");
  -            con.inuse = false;
  -            return false;
  +        /*
  +         * The pattern contains a fixed string.
  +         * The engine checks with Boyer-Moore whether the text contains the fixed string or not.
  +         * If not, it return with false.
  +         */
  +        if (this.fixedString != null) {
  +            int o = this.fixedStringTable.matches(target, con.start, con.limit);
  +            if (o < 0) {
  +                //System.err.println("Non-match in fixed-string search.");
  +                con.inuse = false;
  +                return false;
  +            }
           }
  -    }
   
  -    int limit = con.limit-this.minlength;
  -    int matchStart;
  -    int matchEnd = -1;
  -
  -    /*
  -     * Checks whether the expression starts with ".*".
  -     */
  -    if (this.operations.type == Op.CLOSURE && this.operations.getChild().type == Op.DOT) {
  -        if (isSet(this.options, SINGLE_LINE)) {
  -            matchStart = con.start;
  -            matchEnd = this. matchString (con, this.operations, con.start, 1, this.options);
  -        } else {
  -            boolean previousIsEOL = true;
  -            for (matchStart = con.start;  matchStart <= limit;  matchStart ++) {
  -                int ch =  target .charAt(  matchStart ) ;
  -                if (isEOLChar(ch)) {
  -                    previousIsEOL = true;
  -                } else {
  -                    if (previousIsEOL) {
  -                        if (0 <= (matchEnd = this. matchString (con, this.operations,
  -                                                        matchStart, 1, this.options)))
  -                            break;
  +        int limit = con.limit-this.minlength;
  +        int matchStart;
  +        int matchEnd = -1;
  +
  +        /*
  +         * Checks whether the expression starts with ".*".
  +         */
  +        if (this.operations.type == Op.CLOSURE && this.operations.getChild().type == Op.DOT) {
  +            if (isSet(this.options, SINGLE_LINE)) {
  +                matchStart = con.start;
  +                matchEnd = this. matchString (con, this.operations, con.start, 1, this.options);
  +            } else {
  +                boolean previousIsEOL = true;
  +                for (matchStart = con.start;  matchStart <= limit;  matchStart ++) {
  +                    int ch =  target .charAt(  matchStart ) ;
  +                    if (isEOLChar(ch)) {
  +                        previousIsEOL = true;
  +                    } else {
  +                        if (previousIsEOL) {
  +                            if (0 <= (matchEnd = this. matchString (con, this.operations,
  +                                                                    matchStart, 1, this.options)))
  +                                break;
  +                        }
  +                        previousIsEOL = false;
  +                    }
  +                }
  +            }
  +        }
  +
  +        /*
  +         * Optimization against the first character.
  +         */
  +        else if (this.firstChar != null) {
  +            //System.err.println("DEBUG: with firstchar-matching: "+this.firstChar);
  +            RangeToken range = this.firstChar;
  +            if (this.isSet(this.options, IGNORE_CASE)) {
  +                range = this.firstChar.getCaseInsensitiveToken();
  +                for (matchStart = con.start;  matchStart <= limit;  matchStart ++) {
  +                    int ch =  target .charAt(  matchStart ) ;
  +                    if (REUtil.isHighSurrogate(ch) && matchStart+1 < con.limit) {
  +                        ch = REUtil.composeFromSurrogates(ch,  target .charAt(  matchStart+1 ) );
  +                        if (!range.match(ch))  continue;
  +                    } else {
  +                        if (!range.match(ch)) {
  +                            char ch1 = Character.toUpperCase((char)ch);
  +                            if (!range.match(ch1))
  +                                if (!range.match(Character.toLowerCase(ch1)))
  +                                    continue;
  +                        }
                       }
  -                    previousIsEOL = false;
  +                    if (0 <= (matchEnd = this. matchString (con, this.operations,
  +                                                            matchStart, 1, this.options)))
  +                        break;
                   }
  -            }
  -        }
  -    }
  -
  -    /*
  -     * Optimization against the first character.
  -     */
  -    else if (this.firstChar != null) {
  -        //System.err.println("DEBUG: with firstchar-matching: "+this.firstChar);
  -        RangeToken range = this.firstChar;
  -        if (this.isSet(this.options, IGNORE_CASE)) {
  -            range = this.firstChar.getCaseInsensitiveToken();
  -            for (matchStart = con.start;  matchStart <= limit;  matchStart ++) {
  -                int ch =  target .charAt(  matchStart ) ;
  -                if (REUtil.isHighSurrogate(ch) && matchStart+1 < con.limit) {
  -                    ch = REUtil.composeFromSurrogates(ch,  target .charAt(  matchStart+1 ) );
  +            } else {
  +                for (matchStart = con.start;  matchStart <= limit;  matchStart ++) {
  +                    int ch =  target .charAt(  matchStart ) ;
  +                    if (REUtil.isHighSurrogate(ch) && matchStart+1 < con.limit)
  +                        ch = REUtil.composeFromSurrogates(ch,  target .charAt(  matchStart+1 ) );
                       if (!range.match(ch))  continue;
  -                } else {
  -                    if (!range.match(ch)) {
  -                        char ch1 = Character.toUpperCase((char)ch);
  -                        if (!range.match(ch1))
  -                            if (!range.match(Character.toLowerCase(ch1)))
  -                                continue;
  -                    }
  +                    if (0 <= (matchEnd = this. matchString (con, this.operations,
  +                                                            matchStart, 1, this.options)))
  +                        break;
                   }
  -                if (0 <= (matchEnd = this. matchString (con, this.operations,
  -                                                matchStart, 1, this.options)))
  -                    break;
               }
  -        } else {
  +        }
  +
  +        /*
  +         * Straightforward matching.
  +         */
  +        else {
               for (matchStart = con.start;  matchStart <= limit;  matchStart ++) {
  -                int ch =  target .charAt(  matchStart ) ;
  -                if (REUtil.isHighSurrogate(ch) && matchStart+1 < con.limit)
  -                    ch = REUtil.composeFromSurrogates(ch,  target .charAt(  matchStart+1 ) );
  -                if (!range.match(ch))  continue;
  -                if (0 <= (matchEnd = this. matchString (con, this.operations,
  -                                                matchStart, 1, this.options)))
  +                if (0 <= (matchEnd = this. matchString (con, this.operations, matchStart, 1, this.options)))
                       break;
               }
           }
  -    }
  -
  -    /*
  -     * Straightforward matching.
  -     */
  -    else {
  -        for (matchStart = con.start;  matchStart <= limit;  matchStart ++) {
  -            if (0 <= (matchEnd = this. matchString (con, this.operations, matchStart, 1, this.options)))
  -                break;
  -        }
  -    }
   
  -    if (matchEnd >= 0) {
  -        if (con.match != null) {
  -            con.match.setBeginning(0, matchStart);
  -            con.match.setEnd(0, matchEnd);
  +        if (matchEnd >= 0) {
  +            if (con.match != null) {
  +                con.match.setBeginning(0, matchStart);
  +                con.match.setEnd(0, matchEnd);
  +            }
  +            con.inuse = false;
  +            return true;
  +        } else {
  +            con.inuse = false;
  +            return false;
           }
  -        con.inuse = false;
  -        return true;
  -    } else {
  -        con.inuse = false;
  -        return false;
       }
  -}
   
   /**
    * @return -1 when not match; offset of the end of matched string when match.
    */
  -private int matchString (Context con, Op op, int offset, int dx, int opts) {
  +    private int matchString (Context con, Op op, int offset, int dx, int opts) {
   
   
   
   
  -    String target = con.strTarget;
  +        String target = con.strTarget;
   
   
   
   
  -    while (true) {
  -        if (op == null)
  -            return offset;
  -        if (offset > con.limit || offset < con.start)
  -            return -1;
  -        switch (op.type) {
  -          case Op.CHAR:
  -            if (isSet(opts, IGNORE_CASE)) {
  -                int ch = op.getData();
  -                if (dx > 0) {
  -                    if (offset >= con.limit || !matchIgnoreCase(ch,  target .charAt(  offset ) ))
  -                        return -1;
  -                    offset ++;
  +        while (true) {
  +            if (op == null)
  +                return offset;
  +            if (offset > con.limit || offset < con.start)
  +                return -1;
  +            switch (op.type) {
  +            case Op.CHAR:
  +                if (isSet(opts, IGNORE_CASE)) {
  +                    int ch = op.getData();
  +                    if (dx > 0) {
  +                        if (offset >= con.limit || !matchIgnoreCase(ch,  target .charAt(  offset ) ))
  +                            return -1;
  +                        offset ++;
  +                    } else {
  +                        int o1 = offset-1;
  +                        if (o1 >= con.limit || o1 < 0 || !matchIgnoreCase(ch,  target .charAt(  o1 ) ))
  +                            return -1;
  +                        offset = o1;
  +                    }
                   } else {
  -                    int o1 = offset-1;
  -                    if (o1 >= con.limit || o1 < 0 || !matchIgnoreCase(ch,  target .charAt(  o1 ) ))
  -                        return -1;
  -                    offset = o1;
  +                    int ch = op.getData();
  +                    if (dx > 0) {
  +                        if (offset >= con.limit || ch !=  target .charAt(  offset ) )
  +                            return -1;
  +                        offset ++;
  +                    } else {
  +                        int o1 = offset-1;
  +                        if (o1 >= con.limit || o1 < 0 || ch !=  target .charAt(  o1 ) )
  +                            return -1;
  +                        offset = o1;
  +                    }
                   }
  -            } else {
  -                int ch = op.getData();
  +                op = op.next;
  +                break;
  +
  +            case Op.DOT:
                   if (dx > 0) {
  -                    if (offset >= con.limit || ch !=  target .charAt(  offset ) )
  +                    if (offset >= con.limit)
  +                        return -1;
  +                    int ch =  target .charAt(  offset ) ;
  +                    if (isSet(opts, SINGLE_LINE)) {
  +                        if (REUtil.isHighSurrogate(ch) && offset+1 < con.limit)
  +                            offset ++;
  +                    } else {
  +                        if (REUtil.isHighSurrogate(ch) && offset+1 < con.limit)
  +                            ch = REUtil.composeFromSurrogates(ch,  target .charAt(  ++offset ) );
  +                        if (isEOLChar(ch))
                               return -1;
  +                    }
                       offset ++;
                   } else {
                       int o1 = offset-1;
  -                    if (o1 >= con.limit || o1 < 0 || ch !=  target .charAt(  o1 ) )
  +                    if (o1 >= con.limit || o1 < 0)
                           return -1;
  +                    int ch =  target .charAt(  o1 ) ;
  +                    if (isSet(opts, SINGLE_LINE)) {
  +                        if (REUtil.isLowSurrogate(ch) && o1-1 >= 0)
  +                            o1 --;
  +                    } else {
  +                        if (REUtil.isLowSurrogate(ch) && o1-1 >= 0)
  +                            ch = REUtil.composeFromSurrogates( target .charAt(  --o1 ) , ch);
  +                        if (!isEOLChar(ch))
  +                            return -1;
  +                    }
                       offset = o1;
                   }
  -            }
  -            op = op.next;
  -            break;
  +                op = op.next;
  +                break;
   
  -          case Op.DOT:
  -            if (dx > 0) {
  -                if (offset >= con.limit)
  -                    return -1;
  -                int ch =  target .charAt(  offset ) ;
  -                if (isSet(opts, SINGLE_LINE)) {
  -                    if (REUtil.isHighSurrogate(ch) && offset+1 < con.limit)
  -                        offset ++;
  -                } else {
  +            case Op.RANGE:
  +            case Op.NRANGE:
  +                if (dx > 0) {
  +                    if (offset >= con.limit)
  +                        return -1;
  +                    int ch =  target .charAt(  offset ) ;
                       if (REUtil.isHighSurrogate(ch) && offset+1 < con.limit)
                           ch = REUtil.composeFromSurrogates(ch,  target .charAt(  ++offset ) );
  -                    if (isEOLChar(ch))
  -                        return -1;
  -                }
  -                offset ++;
  -            } else {
  -                int o1 = offset-1;
  -                if (o1 >= con.limit || o1 < 0)
  -                    return -1;
  -                int ch =  target .charAt(  o1 ) ;
  -                if (isSet(opts, SINGLE_LINE)) {
  -                    if (REUtil.isLowSurrogate(ch) && o1-1 >= 0)
  -                        o1 --;
  +                    RangeToken tok = op.getToken();
  +                    if (isSet(opts, IGNORE_CASE)) {
  +                        tok = tok.getCaseInsensitiveToken();
  +                        if (!tok.match(ch)) {
  +                            if (ch >= 0x10000)  return -1;
  +                            char uch;
  +                            if (!tok.match(uch = Character.toUpperCase((char)ch))
  +                                && !tok.match(Character.toLowerCase(uch)))
  +                                return -1;
  +                        }
  +                    } else {
  +                        if (!tok.match(ch))  return -1;
  +                    }
  +                    offset ++;
                   } else {
  +                    int o1 = offset-1;
  +                    if (o1 >= con.limit || o1 < 0)
  +                        return -1;
  +                    int ch =  target .charAt(  o1 ) ;
                       if (REUtil.isLowSurrogate(ch) && o1-1 >= 0)
                           ch = REUtil.composeFromSurrogates( target .charAt(  --o1 ) , ch);
  -                    if (!isEOLChar(ch))
  -                        return -1;
  -                }
  -                offset = o1;
  -            }
  -            op = op.next;
  -            break;
  -            
  -          case Op.RANGE:
  -          case Op.NRANGE:
  -            if (dx > 0) {
  -                if (offset >= con.limit)
  -                    return -1;
  -                int ch =  target .charAt(  offset ) ;
  -                if (REUtil.isHighSurrogate(ch) && offset+1 < con.limit)
  -                    ch = REUtil.composeFromSurrogates(ch,  target .charAt(  ++offset ) );
  -                RangeToken tok = op.getToken();
  -                if (isSet(opts, IGNORE_CASE)) {
  -                    tok = tok.getCaseInsensitiveToken();
  -                    if (!tok.match(ch)) {
  -                        if (ch >= 0x10000)  return -1;
  -                        char uch;
  -                        if (!tok.match(uch = Character.toUpperCase((char)ch))
  -                            && !tok.match(Character.toLowerCase(uch)))
  -                            return -1;
  +                    RangeToken tok = op.getToken();
  +                    if (isSet(opts, IGNORE_CASE)) {
  +                        tok = tok.getCaseInsensitiveToken();
  +                        if (!tok.match(ch)) {
  +                            if (ch >= 0x10000)  return -1;
  +                            char uch;
  +                            if (!tok.match(uch = Character.toUpperCase((char)ch))
  +                                && !tok.match(Character.toLowerCase(uch)))
  +                                return -1;
  +                        }
  +                    } else {
  +                        if (!tok.match(ch))  return -1;
                       }
  -                } else {
  -                    if (!tok.match(ch))  return -1;
  +                    offset = o1;
                   }
  -                offset ++;
  -            } else {
  -                int o1 = offset-1;
  -                if (o1 >= con.limit || o1 < 0)
  -                    return -1;
  -                int ch =  target .charAt(  o1 ) ;
  -                if (REUtil.isLowSurrogate(ch) && o1-1 >= 0)
  -                    ch = REUtil.composeFromSurrogates( target .charAt(  --o1 ) , ch);
  -                RangeToken tok = op.getToken();
  -                if (isSet(opts, IGNORE_CASE)) {
  -                    tok = tok.getCaseInsensitiveToken();
  -                    if (!tok.match(ch)) {
  -                        if (ch >= 0x10000)  return -1;
  -                        char uch;
  -                        if (!tok.match(uch = Character.toUpperCase((char)ch))
  -                            && !tok.match(Character.toLowerCase(uch)))
  +                op = op.next;
  +                break;
  +
  +            case Op.ANCHOR:
  +                boolean go = false;
  +                switch (op.getData()) {
  +                case '^':
  +                    if (isSet(opts, MULTIPLE_LINES)) {
  +                        if (!(offset == con.start
  +                              || offset > con.start && isEOLChar( target .charAt(  offset-1 ) )))
                               return -1;
  +                    } else {
  +                        if (offset != con.start)
  +                            return -1;
                       }
  -                } else {
  -                    if (!tok.match(ch))  return -1;
  -                }
  -                offset = o1;
  -            }
  -            op = op.next;
  -            break;
  +                    break;
   
  -          case Op.ANCHOR:
  -            boolean go = false;
  -            switch (op.getData()) {
  -              case '^':
  -                if (isSet(opts, MULTIPLE_LINES)) {
  +                case '@':                         // Internal use only.
  +                    // The @ always matches line beginnings.
                       if (!(offset == con.start
                             || offset > con.start && isEOLChar( target .charAt(  offset-1 ) )))
  -                        return -1;
  -                } else {
  -                    if (offset != con.start)
                           return -1;
  -                }
  -                break;
  +                    break;
   
  -              case '@':                         // Internal use only.
  -                                                // The @ always matches line beginnings.
  -                if (!(offset == con.start
  -                      || offset > con.start && isEOLChar( target .charAt(  offset-1 ) )))
  -                    return -1;
  -                break;
  +                case '$':
  +                    if (isSet(opts, MULTIPLE_LINES)) {
  +                        if (!(offset == con.limit
  +                              || offset < con.limit && isEOLChar( target .charAt(  offset ) )))
  +                            return -1;
  +                    } else {
  +                        if (!(offset == con.limit
  +                              || offset+1 == con.limit && isEOLChar( target .charAt(  offset ) )
  +                              || offset+2 == con.limit &&  target .charAt(  offset )  == CARRIAGE_RETURN
  +                              &&  target .charAt(  offset+1 )  == LINE_FEED))
  +                            return -1;
  +                    }
  +                    break;
   
  -              case '$':
  -                if (isSet(opts, MULTIPLE_LINES)) {
  -                    if (!(offset == con.limit
  -                          || offset < con.limit && isEOLChar( target .charAt(  offset ) )))
  -                        return -1;
  -                } else {
  +                case 'A':
  +                    if (offset != con.start)  return -1;
  +                    break;
  +
  +                case 'Z':
                       if (!(offset == con.limit
                             || offset+1 == con.limit && isEOLChar( target .charAt(  offset ) )
                             || offset+2 == con.limit &&  target .charAt(  offset )  == CARRIAGE_RETURN
  -                                                   &&  target .charAt(  offset+1 )  == LINE_FEED))
  +                          &&  target .charAt(  offset+1 )  == LINE_FEED))
                           return -1;
  -                }
  -                break;
  -                
  -              case 'A':
  -                if (offset != con.start)  return -1;
  -                break;
  -
  -              case 'Z':
  -                if (!(offset == con.limit
  -                      || offset+1 == con.limit && isEOLChar( target .charAt(  offset ) )
  -                      || offset+2 == con.limit &&  target .charAt(  offset )  == CARRIAGE_RETURN
  -                                               &&  target .charAt(  offset+1 )  == LINE_FEED))
  -                    return -1;
  -                break;
  +                    break;
   
  -              case 'z':
  -                if (offset != con.limit)  return -1;
  -                break;
  +                case 'z':
  +                    if (offset != con.limit)  return -1;
  +                    break;
   
  -              case 'b':
  -                if (con.length == 0)  return -1;
  -                {
  -                    int after = getWordType(target, con.start, con.limit, offset, opts);
  -                    if (after == WT_IGNORE)  return -1;
  -                    int before = getPreviousWordType(target, con.start, con.limit, offset, opts);
  -                    if (after == before)  return -1;
  -                }
  -                break;
  +                case 'b':
  +                    if (con.length == 0)  return -1;
  +                    {
  +                        int after = getWordType(target, con.start, con.limit, offset, opts);
  +                        if (after == WT_IGNORE)  return -1;
  +                        int before = getPreviousWordType(target, con.start, con.limit, offset, opts);
  +                        if (after == before)  return -1;
  +                    }
  +                    break;
   
  -              case 'B':
  -                if (con.length == 0)
  -                    go = true;
  -                else {
  -                    int after = getWordType(target, con.start, con.limit, offset, opts);
  -                    go = after == WT_IGNORE
  -                        || after == getPreviousWordType(target, con.start, con.limit, offset, opts);
  -                }
  -                if (!go)  return -1;
  -                break;
  +                case 'B':
  +                    if (con.length == 0)
  +                        go = true;
  +                    else {
  +                        int after = getWordType(target, con.start, con.limit, offset, opts);
  +                        go = after == WT_IGNORE
  +                             || after == getPreviousWordType(target, con.start, con.limit, offset, opts);
  +                    }
  +                    if (!go)  return -1;
  +                    break;
   
  -              case '<':
  -                if (con.length == 0 || offset == con.limit)  return -1;
  -                if (getWordType(target, con.start, con.limit, offset, opts) != WT_LETTER
  -                    || getPreviousWordType(target, con.start, con.limit, offset, opts) != WT_OTHER)
  -                    return -1;
  -                break;
  +                case '<':
  +                    if (con.length == 0 || offset == con.limit)  return -1;
  +                    if (getWordType(target, con.start, con.limit, offset, opts) != WT_LETTER
  +                        || getPreviousWordType(target, con.start, con.limit, offset, opts) != WT_OTHER)
  +                        return -1;
  +                    break;
   
  -              case '>':
  -                if (con.length == 0 || offset == con.start)  return -1;
  -                if (getWordType(target, con.start, con.limit, offset, opts) != WT_OTHER
  -                    || getPreviousWordType(target, con.start, con.limit, offset, opts) != WT_LETTER)
  -                    return -1;
  +                case '>':
  +                    if (con.length == 0 || offset == con.start)  return -1;
  +                    if (getWordType(target, con.start, con.limit, offset, opts) != WT_OTHER
  +                        || getPreviousWordType(target, con.start, con.limit, offset, opts) != WT_LETTER)
  +                        return -1;
  +                    break;
  +                } // switch anchor type
  +                op = op.next;
                   break;
  -            } // switch anchor type
  -            op = op.next;
  -            break;
   
  -          case Op.BACKREFERENCE:
  -            {
  -                int refno = op.getData();
  -                if (refno <= 0 || refno >= this.nofparen)
  -                    throw new RuntimeException("Internal Error: Reference number must be more than zero: "+refno);
  -                if (con.match.getBeginning(refno) < 0
  -                    || con.match.getEnd(refno) < 0)
  -                    return -1;                // ********
  -                int o2 = con.match.getBeginning(refno);
  -                int literallen = con.match.getEnd(refno)-o2;
  -                if (!isSet(opts, IGNORE_CASE)) {
  -                    if (dx > 0) {
  -                        if (!regionMatches(target, offset, con.limit, o2, literallen))
  -                            return -1;
  -                        offset += literallen;
  -                    } else {
  -                        if (!regionMatches(target, offset-literallen, con.limit, o2, literallen))
  -                            return -1;
  -                        offset -= literallen;
  -                    }
  -                } else {
  -                    if (dx > 0) {
  -                        if (!regionMatchesIgnoreCase(target, offset, con.limit, o2, literallen))
  -                            return -1;
  -                        offset += literallen;
  +            case Op.BACKREFERENCE:
  +                {
  +                    int refno = op.getData();
  +                    if (refno <= 0 || refno >= this.nofparen)
  +                        throw new RuntimeException("Internal Error: Reference number must be more than zero: "+refno);
  +                    if (con.match.getBeginning(refno) < 0
  +                        || con.match.getEnd(refno) < 0)
  +                        return -1;                // ********
  +                    int o2 = con.match.getBeginning(refno);
  +                    int literallen = con.match.getEnd(refno)-o2;
  +                    if (!isSet(opts, IGNORE_CASE)) {
  +                        if (dx > 0) {
  +                            if (!regionMatches(target, offset, con.limit, o2, literallen))
  +                                return -1;
  +                            offset += literallen;
  +                        } else {
  +                            if (!regionMatches(target, offset-literallen, con.limit, o2, literallen))
  +                                return -1;
  +                            offset -= literallen;
  +                        }
                       } else {
  -                        if (!regionMatchesIgnoreCase(target, offset-literallen, con.limit,
  -                                                     o2, literallen))
  -                            return -1;
  -                        offset -= literallen;
  +                        if (dx > 0) {
  +                            if (!regionMatchesIgnoreCase(target, offset, con.limit, o2, literallen))
  +                                return -1;
  +                            offset += literallen;
  +                        } else {
  +                            if (!regionMatchesIgnoreCase(target, offset-literallen, con.limit,
  +                                                         o2, literallen))
  +                                return -1;
  +                            offset -= literallen;
  +                        }
                       }
                   }
  -            }
  -            op = op.next;
  -            break;
  -          case Op.STRING:
  -            {
  -                String literal = op.getString();
  -                int literallen = literal.length();
  -                if (!isSet(opts, IGNORE_CASE)) {
  -                    if (dx > 0) {
  -                        if (!regionMatches(target, offset, con.limit, literal, literallen))
  -                            return -1;
  -                        offset += literallen;
  -                    } else {
  -                        if (!regionMatches(target, offset-literallen, con.limit, literal, literallen))
  -                            return -1;
  -                        offset -= literallen;
  -                    }
  -                } else {
  -                    if (dx > 0) {
  -                        if (!regionMatchesIgnoreCase(target, offset, con.limit, literal, literallen))
  -                            return -1;
  -                        offset += literallen;
  +                op = op.next;
  +                break;
  +            case Op.STRING:
  +                {
  +                    String literal = op.getString();
  +                    int literallen = literal.length();
  +                    if (!isSet(opts, IGNORE_CASE)) {
  +                        if (dx > 0) {
  +                            if (!regionMatches(target, offset, con.limit, literal, literallen))
  +                                return -1;
  +                            offset += literallen;
  +                        } else {
  +                            if (!regionMatches(target, offset-literallen, con.limit, literal, literallen))
  +                                return -1;
  +                            offset -= literallen;
  +                        }
                       } else {
  -                        if (!regionMatchesIgnoreCase(target, offset-literallen, con.limit,
  -                                                     literal, literallen))
  -                            return -1;
  -                        offset -= literallen;
  +                        if (dx > 0) {
  +                            if (!regionMatchesIgnoreCase(target, offset, con.limit, literal, literallen))
  +                                return -1;
  +                            offset += literallen;
  +                        } else {
  +                            if (!regionMatchesIgnoreCase(target, offset-literallen, con.limit,
  +                                                         literal, literallen))
  +                                return -1;
  +                            offset -= literallen;
  +                        }
                       }
                   }
  -            }
  -            op = op.next;
  -            break;
  +                op = op.next;
  +                break;
   
  -          case Op.CLOSURE:
  -            {
  -                /*
  -                 * Saves current position to avoid
  -                 * zero-width repeats.
  -                 */
  -                int id = op.getData();
  -                if (id >= 0) {
  -                    int previousOffset = con.offsets[id];
  -                    if (previousOffset < 0 || previousOffset != offset) {
  -                        con.offsets[id] = offset;
  -                    } else {
  -                        con.offsets[id] = -1;
  -                        op = op.next;
  -                        break;
  +            case Op.CLOSURE:
  +                {
  +                    /*
  +                     * Saves current position to avoid
  +                     * zero-width repeats.
  +                     */
  +                    int id = op.getData();
  +                    if (id >= 0) {
  +                        int previousOffset = con.offsets[id];
  +                        if (previousOffset < 0 || previousOffset != offset) {
  +                            con.offsets[id] = offset;
  +                        } else {
  +                            con.offsets[id] = -1;
  +                            op = op.next;
  +                            break;
  +                        }
                       }
  -                }
  -
  -                int ret = this. matchString (con, op.getChild(), offset, dx, opts);
  -                if (id >= 0)  con.offsets[id] = -1;
  -                if (ret >= 0)  return ret;
  -                op = op.next;
  -            }
  -            break;
   
  -          case Op.QUESTION:
  -            {
  -                int ret = this. matchString (con, op.getChild(), offset, dx, opts);
  -                if (ret >= 0)  return ret;
  -                op = op.next;
  -            }
  -            break;
  +                    int ret = this. matchString (con, op.getChild(), offset, dx, opts);
  +                    if (id >= 0)  con.offsets[id] = -1;
  +                    if (ret >= 0)  return ret;
  +                    op = op.next;
  +                }
  +                break;
   
  -          case Op.NONGREEDYCLOSURE:
  -          case Op.NONGREEDYQUESTION:
  -            {
  -                int ret = this. matchString (con, op.next, offset, dx, opts);
  -                if (ret >= 0)  return ret;
  -                op = op.getChild();
  -            }
  -            break;
  +            case Op.QUESTION:
  +                {
  +                    int ret = this. matchString (con, op.getChild(), offset, dx, opts);
  +                    if (ret >= 0)  return ret;
  +                    op = op.next;
  +                }
  +                break;
   
  -          case Op.UNION:
  -            for (int i = 0;  i < op.size();  i ++) {
  -                int ret = this. matchString (con, op.elementAt(i), offset, dx, opts);
  -                //System.err.println("UNION: "+i+", ret="+ret);
  -                if (ret >= 0)  return ret;
  -            }
  -            return -1;
  -
  -          case Op.CAPTURE:
  -            int refno = op.getData();
  -            if (con.match != null && refno > 0) {
  -                int save = con.match.getBeginning(refno);
  -                con.match.setBeginning(refno, offset);
  -                int ret = this. matchString (con, op.next, offset, dx, opts);
  -                if (ret < 0)  con.match.setBeginning(refno, save);
  -                return ret;
  -            } else if (con.match != null && refno < 0) {
  -                int index = -refno;
  -                int save = con.match.getEnd(index);
  -                con.match.setEnd(index, offset);
  -                int ret = this. matchString (con, op.next, offset, dx, opts);
  -                if (ret < 0)  con.match.setEnd(index, save);
  -                return ret;
  -            }
  -            op = op.next;
  -            break;
  +            case Op.NONGREEDYCLOSURE:
  +            case Op.NONGREEDYQUESTION:
  +                {
  +                    int ret = this. matchString (con, op.next, offset, dx, opts);
  +                    if (ret >= 0)  return ret;
  +                    op = op.getChild();
  +                }
  +                break;
   
  -          case Op.LOOKAHEAD:
  -            if (0 > this. matchString (con, op.getChild(), offset, 1, opts))  return -1;
  -            op = op.next;
  -            break;
  -          case Op.NEGATIVELOOKAHEAD:
  -            if (0 <= this. matchString (con, op.getChild(), offset, 1, opts))  return -1;
  -            op = op.next;
  -            break;
  -          case Op.LOOKBEHIND:
  -            if (0 > this. matchString (con, op.getChild(), offset, -1, opts))  return -1;
  -            op = op.next;
  -            break;
  -          case Op.NEGATIVELOOKBEHIND:
  -            if (0 <= this. matchString (con, op.getChild(), offset, -1, opts))  return -1;
  -            op = op.next;
  -            break;
  +            case Op.UNION:
  +                for (int i = 0;  i < op.size();  i ++) {
  +                    int ret = this. matchString (con, op.elementAt(i), offset, dx, opts);
  +                    //System.err.println("UNION: "+i+", ret="+ret);
  +                    if (ret >= 0)  return ret;
  +                }
  +                return -1;
   
  -          case Op.INDEPENDENT:
  -            {
  -                int ret = this. matchString (con, op.getChild(), offset, dx, opts);
  -                if (ret < 0)  return ret;
  -                offset = ret;
  +            case Op.CAPTURE:
  +                int refno = op.getData();
  +                if (con.match != null && refno > 0) {
  +                    int save = con.match.getBeginning(refno);
  +                    con.match.setBeginning(refno, offset);
  +                    int ret = this. matchString (con, op.next, offset, dx, opts);
  +                    if (ret < 0)  con.match.setBeginning(refno, save);
  +                    return ret;
  +                } else if (con.match != null && refno < 0) {
  +                    int index = -refno;
  +                    int save = con.match.getEnd(index);
  +                    con.match.setEnd(index, offset);
  +                    int ret = this. matchString (con, op.next, offset, dx, opts);
  +                    if (ret < 0)  con.match.setEnd(index, save);
  +                    return ret;
  +                }
                   op = op.next;
  -            }
  -            break;
  +                break;
   
  -          case Op.MODIFIER:
  -            {
  -                int localopts = opts;
  -                localopts |= op.getData();
  -                localopts &= ~op.getData2();
  -                //System.err.println("MODIFIER: "+Integer.toString(opts, 16)+" -> "+Integer.toString(localopts, 16));
  -                int ret = this. matchString (con, op.getChild(), offset, dx, localopts);
  -                if (ret < 0)  return ret;
  -                offset = ret;
  +            case Op.LOOKAHEAD:
  +                if (0 > this. matchString (con, op.getChild(), offset, 1, opts))  return -1;
                   op = op.next;
  -            }
  -            break;
  +                break;
  +            case Op.NEGATIVELOOKAHEAD:
  +                if (0 <= this. matchString (con, op.getChild(), offset, 1, opts))  return -1;
  +                op = op.next;
  +                break;
  +            case Op.LOOKBEHIND:
  +                if (0 > this. matchString (con, op.getChild(), offset, -1, opts))  return -1;
  +                op = op.next;
  +                break;
  +            case Op.NEGATIVELOOKBEHIND:
  +                if (0 <= this. matchString (con, op.getChild(), offset, -1, opts))  return -1;
  +                op = op.next;
  +                break;
   
  -          case Op.CONDITION:
  -            {
  -                Op.ConditionOp cop = (Op.ConditionOp)op;
  -                boolean matchp = false;
  -                if (cop.refNumber > 0) {
  -                    if (cop.refNumber >= this.nofparen)
  -                        throw new RuntimeException("Internal Error: Reference number must be more than zero: "+cop.refNumber);
  -                    matchp = con.match.getBeginning(cop.refNumber) >= 0
  -                        && con.match.getEnd(cop.refNumber) >= 0;
  -                } else {
  -                    matchp = 0 <= this. matchString (con, cop.condition, offset, dx, opts);
  +            case Op.INDEPENDENT:
  +                {
  +                    int ret = this. matchString (con, op.getChild(), offset, dx, opts);
  +                    if (ret < 0)  return ret;
  +                    offset = ret;
  +                    op = op.next;
                   }
  +                break;
   
  -                if (matchp) {
  -                    op = cop.yes;
  -                } else if (cop.no != null) {
  -                    op = cop.no;
  -                } else {
  -                    op = cop.next;
  +            case Op.MODIFIER:
  +                {
  +                    int localopts = opts;
  +                    localopts |= op.getData();
  +                    localopts &= ~op.getData2();
  +                    //System.err.println("MODIFIER: "+Integer.toString(opts, 16)+" -> "+Integer.toString(localopts, 16));
  +                    int ret = this. matchString (con, op.getChild(), offset, dx, localopts);
  +                    if (ret < 0)  return ret;
  +                    offset = ret;
  +                    op = op.next;
                   }
  -            }
  -            break;
  -
  -          default:
  -            throw new RuntimeException("Unknown operation type: "+op.type);
  -        } // switch (op.type)
  -    } // while
  -}
  -    
  -private static final int getPreviousWordType(String  target, int begin, int end,
  -                                             int offset, int opts) {
  -    int ret = getWordType(target, begin, end, --offset, opts);
  -    while (ret == WT_IGNORE)
  -        ret = getWordType(target, begin, end, --offset, opts);
  -    return ret;
  -}
  -
  -private static final int getWordType(String  target, int begin, int end,
  -                                     int offset, int opts) {
  -    if (offset < begin || offset >= end)  return WT_OTHER;
  -    return getWordType0( target .charAt(  offset ) , opts);
  -}
  -
  -
  -private static final boolean regionMatches(String text, int offset, int limit,
  -                                           String part, int partlen) {
  -    if (limit-offset < partlen)  return false;
  -    return text.regionMatches(offset, part, 0, partlen);
  -}
  -
  -private static final boolean regionMatches(String text, int offset, int limit,
  -                                           int offset2, int partlen) {
  -    if (limit-offset < partlen)  return false;
  -    return text.regionMatches(offset, text, offset2, partlen);
  -}
  -
  -private static final boolean regionMatchesIgnoreCase(String text, int offset, int limit,
  -                                                     String part, int partlen) {
  -    return text.regionMatches(true, offset, part, 0, partlen);
  -}
  -
  -private static final boolean regionMatchesIgnoreCase(String text, int offset, int limit,
  -                                                     int offset2, int partlen) {
  -    if (limit-offset < partlen)  return false;
  -    return text.regionMatches(true, offset, text, offset2, partlen);
  -}
  -
  -
  +                break;
   
  +            case Op.CONDITION:
  +                {
  +                    Op.ConditionOp cop = (Op.ConditionOp)op;
  +                    boolean matchp = false;
  +                    if (cop.refNumber > 0) {
  +                        if (cop.refNumber >= this.nofparen)
  +                            throw new RuntimeException("Internal Error: Reference number must be more than zero: "+cop.refNumber);
  +                        matchp = con.match.getBeginning(cop.refNumber) >= 0
  +                                 && con.match.getEnd(cop.refNumber) >= 0;
  +                    } else {
  +                        matchp = 0 <= this. matchString (con, cop.condition, offset, dx, opts);
  +                    }
   
  +                    if (matchp) {
  +                        op = cop.yes;
  +                    } else if (cop.no != null) {
  +                        op = cop.no;
  +                    } else {
  +                        op = cop.next;
  +                    }
  +                }
  +                break;
   
  -/* -*- java -*-
  - *
  - * (C) Copyright IBM Corp. 1998-2000  All rights reserved.
  - *
  - * US Government Users Restricted Rights Use, duplication or
  - * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  - *
  - * The program is provided "as is" without any warranty express or
  - * implied, including the warranty of non-infringement and the implied
  - * warranties of merchantibility and fitness for a particular purpose.
  - * IBM will not be liable for any damages suffered by you as a result
  - * of using the Program. In no event will IBM be liable for any
  - * special, indirect or consequential damages or lost profits even if
  - * IBM has been advised of the possibility of their occurrence. IBM
  - * will not be liable for any third party claims against you.
  - */
  +            default:
  +                throw new RuntimeException("Unknown operation type: "+op.type);
  +            } // switch (op.type)
  +        } // while
  +    }
   
  +    private static final int getPreviousWordType(String  target, int begin, int end,
  +                                                 int offset, int opts) {
  +        int ret = getWordType(target, begin, end, --offset, opts);
  +        while (ret == WT_IGNORE)
  +            ret = getWordType(target, begin, end, --offset, opts);
  +        return ret;
  +    }
   
  +    private static final int getWordType(String  target, int begin, int end,
  +                                         int offset, int opts) {
  +        if (offset < begin || offset >= end)  return WT_OTHER;
  +        return getWordType0( target .charAt(  offset ) , opts);
  +    }
   
   
  +    private static final boolean regionMatches(String text, int offset, int limit,
  +                                               String part, int partlen) {
  +        if (limit-offset < partlen)  return false;
  +        return text.regionMatches(offset, part, 0, partlen);
  +    }
   
  +    private static final boolean regionMatches(String text, int offset, int limit,
  +                                               int offset2, int partlen) {
  +        if (limit-offset < partlen)  return false;
  +        return text.regionMatches(offset, text, offset2, partlen);
  +    }
   
  +    private static final boolean regionMatchesIgnoreCase(String text, int offset, int limit,
  +                                                         String part, int partlen) {
  +        return text.regionMatches(true, offset, part, 0, partlen);
  +    }
   
  +    private static final boolean regionMatchesIgnoreCase(String text, int offset, int limit,
  +                                                         int offset2, int partlen) {
  +        if (limit-offset < partlen)  return false;
  +        return text.regionMatches(true, offset, text, offset2, partlen);
  +    }
   
   
   
  @@ -2155,9 +2052,9 @@
    *
    * @return true if the target is matched to this regular expression.
    */
  -public boolean matches(CharacterIterator target) {
  -    return this.matches(target, (Match)null);
  -}
  +    public boolean matches(CharacterIterator target) {
  +        return this.matches(target, (Match)null);
  +    }
   
   
   /**
  @@ -2165,678 +2062,678 @@
    * @param match A Match instance for storing matching result.
    * @return Offset of the start position in <VAR>target</VAR>; or -1 if not match.
    */
  -
  -public boolean matches(CharacterIterator  target, Match match) {
  -    int start = target.getBeginIndex();
  -    int end = target.getEndIndex();
   
  +    public boolean matches(CharacterIterator  target, Match match) {
  +        int start = target.getBeginIndex();
  +        int end = target.getEndIndex();
   
   
  -    synchronized (this) {
  -        if (this.operations == null)
  -            this.prepare();
  -        if (this.context == null)
  -            this.context = new Context();
  -    }
  -    Context con = null;
  -    synchronized (this.context) {
  -        con = this.context.inuse ? new Context() : this.context;
  -        con.reset(target, start, end, this.numberOfClosures);
  -    }
  -    if (match != null) {
  -        match.setNumberOfGroups(this.nofparen);
  -        match.setSource(target);
  -    } else if (this.hasBackReferences) {
  -        match = new Match();
  -        match.setNumberOfGroups(this.nofparen);
  -                                                // Need not to call setSource() because
  -                                                // a caller can not access this match instance.
  -    }
  -    con.match = match;
  -
  -    if (this.isSet(this.options, XMLSCHEMA_MODE)) {
  -        int matchEnd = this. matchCharacterIterator (con, this.operations, con.start, 1, this.options);
  -        //System.err.println("DEBUG: matchEnd="+matchEnd);
  -        if (matchEnd == con.limit) {
  -            if (con.match != null) {
  -                con.match.setBeginning(0, con.start);
  -                con.match.setEnd(0, matchEnd);
  -            }
  -            con.inuse = false;
  -            return true;
  -        }
  -        return false;
  -    }
   
  -    /*
  -     * The pattern has only fixed string.
  -     * The engine uses Boyer-Moore.
  -     */
  -    if (this.fixedStringOnly) {
  -        //System.err.println("DEBUG: fixed-only: "+this.fixedString);
  -        int o = this.fixedStringTable.matches(target, con.start, con.limit);
  -        if (o >= 0) {
  -            if (con.match != null) {
  -                con.match.setBeginning(0, o);
  -                con.match.setEnd(0, o+this.fixedString.length());
  +        synchronized (this) {
  +            if (this.operations == null)
  +                this.prepare();
  +            if (this.context == null)
  +                this.context = new Context();
  +        }
  +        Context con = null;
  +        synchronized (this.context) {
  +            con = this.context.inuse ? new Context() : this.context;
  +            con.reset(target, start, end, this.numberOfClosures);
  +        }
  +        if (match != null) {
  +            match.setNumberOfGroups(this.nofparen);
  +            match.setSource(target);
  +        } else if (this.hasBackReferences) {
  +            match = new Match();
  +            match.setNumberOfGroups(this.nofparen);
  +            // Need not to call setSource() because
  +            // a caller can not access this match instance.
  +        }
  +        con.match = match;
  +
  +        if (this.isSet(this.options, XMLSCHEMA_MODE)) {
  +            int matchEnd = this. matchCharacterIterator (con, this.operations, con.start, 1, this.options);
  +            //System.err.println("DEBUG: matchEnd="+matchEnd);
  +            if (matchEnd == con.limit) {
  +                if (con.match != null) {
  +                    con.match.setBeginning(0, con.start);
  +                    con.match.setEnd(0, matchEnd);
  +                }
  +                con.inuse = false;
  +                return true;
               }
  -            con.inuse = false;
  -            return true;
  +            return false;
           }
  -        con.inuse = false;
  -        return false;
  -    }
   
  -    /*
  -     * The pattern contains a fixed string.
  -     * The engine checks with Boyer-Moore whether the text contains the fixed string or not.
  -     * If not, it return with false.
  -     */
  -    if (this.fixedString != null) {
  -        int o = this.fixedStringTable.matches(target, con.start, con.limit);
  -        if (o < 0) {
  -            //System.err.println("Non-match in fixed-string search.");
  +        /*
  +         * The pattern has only fixed string.
  +         * The engine uses Boyer-Moore.
  +         */
  +        if (this.fixedStringOnly) {
  +            //System.err.println("DEBUG: fixed-only: "+this.fixedString);
  +            int o = this.fixedStringTable.matches(target, con.start, con.limit);
  +            if (o >= 0) {
  +                if (con.match != null) {
  +                    con.match.setBeginning(0, o);
  +                    con.match.setEnd(0, o+this.fixedString.length());
  +                }
  +                con.inuse = false;
  +                return true;
  +            }
               con.inuse = false;
               return false;
           }
  -    }
   
  -    int limit = con.limit-this.minlength;
  -    int matchStart;
  -    int matchEnd = -1;
  -
  -    /*
  -     * Checks whether the expression starts with ".*".
  -     */
  -    if (this.operations.type == Op.CLOSURE && this.operations.getChild().type == Op.DOT) {
  -        if (isSet(this.options, SINGLE_LINE)) {
  -            matchStart = con.start;
  -            matchEnd = this. matchCharacterIterator (con, this.operations, con.start, 1, this.options);
  -        } else {
  -            boolean previousIsEOL = true;
  -            for (matchStart = con.start;  matchStart <= limit;  matchStart ++) {
  -                int ch =  target .setIndex(  matchStart ) ;
  -                if (isEOLChar(ch)) {
  -                    previousIsEOL = true;
  -                } else {
  -                    if (previousIsEOL) {
  -                        if (0 <= (matchEnd = this. matchCharacterIterator (con, this.operations,
  -                                                        matchStart, 1, this.options)))
  -                            break;
  +        /*
  +         * The pattern contains a fixed string.
  +         * The engine checks with Boyer-Moore whether the text contains the fixed string or not.
  +         * If not, it return with false.
  +         */
  +        if (this.fixedString != null) {
  +            int o = this.fixedStringTable.matches(target, con.start, con.limit);
  +            if (o < 0) {
  +                //System.err.println("Non-match in fixed-string search.");
  +                con.inuse = false;
  +                return false;
  +            }
  +        }
  +
  +        int limit = con.limit-this.minlength;
  +        int matchStart;
  +        int matchEnd = -1;
  +
  +        /*
  +         * Checks whether the expression starts with ".*".
  +         */
  +        if (this.operations.type == Op.CLOSURE && this.operations.getChild().type == Op.DOT) {
  +            if (isSet(this.options, SINGLE_LINE)) {
  +                matchStart = con.start;
  +                matchEnd = this. matchCharacterIterator (con, this.operations, con.start, 1, this.options);
  +            } else {
  +                boolean previousIsEOL = true;
  +                for (matchStart = con.start;  matchStart <= limit;  matchStart ++) {
  +                    int ch =  target .setIndex(  matchStart ) ;
  +                    if (isEOLChar(ch)) {
  +                        previousIsEOL = true;
  +                    } else {
  +                        if (previousIsEOL) {
  +                            if (0 <= (matchEnd = this. matchCharacterIterator (con, this.operations,
  +                                                                               matchStart, 1, this.options)))
  +                                break;
  +                        }
  +                        previousIsEOL = false;
                       }
  -                    previousIsEOL = false;
                   }
               }
           }
  -    }
   
  -    /*
  -     * Optimization against the first character.
  -     */
  -    else if (this.firstChar != null) {
  -        //System.err.println("DEBUG: with firstchar-matching: "+this.firstChar);
  -        RangeToken range = this.firstChar;
  -        if (this.isSet(this.options, IGNORE_CASE)) {
  -            range = this.firstChar.getCaseInsensitiveToken();
  -            for (matchStart = con.start;  matchStart <= limit;  matchStart ++) {
  -                int ch =  target .setIndex(  matchStart ) ;
  -                if (REUtil.isHighSurrogate(ch) && matchStart+1 < con.limit) {
  -                    ch = REUtil.composeFromSurrogates(ch,  target .setIndex(  matchStart+1 ) );
  -                    if (!range.match(ch))  continue;
  -                } else {
  -                    if (!range.match(ch)) {
  -                        char ch1 = Character.toUpperCase((char)ch);
  -                        if (!range.match(ch1))
  -                            if (!range.match(Character.toLowerCase(ch1)))
  -                                continue;
  +        /*
  +         * Optimization against the first character.
  +         */
  +        else if (this.firstChar != null) {
  +            //System.err.println("DEBUG: with firstchar-matching: "+this.firstChar);
  +            RangeToken range = this.firstChar;
  +            if (this.isSet(this.options, IGNORE_CASE)) {
  +                range = this.firstChar.getCaseInsensitiveToken();
  +                for (matchStart = con.start;  matchStart <= limit;  matchStart ++) {
  +                    int ch =  target .setIndex(  matchStart ) ;
  +                    if (REUtil.isHighSurrogate(ch) && matchStart+1 < con.limit) {
  +                        ch = REUtil.composeFromSurrogates(ch,  target .setIndex(  matchStart+1 ) );
  +                        if (!range.match(ch))  continue;
  +                    } else {
  +                        if (!range.match(ch)) {
  +                            char ch1 = Character.toUpperCase((char)ch);
  +                            if (!range.match(ch1))
  +                                if (!range.match(Character.toLowerCase(ch1)))
  +                                    continue;
  +                        }
                       }
  +                    if (0 <= (matchEnd = this. matchCharacterIterator (con, this.operations,
  +                                                                       matchStart, 1, this.options)))
  +                        break;
                   }
  -                if (0 <= (matchEnd = this. matchCharacterIterator (con, this.operations,
  -                                                matchStart, 1, this.options)))
  -                    break;
  +            } else {
  +                for (matchStart = con.start;  matchStart <= limit;  matchStart ++) {
  +                    int ch =  target .setIndex(  matchStart ) ;
  +                    if (REUtil.isHighSurrogate(ch) && matchStart+1 < con.limit)
  +                        ch = REUtil.composeFromSurrogates(ch,  target .setIndex(  matchStart+1 ) );
  +                    if (!range.match(ch))  continue;
  +                    if (0 <= (matchEnd = this. matchCharacterIterator (con, this.operations,
  +                                                                       matchStart, 1, this.options)))
  +                        break;
  +                }
               }
  -        } else {
  +        }
  +
  +        /*
  +         * Straightforward matching.
  +         */
  +        else {
               for (matchStart = con.start;  matchStart <= limit;  matchStart ++) {
  -                int ch =  target .setIndex(  matchStart ) ;
  -                if (REUtil.isHighSurrogate(ch) && matchStart+1 < con.limit)
  -                    ch = REUtil.composeFromSurrogates(ch,  target .setIndex(  matchStart+1 ) );
  -                if (!range.match(ch))  continue;
  -                if (0 <= (matchEnd = this. matchCharacterIterator (con, this.operations,
  -                                                matchStart, 1, this.options)))
  +                if (0 <= (matchEnd = this. matchCharacterIterator (con, this.operations, matchStart, 1, this.options)))
                       break;
               }
           }
  -    }
  -
  -    /*
  -     * Straightforward matching.
  -     */
  -    else {
  -        for (matchStart = con.start;  matchStart <= limit;  matchStart ++) {
  -            if (0 <= (matchEnd = this. matchCharacterIterator (con, this.operations, matchStart, 1, this.options)))
  -                break;
  -        }
  -    }
   
  -    if (matchEnd >= 0) {
  -        if (con.match != null) {
  -            con.match.setBeginning(0, matchStart);
  -            con.match.setEnd(0, matchEnd);
  +        if (matchEnd >= 0) {
  +            if (con.match != null) {
  +                con.match.setBeginning(0, matchStart);
  +                con.match.setEnd(0, matchEnd);
  +            }
  +            con.inuse = false;
  +            return true;
  +        } else {
  +            con.inuse = false;
  +            return false;
           }
  -        con.inuse = false;
  -        return true;
  -    } else {
  -        con.inuse = false;
  -        return false;
       }
  -}
   
   /**
    * @return -1 when not match; offset of the end of matched string when match.
    */
  -private int matchCharacterIterator (Context con, Op op, int offset, int dx, int opts) {
  +    private int matchCharacterIterator (Context con, Op op, int offset, int dx, int opts) {
   
   
  -    CharacterIterator target = con.ciTarget;
  +        CharacterIterator target = con.ciTarget;
   
   
   
   
   
   
  -    while (true) {
  -        if (op == null)
  -            return offset;
  -        if (offset > con.limit || offset < con.start)
  -            return -1;
  -        switch (op.type) {
  -          case Op.CHAR:
  -            if (isSet(opts, IGNORE_CASE)) {
  -                int ch = op.getData();
  -                if (dx > 0) {
  -                    if (offset >= con.limit || !matchIgnoreCase(ch,  target .setIndex(  offset ) ))
  -                        return -1;
  -                    offset ++;
  +        while (true) {
  +            if (op == null)
  +                return offset;
  +            if (offset > con.limit || offset < con.start)
  +                return -1;
  +            switch (op.type) {
  +            case Op.CHAR:
  +                if (isSet(opts, IGNORE_CASE)) {
  +                    int ch = op.getData();
  +                    if (dx > 0) {
  +                        if (offset >= con.limit || !matchIgnoreCase(ch,  target .setIndex(  offset ) ))
  +                            return -1;
  +                        offset ++;
  +                    } else {
  +                        int o1 = offset-1;
  +                        if (o1 >= con.limit || o1 < 0 || !matchIgnoreCase(ch,  target .setIndex(  o1 ) ))
  +                            return -1;
  +                        offset = o1;
  +                    }
                   } else {
  -                    int o1 = offset-1;
  -                    if (o1 >= con.limit || o1 < 0 || !matchIgnoreCase(ch,  target .setIndex(  o1 ) ))
  -                        return -1;
  -                    offset = o1;
  +                    int ch = op.getData();
  +                    if (dx > 0) {
  +                        if (offset >= con.limit || ch !=  target .setIndex(  offset ) )
  +                            return -1;
  +                        offset ++;
  +                    } else {
  +                        int o1 = offset-1;
  +                        if (o1 >= con.limit || o1 < 0 || ch !=  target .setIndex(  o1 ) )
  +                            return -1;
  +                        offset = o1;
  +                    }
                   }
  -            } else {
  -                int ch = op.getData();
  +                op = op.next;
  +                break;
  +
  +            case Op.DOT:
                   if (dx > 0) {
  -                    if (offset >= con.limit || ch !=  target .setIndex(  offset ) )
  +                    if (offset >= con.limit)
  +                        return -1;
  +                    int ch =  target .setIndex(  offset ) ;
  +                    if (isSet(opts, SINGLE_LINE)) {
  +                        if (REUtil.isHighSurrogate(ch) && offset+1 < con.limit)
  +                            offset ++;
  +                    } else {
  +                        if (REUtil.isHighSurrogate(ch) && offset+1 < con.limit)
  +                            ch = REUtil.composeFromSurrogates(ch,  target .setIndex(  ++offset ) );
  +                        if (isEOLChar(ch))
                               return -1;
  +                    }
                       offset ++;
                   } else {
                       int o1 = offset-1;
  -                    if (o1 >= con.limit || o1 < 0 || ch !=  target .setIndex(  o1 ) )
  +                    if (o1 >= con.limit || o1 < 0)
                           return -1;
  +                    int ch =  target .setIndex(  o1 ) ;
  +                    if (isSet(opts, SINGLE_LINE)) {
  +                        if (REUtil.isLowSurrogate(ch) && o1-1 >= 0)
  +                            o1 --;
  +                    } else {
  +                        if (REUtil.isLowSurrogate(ch) && o1-1 >= 0)
  +                            ch = REUtil.composeFromSurrogates( target .setIndex(  --o1 ) , ch);
  +                        if (!isEOLChar(ch))
  +                            return -1;
  +                    }
                       offset = o1;
                   }
  -            }
  -            op = op.next;
  -            break;
  +                op = op.next;
  +                break;
   
  -          case Op.DOT:
  -            if (dx > 0) {
  -                if (offset >= con.limit)
  -                    return -1;
  -                int ch =  target .setIndex(  offset ) ;
  -                if (isSet(opts, SINGLE_LINE)) {
  -                    if (REUtil.isHighSurrogate(ch) && offset+1 < con.limit)
  -                        offset ++;
  -                } else {
  +            case Op.RANGE:
  +            case Op.NRANGE:
  +                if (dx > 0) {
  +                    if (offset >= con.limit)
  +                        return -1;
  +                    int ch =  target .setIndex(  offset ) ;
                       if (REUtil.isHighSurrogate(ch) && offset+1 < con.limit)
                           ch = REUtil.composeFromSurrogates(ch,  target .setIndex(  ++offset ) );
  -                    if (isEOLChar(ch))
  -                        return -1;
  -                }
  -                offset ++;
  -            } else {
  -                int o1 = offset-1;
  -                if (o1 >= con.limit || o1 < 0)
  -                    return -1;
  -                int ch =  target .setIndex(  o1 ) ;
  -                if (isSet(opts, SINGLE_LINE)) {
  -                    if (REUtil.isLowSurrogate(ch) && o1-1 >= 0)
  -                        o1 --;
  +                    RangeToken tok = op.getToken();
  +                    if (isSet(opts, IGNORE_CASE)) {
  +                        tok = tok.getCaseInsensitiveToken();
  +                        if (!tok.match(ch)) {
  +                            if (ch >= 0x10000)  return -1;
  +                            char uch;
  +                            if (!tok.match(uch = Character.toUpperCase((char)ch))
  +                                && !tok.match(Character.toLowerCase(uch)))
  +                                return -1;
  +                        }
  +                    } else {
  +                        if (!tok.match(ch))  return -1;
  +                    }
  +                    offset ++;
                   } else {
  +                    int o1 = offset-1;
  +                    if (o1 >= con.limit || o1 < 0)
  +                        return -1;
  +                    int ch =  target .setIndex(  o1 ) ;
                       if (REUtil.isLowSurrogate(ch) && o1-1 >= 0)
                           ch = REUtil.composeFromSurrogates( target .setIndex(  --o1 ) , ch);
  -                    if (!isEOLChar(ch))
  -                        return -1;
  -                }
  -                offset = o1;
  -            }
  -            op = op.next;
  -            break;
  -            
  -          case Op.RANGE:
  -          case Op.NRANGE:
  -            if (dx > 0) {
  -                if (offset >= con.limit)
  -                    return -1;
  -                int ch =  target .setIndex(  offset ) ;
  -                if (REUtil.isHighSurrogate(ch) && offset+1 < con.limit)
  -                    ch = REUtil.composeFromSurrogates(ch,  target .setIndex(  ++offset ) );
  -                RangeToken tok = op.getToken();
  -                if (isSet(opts, IGNORE_CASE)) {
  -                    tok = tok.getCaseInsensitiveToken();
  -                    if (!tok.match(ch)) {
  -                        if (ch >= 0x10000)  return -1;
  -                        char uch;
  -                        if (!tok.match(uch = Character.toUpperCase((char)ch))
  -                            && !tok.match(Character.toLowerCase(uch)))
  -                            return -1;
  +                    RangeToken tok = op.getToken();
  +                    if (isSet(opts, IGNORE_CASE)) {
  +                        tok = tok.getCaseInsensitiveToken();
  +                        if (!tok.match(ch)) {
  +                            if (ch >= 0x10000)  return -1;
  +                            char uch;
  +                            if (!tok.match(uch = Character.toUpperCase((char)ch))
  +                                && !tok.match(Character.toLowerCase(uch)))
  +                                return -1;
  +                        }
  +                    } else {
  +                        if (!tok.match(ch))  return -1;
                       }
  -                } else {
  -                    if (!tok.match(ch))  return -1;
  +                    offset = o1;
                   }
  -                offset ++;
  -            } else {
  -                int o1 = offset-1;
  -                if (o1 >= con.limit || o1 < 0)
  -                    return -1;
  -                int ch =  target .setIndex(  o1 ) ;
  -                if (REUtil.isLowSurrogate(ch) && o1-1 >= 0)
  -                    ch = REUtil.composeFromSurrogates( target .setIndex(  --o1 ) , ch);
  -                RangeToken tok = op.getToken();
  -                if (isSet(opts, IGNORE_CASE)) {
  -                    tok = tok.getCaseInsensitiveToken();
  -                    if (!tok.match(ch)) {
  -                        if (ch >= 0x10000)  return -1;
  -                        char uch;
  -                        if (!tok.match(uch = Character.toUpperCase((char)ch))
  -                            && !tok.match(Character.toLowerCase(uch)))
  +                op = op.next;
  +                break;
  +
  +            case Op.ANCHOR:
  +                boolean go = false;
  +                switch (op.getData()) {
  +                case '^':
  +                    if (isSet(opts, MULTIPLE_LINES)) {
  +                        if (!(offset == con.start
  +                              || offset > con.start && isEOLChar( target .setIndex(  offset-1 ) )))
  +                            return -1;
  +                    } else {
  +                        if (offset != con.start)
                               return -1;
                       }
  -                } else {
  -                    if (!tok.match(ch))  return -1;
  -                }
  -                offset = o1;
  -            }
  -            op = op.next;
  -            break;
  +                    break;
   
  -          case Op.ANCHOR:
  -            boolean go = false;
  -            switch (op.getData()) {
  -              case '^':
  -                if (isSet(opts, MULTIPLE_LINES)) {
  +                case '@':                         // Internal use only.
  +                    // The @ always matches line beginnings.
                       if (!(offset == con.start
                             || offset > con.start && isEOLChar( target .setIndex(  offset-1 ) )))
  -                        return -1;
  -                } else {
  -                    if (offset != con.start)
                           return -1;
  -                }
  -                break;
  +                    break;
   
  -              case '@':                         // Internal use only.
  -                                                // The @ always matches line beginnings.
  -                if (!(offset == con.start
  -                      || offset > con.start && isEOLChar( target .setIndex(  offset-1 ) )))
  -                    return -1;
  -                break;
  +                case '$':
  +                    if (isSet(opts, MULTIPLE_LINES)) {
  +                        if (!(offset == con.limit
  +                              || offset < con.limit && isEOLChar( target .setIndex(  offset ) )))
  +                            return -1;
  +                    } else {
  +                        if (!(offset == con.limit
  +                              || offset+1 == con.limit && isEOLChar( target .setIndex(  offset ) )
  +                              || offset+2 == con.limit &&  target .setIndex(  offset )  == CARRIAGE_RETURN
  +                              &&  target .setIndex(  offset+1 )  == LINE_FEED))
  +                            return -1;
  +                    }
  +                    break;
   
  -              case '$':
  -                if (isSet(opts, MULTIPLE_LINES)) {
  -                    if (!(offset == con.limit
  -                          || offset < con.limit && isEOLChar( target .setIndex(  offset ) )))
  -                        return -1;
  -                } else {
  +                case 'A':
  +                    if (offset != con.start)  return -1;
  +                    break;
  +
  +                case 'Z':
                       if (!(offset == con.limit
                             || offset+1 == con.limit && isEOLChar( target .setIndex(  offset ) )
                             || offset+2 == con.limit &&  target .setIndex(  offset )  == CARRIAGE_RETURN
  -                                                   &&  target .setIndex(  offset+1 )  == LINE_FEED))
  +                          &&  target .setIndex(  offset+1 )  == LINE_FEED))
  +                        return -1;
  +                    break;
  +
  +                case 'z':
  +                    if (offset != con.limit)  return -1;
  +                    break;
  +
  +                case 'b':
  +                    if (con.length == 0)  return -1;
  +                    {
  +                        int after = getWordType(target, con.start, con.limit, offset, opts);
  +                        if (after == WT_IGNORE)  return -1;
  +                        int before = getPreviousWordType(target, con.start, con.limit, offset, opts);
  +                        if (after == before)  return -1;
  +                    }
  +                    break;
  +
  +                case 'B':
  +                    if (con.length == 0)
  +                        go = true;
  +                    else {
  +                        int after = getWordType(target, con.start, con.limit, offset, opts);
  +                        go = after == WT_IGNORE
  +                             || after == getPreviousWordType(target, con.start, con.limit, offset, opts);
  +                    }
  +                    if (!go)  return -1;
  +                    break;
  +
  +                case '<':
  +                    if (con.length == 0 || offset == con.limit)  return -1;
  +                    if (getWordType(target, con.start, con.limit, offset, opts) != WT_LETTER
  +                        || getPreviousWordType(target, con.start, con.limit, offset, opts) != WT_OTHER)
  +                        return -1;
  +                    break;
  +
  +                case '>':
  +                    if (con.length == 0 || offset == con.start)  return -1;
  +                    if (getWordType(target, con.start, con.limit, offset, opts) != WT_OTHER
  +                        || getPreviousWordType(target, con.start, con.limit, offset, opts) != WT_LETTER)
                           return -1;
  +                    break;
  +                } // switch anchor type
  +                op = op.next;
  +                break;
  +
  +            case Op.BACKREFERENCE:
  +                {
  +                    int refno = op.getData();
  +                    if (refno <= 0 || refno >= this.nofparen)
  +                        throw new RuntimeException("Internal Error: Reference number must be more than zero: "+refno);
  +                    if (con.match.getBeginning(refno) < 0
  +                        || con.match.getEnd(refno) < 0)
  +                        return -1;                // ********
  +                    int o2 = con.match.getBeginning(refno);
  +                    int literallen = con.match.getEnd(refno)-o2;
  +                    if (!isSet(opts, IGNORE_CASE)) {
  +                        if (dx > 0) {
  +                            if (!regionMatches(target, offset, con.limit, o2, literallen))
  +                                return -1;
  +                            offset += literallen;
  +                        } else {
  +                            if (!regionMatches(target, offset-literallen, con.limit, o2, literallen))
  +                                return -1;
  +                            offset -= literallen;
  +                        }
  +                    } else {
  +                        if (dx > 0) {
  +                            if (!regionMatchesIgnoreCase(target, offset, con.limit, o2, literallen))
  +                                return -1;
  +                            offset += literallen;
  +                        } else {
  +                            if (!regionMatchesIgnoreCase(target, offset-literallen, con.limit,
  +                                                         o2, literallen))
  +                                return -1;
  +                            offset -= literallen;
  +                        }
  +                    }
                   }
  +                op = op.next;
                   break;
  -                
  -              case 'A':
  -                if (offset != con.start)  return -1;
  +            case Op.STRING:
  +                {
  +                    String literal = op.getString();
  +                    int literallen = literal.length();
  +                    if (!isSet(opts, IGNORE_CASE)) {
  +                        if (dx > 0) {
  +                            if (!regionMatches(target, offset, con.limit, literal, literallen))
  +                                return -1;
  +                            offset += literallen;
  +                        } else {
  +                            if (!regionMatches(target, offset-literallen, con.limit, literal, literallen))
  +                                return -1;
  +                            offset -= literallen;
  +                        }
  +                    } else {
  +                        if (dx > 0) {
  +                            if (!regionMatchesIgnoreCase(target, offset, con.limit, literal, literallen))
  +                                return -1;
  +                            offset += literallen;
  +                        } else {
  +                            if (!regionMatchesIgnoreCase(target, offset-literallen, con.limit,
  +                                                         literal, literallen))
  +                                return -1;
  +                            offset -= literallen;
  +                        }
  +                    }
  +                }
  +                op = op.next;
                   break;
  +
  +            case Op.CLOSURE:
  +                {
  +                    /*
  +                     * Saves current position to avoid
  +                     * zero-width repeats.
  +                     */
  +                    int id = op.getData();
  +                    if (id >= 0) {
  +                        int previousOffset = con.offsets[id];
  +                        if (previousOffset < 0 || previousOffset != offset) {
  +                            con.offsets[id] = offset;
  +                        } else {
  +                            con.offsets[id] = -1;
  +                            op = op.next;
  +                            break;
  +                        }
  +                    }
   
  -              case 'Z':
  -                if (!(offset == con.limit
  -                      || offset+1 == con.limit && isEOLChar( target .setIndex(  offset ) )
  -                      || offset+2 == con.limit &&  target .setIndex(  offset )  == CARRIAGE_RETURN
  -                                               &&  target .setIndex(  offset+1 )  == LINE_FEED))
  -                    return -1;
  +                    int ret = this. matchCharacterIterator (con, op.getChild(), offset, dx, opts);
  +                    if (id >= 0)  con.offsets[id] = -1;
  +                    if (ret >= 0)  return ret;
  +                    op = op.next;
  +                }
                   break;
   
  -              case 'z':
  -                if (offset != con.limit)  return -1;
  +            case Op.QUESTION:
  +                {
  +                    int ret = this. matchCharacterIterator (con, op.getChild(), offset, dx, opts);
  +                    if (ret >= 0)  return ret;
  +                    op = op.next;
  +                }
                   break;
   
  -              case 'b':
  -                if (con.length == 0)  return -1;
  +            case Op.NONGREEDYCLOSURE:
  +            case Op.NONGREEDYQUESTION:
                   {
  -                    int after = getWordType(target, con.start, con.limit, offset, opts);
  -                    if (after == WT_IGNORE)  return -1;
  -                    int before = getPreviousWordType(target, con.start, con.limit, offset, opts);
  -                    if (after == before)  return -1;
  +                    int ret = this. matchCharacterIterator (con, op.next, offset, dx, opts);
  +                    if (ret >= 0)  return ret;
  +                    op = op.getChild();
                   }
                   break;
   
  -              case 'B':
  -                if (con.length == 0)
  -                    go = true;
  -                else {
  -                    int after = getWordType(target, con.start, con.limit, offset, opts);
  -                    go = after == WT_IGNORE
  -                        || after == getPreviousWordType(target, con.start, con.limit, offset, opts);
  +            case Op.UNION:
  +                for (int i = 0;  i < op.size();  i ++) {
  +                    int ret = this. matchCharacterIterator (con, op.elementAt(i), offset, dx, opts);
  +                    //System.err.println("UNION: "+i+", ret="+ret);
  +                    if (ret >= 0)  return ret;
                   }
  -                if (!go)  return -1;
  +                return -1;
  +
  +            case Op.CAPTURE:
  +                int refno = op.getData();
  +                if (con.match != null && refno > 0) {
  +                    int save = con.match.getBeginning(refno);
  +                    con.match.setBeginning(refno, offset);
  +                    int ret = this. matchCharacterIterator (con, op.next, offset, dx, opts);
  +                    if (ret < 0)  con.match.setBeginning(refno, save);
  +                    return ret;
  +                } else if (con.match != null && refno < 0) {
  +                    int index = -refno;
  +                    int save = con.match.getEnd(index);
  +                    con.match.setEnd(index, offset);
  +                    int ret = this. matchCharacterIterator (con, op.next, offset, dx, opts);
  +                    if (ret < 0)  con.match.setEnd(index, save);
  +                    return ret;
  +                }
  +                op = op.next;
                   break;
   
  -              case '<':
  -                if (con.length == 0 || offset == con.limit)  return -1;
  -                if (getWordType(target, con.start, con.limit, offset, opts) != WT_LETTER
  -                    || getPreviousWordType(target, con.start, con.limit, offset, opts) != WT_OTHER)
  -                    return -1;
  +            case Op.LOOKAHEAD:
  +                if (0 > this. matchCharacterIterator (con, op.getChild(), offset, 1, opts))  return -1;
  +                op = op.next;
  +                break;
  +            case Op.NEGATIVELOOKAHEAD:
  +                if (0 <= this. matchCharacterIterator (con, op.getChild(), offset, 1, opts))  return -1;
  +                op = op.next;
  +                break;
  +            case Op.LOOKBEHIND:
  +                if (0 > this. matchCharacterIterator (con, op.getChild(), offset, -1, opts))  return -1;
  +                op = op.next;
  +                break;
  +            case Op.NEGATIVELOOKBEHIND:
  +                if (0 <= this. matchCharacterIterator (con, op.getChild(), offset, -1, opts))  return -1;
  +                op = op.next;
                   break;
   
  -              case '>':
  -                if (con.length == 0 || offset == con.start)  return -1;
  -                if (getWordType(target, con.start, con.limit, offset, opts) != WT_OTHER
  -                    || getPreviousWordType(target, con.start, con.limit, offset, opts) != WT_LETTER)
  -                    return -1;
  +            case Op.INDEPENDENT:
  +                {
  +                    int ret = this. matchCharacterIterator (con, op.getChild(), offset, dx, opts);
  +                    if (ret < 0)  return ret;
  +                    offset = ret;
  +                    op = op.next;
  +                }
                   break;
  -            } // switch anchor type
  -            op = op.next;
  -            break;
   
  -          case Op.BACKREFERENCE:
  -            {
  -                int refno = op.getData();
  -                if (refno <= 0 || refno >= this.nofparen)
  -                    throw new RuntimeException("Internal Error: Reference number must be more than zero: "+refno);
  -                if (con.match.getBeginning(refno) < 0
  -                    || con.match.getEnd(refno) < 0)
  -                    return -1;                // ********
  -                int o2 = con.match.getBeginning(refno);
  -                int literallen = con.match.getEnd(refno)-o2;
  -                if (!isSet(opts, IGNORE_CASE)) {
  -                    if (dx > 0) {
  -                        if (!regionMatches(target, offset, con.limit, o2, literallen))
  -                            return -1;
  -                        offset += literallen;
  -                    } else {
  -                        if (!regionMatches(target, offset-literallen, con.limit, o2, literallen))
  -                            return -1;
  -                        offset -= literallen;
  -                    }
  -                } else {
  -                    if (dx > 0) {
  -                        if (!regionMatchesIgnoreCase(target, offset, con.limit, o2, literallen))
  -                            return -1;
  -                        offset += literallen;
  -                    } else {
  -                        if (!regionMatchesIgnoreCase(target, offset-literallen, con.limit,
  -                                                     o2, literallen))
  -                            return -1;
  -                        offset -= literallen;
  -                    }
  +            case Op.MODIFIER:
  +                {
  +                    int localopts = opts;
  +                    localopts |= op.getData();
  +                    localopts &= ~op.getData2();
  +                    //System.err.println("MODIFIER: "+Integer.toString(opts, 16)+" -> "+Integer.toString(localopts, 16));
  +                    int ret = this. matchCharacterIterator (con, op.getChild(), offset, dx, localopts);
  +                    if (ret < 0)  return ret;
  +                    offset = ret;
  +                    op = op.next;
                   }
  -            }
  -            op = op.next;
  -            break;
  -          case Op.STRING:
  -            {
  -                String literal = op.getString();
  -                int literallen = literal.length();
  -                if (!isSet(opts, IGNORE_CASE)) {
  -                    if (dx > 0) {
  -                        if (!regionMatches(target, offset, con.limit, literal, literallen))
  -                            return -1;
  -                        offset += literallen;
  -                    } else {
  -                        if (!regionMatches(target, offset-literallen, con.limit, literal, literallen))
  -                            return -1;
  -                        offset -= literallen;
  -                    }
  -                } else {
  -                    if (dx > 0) {
  -                        if (!regionMatchesIgnoreCase(target, offset, con.limit, literal, literallen))
  -                            return -1;
  -                        offset += literallen;
  +                break;
  +
  +            case Op.CONDITION:
  +                {
  +                    Op.ConditionOp cop = (Op.ConditionOp)op;
  +                    boolean matchp = false;
  +                    if (cop.refNumber > 0) {
  +                        if (cop.refNumber >= this.nofparen)
  +                            throw new RuntimeException("Internal Error: Reference number must be more than zero: "+cop.refNumber);
  +                        matchp = con.match.getBeginning(cop.refNumber) >= 0
  +                                 && con.match.getEnd(cop.refNumber) >= 0;
                       } else {
  -                        if (!regionMatchesIgnoreCase(target, offset-literallen, con.limit,
  -                                                     literal, literallen))
  -                            return -1;
  -                        offset -= literallen;
  +                        matchp = 0 <= this. matchCharacterIterator (con, cop.condition, offset, dx, opts);
                       }
  -                }
  -            }
  -            op = op.next;
  -            break;
   
  -          case Op.CLOSURE:
  -            {
  -                /*
  -                 * Saves current position to avoid
  -                 * zero-width repeats.
  -                 */
  -                int id = op.getData();
  -                if (id >= 0) {
  -                    int previousOffset = con.offsets[id];
  -                    if (previousOffset < 0 || previousOffset != offset) {
  -                        con.offsets[id] = offset;
  +                    if (matchp) {
  +                        op = cop.yes;
  +                    } else if (cop.no != null) {
  +                        op = cop.no;
                       } else {
  -                        con.offsets[id] = -1;
  -                        op = op.next;
  -                        break;
  +                        op = cop.next;
                       }
                   }
  -
  -                int ret = this. matchCharacterIterator (con, op.getChild(), offset, dx, opts);
  -                if (id >= 0)  con.offsets[id] = -1;
  -                if (ret >= 0)  return ret;
  -                op = op.next;
  -            }
  -            break;
  -
  -          case Op.QUESTION:
  -            {
  -                int ret = this. matchCharacterIterator (con, op.getChild(), offset, dx, opts);
  -                if (ret >= 0)  return ret;
  -                op = op.next;
  -            }
  -            break;
  -
  -          case Op.NONGREEDYCLOSURE:
  -          case Op.NONGREEDYQUESTION:
  -            {
  -                int ret = this. matchCharacterIterator (con, op.next, offset, dx, opts);
  -                if (ret >= 0)  return ret;
  -                op = op.getChild();
  -            }
  -            break;
  -
  -          case Op.UNION:
  -            for (int i = 0;  i < op.size();  i ++) {
  -                int ret = this. matchCharacterIterator (con, op.elementAt(i), offset, dx, opts);
  -                //System.err.println("UNION: "+i+", ret="+ret);
  -                if (ret >= 0)  return ret;
  -            }
  -            return -1;
  -
  -          case Op.CAPTURE:
  -            int refno = op.getData();
  -            if (con.match != null && refno > 0) {
  -                int save = con.match.getBeginning(refno);
  -                con.match.setBeginning(refno, offset);
  -                int ret = this. matchCharacterIterator (con, op.next, offset, dx, opts);
  -                if (ret < 0)  con.match.setBeginning(refno, save);
  -                return ret;
  -            } else if (con.match != null && refno < 0) {
  -                int index = -refno;
  -                int save = con.match.getEnd(index);
  -                con.match.setEnd(index, offset);
  -                int ret = this. matchCharacterIterator (con, op.next, offset, dx, opts);
  -                if (ret < 0)  con.match.setEnd(index, save);
  -                return ret;
  -            }
  -            op = op.next;
  -            break;
  -
  -          case Op.LOOKAHEAD:
  -            if (0 > this. matchCharacterIterator (con, op.getChild(), offset, 1, opts))  return -1;
  -            op = op.next;
  -            break;
  -          case Op.NEGATIVELOOKAHEAD:
  -            if (0 <= this. matchCharacterIterator (con, op.getChild(), offset, 1, opts))  return -1;
  -            op = op.next;
  -            break;
  -          case Op.LOOKBEHIND:
  -            if (0 > this. matchCharacterIterator (con, op.getChild(), offset, -1, opts))  return -1;
  -            op = op.next;
  -            break;
  -          case Op.NEGATIVELOOKBEHIND:
  -            if (0 <= this. matchCharacterIterator (con, op.getChild(), offset, -1, opts))  return -1;
  -            op = op.next;
  -            break;
  -
  -          case Op.INDEPENDENT:
  -            {
  -                int ret = this. matchCharacterIterator (con, op.getChild(), offset, dx, opts);
  -                if (ret < 0)  return ret;
  -                offset = ret;
  -                op = op.next;
  -            }
  -            break;
  -
  -          case Op.MODIFIER:
  -            {
  -                int localopts = opts;
  -                localopts |= op.getData();
  -                localopts &= ~op.getData2();
  -                //System.err.println("MODIFIER: "+Integer.toString(opts, 16)+" -> "+Integer.toString(localopts, 16));
  -                int ret = this. matchCharacterIterator (con, op.getChild(), offset, dx, localopts);
  -                if (ret < 0)  return ret;
  -                offset = ret;
  -                op = op.next;
  -            }
  -            break;
  +                break;
   
  -          case Op.CONDITION:
  -            {
  -                Op.ConditionOp cop = (Op.ConditionOp)op;
  -                boolean matchp = false;
  -                if (cop.refNumber > 0) {
  -                    if (cop.refNumber >= this.nofparen)
  -                        throw new RuntimeException("Internal Error: Reference number must be more than zero: "+cop.refNumber);
  -                    matchp = con.match.getBeginning(cop.refNumber) >= 0
  -                        && con.match.getEnd(cop.refNumber) >= 0;
  -                } else {
  -                    matchp = 0 <= this. matchCharacterIterator (con, cop.condition, offset, dx, opts);
  -                }
  +            default:
  +                throw new RuntimeException("Unknown operation type: "+op.type);
  +            } // switch (op.type)
  +        } // while
  +    }
   
  -                if (matchp) {
  -                    op = cop.yes;
  -                } else if (cop.no != null) {
  -                    op = cop.no;
  -                } else {
  -                    op = cop.next;
  -                }
  -            }
  -            break;
  +    private static final int getPreviousWordType(CharacterIterator  target, int begin, int end,
  +                                                 int offset, int opts) {
  +        int ret = getWordType(target, begin, end, --offset, opts);
  +        while (ret == WT_IGNORE)
  +            ret = getWordType(target, begin, end, --offset, opts);
  +        return ret;
  +    }
   
  -          default:
  -            throw new RuntimeException("Unknown operation type: "+op.type);
  -        } // switch (op.type)
  -    } // while
  -}
  -    
  -private static final int getPreviousWordType(CharacterIterator  target, int begin, int end,
  -                                             int offset, int opts) {
  -    int ret = getWordType(target, begin, end, --offset, opts);
  -    while (ret == WT_IGNORE)
  -        ret = getWordType(target, begin, end, --offset, opts);
  -    return ret;
  -}
  -
  -private static final int getWordType(CharacterIterator  target, int begin, int end,
  -                                     int offset, int opts) {
  -    if (offset < begin || offset >= end)  return WT_OTHER;
  -    return getWordType0( target .setIndex(  offset ) , opts);
  -}
  +    private static final int getWordType(CharacterIterator  target, int begin, int end,
  +                                         int offset, int opts) {
  +        if (offset < begin || offset >= end)  return WT_OTHER;
  +        return getWordType0( target .setIndex(  offset ) , opts);
  +    }
   
   
   
  -private static final boolean regionMatches(CharacterIterator  target, int offset, int limit,
  -                                           String part, int partlen) {
  -    if (offset < 0)  return false;
  -    if (limit-offset < partlen)
  -        return false;
  -    int i = 0;
  -    while (partlen-- > 0) {
  -        if ( target .setIndex(  offset++ )  != part.charAt(i++))
  +    private static final boolean regionMatches(CharacterIterator  target, int offset, int limit,
  +                                               String part, int partlen) {
  +        if (offset < 0)  return false;
  +        if (limit-offset < partlen)
               return false;
  +        int i = 0;
  +        while (partlen-- > 0) {
  +            if ( target .setIndex(  offset++ )  != part.charAt(i++))
  +                return false;
  +        }
  +        return true;
       }
  -    return true;
  -}
   
  -private static final boolean regionMatches(CharacterIterator  target, int offset, int limit,
  -                                           int offset2, int partlen) {
  -    if (offset < 0)  return false;
  -    if (limit-offset < partlen)
  -        return false;
  -    int i = offset2;
  -    while (partlen-- > 0) {
  -        if ( target .setIndex(  offset++ )  !=  target .setIndex(  i++ ) )
  +    private static final boolean regionMatches(CharacterIterator  target, int offset, int limit,
  +                                               int offset2, int partlen) {
  +        if (offset < 0)  return false;
  +        if (limit-offset < partlen)
               return false;
  +        int i = offset2;
  +        while (partlen-- > 0) {
  +            if ( target .setIndex(  offset++ )  !=  target .setIndex(  i++ ) )
  +                return false;
  +        }
  +        return true;
       }
  -    return true;
  -}
   
   /**
    * @see java.lang.String#regionMatches
    */
  -private static final boolean regionMatchesIgnoreCase(CharacterIterator  target, int offset, int limit,
  -                                                     String part, int partlen) {
  -    if (offset < 0)  return false;
  -    if (limit-offset < partlen)
  -        return false;
  -    int i = 0;
  -    while (partlen-- > 0) {
  -        char ch1 =  target .setIndex(  offset++ ) ;
  -        char ch2 = part.charAt(i++);
  -        if (ch1 == ch2)
  -            continue;
  -        char uch1 = Character.toUpperCase(ch1);
  -        char uch2 = Character.toUpperCase(ch2);
  -        if (uch1 == uch2)
  -            continue;
  -        if (Character.toLowerCase(uch1) != Character.toLowerCase(uch2))
  +    private static final boolean regionMatchesIgnoreCase(CharacterIterator  target, int offset, int limit,
  +                                                         String part, int partlen) {
  +        if (offset < 0)  return false;
  +        if (limit-offset < partlen)
               return false;
  +        int i = 0;
  +        while (partlen-- > 0) {
  +            char ch1 =  target .setIndex(  offset++ ) ;
  +            char ch2 = part.charAt(i++);
  +            if (ch1 == ch2)
  +                continue;
  +            char uch1 = Character.toUpperCase(ch1);
  +            char uch2 = Character.toUpperCase(ch2);
  +            if (uch1 == uch2)
  +                continue;
  +            if (Character.toLowerCase(uch1) != Character.toLowerCase(uch2))
  +                return false;
  +        }
  +        return true;
       }
  -    return true;
  -}
   
  -private static final boolean regionMatchesIgnoreCase(CharacterIterator  target, int offset, int limit,
  -                                                     int offset2, int partlen) {
  -    if (offset < 0)  return false;
  -    if (limit-offset < partlen)
  -        return false;
  -    int i = offset2;
  -    while (partlen-- > 0) {
  -        char ch1 =  target .setIndex(  offset++ ) ;
  -        char ch2 =  target .setIndex(  i++ ) ;
  -        if (ch1 == ch2)
  -            continue;
  -        char uch1 = Character.toUpperCase(ch1);
  -        char uch2 = Character.toUpperCase(ch2);
  -        if (uch1 == uch2)
  -            continue;
  -        if (Character.toLowerCase(uch1) != Character.toLowerCase(uch2))
  +    private static final boolean regionMatchesIgnoreCase(CharacterIterator  target, int offset, int limit,
  +                                                         int offset2, int partlen) {
  +        if (offset < 0)  return false;
  +        if (limit-offset < partlen)
               return false;
  +        int i = offset2;
  +        while (partlen-- > 0) {
  +            char ch1 =  target .setIndex(  offset++ ) ;
  +            char ch2 =  target .setIndex(  i++ ) ;
  +            if (ch1 == ch2)
  +                continue;
  +            char uch1 = Character.toUpperCase(ch1);
  +            char uch2 = Character.toUpperCase(ch2);
  +            if (uch1 == uch2)
  +                continue;
  +            if (Character.toLowerCase(uch1) != Character.toLowerCase(uch2))
  +                return false;
  +        }
  +        return true;
       }
  -    return true;
  -}
   
   
   
  @@ -3053,17 +2950,17 @@
        * "X". XML Schema mode.
        */
       static final int XMLSCHEMA_MODE = 1<<9;
  +
   
  -    
       private static final boolean isSet(int options, int flag) {
  -        return (options & flag) == flag;
  +        return(options & flag) == flag;
       }
   
       /**
        * Constructor.
        *
        * @param regex A regular expression
  -     * @exception com.ibm.regex.ParseException <VAR>regex</VAR> is not conforming to the syntax.
  +     * @exception org.apache.xerces.utils.regex.ParseException <VAR>regex</VAR> is not conforming to the syntax.
        */
       public RegularExpression(String regex) throws ParseException {
           this.setPattern(regex, null);
  @@ -3074,7 +2971,7 @@
        *
        * @param regex A regular expression
        * @param options A String consisted of "i" "m" "s" "u" "w"
  -     * @exception com.ibm.regex.ParseException <VAR>regex</VAR> is not conforming to the syntax.
  +     * @exception org.apache.xerces.utils.regex.ParseException <VAR>regex</VAR> is not conforming to the syntax.
        */
       public RegularExpression(String regex, String options) throws ParseException {
           this.setPattern(regex, options);
  @@ -3099,7 +2996,7 @@
           this.regex = newPattern;
           this.options = options;
           RegexParser rp = this.isSet(this.options, RegularExpression.XMLSCHEMA_MODE)
  -            ? new ParserForXMLSchema() : new RegexParser();
  +                         ? new ParserForXMLSchema() : new RegexParser();
           this.tokentree = rp.parse(this.regex, this.options);
           this.nofparen = rp.parennumber;
           this.hasBackReferences = rp.hasBackReferences;
  @@ -3156,7 +3053,7 @@
        *
        */
       public int hashCode() {
  -        return (this.regex+"/"+this.getOptions()).hashCode();
  +        return(this.regex+"/"+this.getOptions()).hashCode();
       }
   
       /**
  @@ -3185,35 +3082,35 @@
           }
   
           switch (Character.getType(ch)) {
  -          case Character.UPPERCASE_LETTER:      // L
  -          case Character.LOWERCASE_LETTER:      // L
  -          case Character.TITLECASE_LETTER:      // L
  -          case Character.MODIFIER_LETTER:       // L
  -          case Character.OTHER_LETTER:          // L
  -          case Character.LETTER_NUMBER:         // N
  -          case Character.DECIMAL_DIGIT_NUMBER:  // N
  -          case Character.OTHER_NUMBER:          // N
  -          case Character.COMBINING_SPACING_MARK: // Mc
  +        case Character.UPPERCASE_LETTER:      // L
  +        case Character.LOWERCASE_LETTER:      // L
  +        case Character.TITLECASE_LETTER:      // L
  +        case Character.MODIFIER_LETTER:       // L
  +        case Character.OTHER_LETTER:          // L
  +        case Character.LETTER_NUMBER:         // N
  +        case Character.DECIMAL_DIGIT_NUMBER:  // N
  +        case Character.OTHER_NUMBER:          // N
  +        case Character.COMBINING_SPACING_MARK: // Mc
               return WT_LETTER;
   
  -          case Character.FORMAT:                // Cf
  -          case Character.NON_SPACING_MARK:      // Mn
  -          case Character.ENCLOSING_MARK:        // Mc
  +        case Character.FORMAT:                // Cf
  +        case Character.NON_SPACING_MARK:      // Mn
  +        case Character.ENCLOSING_MARK:        // Mc
               return WT_IGNORE;
   
  -          case Character.CONTROL:               // Cc
  +        case Character.CONTROL:               // Cc
               switch (ch) {
  -              case '\t':
  -              case '\n':
  -              case '\u000B':
  -              case '\f':
  -              case '\r':
  +            case '\t':
  +            case '\n':
  +            case '\u000B':
  +            case '\f':
  +            case '\r':
                   return WT_OTHER;
  -              default:
  +            default:
                   return WT_IGNORE;
               }
   
  -          default:
  +        default:
               return WT_OTHER;
           }
       }
  @@ -3227,7 +3124,7 @@
   
       private static final boolean isEOLChar(int ch) {
           return ch == LINE_FEED || ch == CARRIAGE_RETURN || ch == LINE_SEPARATOR
  -            || ch == PARAGRAPH_SEPARATOR;
  +        || ch == PARAGRAPH_SEPARATOR;
       }
   
       private static final boolean isWordChar(int ch) { // Legacy word characters
  
  
  
  1.2       +1 -1      xml-xerces/java/src/org/apache/xerces/utils/regex/Token.java
  
  Index: Token.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/utils/regex/Token.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- Token.java	2000/04/04 19:31:31	1.1
  +++ Token.java	2000/05/17 18:32:57	1.2
  @@ -783,7 +783,7 @@
                           type = CHAR_SYMBOL;
                           break;
                         default:
  -                        throw new RuntimeException("com.ibm.regex.Token#getRange(): Unknown Unicode category: "+type);
  +                        throw new RuntimeException("org.apache.xerces.utils.regex.Token#getRange(): Unknown Unicode category: "+type);
                       }
                       ranges[type].addRange(i, i);
                   } // for all characters
  
  
  
  1.2       +52 -53    xml-xerces/java/src/org/apache/xerces/validators/common/CMLeaf.java
  
  Index: CMLeaf.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/validators/common/CMLeaf.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- CMLeaf.java	2000/04/04 19:36:01	1.1
  +++ CMLeaf.java	2000/05/17 18:33:00	1.2
  @@ -2,7 +2,7 @@
    * The Apache Software License, Version 1.1
    *
    *
  - * Copyright (c) 1999 The Apache Software Foundation.  All rights 
  + * Copyright (c) 1999,2000 The Apache Software Foundation.  All rights 
    * reserved.
    *
    * Redistribution and use in source and binary forms, with or without
  @@ -58,50 +58,60 @@
   package org.apache.xerces.validators.common;
   
   import org.apache.xerces.framework.XMLContentSpec;
  -import org.apache.xerces.utils.StringPool;
   import org.apache.xerces.utils.ImplementationMessages;
  +import org.apache.xerces.utils.QName;
  +import org.apache.xerces.utils.StringPool;
   
   /**
  + * Content model leaf node.
    *
  - * @version
  + * @version $Id: CMLeaf.java,v 1.2 2000/05/17 18:33:00 jeffreyr Exp $
    */
  -public class CMLeaf extends CMNode
  -{
  -    // -------------------------------------------------------------------
  -    //  Constructors
  -    // -------------------------------------------------------------------
  -    public CMLeaf(int type, int elementIndex, int position) throws CMException
  -    {
  -        super(type);
  -
  -        // Insure that its one of the types we require
  -        if (type() != XMLContentSpec.CONTENTSPECNODE_LEAF)
  -            throw new CMException(ImplementationMessages.VAL_LST);
  +public class CMLeaf 
  +    extends CMNode {
  +
  +    //
  +    // Data
  +    //
  +
  +    /** This is the element that this leaf represents. */
  +    private QName fElement = new QName();
  +
  +    /**
  +     * Part of the algorithm to convert a regex directly to a DFA
  +     * numbers each leaf sequentially. If its -1, that means its an
  +     * epsilon node. Zero and greater are non-epsilon positions.
  +     */
  +    private int fPosition = -1;
  +
  +    //
  +    // Constructors
  +    //
  +
  +    /** Constructs a content model leaf. */
  +    public CMLeaf(QName element, int position) throws CMException {
  +        super(XMLContentSpec.CONTENTSPECNODE_LEAF);
   
           // Store the element index and position
  -        fElementIndex = elementIndex;
  +        fElement.setValues(element);
           fPosition = position;
       }
   
  -    public CMLeaf(int type, int elementIndex) throws CMException
  -    {
  -        super(type);
  -
  -        // Insure that its one of the types we require
  -        if (type() != XMLContentSpec.CONTENTSPECNODE_LEAF)
  -            throw new CMException(ImplementationMessages.VAL_LST);
  +    /** Constructs a content model leaf. */
  +    public CMLeaf(QName element) throws CMException {
  +        super(XMLContentSpec.CONTENTSPECNODE_LEAF);
   
           // Store the element index and position
  -        fElementIndex = elementIndex;
  +        fElement.setValues(element);
       }
   
  +    //
  +    // Package methods
  +    //
   
  -    // -------------------------------------------------------------------
  -    //  Package final methods
  -    // -------------------------------------------------------------------
  -    final int getElemIndex()
  +    final QName getElement()
       {
  -        return fElementIndex;
  +        return fElement;
       }
   
       final int getPosition()
  @@ -114,10 +124,12 @@
           fPosition = newPosition;
       }
   
  +    //
  +    // CMNode methods
  +    //
  +
  +    // package
   
  -    // -------------------------------------------------------------------
  -    //  Package, inherited methods
  -    // -------------------------------------------------------------------
       boolean isNullable() throws CMException
       {
           // Leaf nodes are never nullable unless its an epsilon node
  @@ -126,8 +138,12 @@
   
       String toString(StringPool stringPool)
       {
  -        StringBuffer strRet = new StringBuffer(stringPool.toString(fElementIndex));
  -
  +        StringBuffer strRet = new StringBuffer(fElement.toString());
  +        strRet.append(" (");
  +        strRet.append(stringPool.toString(fElement.uri));
  +        strRet.append(',');
  +        strRet.append(stringPool.toString(fElement.localpart));
  +        strRet.append(')');
           if (fPosition >= 0)
           {
               strRet.append
  @@ -140,10 +156,8 @@
           return strRet.toString();
       }
   
  +    // protected
   
  -    // -------------------------------------------------------------------
  -    //  Protected, inherited methods
  -    // -------------------------------------------------------------------
       protected void calcFirstPos(CMStateSet toSet) throws CMException
       {
           // If we are an epsilon node, then the first pos is an empty set
  @@ -166,19 +180,4 @@
               toSet.setBit(fPosition);
       }
   
  -
  -    // -------------------------------------------------------------------
  -    //  Private data members
  -    //
  -    //  fElementIndex
  -    //      This is the element decl pool index of the element that this
  -    //      leaf represents.
  -    //
  -    //  fPosition
  -    //      Part of the algorithm to convert a regex directly to a DFA
  -    //      numbers each leaf sequentially. If its -1, that means its an
  -    //      epsilon node. Zero and greater are non-epsilon positions.
  -    // -------------------------------------------------------------------
  -    private int fElementIndex   = 0;
  -    private int fPosition       = -1;
  -};
  +} // class CMLeaf
  
  
  
  1.2       +235 -171  xml-xerces/java/src/org/apache/xerces/validators/common/DFAContentModel.java
  
  Index: DFAContentModel.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/validators/common/DFAContentModel.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- DFAContentModel.java	2000/04/04 19:36:01	1.1
  +++ DFAContentModel.java	2000/05/17 18:33:01	1.2
  @@ -2,7 +2,7 @@
    * The Apache Software License, Version 1.1
    *
    *
  - * Copyright (c) 1999 The Apache Software Foundation.  All rights 
  + * Copyright (c) 1999,2000 The Apache Software Foundation.  All rights 
    * reserved.
    *
    * Redistribution and use in source and binary forms, with or without
  @@ -58,8 +58,9 @@
   package org.apache.xerces.validators.common;
   
   import org.apache.xerces.framework.XMLContentSpec;
  -import org.apache.xerces.utils.StringPool;
   import org.apache.xerces.utils.ImplementationMessages;
  +import org.apache.xerces.utils.QName;
  +//import org.apache.xerces.utils.StringPool;
   
   /**
    * DFAContentModel is the derivative of ContentModel that does
  @@ -73,47 +74,159 @@
    * are very constrained in form and easily handled via a special case. 
    * This also makes implementation of this class much easier.
    *
  - * @version
  + * @version $Id: DFAContentModel.java,v 1.2 2000/05/17 18:33:01 jeffreyr Exp $
    */
  -public class DFAContentModel implements XMLContentModel
  -{
  +public class DFAContentModel 
  +    implements XMLContentModel {
   
       //
       // Constants
       //
  -
       // special strings
   
       /** Epsilon string. */
  -    private static final String fEpsilonString = "<<CMNODE_EPSILON>>";
  +    //private static final String fEpsilonString = "<<CMNODE_EPSILON>>";
  +    private static final int EPSILON = -2;
   
       /** End-of-content string. */
  -    private static final String fEOCString = "<<CMNODE_EOC>>";
  +    //private static final String fEOCString = "<<CMNODE_EOC>>";
  +    private static final int EOC     = -3;
   
       // debugging
   
       /** Set to true to debug content model validation. */
       private static final boolean DEBUG_VALIDATE_CONTENT = false;
  +
  +    //
  +    // Data
  +    //
  +
  +    /**
  +     * This is the map of unique input symbol elements to indices into
  +     * each state's per-input symbol transition table entry. This is part
  +     * of the built DFA information that must be kept around to do the
  +     * actual validation.
  +     */
  +    private QName fElemMap[] = null;
  +
  +    /** The element map size. */
  +    private int fElemMapSize = 0;
  +
  +    /**
  +     * The string index for the 'end of content' string that we add to
  +     * the string pool. This is used as the special name of an element
  +     * that represents the end of the syntax tree.
  +     */
  +    private int fEOCIndex = 0;
  +
  +    /**
  +     * The NFA position of the special EOC (end of content) node. This
  +     * is saved away since it's used during the DFA build.
  +     */
  +    private int fEOCPos = 0;
  +
  +    /**
  +     * The string index for the 'epsilon' string that we add to the
  +     * string pool. This represents epsilon node transitions in the
  +     * syntax tree.
  +     */
  +    private int fEpsilonIndex = 0;
   
  -    // -----------------------------------------------------------------------
  -    //  Constructors
  -    // -----------------------------------------------------------------------
  +    /**
  +     * This is an array of booleans, one per state (there are
  +     * fTransTableSize states in the DFA) that indicates whether that
  +     * state is a final state.
  +     */
  +    private boolean fFinalStateFlags[] = null;
  +
  +    /**
  +     * The list of follow positions for each NFA position (i.e. for each
  +     * non-epsilon leaf node.) This is only used during the building of
  +     * the DFA, and is let go afterwards.
  +     */
  +    private CMStateSet fFollowList[] = null;
  +
  +    /**
  +     * This is the head node of our intermediate representation. It is
  +     * only non-null during the building of the DFA (just so that it
  +     * does not have to be passed all around.) Once the DFA is built,
  +     * this is no longer required so its nulled out.
  +     */
  +    private CMNode fHeadNode = null;
  +
  +    /**
  +     * The count of leaf nodes. This is an important number that set some
  +     * limits on the sizes of data structures in the DFA process.
  +     */
  +    private int fLeafCount = 0;
  +
  +    /**
  +     * An array of non-epsilon leaf nodes, which is used during the DFA
  +     * build operation, then dropped.
  +     */
  +    private CMLeaf fLeafList[] = null;
  +
  +    /**
  +     * The string pool of our parser session. This is set during construction
  +     * and kept around.
  +     */
  +    //private StringPool fStringPool = null;
   
       /**
  +     * This is the transition table that is the main by product of all
  +     * of the effort here. It is an array of arrays of ints. The first
  +     * dimension is the number of states we end up with in the DFA. The
  +     * second dimensions is the number of unique elements in the content
  +     * model (fElemMapSize). Each entry in the second dimension indicates
  +     * the new state given that input for the first dimension's start
  +     * state.
  +     * <p>
  +     * The fElemMap array handles mapping from element indexes to
  +     * positions in the second dimension of the transition table.
  +     */
  +    private int fTransTable[][] = null;
  +
  +    /**
  +     * The number of valid entries in the transition table, and in the other
  +     * related tables such as fFinalStateFlags.
  +     */
  +    private int fTransTableSize = 0;
  +
  +    /**
  +     * Flag that indicates that even though we have a "complicated"
  +     * content model, it is valid to have no content. In other words,
  +     * all parts of the content model are optional. For example:
  +     * <pre>
  +     *      &lt;!ELEMENT AllOptional (Optional*,NotRequired?)&gt;
  +     * </pre>
  +     */
  +    private boolean fEmptyContentIsValid = false;
  +
  +    // temp variables
  +
  +    /** Temporary qualified name. */
  +    private QName fQName = new QName();
  +
  +    //
  +    // Constructors
  +    //
  +
  +    /**
        * Constructs a DFA content model.
        *
  -     * @param elementIndex  The element decl index.
        * @param stringPool    The string pool.
  -     * @param declPool      The element decl pool.
  +     * @param syntaxTree    The syntax tree of the content model.
  +     * @param leafCount     The number of leaves.
        *
        * @exception CMException Thrown if DMA can't be built.
        */
  -    public DFAContentModel( StringPool      stringPool
  -                            , CMNode        syntaxTree
  -                            , int           leafCount) throws CMException
  -    {
  +
  +   // public DFAContentModel(StringPool stringPool, 
  +   public DFAContentModel( CMNode syntaxTree, 
  +                           int leafCount) throws CMException {
  +
           // Store away our index and pools in members
  -        fStringPool = stringPool;
  +        //fStringPool = stringPool;
           fLeafCount = leafCount;
   
           //
  @@ -129,9 +242,14 @@
               fEOCString.intern();
           }
           /***/
  -        fEpsilonIndex = fStringPool.addSymbol(fEpsilonString);
  -        fEOCIndex = fStringPool.addSymbol(fEOCString);
   
  +       // fEpsilonIndex = fStringPool.addSymbol(fEpsilonString);
  +       // fEOCIndex = fStringPool.addSymbol(fEOCString);
  +
  +        fEpsilonIndex = EPSILON;
  +        fEOCIndex     = EOC;
  +
  +
           //
           //  Ok, so lets grind through the building of the DFA. This method
           //  handles the high level logic of the algorithm, but it uses a
  @@ -143,11 +261,10 @@
           //
           buildDFA(syntaxTree);
       }
  -
   
  -    // -----------------------------------------------------------------------
  -    //  Public, inherited methods
  -    // -----------------------------------------------------------------------
  +    //
  +    // XMLContentModel methods
  +    //
       
       /**
        * Check that the specified content is valid according to this
  @@ -172,8 +289,9 @@
        *
        * @exception CMException Thrown on error.
        */
  -    public int validateContent(int childCount, int[] children) throws CMException
  -    {
  +    public int validateContent(int childCount, 
  +                               QName children[]) throws CMException {
  +
           if (DEBUG_VALIDATE_CONTENT) 
               System.out.println("DFAContentModel#validateContent");
   
  @@ -195,11 +313,15 @@
                   System.out.println("!!! no children");
                   System.out.println("elemMap="+fElemMap);
                   for (int i = 0; i < fElemMap.length; i++) {
  -                    int elemIndex = fElemMap[i];
  -                    System.out.println("fElemMap["+i+"]="+elemIndex+
  -                                       " ("+
  -                                       fStringPool.toString(elemIndex)+
  +                    int uriIndex = fElemMap[i].uri;
  +                    int localpartIndex = fElemMap[i].localpart;
  +                    /*
  +                    System.out.println("fElemMap["+i+"]="+uriIndex+","+
  +                                       localpartIndex+" ("+
  +                                       fStringPool.toString(uriIndex)+", "+
  +                                       fStringPool.toString(localpartIndex)+
                                          ')');
  +                                       */
                   }
                   System.out.println("EOCIndex="+fEOCIndex);
               }
  @@ -217,23 +339,30 @@
           for (int childIndex = 0; childIndex < childCount; childIndex++)
           {
               // Get the current element index out
  -            final int curElem = children[childIndex];
  +            final QName curElem = children[childIndex];
   
               // Look up this child in our element map
               int elemIndex = 0;
               for (; elemIndex < fElemMapSize; elemIndex++)
               {
  -                if (fElemMap[elemIndex] == curElem)
  +                if (isEqual(fElemMap[elemIndex], curElem))
                       break;
               }
   
               // If we didn't find it, then obviously not valid
               if (elemIndex == fElemMapSize) {
  -                if (DEBUG_VALIDATE_CONTENT) 
  +                if (DEBUG_VALIDATE_CONTENT) {
                       System.out.println("!!! didn't find it");
  -                return childIndex;
  +
  +                    System.out.println("curElem : " +curElem );
  +                    for (int i=0; i<fElemMapSize; i++) {
  +                        System.out.println("fElemMap["+i+"] = " +fElemMap[i] );
  +                    }
                   }
   
  +                return childIndex;
  +            }
  +
               //
               //  Look up the next state for this input symbol when in the
               //  current state.
  @@ -245,7 +374,7 @@
                   if (DEBUG_VALIDATE_CONTENT) 
                       System.out.println("!!! not a legal transition");
                   return childIndex;
  -                }
  +            }
           }
   
           //
  @@ -262,6 +391,17 @@
           return -1;
       }
   
  +    private boolean isEqual(QName name1, QName name2) {
  +        if (name1 != null && name2 != null) {
  +        
  +            return name1.localpart == name2.localpart &&
  +                name1.uri == name2.uri;
  +
  +        }
  +        return false;
  +
  +    }
  +
       /**
        * Returns information about which elements can be placed at a particular point
        * in the passed element's content model.
  @@ -290,9 +430,9 @@
        *
        * @see InsertableElementsInfo
        */
  -    public int whatCanGoHere(boolean                    fullyValid
  -                            , InsertableElementsInfo    info) throws CMException
  -    {
  +    public int whatCanGoHere(boolean fullyValid, 
  +                             InsertableElementsInfo info) throws CMException {
  +
           //
           //  First, lets make sure that the passed in current content is valid
           //  up to the insert point.
  @@ -301,13 +441,14 @@
           for (int childIndex = 0; childIndex < info.insertAt; childIndex++)
           {
               // Get the current element index out
  -            final int curElem = info.curChildren[childIndex];
  +            final QName curElem = info.curChildren[childIndex];
   
               // Look up this child in our element map
               int elemIndex = 0;
               for (; elemIndex < fElemMapSize; elemIndex++)
               {
  -                if (fElemMap[elemIndex] == curElem)
  +                if (fElemMap[elemIndex].uri == curElem.uri && 
  +                    fElemMap[elemIndex].localpart == curElem.localpart)
                       break;
               }
   
  @@ -354,7 +495,10 @@
           if ((info.possibleChildren == null)
           ||  (info.possibleChildren.length < info.resultsCount))
           {
  -            info.possibleChildren = new int[info.resultsCount];
  +            info.possibleChildren = new QName[info.resultsCount];
  +            for (int i = 0; i < info.possibleChildren.length; i++) {
  +                info.possibleChildren[i] = new QName();
  +            }
           }
   
           //
  @@ -365,7 +509,7 @@
           //
           for (int index = 0; index < fElemMapSize; index++)
           {
  -            info.possibleChildren[index] = fElemMap[index];
  +            info.possibleChildren[index].setValues(fElemMap[index]);
               info.results[index] = (fTransTable[insertState][index] != -1);
           }
   
  @@ -399,10 +543,17 @@
           return -1;
       }
   
  +    //
  +    // Private methods
  +    //
   
  -    // -----------------------------------------------------------------------
  -    //  Private methods
  -    // -----------------------------------------------------------------------
  +    /** 
  +     * Builds the internal DFA transition table from the given syntax tree.
  +     *
  +     * @param syntaxTree The syntax tree.
  +     *
  +     * @exception CMException Thrown if DFA cannot be built.
  +     */
       private void buildDFA(CMNode syntaxTree) throws CMException
       {
           //
  @@ -433,7 +584,8 @@
           //  level of recursion, which would be piggy in Java (as is everything
           //  for that matter.)
           //
  -        CMLeaf nodeEOC = new CMLeaf(XMLContentSpec.CONTENTSPECNODE_LEAF, fEOCIndex);
  +        fQName.setValues(-1, fEOCIndex, fEOCIndex);
  +        CMLeaf nodeEOC = new CMLeaf(fQName);
           fHeadNode = new CMBinOp
           (
               XMLContentSpec.CONTENTSPECNODE_SEQ
  @@ -488,24 +640,27 @@
           //  input element. So we need to a zero based range of indexes that
           //  map to element types. This element map provides that mapping.
           //
  -        fElemMap = new int[fLeafCount];
  +        fElemMap = new QName[fLeafCount];
           fElemMapSize = 0;
           for (int outIndex = 0; outIndex < fLeafCount; outIndex++)
           {
  +            fElemMap[outIndex] = new QName();
  +
               // Get the current leaf's element index
  -            final int elemIndex = fLeafList[outIndex].getElemIndex();
  +            final QName element = fLeafList[outIndex].getElement();
   
               // See if the current leaf node's element index is in the list
               int inIndex = 0;
               for (; inIndex < fElemMapSize; inIndex++)
               {
  -                if (fElemMap[inIndex] == elemIndex)
  +                if (fElemMap[inIndex].uri == element.uri &&
  +                    fElemMap[inIndex].localpart == element.localpart)
                       break;
               }
   
               // If it was not in the list, then add it, if not the EOC node
               if (inIndex == fElemMapSize)
  -                fElemMap[fElemMapSize++] = elemIndex;
  +                fElemMap[fElemMapSize++].setValues(element);
           }
   
           //
  @@ -597,7 +752,10 @@
                           //  want to add its follow list to the set of states to
                           //  transition to from the current state.
                           //
  -                        if (fLeafList[leafIndex].getElemIndex() == fElemMap[elemIndex])
  +                        final QName leaf = fLeafList[leafIndex].getElement();
  +                        final QName element = fElemMap[elemIndex];
  +                        if (leaf.uri == element.uri &&
  +                            leaf.localpart == element.localpart)
                               newSet.union(fFollowList[leafIndex]);
                       }
                   }
  @@ -694,8 +852,14 @@
           fFollowList = null;
   
       }
  -
   
  +    /**
  +     * Calculates the follow list of the current node.
  +     *
  +     * @param nodeCur The curent node.
  +     *
  +     * @exception CMException Thrown if follow list cannot be calculated.
  +     */
       private void calcFollowList(CMNode nodeCur) throws CMException
       {
           // Recurse as required
  @@ -760,7 +924,14 @@
           }
       }
   
  -
  +    /**
  +     * Dumps the tree of the current node to standard output.
  +     *
  +     * @param nodeCur The current node.
  +     * @param level   The maximum levels to output.
  +     *
  +     * @exception CMException Thrown on error.
  +     */
       private void dumpTree(CMNode nodeCur, int level) throws CMException
       {
           for (int index = 0; index < level; index++)
  @@ -807,9 +978,9 @@
                   "Leaf: (pos="
                   + ((CMLeaf)nodeCur).getPosition()
                   + "), "
  -                + fStringPool.toString(((CMLeaf)nodeCur).getElemIndex())
  +                + ((CMLeaf)nodeCur).getElement()
                   + "(elemIndex="
  -                + ((CMLeaf)nodeCur).getElemIndex()
  +                + ((CMLeaf)nodeCur).getElement()
                   + ") "
               );
   
  @@ -828,11 +999,11 @@
       }
   
   
  -    //
  -    //  -1 is used to represent bad transitions in the transition table
  -    //  entry for each state. So each entry is initialized to an all -1
  -    //  array. This method creates a new entry and initializes it.
  -    //
  +    /**
  +     * -1 is used to represent bad transitions in the transition table
  +     * entry for each state. So each entry is initialized to an all -1
  +     * array. This method creates a new entry and initializes it.
  +     */
       private int[] makeDefStateList()
       {
           int[] retArray = new int[fElemMapSize];
  @@ -840,8 +1011,8 @@
               retArray[index] = -1;
           return retArray;
       }
  -
   
  +    /** Post tree build initialization. */
       private int postTreeBuildInit(CMNode nodeCur, int curIndex) throws CMException
       {
           // Set the maximum states on this node
  @@ -864,7 +1035,8 @@
               //  Put this node in the leaf list at the current index if its
               //  a non-epsilon leaf.
               //
  -            if (((CMLeaf)nodeCur).getElemIndex() != fEpsilonIndex)
  +             final QName node = ((CMLeaf)nodeCur).getElement();
  +            if (node.localpart != fEpsilonIndex)
                   fLeafList[curIndex++] = (CMLeaf)nodeCur;
           }
            else
  @@ -874,113 +1046,5 @@
           return curIndex;
       }
   
  -
  -    // -----------------------------------------------------------------------
  -    //  Private data members
  -    //
  -    //  fDeclPool
  -    //      The element/attribute declaration pool of our parser session.
  -    //      This is set during ctor and kept around.
  -    //
  -    //  fElementIndex
  -    //      The Element Decl pool index of the element that we are the content
  -    //      model for.
  -    //
  -    //  fElemMap
  -    //  fElemMapSize
  -    //      This is the map of unique input symbol elements to indices into
  -    //      each state's per-input symbol transition table entry. This is part
  -    //      of the built DFA information that must be kept around to do the
  -    //      actual validation.
  -    //
  -    //  fEOCIndex
  -    //      The string index for the 'end of content' string that we add to
  -    //      the string pool. This is used as the special name of an element
  -    //      that represents the end of the syntax tree.
  -    //
  -    //  fEOCPos
  -    //      The NFA position of the special EOC (end of content) node. This
  -    //      is saved away since its used during the DFA build.
  -    //
  -    //  fEpsilonIndex
  -    //      The string index for the 'epsilon' string that we add to the
  -    //      string pool. This represents epsilon node transitions in the
  -    //      syntax tree.
  -    //
  -    //  fErrHandler
  -    //      The object to report errors to.
  -    //
  -    //  fFinalStateFlags
  -    //      This is an array of booleans, one per state (there are
  -    //      fTransTableSize states in the DFA) that indicates whether that
  -    //      state is a final state.
  -    //
  -    //  fFollowList
  -    //      The list of follow positions for each NFA position (i.e. for each
  -    //      non-epsilon leaf node.) This is only used during the building of
  -    //      the DFA, and is let go afterwards.
  -    //
  -    //  fHeadNode
  -    //      This is the head node of our intermediate representation. It is
  -    //      only non-null during the building of the DFA (just so that it
  -    //      does not have to be passed all around.) Once the DFA is built,
  -    //      this is no longer required so its nulled out.
  -    //
  -    //  fLeafCount
  -    //      The count of leaf nodes. This is an important number that set some
  -    //      limits on the sizes of data structures in the DFA process.
  -    //
  -    //  fLeafList
  -    //      An array of non-epsilon leaf nodes, which is used during the DFA
  -    //      build operation, then dropped.
  -    //
  -    //  fSpecNode
  -    //      The content spec node for the element that this object represents
  -    //      the content of. This info is needed a good bit so we get it once
  -    //      and keep it.
  -    //
  -    //  fStringPool
  -    //      The string pool of our parser session. This is set during ctor
  -    //      and kept around.
  -    //
  -    //  fTransTable
  -    //  fTransTableSize
  -    //      This is the transition table that is the main by product of all
  -    //      of the effort here. It is an array of arrays of ints. The first
  -    //      dimension is the number of states we end up with in the DFA. The
  -    //      second dimensions is the number of unique elements in the content
  -    //      model (fElemMapSize). Each entry in the second dimension indicates
  -    //      the new state given that input for the first dimension's start
  -    //      state.
  -    //
  -    //      The fElemMap array handles mapping from element indexes to
  -    //      positions in the second dimension of the transition table.
  -    //
  -    //      fTransTableSize is the number of valid entries in the transition
  -    //      table, and in the other related tables such as fFinalStateFlags.
  -    // -----------------------------------------------------------------------
  -    private int[]           fElemMap        = null;
  -    private int             fElemMapSize    = 0;
  -    private int             fEOCIndex       = 0;
  -    private int             fEOCPos         = 0;
  -    private int             fEpsilonIndex   = 0;
  -    private boolean[]       fFinalStateFlags = null;
  -    private CMStateSet[]    fFollowList     = null;
  -    private CMNode          fHeadNode       = null;
  -    private int             fLeafCount      = 0;
  -    private CMLeaf[]        fLeafList       = null;
  -    private StringPool      fStringPool     = null;
  -    private int[][]         fTransTable     = null;
  -    private int             fTransTableSize = 0;
  -
  -    /**
  -     * Flag that indicates that even though we have a "complicated"
  -     * content model, it is valid to have no content. In other words,
  -     * all parts of the content model are optional. For example:
  -     * <pre>
  -     *      &lt;!ELEMENT AllOptional (Optional*,NotRequired?)&gt;
  -     * </pre>
  -     */
  -    private boolean fEmptyContentIsValid = false;
   
  -}
  +} // class DFAContentModel
  
  
  
  1.2       +95 -79    xml-xerces/java/src/org/apache/xerces/validators/common/InsertableElementsInfo.java
  
  Index: InsertableElementsInfo.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/validators/common/InsertableElementsInfo.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- InsertableElementsInfo.java	2000/04/04 19:36:01	1.1
  +++ InsertableElementsInfo.java	2000/05/17 18:33:04	1.2
  @@ -57,6 +57,7 @@
   
   package org.apache.xerces.validators.common;
   
  +import org.apache.xerces.utils.QName;
   
   /**
    * ---------------------------------------------------------------------------
  @@ -71,86 +72,101 @@
    *  Since it exists purely to exchange data, it just uses simple public
    *  data members.
    * ---------------------------------------------------------------------------
  + * InsertableElementsInfo is a simple 'data packet' class that is used to
  + * get information into and out of the validator APIs that allow you to ask
  + * what kind of elements can be inserted into a particular place in an
  + * element's content model.
  + * <p>
  + * The parent element is not explicitly stored here, since it is a separate
  + * parameter to the methods that do the query.
  + * <p>
  + * Since it exists purely to exchange data, it just uses simple public
  + * data members.
    *
  - * @version
  + * @version $Id: InsertableElementsInfo.java,v 1.2 2000/05/17 18:33:04 jeffreyr Exp $
    */
   public class InsertableElementsInfo
   {
  -    // -----------------------------------------------------------------------
  -    //  Public data members
  -    //
  -    //  canHoldPCData
  -    //      One of the things that could be inserted here is a PCDATA node,
  -    //      in addition to the element type nodes reported.
  -    //
  -    //  childCount
  -    //      The count of elements in the curChildren array. The array can be
  -    //      larger than this (for reuse purposes), so this value indicates
  -    //      how many elements are valid.
  -    //
  -    //      Note that, since the curChildren array must have an empty slot at
  -    //      the insertion index, this value can never be zero.
  -    //
  -    //      Note also that this value can be changed during processing, though
  -    //      its value on return is meaningless to the caller.
  -    //
  -    //  curChildren
  -    //      The current list of children of the parent element. This may or
  -    //      may not be the *real* list of children, since the caller can lie
  -    //      but that's of no concern to the validator. These query APIs are
  -    //      intended to be for 'what if' kind of work, so any list of children
  -    //      could be passed in.
  -    //
  -    //      There must be an empy slot in the array at the requested insertion
  -    //      point. That slot does not have to have any particular value, but
  -    //      it will be used by the validator to do brute force validation in
  -    //      some cases when a 'fully valid' check is done for valid insertable
  -    //      elements.
  -    //
  -    //      Note that this array can be modified by the call, so do not expect
  -    //      its contents to remain the same as on input.
  -    //
  -    //  isValidEOC
  -    //      Indicates that one of the valid things after the insert point is
  -    //      'end of content', which means that the element being inserted
  -    //      after can legally be the last element.
  -    //
  -    //  insertAt
  -    //      The insertion point. The question is 'what can go here' and this
  -    //      indicates where 'where' is. It is an offset into curChildren.
  -    //
  -    //  possibleChildren
  -    //      This array is filled with flags that indicate what the possible
  -    //      insertable elements are (i.e. the list of unique elements that
  -    //      could possibly be inserted somewhere in this type of element.)
  -    //      Effectively this is the list of unique children in the content
  -    //      model of the parent element.
  -    //
  -    //      If this array is not big enough to hold the results, or is null,
  -    //      then it will be replaced with a new array of the correct size.
  -    //
  -    //  results
  -    //      This array must be at least as large as possibleChildren since
  -    //      a flag is set in the same indexes in this array to indicate that
  -    //      the possible child at that index in possibleChildren can be
  -    //      inserted at the requested insertion point.
  -    //
  -    //      If this array is not big enough to hold the results, or is null,
  -    //      then it will be replaced with a new array of the correct size.
  -    //
  -    //  resultsCount
  -    //      The number of elements that are valid in the possibleChildren
  -    //      and resultsCount arrays. They can be larger than that, so there
  -    //      must be a way to indicate how many elements are filled in with
  -    //      value results. If they were not at least this large on input,
  -    //      then they will be reallocated up to this size.
  -    // -----------------------------------------------------------------------
  -    public boolean      canHoldPCData;
  -    public int          childCount;
  -    public int[]        curChildren;
  -    public boolean      isValidEOC;
  -    public int          insertAt;
  -    public int[]        possibleChildren;
  -    public boolean[]    results;
  -    public int          resultsCount;
  -};
  +    /**
  +     * One of the things that could be inserted here is a PCDATA node,
  +     * in addition to the element type nodes reported.
  +     */
  +    public boolean canHoldPCData;
  +
  +    /**
  +     * The count of elements in the curChildren array. The array can be
  +     * larger than this (for reuse purposes), so this value indicates
  +     * how many elements are valid.
  +     * <p>
  +     * Note that, since the curChildren array must have an empty slot at
  +     * the insertion index, this value can never be zero.
  +     * <p>
  +     * Note also that this value can be changed during processing, though
  +     * its value on return is meaningless to the caller.
  +     */
  +    public int childCount;
  +    
  +    /**
  +     * The current list of children of the parent element. This may or
  +     * may not be the <em>real</em> list of children, since the caller can lie
  +     * but that's of no concern to the validator. These query APIs are
  +     * intended to be for 'what if' kind of work, so any list of children
  +     * could be passed in.
  +     * <p>
  +     * There must be an empy slot in the array at the requested insertion
  +     * point. That slot does not have to have any particular value, but
  +     * it will be used by the validator to do brute force validation in
  +     * some cases when a 'fully valid' check is done for valid insertable
  +     * elements.
  +     * <p>
  +     * Note that this array can be modified by the call, so do not expect
  +     * its contents to remain the same as on input.
  +     */
  +    public QName curChildren[];
  +
  +    /**
  +     * Indicates that one of the valid things after the insert point is
  +     * 'end of content', which means that the element being inserted
  +     * after can legally be the last element.
  +     */
  +    public boolean isValidEOC;
  +    
  +    /**
  +     * The insertion point. The question is 'what can go here' and this
  +     * indicates where 'where' is. It is an offset into curChildren.
  +     */
  +    public int insertAt;
  +    
  +    /**
  +     * This array is filled with flags that indicate what the possible
  +     * insertable elements are (i.e. the list of unique elements that
  +     * could possibly be inserted somewhere in this type of element.)
  +     * Effectively this is the list of unique children in the content
  +     * model of the parent element.
  +     * <p>
  +     * If this array is not big enough to hold the results, or is null,
  +     * then it will be replaced with a new array of the correct size.
  +     */
  +    public QName possibleChildren[];
  +    
  +    /**
  +     * The number of elements that are valid in the possibleChildren
  +     * and resultsCount arrays. They can be larger than that, so there
  +     * must be a way to indicate how many elements are filled in with
  +     * value results. If they were not at least this large on input,
  +     * then they will be reallocated up to this size.
  +     */
  +    public int resultsCount;
  +    
  +    /**
  +     * This array must be at least as large as possibleChildren since
  +     * a flag is set in the same indexes in this array to indicate that
  +     * the possible child at that index in possibleChildren can be
  +     * inserted at the requested insertion point.
  +     * <p>
  +     * If this array is not big enough to hold the results, or is null,
  +     * then it will be replaced with a new array of the correct size.
  +     */
  +    public boolean results[];
  +    
  +} // class InsertableElementsInfo
  
  
  
  1.3       +3 -0      xml-xerces/java/src/org/apache/xerces/validators/common/Makefile
  
  Index: Makefile
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/validators/common/Makefile,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- Makefile	2000/04/04 21:01:28	1.2
  +++ Makefile	2000/05/17 18:33:04	1.3
  @@ -10,6 +10,9 @@
   	MixedContentModel.class\
   	SimpleContentModel.class\
   	XMLContentModel.class\
  +	GrammarResolver.class \
  +	GrammarResolverImpl.class \
  +	Grammar.class \
   	XMLValidator.class
   
   
  
  
  
  1.2       +105 -50   xml-xerces/java/src/org/apache/xerces/validators/common/MixedContentModel.java
  
  Index: MixedContentModel.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/validators/common/MixedContentModel.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- MixedContentModel.java	2000/04/04 19:36:01	1.1
  +++ MixedContentModel.java	2000/05/17 18:33:04	1.2
  @@ -2,7 +2,7 @@
    * The Apache Software License, Version 1.1
    *
    *
  - * Copyright (c) 1999 The Apache Software Foundation.  All rights 
  + * Copyright (c) 1999,2000 The Apache Software Foundation.  All rights 
    * reserved.
    *
    * Redistribution and use in source and binary forms, with or without
  @@ -57,6 +57,8 @@
   
   package org.apache.xerces.validators.common;
   
  +import org.apache.xerces.utils.QName;
  +
   /**
    * MixedContentModel is a derivative of the abstract content model base
    * class that handles the special case of mixed model elements. If an element
  @@ -70,34 +72,68 @@
    * validate by just looking up each child being validated by looking it up
    * in the list.
    *
  - * @version
  + * @version $Id: MixedContentModel.java,v 1.2 2000/05/17 18:33:04 jeffreyr Exp $
    */
  -public class MixedContentModel implements XMLContentModel
  -{
  -    // -----------------------------------------------------------------------
  -    //  Constructors
  -    // -----------------------------------------------------------------------
  +public class MixedContentModel 
  +    implements XMLContentModel {
  +
  +
  +    //
  +    // Data
  +    //
  +    
  +    /** The count of possible children that we have to deal with. */
  +    private int fCount;
  +
  +    /** The list of possible children that we have to accept. */
  +    private QName fChildren[];
  +
  +    /** 
  +     * True if mixed content model is ordered. DTD mixed content models
  +     * are <em>always</em> unordered.
  +     */
  +    private boolean fOrdered;
  +
  +    //
  +    // Constructors
  +    //
   
       /**
        * Constructs a mixed content model.
        *
  -     * @param declPool The element decl pool.
  -     * @param elementIndex The element index into the pool.
  +     * @param count The child count.
  +     * @param childList The list of allowed children.
        *
        * @exception CMException Thrown if content model can't be built.
        */
  -    public MixedContentModel(int count, int[] childList) throws CMException
  -    {
  +    public MixedContentModel(int count, QName childList[]) throws CMException {
  +        this(count, childList, false);
  +    }
  +
  +    /**
  +     * Constructs a mixed content model.
  +     *
  +     * @param count The child count.
  +     * @param childList The list of allowed children.
  +     * @param ordered True if content must be ordered.
  +     *
  +     * @exception CMException Thrown if content model can't be built.
  +     */
  +    public MixedContentModel(int count, QName childList[],
  +                             boolean ordered) throws CMException {
  +
           // Make our own copy now, which is exactly the right size
           fCount = count;
  -        fChildren = new int[fCount];
  -        System.arraycopy(childList, 0, fChildren, 0, count);
  -    }
  +        fChildren = new QName[fCount];
  +        for (int i = 0; i < fCount; i++) {
  +            fChildren[i] = new QName(childList[i]);
  +        }
   
  +    } // <init>(int,QName[],boolean)
   
  -    // -----------------------------------------------------------------------
  -    //  Public, inherited methods
  -    // -----------------------------------------------------------------------
  +    //
  +    // XMLContentModel methods
  +    //
       
       /**
        * Check that the specified content is valid according to this
  @@ -122,32 +158,60 @@
        *
        * @exception Exception Thrown on error.
        */
  -    public int validateContent(int childCount, int[] children) throws Exception
  -    {
  -        for (int outIndex = 0; outIndex < childCount; outIndex++)
  -        {
  -            // Get the current child out of the source index
  -            final int curChild = children[outIndex];
  +    public int validateContent(int childCount, QName children[]) 
  +        throws Exception {
  +        
  +        // must match order
  +        if (fOrdered) {
  +            int inIndex = 0;
  +            for (int outIndex = 0; outIndex < childCount; outIndex++) {
   
  -            // If its PCDATA, then we just accept that
  -            if (curChild == -1)
  -                continue;
  +                // ignore mixed text
  +                final QName curChild = children[outIndex];
  +                if (curChild.localpart == -1) {
  +                    continue;
  +                }
  +
  +                // element must match
  +                if (fChildren[inIndex].uri != children[outIndex].uri &&
  +                    fChildren[inIndex].localpart != children[outIndex].localpart) {
  +                    return outIndex;
  +                }
  +                
  +                // advance index
  +                inIndex++;
  +            }
  +        }
   
  -            // And try to find it in our list
  -            int inIndex = 0;
  -            for (; inIndex < fCount; inIndex++)
  +        // can appear in any order
  +        else {
  +            for (int outIndex = 0; outIndex < childCount; outIndex++)
               {
  -                if (curChild == fChildren[inIndex])
  -                    break;
  +                // Get the current child out of the source index
  +                final QName curChild = children[outIndex];
  +    
  +                // If its PCDATA, then we just accept that
  +                if (curChild.localpart == -1)
  +                    continue;
  +    
  +                // And try to find it in our list
  +                int inIndex = 0;
  +                for (; inIndex < fCount; inIndex++)
  +                {
  +                    if (curChild.uri == fChildren[inIndex].uri &&
  +                        curChild.localpart == fChildren[inIndex].localpart)
  +                        break;
  +                }
  +
  +                // We did not find this one, so the validation failed
  +                if (inIndex == fCount)
  +                    return outIndex;
               }
  -
  -            // We did not find this one, so the validation failed
  -            if (inIndex == fCount)
  -                return outIndex;
           }
   
           // Everything seems to be in order, so return success
           return -1;
  +
       }
   
       /**
  @@ -218,7 +282,10 @@
           if ((info.possibleChildren == null)
           ||  (info.possibleChildren.length < info.resultsCount))
           {
  -            info.possibleChildren = new int[info.resultsCount];
  +            info.possibleChildren = new QName[info.resultsCount];
  +            for (int i = 0; i < info.possibleChildren.length; i++) {
  +                info.possibleChildren[i] = new QName();
  +            }
           }
   
           //
  @@ -242,23 +309,11 @@
           //
           for (int index = 0; index < fCount; index++)
           {
  -            info.possibleChildren[index] = fChildren[index];
  +            info.possibleChildren[index].setValues(fChildren[index]);
               info.results[index] = bStatus;
           }
   
           return -1;
       }
  -
   
  -    // -----------------------------------------------------------------------
  -    //  Private data members
  -    //
  -    //  fCount
  -    //      The count of possible children that we have to deal with.
  -    //
  -    //  fChildren
  -    //      The list of possible children that we have to accept.
  -    // -----------------------------------------------------------------------
  -    private int             fCount;
  -    private int[]           fChildren;
  -};
  +} // class MixedContentModel
  
  
  
  1.2       +74 -54    xml-xerces/java/src/org/apache/xerces/validators/common/SimpleContentModel.java
  
  Index: SimpleContentModel.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/validators/common/SimpleContentModel.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- SimpleContentModel.java	2000/04/04 19:36:01	1.1
  +++ SimpleContentModel.java	2000/05/17 18:33:05	1.2
  @@ -2,7 +2,7 @@
    * The Apache Software License, Version 1.1
    *
    *
  - * Copyright (c) 1999 The Apache Software Foundation.  All rights 
  + * Copyright (c) 1999,2000 The Apache Software Foundation.  All rights 
    * reserved.
    *
    * Redistribution and use in source and binary forms, with or without
  @@ -59,6 +59,7 @@
   
   import org.apache.xerces.framework.XMLContentSpec;
   import org.apache.xerces.utils.ImplementationMessages;
  +import org.apache.xerces.utils.QName;
   
   /**
    * SimpleContentModel is a derivative of the abstract content model base
  @@ -80,26 +81,51 @@
    * in a simple way without a DFA and without the overhead of setting up a
    * DFA for such a simple check.
    *
  - * @version
  + * @version $Id: SimpleContentModel.java,v 1.2 2000/05/17 18:33:05 jeffreyr Exp $
    */
  -public class SimpleContentModel implements XMLContentModel
  -{
  -    // -----------------------------------------------------------------------
  -    //  Constructors
  -    // -----------------------------------------------------------------------
  +public class SimpleContentModel 
  +    implements XMLContentModel {
   
  +    //
  +    // Data
  +    //
  +
  +    /**
  +     * The element decl pool indices of the first (and optional second)
  +     * child node. The operation code tells us whether the second child
  +     * is used or not.
  +     */
  +    private QName fFirstChild = new QName();
  +
  +    /**
  +     * The element decl pool indices of the first (and optional second)
  +     * child node. The operation code tells us whether the second child
  +     * is used or not.
  +     */
  +    private QName fSecondChild = new QName();
  +
       /**
  +     * The operation that this object represents. Since this class only
  +     * does simple contents, there is only ever a single operation
  +     * involved (i.e. the children of the operation are always one or
  +     * two leafs.) This is one of the XMLDTDParams.CONTENTSPECNODE_XXX values.
  +     */
  +    private int fOp;
  +
  +    //
  +    // Constructors
  +    //
  +
  +    /**
        * Constructs a simple content model.
        *
        * @param firstChildIndex The first child index
        * @parma secondChildIndex The second child index.
        * @param cmOp The content model operator.
        *
  -     * @see XMLContentSpec.Node
  +     * @see XMLContentSpec
        */
  -    public SimpleContentModel(  int     firstChildIndex
  -                                , int   secondChildIndex
  -                                , int   cmOp)
  +    public SimpleContentModel(QName firstChild, QName secondChild, int cmOp)
       {
           //
           //  Store away the children and operation. This is all we need to
  @@ -107,15 +133,20 @@
           //
           //  The operation is one of the ContentSpecNode.NODE_XXX values!
           //
  -        fFirstChild = firstChildIndex;
  -        fSecondChild = secondChildIndex;
  +        fFirstChild.setValues(firstChild);
  +        if (secondChild != null) {
  +            fSecondChild.setValues(secondChild);
  +        }
  +        else {
  +            fSecondChild.clear();
  +        }
           fOp = cmOp;
       }
   
   
  -    // -----------------------------------------------------------------------
  -    //  Public, inherited methods
  -    // -----------------------------------------------------------------------
  +    //
  +    // XMLContentModel methods
  +    //
       
       /**
        * Check that the specified content is valid according to this
  @@ -140,8 +171,9 @@
        *
        * @exception Exception Thrown on error.
        */
  -    public int validateContent(int childCount, int[] children) throws Exception
  -    {
  +    public int validateContent(int childCount, 
  +                               QName children[]) throws Exception {
  +
           //
           //  According to the type of operation, we do the correct type of
           //  content check.
  @@ -154,7 +186,7 @@
                       return 0;
   
                   // If the 0th child is not the right kind, report an error at 0
  -                if (children[0] != fFirstChild)
  +                if (children[0].uri != fFirstChild.uri && children[0].localpart != fFirstChild.localpart)
                       return 0;
   
                   // If more than one child, report an error at index 1
  @@ -167,7 +199,8 @@
                   //  If there is one child, make sure its the right type. If not,
                   //  then its an error at index 0.
                   //
  -                if ((childCount == 1) && (children[0] != fFirstChild))
  +                if (childCount == 1 && 
  +                    (children[0].uri != fFirstChild.uri && children[0].localpart != fFirstChild.localpart))
                       return 0;
   
                   //
  @@ -189,7 +222,7 @@
                   {
                       for (int index = 0; index < childCount; index++)
                       {
  -                        if (children[index] != fFirstChild)
  +                        if (children[index].uri != fFirstChild.uri && children[index].localpart != fFirstChild.localpart)
                               return index;
                       }
                   }
  @@ -210,7 +243,7 @@
                   //
                   for (int index = 0; index < childCount; index++)
                   {
  -                    if (children[index] != fFirstChild)
  +                    if (children[index].uri != fFirstChild.uri && children[index].localpart != fFirstChild.localpart)
                           return index;
                   }
                   break;
  @@ -224,7 +257,8 @@
                       return 0;
   
                   // If the zeroth element isn't one of our choices, error at 0
  -                if ((children[0] != fFirstChild) && (children[0] != fSecondChild))
  +                if ((children[0].uri != fFirstChild.uri && children[0].localpart != fFirstChild.localpart) &&
  +                    (children[0].uri != fSecondChild.uri && children[0].localpart != fSecondChild.localpart))
                       return 0;
   
                   // If there is more than one element, then an error at 1
  @@ -238,10 +272,10 @@
                   //  we stored, in the stored order.
                   //
                   if (childCount == 2) {
  -                    if (children[0] != fFirstChild)
  +                    if (children[0].uri != fFirstChild.uri && children[0].localpart != fFirstChild.localpart)
                           return 0;
   
  -                    if (children[1] != fSecondChild)
  +                    if (children[1].uri != fSecondChild.uri && children[1].localpart != fSecondChild.localpart)
                           return 1;
                   }
                   else {
  @@ -290,16 +324,17 @@
        *
        * @see InsertableElementsInfo
        */
  -    public int whatCanGoHere(boolean                    fullyValid
  -                            , InsertableElementsInfo    info) throws Exception
  -    {
  +    public int whatCanGoHere(boolean fullyValid, InsertableElementsInfo info) 
  +        throws Exception {
  +
           //
           //  For this one, having the empty slot at the insertion point is 
           //  a problem. So lets compress the array down. We know that it has
           //  to have at least the empty slot at the insertion point.
           //
  -        for (int index = info.insertAt; index < info.childCount; index++)
  -            info.curChildren[index] = info.curChildren[index+1];
  +        for (int index = info.insertAt; index < info.childCount; index++) {
  +            info.curChildren[index].setValues(info.curChildren[index+1]);
  +        }
           info.childCount--;
           
           //
  @@ -341,18 +376,21 @@
           if ((info.possibleChildren == null)
           ||  (info.possibleChildren.length < info.resultsCount))
           {
  -            info.possibleChildren = new int[info.resultsCount];
  +            info.possibleChildren = new QName[info.resultsCount];
  +            for (int i = 0; i < info.possibleChildren.length; i++) {
  +                info.possibleChildren[i] = new QName();
  +            }
           }
   
           //
           //  Fill in the possible children array, and set all of the associated
           //  results entries to defaults of false.
           //
  -        info.possibleChildren[0] = fFirstChild;
  +        info.possibleChildren[0].setValues(fFirstChild);
           info.results[0] = false;
           if (info.resultsCount == 2)
           {
  -            info.possibleChildren[1] = fSecondChild;
  +            info.possibleChildren[1].setValues(fSecondChild);
               info.results[1] = false;
           }
   
  @@ -464,7 +502,8 @@
                       if (fullyValid)
                       {
                           if (info.childCount == 1)
  -                            info.results[0] = info.curChildren[0] == fSecondChild;
  +                            info.results[0] = info.curChildren[0].uri == fSecondChild.uri &&
  +                                              info.curChildren[0].localpart == fSecondChild.localpart;
                       }
                        else
                       {
  @@ -491,23 +530,4 @@
           return -1;
       }
   
  -
  -    // -----------------------------------------------------------------------
  -    //  Private data members
  -    //
  -    //  fFirstChild
  -    //  fSecondChild
  -    //      The element decl pool indices of the first (and optional second)
  -    //      child node. The operation code tells us whether the second child
  -    //      is used or not.
  -    //
  -    //  fOp
  -    //      The operation that this object represents. Since this class only
  -    //      does simple contents, there is only ever a single operation
  -    //      involved (i.e. the children of the operation are always one or
  -    //      two leafs.) This is one of the XMLDTDParams.CONTENTSPECNODE_XXX values.
  -    // -----------------------------------------------------------------------
  -    int     fFirstChild;
  -    int     fSecondChild;
  -    int     fOp;
  -};
  +} // class SimpleContentModel
  
  
  
  1.2       +12 -15    xml-xerces/java/src/org/apache/xerces/validators/common/XMLContentModel.java
  
  Index: XMLContentModel.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/validators/common/XMLContentModel.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- XMLContentModel.java	2000/04/04 19:36:01	1.1
  +++ XMLContentModel.java	2000/05/17 18:33:05	1.2
  @@ -2,7 +2,7 @@
    * The Apache Software License, Version 1.1
    *
    *
  - * Copyright (c) 1999 The Apache Software Foundation.  All rights 
  + * Copyright (c) 1999,2000 The Apache Software Foundation.  All rights 
    * reserved.
    *
    * Redistribution and use in source and binary forms, with or without
  @@ -57,17 +57,19 @@
   
   package org.apache.xerces.validators.common;
   
  +import org.apache.xerces.utils.QName;
  +
   /**
    * ContentModel is an interface that can be used by your own custom validators
    * to plug in various types of content models. It is used internally as well
    * for the same purposes.
  - *
  + * <p>
    * Since there are a number of optimizations that can be used for simple or
    * special content models, this class provides the interface via which all of
    * the various content model types are managed. So the validation handler
    * class has a list of things derived from this class. It finds the one for
    * the desired element, then asks it to validate the element contents.
  - *
  + * <p>
    * The validation interface from the scanner to the validation handle provides
    * a child count and an array of element name indices into the string pool.
    * So it is assumed that those same parameters will be passed to the content
  @@ -75,7 +77,7 @@
    * this standard view of the elements to be validated.
    *
    * @author  Dean Roddey
  - * @version
  + * @version $Id: XMLContentModel.java,v 1.2 2000/05/17 18:33:05 jeffreyr Exp $
    */
   public interface XMLContentModel {
   
  @@ -102,11 +104,8 @@
        *
        * @exception Exception Thrown on error.
        */
  -    public int validateContent
  -    (
  -        int         childCount
  -        , int[]     children
  -    )   throws Exception;
  +    public int validateContent(int childCount, 
  +                               QName children[]) throws Exception;
   
       /**
        * Returns information about which elements can be placed at a particular point
  @@ -136,9 +135,7 @@
        *
        * @see InsertableElementsInfo
        */
  -    public int whatCanGoHere
  -    (
  -        boolean                     fullyValid
  -        , InsertableElementsInfo    info
  -    )   throws Exception;
  -}
  +    public int whatCanGoHere(boolean fullyValid, 
  +                             InsertableElementsInfo info) throws Exception;
  +
  +} // interface XMLContentModel
  
  
  
  1.5       +4019 -2720xml-xerces/java/src/org/apache/xerces/validators/common/XMLValidator.java
  
  Index: XMLValidator.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/validators/common/XMLValidator.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- XMLValidator.java	2000/04/12 16:56:52	1.4
  +++ XMLValidator.java	2000/05/17 18:33:06	1.5
  @@ -2,7 +2,7 @@
    * The Apache Software License, Version 1.1
    *
    *
  - * Copyright (c) 1999 The Apache Software Foundation.  All rights 
  + * Copyright (c) 1999,2000 The Apache Software Foundation.  All rights 
    * reserved.
    *
    * Redistribution and use in source and binary forms, with or without
  @@ -65,83 +65,235 @@
   import org.apache.xerces.readers.DefaultEntityHandler;
   import org.apache.xerces.readers.XMLEntityHandler;
   import org.apache.xerces.utils.ChunkyCharArray;
  +import org.apache.xerces.utils.Hash2intTable;
   import org.apache.xerces.utils.NamespacesScope;
  +import org.apache.xerces.utils.QName;
   import org.apache.xerces.utils.StringPool;
   import org.apache.xerces.utils.XMLCharacterProperties;
   import org.apache.xerces.utils.XMLMessages;
   import org.apache.xerces.utils.ImplementationMessages;
   
  +import org.apache.xerces.parsers.DOMParser;
  +
   import org.w3c.dom.Document;
  +import org.w3c.dom.Element;
   
   import org.xml.sax.InputSource;
   import org.xml.sax.EntityResolver;
   import org.xml.sax.Locator;
   import org.xml.sax.helpers.LocatorImpl;
  +import org.xml.sax.SAXException;
  +import org.xml.sax.SAXParseException;
  +
  +import java.io.IOException;
   
   import java.util.Enumeration;
   import java.util.Hashtable;
   import java.util.StringTokenizer;
  +import java.util.Vector;
   
  -import org.apache.xerces.validators.dtd.DTDImporter;
  -import org.apache.xerces.validators.schema.SchemaImporter;
  +import org.apache.xerces.validators.dtd.DTDGrammar;
  +
  +import org.apache.xerces.validators.schema.SchemaGrammar;
   import org.apache.xerces.validators.schema.SchemaMessageProvider;
  -import org.apache.xerces.validators.schema.DatatypeContentModel;
  +import org.apache.xerces.validators.schema.SchemaSymbols;
  +import org.apache.xerces.validators.schema.TraverseSchema;
  +
  +import org.apache.xerces.validators.datatype.DatatypeValidator;
   import org.apache.xerces.validators.datatype.InvalidDatatypeValueException;
   
  +/**
  + * This class is the super all-in-one validator used by the parser.
  + *
  + * @version $Id: XMLValidator.java,v 1.5 2000/05/17 18:33:06 jeffreyr Exp $
  + */
   public final class XMLValidator
       implements DefaultEntityHandler.EventHandler,
                  XMLEntityHandler.CharDataHandler,
                  XMLDocumentScanner.EventHandler,
  -               NamespacesScope.NamespacesHandler
  -{
  -	// **** DEBUG ****
  -	static XMLValidator schemaValidator = null;
  -    static boolean DEBUG = false;
  -	// **** DEBUG ****
  +               NamespacesScope.NamespacesHandler {
   
  -
       //
  -    // Debugging options
  +    // Constants
       //
  +
  +    // debugging
  +
       private static final boolean PRINT_EXCEPTION_STACK_TRACE = false;
       private static final boolean DEBUG_PRINT_ATTRIBUTES = false;
       private static final boolean DEBUG_PRINT_CONTENT = false;
  +    private static final boolean DEBUG_SCHEMA_VALIDATION = false;
  +
  +    // Chunk size constants
  +
  +    private static final int CHUNK_SHIFT = 8;           // 2^8 = 256
  +    private static final int CHUNK_SIZE = (1 << CHUNK_SHIFT);
  +    private static final int CHUNK_MASK = CHUNK_SIZE - 1;
  +    private static final int INITIAL_CHUNK_COUNT = (1 << (10 - CHUNK_SHIFT));   // 2^10 = 1k
  +
       //
  -    // Package access for use by AttributeValidator classes.
  +    // Data
       //
  +
  +    // REVISIT: The data should be regrouped and re-organized so that
  +    //          it's easier to find a meaningful field.
  +
  +    // debugging
  +
  +        private static XMLValidator schemaValidator = null;
  +
  +    private static boolean DEBUG = false;
  +
  +    // all the following were moved into Grammar class
  +    // Element list
  +    
  +    //private int fElementCount = 0;
  +
  +    /*
  +    // REVISIT: Validation. Convert elementType to <uri,localpart> tuple!
  +    private int[][] fElementType = new int[INITIAL_CHUNK_COUNT][];
  +    // REVISIT: For now, Qname seems to be a overkill 
  +    private QName[][] fElementQName = new QName[INITIAL_CHUNK_COUNT][];
  +    private int[][] fScope = new int[INITIAL_CHUNK_COUNT][];
  +
  +    private byte[][] fElementDeclIsExternal = new byte[INITIAL_CHUNK_COUNT][];
  +    private int[][] fContentSpecType = new int[INITIAL_CHUNK_COUNT][];
  +    private int[][] fContentSpec = new int[INITIAL_CHUNK_COUNT][];
  +    private XMLContentModel[][] fContentModel = new XMLContentModel[INITIAL_CHUNK_COUNT][];
  +    private int[][] fAttlistHead = new int[INITIAL_CHUNK_COUNT][];
  +    private int[][] fAttlistTail = new int[INITIAL_CHUNK_COUNT][];
  +    */
  +    // ContentSpecNode list
  +
  +    //private int fNodeCount = 0;
  +    //private byte[][] fNodeType = new byte[INITIAL_CHUNK_COUNT][];
  +    //private int[][] fNodeValue = new int[INITIAL_CHUNK_COUNT][];
  +
  +    // AttDef list
  +
  +   // private int fAttDefCount = 0;
  +    /*
  +    // REVISIT: Validation. I don't think we need to store the prefix.
  +    //          The namespace URI is important.
  +    private int[][] fAttPrefix = new int[INITIAL_CHUNK_COUNT][];
  +    private int[][] fAttName = new int[INITIAL_CHUNK_COUNT][];
  +    private int[][] fAttType = new int[INITIAL_CHUNK_COUNT][];
  +    private AttributeValidator[][] fAttValidator = new AttributeValidator[INITIAL_CHUNK_COUNT][];
  +    private int[][] fEnumeration = new int[INITIAL_CHUNK_COUNT][];
  +    private int[][] fAttDefaultType = new int[INITIAL_CHUNK_COUNT][];
  +    private int[][] fAttValue = new int[INITIAL_CHUNK_COUNT][];
  +    private byte[][] fAttDefIsExternal = new byte[INITIAL_CHUNK_COUNT][];
  +    private int[][] fNextAttDef = new int[INITIAL_CHUNK_COUNT][];
  +    
  +    */
  +
  +    // other
  +
  +    private Hashtable fIdDefs = null;
  +    private Hashtable fIdRefs = null;
  +    private Object fNullValue = null;
  +
  +    // attribute validators
  +
  +    // REVISIT: Validation. A validator per element declaration and
  +    //          attribute declaration is required to accomodate
  +    //          Schema facets on simple types.
  +    private AttributeValidator fAttValidatorCDATA = null;
  +    private AttributeValidator fAttValidatorID = new AttValidatorID();
  +    private AttributeValidator fAttValidatorIDREF = new AttValidatorIDREF();
  +    private AttributeValidator fAttValidatorIDREFS = new AttValidatorIDREFS();
  +    private AttributeValidator fAttValidatorENTITY = new AttValidatorENTITY();
  +    private AttributeValidator fAttValidatorENTITIES = new AttValidatorENTITIES();
  +    private AttributeValidator fAttValidatorNMTOKEN = new AttValidatorNMTOKEN();
  +    private AttributeValidator fAttValidatorNMTOKENS = new AttValidatorNMTOKENS();
  +    private AttributeValidator fAttValidatorNOTATION = new AttValidatorNOTATION();
  +    private AttributeValidator fAttValidatorENUMERATION = new AttValidatorENUMERATION();
  +    private AttributeValidator fAttValidatorDATATYPE = null;
  +
  +    // Package access for use by AttributeValidator classes.
  +    
       StringPool fStringPool = null;
       boolean fValidating = false;
       boolean fInElementContent = false;
       int fStandaloneReader = -1;
  -    //
  -    //
  -    //
  -    private XMLErrorReporter fErrorReporter = null;
  -    private DefaultEntityHandler fEntityHandler = null;
  +
  +
  +    // settings
  +
       private boolean fValidationEnabled = false;
       private boolean fDynamicValidation = false;
       private boolean fValidationEnabledByDynamic = false;
       private boolean fDynamicDisabledByValidation = false;
       private boolean fWarningOnDuplicateAttDef = false;
       private boolean fWarningOnUndeclaredElements = false;
  +
  +    // declarations
  +
  +    // private ContentSpecImpl fContentSpecImpl = null;
  +    private int fDeclaration[];
  +    private XMLErrorReporter fErrorReporter = null;
  +    private DefaultEntityHandler fEntityHandler = null;
  +    private QName fCurrentElement = new QName();
  +
  +    //REVISIT: validation
  +    private int[] fScopeStack = new int[8];
  +    private int[] fGrammarNameSpaceIndexStack = new int[8];
  +
       private int[] fElementTypeStack = new int[8];
       private int[] fElementEntityStack = new int[8];
       private int[] fElementIndexStack = new int[8];
       private int[] fContentSpecTypeStack = new int[8];
       private int[] fElementChildCount = new int[8];
  -    private int[][] fElementChildren = new int[8][];
  +    private QName[][] fElementChildren = new QName[8][];
       private int fElementDepth = -1;
       private boolean fNamespacesEnabled = false;
       private NamespacesScope fNamespacesScope = null;
       private int fNamespacesPrefix = -1;
  -    private int fRootElementType = -1;
  +    private QName fRootElement = new QName();
       private int fAttrListHandle = -1;
  -    private int fElementDeclCount = 0;
  -    private int fCurrentElementType = -1;
  +    //private int fElementDeclCount = 0;
       private int fCurrentElementEntity = -1;
       private int fCurrentElementIndex = -1;
       private int fCurrentContentSpecType = -1;
       private boolean fSeenDoctypeDecl = false;
  +
  +    private final int TOP_LEVEL_SCOPE = -1;
  +    private int fCurrentScope = TOP_LEVEL_SCOPE;
  +    private int fCurrentSchemaURI = -1;
  +    private int fEmptyURI = - 1; 
  +    private int fXsiPrefix = - 1;
  +    private int fXsiURI = -2; 
  +
  +    private Grammar fGrammar = null;
  +    private int fGrammarNameSpaceIndex = -1;
  +    private GrammarResolver fGrammarResolver = null;
  +
  +    // state and stuff
  +
  +    private boolean fScanningDTD = false;
  +    private XMLDocumentScanner fDocumentScanner = null;
  +    private boolean fCalledStartDocument = false;
  +    private XMLDocumentHandler fDocumentHandler = null;
  +    private XMLDocumentHandler.DTDHandler fDTDHandler = null;
  +    private boolean fSeenRootElement = false;
  +    private XMLAttrList fAttrList = null;
  +    private int fXMLLang = -1;
  +    private LocatorImpl fAttrNameLocator = null;
  +    private boolean fCheckedForSchema = false;
  +    private boolean fDeclsAreExternal = false;
  +    private StringPool.CharArrayRange fCurrentElementCharArrayRange = null;
  +    private char[] fCharRefData = null;
  +    private boolean fSendCharDataAsCharArray = false;
  +    private boolean fBufferDatatype = false;
  +    private StringBuffer fDatatypeBuffer = new StringBuffer();
  +
  +    private QName fTempQName = new QName();
  +    private XMLAttributeDecl fTempAttDecl = new XMLAttributeDecl();
  +    private XMLElementDecl fTempElementDecl = new XMLElementDecl();
  +    //REVISIT: ericye, use this temp QName whenever we can!!
  +
  +    // symbols
  +
       private int fEMPTYSymbol = -1;
       private int fANYSymbol = -1;
       private int fMIXEDSymbol = -1;
  @@ -160,117 +312,105 @@
       private int fFIXEDSymbol = -1;
       private int fDATATYPESymbol = -1;
       private int fEpsilonIndex = -1;
  -    private boolean fScanningDTD = false;
  -    private DTDImporter fDTDImporter = null;
  -    private SchemaImporter fSchemaImporter = null;
  -    private XMLDocumentScanner fDocumentScanner = null;
  -    private boolean fCalledStartDocument = false;
  -    private XMLDocumentHandler fDocumentHandler = null;
  -    private XMLDocumentHandler.DTDHandler fDTDHandler = null;
  -    private boolean fSeenRootElement = false;
  -    private XMLAttrList fAttrList = null;
  -    private int fXMLLang = -1;
  -    private LocatorImpl fAttrNameLocator = null;
  -    private boolean fCheckedForSchema = false;
  -    private Document fSchemaDocument = null;
  -    private boolean fDeclsAreExternal = false;
  -    private StringPool.CharArrayRange fCurrentElementCharArrayRange = null;
  -    private char[] fCharRefData = null;
  -    private boolean fSendCharDataAsCharArray = false;
  -    private boolean fBufferDatatype = false;
  -    private StringBuffer fDatatypeBuffer = new StringBuffer();
  -    //
  +
  +    /* these below should also be in the Grammar class.
  +    // building content models
  +
  +    private int fLeafCount = 0;
  +    private int fCount = 0;
  +    private int[] fContentList = new int[64];
  +    */
  +
       //
  +    // Constructors
       //
  +
  +    /** Constructs an XML validator. */
       public XMLValidator(StringPool stringPool,
                           XMLErrorReporter errorReporter,
                           DefaultEntityHandler entityHandler,
  -                        XMLDocumentScanner documentScanner)
  -    {
  +                        XMLDocumentScanner documentScanner) {
  +
  +        //REVISIT fGrammarResolver needed to be initialiezed somehow. 
  +        //        since SchemaGrammarResolver is the only implementation, for now ,we use this.
  +        //fGrammarResolver = SchemaGrammarResolver.instanceGrammarResolver();
  +
  +        // keep references
           fStringPool = stringPool;
           fErrorReporter = errorReporter;
           fEntityHandler = entityHandler;
           fDocumentScanner = documentScanner;
  +
  +        fEmptyURI = fStringPool.addSymbol("");
  +        fXsiURI = fStringPool.addSymbol(SchemaSymbols.URI_XSI);
  +        // initialize
           fAttrList = new XMLAttrList(fStringPool);
           entityHandler.setEventHandler(this);
           entityHandler.setCharDataHandler(this);
           fDocumentScanner.setEventHandler(this);
           init();
  -
  -		// **** DEBUG ****
  -		if ( schemaValidator == null ) {
  -			// only set for the first one!!
  -			schemaValidator = this;
  -		}
  -		// **** DEBUG ****
   
  -    }
  -
  -
  -	//****DEBUG****
  -	private String nameOf (int stringPoolIndex) 
  -	{
  -		return fStringPool.toString(stringPoolIndex);
  -	}
  +        if (DEBUG) {
  +            // REVISIT: Synchronization.
  +            if (schemaValidator == null) {
  +                // only set for the first one!!
  +                schemaValidator = this;
  +            }
  +        }
   
  -	private String param (String name, int stringPoolIndex) 
  -	{
  -		return name + "=\"" + fStringPool.toString(stringPoolIndex) + "\" ";
  -	}
  +    } // <init>(StringPool,XMLErrorReporter,DefaultEntityHandler,XMLDocumentScanner)
   
  +    public void setGrammarResolver(GrammarResolver grammarResolver){
  +        fGrammarResolver = grammarResolver;
  +    }
   
  -	private void print(String message)
  -	{
  -		if ( this == schemaValidator ) {
  -			System.err.println(message);
  -		}
  -	}
  +    //
  +    // Public methods
  +    //
   
  -	//****DEBUG****
  -	
  +    // initialization
   
  -    /**
  -     * Set char data processing preference and handlers.
  -     */
  +    /** Set char data processing preference and handlers. */
       public void initHandlers(boolean sendCharDataAsCharArray,
                                XMLDocumentHandler docHandler,
  -                             XMLDocumentHandler.DTDHandler dtdHandler)
  -    {
  -		//****DEBUG****
  -		if (DEBUG) print("(GEN) XMLValidator.initHandlers\n");
  -		//****DEBUG****
  +                             XMLDocumentHandler.DTDHandler dtdHandler) {
  +
  +                //****DEBUG****
  +                if (DEBUG) print("(GEN) XMLValidator.initHandlers\n");
  +                //****DEBUG****
   
           fSendCharDataAsCharArray = sendCharDataAsCharArray;
           fEntityHandler.setSendCharDataAsCharArray(fSendCharDataAsCharArray);
           fDocumentHandler = docHandler;
           fDTDHandler = dtdHandler;
  -    }
  -    //
  -    //
  -    //
  -    public Document getSchemaDocument() {
  -        return fSchemaDocument;
  -    }
  -    //
  -    //
  -    //
  +
  +    } // initHandlers(boolean,XMLDocumentHandler,XMLDocumentHandler.DTDHandler)
  +
  +    /** Reset or copy. */
       public void resetOrCopy(StringPool stringPool) throws Exception {
           fAttrList = new XMLAttrList(stringPool);
           resetCommon(stringPool);
       }
  +
  +    /** Reset. */
       public void reset(StringPool stringPool) throws Exception {
           fAttrList.reset(stringPool);
           resetCommon(stringPool);
       }
  -    //
  -    // Turning on validation/dynamic turns on validation if it is off, and this
  -    // is remembered.  Turning off validation DISABLES validation/dynamic if it
  -    // is on.  Turning off validation/dynamic DOES NOT turn off validation if it
  -    // was explicitly turned on, only if it was turned on BECAUSE OF the call to
  -    // turn validation/dynamic on.  Turning on validation will REENABLE and turn
  -    // validation/dynamic back on if it was disabled by a call that turned off
  -    // validation while validation/dynamic was enabled.
  -    //
  +
  +    
  +    // settings
  +
  +    /**
  +     * Turning on validation/dynamic turns on validation if it is off, and 
  +     * this is remembered.  Turning off validation DISABLES validation/dynamic
  +     * if it is on.  Turning off validation/dynamic DOES NOT turn off
  +     * validation if it was explicitly turned on, only if it was turned on
  +     * BECAUSE OF the call to turn validation/dynamic on.  Turning on
  +     * validation will REENABLE and turn validation/dynamic back on if it
  +     * was disabled by a call that turned off validation while 
  +     * validation/dynamic was enabled.
  +     */
       public void setValidationEnabled(boolean flag) throws Exception {
           fValidationEnabled = flag;
           fValidationEnabledByDynamic = false;
  @@ -285,9 +425,13 @@
           }
           fValidating = fValidationEnabled;
       }
  +
  +    /** Returns true if validation is enabled. */
       public boolean getValidationEnabled() {
           return fValidationEnabled;
       }
  +
  +    /** Sets whether validation is dynamic. */
       public void setDynamicValidationEnabled(boolean flag) throws Exception {
           fDynamicValidation = flag;
           fDynamicDisabledByValidation = false;
  @@ -302,103 +446,139 @@
           }
           fValidating = fValidationEnabled;
       }
  +
  +    /** Returns true if validation is dynamic. */
       public boolean getDynamicValidationEnabled() {
           return fDynamicValidation;
       }
  +
  +    /** Sets whether namespaces are enabled. */
       public void setNamespacesEnabled(boolean flag) {
           fNamespacesEnabled = flag;
       }
  +
  +    /** Returns true if namespaces are enabled. */
       public boolean getNamespacesEnabled() {
           return fNamespacesEnabled;
       }
  +
  +    /** Sets whether duplicate attribute definitions signal a warning. */
       public void setWarningOnDuplicateAttDef(boolean flag) {
           fWarningOnDuplicateAttDef = flag;
       }
  +
  +    /** Returns true if duplicate attribute definitions signal a warning. */
       public boolean getWarningOnDuplicateAttDef() {
           return fWarningOnDuplicateAttDef;
       }
  +
  +    /** Sets whether undeclared elements signal a warning. */
       public void setWarningOnUndeclaredElements(boolean flag) {
           fWarningOnUndeclaredElements = flag;
       }
  +
  +    /** Returns true if undeclared elements signal a warning. */
       public boolean getWarningOnUndeclaredElements() {
           return fWarningOnUndeclaredElements;
       }
   
  -    //
  -    // DefaultEntityHandler.EventHandler interface
       //
  -    //    public void startEntityReference(int entityName, int entityType, int entityContext) throws Exception;
  -    //    public void endEntityReference(int entityName, int entityType, int entityContext) throws Exception;
  -    //    public void sendEndOfInputNotifications(int entityName, boolean moreToFollow) throws Exception;
  -    //    public void sendReaderChangeNotifications(XMLEntityHandler.EntityReader reader, int readerId) throws Exception;
  -    //    public boolean externalEntityStandaloneCheck();
  -    //    public boolean getValidating();
  +    // DefaultEntityHandler.EventHandler methods
       //
  +
  +    /** Start entity reference. */
       public void startEntityReference(int entityName, int entityType, int entityContext) throws Exception {
           fDocumentHandler.startEntityReference(entityName, entityType, entityContext);
       }
  +
  +    /** End entity reference. */
       public void endEntityReference(int entityName, int entityType, int entityContext) throws Exception {
           fDocumentHandler.endEntityReference(entityName, entityType, entityContext);
       }
  +
  +    /** Send end of input notification. */
       public void sendEndOfInputNotifications(int entityName, boolean moreToFollow) throws Exception {
           fDocumentScanner.endOfInput(entityName, moreToFollow);
  +        /***
           if (fScanningDTD) {
               fDTDImporter.sendEndOfInputNotifications(entityName, moreToFollow);
           }
  +        /***/
       }
  +
  +    /** Send reader change notifications. */
       public void sendReaderChangeNotifications(XMLEntityHandler.EntityReader reader, int readerId) throws Exception {
           fDocumentScanner.readerChange(reader, readerId);
  +        /***
           if (fScanningDTD) {
               fDTDImporter.sendReaderChangeNotifications(reader, readerId);
           }
  +        /***/
       }
  +
  +    /** External entity standalone check. */
       public boolean externalEntityStandaloneCheck() {
           return (fStandaloneReader != -1 && fValidating);
       }
  +
  +    /** Return true if validating. */
       public boolean getValidating() {
           return fValidating;
       }
   
       //
  -    // XMLEntityHandler.CharDataHandler interface
  +    // XMLEntityHandler.CharDataHandler methods
       //
  -    //    public void processCharacters(char[] chars, int offset, int length) throws Exception;
  -    //    public void processCharacters(int stringHandle) throws Exception;
  -    //    public void processWhitespace(char[] chars, int offset, int length) throws Exception;
  -    //    public void processWhitespace(int stringHandle) throws Exception;
  -    //
  +
  +    /** Process characters. */
       public void processCharacters(char[] chars, int offset, int length) throws Exception {
           if (fValidating) {
  -            if (fInElementContent || fCurrentContentSpecType == fEMPTYSymbol)
  +            if (fInElementContent || fCurrentContentSpecType == fEMPTYSymbol) {
                   charDataInContent();
  -            if (fBufferDatatype)
  +            }
  +            if (fBufferDatatype) {
                   fDatatypeBuffer.append(chars, offset, length);
  +            }
           }
           fDocumentHandler.characters(chars, offset, length);
       }
  +
  +    /** Process characters. */
       public void processCharacters(int data) throws Exception {
           if (fValidating) {
  -            if (fInElementContent || fCurrentContentSpecType == fEMPTYSymbol)
  +            if (fInElementContent || fCurrentContentSpecType == fEMPTYSymbol) {
                   charDataInContent();
  -            if (fBufferDatatype)
  +            }
  +            if (fBufferDatatype) {
                   fDatatypeBuffer.append(fStringPool.toString(data));
  +            }
           }
           fDocumentHandler.characters(data);
       }
  -    public void processWhitespace(char[] chars, int offset, int length) throws Exception {
  +
  +    /** Process whitespace. */
  +    public void processWhitespace(char[] chars, int offset, int length) 
  +        throws Exception {
  +
           if (fInElementContent) {
               if (fStandaloneReader != -1 && fValidating && getElementDeclIsExternal(fCurrentElementIndex)) {
                   reportRecoverableXMLError(XMLMessages.MSG_WHITE_SPACE_IN_ELEMENT_CONTENT_WHEN_STANDALONE,
                                             XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION);
               }
               fDocumentHandler.ignorableWhitespace(chars, offset, length);
  -        } else {
  -            if (fCurrentContentSpecType == fEMPTYSymbol)
  +        } 
  +        else {
  +            if (fCurrentContentSpecType == fEMPTYSymbol) {
                   charDataInContent();
  +            }
               fDocumentHandler.characters(chars, offset, length);
           }
  -    }
  +
  +    } // processWhitespace(char[],int,int)
  +
  +    /** Process whitespace. */
       public void processWhitespace(int data) throws Exception {
  +
           if (fInElementContent) {
               if (fStandaloneReader != -1 && fValidating && getElementDeclIsExternal(fCurrentElementIndex)) {
                   reportRecoverableXMLError(XMLMessages.MSG_WHITE_SPACE_IN_ELEMENT_CONTENT_WHEN_STANDALONE,
  @@ -406,272 +586,341 @@
               }
               fDocumentHandler.ignorableWhitespace(data);
           } else {
  -            if (fCurrentContentSpecType == fEMPTYSymbol)
  +            if (fCurrentContentSpecType == fEMPTYSymbol) {
                   charDataInContent();
  +            }
               fDocumentHandler.characters(data);
           }
  -    }
   
  -    //
  -    // XMLDocumentScanner.EventHandler interface
  +    } // processWhitespace(int)
  +
       //
  -    //    public int scanElementType(XMLEntityHandler.EntityReader entityReader, char fastchar) throws Exception;
  -    //    public boolean scanExpectedElementType(XMLEntityHandler.EntityReader entityReader, char fastchar) throws Exception;
  -    //    public int scanAttributeName(XMLEntityHandler.EntityReader entityReader, int elementType) throws Exception;
  -    //    public void callStartDocument() throws Exception;
  -    //    public void callEndDocument() throws Exception;
  -    //    public void callXMLDecl(int version, int encoding, int standalone) throws Exception;
  -    //    public void callTextDecl(int version, int encoding) throws Exception;
  -    //    public void callStartElement(int elementType) throws Exception;
  -    //    public void callEndElement(int readerId) throws Exception;
  -    //    public boolean validVersionNum(String version) throws Exception;
  -    //    public boolean validEncName(String encoding) throws Exception;
  -    //    public void callStartCDATA() throws Exception;
  -    //    public void callEndCDATA() throws Exception;
  -    //    public void callCharacters(int ch) throws Exception;
  -    //    public void callProcessingInstruction(int piTarget, int piData) throws Exception;
  -    //    public void callComment(int data) throws Exception;
  -    //    public void scanDoctypeDecl(boolean standalone) throws Exception;
  -    //    public int scanAttValue(int elementType, int attrName) throws Exception;
  +    // XMLDocumentScanner.EventHandler methods
       //
  -
  -
  -	//
  -	// scanElementName
  -	//
   
  -    public int scanElementType(XMLEntityHandler.EntityReader entityReader, char fastchar) throws Exception {
  +    /** Scans element type. */
  +    public void scanElementType(XMLEntityHandler.EntityReader entityReader, 
  +                                char fastchar, QName element) throws Exception {
   
  -		int elementType;
  -
           if (!fNamespacesEnabled) {
  -            elementType = entityReader.scanName(fastchar);
  -        } else {
  -
  -			elementType = entityReader.scanQName(fastchar);
  -			if (entityReader.lookingAtChar(':', false)) {
  -				fErrorReporter.reportError(fErrorReporter.getLocator(),
  -										   XMLMessages.XML_DOMAIN,
  -										   XMLMessages.MSG_TWO_COLONS_IN_QNAME,
  -										   XMLMessages.P5_INVALID_CHARACTER,
  -										   null,
  -										   XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
  -				entityReader.skipPastNmtoken(' ');
  -			}
  -
  -		}
  +            element.clear();
  +            element.localpart = entityReader.scanName(fastchar);
  +            element.rawname = element.localpart;
  +        } 
  +        else {
  +            entityReader.scanQName(fastchar, element);
  +                        if (entityReader.lookingAtChar(':', false)) {
  +                                fErrorReporter.reportError(fErrorReporter.getLocator(),
  +                                                                                   XMLMessages.XML_DOMAIN,
  +                                                                                   XMLMessages.MSG_TWO_COLONS_IN_QNAME,
  +                                                                                   XMLMessages.P5_INVALID_CHARACTER,
  +                                                                                   null,
  +                                                                                   XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
  +                                entityReader.skipPastNmtoken(' ');
  +                        }
  +                }
   
  -		//****DEBUG****
  +                //****DEBUG****
           if (DEBUG) {
               String nsFlag = "";
               if ( fNamespacesEnabled ) {
                   nsFlag = "NameSpacesEnabled";
               }
  -
  -            print("(SCN) XMLValidator.scanElementType: " + param("elementType",elementType) + nsFlag + "\n");
  +            print("(SCN) XMLValidator.scanElementType: " + param("elementType",element.rawname) + nsFlag + "\n");
           }
  -		//****DEBUG****
  +                //****DEBUG****
   
  -        return elementType;
  -    }
  +    } // scanElementType(XMLEntityHandler.EntityReader,char,QName)
   
  -    public boolean scanExpectedElementType(XMLEntityHandler.EntityReader entityReader, char fastchar) throws Exception {
  +    /** Scans expected element type. */
  +    public boolean scanExpectedElementType(XMLEntityHandler.EntityReader entityReader, 
  +                                           char fastchar, QName element) 
  +        throws Exception {
   
  -		//****DEBUG****
  -		if (DEBUG) print("(SCN) XMLValidator.scanExpectedElementType ... \n");
  -		//****DEBUG****
  +                //****DEBUG****
  +                if (DEBUG) print("(SCN) XMLValidator.scanExpectedElementType ... \n");
  +                //****DEBUG****
   
  -        if (fCurrentElementCharArrayRange == null)
  +        if (fCurrentElementCharArrayRange == null) {
               fCurrentElementCharArrayRange = fStringPool.createCharArrayRange();
  -        fStringPool.getCharArrayRange(fCurrentElementType, fCurrentElementCharArrayRange);
  +        }
  +        fStringPool.getCharArrayRange(fCurrentElement.rawname, fCurrentElementCharArrayRange);
           return entityReader.scanExpectedName(fastchar, fCurrentElementCharArrayRange);
  -    }
  -
  -	
  -	//
  -	// scanAttributeName
  -	//
   
  -    public int scanAttributeName(XMLEntityHandler.EntityReader entityReader, int elementType) throws Exception {
  +    } // scanExpectedElementType(XMLEntityHandler.EntityReader,char,QName)
   
  -		int attrName;
  +    /** Scans attribute name. */
  +    public void scanAttributeName(XMLEntityHandler.EntityReader entityReader, 
  +                                  QName element, QName attribute) 
  +        throws Exception {
   
           if (!fSeenRootElement) {
               fSeenRootElement = true;
  -            rootElementSpecified(elementType);
  +            rootElementSpecified(element);
               fStringPool.resetShuffleCount();
           }
   
           if (!fNamespacesEnabled) {
  -            attrName = entityReader.scanName('=');
  -        } else {
  -			attrName = entityReader.scanQName('=');
  -			if (entityReader.lookingAtChar(':', false)) {
  -				fErrorReporter.reportError(fErrorReporter.getLocator(),
  -										   XMLMessages.XML_DOMAIN,
  -										   XMLMessages.MSG_TWO_COLONS_IN_QNAME,
  -										   XMLMessages.P5_INVALID_CHARACTER,
  -										   null,
  -										   XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
  -				entityReader.skipPastNmtoken(' ');
  -			}
  -		}
  -
  -		//****DEBUG****
  -		if (DEBUG) print("(SCN) XMLValidator.scanAttributeName: " + param("elementType",elementType) + param("attrName",attrName) + "\n");
  -		//****DEBUG****
  -
  -        return attrName;
  -    }
  +            attribute.clear();
  +            attribute.localpart = entityReader.scanName('=');
  +            attribute.rawname = attribute.localpart;
  +        } 
  +        else {
  +            entityReader.scanQName('=', attribute);
  +                        if (entityReader.lookingAtChar(':', false)) {
  +                                fErrorReporter.reportError(fErrorReporter.getLocator(),
  +                                                                                   XMLMessages.XML_DOMAIN,
  +                                                                                   XMLMessages.MSG_TWO_COLONS_IN_QNAME,
  +                                                                                   XMLMessages.P5_INVALID_CHARACTER,
  +                                                                                   null,
  +                                                                                   XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
  +                                entityReader.skipPastNmtoken(' ');
  +                        }
  +                }
   
  +                //****DEBUG****
  +                if (DEBUG) print("(SCN) XMLValidator.scanAttributeName: " + param("elementType",element.rawname) + param("attrName",attribute.rawname) + "\n");
  +                //****DEBUG****
   
  -	//
  -	// callStartDocument
  -	//
  +    } // scanAttributeName(XMLEntityHandler.EntityReader,QName,QName)
   
  +    /** Call start document. */
       public void callStartDocument() throws Exception {
   
  -		//****DEBUG****
  -		if (DEBUG) print("\n(VAL) XMLValidator.callStartDocument\n");
  -		//****DEBUG****
  +                //****DEBUG****
  +                if (DEBUG) print("\n(VAL) XMLValidator.callStartDocument\n");
  +                //****DEBUG****
   
           if (!fCalledStartDocument) {
               fDocumentHandler.startDocument();
               fCalledStartDocument = true;
           }
       }
  -
   
  -	//
  -	// callEndDocument
  -	//
  -
  +    /** Call end document. */
       public void callEndDocument() throws Exception {
   
  -		//****DEBUG****
  -		if (DEBUG) print("(VAL) XMLValidator.callEndDocument\n\n");
  -		//****DEBUG****
  +                //****DEBUG****
  +                if (DEBUG) print("(VAL) XMLValidator.callEndDocument\n\n");
  +                //****DEBUG****
   
  -        if (fCalledStartDocument)
  +        if (fCalledStartDocument) {
               fDocumentHandler.endDocument();
  +        }
       }
   
  +    /** Call XML declaration. */
       public void callXMLDecl(int version, int encoding, int standalone) throws Exception {
           fDocumentHandler.xmlDecl(version, encoding, standalone);
       }
  +    public void callStandaloneIsYes() throws Exception {
  +        // standalone = "yes". said XMLDocumentScanner.
  +        fStandaloneReader = fEntityHandler.getReaderId() ;
  +        
  +    }
  +    
  +
   
  +    /** Call text declaration. */
       public void callTextDecl(int version, int encoding) throws Exception {
           fDocumentHandler.textDecl(version, encoding);
       }
  +
  +    /**
  +     * Signal the scanning of an element name in a start element tag.
  +     *
  +     * @param element Element name scanned.
  +     */
  +    public void element(QName element) throws Exception {
  +        fAttrListHandle = -1;
  +    }
  +    /**
  +     * Signal the scanning of an attribute associated to the previous
  +     * start element tag.
  +     *
  +     * @param element Element name scanned.
  +     * @param attrName Attribute name scanned.
  +     * @param attrValue The string pool index of the attribute value.
  +     */
  +    public boolean attribute(QName element, QName attrName, int attrValue) throws Exception {
  +        if (fAttrListHandle == -1) {
  +            fAttrListHandle = fAttrList.startAttrList();
  +        }
  +        
  +        // if fAttrList.addAttr returns -1, indicates duplicate att in start tag of an element.
  +        // specified: true, search : true
  +        return fAttrList.addAttr(attrName, attrValue, -1, true, true) == -1;
  +    }
  +
  +    /** Call start element. */
  +    public void callStartElement(QName element) throws Exception {
  +
  +        if ( DEBUG_SCHEMA_VALIDATION )
  +            System.out.println("\n=======StartElement : " + fStringPool.toString(element.localpart));
  +
  +        if (fAttrListHandle != -1) {
  +            fAttrList.endAttrList();
  +        }
   
  -    public void callStartElement(int elementType) throws Exception {
           //
           // Check after all specified attrs are scanned
           // (1) report error for REQUIRED attrs that are missing (V_TAGc)
           // (2) add default attrs (FIXED and NOT_FIXED)
           //
   
  -		//****DEBUG****
  -		if (DEBUG) print("(VAL) XMLValidator.callStartElement: " + param("elementType",elementType) + "\n");
  -		//****DEBUG****
  +                //****DEBUG****
  +                if (DEBUG) print("(VAL) XMLValidator.callStartElement: " + param("elementType",element.rawname) + "\n");
  +                //****DEBUG****
   
           if (!fSeenRootElement) {
               fSeenRootElement = true;
  -            rootElementSpecified(elementType);
  +            rootElementSpecified(element);
               fStringPool.resetShuffleCount();
           }
  +        
           fCheckedForSchema = true;
  -        validateElementAndAttributes(elementType, fAttrList);
  -        fDocumentHandler.startElement(elementType, fAttrList, fAttrListHandle);
  +        if (fNamespacesEnabled) {
  +            bindNamespacesToElementAndAttributes(element, fAttrList);
  +        }
  +
  +        validateElementAndAttributes(element, fAttrList);
  +        fDocumentHandler.startElement(element, fAttrList, fAttrListHandle);
           fAttrListHandle = -1;
  +
  +        //before we increment the element depth, add this element's QName to its enclosing element 's children list
           if (fElementDepth >= 0) {
  -            int[] children = fElementChildren[fElementDepth];
  +            QName[] children = fElementChildren[fElementDepth];
               int childCount = fElementChildCount[fElementDepth];
               try {
  -                children[childCount] = elementType;
  -            } catch (NullPointerException ex) {
  -                children = fElementChildren[fElementDepth] = new int[256];
  +                children[childCount].setValues(element);
  +            } 
  +            catch (NullPointerException ex) {
  +                children = fElementChildren[fElementDepth] = new QName[256];
  +                for (int i=0; i<256; i++) {
  +                    children[i] = new QName();
  +                }
                   childCount = 0; // should really assert this...
  -                children[childCount] = elementType;
  -            } catch (ArrayIndexOutOfBoundsException ex) {
  -                int[] newChildren = new int[childCount * 2];
  +                children[childCount].setValues(element);
  +            } 
  +            catch (ArrayIndexOutOfBoundsException ex) {
  +                QName[] newChildren = new QName[childCount * 2];
  +                for (int i=0; i<(childCount*2); i++) {
  +                    children[i] = new QName();
  +                }
                   System.arraycopy(children, 0, newChildren, 0, childCount);
                   children = fElementChildren[fElementDepth] = newChildren;
  -                children[childCount] = elementType;
  +                children[childCount].setValues(element);
               }
               fElementChildCount[fElementDepth] = ++childCount;
           }
  +        
  +        // One more level of depth
           fElementDepth++;
  -        if (fElementDepth == fElementTypeStack.length) {
  -            int[] newStack = new int[fElementDepth * 2];
  -            System.arraycopy(fElementTypeStack, 0, newStack, 0, fElementDepth);
  -            fElementTypeStack = newStack;
  -            newStack = new int[fElementDepth * 2];
  -            System.arraycopy(fElementEntityStack, 0, newStack, 0, fElementDepth);
  -            fElementEntityStack = newStack;
  -            newStack = new int[fElementDepth * 2];
  -            System.arraycopy(fElementIndexStack, 0, newStack, 0, fElementDepth);
  -            fElementIndexStack = newStack;
  -            newStack = new int[fElementDepth * 2];
  -            System.arraycopy(fContentSpecTypeStack, 0, newStack, 0, fElementDepth);
  -            fContentSpecTypeStack = newStack;
  -            newStack = new int[fElementDepth * 2];
  -            System.arraycopy(fElementChildCount, 0, newStack, 0, fElementDepth);
  -            fElementChildCount = newStack;
  -            int[][] newContentStack = new int[fElementDepth * 2][];
  -            System.arraycopy(fElementChildren, 0, newContentStack, 0, fElementDepth);
  -            fElementChildren = newContentStack;
  -        }
  -        fCurrentElementType = elementType;
  +        ensureStackCapacity(fElementDepth);
  +
  +        fCurrentElement.setValues(element);
           fCurrentElementEntity = fEntityHandler.getReaderId();
  -        fElementTypeStack[fElementDepth] = fCurrentElementType;
  +        fElementTypeStack[fElementDepth] = fCurrentElement.rawname;
           fElementEntityStack[fElementDepth] = fCurrentElementEntity;
           fElementIndexStack[fElementDepth] = fCurrentElementIndex;
           fContentSpecTypeStack[fElementDepth] = fCurrentContentSpecType;
           fElementChildCount[fElementDepth] = 0;
  -    }
   
  +        //REVISIT: Validation
  +        if ( fCurrentElementIndex > -1 && fGrammar instanceof SchemaGrammar  && fValidating) {
  +            fCurrentScope = ((SchemaGrammar) fGrammar).getElementDefinedScope(fCurrentElementIndex);
  +        }
   
  -	//
  -	// callEndElement
  -	//
  +        fScopeStack[fElementDepth] = fCurrentScope;
  +        fGrammarNameSpaceIndexStack[fElementDepth] = fGrammarNameSpaceIndex;
   
  -    public void callEndElement(int readerId) throws Exception {
  +    } // callStartElement(QName)
   
  -		//****DEBUG****
  -		if (DEBUG) print("(VAL) XMLValidator.callEndElement: " + param("readerId",readerId) + "\n");
  -		//****DEBUG****
  +    private void ensureStackCapacity ( int newElementDepth) {
  +  
  +        if (newElementDepth == fElementTypeStack.length) {
  +            int[] newStack = new int[newElementDepth * 2];
   
  -        int elementType = fCurrentElementType;
  -        if (fCurrentElementEntity != readerId) {
  -            fErrorReporter.reportError(fErrorReporter.getLocator(),
  +            System.arraycopy(fScopeStack, 0, newStack, 0, newElementDepth);
  +            fScopeStack = newStack;
  +            newStack = new int[newElementDepth * 2];
  +            System.arraycopy(fGrammarNameSpaceIndexStack, 0, newStack, 0, newElementDepth);
  +            fGrammarNameSpaceIndexStack = newStack;
  +
  +            newStack = new int[newElementDepth * 2];
  +
  +
  +            System.arraycopy(fElementTypeStack, 0, newStack, 0, newElementDepth);
  +            fElementTypeStack = newStack;
  +            newStack = new int[newElementDepth * 2];
  +            System.arraycopy(fElementEntityStack, 0, newStack, 0, newElementDepth);
  +            fElementEntityStack = newStack;
  +            newStack = new int[newElementDepth * 2];
  +            System.arraycopy(fElementIndexStack, 0, newStack, 0, newElementDepth);
  +            fElementIndexStack = newStack;
  +            newStack = new int[newElementDepth * 2];
  +            System.arraycopy(fContentSpecTypeStack, 0, newStack, 0, newElementDepth);
  +            fContentSpecTypeStack = newStack;
  +            newStack = new int[newElementDepth * 2];
  +            System.arraycopy(fElementChildCount, 0, newStack, 0, newElementDepth);
  +            fElementChildCount = newStack;
  +            QName[][] newContentStack = new QName[newElementDepth * 2][];
  +            System.arraycopy(fElementChildren, 0, newContentStack, 0, newElementDepth);
  +            fElementChildren = newContentStack;
  +        }
  +    }
  +
  +    /** Call end element. */
  +    public void callEndElement(int readerId) throws Exception {
  +        if ( DEBUG_SCHEMA_VALIDATION )
  +            System.out.println("=======EndElement : " + fStringPool.toString(fCurrentElement.localpart)+"\n");
  +
  +                //****DEBUG****
  +                if (DEBUG) print("(VAL) XMLValidator.callEndElement: " + param("readerId",readerId) + "\n");
  +                //****DEBUG****
  +
  +        int prefixIndex = fCurrentElement.prefix;
  +        // REVISIT: Validation
  +        int elementType = fCurrentElement.rawname;
  +
  +        if (fCurrentElementEntity != readerId) {
  +            fErrorReporter.reportError(fErrorReporter.getLocator(),
                                          XMLMessages.XML_DOMAIN,
                                          XMLMessages.MSG_ELEMENT_ENTITY_MISMATCH,
                                          XMLMessages.P78_NOT_WELLFORMED,
                                          new Object[] { fStringPool.toString(elementType) },
                                          XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
           }
  -        fDocumentHandler.endElement(elementType);
  +        fDocumentHandler.endElement(fCurrentElement);
           if (fValidating) {
               int elementIndex = fCurrentElementIndex;
               if (elementIndex != -1 && fCurrentContentSpecType != -1) {
                   int childCount = peekChildCount();
                   int result = checkContent(elementIndex, childCount, peekChildren());
  +
  +                if ( DEBUG_SCHEMA_VALIDATION )
  +                    System.out.println("!!!!!!!!In XMLValidator, the return value from checkContent : " + result);
  +
                   if (result != -1) {
                       int majorCode = result != childCount ? XMLMessages.MSG_CONTENT_INVALID : XMLMessages.MSG_CONTENT_INCOMPLETE;
  +                    fGrammar.getElementDecl(elementIndex, fTempElementDecl);
                       reportRecoverableXMLError(majorCode,
                                                 0,
                                                 fStringPool.toString(elementType),
  -                                              getContentSpecAsString(elementIndex));
  +                                              XMLContentSpec.toString(fGrammar, fStringPool, fTempElementDecl.contentSpecIndex));// REVISIT: getContentSpecAsString(elementIndex));
                   }
               }
           }
  -        if (fNamespacesEnabled)
  +        if (fNamespacesEnabled) {
               fNamespacesScope.decreaseDepth();
  -        if (fElementDepth-- < 0)
  +        }
  +
  +        // now pop this element off the top of the element stack
  +        if (fElementDepth-- < 0) {
               throw new RuntimeException("FWK008 Element stack underflow");
  +        }
           if (fElementDepth < 0) {
  -            fCurrentElementType = -1;
  +            fCurrentElement.clear();
               fCurrentElementEntity = -1;
               fCurrentElementIndex = -1;
               fCurrentContentSpecType = -1;
  @@ -681,91 +930,102 @@
               // (1) check that there was an element with a matching id for every
               //   IDREF and IDREFS attr (V_IDREF0)
               //
  -            if (fValidating && fIdRefs != null)
  +            if (fValidating && fIdRefs != null) {
                   checkIdRefs();
  +            }
               return;
           }
  -        fCurrentElementType = fElementTypeStack[fElementDepth];
  +
  +        //restore enclosing element to all the "current" variables
  +        // REVISIT: Validation. This information needs to be stored.
  +        fCurrentElement.prefix = -1;
  +        fCurrentElement.localpart = fElementTypeStack[fElementDepth];
  +        fCurrentElement.rawname = fElementTypeStack[fElementDepth];
           fCurrentElementEntity = fElementEntityStack[fElementDepth];
           fCurrentElementIndex = fElementIndexStack[fElementDepth];
           fCurrentContentSpecType = fContentSpecTypeStack[fElementDepth];
  -        if (fValidating)
  +
  +        //REVISIT: Validation
  +        fCurrentScope = fScopeStack[fElementDepth];
  +
  +        if ( DEBUG_SCHEMA_VALIDATION ) {
  +        
  +/****
  +System.out.println("+++++ currentElement : " + fStringPool.toString(elementType)+
  +                   "\n fCurrentElementIndex : " + fCurrentElementIndex +
  +                   "\n fCurrentScope : " + fCurrentScope +
  +                   "\n fCurrentContentSpecType : " + fCurrentContentSpecType +
  +                   "\n++++++++++++++++++++++++++++++++++++++++++++++++" );
  +/****/  
  +        }
  +
  +        // if enclosing element's Schema is different, need to switch "context"
  +        if ( fGrammarNameSpaceIndex != fGrammarNameSpaceIndexStack[fElementDepth] ) {
  +            fGrammarNameSpaceIndex = fGrammarNameSpaceIndexStack[fElementDepth];
  +            switchGrammar(fGrammarNameSpaceIndex);
  +        }
  +
  +        if (fValidating) {
               fBufferDatatype = false;
  +        }
           fInElementContent = (fCurrentContentSpecType == fCHILDRENSymbol);
  -    }
  +
  +    } // callEndElement(int)
   
  -	
  -	//
  -	// validateVersionNum
  -	//
  -
  -    public boolean validVersionNum(String version) {
  -
  -		//****DEBUG****
  -		if (DEBUG) print("(VAL) XMLValidator.validVersionNum: version=" + version + "\n");
  -		//****DEBUG****
  +    /** Returns true if the version number is valid. */
  +    /*public boolean validVersionNum(String version) {
   
  +                //****DEBUG****
  +                if (DEBUG) print("(VAL) XMLValidator.validVersionNum: version=" + version + "\n");
  +                //****DEBUG****
  +
           return XMLCharacterProperties.validVersionNum(version);
  -    }
  +    }*/
   
  +    /** Returns true if the encoding name is valid. */
  +    /*public boolean validEncName(String encoding) {
   
  -	//
  -	// validEncName
  -	//
  -
  -    public boolean validEncName(String encoding) {
  -
  -		//****DEBUG****
  -		if (DEBUG) print("(VAL) XMLValidator.validEncName: encoding=" + encoding + "\n");
  -		//****DEBUG****
  +                //****DEBUG****
  +                if (DEBUG) print("(VAL) XMLValidator.validEncName: encoding=" + encoding + "\n");
  +                //****DEBUG****
   
           return XMLCharacterProperties.validEncName(encoding);
  -    }
  -
  -	
  -	//
  -	// callStartCDATA
  -	//
  +    }*/
   
  +    /** Call start CDATA section. */
       public void callStartCDATA() throws Exception {
   
  -		//****DEBUG****
  -		if (DEBUG) print("(VAL) XMLValidator.callStartCDATA\n");
  -		//****DEBUG****
  +                //****DEBUG****
  +                if (DEBUG) print("(VAL) XMLValidator.callStartCDATA\n");
  +                //****DEBUG****
   
           fDocumentHandler.startCDATA();
       }
   
  -
  -	//
  -	// callEndCDATA
  -	//
  -
  +    /** Call end CDATA section. */
       public void callEndCDATA() throws Exception {
   
  -		//****DEBUG****
  -		if (DEBUG) print("(VAL) XMLValidator.callEndCDATA\n");
  -		//****DEBUG****
  +                //****DEBUG****
  +                if (DEBUG) print("(VAL) XMLValidator.callEndCDATA\n");
  +                //****DEBUG****
   
           fDocumentHandler.endCDATA();
       }
  -
  -
  -	//
  -	// callCharacters
  -	//
   
  +    /** Call characters. */
       public void callCharacters(int ch) throws Exception {
   
  -		//****DEBUG****
  -		if (DEBUG) print("(VAL) XMLValidator.callCharacters: ... \n");
  -		//****DEBUG****
  +                //****DEBUG****
  +                if (DEBUG) print("(VAL) XMLValidator.callCharacters: ... \n");
  +                //****DEBUG****
   
  -        if (fCharRefData == null)
  +        if (fCharRefData == null) {
               fCharRefData = new char[2];
  +        }
           int count = (ch < 0x10000) ? 1 : 2;
  -        if (count == 1)
  +        if (count == 1) {
               fCharRefData[0] = (char)ch;
  +        }
           else {
               fCharRefData[0] = (char)(((ch-0x00010000)>>10)+0xd800);
               fCharRefData[1] = (char)(((ch-0x00010000)&0x3ff)+0xdc00);
  @@ -775,44 +1035,34 @@
           }
           if (fSendCharDataAsCharArray) {
               fDocumentHandler.characters(fCharRefData, 0, count);
  -        } else {
  +        } 
  +        else {
               int index = fStringPool.addString(new String(fCharRefData, 0, count));
               fDocumentHandler.characters(index);
           }
  -    }
  -
   
  -	//
  -	// callProcessingInstruction
  -	//
  +    } // callCharacters(int)
   
  +    /** Call processing instruction. */
       public void callProcessingInstruction(int target, int data) throws Exception {
           fDocumentHandler.processingInstruction(target, data);
       }
  -
  -
  -	//
  -	// callComment
  -	//
   
  +    /** Call comment. */
       public void callComment(int comment) throws Exception {
           fDocumentHandler.comment(comment);
       }
   
  +    /** Scan doctype declaration. */
  +    /*public void scanDoctypeDecl(boolean standalone) throws Exception {
   
  -	//
  -	// scanDocTypeDecl
  -	//
  -
  -    public void scanDoctypeDecl(boolean standalone) throws Exception {
  -
  -		//****DEBUG****
  -		if (DEBUG) print("(SCN) XMLValidator.scanDoctypeDecl\n");
  -		//****DEBUG****
  -
  -		//****DEBUG****
  -		if (DEBUG) print("\n\n**** BEGIN DTD ****\n\n");
  -		//****DEBUG****
  +                //****DEBUG****
  +                if (DEBUG) print("(SCN) XMLValidator.scanDoctypeDecl\n");
  +                //****DEBUG****
  +
  +                //****DEBUG****
  +                if (DEBUG) print("\n\n**** BEGIN DTD ****\n\n");
  +                //****DEBUG****
   
           fScanningDTD = true;
           fCheckedForSchema = true;
  @@ -821,7 +1071,8 @@
           fDeclsAreExternal = false;
           if (fDTDImporter == null) {
               fDTDImporter = new DTDImporter(fStringPool, fErrorReporter, fEntityHandler, this);
  -        } else {
  +        } 
  +        else {
               fDTDImporter.reset(fStringPool);
           }
           fDTDImporter.initHandlers(fDTDHandler);
  @@ -829,46 +1080,45 @@
           fDTDImporter.setNamespacesEnabled(fNamespacesEnabled);
           if (fDTDImporter.scanDoctypeDecl(standalone) && fValidating) {
               // check declared elements
  -            if (fWarningOnUndeclaredElements)
  -                checkDeclaredElements();
  +            if (fWarningOnUndeclaredElements) {
  +                // REVISIT: comment out because won't compile 
  +                // checkDeclaredElements();
  +            }
   
               // check required notations
               fEntityHandler.checkRequiredNotations();
           }
           fScanningDTD = false;
  -
  -		//****DEBUG****
  -		if (DEBUG) print("\n\n**** END DTD ****\n\n");
  -		//****DEBUG****
  -    }
  -
  -
  -	//
  -	// scannAttValue
  -	//
  -
  -    public int scanAttValue(int elementType, int attrName) throws Exception {
  -
  -
  -        fAttrNameLocator = getLocatorImpl(fAttrNameLocator);
  -        int attValue = fDocumentScanner.scanAttValue(elementType, attrName, fValidating/* && attType != fCDATASymbol*/);
  -        if (attValue == -1) {
  -            return XMLDocumentScanner.RESULT_FAILURE;
  -        }
  -
  -		//****DEBUG****
  -		if (DEBUG) print("(SCN) XMLValidator.scanAttValue: " + param ("elementType",elementType) +  param ("attrName",attrName) + 
  -							param ("attValue",attValue) + "\n" );
  -		//****DEBUG****
   
  -		//
  -		// Check for Schema and load
  -		//
  +                //****DEBUG****
  +                if (DEBUG) print("\n\n**** END DTD ****\n\n");
  +                //****DEBUG****
  +
  +    } // scanDoctypeDecl(boolean)
  +    */
  +    /** Scan attribute value. */
  +//    public int scanAttValue(QName element, QName attribute) throws Exception {
  +
  + //       fAttrNameLocator = getLocatorImpl(fAttrNameLocator);
  + //       int attValue = fDocumentScanner.scanAttValue(element, attribute, fValidating/* && attType != fCDATASymbol*/);
  + //       if (attValue == -1) {
  +  //          return XMLDocumentScanner.RESULT_FAILURE;
  +  //      }
  +
  +                //****DEBUG****
  +    //            if (DEBUG) print("(SCN) XMLValidator.scanAttValue: " + param ("elementType",element.rawname) +  param ("attrName",attribute.rawname) + 
  +//                                                        param ("attValue",attValue) + "\n" );
  +                //****DEBUG****
   
  +                //
  +                // Check for Schema and load
  +                //
  +    
  +        /*
           if (!fCheckedForSchema) {
               fCheckedForSchema = true;
               if (attrName == fStringPool.addSymbol("xmlns")) { // default namespacedecl
  -				
  +                                
                   if (fSchemaImporter == null) {
                       fSchemaImporter = new SchemaImporter(fStringPool, fErrorReporter, fEntityHandler, this);
                   } else {
  @@ -881,37 +1131,40 @@
                       is = new InputSource(fs);
                   }
   
  -				//****DEBUG****
  -				if (DEBUG) print( "\n\n**** BEGIN SCHEMA ****\n\n" );
  -				//****DEBUG****
  +                                //****DEBUG****
  +                                if (DEBUG) print( "\n\n**** BEGIN SCHEMA ****\n\n" );
  +                                //****DEBUG****
   
                   fSchemaImporter.loadSchema(is);
   
  -				//****DEBUG****
  -				if (DEBUG) print( "\n\n**** END SCHEMA ****\n\n" );
  -				//****DEBUG****
  +                                //****DEBUG****
  +                                if (DEBUG) print( "\n\n**** END SCHEMA ****\n\n" );
  +                                //****DEBUG****
   
                   fSchemaDocument = fSchemaImporter.getSchemaDocument();
               }
           }
  +        */
   
  -        if (!fValidating && fAttDefCount == 0) {
  +      /*  if (!fValidating && fAttDefCount == 0) {
               int attType = fCDATASymbol;
               if (fAttrListHandle == -1)
                   fAttrListHandle = fAttrList.startAttrList();
  -            if (fAttrList.addAttr(attrName, attValue, attType, true, true) == -1) {
  +            // REVISIT: Should this be localpart or rawname?
  +            if (fAttrList.addAttr(attribute, attValue, attType, true, true) == -1) {
                   return XMLDocumentScanner.RESULT_DUPLICATE_ATTR;
               }
               return XMLDocumentScanner.RESULT_SUCCESS;
           }
   
  -        int attDefIndex = getAttDef(elementType, attrName);
  +        // REVISIT: Validation. What should these be?
  +        int attDefIndex = getAttDef(element, attribute);
           if (attDefIndex == -1) {
               if (fValidating) {
                   // REVISIT - cache the elem/attr tuple so that we only give
                   //  this error once for each unique occurrence
  -                Object[] args = { fStringPool.toString(elementType),
  -                                  fStringPool.toString(attrName) };
  +                Object[] args = { fStringPool.toString(element.rawname),
  +                                  fStringPool.toString(attribute.rawname) };
                   fErrorReporter.reportError(fAttrNameLocator,
                                              XMLMessages.XML_DOMAIN,
                                              XMLMessages.MSG_ATTRIBUTE_NOT_DECLARED,
  @@ -920,9 +1173,11 @@
                                              XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
               }
               int attType = fCDATASymbol;
  -            if (fAttrListHandle == -1)
  +            if (fAttrListHandle == -1) {
                   fAttrListHandle = fAttrList.startAttrList();
  -            if (fAttrList.addAttr(attrName, attValue, attType, true, true) == -1) {
  +            }
  +            // REVISIT: Validation. What should the name be?
  +            if (fAttrList.addAttr(attribute, attValue, attType, true, true) == -1) {
                   return XMLDocumentScanner.RESULT_DUPLICATE_ATTR;
               }
               return XMLDocumentScanner.RESULT_SUCCESS;
  @@ -932,1052 +1187,647 @@
           if (attType != fCDATASymbol) {
               AttributeValidator av = getAttributeValidator(attDefIndex);
               int enumHandle = getEnumeration(attDefIndex);
  -            attValue = av.normalize(elementType, attrName, attValue, attType, enumHandle);
  +            // REVISIT: Validation. What should these be?
  +            attValue = av.normalize(element, attribute, 
  +                                    attValue, attType, enumHandle);
           }
   
  -        if (fAttrListHandle == -1)
  +        if (fAttrListHandle == -1) {
               fAttrListHandle = fAttrList.startAttrList();
  -        if (fAttrList.addAttr(attrName, attValue, attType, true, true) == -1) {
  +        }
  +        // REVISIT: Validation. What should the name be?
  +        if (fAttrList.addAttr(attribute, attValue, attType, true, true) == -1) {
               return XMLDocumentScanner.RESULT_DUPLICATE_ATTR;
           }
   
           return XMLDocumentScanner.RESULT_SUCCESS;
  -    }
   
  -    //
  -    // NamespacesScope.NamespacesHandler interface
  +    } // scanAttValue(QName,QName):int
  +*/
       //
  -    //    public void startNamespaceDeclScope(int prefix, int uri) throws Exception;
  -    //    public void endNamespaceDeclScope(int prefix) throws Exception;
  +    // NamespacesScope.NamespacesHandler methods
       //
   
  +    /** Start a new namespace declaration scope. */
       public void startNamespaceDeclScope(int prefix, int uri) throws Exception {
  -		//****DEBUG****
  -		if (DEBUG) print("(VAL) XMLValidator.startNamespaceDeclScope: " + param("prefix",prefix) + param("uri",uri) + "\n");
  -		//****DEBUG****
  +                //****DEBUG****
  +                if (DEBUG) print("(VAL) XMLValidator.startNamespaceDeclScope: " + param("prefix",prefix) + param("uri",uri) + "\n");
  +                //****DEBUG****
           fDocumentHandler.startNamespaceDeclScope(prefix, uri);
       }
   
  -
  -	//
  -	// endNamespaceDeclScope
  -	//
  -
  +    /** End a namespace declaration scope. */
       public void endNamespaceDeclScope(int prefix) throws Exception {
  -		//****DEBUG****
  -		if (DEBUG) print("(VAL) XMLValidator.endNamespaceDeclScope: " + param("prefix",prefix) + "\n");
  -		//****DEBUG****
  +                //****DEBUG****
  +                if (DEBUG) print("(VAL) XMLValidator.endNamespaceDeclScope: " + param("prefix",prefix) + "\n");
  +                //****DEBUG****
           fDocumentHandler.endNamespaceDeclScope(prefix);
       }
   
  -    //
  -    // XMLValidator implementation
  -    //
  -    private void resetCommon(StringPool stringPool) throws Exception {
  -		//****DEBUG****
  -		if (DEBUG) print("(POP) XMLValidator.resetCommon\n");
  -		//****DEBUG****
  -        fStringPool = stringPool;
  -        fValidating = fValidationEnabled;
  -        fValidationEnabledByDynamic = false;
  -        fDynamicDisabledByValidation = false;
  -        poolReset();
  -        fCalledStartDocument = false;
  -        fStandaloneReader = -1;
  -        fElementDepth = -1;
  -        fSeenRootElement = false;
  -        fSeenDoctypeDecl = false;
  -        fNamespacesScope = null;
  -        fNamespacesPrefix = -1;
  -        fRootElementType = -1;
  -        fAttrListHandle = -1;
  -        fElementDeclCount = 0;
  -        fCheckedForSchema = false;
  -        fSchemaDocument = null;
  -        init();
  -    }
  +    // attributes
   
  -    private void init() {
  -		//****DEBUG****
  -		if (DEBUG) print("(POP) XMLValidator.init\n");
  -		//****DEBUG****
  -        fEMPTYSymbol = fStringPool.addSymbol("EMPTY");
  -        fANYSymbol = fStringPool.addSymbol("ANY");
  -        fMIXEDSymbol = fStringPool.addSymbol("MIXED");
  -        fCHILDRENSymbol = fStringPool.addSymbol("CHILDREN");
  -        fCDATASymbol = fStringPool.addSymbol("CDATA");
  -        fIDSymbol = fStringPool.addSymbol("ID");
  -        fIDREFSymbol = fStringPool.addSymbol("IDREF");
  -        fIDREFSSymbol = fStringPool.addSymbol("IDREFS");
  -        fENTITYSymbol = fStringPool.addSymbol("ENTITY");
  -        fENTITIESSymbol = fStringPool.addSymbol("ENTITIES");
  -        fNMTOKENSymbol = fStringPool.addSymbol("NMTOKEN");
  -        fNMTOKENSSymbol = fStringPool.addSymbol("NMTOKENS");
  -        fNOTATIONSymbol = fStringPool.addSymbol("NOTATION");
  -        fENUMERATIONSymbol = fStringPool.addSymbol("ENUMERATION");
  -        fREQUIREDSymbol = fStringPool.addSymbol("#REQUIRED");
  -        fFIXEDSymbol = fStringPool.addSymbol("#FIXED");
  -        fDATATYPESymbol = fStringPool.addSymbol("DATATYPE");
  -        fEpsilonIndex = fStringPool.addSymbol("<<CMNODE_EPSILON>>");
  -        fXMLLang = fStringPool.addSymbol("xml:lang");
  +    /** Normalize attribute value. */
  +    public int normalizeAttValue(QName element, QName attribute, 
  +                                int attValue, int attType, boolean list,
  +                                 int enumHandle) throws Exception {
  +
  +                //****DEBUG****
  +                if (DEBUG) print("(VAL) XMLValidator.normalizeAttValue: " + param("elementType",element.rawname) + param("attValue",attValue) +
  +                                                        param("attType",attType) + param("enumHandle",enumHandle) + "\n");
  +                //****DEBUG****
  +        AttributeValidator av = getValidatorForAttType(attType, list);
  +        if (av != null) {
  +            return av.normalize(element, attribute, attValue, attType, enumHandle);
  +        }
  +        return -1;
  +
  +    } // normalizeAttValue(QName,QName,int,int,boolean,int):int
  +
  +    // other
  +
  +    /** Sets the root element. */
  +    public void setRootElementType(QName rootElement) {
  +        fRootElement.setValues(rootElement);
       }
  -    //
  -    //
  -    //
  -    public int normalizeAttValue(int elementType, int attrName, int attValue, int attType, int enumHandle) throws Exception {
  -		//****DEBUG****
  -		if (DEBUG) print("(VAL) XMLValidator.normalizeAttValue: " + param("elementType",elementType) + param("attValue",attValue) +
  -							param("attType",attType) + param("enumHandle",enumHandle) + "\n");
  -		//****DEBUG****
  -        AttributeValidator av = getValidatorForAttType(attType);
  -        return av.normalize(elementType, attrName, attValue, attType, enumHandle);
  +    
  +    
  +    /*
  +    // a convenience method for TraverseSchema 
  +    public int addElementDecl(QName elementDecl, int scopeDefined,
  +                              int contentSpecType, int contentSpec, 
  +                              boolean isExternal) {
  +        int elementIndex = 
  +            addElementDecl(elementDecl,contentSpecType,contentSpec,isExternal);
  +
  +        if (elementIndex > -1) {
  + 
  +            int chunk = elementIndex >> CHUNK_SHIFT;
  +            int index = elementIndex & CHUNK_MASK;
  +            fScope[chunk][index] = scopeDefined;
  +        }
  +        
  +        return elementIndex;
  +
       }
   
  +    // Adds an element declaration. 
  +    public int addElementDecl(QName elementDecl, 
  +                              int contentSpecType, int contentSpec, 
  +                              boolean isExternal) {
  +        
  +        //System.out.println("XMLValidator#addElementDecl(QName,int,int,boolean)");
  +        //System.out.println("  elementDecl: "+elementDecl);
  +        //System.out.println("    prefix: "+fStringPool.toString(elementDecl.prefix));
  +        //System.out.println("    localpart: "+fStringPool.toString(elementDecl.localpart));
  +        //System.out.println("    rawname: "+fStringPool.toString(elementDecl.rawname));
  +        //System.out.println("    uri: "+fStringPool.toString(elementDecl.uri));
  +        //try { throw new Exception("!!! STACK TRACE !!!"); }
  +        //catch (Exception e) { e.printStackTrace(); }
   
   
  -	//====================================================
  -	// AttributeValidator Interface and Implementations
  -	//====================================================
  +                //****DEBUG****
  +                if (DEBUG) print("(POP) XMLValidator.addElementDecl: " + param("elementType",elementDecl.rawname) + "\n");
  +                //****DEBUG****
   
  +                int elementIndex = getDeclaration(elementDecl);
  +        if (elementIndex != -1) {
  +            int chunk = elementIndex >> CHUNK_SHIFT;
  +            int index = elementIndex & CHUNK_MASK;
  +            if (fContentSpecType[chunk][index] != -1) {
  +                return -1;
  +            }
  +            fElementDeclIsExternal[chunk][index] = (byte)(isExternal ? 1 : 0);
  +            fContentSpecType[chunk][index] = contentSpecType;
  +            fContentSpec[chunk][index] = contentSpec;
  +            fContentModel[chunk][index] = null;
  +            fElementDeclCount++;
  +            return elementIndex;
  +        }
  +        int chunk = fElementCount >> CHUNK_SHIFT;
  +        int index = fElementCount & CHUNK_MASK;
  +        ensureElementCapacity(chunk);
  +        // REVISIT: Validation. Store as tuple.
  +        fElementType[chunk][index] = elementDecl.rawname;
  +        fElementDeclIsExternal[chunk][index] = (byte)(isExternal ? 1 : 0);
  +        fContentSpecType[chunk][index] = contentSpecType;
  +        fContentSpec[chunk][index] = contentSpec;
  +        fContentModel[chunk][index] = null;
  +        fAttlistHead[chunk][index] = -1;
  +        fAttlistTail[chunk][index] = -1;
  +        setDeclaration(elementDecl, fElementCount);
  +        fElementDeclCount++;
  +        return fElementCount++;
   
  +    } // addElementDecl(QName,int,int,boolean):int
       //
  -    // AttributeValidator
  -    //
  -
  -    public interface AttributeValidator {
  -        //
  -        //
  -        //
  -        public int normalize(int elementType, int attrName, int attValue, int attType, int enumHandle) throws Exception;
  -    }
  +    
  +    /** Gets an element type. */
  +    /*public void getElementType(int elementIndex, QName element) {
   
  +        if (elementIndex < 0 || elementIndex >= fElementCount) {
  +            element.clear();
  +            return;
  +        }
  +        int chunk = elementIndex >> CHUNK_SHIFT;
  +        int index = elementIndex & CHUNK_MASK;
  +        // REVISIT: Validation. Copy in <uri, localpart> tuple.
  +        element.clear();
  +        element.localpart = fElementType[chunk][index];
  +        element.rawname = element.localpart;
   
  -	//
  -	// AttValidatorCDATA
  -	//
  +    } // getElementType(int,QName)
  +    */
  +    /** 
  +     * Returns true if the element declaration is external. 
  +     * <p>
  +     * <strong>Note:</strong> This method is primarilly useful for
  +     * DTDs with internal and external subsets.
  +     */
  +    private boolean getElementDeclIsExternal(int elementIndex) {
  +        /*if (elementIndex < 0 || elementIndex >= fElementCount) {
  +            return false;
  +        }
  +        int chunk = elementIndex >> CHUNK_SHIFT;
  +        int index = elementIndex & CHUNK_MASK;
  +        return (fElementDeclIsExternal[chunk][index] != 0);
  +        */
   
  -    final class AttValidatorCDATA implements AttributeValidator {
  -        public int normalize(int elementType, int attrName, int attValueHandle, int attType, int enumHandle) throws Exception {
  -            //
  -            // Normalize attribute based upon attribute type...
  -            //
  -            return attValueHandle;
  +        if (fGrammar instanceof DTDGrammar ) {
  +            return ((DTDGrammar) fGrammar).getElementDeclIsExternal(elementIndex);
           }
  +        return false;
       }
  -
   
  -	//
  -	// AttValidatorID
  -	//
  +    /** Returns the content spec type for an element index. */
  +    public int getContentSpecType(int elementIndex) {
   
  -    final class AttValidatorID implements AttributeValidator {
  -        public int normalize(int elementType, int attrName, int attValueHandle, int attType, int enumHandle) throws Exception {
  -            //
  -            // Normalize attribute based upon attribute type...
  -            //
  -            String attValue = fStringPool.toString(attValueHandle);
  -            String newAttValue = attValue.trim();
  -            if (fValidating) {
  -                // REVISIT - can we release the old string?
  -                if (newAttValue != attValue) {
  -                    if (invalidStandaloneAttDef(elementType, attrName)) {
  -                        reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
  -                                                  XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
  -                                                  fStringPool.toString(attrName), attValue, newAttValue);
  -                    }
  -                    attValueHandle = fStringPool.addSymbol(newAttValue);
  -                } else {
  -                    attValueHandle = fStringPool.addSymbol(attValueHandle);
  -                }
  -                if (!XMLCharacterProperties.validName(newAttValue)) {
  -                    reportRecoverableXMLError(XMLMessages.MSG_ID_INVALID,
  -                                              XMLMessages.VC_ID,
  -                                              fStringPool.toString(attrName), newAttValue);
  -                }
  -                //
  -                // ID - check that the id value is unique within the document (V_TAG8)
  -                //
  -                if (elementType != -1 && !addId(attValueHandle)) {
  -                    reportRecoverableXMLError(XMLMessages.MSG_ID_NOT_UNIQUE,
  -                                              XMLMessages.VC_ID,
  -                                              fStringPool.toString(attrName), newAttValue);
  -                }
  -            } else if (newAttValue != attValue) {
  -                // REVISIT - can we release the old string?
  -                attValueHandle = fStringPool.addSymbol(newAttValue);
  +        int contentSpecType = -1;
  +        if ( elementIndex > -1) {
  +            if ( fGrammar.getElementDecl(elementIndex,fTempElementDecl) ) {
  +                contentSpecType = fTempElementDecl.type;
               }
  -            return attValueHandle;
  -        }
  -        //
  -        //
  -        //
  -        boolean invalidStandaloneAttDef(int elementType, int attrName) {
  -            if (fStandaloneReader == -1)
  -                return false;
  -            if (elementType == -1) // we are normalizing a default att value...  this ok?
  -                return false;
  -            return getAttDefIsExternal(elementType, attrName);
           }
  +        return contentSpecType;
       }
   
  -	
  -	//
  -	// AttValidatorIDREF
  -	//
  +    /** Returns the XMLContentSpec for an element index. */
  +    /*public XMLContentSpec getContentSpec(int elementIndex) {
  +        if (elementIndex < 0 || elementIndex >= fElementCount) {
  +            return null;
  +        }
  +        int chunk = elementIndex >> CHUNK_SHIFT;
  +        int index = elementIndex & CHUNK_MASK;
  +        if (fContentSpecImpl == null) {
  +            fContentSpecImpl = new ContentSpecImpl();
  +        }
  +        fContentSpecImpl.fStringPool = fStringPool;
  +        fContentSpecImpl.fHandle = fContentSpec[chunk][index];
  +        fContentSpecImpl.fType = fContentSpecType[chunk][index];
  +        return fContentSpecImpl;
  +    }*/
   
  -    final class AttValidatorIDREF implements AttributeValidator {
  -        public int normalize(int elementType, int attrName, int attValueHandle, int attType, int enumHandle) throws Exception {
  -            //
  -            // Normalize attribute based upon attribute type...
  -            //
  -            String attValue = fStringPool.toString(attValueHandle);
  -            String newAttValue = attValue.trim();
  -            if (fValidating) {
  -                // REVISIT - can we release the old string?
  -                if (newAttValue != attValue) {
  -                    if (invalidStandaloneAttDef(elementType, attrName)) {
  -                        reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
  -                                                  XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
  -                                                  fStringPool.toString(attrName), attValue, newAttValue);
  -                    }
  -                    attValueHandle = fStringPool.addSymbol(newAttValue);
  -                } else {
  -                    attValueHandle = fStringPool.addSymbol(attValueHandle);
  -                }
  -                if (!XMLCharacterProperties.validName(newAttValue)) {
  -                    reportRecoverableXMLError(XMLMessages.MSG_IDREF_INVALID,
  -                                              XMLMessages.VC_IDREF,
  -                                              fStringPool.toString(attrName), newAttValue);
  -                }
  -                //
  -                // IDREF - remember the id value
  -                //
  -                if (elementType != -1)
  -                    addIdRef(attValueHandle);
  -            } else if (newAttValue != attValue) {
  -                // REVISIT - can we release the old string?
  -                attValueHandle = fStringPool.addSymbol(newAttValue);
  +    /** Returns the content spec handle for an element index. */
  +    public int getContentSpecHandle(int elementIndex) {
  +        int contentSpecHandle = -1;
  +        if ( elementIndex > -1) {
  +            if ( fGrammar.getElementDecl(elementIndex,fTempElementDecl) ) {
  +                contentSpecHandle = fTempElementDecl.contentSpecIndex;
               }
  -            return attValueHandle;
  -        }
  -        //
  -        //
  -        //
  -        boolean invalidStandaloneAttDef(int elementType, int attrName) {
  -            if (fStandaloneReader == -1)
  -                return false;
  -            if (elementType == -1) // we are normalizing a default att value...  this ok?
  -                return false;
  -            return getAttDefIsExternal(elementType, attrName);
           }
  +        return contentSpecHandle;
       }
   
  +    /** Adds a content spec node. */
  +    /*public int addContentSpecNode(int nodeType, int nodeValue, 
  +                                  int otherNodeValue, 
  +                                  boolean mustBeUnique) throws Exception {
   
  -	//
  -	// AttValidatorIDREFS
  -	//
  +                //****DEBUG****
  +                if (DEBUG) print("(POP) XMLValidator.addContentSpecNode: " + param("nodeType",nodeType) + param("nodeValue",nodeValue) + "\n");
  +                //****DEBUG****
   
  -    final class AttValidatorIDREFS implements AttributeValidator {
  -        public int normalize(int elementType, int attrName, int attValueHandle, int attType, int enumHandle) throws Exception {
  -            //
  -            // Normalize attribute based upon attribute type...
  -            //
  -            String attValue = fStringPool.toString(attValueHandle);
  -            StringTokenizer tokenizer = new StringTokenizer(attValue);
  -            StringBuffer sb = new StringBuffer(attValue.length());
  -            boolean ok = true;
  -            if (tokenizer.hasMoreTokens()) {
  -                while (true) {
  -                    String idName = tokenizer.nextToken();
  -                    if (fValidating) {
  -                        if (!XMLCharacterProperties.validName(idName)) {
  -                            ok = false;
  -                        }
  -                        //
  -                        // IDREFS - remember the id values
  -                        //
  -                        if (elementType != -1)
  -                            addIdRef(fStringPool.addSymbol(idName));
  -                    }
  -                    sb.append(idName);
  -                    if (!tokenizer.hasMoreTokens())
  -                        break;
  -                    sb.append(' ');
  -                }
  -            }
  -            String newAttValue = sb.toString();
  -            if (fValidating && (!ok || newAttValue.length() == 0)) {
  -                reportRecoverableXMLError(XMLMessages.MSG_IDREFS_INVALID,
  -                                          XMLMessages.VC_IDREF,
  -                                          fStringPool.toString(attrName), newAttValue);
  +        if (mustBeUnique) // REVISIT - merge these methods...
  +            return addContentSpecLeafNode(nodeValue);
  +        int chunk = fNodeCount >> CHUNK_SHIFT;
  +        int index = fNodeCount & CHUNK_MASK;
  +        ensureNodeCapacity(chunk);
  +        switch (nodeType) {
  +            case XMLContentSpec.CONTENTSPECNODE_LEAF:
  +            case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE:
  +            case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE:
  +            case XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE: {
  +                fNodeType[chunk][index] = (byte)nodeType;
  +                fNodeValue[chunk][index] = nodeValue;
  +                return fNodeCount++;
               }
  -            if (!newAttValue.equals(attValue)) {
  -                attValueHandle = fStringPool.addString(newAttValue);
  -                if (fValidating && invalidStandaloneAttDef(elementType, attrName)) {
  -                    reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
  -                                              XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
  -                                              fStringPool.toString(attrName), attValue, newAttValue);
  +            case XMLContentSpec.CONTENTSPECNODE_CHOICE:
  +            case XMLContentSpec.CONTENTSPECNODE_SEQ: {
  +                fNodeType[chunk][index] = (byte)nodeType;
  +                fNodeValue[chunk][index] = nodeValue;
  +                int nodeIndex = fNodeCount++;
  +                if (++index == CHUNK_SIZE) {
  +                    chunk++;
  +                    ensureNodeCapacity(chunk);
  +                    index = 0;
                   }
  +                fNodeType[chunk][index] = (byte)(nodeType | 64); // flag second entry for consistancy checking
  +                fNodeValue[chunk][index] = otherNodeValue;
  +                fNodeCount++;
  +                return nodeIndex;
               }
  -            return attValueHandle;
  -        }
  -        //
  -        //
  -        //
  -        boolean invalidStandaloneAttDef(int elementType, int attrName) {
  -            if (fStandaloneReader == -1)
  -                return false;
  -            if (elementType == -1) // we are normalizing a default att value...  this ok?
  -                return false;
  -            return getAttDefIsExternal(elementType, attrName);
  +            default: {
  +                return -1;
  +            }
           }
  -    }
   
  +    } // addContentSpecNode(int,int.int,boolean):int
  +    */
   
  -	//
  -	// AttValidatorENTITY
  -	//
  +    /** Returns a string representation of a content spec node. */
  +    /*public String contentSpecNodeAsString(int contentSpecIndex) {
   
  -    final class AttValidatorENTITY implements AttributeValidator {
  -        public int normalize(int elementType, int attrName, int attValueHandle, int attType, int enumHandle) throws Exception {
  -            //
  -            // Normalize attribute based upon attribute type...
  -            //
  -            String attValue = fStringPool.toString(attValueHandle);
  -            String newAttValue = attValue.trim();
  -            if (fValidating) {
  -                // REVISIT - can we release the old string?
  -                if (newAttValue != attValue) {
  -                    if (invalidStandaloneAttDef(elementType, attrName)) {
  -                        reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
  -                                                  XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
  -                                                  fStringPool.toString(attrName), attValue, newAttValue);
  -                    }
  -                    attValueHandle = fStringPool.addSymbol(newAttValue);
  -                } else {
  -                    attValueHandle = fStringPool.addSymbol(attValueHandle);
  +        int chunk = contentSpecIndex >> CHUNK_SHIFT;
  +        int index = contentSpecIndex & CHUNK_MASK;
  +        int type = fNodeType[chunk][index];
  +        int value = fNodeValue[chunk][index];
  +        StringBuffer sb = new StringBuffer();
  +        switch (type) {
  +            case XMLContentSpec.CONTENTSPECNODE_LEAF: {
  +                sb.append("(" + (value == -1 ? "#PCDATA" : fStringPool.toString(value)) + ")");
  +                break;
  +            }
  +            case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE: {
  +                chunk = value >> CHUNK_SHIFT;
  +                index = value & CHUNK_MASK;
  +                if (fNodeType[chunk][index] == XMLContentSpec.CONTENTSPECNODE_LEAF) {
  +                    value = fNodeValue[chunk][index];
  +                    sb.append("(" + (value == -1 ? "#PCDATA" : fStringPool.toString(value)) + ")?");
  +                } 
  +                else {
  +                    appendContentSpecNode(contentSpecIndex, sb, false);
                   }
  -                //
  -                // ENTITY - check that the value is an unparsed entity name (V_TAGa)
  -                //
  -                if (!fEntityHandler.isUnparsedEntity(attValueHandle)) {
  -                    reportRecoverableXMLError(XMLMessages.MSG_ENTITY_INVALID,
  -                                              XMLMessages.VC_ENTITY_NAME,
  -                                              fStringPool.toString(attrName), newAttValue);
  +                break;
  +            }
  +            case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE: {
  +                chunk = value >> CHUNK_SHIFT;
  +                index = value & CHUNK_MASK;
  +                if (fNodeType[chunk][index] == XMLContentSpec.CONTENTSPECNODE_LEAF) {
  +                    value = fNodeValue[chunk][index];
  +                    sb.append("(" + (value == -1 ? "#PCDATA" : fStringPool.toString(value)) + ")*");
  +                } 
  +                else {
  +                    appendContentSpecNode(contentSpecIndex, sb, false);
                   }
  -            } else if (newAttValue != attValue) {
  -                // REVISIT - can we release the old string?
  -                attValueHandle = fStringPool.addSymbol(newAttValue);
  +                break;
               }
  -            return attValueHandle;
  -        }
  -        //
  -        //
  -        //
  -        boolean invalidStandaloneAttDef(int elementType, int attrName) {
  -            if (fStandaloneReader == -1)
  -                return false;
  -            if (elementType == -1) // we are normalizing a default att value...  this ok?
  -                return false;
  -            return getAttDefIsExternal(elementType, attrName);
  +            case XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE: {
  +                chunk = value >> CHUNK_SHIFT;
  +                index = value & CHUNK_MASK;
  +                if (fNodeType[chunk][index] == XMLContentSpec.CONTENTSPECNODE_LEAF) {
  +                    value = fNodeValue[chunk][index];
  +                    sb.append("(" + (value == -1 ? "#PCDATA" : fStringPool.toString(value)) + ")+");
  +                } 
  +                else {
  +                    appendContentSpecNode(contentSpecIndex, sb, false);
  +                }
  +                break;
  +            }
  +            case XMLContentSpec.CONTENTSPECNODE_CHOICE:
  +            case XMLContentSpec.CONTENTSPECNODE_SEQ: {
  +                appendContentSpecNode(contentSpecIndex, sb, false);
  +                break;
  +            }
  +            default: {
  +                return null;
  +            }
           }
  -    }
  -
  +        return sb.toString();
   
  -	//
  -	// AttValidatorENTITIES
  -	//
  +    } // contentSpecNodeAsString(int):String
  +    */
  +        /** addAttDef. */
  +   /* public int addAttDef(QName elementDecl, QName attributeDecl, 
  +                         int attType, int enumeration, 
  +                         int attDefaultType, int attDefaultValue, 
  +                         boolean isExternal) throws Exception {
  +
  +                //****DEBUG****
  +                if (DEBUG) print("(POP) XMLValidator.addAttDef\n");
  +                //****DEBUG****
   
  -    final class AttValidatorENTITIES implements AttributeValidator {
  -        public int normalize(int elementType, int attrName, int attValueHandle, int attType, int enumHandle) throws Exception {
  -            //
  -            // Normalize attribute based upon attribute type...
  -            //
  -            String attValue = fStringPool.toString(attValueHandle);
  -            StringTokenizer tokenizer = new StringTokenizer(attValue);
  -            StringBuffer sb = new StringBuffer(attValue.length());
  -            boolean ok = true;
  -            if (tokenizer.hasMoreTokens()) {
  -                while (true) {
  -                    String entityName = tokenizer.nextToken();
  -                    //
  -                    // ENTITIES - check that each value is an unparsed entity name (V_TAGa)
  -                    //
  -                    if (fValidating && !fEntityHandler.isUnparsedEntity(fStringPool.addSymbol(entityName))) {
  -                        ok = false;
  -                    }
  -                    sb.append(entityName);
  -                    if (!tokenizer.hasMoreTokens())
  -                        break;
  -                    sb.append(' ');
  +        //
  +        // check fields
  +        //
  +        // REVISIT: Validation. This needs to be tuple.
  +        int elementIndex = getDeclaration(elementDecl);
  +        int elemChunk = elementIndex >> CHUNK_SHIFT;
  +        int elemIndex = elementIndex & CHUNK_MASK;
  +        int attlistIndex = fAttlistHead[elemChunk][elemIndex];
  +        int dupID = -1;
  +        int dupNotation = -1;
  +        while (attlistIndex != -1) {
  +            int attrChunk = attlistIndex >> CHUNK_SHIFT;
  +            int attrIndex = attlistIndex & CHUNK_MASK;
  +            // REVISIT: Validation. Attributes are also tuples.
  +            if (fStringPool.equalNames(fAttName[attrChunk][attrIndex], attributeDecl.rawname)) {
  +                if (fWarningOnDuplicateAttDef) {
  +                    Object[] args = { fStringPool.toString(fElementType[elemChunk][elemIndex]),
  +                                      fStringPool.toString(attributeDecl.rawname) };
  +                    fErrorReporter.reportError(fErrorReporter.getLocator(),
  +                                               XMLMessages.XML_DOMAIN,
  +                                               XMLMessages.MSG_DUPLICATE_ATTDEF,
  +                                               XMLMessages.P53_DUPLICATE,
  +                                               args,
  +                                               XMLErrorReporter.ERRORTYPE_WARNING);
                   }
  -            }
  -            String newAttValue = sb.toString();
  -            if (fValidating && (!ok || newAttValue.length() == 0)) {
  -                reportRecoverableXMLError(XMLMessages.MSG_ENTITIES_INVALID,
  -                                          XMLMessages.VC_ENTITY_NAME,
  -                                          fStringPool.toString(attrName), newAttValue);
  +                return -1;
               }
  -            if (!newAttValue.equals(attValue)) {
  -                attValueHandle = fStringPool.addString(newAttValue);
  -                if (fValidating && invalidStandaloneAttDef(elementType, attrName)) {
  -                    reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
  -                                              XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
  -                                              fStringPool.toString(attrName), attValue, newAttValue);
  +            if (fValidating) {
  +                if (attType == fIDSymbol && fAttType[attrChunk][attrIndex] == fIDSymbol) {
  +                    dupID = fAttName[attrChunk][attrIndex];
  +                }
  +                if (attType == fNOTATIONSymbol && fAttType[attrChunk][attrIndex] == fNOTATIONSymbol) {
  +                    dupNotation = fAttName[attrChunk][attrIndex];
                   }
               }
  -            return attValueHandle;
  +            attlistIndex = fNextAttDef[attrChunk][attrIndex];
  +        }
  +        if (fValidating) {
  +            if (dupID != -1) {
  +                Object[] args = { fStringPool.toString(fElementType[elemChunk][elemIndex]),
  +                                  fStringPool.toString(dupID),
  +                                  fStringPool.toString(attributeDecl.rawname) };
  +                fErrorReporter.reportError(fErrorReporter.getLocator(),
  +                                           XMLMessages.XML_DOMAIN,
  +                                           XMLMessages.MSG_MORE_THAN_ONE_ID_ATTRIBUTE,
  +                                           XMLMessages.VC_ONE_ID_PER_ELEMENT_TYPE,
  +                                           args,
  +                                           XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
  +                return -1;
  +            }
  +            if (dupNotation != -1) {
  +                Object[] args = { fStringPool.toString(fElementType[elemChunk][elemIndex]),
  +                                  fStringPool.toString(dupNotation),
  +                                  fStringPool.toString(attributeDecl.rawname) };
  +                fErrorReporter.reportError(fErrorReporter.getLocator(),
  +                                           XMLMessages.XML_DOMAIN,
  +                                           XMLMessages.MSG_MORE_THAN_ONE_NOTATION_ATTRIBUTE,
  +                                           XMLMessages.VC_ONE_NOTATION_PER_ELEMENT_TYPE,
  +                                           args,
  +                                           XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
  +                return -1;
  +            }
           }
           //
  +        // save the fields
  +        //
  +        int chunk = fAttDefCount >> CHUNK_SHIFT;
  +        int index = fAttDefCount & CHUNK_MASK;
  +        ensureAttrCapacity(chunk);
  +        fAttName[chunk][index] = attributeDecl.rawname;
  +        fAttType[chunk][index] = attType;
  +        fAttValidator[chunk][index] = getValidatorForAttType(attType);
  +        fEnumeration[chunk][index] = enumeration;
  +        fAttDefaultType[chunk][index] = attDefaultType;
  +        fAttDefIsExternal[chunk][index] = (byte)(isExternal ? 1 : 0);
  +        fAttValue[chunk][index] = attDefaultValue;
           //
  +        // add to the attr list for this element
           //
  -        boolean invalidStandaloneAttDef(int elementType, int attrName) {
  -            if (fStandaloneReader == -1)
  -                return false;
  -            if (elementType == -1) // we are normalizing a default att value...  this ok?
  -                return false;
  -            return getAttDefIsExternal(elementType, attrName);
  +        int nextIndex = -1;
  +        if (attDefaultValue != -1) {
  +            nextIndex = fAttlistHead[elemChunk][elemIndex];
  +            fAttlistHead[elemChunk][elemIndex] = fAttDefCount;
  +            if (nextIndex == -1) {
  +                fAttlistTail[elemChunk][elemIndex] = fAttDefCount;
  +            }
  +        } else {
  +            nextIndex = fAttlistTail[elemChunk][elemIndex];
  +            fAttlistTail[elemChunk][elemIndex] = fAttDefCount;
  +            if (nextIndex == -1) {
  +                fAttlistHead[elemChunk][elemIndex] = fAttDefCount;
  +            }
  +            else {
  +                fNextAttDef[nextIndex >> CHUNK_SHIFT][nextIndex & CHUNK_MASK] = fAttDefCount;
  +                nextIndex = -1;
  +            }
           }
  -    }
  +        fNextAttDef[chunk][index] = nextIndex;
  +        return fAttDefCount++;
   
  +    } // addAttDef(QName,QName,int,int,int,int,boolean):int
  +    */
   
  -	//
  -	// AttValidatorNMTOKEN
  -	//
  +    /** Copy attributes. */
  +    /*public void copyAtts(QName fromElement, QName toElement) {
   
  -    final class AttValidatorNMTOKEN implements AttributeValidator {
  -        public int normalize(int elementType, int attrName, int attValueHandle, int attType, int enumHandle) throws Exception {
  -            //
  -            // Normalize attribute based upon attribute type...
  -            //
  -            String attValue = fStringPool.toString(attValueHandle);
  -            String newAttValue = attValue.trim();
  -            if (fValidating) {
  -                // REVISIT - can we release the old string?
  -                if (newAttValue != attValue) {
  -                    if (invalidStandaloneAttDef(elementType, attrName)) {
  -                        reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
  -                                                  XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
  -                                                  fStringPool.toString(attrName), attValue, newAttValue);
  -                    }
  -                    attValueHandle = fStringPool.addSymbol(newAttValue);
  -                } else {
  -                    attValueHandle = fStringPool.addSymbol(attValueHandle);
  -                }
  -                if (!XMLCharacterProperties.validNmtoken(newAttValue)) {
  -                    reportRecoverableXMLError(XMLMessages.MSG_NMTOKEN_INVALID,
  -                                              XMLMessages.VC_NAME_TOKEN,
  -                                              fStringPool.toString(attrName), newAttValue);
  -                }
  -            } else if (newAttValue != attValue) {
  -                // REVISIT - can we release the old string?
  -                attValueHandle = fStringPool.addSymbol(newAttValue);
  -            }
  -            return attValueHandle;
  +                //****DEBUG****
  +                if (DEBUG) print("(POP) XMLValidator.copyAtts: " + param("fromElementType",fromElement.rawname) + param("toElementType",toElement.rawname) + "\n");
  +                //****DEBUG****
  +
  +        // REVISIT: Validation.
  +        int fromElementIndex = getDeclaration(fromElement);
  +        int toElementIndex = getDeclaration(toElement);
  +        if (fromElementIndex == -1) {
  +            return;
           }
  -        //
  -        //
  -        //
  -        boolean invalidStandaloneAttDef(int elementType, int attrName) {
  -            if (fStandaloneReader == -1)
  -                return false;
  -            if (elementType == -1) // we are normalizing a default att value...  this ok?
  -                return false;
  -            return getAttDefIsExternal(elementType, attrName);
  +        int chunk = fromElementIndex >> CHUNK_SHIFT;
  +        int index = fromElementIndex & CHUNK_MASK;
  +        int attDefIndex = fAttlistHead[chunk][index];
  +        while (attDefIndex != -1) {
  +            chunk = attDefIndex >> CHUNK_SHIFT;
  +            index = attDefIndex & CHUNK_MASK;
  +            try {
  +                // REVISIT: Validation. Needs to be tuples.
  +                int attName = fAttName[chunk][index];
  +                fTempQName.setValues(-1, attName, attName, -1);
  +                addAttDef(toElement, fTempQName, 
  +                          fAttType[chunk][index],
  +                          fEnumeration[chunk][index], 
  +                          fAttDefaultType[chunk][index], 
  +                          fAttValue[chunk][index], 
  +                          fAttDefIsExternal[chunk][index] != 0);
  +            } catch (Exception ex) {
  +                // REVISIT: What should happen here?
  +            }
  +            attDefIndex = fNextAttDef[chunk][index];
           }
  -    }
   
  +    } // copyAtts(QName,QName)
   
  -	//
  -	// AttValidatorNMTOKENS
  -	//
  +    // a hack for traverseElementDecl in Traverse Schema
  +    public void copyAttsForSchema(int fromAttDefIndex, QName toElement) {
   
  -    final class AttValidatorNMTOKENS implements AttributeValidator {
  -        public int normalize(int elementType, int attrName, int attValueHandle, int attType, int enumHandle) throws Exception {
  -            //
  -            // Normalize attribute based upon attribute type...
  -            //
  -            String attValue = fStringPool.toString(attValueHandle);
  -            StringTokenizer tokenizer = new StringTokenizer(attValue);
  -            StringBuffer sb = new StringBuffer(attValue.length());
  -            boolean ok = true;
  -            if (tokenizer.hasMoreTokens()) {
  -                while (true) {
  -                    String nmtoken = tokenizer.nextToken();
  -                    if (fValidating && !XMLCharacterProperties.validNmtoken(nmtoken)) {
  -                        ok = false;
  -                    }
  -                    sb.append(nmtoken);
  -                    if (!tokenizer.hasMoreTokens())
  -                        break;
  -                    sb.append(' ');
  -                }
  -            }
  -            String newAttValue = sb.toString();
  -            if (fValidating && (!ok || newAttValue.length() == 0)) {
  -                reportRecoverableXMLError(XMLMessages.MSG_NMTOKENS_INVALID,
  -                                          XMLMessages.VC_NAME_TOKEN,
  -                                          fStringPool.toString(attrName), newAttValue);
  -            }
  -            if (!newAttValue.equals(attValue)) {
  -                attValueHandle = fStringPool.addString(newAttValue);
  -                if (fValidating && invalidStandaloneAttDef(elementType, attrName)) {
  -                    reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
  -                                              XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
  -                                              fStringPool.toString(attrName), attValue, newAttValue);
  -                }
  -            }
  -            return attValueHandle;
  -        }
  -        //
  -        //
  -        //
  -        boolean invalidStandaloneAttDef(int elementType, int attrName) {
  -            if (fStandaloneReader == -1)
  -                return false;
  -            if (elementType == -1) // we are normalizing a default att value...  this ok?
  -                return false;
  -            return getAttDefIsExternal(elementType, attrName);
  +                //****DEBUG****
  +                //if (DEBUG) print("(POP) XMLValidator.copyAtts: " + param("fromElementType",fromElement.rawname) + param("toElementType",toElement.rawname) + "\n");
  +                //****DEBUG****
  +
  +        // REVISIT: Validation.
  +        int toElementIndex = getDeclaration(toElement);
  +        if (fromAttDefIndex == -1) {
  +            return;
           }
  -    }
   
  +        int chunk;
  +        int index;
   
  -	//
  -	// AttValidatorNOTATION
  -	//
  -
  -    final class AttValidatorNOTATION implements AttributeValidator {
  -        public int normalize(int elementType, int attrName, int attValueHandle, int attType, int enumHandle) throws Exception {
  -            //
  -            // Normalize attribute based upon attribute type...
  -            //
  -            String attValue = fStringPool.toString(attValueHandle);
  -            String newAttValue = attValue.trim();
  -            if (fValidating) {
  -                // REVISIT - can we release the old string?
  -                if (newAttValue != attValue) {
  -                    if (invalidStandaloneAttDef(elementType, attrName)) {
  -                        reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
  -                                                  XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
  -                                                  fStringPool.toString(attrName), attValue, newAttValue);
  -                    }
  -                    attValueHandle = fStringPool.addSymbol(newAttValue);
  -                } else {
  -                    attValueHandle = fStringPool.addSymbol(attValueHandle);
  -                }
  -                //
  -                // NOTATION - check that the value is in the AttDef enumeration (V_TAGo)
  -                //
  -                if (!fStringPool.stringInList(enumHandle, attValueHandle)) {
  -                    reportRecoverableXMLError(XMLMessages.MSG_ATTRIBUTE_VALUE_NOT_IN_LIST,
  -                                              XMLMessages.VC_NOTATION_ATTRIBUTES,
  -                                              fStringPool.toString(attrName),
  -                                              newAttValue, fStringPool.stringListAsString(enumHandle));
  -                }
  -            } else if (newAttValue != attValue) {
  -                // REVISIT - can we release the old string?
  -                attValueHandle = fStringPool.addSymbol(newAttValue);
  +        int attDefIndex = fromAttDefIndex;
  +        while (attDefIndex != -1) {
  +            chunk = attDefIndex >> CHUNK_SHIFT;
  +            index = attDefIndex & CHUNK_MASK;
  +            try {
  +                // REVISIT: Validation. Needs to be tuples.
  +                int attName = fAttName[chunk][index];
  +                fTempQName.setValues(-1, attName, attName, -1);
  +                addAttDef(toElement, fTempQName, 
  +                          fAttType[chunk][index],
  +                          fEnumeration[chunk][index], 
  +                          fAttDefaultType[chunk][index], 
  +                          fAttValue[chunk][index], 
  +                          fAttDefIsExternal[chunk][index] != 0);
  +            } catch (Exception ex) {
  +                // REVISIT: What should happen here?
               }
  -            return attValueHandle;
  -        }
  -        //
  -        //
  -        //
  -        boolean invalidStandaloneAttDef(int elementType, int attrName) {
  -            if (fStandaloneReader == -1)
  -                return false;
  -            if (elementType == -1) // we are normalizing a default att value...  this ok?
  -                return false;
  -            return getAttDefIsExternal(elementType, attrName);
  +            attDefIndex = fNextAttDef[chunk][index];
           }
  -    }
   
  +    } // copyAtts(QName,QName)
  +    */
   
  -	//
  -	// AttValidatorENUMERATION
  -	//
  +    //
  +    // Protected methods
  +    //
   
  -    final class AttValidatorENUMERATION implements AttributeValidator {
  -        public int normalize(int elementType, int attrName, int attValueHandle, int attType, int enumHandle) throws Exception {
  -            //
  -            // Normalize attribute based upon attribute type...
  -            //
  -            String attValue = fStringPool.toString(attValueHandle);
  -            String newAttValue = attValue.trim();
  -            if (fValidating) {
  -                // REVISIT - can we release the old string?
  -                if (newAttValue != attValue) {
  -                    if (invalidStandaloneAttDef(elementType, attrName)) {
  -                        reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
  -                                                  XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
  -                                                  fStringPool.toString(attrName), attValue, newAttValue);
  -                    }
  -                    attValueHandle = fStringPool.addSymbol(newAttValue);
  -                } else {
  -                    attValueHandle = fStringPool.addSymbol(attValueHandle);
  -                }
  -                //
  -                // ENUMERATION - check that value is in the AttDef enumeration (V_TAG9)
  -                //
  -                if (!fStringPool.stringInList(enumHandle, attValueHandle)) {
  -                    reportRecoverableXMLError(XMLMessages.MSG_ATTRIBUTE_VALUE_NOT_IN_LIST,
  -                                              XMLMessages.VC_ENUMERATION,
  -                                              fStringPool.toString(attrName),
  -                                              newAttValue, fStringPool.stringListAsString(enumHandle));
  -                }
  -            } else if (newAttValue != attValue) {
  -                // REVISIT - can we release the old string?
  -                attValueHandle = fStringPool.addSymbol(newAttValue);
  -            }
  -            return attValueHandle;
  -        }
  -        //
  -        //
  -        //
  -        boolean invalidStandaloneAttDef(int elementType, int attrName) {
  -            if (fStandaloneReader == -1)
  -                return false;
  -            if (elementType == -1) // we are normalizing a default att value...  this ok?
  -                return false;
  -            return getAttDefIsExternal(elementType, attrName);
  -        }
  -    }
  +    // error reporting
  +    
  +    /** Report a recoverable xml error. */
  +    protected void reportRecoverableXMLError(int majorCode, int minorCode) 
  +        throws Exception {
   
  -	//====================================================
  -	// End AttributeValidator Interface and Implementations
  -	//====================================================
  +        fErrorReporter.reportError(fErrorReporter.getLocator(),
  +                                   XMLMessages.XML_DOMAIN,
  +                                   majorCode,
  +                                   minorCode,
  +                                   null,
  +                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
   
  +    } // reportRecoverableXMLError(int,int)
   
  -    public void setRootElementType(int rootElementType) {
  -        fRootElementType = rootElementType;
  -    }
  +    /** Report a recoverable xml error. */
  +    protected void reportRecoverableXMLError(int majorCode, int minorCode, 
  +                                             int stringIndex1) 
  +        throws Exception {
   
  -    private void rootElementSpecified(int rootElementType) throws Exception {
  -        if (fDynamicValidation && !fSeenDoctypeDecl) {
  -            fValidating = false;
  -        }
  -        if (fValidating) {
  -            if (fRootElementType != -1) {
  -                String root1 = fStringPool.toString(fRootElementType);
  -                String root2 = fStringPool.toString(rootElementType);
  -                if (!root1.equals(root2)) {
  -                    reportRecoverableXMLError(XMLMessages.MSG_ROOT_ELEMENT_TYPE,
  -                                                XMLMessages.VC_ROOT_ELEMENT_TYPE,
  -                                                fRootElementType, rootElementType);
  -                }
  -            }
  -        }
  -        if (fNamespacesEnabled) {
  -            if (fNamespacesScope == null) {
  -                fNamespacesScope = new NamespacesScope(this);
  -                fNamespacesPrefix = fStringPool.addSymbol("xmlns");
  -                fNamespacesScope.setNamespaceForPrefix(fNamespacesPrefix, -1);
  -                int xmlSymbol = fStringPool.addSymbol("xml");
  -                int xmlNamespace = fStringPool.addSymbol("http://www.w3.org/XML/1998/namespace");
  -                fNamespacesScope.setNamespaceForPrefix(xmlSymbol, xmlNamespace);
  -            }
  -        }
  -    }
  +        Object[] args = { fStringPool.toString(stringIndex1) };
  +        fErrorReporter.reportError(fErrorReporter.getLocator(),
  +                                   XMLMessages.XML_DOMAIN,
  +                                   majorCode,
  +                                   minorCode,
  +                                   args,
  +                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
   
  +    } // reportRecoverableXMLError(int,int,int)
   
  -	//
  -	// validateElementAndAttributes
  -	//
  +    /** Report a recoverable xml error. */
  +    protected void reportRecoverableXMLError(int majorCode, int minorCode, 
  +                                             String string1) throws Exception {
   
  -    private void validateElementAndAttributes(int elementType, XMLAttrList attrList) throws Exception {
  +        Object[] args = { string1 };
  +        fErrorReporter.reportError(fErrorReporter.getLocator(),
  +                                   XMLMessages.XML_DOMAIN,
  +                                   majorCode,
  +                                   minorCode,
  +                                   args,
  +                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
   
  -		//****DEBUG****
  -		if (DEBUG) print("(VAL) XMLValidator.validateElementAndAttributes: " + param("elementType",elementType) + " !!!!\n");
  -		//****DEBUG****
  +    } // reportRecoverableXMLError(int,int,String)
   
  -        if (fElementDeclCount == 0 && fAttDefCount == 0 && !fValidating && !fNamespacesEnabled) {
  -            fCurrentElementIndex = -1;
  -            fCurrentContentSpecType = -1;
  -            fInElementContent = false;
  -            if (fAttrListHandle != -1) {
  -                fAttrList.endAttrList();
  -                int index = fAttrList.getFirstAttr(fAttrListHandle);
  -                while (index != -1) {
  -                    if (fStringPool.equalNames(fAttrList.getAttrName(index), fXMLLang)) {
  -                        fDocumentScanner.checkXMLLangAttributeValue(fAttrList.getAttValue(index));
  -                        break;
  -                    }
  -                    index = fAttrList.getNextAttr(index);
  -                }
  -            }
  -            return;
  -        }
  -        int elementIndex = fStringPool.getDeclaration(elementType);
  -        int contentSpecType = (elementIndex == -1) ? -1 : getContentSpecType(elementIndex);
  -        if (contentSpecType == -1 && fValidating) {
  -            reportRecoverableXMLError(XMLMessages.MSG_ELEMENT_NOT_DECLARED,
  -                                      XMLMessages.VC_ELEMENT_VALID,
  -                                      elementType);
  -        }
  -        if (fAttDefCount != 0 && elementIndex != -1) {
  -            fAttrListHandle = addDefaultAttributes(elementIndex, attrList, fAttrListHandle, fValidating, fStandaloneReader != -1);
  -        }
  -        if (fAttrListHandle != -1) {
  -            fAttrList.endAttrList();
  -        }
  +    /** Report a recoverable xml error. */
  +    protected void reportRecoverableXMLError(int majorCode, int minorCode, 
  +                                             int stringIndex1, int stringIndex2) 
  +        throws Exception {
   
  -        if (DEBUG_PRINT_ATTRIBUTES) {
  -            String element = fStringPool.toString(elementType);
  -            System.out.print("startElement: <" + element);
  -            if (fAttrListHandle != -1) {
  -                int index = attrList.getFirstAttr(fAttrListHandle);
  -                while (index != -1) {
  -                    System.out.print(" " + fStringPool.toString(attrList.getAttrName(index)) + "=\"" +
  -                            fStringPool.toString(attrList.getAttValue(index)) + "\"");
  -                    index = attrList.getNextAttr(index);
  -                }
  -            }
  -            System.out.println(">");
  -        }
  -        //
  -        // Namespace support
  -        //
  -        if (fNamespacesEnabled) {
  -            fNamespacesScope.increaseDepth();
  -            if (fAttrListHandle != -1) {
  -                int index = attrList.getFirstAttr(fAttrListHandle);
  -                while (index != -1) {
  -                    int attName = attrList.getAttrName(index);
  -                    if (fStringPool.equalNames(attName, fXMLLang)) {
  -                        fDocumentScanner.checkXMLLangAttributeValue(attrList.getAttValue(index));
  -                    } else if (fStringPool.equalNames(attName, fNamespacesPrefix)) {
  -                        int uri = fStringPool.addSymbol(attrList.getAttValue(index));
  -                        fNamespacesScope.setNamespaceForPrefix(StringPool.EMPTY_STRING, uri);
  -                    } else {
  -                        int attPrefix = fStringPool.getPrefixForQName(attName);
  -                        if (attPrefix == fNamespacesPrefix) {
  -                            attPrefix = fStringPool.getLocalPartForQName(attName);
  -                            int uri = fStringPool.addSymbol(attrList.getAttValue(index));
  -                            fNamespacesScope.setNamespaceForPrefix(attPrefix, uri);
  -                        }
  -                    }
  -                    index = attrList.getNextAttr(index);
  -                }
  -            }
  -            int prefix = fStringPool.getPrefixForQName(elementType);
  -            int elementURI;
  -            if (prefix == -1) {
  -                elementURI = fNamespacesScope.getNamespaceForPrefix(StringPool.EMPTY_STRING);
  -                if (elementURI != -1) {
  -                    fStringPool.setURIForQName(elementType, elementURI);
  -                }
  -            } else {
  -                elementURI = fNamespacesScope.getNamespaceForPrefix(prefix);
  -                if (elementURI == -1) {
  -                    Object[] args = { fStringPool.toString(prefix) };
  -                    fErrorReporter.reportError(fErrorReporter.getLocator(),
  -                                               XMLMessages.XMLNS_DOMAIN,
  -                                               XMLMessages.MSG_PREFIX_DECLARED,
  -                                               XMLMessages.NC_PREFIX_DECLARED,
  -                                               args,
  -                                               XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
  -                }
  -                fStringPool.setURIForQName(elementType, elementURI);
  -            }
  -            if (fAttrListHandle != -1) {
  -                int index = attrList.getFirstAttr(fAttrListHandle);
  -                while (index != -1) {
  -                    int attName = attrList.getAttrName(index);
  -                    if (!fStringPool.equalNames(attName, fNamespacesPrefix)) {
  -                        int attPrefix = fStringPool.getPrefixForQName(attName);
  -                        if (attPrefix != fNamespacesPrefix) {
  -                            if (attPrefix != -1) {
  -                                int uri = fNamespacesScope.getNamespaceForPrefix(attPrefix);
  -                                if (uri == -1) {
  -                                    Object[] args = { fStringPool.toString(attPrefix) };
  -                                    fErrorReporter.reportError(fErrorReporter.getLocator(),
  -                                                               XMLMessages.XMLNS_DOMAIN,
  -                                                               XMLMessages.MSG_PREFIX_DECLARED,
  -                                                               XMLMessages.NC_PREFIX_DECLARED,
  -                                                               args,
  -                                                               XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
  -                                }
  -                                fStringPool.setURIForQName(attName, uri);
  -                            }
  -                        }
  -                    }
  -                    index = attrList.getNextAttr(index);
  -                }
  -            }
  -        } else if (fAttrListHandle != -1) {
  -            int index = fAttrList.getFirstAttr(fAttrListHandle);
  -            while (index != -1) {
  -                if (fStringPool.equalNames(attrList.getAttrName(index), fXMLLang)) {
  -                    fDocumentScanner.checkXMLLangAttributeValue(attrList.getAttValue(index));
  -                    break;
  -                }
  -                index = fAttrList.getNextAttr(index);
  -            }
  -        }
  -        fCurrentElementIndex = elementIndex;
  -        fCurrentContentSpecType = contentSpecType;
  -        if (fValidating && contentSpecType == fDATATYPESymbol) {
  -            fBufferDatatype = true;
  -            fDatatypeBuffer.setLength(0);
  -        }
  -        fInElementContent = (contentSpecType == fCHILDRENSymbol);
  -    }
  +        Object[] args = { fStringPool.toString(stringIndex1), fStringPool.toString(stringIndex2) };
  +        fErrorReporter.reportError(fErrorReporter.getLocator(),
  +                                   XMLMessages.XML_DOMAIN,
  +                                   majorCode,
  +                                   minorCode,
  +                                   args,
  +                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
   
  +    } // reportRecoverableXMLError(int,int,int,int)
   
  -    //
  -    // charDataInContent
  -    //
  +    /** Report a recoverable xml error. */
  +    protected void reportRecoverableXMLError(int majorCode, int minorCode, 
  +                                             String string1, String string2) 
  +        throws Exception {
   
  -    private void charDataInContent () {
  +        Object[] args = { string1, string2 };
  +        fErrorReporter.reportError(fErrorReporter.getLocator(),
  +                                   XMLMessages.XML_DOMAIN,
  +                                   majorCode,
  +                                   minorCode,
  +                                   args,
  +                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
   
  -		//****DEBUG****
  -		if (DEBUG) print("(???) XMLValidator.charDataInContent\n");
  -		//****DEBUG****
  +    } // reportRecoverableXMLError(int,int,String,String)
   
  -        int[] children = fElementChildren[fElementDepth];
  -        int childCount = fElementChildCount[fElementDepth];
  -        try {
  -            children[childCount] = -1;
  -        } catch (NullPointerException ex) {
  -            children = fElementChildren[fElementDepth] = new int[256];
  -            childCount = 0; // should really assert this...
  -            children[childCount] = -1;
  -        } catch (ArrayIndexOutOfBoundsException ex) {
  -            int[] newChildren = new int[childCount * 2];
  -            System.arraycopy(children, 0, newChildren, 0, childCount);
  -            children = fElementChildren[fElementDepth] = newChildren;
  -            children[childCount] = -1;
  -        }
  -        fElementChildCount[fElementDepth] = ++childCount;
  -    }
  -
  -
  -	//
  -	// peekChildCount
  -	//
  -
  -    private int peekChildCount() {
  +    /** Report a recoverable xml error. */
  +    protected void reportRecoverableXMLError(int majorCode, int minorCode, 
  +                                             String string1, String string2, 
  +                                             String string3) throws Exception {
   
  -		//****DEBUG****
  -		if (DEBUG) print("(???) XMLValidator.peekChildCount\n");
  -		//****DEBUG****
  -
  -        return fElementChildCount[fElementDepth];
  -    }
  -
  -
  -	//
  -	// peekChildren
  -	//
  -
  -    private int[] peekChildren() {
  -
  -		//****DEBUG****
  -		if (DEBUG) print("(???) XMLValidator.peekChildren\n");
  -		//****DEBUG****
  -
  -        return fElementChildren[fElementDepth];
  -    }
  +        Object[] args = { string1, string2, string3 };
  +        fErrorReporter.reportError(fErrorReporter.getLocator(),
  +                                   XMLMessages.XML_DOMAIN,
  +                                   majorCode,
  +                                   minorCode,
  +                                   args,
  +                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
   
  -    /**
  -     * Check that the content of an element is valid.
  -     * <p>
  -     * This is the method of primary concern to the validator. This method is called
  -     * upon the scanner reaching the end tag of an element. At that time, the
  -     * element's children must be structurally validated, so it calls this method.
  -     * The index of the element being checked (in the decl pool), is provided as
  -     * well as an array of element name indexes of the children. The validator must
  -     * confirm that this element can have these children in this order.
  -     * <p>
  -     * This can also be called to do 'what if' testing of content models just to see
  -     * if they would be valid.
  -     * <p>
  -     * Note that the element index is an index into the element decl pool, whereas
  -     * the children indexes are name indexes, i.e. into the string pool.
  -     * <p>
  -     * A value of -1 in the children array indicates a PCDATA node. All other
  -     * indexes will be positive and represent child elements. The count can be
  -     * zero, since some elements have the EMPTY content model and that must be
  -     * confirmed.
  -     *
  -     * @param elementIndex The index within the <code>ElementDeclPool</code> of this
  -     *                     element.
  -     * @param childCount The number of entries in the <code>children</code> array.
  -     * @param children The children of this element.  Each integer is an index within
  -     *                 the <code>StringPool</code> of the child element name.  An index
  -     *                 of -1 is used to indicate an occurrence of non-whitespace character
  -     *                 data.
  -     *
  -     * @return The value -1 if fully valid, else the 0 based index of the child
  -     *         that first failed. If the value returned is equal to the number
  -     *         of children, then additional content is required to reach a valid
  -     *         ending state.
  -     *
  -     * @exception Exception Thrown on error.
  -     */
  +    } // reportRecoverableXMLError(int,int,String,String,String)
   
  -    private int checkContent(int elementIndex, int childCount, int[] children) throws Exception
  -    {
  -		//****DEBUG****
  -		if (DEBUG) print("(VAL) XMLValidator.checkContent: " + param("elementIndex",elementIndex) + "... \n");
  -		//****DEBUG****
  +    // content spec
   
  -        // Get the element name index from the element
  -        final int elementType = fCurrentElementType;
  +    /** Protected for access by ContentSpecImpl. */
  +    /*protected void getContentSpecNode(int contentSpecIndex, 
  +                                      XMLContentSpec csn) {
   
  -        if (DEBUG_PRINT_CONTENT)
  -        {
  -            String strTmp = fStringPool.toString(elementType);
  -            System.out.println
  -            (
  -                "Name: "
  -                + strTmp
  -                + ", Count: "
  -                + childCount
  -                + ", ContentSpec: "
  -                + getContentSpecAsString(elementIndex)
  -            );
  -            for (int index = 0; index < childCount && index < 10; index++) {
  -                if (index == 0) System.out.print("  (");
  -                String childName = (children[index] == -1) ? "#PCDATA" : fStringPool.toString(children[index]);
  -                if (index + 1 == childCount)
  -                    System.out.println(childName + ")");
  -                else if (index + 1 == 10)
  -                    System.out.println(childName + ",...)");
  -                else
  -                    System.out.print(childName + ",");
  +        int chunk = contentSpecIndex >> CHUNK_SHIFT;
  +        int index = contentSpecIndex & CHUNK_MASK;
  +        csn.type = fNodeType[chunk][index];
  +        csn.value = fNodeValue[chunk][index];
  +        if (csn.type == XMLContentSpec.CONTENTSPECNODE_CHOICE || csn.type == XMLContentSpec.CONTENTSPECNODE_SEQ) {
  +            if (++index == CHUNK_SIZE) {
  +                chunk++;
  +                index = 0;
               }
  +            csn.otherValue = fNodeValue[chunk][index];
  +        } 
  +        else {
  +            csn.otherValue = -1;
           }
   
  -        // Get out the content spec for this element
  -        final int contentSpec = fCurrentContentSpecType;
  +    } // getContentSpecNode(int,XMLContentSpec)
   
  -        //
  -        //  Deal with the possible types of content. We try to optimized here
  -        //  by dealing specially with content models that don't require the
  -        //  full DFA treatment.
  -        //
  -        if (contentSpec == fEMPTYSymbol)
  -        {
  -            //
  -            //  If the child count is greater than zero, then this is
  -            //  an error right off the bat at index 0.
  -            //
  -            if (childCount != 0)
  -                return 0;
  -        }
  -         else if (contentSpec == fANYSymbol)
  -        {
  -            //
  -            //  This one is open game so we don't pass any judgement on it
  -            //  at all. Its assumed to fine since it can hold anything.
  -            //
  -        }
  -         else if (contentSpec == fMIXEDSymbol ||  contentSpec == fCHILDRENSymbol)
  -        {
  -            // Get the content model for this element, faulting it in if needed
  -            XMLContentModel cmElem = null;
  -            try
  -            {
  -                cmElem = getContentModel(elementIndex);
  -                return cmElem.validateContent(childCount, children);
  -            }
  +    /** Returns a string representation of a content spec. */
  +    /*protected String getContentSpecAsString(int elementIndex) {
   
  -            catch(CMException excToCatch)
  -            {
  -                // REVISIT - Translate the caught exception to the protected error API
  -                int majorCode = excToCatch.getErrorCode();
  -                fErrorReporter.reportError(fErrorReporter.getLocator(),
  -                                           ImplementationMessages.XERCES_IMPLEMENTATION_DOMAIN,
  -                                           majorCode,
  -                                           0,
  -                                           null,
  -                                           XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
  -            }
  -        }
  -         else if (contentSpec == -1)
  -        {
  -            reportRecoverableXMLError(XMLMessages.MSG_ELEMENT_NOT_DECLARED,
  -                                      XMLMessages.VC_ELEMENT_VALID,
  -                                      elementType);
  +        if (elementIndex < 0 || elementIndex >= fElementCount) {
  +            return null;
           }
  -         else if (contentSpec == fStringPool.addSymbol("DATATYPE"))
  -        {
  -
  -            XMLContentModel cmElem = null;
  -            try {
  -                cmElem = getContentModel(elementIndex);
  -                return cmElem.validateContent(1, new int[] { fStringPool.addString(fDatatypeBuffer.toString()) });
  -            } catch (CMException cme) {
  -                System.out.println("Internal Error in datatype validation");
  -            } catch (InvalidDatatypeValueException idve) {
  -                fErrorReporter.reportError(fErrorReporter.getLocator(),
  -                                           SchemaMessageProvider.SCHEMA_DOMAIN,
  -                                           SchemaMessageProvider.DatatypeError,
  -                                           SchemaMessageProvider.MSG_NONE,
  -                                           new Object [] { idve.getMessage() },
  -                                           XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
  -            }
  -/*
  -            boolean DEBUG_DATATYPES = false;
  -            if (DEBUG_DATATYPES) {
  -                System.out.println("Checking content of datatype");
  -                String strTmp = fStringPool.toString(elementTypeIndex);
  -                int contentSpecIndex = fElementDeclPool.getContentSpec(elementIndex);
  -                XMLContentSpec.Node csn = new XMLContentSpec.Node();
  -                fElementDeclPool.getContentSpecNode(contentSpecIndex, csn);
  -                String contentSpecString = fStringPool.toString(csn.value);
  -                System.out.println
  -                (
  -                    "Name: "
  -                    + strTmp
  -                    + ", Count: "
  -                    + childCount
  -                    + ", ContentSpec: "
  -                    + contentSpecString
  -                );
  -                for (int index = 0; index < childCount && index < 10; index++) {
  -                    if (index == 0) System.out.print("  (");
  -                    String childName = (children[index] == -1) ? "#PCDATA" : fStringPool.toString(children[index]);
  -                    if (index + 1 == childCount)
  -                        System.out.println(childName + ")");
  -                    else if (index + 1 == 10)
  -                        System.out.println(childName + ",...)");
  -                    else
  -                        System.out.print(childName + ",");
  -                }
  -            }
  -            try { // REVISIT - integrate w/ error handling
  -                int contentSpecIndex = fElementDeclPool.getContentSpec(elementIndex);
  -                XMLContentSpec.Node csn = new XMLContentSpec.Node();
  -                fElementDeclPool.getContentSpecNode(contentSpecIndex, csn);
  -                String type = fStringPool.toString(csn.value);
  -                DatatypeValidator v = fDatatypeRegistry.getValidatorFor(type);
  -                if (v != null)
  -                    v.validate(fDatatypeBuffer.toString());
  -                else
  -                    System.out.println("No validator for datatype "+type);
  -            } catch (InvalidDatatypeValueException idve) {
  -                System.out.println("Incorrect datatype: "+idve.getMessage());
  -            } catch (Exception e) {
  -                e.printStackTrace();
  -                System.out.println("Internal error in datatype validation");
  -            }
  - */
  +        int chunk = elementIndex >> CHUNK_SHIFT;
  +        int index = elementIndex & CHUNK_MASK;
  +        int contentSpecType = fContentSpecType[chunk][index];
  +        if (contentSpecType == fMIXEDSymbol || contentSpecType == fCHILDRENSymbol) {
  +            return contentSpecNodeAsString(fContentSpec[chunk][index]);
           }
  -         else
  -        {
  -            fErrorReporter.reportError(fErrorReporter.getLocator(),
  -                                       ImplementationMessages.XERCES_IMPLEMENTATION_DOMAIN,
  -                                       ImplementationMessages.VAL_CST,
  -                                       0,
  -                                       null,
  -                                       XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
  +        else {
  +            return fStringPool.toString(contentSpecType);
           }
   
  -        // We succeeded
  -        return -1;
  -    }
  +    } // getContentSpecAsString(int):String
  +    */
   
       /**
        * Returns information about which elements can be placed at a particular point
  @@ -2011,12 +1861,12 @@
        *
        * @see InsertableElementsInfo
        */
  -    protected int whatCanGoHere(int elementIndex,boolean fullyValid,InsertableElementsInfo info) throws Exception
  -    {
  +    protected int whatCanGoHere(int elementIndex, boolean fullyValid,
  +                                InsertableElementsInfo info) throws Exception {
   
  -		//****DEBUG****
  -		if (DEBUG) print("(VAL) XMLValidator.whatCanGoHere: ...\n");
  -		//****DEBUG****
  +                //****DEBUG****
  +                if (DEBUG) print("(VAL) XMLValidator.whatCanGoHere: ...\n");
  +                //****DEBUG****
   
           //
           //  Do some basic sanity checking on the info packet. First, make sure
  @@ -2032,11 +1882,8 @@
           //  array. It can be equal, which means get appendable elements, but not
           //  greater.
           //
  -        if ((info.insertAt > info.childCount)
  -        ||  (info.curChildren == null)
  -        ||  (info.childCount < 1)
  -        ||  (info.childCount > info.curChildren.length))
  -        {
  +        if (info.insertAt > info.childCount || info.curChildren == null ||  
  +            info.childCount < 1 || info.childCount > info.curChildren.length) {
               fErrorReporter.reportError(fErrorReporter.getLocator(),
                                          ImplementationMessages.XERCES_IMPLEMENTATION_DOMAIN,
                                          ImplementationMessages.VAL_WCGHI,
  @@ -2046,17 +1893,14 @@
           }
   
           int retVal = 0;
  -        try
  -        {
  +        try {
               // Get the content model for this element
               final XMLContentModel cmElem = getContentModel(elementIndex);
   
               // And delegate this call to it
               retVal = cmElem.whatCanGoHere(fullyValid, info);
           }
  -
  -        catch(CMException excToCatch)
  -        {
  +        catch (CMException excToCatch) {
               // REVISIT - Translate caught error to the protected error handler interface
               int majorCode = excToCatch.getErrorCode();
               fErrorReporter.reportError(fErrorReporter.getLocator(),
  @@ -2067,31 +1911,118 @@
                                          XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
           }
           return retVal;
  +
  +    } // whatCanGoHere(int,boolean,InsertableElementsInfo):int
  +
  +    // attribute information
  +
  +    /** Protected for use by AttributeValidator classes. */
  +    protected boolean getAttDefIsExternal(QName element, QName attribute) {
  +        int attDefIndex = getAttDef(element, attribute);
  +        if (fGrammar instanceof DTDGrammar ) {
  +            return ((DTDGrammar) fGrammar).getAttributeDeclIsExternal(attDefIndex);
  +        }
  +        return false;
       }
   
  +    /** addId. */
  +    protected boolean addId(int idIndex) {
  +
  +                //****DEBUG****
  +                if (DEBUG) print("(POP) XMLValidator.addId" + param("idIndex",idIndex) + "\n");
  +                //****DEBUG****
  +
  +                //System.err.println("addId(" + fStringPool.toString(idIndex) + ") " + idIndex);
  +        Integer key = new Integer(idIndex);
  +        if (fIdDefs == null) {
  +            fIdDefs = new Hashtable();
  +        }
  +        else if (fIdDefs.containsKey(key)) {
  +            return false;
  +        }
  +        if (fNullValue == null) {
  +            fNullValue = new Object();
  +        }
  +        fIdDefs.put(key, fNullValue/*new Integer(elementType)*/);
  +        return true;
  +
  +    } // addId(int):boolean
  +
  +    /** addIdRef. */
  +    protected void addIdRef(int idIndex) {
  +
  +                //****DEBUG****
  +                if (DEBUG) print("(POP) XMLValidator.addIdRef" + param("idIndex",idIndex) + "\n");
  +                //****DEBUG****
  +
  +                //System.err.println("addIdRef(" + fStringPool.toString(idIndex) + ") " + idIndex);
  +        Integer key = new Integer(idIndex);
  +        if (fIdDefs != null && fIdDefs.containsKey(key)) {
  +            return;
  +        }
  +        if (fIdRefs == null) {
  +            fIdRefs = new Hashtable();
  +        }
  +        else if (fIdRefs.containsKey(key)) {
  +            return;
  +        }
  +        if (fNullValue == null) {
  +            fNullValue = new Object();
  +        }
  +        fIdRefs.put(key, fNullValue/*new Integer(elementType)*/);
   
  -    // -----------------------------------------------------------------------
  -    //  Private methods
  -    // -----------------------------------------------------------------------
  +    } // addIdRef(int)
   
  +    //
  +    // Private methods
       //
  -    //  When the element has a 'CHILDREN' model, this method is called to
  -    //  create the content model object. It looks for some special case simple
  -    //  models and creates SimpleContentModel objects for those. For the rest
  -    //  it creates the standard DFA style model.
  -    //
  -    private XMLContentModel createChildModel(int elementIndex) throws CMException
  -    {
  -		//****DEBUG****
  -		if (DEBUG) print("(POP) XMLValidator.createChildModel: " + param("elementIndex",elementIndex) + "\n");
  -		//****DEBUG****
   
  +    // other
  +
  +    /** Returns true if using a standalone reader. */
  +    private boolean usingStandaloneReader() {
  +        return fStandaloneReader == -1 || fEntityHandler.getReaderId() == fStandaloneReader;
  +    }
  +
  +    /** Returns a locator implementation. */
  +    private LocatorImpl getLocatorImpl(LocatorImpl fillin) {
  +
  +                //****DEBUG****
  +                if (DEBUG) print("(INF) XMLValidator.getLocatorImpl: ...\n");
  +                //****DEBUG****
  +
  +        Locator here = fErrorReporter.getLocator();
  +        if (fillin == null)
  +            return new LocatorImpl(here);
  +        fillin.setPublicId(here.getPublicId());
  +        fillin.setSystemId(here.getSystemId());
  +        fillin.setLineNumber(here.getLineNumber());
  +        fillin.setColumnNumber(here.getColumnNumber());
  +        return fillin;
  +
  +    } // getLocatorImpl(LocatorImpl):LocatorImpl
  +
  +    // content models
  +
  +    /**
  +     * When the element has a 'CHILDREN' model, this method is called to
  +     * create the content model object. It looks for some special case simple
  +     * models and creates SimpleContentModel objects for those. For the rest
  +     * it creates the standard DFA style model.
  +     */
  +    /*private XMLContentModel createChildModel(int elementIndex) 
  +        throws CMException {
  +
  +                //****DEBUG****
  +                if (DEBUG) print("(POP) XMLValidator.createChildModel: " + param("elementIndex",elementIndex) + "\n");
  +                //****DEBUG****
  +
           //
           //  Get the content spec node for the element we are working on.
           //  This will tell us what kind of node it is, which tells us what
           //  kind of model we will try to create.
           //
  -        XMLContentSpec.Node specNode = new XMLContentSpec.Node();
  +        XMLContentSpec specNode = new XMLContentSpec();
           int contentSpecIndex = getContentSpecHandle(elementIndex);
           getContentSpecNode(contentSpecIndex, specNode);
   
  @@ -2099,11 +2030,11 @@
           //  Check that the left value is not -1, since any content model
           //  with PCDATA should be MIXED, so we should not have gotten here.
           //
  -        if (specNode.value == -1)
  +        if (specNode.value == -1) {
               throw new CMException(ImplementationMessages.VAL_NPCD);
  +        }
   
  -        if (specNode.type == XMLContentSpec.CONTENTSPECNODE_LEAF)
  -        {
  +        if (specNode.type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
               //
               //  Its a single leaf, so its an 'a' type of content model, i.e.
               //  just one instance of one element. That one is definitely a
  @@ -2111,47 +2042,40 @@
               //
               return new SimpleContentModel(specNode.value, -1, specNode.type);
           }
  -         else if ((specNode.type == XMLContentSpec.CONTENTSPECNODE_CHOICE)
  -              ||  (specNode.type == XMLContentSpec.CONTENTSPECNODE_SEQ))
  -        {
  +        else if (specNode.type == XMLContentSpec.CONTENTSPECNODE_CHOICE || 
  +                 specNode.type == XMLContentSpec.CONTENTSPECNODE_SEQ) {
               //
               //  Lets see if both of the children are leafs. If so, then it
               //  it has to be a simple content model
               //
  -            XMLContentSpec.Node specLeft = new XMLContentSpec.Node();
  -            XMLContentSpec.Node specRight = new XMLContentSpec.Node();
  +            XMLContentSpec specLeft = new XMLContentSpec();
  +            XMLContentSpec specRight = new XMLContentSpec();
               getContentSpecNode(specNode.value, specLeft);
               getContentSpecNode(specNode.otherValue, specRight);
   
  -            if ((specLeft.type == XMLContentSpec.CONTENTSPECNODE_LEAF)
  -            &&  (specRight.type == XMLContentSpec.CONTENTSPECNODE_LEAF))
  -            {
  +            if (specLeft.type == XMLContentSpec.CONTENTSPECNODE_LEAF && 
  +                specRight.type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
                   //
                   //  Its a simple choice or sequence, so we can do a simple
                   //  content model for it.
                   //
  -                return new SimpleContentModel
  -                (
  -                    specLeft.value
  -                    , specRight.value
  -                    , specNode.type
  -                );
  +                return new SimpleContentModel(specLeft.value, 
  +                                              specRight.value, 
  +                                              specNode.type);
               }
           }
  -         else if ((specNode.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE)
  -              ||  (specNode.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE)
  -              ||  (specNode.type == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE))
  -        {
  +        else if (specNode.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ||  
  +                 specNode.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE || 
  +                 specNode.type == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE) {
               //
               //  Its a repetition, so see if its one child is a leaf. If so
               //  its a repetition of a single element, so we can do a simple
               //  content model for that.
               //
  -            XMLContentSpec.Node specLeft = new XMLContentSpec.Node();
  +            XMLContentSpec specLeft = new XMLContentSpec();
               getContentSpecNode(specNode.value, specLeft);
   
  -            if (specLeft.type == XMLContentSpec.CONTENTSPECNODE_LEAF)
  -            {
  +            if (specLeft.type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
                   //
                   //  It is, so we can create a simple content model here that
                   //  will check for this repetition. We pass -1 for the unused
  @@ -2160,8 +2084,7 @@
                   return new SimpleContentModel(specLeft.value, -1, specNode.type);
               }
           }
  -         else
  -        {
  +        else {
               throw new CMException(ImplementationMessages.VAL_CST);
           }
   
  @@ -2172,50 +2095,48 @@
           //
           fLeafCount = 0;
           CMNode cmn = buildSyntaxTree(contentSpecIndex, specNode);
  -        return new DFAContentModel
  -        (
  -            fStringPool
  -            , cmn
  -            , fLeafCount
  -        );
  -    }
  +        return new DFAContentModel(fStringPool, cmn, fLeafCount);
   
  +    } // createChildModel(int):XMLContentModel
  +    */
   
  -    //
  -    //  This method will handle the querying of the content model for a
  -    //  particular element. If the element does not have a content model, then
  -    //  it will be created.
  -    //
  -    private XMLContentModel getContentModel(int elementIndex) throws CMException
  -    {
  -		//****DEBUG****
  -		if (DEBUG) print("(INF) XMLValidator.getContentModel: " + param("elementIndex",elementIndex) + "\n");
  -		//****DEBUG****
  +    /**
  +     * This method will handle the querying of the content model for a
  +     * particular element. If the element does not have a content model, then
  +     * it will be created.
  +     */
  +    private XMLContentModel getContentModel(int elementIndex) 
  +        throws CMException {
   
  +                //****DEBUG****
  +                if (DEBUG) print("(INF) XMLValidator.getContentModel: " + param("elementIndex",elementIndex) + "\n");
  +                //****DEBUG****
  +
           // See if a content model already exists first
           XMLContentModel cmRet = getElementContentModel(elementIndex);
   
           // If we have one, just return that. Otherwise, gotta create one
  -        if (cmRet != null)
  +        if (cmRet != null) {
               return cmRet;
  +        }
   
           // Get the type of content this element has
           final int contentSpec = getContentSpecType(elementIndex);
   
           // And create the content model according to the spec type
  -        if (contentSpec == fMIXEDSymbol)
  -        {
  +        if (contentSpec == fMIXEDSymbol) {
               //
               //  Just create a mixel content model object. This type of
               //  content model is optimized for mixed content validation.
               //
  -            XMLContentSpec.Node specNode = new XMLContentSpec.Node();
  -            int contentSpecIndex = getContentSpecHandle(elementIndex);
  -            makeContentList(contentSpecIndex, specNode);
  -            cmRet = new MixedContentModel(fCount, fContentList);
  +
  +            //REVISIT, could not compile
  +           // XMLContentSpec specNode = new XMLContentSpec();
  +           // int contentSpecIndex = getContentSpecHandle(elementIndex);
  +           // makeContentList(contentSpecIndex, specNode);
  +           // cmRet = new MixedContentModel(fCount, fContentList);
           }
  -         else if (contentSpec == fCHILDRENSymbol)
  -        {
  +        else if (contentSpec == fCHILDRENSymbol) {
               //
               //  This method will create an optimal model for the complexity
               //  of the element's defined model. If its simple, it will create
  @@ -2223,127 +2144,44 @@
               //  create a SimpleListContentModel object. If its complex, it
               //  will create a DFAContentModel object.
               //
  -            cmRet = createChildModel(elementIndex);
  +            //REVISIT: couldnot compile
  +            //cmRet = createChildModel(elementIndex);
           }
  -         else if (contentSpec == fDATATYPESymbol)
  -        {
  -            cmRet = fSchemaImporter.createDatatypeContentModel(elementIndex);
  +        else if (contentSpec == fDATATYPESymbol) {
  +           // cmRet = fSchemaImporter.createDatatypeContentModel(elementIndex);
           }
  -         else
  -        {
  +        else {
               throw new CMException(ImplementationMessages.VAL_CST);
           }
   
           // Add the new model to the content model for this element
  +        //REVISIT
           setContentModel(elementIndex, cmRet);
   
           return cmRet;
  -    }
  -    //
  -    //
  -    //
  -    protected void reportRecoverableXMLError(int majorCode, int minorCode) throws Exception {
  -        fErrorReporter.reportError(fErrorReporter.getLocator(),
  -                                   XMLMessages.XML_DOMAIN,
  -                                   majorCode,
  -                                   minorCode,
  -                                   null,
  -                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
  -    }
  -    protected void reportRecoverableXMLError(int majorCode, int minorCode, int stringIndex1) throws Exception {
  -        Object[] args = { fStringPool.toString(stringIndex1) };
  -        fErrorReporter.reportError(fErrorReporter.getLocator(),
  -                                   XMLMessages.XML_DOMAIN,
  -                                   majorCode,
  -                                   minorCode,
  -                                   args,
  -                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
  -    }
  -    protected void reportRecoverableXMLError(int majorCode, int minorCode, String string1) throws Exception {
  -        Object[] args = { string1 };
  -        fErrorReporter.reportError(fErrorReporter.getLocator(),
  -                                   XMLMessages.XML_DOMAIN,
  -                                   majorCode,
  -                                   minorCode,
  -                                   args,
  -                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
  -    }
  -    protected void reportRecoverableXMLError(int majorCode, int minorCode, int stringIndex1, int stringIndex2) throws Exception {
  -        Object[] args = { fStringPool.toString(stringIndex1), fStringPool.toString(stringIndex2) };
  -        fErrorReporter.reportError(fErrorReporter.getLocator(),
  -                                   XMLMessages.XML_DOMAIN,
  -                                   majorCode,
  -                                   minorCode,
  -                                   args,
  -                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
  -    }
  -    protected void reportRecoverableXMLError(int majorCode, int minorCode, String string1, String string2) throws Exception {
  -        Object[] args = { string1, string2 };
  -        fErrorReporter.reportError(fErrorReporter.getLocator(),
  -                                   XMLMessages.XML_DOMAIN,
  -                                   majorCode,
  -                                   minorCode,
  -                                   args,
  -                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
  -    }
  -    protected void reportRecoverableXMLError(int majorCode, int minorCode, String string1, String string2, String string3) throws Exception {
  -        Object[] args = { string1, string2, string3 };
  -        fErrorReporter.reportError(fErrorReporter.getLocator(),
  -                                   XMLMessages.XML_DOMAIN,
  -                                   majorCode,
  -                                   minorCode,
  -                                   args,
  -                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
  -    }
  -
  -    //
  -    //
  -    //
  -    private boolean usingStandaloneReader() {
  -        return fStandaloneReader == -1 || fEntityHandler.getReaderId() == fStandaloneReader;
  -    }
  -
  -
  -	//
  -	// getLocatorImpl
  -	//
   
  -    private LocatorImpl getLocatorImpl(LocatorImpl fillin) {
  -
  -		//****DEBUG****
  -		if (DEBUG) print("(INF) XMLValidator.getLocatorImpl: ...\n");
  -		//****DEBUG****
  -
  -        Locator here = fErrorReporter.getLocator();
  -        if (fillin == null)
  -            return new LocatorImpl(here);
  -        fillin.setPublicId(here.getPublicId());
  -        fillin.setSystemId(here.getSystemId());
  -        fillin.setLineNumber(here.getLineNumber());
  -        fillin.setColumnNumber(here.getColumnNumber());
  -        return fillin;
  -    }
  +    } // getContentModel(int):XMLContentModel
  +    
   
  -    //
  -    //  This method will build our syntax tree by recursively going though
  -    //  the element's content model and creating new CMNode type node for
  -    //  the model, and rewriting '?' and '+' nodes along the way.
  -    //
  -    //  On final return, the head node of the syntax tree will be returned.
  -    //  This top node will be a sequence node with the left side being the
  -    //  rewritten content, and the right side being a special end of content
  -    //  node.
  -    //
  -    //  We also count the non-epsilon leaf nodes, which is an important value
  -    //  that is used in a number of places later.
  -    //
  +    /**
  +     * This method will build our syntax tree by recursively going though
  +     * the element's content model and creating new CMNode type node for
  +     * the model, and rewriting '?' and '+' nodes along the way.
  +     * <p>
  +     * On final return, the head node of the syntax tree will be returned.
  +     * This top node will be a sequence node with the left side being the
  +     * rewritten content, and the right side being a special end of content
  +     * node.
  +     * <p>
  +     * We also count the non-epsilon leaf nodes, which is an important value
  +     * that is used in a number of places later.
  +     */
  +/*    private CMNode buildSyntaxTree(int startNode, XMLContentSpec specNode) 
  +        throws CMException {
   
  -    private int fLeafCount = 0;
  -    private CMNode buildSyntaxTree(int startNode, XMLContentSpec.Node specNode) throws CMException
  -    {
  -		//****DEBUG****
  -		if (DEBUG) print("(POP) XMLValidator.buildSyntaxTree: ... \n");
  -		//****DEBUG****
  +                //****DEBUG****
  +                if (DEBUG) print("(POP) XMLValidator.buildSyntaxTree: ... \n");
  +                //****DEBUG****
   
           // We will build a node at this level for the new tree
           CMNode nodeRet = null;
  @@ -2354,8 +2192,7 @@
           //  If this node is a leaf, then its an easy one. We just add it
           //  to the tree.
           //
  -        if (specNode.type == XMLContentSpec.CONTENTSPECNODE_LEAF)
  -        {
  +        if (specNode.type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
               //
               //  Create a new leaf node, and pass it the current leaf count,
               //  which is its DFA state position. Bump the leaf count after
  @@ -2364,8 +2201,7 @@
               //
               nodeRet = new CMLeaf(specNode.type, specNode.value, fLeafCount++);
           }
  -         else
  -        {
  +        else {
               //
               //  Its not a leaf, so we have to recurse its left and maybe right
               //  nodes. Save both values before we recurse and trash the node.
  @@ -2373,72 +2209,55 @@
               final int leftNode = specNode.value;
               final int rightNode = specNode.otherValue;
   
  -            if ((specNode.type == XMLContentSpec.CONTENTSPECNODE_CHOICE)
  -            ||  (specNode.type == XMLContentSpec.CONTENTSPECNODE_SEQ))
  -            {
  +            if (specNode.type == XMLContentSpec.CONTENTSPECNODE_CHOICE || 
  +                specNode.type == XMLContentSpec.CONTENTSPECNODE_SEQ) {
                   //
                   //  Recurse on both children, and return a binary op node
                   //  with the two created sub nodes as its children. The node
                   //  type is the same type as the source.
                   //
   
  -                nodeRet = new CMBinOp
  -                (
  -                    specNode.type
  -                    , buildSyntaxTree(leftNode, specNode)
  -                    , buildSyntaxTree(rightNode, specNode)
  -                );
  +                nodeRet = new CMBinOp(specNode.type, 
  +                                      buildSyntaxTree(leftNode, specNode), 
  +                                      buildSyntaxTree(rightNode, specNode));
               }
  -             else if (specNode.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE)
  -            {
  +            else if (specNode.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE) {
                   // This one is fine as is, just change to our form
  -                nodeRet = new CMUniOp
  -                (
  -                    specNode.type
  -                    , buildSyntaxTree(leftNode, specNode)
  -                );
  +                nodeRet = new CMUniOp(specNode.type, 
  +                                      buildSyntaxTree(leftNode, specNode));
               }
  -             else if (specNode.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE)
  -            {
  +            else if (specNode.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE) {
                   // Convert to (x|epsilon)
  -                nodeRet = new CMBinOp
  -                (
  -                    XMLContentSpec.CONTENTSPECNODE_CHOICE
  -                    , buildSyntaxTree(leftNode, specNode)
  -                    , new CMLeaf(XMLContentSpec.CONTENTSPECNODE_LEAF, fEpsilonIndex)
  -                );
  +                nodeRet = new CMBinOp(XMLContentSpec.CONTENTSPECNODE_CHOICE, 
  +                                      buildSyntaxTree(leftNode, specNode), 
  +                                      new CMLeaf(XMLContentSpec.CONTENTSPECNODE_LEAF, fEpsilonIndex));
               }
  -             else if (specNode.type == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE)
  -            {
  +            else if (specNode.type == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE) {
                   // Convert to (x,x*)
  -                nodeRet = new CMBinOp
  -                (
  -                    XMLContentSpec.CONTENTSPECNODE_SEQ
  -                    , buildSyntaxTree(leftNode, specNode)
  -                    , new CMUniOp
  -                      (
  -                        XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE
  -                        , buildSyntaxTree(leftNode, specNode)
  -                      )
  -                );
  +                nodeRet = new CMBinOp(XMLContentSpec.CONTENTSPECNODE_SEQ, 
  +                                      buildSyntaxTree(leftNode, specNode), 
  +                                      new CMUniOp(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE, 
  +                                                  buildSyntaxTree(leftNode, specNode))
  +                                      );
               }
  -             else
  -            {
  +            else {
                   throw new CMException(ImplementationMessages.VAL_CST);
               }
           }
   
           // And return our new node for this level
           return nodeRet;
  -    }
   
  -    private int fCount = 0;
  -    private int[] fContentList = new int[64];
  -    private void makeContentList(int startNode, XMLContentSpec.Node specNode) throws CMException {
  +    } // buildSyntaxTree(int,XMLContentSpec):CMNode
  +    /*
   
  -		//****DEBUG****
  -		if (DEBUG) print("(POP) XMLValidator.makeContentList: ...\n");
  -		//****DEBUG****
  +    /** Makes a content list. */
  +    /* private void makeContentList(int startNode, XMLContentSpec specNode) 
  +        throws CMException {
  +
  +                //****DEBUG****
  +                if (DEBUG) print("(POP) XMLValidator.makeContentList: ...\n");
  +                //****DEBUG****
   
           //
           //  Ok, we need to build up an array of the possible children
  @@ -2452,22 +2271,13 @@
           //  along a content node for each iteration to use so that it does
           //  not have to create and trash lots of objects.
           //
  -        while (true)
  -        {
  +        while (true) {
               fCount = 0;
   
  -            try
  -            {
  -                fCount = buildContentList
  -                (
  -                    startNode
  -                    , 0
  -                    , specNode
  -                );
  +            try {
  +                fCount = buildContentList(startNode, 0, specNode);
               }
  -
  -            catch(IndexOutOfBoundsException excToCatch)
  -            {
  +            catch(IndexOutOfBoundsException excToCatch) {
                   //
                   //  Expand the array and try it again. Yes, this is
                   //  piggy, but the odds of it ever actually happening
  @@ -2481,19 +2291,24 @@
               // We survived, so break out
               break;
           }
  -    }
  -    private int buildContentList( int startNode, int count, XMLContentSpec.Node specNode) throws CMException
  -    {
  -		//****DEBUG****
  -		if (DEBUG) print("(POP) XMLValidator.buildContentList: ...\n");
  -		//****DEBUG****
   
  +    } // makeContentList(int,XMLContentSpec)
  +    */
  +
  +    /** Builds a content list. */
  +    /*private int buildContentList(int startNode, int count, 
  +                                 XMLContentSpec specNode) 
  +        throws CMException {
  +
  +                //****DEBUG****
  +                if (DEBUG) print("(POP) XMLValidator.buildContentList: ...\n");
  +                //****DEBUG****
  +
           // Get the content spec for the passed start node
           getContentSpecNode(startNode, specNode);
   
           // If this node is a leaf, then add it to our list and return.
  -        if (specNode.type == XMLContentSpec.CONTENTSPECNODE_LEAF)
  -        {
  +        if (specNode.type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
               fContentList[count++] = specNode.value;
               return count;
           }
  @@ -2505,9 +2320,8 @@
           final int leftNode = specNode.value;
           final int rightNode = specNode.otherValue;
   
  -        if ((specNode.type == XMLContentSpec.CONTENTSPECNODE_CHOICE)
  -        ||  (specNode.type == XMLContentSpec.CONTENTSPECNODE_SEQ))
  -        {
  +        if (specNode.type == XMLContentSpec.CONTENTSPECNODE_CHOICE || 
  +            specNode.type == XMLContentSpec.CONTENTSPECNODE_SEQ) {
               //
               //  Recurse on the left and right nodes of this guy, making sure
               //  to keep the count correct.
  @@ -2515,82 +2329,27 @@
               count = buildContentList(leftNode, count, specNode);
               count = buildContentList(rightNode, count, specNode);
           }
  -         else if ((specNode.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE)
  -              ||  (specNode.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE)
  -              ||  (specNode.type == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE))
  -        {
  +        else if (specNode.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE || 
  +                 specNode.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE ||
  +                 specNode.type == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE) {
               // Just do the left node on this one
               count = buildContentList(leftNode, count, specNode);
           }
  -         else
  -        {
  +        else {
               throw new CMException(ImplementationMessages.VAL_CST);
           }
   
           // And return our accumlated new count
           return count;
  -    }
   
  -    //
  -    // Chunk size constants
  -    //
  -    private static final int CHUNK_SHIFT = 8;           // 2^8 = 256
  -    private static final int CHUNK_SIZE = (1 << CHUNK_SHIFT);
  -    private static final int CHUNK_MASK = CHUNK_SIZE - 1;
  -    private static final int INITIAL_CHUNK_COUNT = (1 << (10 - CHUNK_SHIFT));   // 2^10 = 1k
  -    //
  -    // Instance variables
  -    //
  -    //
  -    // Element list
  -    //
  -    private int fElementCount = 0;
  -    private int[][] fElementType = new int[INITIAL_CHUNK_COUNT][];
  -    private byte[][] fElementDeclIsExternal = new byte[INITIAL_CHUNK_COUNT][];
  -    private int[][] fContentSpecType = new int[INITIAL_CHUNK_COUNT][];
  -    private int[][] fContentSpec = new int[INITIAL_CHUNK_COUNT][];
  -    private XMLContentModel[][] fContentModel = new XMLContentModel[INITIAL_CHUNK_COUNT][];
  -    private int[][] fAttlistHead = new int[INITIAL_CHUNK_COUNT][];
  -    private int[][] fAttlistTail = new int[INITIAL_CHUNK_COUNT][];
  -    //
  -    // ContentSpecNode list
  -    //
  -    private int fNodeCount = 0;
  -    private byte[][] fNodeType = new byte[INITIAL_CHUNK_COUNT][];
  -    private int[][] fNodeValue = new int[INITIAL_CHUNK_COUNT][];
  -    //
  -    // AttDef list
  -    //
  -    private int fAttDefCount = 0;
  -    private int[][] fAttName = new int[INITIAL_CHUNK_COUNT][];
  -    private int[][] fAttType = new int[INITIAL_CHUNK_COUNT][];
  -    private AttributeValidator[][] fAttValidator = new AttributeValidator[INITIAL_CHUNK_COUNT][];
  -    private int[][] fEnumeration = new int[INITIAL_CHUNK_COUNT][];
  -    private int[][] fAttDefaultType = new int[INITIAL_CHUNK_COUNT][];
  -    private int[][] fAttValue = new int[INITIAL_CHUNK_COUNT][];
  -    private byte[][] fAttDefIsExternal = new byte[INITIAL_CHUNK_COUNT][];
  -    private int[][] fNextAttDef = new int[INITIAL_CHUNK_COUNT][];
  -    //
  -    //
  -    //
  -    private Hashtable fIdDefs = null;
  -    private Hashtable fIdRefs = null;
  -    private Object fNullValue = null;
  -    private AttributeValidator fAttValidatorCDATA = null;
  -    private AttributeValidator fAttValidatorID = null;
  -    private AttributeValidator fAttValidatorIDREF = null;
  -    private AttributeValidator fAttValidatorIDREFS = null;
  -    private AttributeValidator fAttValidatorENTITY = null;
  -    private AttributeValidator fAttValidatorENTITIES = null;
  -    private AttributeValidator fAttValidatorNMTOKEN = null;
  -    private AttributeValidator fAttValidatorNMTOKENS = null;
  -    private AttributeValidator fAttValidatorNOTATION = null;
  -    private AttributeValidator fAttValidatorENUMERATION = null;
  -    private AttributeValidator fAttValidatorDATATYPE = null;
  -    //
  -    //
  -    //
  +    } // buildContentList(int,int,XMLContentSpec):int
  +    */
  +
  +    // initialization
  +
  +    /** Reset pool. */
       private void poolReset() {
  +        /***
           int chunk = 0;
           int index = 0;
           for (int i = 0; i < fElementCount; i++) {
  @@ -2600,1026 +2359,2566 @@
                   index = 0;
               }
           }
  +        
           fElementCount = 0;
           fNodeCount = 0;
           fAttDefCount = 0;
  -        if (fIdDefs != null)
  +        ***/
  +        if (fIdDefs != null) {
               fIdDefs.clear();
  -        if (fIdRefs != null)
  +        }
  +        if (fIdRefs != null) {
               fIdRefs.clear();
  -    }
  -    //
  -    // Element entries
  -    //
  -    private boolean ensureElementCapacity(int chunk) {
  -        try {
  -            return fElementType[chunk][0] == 0;
  -        } catch (ArrayIndexOutOfBoundsException ex) {
  -            byte[][] newByteArray = new byte[chunk * 2][];
  -            System.arraycopy(fElementDeclIsExternal, 0, newByteArray, 0, chunk);
  -            fElementDeclIsExternal = newByteArray;
  -            int[][] newIntArray = new int[chunk * 2][];
  -            System.arraycopy(fElementType, 0, newIntArray, 0, chunk);
  -            fElementType = newIntArray;
  -            newIntArray = new int[chunk * 2][];
  -            System.arraycopy(fContentSpecType, 0, newIntArray, 0, chunk);
  -            fContentSpecType = newIntArray;
  -            newIntArray = new int[chunk * 2][];
  -            System.arraycopy(fContentSpec, 0, newIntArray, 0, chunk);
  -            fContentSpec = newIntArray;
  -            XMLContentModel[][] newContentModel = new XMLContentModel[chunk * 2][];
  -            System.arraycopy(fContentModel, 0, newContentModel, 0, chunk);
  -            fContentModel = newContentModel;
  -            newIntArray = new int[chunk * 2][];
  -            System.arraycopy(fAttlistHead, 0, newIntArray, 0, chunk);
  -            fAttlistHead = newIntArray;
  -            newIntArray = new int[chunk * 2][];
  -            System.arraycopy(fAttlistTail, 0, newIntArray, 0, chunk);
  -            fAttlistTail = newIntArray;
  -        } catch (NullPointerException ex) {
           }
  -        fElementType[chunk] = new int[CHUNK_SIZE];
  -        fElementDeclIsExternal[chunk] = new byte[CHUNK_SIZE];
  -        fContentSpecType[chunk] = new int[CHUNK_SIZE];
  -        fContentSpec[chunk] = new int[CHUNK_SIZE];
  -        fContentModel[chunk] = new XMLContentModel[CHUNK_SIZE];
  -        fAttlistHead[chunk] = new int[CHUNK_SIZE];
  -        fAttlistTail[chunk] = new int[CHUNK_SIZE];
  -        return true;
  -    }
   
  -	
  -	//
  -	// addElement
  -	//
  -
  -    public int addElement(int elementType) {
  -
  -		//****DEBUG****
  -		if (DEBUG) print("(POP) XMLValidator.addElement: " + param("elementType",elementType) + "\n");
  -		//****DEBUG****
  +    } // poolReset()
  +    
   
  -        int elementIndex = fStringPool.getDeclaration(elementType);
  -        if (elementIndex != -1)
  -            return elementIndex;
  -        int chunk = fElementCount >> CHUNK_SHIFT;
  -        int index = fElementCount & CHUNK_MASK;
  -        ensureElementCapacity(chunk);
  -        fElementType[chunk][index] = elementType;
  -        fElementDeclIsExternal[chunk][index] = 0;
  -        fContentSpecType[chunk][index] = -1;
  -        fContentSpec[chunk][index] = -1;
  -        fContentModel[chunk][index] = null;
  -        fAttlistHead[chunk][index] = -1;
  -        fAttlistTail[chunk][index] = -1;
  -        fStringPool.setDeclaration(elementType, fElementCount);
  -        return fElementCount++;
  -    }
  +    /** Reset common. */
  +    private void resetCommon(StringPool stringPool) throws Exception {
   
  +                //****DEBUG****
  +                if (DEBUG) print("(POP) XMLValidator.resetCommon\n");
  +                //****DEBUG****
  +        fStringPool = stringPool;
  +        fValidating = fValidationEnabled;
  +        fValidationEnabledByDynamic = false;
  +        fDynamicDisabledByValidation = false;
  +        poolReset();
  +        fCalledStartDocument = false;
  +        fStandaloneReader = -1;
  +        fElementDepth = -1;
  +        fSeenRootElement = false;
  +        fSeenDoctypeDecl = false;
  +        fNamespacesScope = null;
  +        fNamespacesPrefix = -1;
  +        fRootElement.clear();
  +        fAttrListHandle = -1;
  +        //fElementDeclCount = 0;
  +        fCheckedForSchema = false;
   
  -	//
  -	// addElementDecl
  -	//
  +        fCurrentScope = TOP_LEVEL_SCOPE;
  +        fCurrentSchemaURI = -1;
  +        fEmptyURI = - 1; 
  +        fXsiPrefix = - 1;
  +
  +        fGrammar = null;
  +        fGrammarNameSpaceIndex = -1;
  +        fGrammarResolver = null;
   
  -    public int addElementDecl(int elementType, int contentSpecType, int contentSpec, boolean isExternal) {
  +        init();
   
  -		//****DEBUG****
  -		if (DEBUG) print("(POP) XMLValidator.addElementDecl: " + param("elementType",elementType) + "\n");
  -		//****DEBUG****
  +    } // resetCommon(StringPool)
   
  -		//System.out.println("Pool " + this + " add " + decl.elementType + " (" + fStringPool.toString(decl.elementType) + ")");
  -        
  -		int elementIndex = fStringPool.getDeclaration(elementType);
  -        if (elementIndex != -1) {
  -            int chunk = elementIndex >> CHUNK_SHIFT;
  -            int index = elementIndex & CHUNK_MASK;
  -            if (fContentSpecType[chunk][index] != -1)
  -                return -1;
  -            fElementDeclIsExternal[chunk][index] = (byte)(isExternal ? 1 : 0);
  -            fContentSpecType[chunk][index] = contentSpecType;
  -            fContentSpec[chunk][index] = contentSpec;
  -            fContentModel[chunk][index] = null;
  -            fElementDeclCount++;
  -            return elementIndex;
  -        }
  -        int chunk = fElementCount >> CHUNK_SHIFT;
  -        int index = fElementCount & CHUNK_MASK;
  -        ensureElementCapacity(chunk);
  -        fElementType[chunk][index] = elementType;
  -        fElementDeclIsExternal[chunk][index] = (byte)(isExternal ? 1 : 0);
  -        fContentSpecType[chunk][index] = contentSpecType;
  -        fContentSpec[chunk][index] = contentSpec;
  -        fContentModel[chunk][index] = null;
  -        fAttlistHead[chunk][index] = -1;
  -        fAttlistTail[chunk][index] = -1;
  -        fStringPool.setDeclaration(elementType, fElementCount);
  -        fElementDeclCount++;
  -        return fElementCount++;
  -    }
  +    /** Initialize. */
  +    private void init() {
   
  -    public int getElementType(int elementIndex) {
  -        if (elementIndex < 0 || elementIndex >= fElementCount)
  -            return -1;
  -        int chunk = elementIndex >> CHUNK_SHIFT;
  -        int index = elementIndex & CHUNK_MASK;
  -        return fElementType[chunk][index];
  -    }
  +                //****DEBUG****
  +                if (DEBUG) print("(POP) XMLValidator.init\n");
  +                //****DEBUG****
  +        //fEMPTYSymbol = fStringPool.addSymbol("EMPTY");
  +        fEMPTYSymbol = XMLElementDecl.TYPE_EMPTY;
  +        fANYSymbol = XMLElementDecl.TYPE_ANY;
  +        fMIXEDSymbol = XMLElementDecl.TYPE_MIXED;
  +        fCHILDRENSymbol = XMLElementDecl.TYPE_CHILDREN;
  +
  +        fCDATASymbol = XMLAttributeDecl.TYPE_CDATA;
  +        fIDSymbol = XMLAttributeDecl.TYPE_ID;
  +        fIDREFSymbol = XMLAttributeDecl.TYPE_IDREF;
  +        fIDREFSSymbol = XMLAttributeDecl.TYPE_IDREF;
  +        fENTITYSymbol = XMLAttributeDecl.TYPE_ENTITY;
  +        fENTITIESSymbol = XMLAttributeDecl.TYPE_ENTITY;
  +        fNMTOKENSymbol = XMLAttributeDecl.TYPE_NMTOKEN;
  +        fNMTOKENSSymbol = XMLAttributeDecl.TYPE_NMTOKEN;
  +        fNOTATIONSymbol = XMLAttributeDecl.TYPE_NOTATION;
  +        fENUMERATIONSymbol = XMLAttributeDecl.TYPE_ENUMERATION;
  +        fREQUIREDSymbol = XMLAttributeDecl.DEFAULT_TYPE_REQUIRED;
  +        fFIXEDSymbol = XMLAttributeDecl.DEFAULT_TYPE_FIXED;
  +        fDATATYPESymbol = XMLElementDecl.TYPE_SIMPLE;
  +        fEpsilonIndex = fStringPool.addSymbol("<<CMNODE_EPSILON>>");
  +        fXMLLang = fStringPool.addSymbol("xml:lang");
   
  -    private boolean getElementDeclIsExternal(int elementIndex) {
  -        if (elementIndex < 0 || elementIndex >= fElementCount)
  -            return false;
  -        int chunk = elementIndex >> CHUNK_SHIFT;
  -        int index = elementIndex & CHUNK_MASK;
  -        return (fElementDeclIsExternal[chunk][index] != 0);
  -    }
  +    } // init()
   
  -    public int getContentSpecType(int elementIndex) {
  -        if (elementIndex < 0 || elementIndex >= fElementCount)
  -            return -1;
  -        int chunk = elementIndex >> CHUNK_SHIFT;
  -        int index = elementIndex & CHUNK_MASK;
  -        return fContentSpecType[chunk][index];
  -    }
  +    // other
   
  -    final class ContentSpecImpl implements XMLContentSpec {
  -        protected StringPool fStringPool;
  -        protected int fHandle;
  -        protected int fType;
  -        public String toString() {
  -            if (fType == fMIXEDSymbol || fType == fCHILDRENSymbol)
  -                return contentSpecNodeAsString(fHandle);
  -            else
  -                return fStringPool.toString(fType);
  -        }
  -        public int getType() {
  -            return fType;
  -        }
  -        public int getHandle() {
  -            return fHandle;
  -        }
  -        public void getNode(int handle, XMLContentSpec.Node node) {
  -            getContentSpecNode(handle, node);
  -        }
  -    }
  +    /** Appends a content spec node to a string buffer. */
  +    /*private void appendContentSpecNode(int contentSpecIndex, 
  +                                       StringBuffer sb, boolean noParen) {
   
  -    private ContentSpecImpl fContentSpecImpl = null;
  -    public XMLContentSpec getContentSpec(int elementIndex) {
  -        if (elementIndex < 0 || elementIndex >= fElementCount)
  -            return null;
  -        int chunk = elementIndex >> CHUNK_SHIFT;
  -        int index = elementIndex & CHUNK_MASK;
  -        if (fContentSpecImpl == null)
  -            fContentSpecImpl = new ContentSpecImpl();
  -        fContentSpecImpl.fStringPool = fStringPool;
  -        fContentSpecImpl.fHandle = fContentSpec[chunk][index];
  -        fContentSpecImpl.fType = fContentSpecType[chunk][index];
  -        return fContentSpecImpl;
  +                //****DEBUG****
  +                if (DEBUG) print("(POP) XMLValidator.appendContentSpecNode: ...\n");
  +                //****DEBUG****
  +
  +        int chunk = contentSpecIndex >> CHUNK_SHIFT;
  +        int index = contentSpecIndex & CHUNK_MASK;
  +        int type = fNodeType[chunk][index];
  +        int value = fNodeValue[chunk][index];
  +        switch (type) {
  +            case XMLContentSpec.CONTENTSPECNODE_LEAF: {
  +                sb.append(value == -1 ? "#PCDATA" : fStringPool.toString(value));
  +                return;
  +            }
  +            case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE: {
  +                appendContentSpecNode(value, sb, false);
  +                sb.append('?');
  +                return;
  +            }
  +            case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE: {
  +                appendContentSpecNode(value, sb, false);
  +                sb.append('*');
  +                return;
  +            }
  +            case XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE: {
  +                appendContentSpecNode(value, sb, false);
  +                sb.append('+');
  +                return;
  +            }
  +            case XMLContentSpec.CONTENTSPECNODE_CHOICE:
  +            case XMLContentSpec.CONTENTSPECNODE_SEQ: {
  +                if (!noParen) {
  +                    sb.append('(');
  +                }
  +                int leftChunk = value >> CHUNK_SHIFT;
  +                int leftIndex = value & CHUNK_MASK;
  +                int leftType = fNodeType[leftChunk][leftIndex];
  +                appendContentSpecNode(value, sb, leftType == type);
  +                sb.append(type == XMLContentSpec.CONTENTSPECNODE_CHOICE ? '|' : ',');
  +                if (++index == CHUNK_SIZE) {
  +                    chunk++;
  +                    index = 0;
  +                }
  +                appendContentSpecNode(fNodeValue[chunk][index], sb, false);
  +                if (!noParen) {
  +                    sb.append(')');
  +                }
  +                return;
  +            }
  +            default: {
  +                return;
  +            }
  +        }
  +
  +    } // appendContentSpecNode(int,StringBuffer,boolean)
  +    */
  +
  +    // default attribute
  +
  +        /** addDefaultAttributes. */
  +    private int addDefaultAttributes(int elementIndex, XMLAttrList attrList, int attrIndex, boolean validationEnabled, boolean standalone) throws Exception {
  +
  +        //System.out.println("XMLValidator#addDefaultAttributes");
  +        //System.out.print("  ");
  +        //fGrammar.printAttributes(elementIndex);
  +
  +        //
  +        // Check after all specified attrs are scanned
  +        // (1) report error for REQUIRED attrs that are missing (V_TAGc)
  +        // (2) check that FIXED attrs have matching value (V_TAGd)
  +        // (3) add default attrs (FIXED and NOT_FIXED)
  +        //
  +        fGrammar.getElementDecl(elementIndex,fTempElementDecl);
  +
  +        //System.out.println("addDefaultAttributes: " + fStringPool.toString(fTempElementDecl.name.localpart)+
  +        //                   "," + attrIndex + "," + validationEnabled);
  +
  +        int elementNameIndex = fTempElementDecl.name.localpart;
  +        int attlistIndex = fGrammar.getFirstAttributeDeclIndex(elementIndex);
  +        int firstCheck = attrIndex;
  +        int lastCheck = -1;
  +        while (attlistIndex != -1) {
  +            //int adChunk = attlistIndex >> CHUNK_SHIFT;
  +            //int adIndex = attlistIndex & CHUNK_MASK;
  +            fGrammar.getAttributeDecl(attlistIndex, fTempAttDecl);
  +
  +            // TO DO: For ericye Debug only
  +            /***
  +            if (fTempAttDecl != null) {
  +                XMLElementDecl element = new XMLElementDecl();
  +                fGrammar.getElementDecl(elementIndex, element);
  +                System.out.println("element: "+fStringPool.toString(element.name.localpart));
  +                System.out.println("attlistIndex " + attlistIndex + "\n"+
  +                    "attName : '"+fStringPool.toString(fTempAttDecl.name.localpart) + "'\n"
  +                                   + "attType : "+fTempAttDecl.type + "\n"
  +                                   + "attDefaultType : "+fTempAttDecl.defaultType + "\n"
  +                                   + "attDefaultValue : '"+fTempAttDecl.defaultValue + "'\n"
  +                                   );
  +            }
  +            /***/
  +
  +            int attPrefix = fTempAttDecl.name.prefix;
  +            int attName = fTempAttDecl.name.localpart;
  +            int attType = fTempAttDecl.type;
  +            int attDefType =fTempAttDecl.defaultType;
  +            int attValue = -1 ;
  +            if (fTempAttDecl.defaultValue != null ) {
  +                attValue = fStringPool.addSymbol(fTempAttDecl.defaultValue);
  +            }
  +            boolean specified = false;
  +            boolean required = attDefType == fREQUIREDSymbol;
  +
  +            /****
  +            if (fValidating && fGrammar != null && fGrammar instanceof DTDGrammar && attValue != -1) {
  +                normalizeAttValue(null, fTempAttDecl.name,
  +                                  attValue,attType,fTempAttDecl.list, 
  +                                  fTempAttDecl.enumeration);
  +            }
  +            /****/
  +
  +            if (firstCheck != -1) {
  +                boolean cdata = attType == fCDATASymbol;
  +                if (!cdata || required || attValue != -1) {
  +                    int i = attrList.getFirstAttr(firstCheck);
  +                    while (i != -1 && (lastCheck == -1 || i <= lastCheck)) {
  +                        if (fStringPool.equalNames(attrList.getAttrName(i), attName)) {
  +                            if (validationEnabled && attDefType == fFIXEDSymbol) {
  +                                int alistValue = attrList.getAttValue(i);
  +                                if (alistValue != attValue &&
  +                                    !fStringPool.toString(alistValue).equals(fStringPool.toString(attValue))) {
  +                                    Object[] args = { fStringPool.toString(elementNameIndex),
  +                                                    fStringPool.toString(attName),
  +                                                    fStringPool.toString(alistValue),
  +                                                    fStringPool.toString(attValue) };
  +                                    fErrorReporter.reportError(fErrorReporter.getLocator(),
  +                                                            XMLMessages.XML_DOMAIN,
  +                                                            XMLMessages.MSG_FIXED_ATTVALUE_INVALID,
  +                                                            XMLMessages.VC_FIXED_ATTRIBUTE_DEFAULT,
  +                                                            args,
  +                                                            XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
  +                                }
  +                            }
  +                            specified = true;
  +                            break;
  +                        }
  +                        i = attrList.getNextAttr(i);
  +                    }
  +                }
  +            }
  +            if (!specified) {
  +                if (required) {
  +                    if (validationEnabled) {
  +                        Object[] args = { fStringPool.toString(elementNameIndex),
  +                                          fStringPool.toString(attName) };
  +                        fErrorReporter.reportError(fErrorReporter.getLocator(),
  +                                                   XMLMessages.XML_DOMAIN,
  +                                                   XMLMessages.MSG_REQUIRED_ATTRIBUTE_NOT_SPECIFIED,
  +                                                   XMLMessages.VC_REQUIRED_ATTRIBUTE,
  +                                                   args,
  +                                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
  +                    }
  +                } 
  +                else if (attValue != -1) {
  +                    if (validationEnabled && standalone )
  +                        if ( fGrammar instanceof DTDGrammar 
  +                             && ((DTDGrammar) fGrammar).getAttributeDeclIsExternal(attlistIndex) ) {
  +                        
  +                         // REVISIT: we don't have such informatio anymore && fAttDefIsExternal[adChunk][adIndex] != 0) {
  +                        Object[] args = { fStringPool.toString(elementNameIndex),
  +                                          fStringPool.toString(attName) };
  +                        fErrorReporter.reportError(fErrorReporter.getLocator(),
  +                                                   XMLMessages.XML_DOMAIN,
  +                                                   XMLMessages.MSG_DEFAULTED_ATTRIBUTE_NOT_SPECIFIED,
  +                                                   XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
  +                                                   args,
  +                                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
  +                    }
  +                    if (attType == fIDREFSymbol) {
  +                        addIdRef(attValue);
  +                    } 
  +                    else if (attType == fIDREFSSymbol) {
  +                        StringTokenizer tokenizer = new StringTokenizer(fStringPool.toString(attValue));
  +                        while (tokenizer.hasMoreTokens()) {
  +                            String idName = tokenizer.nextToken();
  +                            addIdRef(fStringPool.addSymbol(idName));
  +                        }
  +                    }
  +                    if (attrIndex == -1) {
  +                        attrIndex = attrList.startAttrList();
  +                    }
  +                    // REVISIT: Validation. What should the prefix be?
  +                    fTempQName.setValues(attPrefix, attName, attName);
  +                    int newAttr = attrList.addAttr(fTempQName, 
  +                                                   attValue, attType, 
  +                                                   false, false);
  +                    if (lastCheck == -1) {
  +                        lastCheck = newAttr;
  +                    }
  +                }
  +            }
  +            attlistIndex = fGrammar.getNextAttributeDeclIndex(attlistIndex);
  +        }
  +        return attrIndex;
  +
  +    } // addDefaultAttributes(int,XMLAttrList,int,boolean,boolean):int
  +    
  +
  +    /*public void setCurrentScope(int scope) {
  +        fCurrentScope = scope;
       }
   
  -    public int getContentSpecHandle(int elementIndex) {
  -        if (elementIndex < 0 || elementIndex >= fElementCount)
  -            return -1;
  -        int chunk = elementIndex >> CHUNK_SHIFT;
  -        int index = elementIndex & CHUNK_MASK;
  -        return fContentSpec[chunk][index];
  +    public int getCurrentScope() {
  +        return fCurrentScope;
       }
  +    */
  +    
  +    // string pool to declaration mapping
   
  -    protected String getContentSpecAsString(int elementIndex) {
  -        if (elementIndex < 0 || elementIndex >= fElementCount)
  -            return null;
  -        int chunk = elementIndex >> CHUNK_SHIFT;
  -        int index = elementIndex & CHUNK_MASK;
  -        int contentSpecType = fContentSpecType[chunk][index];
  -        if (contentSpecType == fMIXEDSymbol || contentSpecType == fCHILDRENSymbol)
  -            return contentSpecNodeAsString(fContentSpec[chunk][index]);
  -        else
  -            return fStringPool.toString(contentSpecType);
  +    /** Sets the string pool to declaration mapping. */
  +    /*private void setDeclaration(QName qname, int decl) {
  +        // REVISIT: Validation. Key from <uri, localpart> tuple.
  +        int stringIndex = qname.rawname;
  +        ensureDeclarationCapacity(stringIndex);
  +        fDeclaration[stringIndex] = decl;
  +    }*/
  +
  +    //REVISIT: ye
  +    /*private void setDeclaration(QName qname, int decl) {
  +        // REVISIT: 1)Where will the fCurrentScope come from?
  +        //          2)Should uri be checked if present? 
  +        int uri = qname.uri;
  +
  +        if (uri==-1) {
  +            fNameScopeToIndex.put(qname.localpart, fCurrentScope, decl);
  +        }
  +        else {
  +            fNameScopeToIndex.put(qname.localpart, TOP_LEVEL_SCOPE, decl);
  +        }
       }
  +    */
  +    /** Returns the string pool to declaration mapping. */
  +    /*private int getDeclaration(QName qname) {
  +        // REVISIT: Validation. Key from <uri, localpart> tuple.
  +        int stringIndex = qname.rawname;
  +        if (fDeclaration == null || 
  +            stringIndex < 0 || stringIndex >= fDeclaration.length) {
  +            return -1;
  +        }
  +        return fDeclaration[stringIndex];
  +    }*/
   
  -    private XMLContentModel getElementContentModel(int elementIndex) {
  -        if (elementIndex < 0 || elementIndex >= fElementCount)
  -            return null;
  +    //REVISIT: ye
  +    /*private int getDeclaration(QName qname) {
  +    // REVISIT: should we pass in the scope? switchNS(uri) should be done
  +        //      before we come in.
  +        int uri = qname.uri;
  +        if (uri == -1) {
  +            return fNameScopeToIndex.get(qname.localpart,fCurrentScope);
  +        }
  +        else {
  +            return fNameScopeToIndex.get(qname.localpart, TOP_LEVEL_SCOPE);
  +        }
  +   } */
  +
  +   /*public int getDeclaration(int localpart, int scope) {
  +            return fNameScopeToIndex.get(localpart, scope);
  +   }*/
  +
  +
  +    // content specs
  +
  +    /** Adds a content spec leaf node. */
  +    /*private int addContentSpecLeafNode(int nodeValue) throws Exception {
  +
  +                //****DEBUG****
  +                if (DEBUG) print("(POP) XMLValidator.addContentSpecLeafNode: " + param("nodeValue",nodeValue) + "\n");
  +                //****DEBUG****
  +
  +        //
  +        // Check that we have not seen this value before...
  +        //
  +        if (nodeValue != -1) {
  +            int nodeCount = fNodeCount;
  +            int chunk = fNodeCount >> CHUNK_SHIFT;
  +            int index = fNodeCount & CHUNK_MASK;
  +            while (true) {
  +                if (index-- == 0) {
  +                    index = CHUNK_SIZE - 1;
  +                    chunk--;
  +                }
  +                int nodeType = fNodeType[chunk][index];
  +                if (nodeType == XMLContentSpec.CONTENTSPECNODE_LEAF) {
  +                    int otherNodeValue = fNodeValue[chunk][index];
  +                    if (otherNodeValue == -1) {
  +                        break;
  +                    }
  +                    if (otherNodeValue == nodeValue) {
  +                        return -1;
  +                    }
  +                }
  +            }
  +        }
  +        int chunk = fNodeCount >> CHUNK_SHIFT;
  +        int index = fNodeCount & CHUNK_MASK;
  +        ensureNodeCapacity(chunk);
  +        fNodeType[chunk][index] = (byte)XMLContentSpec.CONTENTSPECNODE_LEAF;
  +        fNodeValue[chunk][index] = nodeValue;
  +        return fNodeCount++;
  +
  +    } // addContentSpecLeafNode(int):int
  +    */
  +
  +    // content models
  +
  +    /** Queries the content model for the specified element index. */
  +    private XMLContentModel getElementContentModel(int elementIndex) throws CMException {
  +        XMLContentModel contentModel = null;
  +        if ( elementIndex > -1) {
  +            if ( fGrammar.getElementDecl(elementIndex,fTempElementDecl) ) {
  +                contentModel = fGrammar.getElementContentModel(elementIndex);
  +            }
  +        }
  +        //return fGrammar.getElementContentModel(elementIndex);
  +        return contentModel;
  +    }
  +    
  +
  +    /** Sets the content model for the specified element index. */
  +    private void setContentModel(int elementIndex, XMLContentModel cm) {
  +        /*if (elementIndex < 0 || elementIndex >= fElementCount) {
  +            return;
  +        }
           int chunk = elementIndex >> CHUNK_SHIFT;
           int index = elementIndex & CHUNK_MASK;
  -        return fContentModel[chunk][index];
  +        fContentModel[chunk][index] = cm;
  +        */
       }
  +    
  +    // ensure capacity
  +
  +    /** Ensures that there is enough storage for element information. */
  +    /*private boolean ensureElementCapacity(int chunk) {
  +
  +        try {
  +            return fElementType[chunk][0] == 0;
  +        } 
  +        catch (ArrayIndexOutOfBoundsException ex) {
  +            byte[][] newByteArray = new byte[chunk * 2][];
  +            System.arraycopy(fElementDeclIsExternal, 0, newByteArray, 0, chunk);
  +            fElementDeclIsExternal = newByteArray;
  +            //REVISIT: fElementType            
  +            int[][] newIntArray = new int[chunk * 2][];
  +            System.arraycopy(fElementType, 0, newIntArray, 0, chunk);
  +            fElementType = newIntArray;
  +            //REVISIT: fElementQName           
  +            QName[][] newQNameArray = new QName[chunk * 2][];
  +            System.arraycopy(fElementQName, 0, newQNameArray, 0, chunk);
  +            fElementQName = newQNameArray;
  +            //REVISIT: fScope             
  +            newIntArray = new int[chunk * 2][];
  +            System.arraycopy(fScope, 0, newIntArray, 0, chunk);
  +            fScope = newIntArray;
  +
  +            newIntArray = new int[chunk * 2][];
  +            System.arraycopy(fContentSpecType, 0, newIntArray, 0, chunk);
  +            fContentSpecType = newIntArray;
  +            newIntArray = new int[chunk * 2][];
  +            System.arraycopy(fContentSpec, 0, newIntArray, 0, chunk);
  +            fContentSpec = newIntArray;
  +            XMLContentModel[][] newContentModel = new XMLContentModel[chunk * 2][];
  +            System.arraycopy(fContentModel, 0, newContentModel, 0, chunk);
  +            fContentModel = newContentModel;
  +            newIntArray = new int[chunk * 2][];
  +            System.arraycopy(fAttlistHead, 0, newIntArray, 0, chunk);
  +            fAttlistHead = newIntArray;
  +            newIntArray = new int[chunk * 2][];
  +            System.arraycopy(fAttlistTail, 0, newIntArray, 0, chunk);
  +            fAttlistTail = newIntArray;
  +        } catch (NullPointerException ex) {
  +            // ignore
  +        }
  +        //REVISIT: fElementType, fElementQName, fScope
  +        fElementType[chunk] = new int[CHUNK_SIZE];
  +        fElementQName[chunk] = new QName[CHUNK_SIZE];
  +        fScope[chunk] = new int[CHUNK_SIZE];
  +        //by default, all the scope should be top-level
  +        for (int i=0; i<CHUNK_SIZE; i++) {
  +            fScope[chunk][i] = TOP_LEVEL_SCOPE;
  +        }
  +
  +        fElementDeclIsExternal[chunk] = new byte[CHUNK_SIZE];
  +        fContentSpecType[chunk] = new int[CHUNK_SIZE];
  +        fContentSpec[chunk] = new int[CHUNK_SIZE];
  +        fContentModel[chunk] = new XMLContentModel[CHUNK_SIZE];
  +        fAttlistHead[chunk] = new int[CHUNK_SIZE];
  +        fAttlistTail[chunk] = new int[CHUNK_SIZE];
  +        return true;
  +
  +    } // ensureElementCapacity(int):boolean
  +    */
  +
  +    /** Ensures that there is enough storage for node information. */
  +    /*    private boolean ensureNodeCapacity(int chunk) {
  +
  +        try {
  +            return fNodeType[chunk][0] == 0;
  +        } 
  +        catch (ArrayIndexOutOfBoundsException ex) {
  +            byte[][] newByteArray = new byte[chunk * 2][];
  +            System.arraycopy(fNodeType, 0, newByteArray, 0, chunk);
  +            fNodeType = newByteArray;
  +            int[][] newIntArray = new int[chunk * 2][];
  +            System.arraycopy(fNodeValue, 0, newIntArray, 0, chunk);
  +            fNodeValue = newIntArray;
  +        } 
  +        catch (NullPointerException ex) {
  +            // ignore
  +        }
  +        fNodeType[chunk] = new byte[CHUNK_SIZE];
  +        fNodeValue[chunk] = new int[CHUNK_SIZE];
  +        return true;
  +
  +    } // ensureNodeCapacity(int):boolean
  +    */
  +    
  +    /** Ensures that there's enough storage for attribute information. */
  +    /*private boolean ensureAttrCapacity(int chunk) {
  +
  +        try {
  +            return fAttName[chunk][0] == 0;
  +        } 
  +        catch (ArrayIndexOutOfBoundsException ex) {
  +            byte[][] newByteArray = new byte[chunk * 2][];
  +            System.arraycopy(fAttDefIsExternal, 0, newByteArray, 0, chunk);
  +            fAttDefIsExternal = newByteArray;
  +            int[][] newIntArray = new int[chunk * 2][];
  +            System.arraycopy(fAttPrefix, 0, newIntArray, 0, chunk);
  +            fAttPrefix = newIntArray;
  +            System.arraycopy(fAttName, 0, newIntArray, 0, chunk);
  +            fAttName = newIntArray;
  +            newIntArray = new int[chunk * 2][];
  +            System.arraycopy(fAttType, 0, newIntArray, 0, chunk);
  +            fAttType = newIntArray;
  +            newIntArray = new int[chunk * 2][];
  +            System.arraycopy(fEnumeration, 0, newIntArray, 0, chunk);
  +            fEnumeration = newIntArray;
  +            newIntArray = new int[chunk * 2][];
  +            System.arraycopy(fAttDefaultType, 0, newIntArray, 0, chunk);
  +            fAttDefaultType = newIntArray;
  +            newIntArray = new int[chunk * 2][];
  +            System.arraycopy(fAttValue, 0, newIntArray, 0, chunk);
  +            fAttValue = newIntArray;
  +            newIntArray = new int[chunk * 2][];
  +            System.arraycopy(fNextAttDef, 0, newIntArray, 0, chunk);
  +            fNextAttDef = newIntArray;
  +            AttributeValidator[][] newValidatorArray = new AttributeValidator[chunk * 2][];
  +            System.arraycopy(fAttValidator, 0, newValidatorArray, 0, chunk);
  +            fAttValidator = newValidatorArray;
  +        } 
  +        catch (NullPointerException ex) {
  +            // ignore
  +        }
  +        fAttDefIsExternal[chunk] = new byte[CHUNK_SIZE];
  +        fAttPrefix[chunk] = new int[CHUNK_SIZE];
  +        fAttName[chunk] = new int[CHUNK_SIZE];
  +        fAttType[chunk] = new int[CHUNK_SIZE];
  +        fAttValidator[chunk] = new AttributeValidator[CHUNK_SIZE];
  +        fEnumeration[chunk] = new int[CHUNK_SIZE];
  +        fAttDefaultType[chunk] = new int[CHUNK_SIZE];
  +        fAttValue[chunk] = new int[CHUNK_SIZE];
  +        fNextAttDef[chunk] = new int[CHUNK_SIZE];
  +        return true;
  +
  +    } // ensureAttrCapacity(int):boolean
  +    */
  +
  +    /** 
  +     * Ensures that there is enough storage for the string pool to
  +     * declaration mappings.
  +     */
  +    /*private void ensureDeclarationCapacity(int stringIndex) {
  +        if (fDeclaration == null) {
  +            fDeclaration = new int[stringIndex + 1];
  +            for (int i = 0; i < stringIndex; i++) {
  +                fDeclaration[i] = -1;
  +            }
  +        }
  +        else if (fDeclaration.length < stringIndex + 1) {
  +            int newint[] = new int[stringIndex + 1];
  +            System.arraycopy(fDeclaration, 0, newint, 0, fDeclaration.length);
  +            for (int i = fDeclaration.length; i < stringIndex - 1; i++) {
  +                newint[i] = -1;
  +            }
  +            fDeclaration = newint;
  +        }
  +    }*/
  +
  +    // query attribute information
  +
  +    /** Returns the validatator for an attribute type. */
  +    private AttributeValidator getValidatorForAttType(int attType, boolean list) {
  +        if (attType == fCDATASymbol) {
  +            if (fAttValidatorCDATA == null) {
  +                fAttValidatorCDATA = new AttValidatorCDATA();
  +            }
  +            return fAttValidatorCDATA;
  +        }
  +        if (attType == fIDSymbol) {
  +            if (fAttValidatorID == null) {
  +                fAttValidatorID = new AttValidatorID();
  +            }
  +            return fAttValidatorID;
  +        }
  +        if (attType == fIDREFSymbol) {
  +            if (!list) {
  +            
  +                if (fAttValidatorIDREF == null) {
  +                    fAttValidatorIDREF = new AttValidatorIDREF();
  +                }
  +                return fAttValidatorIDREF;
  +            }
  +            else {
  +                if (fAttValidatorIDREFS == null) {
  +                    fAttValidatorIDREFS = new AttValidatorIDREFS();
  +                }
  +                return fAttValidatorIDREFS;
  +            }
  +        }
  +        if (attType == fENTITYSymbol) {
  +            if (!list) {
  +                if (fAttValidatorENTITY == null) {
  +                    fAttValidatorENTITY = new AttValidatorENTITY();
  +                }
  +                return fAttValidatorENTITY;
  +            }
  +            else{
  +                if (fAttValidatorENTITIES == null) {
  +                    fAttValidatorENTITIES = new AttValidatorENTITIES();
  +                }
  +                return fAttValidatorENTITIES;
  +            }
  +        }
  +        if (attType == fNMTOKENSymbol) {
  +            if (!list) {
  +                if (fAttValidatorNMTOKEN == null) {
  +                    fAttValidatorNMTOKEN = new AttValidatorNMTOKEN();
  +                }
  +                return fAttValidatorNMTOKEN;
  +            }
  +            else{
  +                if (fAttValidatorNMTOKENS == null) {
  +                    fAttValidatorNMTOKENS = new AttValidatorNMTOKENS();
  +                }
  +                return fAttValidatorNMTOKENS;
  +            }
  +        }
  +        if (attType == fNOTATIONSymbol) {
  +            if (fAttValidatorNOTATION == null) {
  +                fAttValidatorNOTATION = new AttValidatorNOTATION();
  +            }
  +            return fAttValidatorNOTATION;
  +        }
  +        if (attType == fENUMERATIONSymbol) {
  +            if (fAttValidatorENUMERATION == null) {
  +                fAttValidatorENUMERATION = new AttValidatorENUMERATION();
  +            }
  +            return fAttValidatorENUMERATION;
  +        }
  +        if (attType == fDATATYPESymbol) {
  +            if (fAttValidatorDATATYPE == null) {
  +                fAttValidatorDATATYPE = null; //REVISIT : !!! used to be fSchemaImporter.createDatatypeAttributeValidator();
  +            }
  +            //return fAttValidatorDATATYPE;
  +        }
  +        return null;
  +        //throw new RuntimeException("getValidatorForAttType(" + fStringPool.toString(attType) + ")");
  +    }
  +
  +    /** Returns an attribute definition for an element type. */
  +    private int getAttDef(QName element, QName attribute) {
  +        int scope = fCurrentScope;
  +        if (element.uri > -1) {
  +            scope = TOP_LEVEL_SCOPE;
  +        }
  +        int elementIndex = fGrammar.getElementDeclIndex(element.localpart,scope);
  +        if (elementIndex == -1) {
  +            return -1;
  +        }
  +        int attDefIndex = fGrammar.getFirstAttributeDeclIndex(elementIndex);
  +        while (attDefIndex != -1) {
  +            fGrammar.getAttributeDecl(attDefIndex, fTempAttDecl);
  +            if (fTempAttDecl.name.localpart == attribute.localpart &&
  +                fTempAttDecl.name.uri == attribute.uri ) {
  +                return attDefIndex;
  +            }
  +            attDefIndex = fGrammar.getNextAttributeDeclIndex(attDefIndex);
  +        }
  +        return -1;
  +
  +    } // getAttDef(QName,QName)
  +
  +    /** Returns an attribute's name from its definition index. */
  +    /*private int getAttName(int attDefIndex) {
  +
  +        int chunk = attDefIndex >> CHUNK_SHIFT;
  +        int index = attDefIndex & CHUNK_MASK;
  +        return fAttName[chunk][index];
  +    }
  +    */
  +    /** Returns an attribute's value from its definition index. */
  +    /*private int getAttValue(int attDefIndex) {
  +        int chunk = attDefIndex >> CHUNK_SHIFT;
  +        int index = attDefIndex & CHUNK_MASK;
  +        return fAttValue[chunk][index];
  +    }*/
  +
  +    /** Returns a validator from its definition index. */
  +    private AttributeValidator getAttributeValidator(int attDefIndex) {
  +        //int chunk = attDefIndex >> CHUNK_SHIFT;
  +        //int index = attDefIndex & CHUNK_MASK;
  +        //return fAttValidator[chunk][index];
  +        //REVISIT:
  +        return null;
  +    }
  +
  +    /** Returns an attribute's type from its definition index. */
  +    private int getAttType(int attDefIndex) {
  +        if (attDefIndex > -1 ) {
  +            fGrammar.getAttributeDecl(attDefIndex, fTempAttDecl);
  +            return fTempAttDecl.type;
  +        }
  +        return -1;
  +    }
  +
  +    /** Returns an attribute's default type from its definition index. */
  +    private int getAttDefaultType(int attDefIndex) {
  +        if (attDefIndex > -1 ) {
  +            fGrammar.getAttributeDecl(attDefIndex, fTempAttDecl);
  +            return fStringPool.addSymbol(fTempAttDecl.defaultType);
  +        }
  +        return -1;
  +   }
  +
  +    /** Returns an attribute's enumeration values from its definition index. */
  +    private int getEnumeration(int attDefIndex) {
  +        //int chunk = attDefIndex >> CHUNK_SHIFT;
  +        //int index = attDefIndex & CHUNK_MASK;
  +        //return fEnumeration[chunk][index];
  +        //REVISIT:
  +        return -1;
  +    }
  +
  +    // validation
  +
  +    /** Root element specified. */
  +    private void rootElementSpecified(QName rootElement) throws Exception {
  +
  +        if  (fDynamicValidation && !fSeenDoctypeDecl) {
  +          fValidating = false;
  +        }
  +        if (fValidating) {
  +
  +            // initialize the grammar to be the default one.
  +            if (fGrammar == null) {
  +
  +                fGrammar = fGrammarResolver.getGrammar("");
  +                
  +                //TO DO, for ericye debug only
  +                if (fGrammar == null && DEBUG_SCHEMA_VALIDATION) {
  +                    System.out.println("Oops! no grammar is found for validation");
  +                }
  +
  +                fGrammarNameSpaceIndex = fEmptyURI;
  +            }
  +
  +            if ( fGrammar instanceof DTDGrammar && 
  +                ((DTDGrammar) fGrammar).getRootElementQName(fRootElement) ) {
  +
  +                String root1 = fStringPool.toString(fRootElement.rawname);
  +                String root2 = fStringPool.toString(rootElement.rawname);
  +                if (!root1.equals(root2)) {
  +                    reportRecoverableXMLError(XMLMessages.MSG_ROOT_ELEMENT_TYPE,
  +                                              XMLMessages.VC_ROOT_ELEMENT_TYPE,
  +                                              fRootElement.rawname, 
  +                                              rootElement.rawname);
  +                }
  +            }
  +        }
  +        if (fNamespacesEnabled) {
  +            if (fNamespacesScope == null) {
  +                fNamespacesScope = new NamespacesScope(this);
  +                fNamespacesPrefix = fStringPool.addSymbol("xmlns");
  +                fNamespacesScope.setNamespaceForPrefix(fNamespacesPrefix, -1);
  +                int xmlSymbol = fStringPool.addSymbol("xml");
  +                int xmlNamespace = fStringPool.addSymbol("http://www.w3.org/XML/1998/namespace");
  +                fNamespacesScope.setNamespaceForPrefix(xmlSymbol, xmlNamespace);
  +            }
  +        }
  +
  +    } // rootElementSpecified(QName)
  +
  +    /** Switchs to correct validating symbol tables when Schema changes.*/
  +    
  +    private void switchGrammar(int newGrammarNameSpaceIndex) {
  +        Grammar tempGrammar = fGrammarResolver.getGrammar(fStringPool.toString(newGrammarNameSpaceIndex));
  +        if (tempGrammar == null) {
  +            //TO DO report error here
  +        }
  +        else {
  +            fGrammar = tempGrammar;
  +        }
  +    }
  +    /** Binds namespaces to the element and attributes. */
  +    private void bindNamespacesToElementAndAttributes(QName element, 
  +                                                      XMLAttrList attrList)
  +        throws Exception {
  +
  +        fNamespacesScope.increaseDepth();
  +        int prefix = element.prefix;
  +
  +        Vector schemaCandidateURIs = null;
  +        Hashtable locationUriPairs = null;
  +        
  +        if (fValidating) {
  +            schemaCandidateURIs = new Vector();
  +            locationUriPairs = new Hashtable(); 
  +        }
  +        if (fAttrListHandle != -1) {
  +            int index = attrList.getFirstAttr(fAttrListHandle);
  +            while (index != -1) {
  +                int attName = attrList.getAttrName(index);
  +                int attPrefix = attrList.getAttrPrefix(index);
  +                if (fStringPool.equalNames(attName, fXMLLang)) {
  +                    /***
  +                    // NOTE: This check is done in the validateElementsAndAttributes
  +                    //       method.
  +                    fDocumentScanner.checkXMLLangAttributeValue(attrList.getAttValue(index));
  +                    /***/
  +                } 
  +                else if (fStringPool.equalNames(attName, fNamespacesPrefix)) {
  +                    int uri = fStringPool.addSymbol(attrList.getAttValue(index));
  +                    fNamespacesScope.setNamespaceForPrefix(StringPool.EMPTY_STRING, uri);
  +                } 
  +                else {
  +                    if (attPrefix == fNamespacesPrefix) {
  +                        int nsPrefix = attrList.getAttrLocalpart(index);
  +                        int uri = fStringPool.addSymbol(attrList.getAttValue(index));
  +                        boolean seeXsi = false;
  +                        fNamespacesScope.setNamespaceForPrefix(nsPrefix, uri);
  +
  +                        String attrValue = fStringPool.toString(attrList.getAttValue(index));
  +
  +                        if (attrValue.equals(SchemaSymbols.URI_XSI)) {
  +                            fXsiPrefix = nsPrefix;
  +                            seeXsi = true;
  +                        }
  +                        
  +                        if (fValidating && !seeXsi) {
  +                            schemaCandidateURIs.addElement( fStringPool.toString(uri) );
  +                        }
  +                    }
  +                }
  +                index = attrList.getNextAttr(index);
  +            }
  +
  +            // if validating, walk through the list again to deal with "xsi:...."
  +            if (fValidating) {
  +
  +                index = attrList.getFirstAttr(fAttrListHandle);
  +                while (index != -1) {
  +                    
  +                    int attName = attrList.getAttrName(index);
  +                    int attPrefix = attrList.getAttrPrefix(index);
  +                    
  +                    if (fStringPool.equalNames(attName, fNamespacesPrefix)) {
  +                        // REVISIT
  +                    } 
  +                    else {
  +                        if ( DEBUG_SCHEMA_VALIDATION ) {
  +                            System.out.println("deal with XSI");
  +                            System.out.println("before find XSI: "+fStringPool.toString(attPrefix)
  +                                               +","+fStringPool.toString(fXsiPrefix) );
  +                        }
  +                        if (attPrefix == fXsiPrefix && fXsiPrefix != -1 ) {
  +
  +                            if (DEBUG_SCHEMA_VALIDATION) {
  +                                System.out.println("find XSI: "+fStringPool.toString(attPrefix)
  +                                                   +","+fStringPool.toString(attName) );
  +                            }
  +
  +
  +                            int localpart = attrList.getAttrLocalpart(index);
  +                            if (localpart == fStringPool.addSymbol(SchemaSymbols.XSI_SCHEMALOCACTION)) {
  +                                parseSchemaLocation(fStringPool.toString(attrList.getAttValue(index)), locationUriPairs);
  +                            }
  +                            else if (localpart == fStringPool.addSymbol(SchemaSymbols.XSI_NONAMESPACESCHEMALOCACTION))  {
  +                                locationUriPairs.put(fStringPool.toString(attrList.getAttValue(index)), "");
  +                            }
  +                            // REVISIT: should we break here? 
  +                            break;
  +                        }
  +                    }
  +                    index = attrList.getNextAttr(index);
  +                }
  +
  +                // try to resolve all the grammars here
  +                Enumeration locations = locationUriPairs.keys();
  +
  +                while (locations.hasMoreElements()) {
  +                    String loc = (String) locations.nextElement();
  +                    String uri = (String) locationUriPairs.get(loc);
  +                    resolveSchemaGrammar( loc, uri);
  +                    schemaCandidateURIs.removeElement(uri);
  +                }
  +
  +                //TO DO: This should be a feature that can be turned on or off
  +                /*****
  +                for (int i=0; i< schemaCandidateURIs.size(); i++) {
  +                
  +                    String uri = (String) schemaCandidateURIs.elementAt(i);
  +                    resolveSchemaGrammar(uri);
  +                }
  +                /*****/
  +
  +            }
  +
  +        }
  +
  +        int elementURI;
  +        if (prefix == -1) {
  +            // REVISIT, is this only valid for Schema Validation
  +            if (fGrammar != null && fValidating && fGrammar.getElementDeclIndex(element.localpart, fCurrentScope) > -1) {
  +                element.uri = -1;
  +            }
  +            else {
  +                elementURI = fNamespacesScope.getNamespaceForPrefix(StringPool.EMPTY_STRING);
  +                if (elementURI != -1) {
  +                    element.uri = elementURI;
  +                }
  +            }
  +        } 
  +        else {
  +            elementURI = fNamespacesScope.getNamespaceForPrefix(prefix);
  +            if (elementURI == -1) {
  +                Object[] args = { fStringPool.toString(prefix) };
  +                fErrorReporter.reportError(fErrorReporter.getLocator(),
  +                                           XMLMessages.XMLNS_DOMAIN,
  +                                           XMLMessages.MSG_PREFIX_DECLARED,
  +                                           XMLMessages.NC_PREFIX_DECLARED,
  +                                           args,
  +                                           XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
  +            }
  +            element.uri = elementURI;
  +        }
  +
  +
  +        //REVISIT: is this the right place to check on if the Schema has changed?
  +
  +        if ( fValidating && element.uri != fGrammarNameSpaceIndex && element.uri != -1  ) {
  +            fGrammarNameSpaceIndex = element.uri;
  +            switchGrammar(fGrammarNameSpaceIndex);
  +        }
  +
  +        if (fAttrListHandle != -1) {
  +            int index = attrList.getFirstAttr(fAttrListHandle);
  +            while (index != -1) {
  +                int attName = attrList.getAttrName(index);
  +                if (!fStringPool.equalNames(attName, fNamespacesPrefix)) {
  +                    int attPrefix = attrList.getAttrPrefix(index);
  +                    if (attPrefix != fNamespacesPrefix) {
  +                        if (attPrefix != -1) {
  +                            int uri = fNamespacesScope.getNamespaceForPrefix(attPrefix);
  +                            if (uri == -1) {
  +                                Object[] args = { fStringPool.toString(attPrefix) };
  +                                fErrorReporter.reportError(fErrorReporter.getLocator(),
  +                                                           XMLMessages.XMLNS_DOMAIN,
  +                                                           XMLMessages.MSG_PREFIX_DECLARED,
  +                                                           XMLMessages.NC_PREFIX_DECLARED,
  +                                                           args,
  +                                                           XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
  +                            }
  +                            attrList.setAttrURI(index, uri);
  +                        }
  +                    }
  +                }
  +                index = attrList.getNextAttr(index);
  +            }
  +        }
  +
  +    } // bindNamespacesToElementAndAttributes(QName,XMLAttrList)
  +    
  +    void parseSchemaLocation(String schemaLocationStr, Hashtable locationUriPairs){
  +        if (locationUriPairs != null) {
  +            StringTokenizer tokenizer = new StringTokenizer(schemaLocationStr, " \n\t\r", false);
  +            int tokenTotal = tokenizer.countTokens();
  +            if (tokenTotal % 2 != 0 ) {
  +                // TO DO: report warning - malformed schemaLocation string
  +            }
  +            else {
  +                while (tokenizer.hasMoreTokens()) {
  +                    String uri = tokenizer.nextToken();
  +                    String location = tokenizer.nextToken();
  +
  +                    locationUriPairs.put(location, uri);
  +                }
  +            }
  +        }
  +        else {
  +            // TO DO: should report internal error here
  +        }
  +
  +    }// parseSchemaLocaltion(String, Hashtable)
  +    private void resolveSchemaGrammar( String loc, String uri) {
  +
  +        DOMParser parser = new DOMParser() {
  +            public void ignorableWhitespace(char ch[], int start, int length) {}
  +            public void ignorableWhitespace(int dataIdx) {}
  +        };
  +        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( fEntityHandler.expandSystemId(loc) );
  +        }catch( IOException e ) {
  +            e.printStackTrace();
  +        }catch( SAXException e ) {
  +            e.printStackTrace();
  +        }
  +
  +        Document     document   = parser.getDocument(); //Our Grammar
  +
  +        TraverseSchema tst = null;
  +        try {
  +            if (DEBUG_SCHEMA_VALIDATION) {
  +                System.out.println("I am geting the Schema Document");
  +            }
  +
  +            Element root   = document.getDocumentElement();// This is what we pass to TraverserSchema
  +            if (uri == null || !uri.equals(root.getAttribute(SchemaSymbols.ATT_TARGETNAMESPACE)) ) {
  +                //TO DO : report error here
  +                System.out.println("Schema in " + loc + " has a different target namespace " + 
  +                                   "from the one specified in the instance document :" + uri); 
  +            }
  +            if (fGrammar == null) {
  +                fGrammar = new SchemaGrammar();
  +            }
  +            tst = new TraverseSchema( root, fStringPool, (SchemaGrammar)fGrammar, fGrammarResolver, fErrorReporter);
  +        }
  +        catch (Exception e) {
  +            e.printStackTrace(System.err);
  +        }
  +
  +    }
  +
  +    private void resolveSchemaGrammar(String uri){
  +
  +        resolveSchemaGrammar(uri, uri);
  +
  +    }
  +
  +    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)  {
  +        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
  +    }
  +
  +
  +        /** Validates element and attributes. */
  +    private void validateElementAndAttributes(QName element, 
  +                                              XMLAttrList attrList) 
  +        throws Exception {
  +
  +                //****DEBUG****
  +                if (DEBUG) print("(VAL) XMLValidator.validateElementAndAttributes: " + param("elementType",element.rawname) + " !!!!\n");
  +                //****DEBUG****
  +
  +        if (fGrammar == null && 
  +            !fValidating && !fNamespacesEnabled) {
  +            fCurrentElementIndex = -1;
  +            fCurrentContentSpecType = -1;
  +            fInElementContent = false;
  +            if (fAttrListHandle != -1) {
  +                fAttrList.endAttrList();
  +                int index = fAttrList.getFirstAttr(fAttrListHandle);
  +                while (index != -1) {
  +                    if (fStringPool.equalNames(fAttrList.getAttrName(index), fXMLLang)) {
  +                        fDocumentScanner.checkXMLLangAttributeValue(fAttrList.getAttValue(index));
  +                        break;
  +                    }
  +                    index = fAttrList.getNextAttr(index);
  +                }
  +            }
  +            return;
  +        }
  +        
  +        int elementIndex = -1;
  +
  +        //REVISIT, is it possible, fValidating is false and fGrammar is no null.???
  +        if ( fGrammar != null ){
  +            if (DEBUG_SCHEMA_VALIDATION) {
  +                System.out.println("localpart: '" + fStringPool.toString(element.localpart)
  +                                   +"' and scope : " + fCurrentScope);
  +            }
  +
  +            if (element.uri == -1) {
  +                elementIndex = fGrammar.getElementDeclIndex(element.localpart,fCurrentScope);
  +            }
  +            else {
  +                elementIndex = fGrammar.getElementDeclIndex(element.localpart, TOP_LEVEL_SCOPE);
  +            }
  +
  +            if (elementIndex == -1) {
  +                // if validating based on a Schema, try to resolve the element again by look it up in its ancestor types
  +                if (fGrammar instanceof SchemaGrammar && fCurrentElementIndex != -1) {
  +                    TraverseSchema.ComplexTypeInfo baseTypeInfo = null;
  +                    baseTypeInfo = ((SchemaGrammar)fGrammar).getElementComplexTypeInfo(fCurrentElementIndex);
  +                    while (baseTypeInfo != null) {
  +                        elementIndex = fGrammar.getElementDeclIndex(element.localpart, baseTypeInfo.scopeDefined);
  +                        if (elementIndex > -1 ) {
  +                            break;
  +                        }
  +                        baseTypeInfo = baseTypeInfo.baseComplexTypeInfo;
  +
  +                    }
  +                }
  +                /****/
  +                if (elementIndex == -1)
  +                    if (DEBUG_SCHEMA_VALIDATION)
  +                        System.out.println("!!! can not find elementDecl in the grammar, " +
  +                                       " the element localpart: " + element.localpart+"["+fStringPool.toString(element.localpart) +"]" +
  +                                       " the element uri: " + element.uri+"["+fStringPool.toString(element.uri) +"]" +
  +                                       " and the current enclosing scope: " + fCurrentScope );
  +                /****/
  +            }
  +
  +            if (DEBUG_SCHEMA_VALIDATION) {
  +                fGrammar.getElementDecl(elementIndex, fTempElementDecl);
  +                System.out.println("elementIndex: " + elementIndex+" \n and itsName : '" 
  +                                   + fStringPool.toString(fTempElementDecl.name.localpart)
  +                                   +"' \n its ContentType:" + fStringPool.toString(fTempElementDecl.type)
  +                                   +"\n its ContentSpecIndex : " + fTempElementDecl.contentSpecIndex +"\n");
  +            }
  +        }
  +
  +        //       here need to check if we need to switch Grammar by asking SchemaGrammar whether 
  +        //       this element actually is of a type in another Schema.
  +        if (fGrammar instanceof SchemaGrammar && elementIndex != -1) {
  +            String anotherSchemaURI = ((SchemaGrammar)fGrammar).getElementFromAnotherSchemaURI(elementIndex);
  +            if (anotherSchemaURI != null) {
  +                fCurrentSchemaURI = fStringPool.addSymbol(anotherSchemaURI);
  +                switchGrammar(fCurrentSchemaURI);
  +            }
  +        }
  +
  +        int contentSpecType =  getContentSpecType(elementIndex);
  +        if (contentSpecType == -1 && fValidating) {
  +            reportRecoverableXMLError(XMLMessages.MSG_ELEMENT_NOT_DECLARED,
  +                                      XMLMessages.VC_ELEMENT_VALID,
  +                                      element.rawname);
  +        }
  +        if (fGrammar != null && elementIndex != -1) {
  +            //REVISIT: broken
  +            fAttrListHandle = addDefaultAttributes(elementIndex, attrList, fAttrListHandle, fValidating, fStandaloneReader != -1);
  +        }
  +        if (fAttrListHandle != -1) {
  +            fAttrList.endAttrList();
  +        }
  +
  +        if (DEBUG_PRINT_ATTRIBUTES) {
  +            String elementStr = fStringPool.toString(element.rawname);
  +            System.out.print("startElement: <" + elementStr);
  +            if (fAttrListHandle != -1) {
  +                int index = attrList.getFirstAttr(fAttrListHandle);
  +                while (index != -1) {
  +                    System.out.print(" " + fStringPool.toString(attrList.getAttrName(index)) + "=\"" +
  +                            fStringPool.toString(attrList.getAttValue(index)) + "\"");
  +                    index = attrList.getNextAttr(index);
  +                }
  +            }
  +            System.out.println(">");
  +        }
  +        // REVISIT: Validation. Do we need to recheck for the xml:lang
  +        //          attribute? It was already checked above -- perhaps
  +        //          this is to check values that are defaulted in? If
  +        //          so, this check could move to the attribute decl
  +        //          callback so we can check the default value before
  +        //          it is used.
  +        if (fAttrListHandle != -1) {
  +            int index = fAttrList.getFirstAttr(fAttrListHandle);
  +            while (index != -1) {
  +                int attrNameIndex = attrList.getAttrName(index);
  +
  +                if (fStringPool.equalNames(attrNameIndex, fXMLLang)) {
  +                    fDocumentScanner.checkXMLLangAttributeValue(attrList.getAttValue(index));
  +                    // break;
  +                }
  +                // here, we validate every "user-defined" attributes
  +                int _xmlns = fStringPool.addSymbol("xmlns");
  +                if (attrNameIndex != _xmlns && attrList.getAttrPrefix(index) != _xmlns) 
  +                if (fValidating) {
  +                    fAttrNameLocator = getLocatorImpl(fAttrNameLocator);
  +                    fTempQName.setValues(attrList.getAttrPrefix(index), 
  +                                         attrList.getAttrLocalpart(index),
  +                                         attrList.getAttrName(index),
  +                                         attrList.getAttrURI(index) );
  +                    int attDefIndex = getAttDef(element, fTempQName);
  +                    if (fTempQName.uri != fXsiURI)
  +                    if (attDefIndex == -1) {
  +                        // REVISIT - cache the elem/attr tuple so that we only give
  +                        //  this error once for each unique occurrence
  +                        Object[] args = { fStringPool.toString(element.rawname),
  +                                          fStringPool.toString(attrList.getAttrName(index)) };
  +                        System.out.println("[Error] attribute " + fStringPool.toString(attrList.getAttrName(index))
  +                                           + " not found in element type " + fStringPool.toString(element.rawname));
  +
  +                        /*****/
  +                        fErrorReporter.reportError(fAttrNameLocator,
  +                                                   XMLMessages.XML_DOMAIN,
  +                                                   XMLMessages.MSG_ATTRIBUTE_NOT_DECLARED,
  +                                                   XMLMessages.VC_ATTRIBUTE_VALUE_TYPE,
  +                                                   args,
  +                                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
  +                        /******/   
  +
  +                    }
  +                    else  {
  +
  +                        fGrammar.getAttributeDecl(attDefIndex, fTempAttDecl); 
  +
  +                        //TO DO: special handling needed here for IDs IDrefs, ENTITIES, ?NOTations
  +
  +                        if (fGrammar instanceof DTDGrammar && 
  +                            (fTempAttDecl.type == XMLAttributeDecl.TYPE_ENTITY ||
  +                            fTempAttDecl.type == XMLAttributeDecl.TYPE_ENUMERATION ||
  +                            fTempAttDecl.type == XMLAttributeDecl.TYPE_ID ||
  +                            fTempAttDecl.type == XMLAttributeDecl.TYPE_IDREF ||
  +                            fTempAttDecl.type == XMLAttributeDecl.TYPE_NMTOKEN ||
  +                            fTempAttDecl.type == XMLAttributeDecl.TYPE_NOTATION)
  +                            ) {
  +
  +                            validateDTDattribute(element, attrList.getAttValue(index), fTempAttDecl);
  +                        }
  +
  +                        if (fTempAttDecl.datatypeValidator == null) {
  +                            Object[] args = { fStringPool.toString(element.rawname),
  +                                              fStringPool.toString(attrList.getAttrName(index)) };
  +                            System.out.println("[Error] Datatypevalidator for attribute " + fStringPool.toString(attrList.getAttrName(index))
  +                                               + " not found in element type " + fStringPool.toString(element.rawname));
  +                            //REVISIT : is this the right message?
  +                              /****/
  +                            fErrorReporter.reportError(fAttrNameLocator,    
  +                                                   XMLMessages.XML_DOMAIN,
  +                                                   XMLMessages.MSG_ATTRIBUTE_NOT_DECLARED,
  +                                                   XMLMessages.VC_ATTRIBUTE_VALUE_TYPE,
  +                                                   args,
  +                                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
  +                             /****/   
  +                        }
  +                        else{
  +                            fTempAttDecl.datatypeValidator.validate(fStringPool.toString(attrList.getAttValue(index)) );
  +                        }
  +                    }
  +                }
  +                index = fAttrList.getNextAttr(index);
  +            }
  +        }
  +        if (fAttrListHandle != -1) {
  +            int index = attrList.getFirstAttr(fAttrListHandle);
  +            while (index != -1) {
  +                int attName = attrList.getAttrName(index);
  +                if (!fStringPool.equalNames(attName, fNamespacesPrefix)) {
  +                    int attPrefix = attrList.getAttrPrefix(index);
  +                    if (attPrefix != fNamespacesPrefix) {
  +                        if (attPrefix != -1) {
  +                            int uri = fNamespacesScope.getNamespaceForPrefix(attPrefix);
  +                            if (uri == -1) {
  +                                Object[] args = { fStringPool.toString(attPrefix) };
  +                                fErrorReporter.reportError(fErrorReporter.getLocator(),
  +                                                           XMLMessages.XMLNS_DOMAIN,
  +                                                           XMLMessages.MSG_PREFIX_DECLARED,
  +                                                           XMLMessages.NC_PREFIX_DECLARED,
  +                                                           args,
  +                                                           XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
  +                            }
  +                            attrList.setAttrURI(index, uri);
  +                        }
  +                    }
  +                }
  +                index = attrList.getNextAttr(index);
  +            }
  +        }
  +
  +        fCurrentElementIndex = elementIndex;
  +        fCurrentContentSpecType = contentSpecType;
  +
  +        if (fValidating && contentSpecType == fDATATYPESymbol) {
  +            fBufferDatatype = true;
  +            fDatatypeBuffer.setLength(0);
  +        }
  +        
  +        fInElementContent = (contentSpecType == fCHILDRENSymbol);
  +
  +    } // validateElementAndAttributes(QName,XMLAttrList)
  +
  +
  +    //validate attributes in DTD fashion
  +    private void validateDTDattribute(QName element, int attValue, 
  +                                      XMLAttributeDecl attributeDecl) throws Exception{
  +        AttributeValidator av = null;
  +        switch (attributeDecl.type) {
  +        case XMLAttributeDecl.TYPE_ENTITY:
  +            if (attributeDecl.list) {
  +                av = fAttValidatorENTITIES;
  +            }
  +            else {
  +                av = fAttValidatorENTITY;
  +            }
  +            break;
  +        case XMLAttributeDecl.TYPE_ENUMERATION:
  +                av = fAttValidatorENUMERATION;
  +                break;
  +        case XMLAttributeDecl.TYPE_ID:
  +            av = fAttValidatorID;
  +            break;
  +        case XMLAttributeDecl.TYPE_IDREF:
  +            if (attributeDecl.list) {
  +                av = fAttValidatorIDREFS;
  +            }
  +            else {
  +                av = fAttValidatorIDREF;
  +            }
  +            break;
  +        case XMLAttributeDecl.TYPE_NOTATION:
  +            av = fAttValidatorNOTATION;
  +            break;
  +        case XMLAttributeDecl.TYPE_NMTOKEN:
  +            if (attributeDecl.list) {
  +                av = fAttValidatorNMTOKENS;
  +            }
  +            else {
  +                av = fAttValidatorNMTOKEN;
  +            }
  +            break;
  +        }
  +
  +        av.normalize(element, attributeDecl.name, attValue, 
  +                     attributeDecl.type, attributeDecl.enumeration);
  +    }
  +
  +    /** Character data in content. */
  +    private void charDataInContent() {
  +
  +                //****DEBUG****
  +                if (DEBUG) print("(???) XMLValidator.charDataInContent\n");
  +                //****DEBUG****
  +
  +        QName[] children = fElementChildren[fElementDepth];
  +        int childCount = fElementChildCount[fElementDepth];
  +        try {
  +            children[childCount].localpart = -1;
  +        } 
  +        catch (NullPointerException ex) {
  +            children = fElementChildren[fElementDepth] = new QName[256];
  +            for (int i=0; i<256; i++) {
  +                children[i] = new QName();
  +            }
  +            childCount = 0; // should really assert this...
  +            children[childCount].localpart = -1;
  +        } 
  +        catch (ArrayIndexOutOfBoundsException ex) {
  +            QName[] newChildren = new QName[childCount * 2];
  +            for (int i=0; i<childCount*2; i++) {
  +                children[i] = new QName();
  +            }
  +            System.arraycopy(children, 0, newChildren, 0, childCount);
  +            children = fElementChildren[fElementDepth] = newChildren;
  +            children[childCount].localpart = -1;
  +        }
  +        fElementChildCount[fElementDepth] = ++childCount;
  +
  +    } // charDataInCount()
  +
  +    /** Peek child count. */
  +    private int peekChildCount() {
  +
  +                //****DEBUG****
  +                if (DEBUG) print("(???) XMLValidator.peekChildCount\n");
  +                //****DEBUG****
  +
  +        return fElementChildCount[fElementDepth];
  +    }
  +
  +    /** Peek children. */
  +    private QName[] peekChildren() {
  +
  +                //****DEBUG****
  +                if (DEBUG) print("(???) XMLValidator.peekChildren\n");
  +                //****DEBUG****
  +
  +        return fElementChildren[fElementDepth];
  +    }
  +
  +    /**
  +     * Check that the content of an element is valid.
  +     * <p>
  +     * This is the method of primary concern to the validator. This method is called
  +     * upon the scanner reaching the end tag of an element. At that time, the
  +     * element's children must be structurally validated, so it calls this method.
  +     * The index of the element being checked (in the decl pool), is provided as
  +     * well as an array of element name indexes of the children. The validator must
  +     * confirm that this element can have these children in this order.
  +     * <p>
  +     * This can also be called to do 'what if' testing of content models just to see
  +     * if they would be valid.
  +     * <p>
  +     * Note that the element index is an index into the element decl pool, whereas
  +     * the children indexes are name indexes, i.e. into the string pool.
  +     * <p>
  +     * A value of -1 in the children array indicates a PCDATA node. All other
  +     * indexes will be positive and represent child elements. The count can be
  +     * zero, since some elements have the EMPTY content model and that must be
  +     * confirmed.
  +     *
  +     * @param elementIndex The index within the <code>ElementDeclPool</code> of this
  +     *                     element.
  +     * @param childCount The number of entries in the <code>children</code> array.
  +     * @param children The children of this element.  Each integer is an index within
  +     *                 the <code>StringPool</code> of the child element name.  An index
  +     *                 of -1 is used to indicate an occurrence of non-whitespace character
  +     *                 data.
  +     *
  +     * @return The value -1 if fully valid, else the 0 based index of the child
  +     *         that first failed. If the value returned is equal to the number
  +     *         of children, then additional content is required to reach a valid
  +     *         ending state.
  +     *
  +     * @exception Exception Thrown on error.
  +     */
  +    private int checkContent(int elementIndex, 
  +                             int childCount, QName[] children) throws Exception {
  +
  +                //****DEBUG****
  +                if (DEBUG) print("(VAL) XMLValidator.checkContent: " + param("elementIndex",elementIndex) + "... \n");
  +                //****DEBUG****
  +
  +        // Get the element name index from the element
  +        // REVISIT: Validation
  +        final int elementType = fCurrentElement.rawname;
  +
  +        if (DEBUG_PRINT_CONTENT) {
  +            String strTmp = fStringPool.toString(elementType);
  +            System.out.println("Name: "+strTmp+", "+
  +                               "Count: "+childCount+", "+
  +                               "ContentSpecType: " +fCurrentContentSpecType); //+getContentSpecAsString(elementIndex));
  +            for (int index = 0; index < childCount && index < 10; index++) {
  +                if (index == 0) {
  +                    System.out.print("  (");
  +                }
  +                String childName = (children[index].localpart == -1) ? "#PCDATA" : fStringPool.toString(children[index].localpart);
  +                if (index + 1 == childCount) {
  +                    System.out.println(childName + ")");
  +                }
  +                else if (index + 1 == 10) {
  +                    System.out.println(childName + ",...)");
  +                }
  +                else {
  +                    System.out.print(childName + ",");
  +                }
  +            }
  +        }
  +
  +        // Get out the content spec for this element
  +        final int contentType = fCurrentContentSpecType;
  +
  +// debugging
  +//System.out.println("~~~~~~in checkContent, fCurrentContentSpecType : " + fCurrentContentSpecType);
  +
  +        //
  +        //  Deal with the possible types of content. We try to optimized here
  +        //  by dealing specially with content models that don't require the
  +        //  full DFA treatment.
  +        //
  +        if (contentType == XMLElementDecl.TYPE_EMPTY) {
  +            //
  +            //  If the child count is greater than zero, then this is
  +            //  an error right off the bat at index 0.
  +            //
  +            if (childCount != 0) {
  +                return 0;
  +            }
  +        }
  +        else if (contentType == XMLElementDecl.TYPE_ANY) {
  +            //
  +            //  This one is open game so we don't pass any judgement on it
  +            //  at all. Its assumed to fine since it can hold anything.
  +            //
  +        }
  +        else if (contentType == XMLElementDecl.TYPE_MIXED ||  
  +                 contentType == XMLElementDecl.TYPE_CHILDREN) {
  +            // Get the content model for this element, faulting it in if needed
  +            XMLContentModel cmElem = null;
  +            try {
  +                cmElem = getContentModel(elementIndex);
  +                return cmElem.validateContent(childCount, children);
  +            }
  +            catch(CMException excToCatch) {
  +                // REVISIT - Translate the caught exception to the protected error API
  +                int majorCode = excToCatch.getErrorCode();
  +                fErrorReporter.reportError(fErrorReporter.getLocator(),
  +                                           ImplementationMessages.XERCES_IMPLEMENTATION_DOMAIN,
  +                                           majorCode,
  +                                           0,
  +                                           null,
  +                                           XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
  +            }
  +        }
  +        else if (contentType == -1) {
  +            reportRecoverableXMLError(XMLMessages.MSG_ELEMENT_NOT_DECLARED,
  +                                      XMLMessages.VC_ELEMENT_VALID,
  +                                      elementType);
  +        }
  +        else if (contentType == XMLElementDecl.TYPE_SIMPLE ) {
   
  -    private void setContentModel(int elementIndex, XMLContentModel cm) {
  -        if (elementIndex < 0 || elementIndex >= fElementCount)
  -            return;
  -        int chunk = elementIndex >> CHUNK_SHIFT;
  -        int index = elementIndex & CHUNK_MASK;
  -        fContentModel[chunk][index] = cm;
  -    }
  +            XMLContentModel cmElem = null;
  +            try {
  +                // REVISIT: this might not be right
  +                //cmElem = getContentModel(elementIndex);
  +                //fTempQName.rawname = fTempQName.localpart = fStringPool.addString(fDatatypeBuffer.toString());
  +                //return cmElem.validateContent(1, new QName[] { fTempQName });
  +                fGrammar.getElementDecl(elementIndex, fTempElementDecl);
  +
  +                DatatypeValidator dv = fTempElementDecl.datatypeValidator;
  +                if (dv == null) {
  +                    System.out.println("Internal Error: this element have a simpletype "+
  +                                       "but no datatypevalidator was found, element "+fTempElementDecl.name);
  +                }
  +                else {
  +                    dv.validate(fDatatypeBuffer.toString());
  +                }
   
  -    
  -	//
  -    // contentspec entries
  -    //
  -    
  -	private boolean ensureNodeCapacity(int chunk) {
  -        try {
  -            return fNodeType[chunk][0] == 0;
  -        } catch (ArrayIndexOutOfBoundsException ex) {
  -            byte[][] newByteArray = new byte[chunk * 2][];
  -            System.arraycopy(fNodeType, 0, newByteArray, 0, chunk);
  -            fNodeType = newByteArray;
  -            int[][] newIntArray = new int[chunk * 2][];
  -            System.arraycopy(fNodeValue, 0, newIntArray, 0, chunk);
  -            fNodeValue = newIntArray;
  -        } catch (NullPointerException ex) {
  +            } 
  +            //catch (CMException cme) {
  +              //  System.out.println("Internal Error in datatype validation");
  +            //} 
  +            catch (InvalidDatatypeValueException idve) {
  +                fErrorReporter.reportError(fErrorReporter.getLocator(),
  +                                           SchemaMessageProvider.SCHEMA_DOMAIN,
  +                                           SchemaMessageProvider.DatatypeError,
  +                                           SchemaMessageProvider.MSG_NONE,
  +                                           new Object [] { idve.getMessage() },
  +                                           XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
  +            }
  +            /*
  +            boolean DEBUG_DATATYPES = false;
  +            if (DEBUG_DATATYPES) {
  +                System.out.println("Checking content of datatype");
  +                String strTmp = fStringPool.toString(elementTypeIndex);
  +                int contentSpecIndex = fElementDeclPool.getContentSpec(elementIndex);
  +                XMLContentSpec csn = new XMLContentSpec();
  +                fElementDeclPool.getContentSpecNode(contentSpecIndex, csn);
  +                String contentSpecString = fStringPool.toString(csn.value);
  +                System.out.println
  +                (
  +                    "Name: "
  +                    + strTmp
  +                    + ", Count: "
  +                    + childCount
  +                    + ", ContentSpec: "
  +                    + contentSpecString
  +                );
  +                for (int index = 0; index < childCount && index < 10; index++) {
  +                    if (index == 0) System.out.print("  (");
  +                    String childName = (children[index] == -1) ? "#PCDATA" : fStringPool.toString(children[index]);
  +                    if (index + 1 == childCount)
  +                        System.out.println(childName + ")");
  +                    else if (index + 1 == 10)
  +                        System.out.println(childName + ",...)");
  +                    else
  +                        System.out.print(childName + ",");
  +                }
  +            }
  +            try { // REVISIT - integrate w/ error handling
  +                int contentSpecIndex = fElementDeclPool.getContentSpec(elementIndex);
  +                XMLContentSpec csn = new XMLContentSpec();
  +                fElementDeclPool.getContentSpecNode(contentSpecIndex, csn);
  +                String type = fStringPool.toString(csn.value);
  +                DatatypeValidator v = fDatatypeRegistry.getValidatorFor(type);
  +                if (v != null)
  +                    v.validate(fDatatypeBuffer.toString());
  +                else
  +                    System.out.println("No validator for datatype "+type);
  +            } catch (InvalidDatatypeValueException idve) {
  +                System.out.println("Incorrect datatype: "+idve.getMessage());
  +            } catch (Exception e) {
  +                e.printStackTrace();
  +                System.out.println("Internal error in datatype validation");
  +            }
  +            */
           }
  -        fNodeType[chunk] = new byte[CHUNK_SIZE];
  -        fNodeValue[chunk] = new int[CHUNK_SIZE];
  -        return true;
  -    }
  +        else {
  +            fErrorReporter.reportError(fErrorReporter.getLocator(),
  +                                       ImplementationMessages.XERCES_IMPLEMENTATION_DOMAIN,
  +                                       ImplementationMessages.VAL_CST,
  +                                       0,
  +                                       null,
  +                                       XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
  +        }
   
  +        // We succeeded
  +        return -1;
   
  -    //
  -    // addContentSpecLeafNode
  -    //
  +    } // checkContent(int,int,int[]):int
   
  -    private int addContentSpecLeafNode(int nodeValue) throws Exception {
  +    /**
  +     * Check that all ID references were to ID attributes present in the document.
  +     * <p>
  +     * This method is a convenience call that allows the validator to do any id ref
  +     * checks above and beyond those done by the scanner. The scanner does the checks
  +     * specificied in the XML spec, i.e. that ID refs refer to ids which were
  +     * eventually defined somewhere in the document.
  +     * <p>
  +     * If the validator is for a Schema perhaps, which defines id semantics beyond
  +     * those of the XML specificiation, this is where that extra checking would be
  +     * done. For most validators, this is a no-op.
  +     *
  +     * @exception Exception Thrown on error.
  +     */
  +    private void checkIdRefs() throws Exception {
   
  -		//****DEBUG****
  -		if (DEBUG) print("(POP) XMLValidator.addContentSpecLeafNode: " + param("nodeValue",nodeValue) + "\n");
  -		//****DEBUG****
  +                //****DEBUG****
  +                if (DEBUG) print("(???) XMLValidator.checkIdRefs\n");
  +                //****DEBUG****
   
  -        //
  -        // Check that we have not seen this value before...
  -        //
  -        if (nodeValue != -1) {
  -            int nodeCount = fNodeCount;
  -            int chunk = fNodeCount >> CHUNK_SHIFT;
  -            int index = fNodeCount & CHUNK_MASK;
  -            while (true) {
  -                if (index-- == 0) {
  -                    index = CHUNK_SIZE - 1;
  -                    chunk--;
  -                }
  -                int nodeType = fNodeType[chunk][index];
  -                if (nodeType == XMLContentSpec.CONTENTSPECNODE_LEAF) {
  -                    int otherNodeValue = fNodeValue[chunk][index];
  -                    if (otherNodeValue == -1)
  -                        break;
  -                    if (otherNodeValue == nodeValue) {
  -                        return -1;
  -                    }
  -                }
  +        if (fIdRefs == null)
  +            return;
  +        Enumeration en = fIdRefs.keys();
  +        while (en.hasMoreElements()) {
  +            Integer key = (Integer)en.nextElement();
  +            if (fIdDefs == null || !fIdDefs.containsKey(key)) {
  +                Object[] args = { fStringPool.toString(key.intValue()) };
  +                fErrorReporter.reportError(fErrorReporter.getLocator(),
  +                                           XMLMessages.XML_DOMAIN,
  +                                           XMLMessages.MSG_ELEMENT_WITH_ID_REQUIRED,
  +                                           XMLMessages.VC_IDREF,
  +                                           args,
  +                                           XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
               }
           }
  -        int chunk = fNodeCount >> CHUNK_SHIFT;
  -        int index = fNodeCount & CHUNK_MASK;
  -        ensureNodeCapacity(chunk);
  -        fNodeType[chunk][index] = (byte)XMLContentSpec.CONTENTSPECNODE_LEAF;
  -        fNodeValue[chunk][index] = nodeValue;
  -        return fNodeCount++;
  -    }
  -
   
  -    //
  -    // addContentSpecNode
  -    //
  +    } // checkIdRefs()
   
  -    public int addContentSpecNode(int nodeType, int nodeValue, int otherNodeValue, boolean mustBeUnique) throws Exception {
  +    /** 
  +     * Checks that all declared elements refer to declared elements
  +     * in their content models. This method calls out to the error
  +     * handler to indicate warnings.
  +     */
  +    /*private void checkDeclaredElements() throws Exception {
   
  -		//****DEBUG****
  -		if (DEBUG) print("(POP) XMLValidator.addContentSpecNode: " + param("nodeType",nodeType) + param("nodeValue",nodeValue) + "\n");
  -		//****DEBUG****
  +                //****DEBUG****
  +                if (DEBUG) print("(???) XMLValidator.checkDeclaredElements\n");
  +                //****DEBUG****
   
  -        if (mustBeUnique) // REVISIT - merge these methods...
  -            return addContentSpecLeafNode(nodeValue);
  -        int chunk = fNodeCount >> CHUNK_SHIFT;
  -        int index = fNodeCount & CHUNK_MASK;
  -        ensureNodeCapacity(chunk);
  -        switch (nodeType) {
  -        case XMLContentSpec.CONTENTSPECNODE_LEAF:
  -        case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE:
  -        case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE:
  -        case XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE:
  -            fNodeType[chunk][index] = (byte)nodeType;
  -            fNodeValue[chunk][index] = nodeValue;
  -            return fNodeCount++;
  -        case XMLContentSpec.CONTENTSPECNODE_CHOICE:
  -        case XMLContentSpec.CONTENTSPECNODE_SEQ:
  -            fNodeType[chunk][index] = (byte)nodeType;
  -            fNodeValue[chunk][index] = nodeValue;
  -            int nodeIndex = fNodeCount++;
  -            if (++index == CHUNK_SIZE) {
  -                chunk++;
  -                ensureNodeCapacity(chunk);
  -                index = 0;
  +        for (int i = 0; i < fElementCount; i++) {
  +            int type = fGrammar.getContentSpecType(i);
  +            if (type == fMIXEDSymbol || type == fCHILDRENSymbol) {
  +                int chunk = i >> CHUNK_SHIFT;
  +                int index = i &  CHUNK_MASK;
  +                int contentSpecIndex = fContentSpec[chunk][index];
  +                checkDeclaredElements(i, contentSpecIndex);
               }
  -            fNodeType[chunk][index] = (byte)(nodeType | 64); // flag second entry for consistancy checking
  -            fNodeValue[chunk][index] = otherNodeValue;
  -            fNodeCount++;
  -            return nodeIndex;
  -        default:
  -            return -1;
           }
  -    }
   
  -    //
  -    // Protected for access by ContentSpecImpl
  -    //
  -
  -    protected void getContentSpecNode(int contentSpecIndex, XMLContentSpec.Node csn) {
  -        int chunk = contentSpecIndex >> CHUNK_SHIFT;
  -        int index = contentSpecIndex & CHUNK_MASK;
  -        csn.type = fNodeType[chunk][index];
  -        csn.value = fNodeValue[chunk][index];
  -        if (csn.type == XMLContentSpec.CONTENTSPECNODE_CHOICE || csn.type == XMLContentSpec.CONTENTSPECNODE_SEQ) {
  -            if (++index == CHUNK_SIZE) {
  -                chunk++;
  -                index = 0;
  -            }
  -            csn.otherValue = fNodeValue[chunk][index];
  -        } else
  -            csn.otherValue = -1;
  -    }
  +    } // checkUndeclaredElements()
  +    */
  +    /** 
  +     * Does a recursive (if necessary) check on the specified element's
  +     * content spec to make sure that all children refer to declared
  +     * elements.
  +     * <p>
  +     * This method assumes that it will only be called when there is
  +     * a validation handler.
  +     */
  +    /*
  +    private void checkDeclaredElements(int elementIndex, 
  +                                       int contentSpecIndex) throws Exception {
  +        
  +                //****DEBUG****
  +                if (DEBUG) print("(???) XMLValidator.checkDeclaredElements\n");
  +                //****DEBUG****
   
  -    public String contentSpecNodeAsString(int contentSpecIndex) {
  +        // get spec type and value
           int chunk = contentSpecIndex >> CHUNK_SHIFT;
  -        int index = contentSpecIndex & CHUNK_MASK;
  -        int type = fNodeType[chunk][index];
  +        int index = contentSpecIndex &  CHUNK_MASK;
  +        int type  = fNodeType[chunk][index];
           int value = fNodeValue[chunk][index];
  -        StringBuffer sb = new StringBuffer();
  -        switch (type) {
  -        case XMLContentSpec.CONTENTSPECNODE_LEAF:
  -            sb.append("(" + (value == -1 ? "#PCDATA" : fStringPool.toString(value)) + ")");
  -            break;
  -        case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE:
  -            chunk = value >> CHUNK_SHIFT;
  -            index = value & CHUNK_MASK;
  -            if (fNodeType[chunk][index] == XMLContentSpec.CONTENTSPECNODE_LEAF) {
  -                value = fNodeValue[chunk][index];
  -                sb.append("(" + (value == -1 ? "#PCDATA" : fStringPool.toString(value)) + ")?");
  -            } else
  -                appendContentSpecNode(contentSpecIndex, sb, false);
  -            break;
  -        case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE:
  -            chunk = value >> CHUNK_SHIFT;
  -            index = value & CHUNK_MASK;
  -            if (fNodeType[chunk][index] == XMLContentSpec.CONTENTSPECNODE_LEAF) {
  -                value = fNodeValue[chunk][index];
  -                sb.append("(" + (value == -1 ? "#PCDATA" : fStringPool.toString(value)) + ")*");
  -            } else
  -                appendContentSpecNode(contentSpecIndex, sb, false);
  -            break;
  -        case XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE:
  -            chunk = value >> CHUNK_SHIFT;
  -            index = value & CHUNK_MASK;
  -            if (fNodeType[chunk][index] == XMLContentSpec.CONTENTSPECNODE_LEAF) {
  -                value = fNodeValue[chunk][index];
  -                sb.append("(" + (value == -1 ? "#PCDATA" : fStringPool.toString(value)) + ")+");
  -            } else
  -                appendContentSpecNode(contentSpecIndex, sb, false);
  -            break;
  -        case XMLContentSpec.CONTENTSPECNODE_CHOICE:
  -        case XMLContentSpec.CONTENTSPECNODE_SEQ:
  -            appendContentSpecNode(contentSpecIndex, sb, false);
  -            break;
  -        default:
  -            return null;
  -        }
  -        return sb.toString();
  -    }
  -
  -    private void appendContentSpecNode(int contentSpecIndex, StringBuffer sb, boolean noParen) {
   
  -		//****DEBUG****
  -		if (DEBUG) print("(POP) XMLValidator.appendContentSpecNode: ...\n");
  -		//****DEBUG****
  +        // temp vars
  +        // REVISIT: Validation. Use tuples.
  +        QName qname = new QName(-1, type, type);
   
  -        int chunk = contentSpecIndex >> CHUNK_SHIFT;
  -        int index = contentSpecIndex & CHUNK_MASK;
  -        int type = fNodeType[chunk][index];
  -        int value = fNodeValue[chunk][index];
  +        // handle type
           switch (type) {
  -        case XMLContentSpec.CONTENTSPECNODE_LEAF:
  -            sb.append(value == -1 ? "#PCDATA" : fStringPool.toString(value));
  -            return;
  -        case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE:
  -            appendContentSpecNode(value, sb, false);
  -            sb.append('?');
  -            return;
  -        case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE:
  -            appendContentSpecNode(value, sb, false);
  -            sb.append('*');
  -            return;
  -        case XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE:
  -            appendContentSpecNode(value, sb, false);
  -            sb.append('+');
  -            return;
  -        case XMLContentSpec.CONTENTSPECNODE_CHOICE:
  -        case XMLContentSpec.CONTENTSPECNODE_SEQ:
  -            if (!noParen)
  -                sb.append('(');
  -            int leftChunk = value >> CHUNK_SHIFT;
  -            int leftIndex = value & CHUNK_MASK;
  -            int leftType = fNodeType[leftChunk][leftIndex];
  -            appendContentSpecNode(value, sb, leftType == type);
  -            sb.append(type == XMLContentSpec.CONTENTSPECNODE_CHOICE ? '|' : ',');
  -            if (++index == CHUNK_SIZE) {
  -                chunk++;
  -                index = 0;
  +        
  +            // #PCDATA | element
  +            case XMLContentSpec.CONTENTSPECNODE_LEAF: {
  +                // perform check for declared element
  +                if (value != -1 && getDeclaration(qname) == -1) {
  +                    int elemChunk = elementIndex >> CHUNK_SHIFT;
  +                    int elemIndex = elementIndex &  CHUNK_MASK;
  +                    int elementType = fElementType[elemChunk][elemIndex];
  +                    Object[] args = { fStringPool.toString(elementType),
  +                                      fStringPool.toString(value) };
  +                    fErrorReporter.reportError(fErrorReporter.getLocator(),
  +                                               XMLMessages.XML_DOMAIN,
  +                                               XMLMessages.MSG_UNDECLARED_ELEMENT_IN_CONTENTSPEC,
  +                                               XMLMessages.P45_UNDECLARED_ELEMENT_IN_CONTENTSPEC,
  +                                               args,
  +                                               XMLErrorReporter.ERRORTYPE_WARNING);
  +                }
  +                break;
  +            }
  +
  +            // (...)? | (...)* | (...)+
  +            case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE:
  +            case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE: 
  +            case XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE: {
  +                checkDeclaredElements(elementIndex, value);
  +                break;
  +            }
  +
  +            // (... , ...) | (... | ...)
  +            case XMLContentSpec.CONTENTSPECNODE_CHOICE:
  +            case XMLContentSpec.CONTENTSPECNODE_SEQ: {
  +                checkDeclaredElements(elementIndex, value);
  +                if (++index == CHUNK_SIZE) {
  +                    chunk++;
  +                    index = 0;
  +                }
  +                checkDeclaredElements(elementIndex, fNodeValue[chunk][index]);
  +                break;
               }
  -            appendContentSpecNode(fNodeValue[chunk][index], sb, false);
  -            if (!noParen)
  -                sb.append(')');
  -            return;
  -        default:
  -            return;
           }
       }
  +    */
  +    // debugging
  +
  +    /** Returns the string value for a string pool index. */
  +        private String nameOf(int stringPoolIndex) {
  +                return fStringPool.toString(stringPoolIndex);
  +        }
  +
  +    /** Returns a contatenated name and its associated string pool value. */
  +        private String param(String name, int stringPoolIndex) {
  +                return name + "=\"" + fStringPool.toString(stringPoolIndex) + "\" ";
  +        }
   
  +    /** Prints a message to standard error. */
  +        private void print(String message) {
  +                if (this == schemaValidator ) {
  +                        System.err.println(message);
  +                }
  +        }
  +        
       //
  -    // attribute list interfaces
  +    // Interfaces
       //
  -    private boolean ensureAttrCapacity(int chunk) {
  -        try {
  -            return fAttName[chunk][0] == 0;
  -        } catch (ArrayIndexOutOfBoundsException ex) {
  -            byte[][] newByteArray = new byte[chunk * 2][];
  -            System.arraycopy(fAttDefIsExternal, 0, newByteArray, 0, chunk);
  -            fAttDefIsExternal = newByteArray;
  -            int[][] newIntArray = new int[chunk * 2][];
  -            System.arraycopy(fAttName, 0, newIntArray, 0, chunk);
  -            fAttName = newIntArray;
  -            newIntArray = new int[chunk * 2][];
  -            System.arraycopy(fAttType, 0, newIntArray, 0, chunk);
  -            fAttType = newIntArray;
  -            newIntArray = new int[chunk * 2][];
  -            System.arraycopy(fEnumeration, 0, newIntArray, 0, chunk);
  -            fEnumeration = newIntArray;
  -            newIntArray = new int[chunk * 2][];
  -            System.arraycopy(fAttDefaultType, 0, newIntArray, 0, chunk);
  -            fAttDefaultType = newIntArray;
  -            newIntArray = new int[chunk * 2][];
  -            System.arraycopy(fAttValue, 0, newIntArray, 0, chunk);
  -            fAttValue = newIntArray;
  -            newIntArray = new int[chunk * 2][];
  -            System.arraycopy(fNextAttDef, 0, newIntArray, 0, chunk);
  -            fNextAttDef = newIntArray;
  -            AttributeValidator[][] newValidatorArray = new AttributeValidator[chunk * 2][];
  -            System.arraycopy(fAttValidator, 0, newValidatorArray, 0, chunk);
  -            fAttValidator = newValidatorArray;
  -        } catch (NullPointerException ex) {
  -        }
  -        fAttDefIsExternal[chunk] = new byte[CHUNK_SIZE];
  -        fAttName[chunk] = new int[CHUNK_SIZE];
  -        fAttType[chunk] = new int[CHUNK_SIZE];
  -        fAttValidator[chunk] = new AttributeValidator[CHUNK_SIZE];
  -        fEnumeration[chunk] = new int[CHUNK_SIZE];
  -        fAttDefaultType[chunk] = new int[CHUNK_SIZE];
  -        fAttValue[chunk] = new int[CHUNK_SIZE];
  -        fNextAttDef[chunk] = new int[CHUNK_SIZE];
  -        return true;
  -    }
   
  +    /**
  +     * AttributeValidator.
  +     */
  +    public interface AttributeValidator {
  +
  +        //
  +        // AttributeValidator methods
  +        //
  +
  +        /** Normalize. */
  +        public int normalize(QName element, QName attribute, 
  +                             int attValue, int attType, int enumHandle) 
  +        throws Exception;
  +
  +    } // interface AttributeValidator
   
       //
  -	// addAttDef
  -	//
  +    // Classes
  +    //
  +
  +    /**
  +     * Content spec implementation. 
  +     */
  +    //final class ContentSpecImpl 
  +        //implements XMLContentSpec {
   
  -    public int addAttDef(int elementIndex, int attName, int attType, int enumeration, int attDefaultType, int attDefaultValue, boolean isExternal) throws Exception {
  +        //
  +        // Data
  +        //
  +
  +        /** String pool. */
  +        //protected StringPool fStringPool;
  +
  +        /** Handle. */
  +        //protected int fHandle;
   
  -		//****DEBUG****
  -		if (DEBUG) print("(POP) XMLValidator.addAttDef\n");
  -		//****DEBUG****
  +        /** Type. */
  +        //protected int fType;
   
           //
  -        // check fields
  +        // Public methods
           //
  -        int elemChunk = elementIndex >> CHUNK_SHIFT;
  -        int elemIndex = elementIndex & CHUNK_MASK;
  -        int attlistIndex = fAttlistHead[elemChunk][elemIndex];
  -        int dupID = -1;
  -        int dupNotation = -1;
  -        while (attlistIndex != -1) {
  -            int attrChunk = attlistIndex >> CHUNK_SHIFT;
  -            int attrIndex = attlistIndex & CHUNK_MASK;
  -            if (fStringPool.equalNames(fAttName[attrChunk][attrIndex], attName)) {
  -                if (fWarningOnDuplicateAttDef) {
  -                    Object[] args = { fStringPool.toString(fElementType[elemChunk][elemIndex]),
  -                                      fStringPool.toString(attName) };
  -                    fErrorReporter.reportError(fErrorReporter.getLocator(),
  -                                               XMLMessages.XML_DOMAIN,
  -                                               XMLMessages.MSG_DUPLICATE_ATTDEF,
  -                                               XMLMessages.P53_DUPLICATE,
  -                                               args,
  -                                               XMLErrorReporter.ERRORTYPE_WARNING);
  -                }
  -                return -1;
  -            }
  -            if (fValidating) {
  -                if (attType == fIDSymbol && fAttType[attrChunk][attrIndex] == fIDSymbol)
  -                    dupID = fAttName[attrChunk][attrIndex];
  -                if (attType == fNOTATIONSymbol && fAttType[attrChunk][attrIndex] == fNOTATIONSymbol)
  -                    dupNotation = fAttName[attrChunk][attrIndex];
  -            }
  -            attlistIndex = fNextAttDef[attrChunk][attrIndex];
  -        }
  -        if (fValidating) {
  -            if (dupID != -1) {
  -                Object[] args = { fStringPool.toString(fElementType[elemChunk][elemIndex]),
  -                                  fStringPool.toString(dupID),
  -                                  fStringPool.toString(attName) };
  -                fErrorReporter.reportError(fErrorReporter.getLocator(),
  -                                           XMLMessages.XML_DOMAIN,
  -                                           XMLMessages.MSG_MORE_THAN_ONE_ID_ATTRIBUTE,
  -                                           XMLMessages.VC_ONE_ID_PER_ELEMENT_TYPE,
  -                                           args,
  -                                           XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
  -                return -1;
  -            }
  -            if (dupNotation != -1) {
  -                Object[] args = { fStringPool.toString(fElementType[elemChunk][elemIndex]),
  -                                  fStringPool.toString(dupNotation),
  -                                  fStringPool.toString(attName) };
  -                fErrorReporter.reportError(fErrorReporter.getLocator(),
  -                                           XMLMessages.XML_DOMAIN,
  -                                           XMLMessages.MSG_MORE_THAN_ONE_NOTATION_ATTRIBUTE,
  -                                           XMLMessages.VC_ONE_NOTATION_PER_ELEMENT_TYPE,
  -                                           args,
  -                                           XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
  -                return -1;
  -            }
  +
  +        /** Returns the handle. */
  +        //public int getHandle() {
  +        //    return fHandle;
  +        //}
  +
  +        /** Returns the type. */
  +        //public int getType() {
  +        //    return fType;
  +        //}
  +
  +        /** 
  +         * Fills in the XMLContentSpec with the information
  +         * associated with the specified handle. 
  +         */
  +        //public void getNode(int handle, XMLContentSpec node) {
  +          //  getContentSpecNode(handle, node);
  +        //}
  +
  +        //
  +        // Object methods
  +        //
  +
  +        /** Returns a string representation of the object. */
  +        //public String toString() {
  +          //  if (fType == fMIXEDSymbol || fType == fCHILDRENSymbol)
  +        //        return contentSpecNodeAsString(fHandle);
  +        //    else
  +        //        return fStringPool.toString(fType);
  +       // }
  +
  +    //} // class ContentSpecImpl
  +
  +        /**
  +         * AttValidatorCDATA.
  +     */
  +    final class AttValidatorCDATA 
  +        implements AttributeValidator {
  +
  +        //
  +        // AttributeValidator methods
  +        //
  +
  +        /** Normalize. */
  +        public int normalize(QName element, QName attribute, 
  +                             int attValueHandle, int attType, 
  +                             int enumHandle) throws Exception {
  +            // Normalize attribute based upon attribute type...
  +            return attValueHandle;
           }
  +
  +    } // class AttValidatorCDATA
  +
  +        /**
  +     *  AttValidatorID.
  +     */
  +    final class AttValidatorID 
  +        implements AttributeValidator {
  +
           //
  -        // save the fields
  +        // AttributeValidator methods
           //
  -        int chunk = fAttDefCount >> CHUNK_SHIFT;
  -        int index = fAttDefCount & CHUNK_MASK;
  -        ensureAttrCapacity(chunk);
  -        fAttName[chunk][index] = attName;
  -        fAttType[chunk][index] = attType;
  -        fAttValidator[chunk][index] = getValidatorForAttType(attType);
  -        fEnumeration[chunk][index] = enumeration;
  -        fAttDefaultType[chunk][index] = attDefaultType;
  -        fAttDefIsExternal[chunk][index] = (byte)(isExternal ? 1 : 0);
  -        fAttValue[chunk][index] = attDefaultValue;
  +        
  +        /** Normalize. */
  +        
  +        public int normalize(QName element, QName attribute, 
  +                             int attValueHandle, int attType, 
  +                             int enumHandle) throws Exception {
  +            //
  +            // Normalize attribute based upon attribute type...
  +            //
  +            String attValue = fStringPool.toString(attValueHandle);
  +            String newAttValue = attValue.trim();
  +            if (fValidating) {
  +                // REVISIT - can we release the old string?
  +                if (newAttValue != attValue) {
  +                    if (invalidStandaloneAttDef(element, attribute)) {
  +                        reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
  +                                                  XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
  +                                                  fStringPool.toString(attribute.rawname), attValue, newAttValue);
  +                    }
  +                    attValueHandle = fStringPool.addSymbol(newAttValue);
  +                } 
  +                else {
  +                    attValueHandle = fStringPool.addSymbol(attValueHandle);
  +                }
  +                if (!XMLCharacterProperties.validName(newAttValue)) {
  +                    reportRecoverableXMLError(XMLMessages.MSG_ID_INVALID,
  +                                              XMLMessages.VC_ID,
  +                                              fStringPool.toString(attribute.rawname), newAttValue);
  +                }
  +                //
  +                // ID - check that the id value is unique within the document (V_TAG8)
  +                //
  +                if (element.rawname != -1 && !addId(attValueHandle)) {
  +                    reportRecoverableXMLError(XMLMessages.MSG_ID_NOT_UNIQUE,
  +                                              XMLMessages.VC_ID,
  +                                              fStringPool.toString(attribute.rawname), newAttValue);
  +                }
  +            } 
  +            else if (newAttValue != attValue) {
  +                // REVISIT - can we release the old string?
  +                attValueHandle = fStringPool.addSymbol(newAttValue);
  +            }
  +            return attValueHandle;
  +
  +        } // normalize(QName,QName,int,int,int):int
  +
           //
  -        // add to the attr list for this element
  +        // Package methods
           //
  -        int nextIndex = -1;
  -        if (attDefaultValue != -1) {
  -            nextIndex = fAttlistHead[elemChunk][elemIndex];
  -            fAttlistHead[elemChunk][elemIndex] = fAttDefCount;
  -            if (nextIndex == -1)
  -                fAttlistTail[elemChunk][elemIndex] = fAttDefCount;
  -        } else {
  -            nextIndex = fAttlistTail[elemChunk][elemIndex];
  -            fAttlistTail[elemChunk][elemIndex] = fAttDefCount;
  -            if (nextIndex == -1)
  -                fAttlistHead[elemChunk][elemIndex] = fAttDefCount;
  -            else {
  -                fNextAttDef[nextIndex >> CHUNK_SHIFT][nextIndex & CHUNK_MASK] = fAttDefCount;
  -                nextIndex = -1;
  +
  +        /** Returns true if invalid standalong attribute definition. */
  +        
  +        boolean invalidStandaloneAttDef(QName element, QName attribute) {
  +            if (fStandaloneReader == -1) {
  +                return false;
  +            }
  +            // we are normalizing a default att value...  this ok?
  +            if (element.rawname == -1) {
  +                return false;
               }
  +            return getAttDefIsExternal(element, attribute);
           }
  -        fNextAttDef[chunk][index] = nextIndex;
  -        return fAttDefCount++;
  -    }
   
  +    } // class AttValidatorID
   
  -	//
  -	// getValidatorAttType
  -	//
  +    /**
  +     * AttValidatorIDREF.
  +     */
  +    final class AttValidatorIDREF 
  +        implements AttributeValidator {
   
  -    private AttributeValidator getValidatorForAttType(int attType) {
  -        if (attType == fCDATASymbol) {
  -            if (fAttValidatorCDATA == null)
  -                fAttValidatorCDATA = new AttValidatorCDATA();
  -            return fAttValidatorCDATA;
  -        }
  -        if (attType == fIDSymbol) {
  -            if (fAttValidatorID == null)
  -                fAttValidatorID = new AttValidatorID();
  -            return fAttValidatorID;
  -        }
  -        if (attType == fIDREFSymbol) {
  -            if (fAttValidatorIDREF == null)
  -                fAttValidatorIDREF = new AttValidatorIDREF();
  -            return fAttValidatorIDREF;
  -        }
  -        if (attType == fIDREFSSymbol) {
  -            if (fAttValidatorIDREFS == null)
  -                fAttValidatorIDREFS = new AttValidatorIDREFS();
  -            return fAttValidatorIDREFS;
  -        }
  -        if (attType == fENTITYSymbol) {
  -            if (fAttValidatorENTITY == null)
  -                fAttValidatorENTITY = new AttValidatorENTITY();
  -            return fAttValidatorENTITY;
  -        }
  -        if (attType == fENTITIESSymbol) {
  -            if (fAttValidatorENTITIES == null)
  -                fAttValidatorENTITIES = new AttValidatorENTITIES();
  -            return fAttValidatorENTITIES;
  -        }
  -        if (attType == fNMTOKENSymbol) {
  -            if (fAttValidatorNMTOKEN == null)
  -                fAttValidatorNMTOKEN = new AttValidatorNMTOKEN();
  -            return fAttValidatorNMTOKEN;
  -        }
  -        if (attType == fNMTOKENSSymbol) {
  -            if (fAttValidatorNMTOKENS == null)
  -                fAttValidatorNMTOKENS = new AttValidatorNMTOKENS();
  -            return fAttValidatorNMTOKENS;
  -        }
  -        if (attType == fNOTATIONSymbol) {
  -            if (fAttValidatorNOTATION == null)
  -                fAttValidatorNOTATION = new AttValidatorNOTATION();
  -            return fAttValidatorNOTATION;
  -        }
  -        if (attType == fENUMERATIONSymbol) {
  -            if (fAttValidatorENUMERATION == null)
  -                fAttValidatorENUMERATION = new AttValidatorENUMERATION();
  -            return fAttValidatorENUMERATION;
  -        }
  -        if (attType == fDATATYPESymbol) {
  -            if (fAttValidatorDATATYPE == null)
  -                fAttValidatorDATATYPE = fSchemaImporter.createDatatypeAttributeValidator();
  -            return fAttValidatorDATATYPE;
  -        }
  -        throw new RuntimeException("getValidatorForAttType(" + fStringPool.toString(attType) + ")");
  -    }
  +        //
  +        // AttributeValidator methods
  +        //
  +
  +        /** Normalize. */
  +        public int normalize(QName element, QName attribute, 
  +                             int attValueHandle, int attType, 
  +                             int enumHandle) throws Exception {
  +            //
  +            // Normalize attribute based upon attribute type...
  +            //
  +            String attValue = fStringPool.toString(attValueHandle);
  +            String newAttValue = attValue.trim();
  +            if (fValidating) {
  +                // REVISIT - can we release the old string?
  +                if (newAttValue != attValue) {
  +                    if (invalidStandaloneAttDef(element, attribute)) {
  +                        reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
  +                                                  XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
  +                                                  fStringPool.toString(attribute.rawname), attValue, newAttValue);
  +                    }
  +                    attValueHandle = fStringPool.addSymbol(newAttValue);
  +                } 
  +                else {
  +                    attValueHandle = fStringPool.addSymbol(attValueHandle);
  +                }
  +                if (!XMLCharacterProperties.validName(newAttValue)) {
  +                    reportRecoverableXMLError(XMLMessages.MSG_IDREF_INVALID,
  +                                              XMLMessages.VC_IDREF,
  +                                              fStringPool.toString(attribute.rawname), newAttValue);
  +                }
  +                //
  +                // IDREF - remember the id value
  +                //
  +                if (element.rawname != -1)
  +                    addIdRef(attValueHandle);
  +            } 
  +            else if (newAttValue != attValue) {
  +                // REVISIT - can we release the old string?
  +                attValueHandle = fStringPool.addSymbol(newAttValue);
  +            }
  +            return attValueHandle;
   
  -    private int getAttDef(int elementType, int attrName) {
  -        int elementIndex = fStringPool.getDeclaration(elementType);
  -        if (elementIndex == -1)
  -            return -1;
  -        int chunk = elementIndex >> CHUNK_SHIFT;
  -        int index = elementIndex & CHUNK_MASK;
  -        int attDefIndex = fAttlistHead[chunk][index];
  -        while (attDefIndex != -1) {
  -            chunk = attDefIndex >> CHUNK_SHIFT;
  -            index = attDefIndex & CHUNK_MASK;
  -            if (fAttName[chunk][index] == attrName || fStringPool.equalNames(fAttName[chunk][index], attrName))
  -                return attDefIndex;
  -            attDefIndex = fNextAttDef[chunk][index];
  -        }
  -        return -1;
  -    }
  +        } // normalize(QName,QName,int,int,int):int
   
  -    private int getAttName(int attDefIndex) {
  -        int chunk = attDefIndex >> CHUNK_SHIFT;
  -        int index = attDefIndex & CHUNK_MASK;
  -        return fAttName[chunk][index];
  -    }
  +        //
  +        // Package methods
  +        //
   
  -    private int getAttValue(int attDefIndex) {
  -        int chunk = attDefIndex >> CHUNK_SHIFT;
  -        int index = attDefIndex & CHUNK_MASK;
  -        return fAttValue[chunk][index];
  -    }
  +        /** Returns true if invalid standalone attribute definition. */
  +        boolean invalidStandaloneAttDef(QName element, QName attribute) {
  +            if (fStandaloneReader == -1) {
  +                return false;
  +            }
  +            // we are normalizing a default att value...  this ok?
  +            if (element.rawname == -1) {
  +                return false;
  +            }
  +            return getAttDefIsExternal(element, attribute);
  +        }
   
  -    private AttributeValidator getAttributeValidator(int attDefIndex) {
  -        int chunk = attDefIndex >> CHUNK_SHIFT;
  -        int index = attDefIndex & CHUNK_MASK;
  -        return fAttValidator[chunk][index];
  -    }
  +    } // class AttValidatorIDREF
   
  -    private int getAttType(int attDefIndex) {
  -        int chunk = attDefIndex >> CHUNK_SHIFT;
  -        int index = attDefIndex & CHUNK_MASK;
  -        return fAttType[chunk][index];
  -    }
  +    /**
  +     * AttValidatorIDREFS.
  +     */
  +    final class AttValidatorIDREFS 
  +        implements AttributeValidator {
   
  -    private int getAttDefaultType(int attDefIndex) {
  -        int chunk = attDefIndex >> CHUNK_SHIFT;
  -        int index = attDefIndex & CHUNK_MASK;
  -        return fAttDefaultType[chunk][index];
  -    }
  +        //
  +        // AttributeValidator methods
  +        //
   
  -    private int getEnumeration(int attDefIndex) {
  -        int chunk = attDefIndex >> CHUNK_SHIFT;
  -        int index = attDefIndex & CHUNK_MASK;
  -        return fEnumeration[chunk][index];
  -    }
  +        /** Normalize. */
  +        public int normalize(QName element, QName attribute, 
  +                             int attValueHandle, int attType, 
  +                             int enumHandle) throws Exception {
  +            //
  +            // Normalize attribute based upon attribute type...
  +            //
  +            String attValue = fStringPool.toString(attValueHandle);
  +            StringTokenizer tokenizer = new StringTokenizer(attValue);
  +            StringBuffer sb = new StringBuffer(attValue.length());
  +            boolean ok = true;
  +            if (tokenizer.hasMoreTokens()) {
  +                while (true) {
  +                    String idName = tokenizer.nextToken();
  +                    if (fValidating) {
  +                        if (!XMLCharacterProperties.validName(idName)) {
  +                            ok = false;
  +                        }
  +                        //
  +                        // IDREFS - remember the id values
  +                        //
  +                        if (element.rawname != -1) {
  +                            addIdRef(fStringPool.addSymbol(idName));
  +                        }
  +                    }
  +                    sb.append(idName);
  +                    if (!tokenizer.hasMoreTokens())
  +                        break;
  +                    sb.append(' ');
  +                }
  +            }
  +            String newAttValue = sb.toString();
  +            if (fValidating && (!ok || newAttValue.length() == 0)) {
  +                reportRecoverableXMLError(XMLMessages.MSG_IDREFS_INVALID,
  +                                          XMLMessages.VC_IDREF,
  +                                          fStringPool.toString(attribute.rawname), newAttValue);
  +            }
  +            if (!newAttValue.equals(attValue)) {
  +                attValueHandle = fStringPool.addString(newAttValue);
  +                if (fValidating && invalidStandaloneAttDef(element, attribute)) {
  +                    reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
  +                                              XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
  +                                              fStringPool.toString(attribute.rawname), attValue, newAttValue);
  +                }
  +            }
  +            return attValueHandle;
   
  +        } // normalize(QName,QName,int,int,int):int
   
  -	//
  -	// copyAtts
  -	//
  -    // added by twl
  +        //
  +        // Package methods
  +        //
   
  -    public void copyAtts(int fromElementType, int toElementType) {
  +        /** Returns true if invalid standalone attribute definition. */
  +        boolean invalidStandaloneAttDef(QName element, QName attribute) {
  +            if (fStandaloneReader == -1) {
  +                return false;
  +            }
  +            // we are normalizing a default att value...  this ok?
  +            if (element.rawname == -1) {
  +                return false;
  +            }
  +            return getAttDefIsExternal(element, attribute);
  +        }
   
  -		//****DEBUG****
  -		if (DEBUG) print("(POP) XMLValidator.copyAtts: " + param("fromElementType",fromElementType) + param("toElementType",toElementType) + "\n");
  -		//****DEBUG****
  +    } // class AttValidatorIDREFS
  +        
  +    /**
  +     * AttValidatorENTITY.
  +     */
  +    final class AttValidatorENTITY 
  +        implements AttributeValidator {
   
  -        int fromElement = fStringPool.getDeclaration(fromElementType);
  -        int toElement = fStringPool.getDeclaration(toElementType);
  -        if (fromElement == -1)
  -            return;
  -        int chunk = fromElement >> CHUNK_SHIFT;
  -        int index = fromElement & CHUNK_MASK;
  -        int attDefIndex = fAttlistHead[chunk][index];
  -        while (attDefIndex != -1) {
  -            chunk = attDefIndex >> CHUNK_SHIFT;
  -            index = attDefIndex & CHUNK_MASK;
  -            try {
  -                addAttDef(toElement, 
  -                          fAttName[chunk][index], 
  -                          fAttType[chunk][index], 
  -                          fEnumeration[chunk][index], 
  -                          fAttDefaultType[chunk][index], 
  -                          fAttValue[chunk][index], 
  -                          fAttDefIsExternal[chunk][index] != 0);
  -            } catch (Exception ex) {
  +        //
  +        // AttributeValidator methods
  +        //
  +
  +        /** Normalize. */
  +        public int normalize(QName element, QName attribute, 
  +                             int attValueHandle, int attType, 
  +                             int enumHandle) throws Exception {
  +            //
  +            // Normalize attribute based upon attribute type...
  +            //
  +            String attValue = fStringPool.toString(attValueHandle);
  +            String newAttValue = attValue.trim();
  +            if (fValidating) {
  +                // REVISIT - can we release the old string?
  +                if (newAttValue != attValue) {
  +                    if (invalidStandaloneAttDef(element, attribute)) {
  +                        reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
  +                                                  XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
  +                                                  fStringPool.toString(attribute.rawname), attValue, newAttValue);
  +                    }
  +                    attValueHandle = fStringPool.addSymbol(newAttValue);
  +                } 
  +                else {
  +                    attValueHandle = fStringPool.addSymbol(attValueHandle);
  +                }
  +                //
  +                // ENTITY - check that the value is an unparsed entity name (V_TAGa)
  +                //
  +                if (!fEntityHandler.isUnparsedEntity(attValueHandle)) {
  +                    reportRecoverableXMLError(XMLMessages.MSG_ENTITY_INVALID,
  +                                              XMLMessages.VC_ENTITY_NAME,
  +                                              fStringPool.toString(attribute.rawname), newAttValue);
  +                }
  +            } 
  +            else if (newAttValue != attValue) {
  +                // REVISIT - can we release the old string?
  +                attValueHandle = fStringPool.addSymbol(newAttValue);
               }
  -            attDefIndex = fNextAttDef[chunk][index];
  -        }
  -    }
  +            return attValueHandle;
   
  +        } // normalize(QName,QName,int,int,int):int
   
  -	//
  -	// addDefaultAttributes
  -	//
  +        //
  +        // Package methods
  +        //
   
  -    private int addDefaultAttributes(int elementIndex, XMLAttrList attrList, int attrIndex, boolean validationEnabled, boolean standalone) throws Exception {
  +        /** Returns true if invalid standalone attribute definition. */
  +        boolean invalidStandaloneAttDef(QName element, QName attribute) {
  +            if (fStandaloneReader == -1) {
  +                return false;
  +            }
  +            // we are normalizing a default att value...  this ok?
  +            if (element.rawname == -1) {
  +                return false;
  +            }
  +            return getAttDefIsExternal(element, attribute);
  +        }
   
  -		//****DEBUG****
  -		if (DEBUG) print("(POP) XMLValidator.addDefaultAttributes\n");
  -		//****DEBUG****
  +    } // class AttValidatorENTITY
   
  +    /**
  +     * AttValidatorENTITIES.
  +     */
  +    final class AttValidatorENTITIES 
  +        implements AttributeValidator {
  +
           //
  -        // Check after all specified attrs are scanned
  -        // (1) report error for REQUIRED attrs that are missing (V_TAGc)
  -        // (2) check that FIXED attrs have matching value (V_TAGd)
  -        // (3) add default attrs (FIXED and NOT_FIXED)
  +        // AttributeValidator methods
           //
  -        int elemChunk = elementIndex >> CHUNK_SHIFT;
  -        int elemIndex = elementIndex & CHUNK_MASK;
  -        int attlistIndex = fAttlistHead[elemChunk][elemIndex];
  -        int firstCheck = attrIndex;
  -        int lastCheck = -1;
  -//System.err.println("specified attributes for element type " + fStringPool.toString(fElementType[elemChunk][elemIndex]));
  -        while (attlistIndex != -1) {
  -            int adChunk = attlistIndex >> CHUNK_SHIFT;
  -            int adIndex = attlistIndex & CHUNK_MASK;
  -            int attName = fAttName[adChunk][adIndex];
  -            int attType = fAttType[adChunk][adIndex];
  -            int attDefType = fAttDefaultType[adChunk][adIndex];
  -            int attValue = fAttValue[adChunk][adIndex];
  -            boolean specified = false;
  -            boolean required = attDefType == fREQUIREDSymbol;
  -            if (firstCheck != -1) {
  -                boolean cdata = attType == fCDATASymbol;
  -                if (!cdata || required || attValue != -1) {
  -                    int i = attrList.getFirstAttr(firstCheck);
  -                    while (i != -1 && (lastCheck == -1 || i <= lastCheck)) {
  -                        if (fStringPool.equalNames(attrList.getAttrName(i), attName)) {
  -//System.err.println(fStringPool.toString(attrList.getAttrName(i)) + " == " + fStringPool.toString(attName));
  -                            if (validationEnabled && attDefType == fFIXEDSymbol) {
  -                                int alistValue = attrList.getAttValue(i);
  -                                if (alistValue != attValue &&
  -                                    !fStringPool.toString(alistValue).equals(fStringPool.toString(attValue))) {
  -                                    Object[] args = { fStringPool.toString(fElementType[elemChunk][elemIndex]),
  -                                                    fStringPool.toString(attName),
  -                                                    fStringPool.toString(alistValue),
  -                                                    fStringPool.toString(attValue) };
  -                                    fErrorReporter.reportError(fErrorReporter.getLocator(),
  -                                                            XMLMessages.XML_DOMAIN,
  -                                                            XMLMessages.MSG_FIXED_ATTVALUE_INVALID,
  -                                                            XMLMessages.VC_FIXED_ATTRIBUTE_DEFAULT,
  -                                                            args,
  -                                                            XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
  -                                }
  -                            }
  -                            specified = true;
  -                            break;
  -                        }
  -//System.err.println(fStringPool.toString(attrList.getAttrName(i)) + " != " + fStringPool.toString(attName));
  -                        i = attrList.getNextAttr(i);
  +
  +        /** Normalize. */
  +        public int normalize(QName element, QName attribute, 
  +                             int attValueHandle, int attType, 
  +                             int enumHandle) throws Exception {
  +            //
  +            // Normalize attribute based upon attribute type...
  +            //
  +            String attValue = fStringPool.toString(attValueHandle);
  +            StringTokenizer tokenizer = new StringTokenizer(attValue);
  +            StringBuffer sb = new StringBuffer(attValue.length());
  +            boolean ok = true;
  +            if (tokenizer.hasMoreTokens()) {
  +                while (true) {
  +                    String entityName = tokenizer.nextToken();
  +                    //
  +                    // ENTITIES - check that each value is an unparsed entity name (V_TAGa)
  +                    //
  +                    if (fValidating && !fEntityHandler.isUnparsedEntity(fStringPool.addSymbol(entityName))) {
  +                        ok = false;
                       }
  +                    sb.append(entityName);
  +                    if (!tokenizer.hasMoreTokens()) {
  +                        break;
  +                    }
  +                    sb.append(' ');
                   }
               }
  -            if (!specified) {
  -                if (required) {
  -                    if (validationEnabled) {
  -                        Object[] args = { fStringPool.toString(fElementType[elemChunk][elemIndex]),
  -                                          fStringPool.toString(attName) };
  -                        fErrorReporter.reportError(fErrorReporter.getLocator(),
  -                                                   XMLMessages.XML_DOMAIN,
  -                                                   XMLMessages.MSG_REQUIRED_ATTRIBUTE_NOT_SPECIFIED,
  -                                                   XMLMessages.VC_REQUIRED_ATTRIBUTE,
  -                                                   args,
  -                                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
  -                    }
  -                } else if (attValue != -1) {
  -                    if (validationEnabled && standalone && fAttDefIsExternal[adChunk][adIndex] != 0) {
  -                        Object[] args = { fStringPool.toString(fElementType[elemChunk][elemIndex]),
  -                                          fStringPool.toString(attName) };
  -                        fErrorReporter.reportError(fErrorReporter.getLocator(),
  -                                                   XMLMessages.XML_DOMAIN,
  -                                                   XMLMessages.MSG_DEFAULTED_ATTRIBUTE_NOT_SPECIFIED,
  -                                                   XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
  -                                                   args,
  -                                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
  -                    }
  -                    if (attType == fIDREFSymbol) {
  -                        addIdRef(attValue);
  -                    } else if (attType == fIDREFSSymbol) {
  -                        StringTokenizer tokenizer = new StringTokenizer(fStringPool.toString(attValue));
  -                        while (tokenizer.hasMoreTokens()) {
  -                            String idName = tokenizer.nextToken();
  -                            addIdRef(fStringPool.addSymbol(idName));
  -                        }
  +            String newAttValue = sb.toString();
  +            if (fValidating && (!ok || newAttValue.length() == 0)) {
  +                reportRecoverableXMLError(XMLMessages.MSG_ENTITIES_INVALID,
  +                                          XMLMessages.VC_ENTITY_NAME,
  +                                          fStringPool.toString(attribute.rawname), newAttValue);
  +            }
  +            if (!newAttValue.equals(attValue)) {
  +                attValueHandle = fStringPool.addString(newAttValue);
  +                if (fValidating && invalidStandaloneAttDef(element, attribute)) {
  +                    reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
  +                                              XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
  +                                              fStringPool.toString(attribute.rawname), attValue, newAttValue);
  +                }
  +            }
  +            return attValueHandle;
  +
  +        } // normalize(QName,QName,int,int,int):int
  +
  +        //
  +        // Package methods
  +        //
  +
  +        /** Returns true if invalid standalone attribute definition. */
  +        boolean invalidStandaloneAttDef(QName element, QName attribute) {
  +            if (fStandaloneReader == -1) {
  +                return false;
  +            }
  +            // we are normalizing a default att value...  this ok?
  +            if (element.rawname == -1) {
  +                return false;
  +            }
  +            return getAttDefIsExternal(element, attribute);
  +        }
  +
  +    } // class AttValidatorENTITIES
  +
  +    /**
  +     * AttValidatorNMTOKEN.
  +     */
  +    final class AttValidatorNMTOKEN 
  +        implements AttributeValidator {
  +
  +        //
  +        // AttributeValidator methods
  +        //
  +
  +        /** Normalize. */
  +        public int normalize(QName element, QName attribute, 
  +                             int attValueHandle, int attType, 
  +                             int enumHandle) throws Exception {
  +            //
  +            // Normalize attribute based upon attribute type...
  +            //
  +            String attValue = fStringPool.toString(attValueHandle);
  +            String newAttValue = attValue.trim();
  +            if (fValidating) {
  +                // REVISIT - can we release the old string?
  +                if (newAttValue != attValue) {
  +                    if (invalidStandaloneAttDef(element, attribute)) {
  +                        reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
  +                                                  XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
  +                                                  fStringPool.toString(attribute.rawname), attValue, newAttValue);
                       }
  -                    if (attrIndex == -1)
  -                        attrIndex = attrList.startAttrList();
  -                    int newAttr = attrList.addAttr(attName, attValue, attType, false, false);
  -                    if (lastCheck == -1)
  -                        lastCheck = newAttr;
  +                    attValueHandle = fStringPool.addSymbol(newAttValue);
  +                } 
  +                else {
  +                    attValueHandle = fStringPool.addSymbol(attValueHandle);
  +                }
  +                if (!XMLCharacterProperties.validNmtoken(newAttValue)) {
  +                    reportRecoverableXMLError(XMLMessages.MSG_NMTOKEN_INVALID,
  +                                              XMLMessages.VC_NAME_TOKEN,
  +                                              fStringPool.toString(attribute.rawname), newAttValue);
                   }
  +            } 
  +            else if (newAttValue != attValue) {
  +                // REVISIT - can we release the old string?
  +                attValueHandle = fStringPool.addSymbol(newAttValue);
               }
  -            attlistIndex = fNextAttDef[adChunk][adIndex];
  -        }
  -        return attrIndex;
  -    }
  -
  +            return attValueHandle;
   
  -    //
  -    // Protected for use by AttributeValidator classes.
  -    //
  -    protected boolean getAttDefIsExternal(int elementType, int attrName) {
  -        int attDefIndex = getAttDef(elementType, attrName);
  -        int chunk = attDefIndex >> CHUNK_SHIFT;
  -        int index = attDefIndex & CHUNK_MASK;
  -        return (fAttDefIsExternal[chunk][index] != 0);
  -    }
  +        } // normalize(QName,QName,int,int,int):int
   
  +        //
  +        // Package methods
  +        //
   
  -	//
  -	// addId
  -	//
  +        /** Returns true if invalid standalone attribute definition. */
  +        boolean invalidStandaloneAttDef(QName element, QName attribute) {
  +            if (fStandaloneReader == -1) {
  +                return false;
  +            }
  +            // we are normalizing a default att value...  this ok?
  +            if (element.rawname == -1) {
  +                return false;
  +            }
  +            return getAttDefIsExternal(element, attribute);
  +        }
   
  -    protected boolean addId (int idIndex) {
  +    } // class AttValidatorNMTOKEN
   
  -		//****DEBUG****
  -		if (DEBUG) print("(POP) XMLValidator.addId" + param("idIndex",idIndex) + "\n");
  -		//****DEBUG****
  +    /**
  +     * AttValidatorNMTOKENS.
  +     */
  +    final class AttValidatorNMTOKENS 
  +        implements AttributeValidator {
   
  -		//System.err.println("addId(" + fStringPool.toString(idIndex) + ") " + idIndex);
  -        Integer key = new Integer(idIndex);
  -        if (fIdDefs == null)
  -            fIdDefs = new Hashtable();
  -        else if (fIdDefs.containsKey(key))
  -            return false;
  -        if (fNullValue == null)
  -            fNullValue = new Object();
  -        fIdDefs.put(key, fNullValue/*new Integer(elementType)*/);
  -        return true;
  -    }
  +        //
  +        // AttributeValidator methods
  +        //
   
  +        /** Normalize. */
  +        public int normalize(QName element, QName attribute, 
  +                             int attValueHandle, int attType, 
  +                             int enumHandle) throws Exception {
  +            //
  +            // Normalize attribute based upon attribute type...
  +            //
  +            String attValue = fStringPool.toString(attValueHandle);
  +            StringTokenizer tokenizer = new StringTokenizer(attValue);
  +            StringBuffer sb = new StringBuffer(attValue.length());
  +            boolean ok = true;
  +            if (tokenizer.hasMoreTokens()) {
  +                while (true) {
  +                    String nmtoken = tokenizer.nextToken();
  +                    if (fValidating && !XMLCharacterProperties.validNmtoken(nmtoken)) {
  +                        ok = false;
  +                    }
  +                    sb.append(nmtoken);
  +                    if (!tokenizer.hasMoreTokens()) {
  +                        break;
  +                    }
  +                    sb.append(' ');
  +                }
  +            }
  +            String newAttValue = sb.toString();
  +            if (fValidating && (!ok || newAttValue.length() == 0)) {
  +                reportRecoverableXMLError(XMLMessages.MSG_NMTOKENS_INVALID,
  +                                          XMLMessages.VC_NAME_TOKEN,
  +                                          fStringPool.toString(attribute.rawname), newAttValue);
  +            }
  +            if (!newAttValue.equals(attValue)) {
  +                attValueHandle = fStringPool.addString(newAttValue);
  +                if (fValidating && invalidStandaloneAttDef(element, attribute)) {
  +                    reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
  +                                              XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
  +                                              fStringPool.toString(attribute.rawname), attValue, newAttValue);
  +                }
  +            }
  +            return attValueHandle;
   
  -	//
  -	// addIdRef
  -	//
  +        } // normalize(QName,QName,int,int,int):int
   
  -    protected void addIdRef(int idIndex) {
  +        //
  +        // Package methods
  +        //
   
  -		//****DEBUG****
  -		if (DEBUG) print("(POP) XMLValidator.addIdRef" + param("idIndex",idIndex) + "\n");
  -		//****DEBUG****
  +        /** Returns true if standalone attribute definition. */
  +        boolean invalidStandaloneAttDef(QName element, QName attribute) {
  +            if (fStandaloneReader == -1) {
  +                return false;
  +            }
  +            // we are normalizing a default att value...  this ok?
  +            if (element.rawname == -1) {
  +                return false;
  +            }
  +            return getAttDefIsExternal(element, attribute);
  +        }
   
  -		//System.err.println("addIdRef(" + fStringPool.toString(idIndex) + ") " + idIndex);
  -        Integer key = new Integer(idIndex);
  -        if (fIdDefs != null && fIdDefs.containsKey(key))
  -            return;
  -        if (fIdRefs == null)
  -            fIdRefs = new Hashtable();
  -        else if (fIdRefs.containsKey(key))
  -            return;
  -        if (fNullValue == null)
  -            fNullValue = new Object();
  -        fIdRefs.put(key, fNullValue/*new Integer(elementType)*/);
  -    }
  +    } // class AttValidatorNMTOKENS
   
       /**
  -     * Check that all ID references were to ID attributes present in the document.
  -     * <p>
  -     * This method is a convenience call that allows the validator to do any id ref
  -     * checks above and beyond those done by the scanner. The scanner does the checks
  -     * specificied in the XML spec, i.e. that ID refs refer to ids which were
  -     * eventually defined somewhere in the document.
  -     * <p>
  -     * If the validator is for a Schema perhaps, which defines id semantics beyond
  -     * those of the XML specificiation, this is where that extra checking would be
  -     * done. For most validators, this is a no-op.
  -     *
  -     * @exception Exception Thrown on error.
  +     * AttValidatorNOTATION.
        */
  -    private void checkIdRefs() throws Exception {
  +    final class AttValidatorNOTATION 
  +        implements AttributeValidator {
   
  -		//****DEBUG****
  -		if (DEBUG) print("(???) XMLValidator.checkIdRefs\n");
  -		//****DEBUG****
  +        //
  +        // AttributeValidator methods
  +        //
   
  -        if (fIdRefs == null)
  -            return;
  -        Enumeration en = fIdRefs.keys();
  -        while (en.hasMoreElements()) {
  -            Integer key = (Integer)en.nextElement();
  -            if (fIdDefs == null || !fIdDefs.containsKey(key)) {
  -                Object[] args = { fStringPool.toString(key.intValue()) };
  -                fErrorReporter.reportError(fErrorReporter.getLocator(),
  -                                           XMLMessages.XML_DOMAIN,
  -                                           XMLMessages.MSG_ELEMENT_WITH_ID_REQUIRED,
  -                                           XMLMessages.VC_IDREF,
  -                                           args,
  -                                           XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
  +        /** Normalize. */
  +        public int normalize(QName element, QName attribute, 
  +                             int attValueHandle, int attType, 
  +                             int enumHandle) throws Exception {
  +            //
  +            // Normalize attribute based upon attribute type...
  +            //
  +            String attValue = fStringPool.toString(attValueHandle);
  +            String newAttValue = attValue.trim();
  +            if (fValidating) {
  +                // REVISIT - can we release the old string?
  +                if (newAttValue != attValue) {
  +                    if (invalidStandaloneAttDef(element, attribute)) {
  +                        reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
  +                                                  XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
  +                                                  fStringPool.toString(attribute.rawname), attValue, newAttValue);
  +                    }
  +                    attValueHandle = fStringPool.addSymbol(newAttValue);
  +                } 
  +                else {
  +                    attValueHandle = fStringPool.addSymbol(attValueHandle);
  +                }
  +                //
  +                // NOTATION - check that the value is in the AttDef enumeration (V_TAGo)
  +                //
  +                if (!fStringPool.stringInList(enumHandle, attValueHandle)) {
  +                    reportRecoverableXMLError(XMLMessages.MSG_ATTRIBUTE_VALUE_NOT_IN_LIST,
  +                                              XMLMessages.VC_NOTATION_ATTRIBUTES,
  +                                              fStringPool.toString(attribute.rawname),
  +                                              newAttValue, fStringPool.stringListAsString(enumHandle));
  +                }
  +            } 
  +            else if (newAttValue != attValue) {
  +                // REVISIT - can we release the old string?
  +                attValueHandle = fStringPool.addSymbol(newAttValue);
               }
  -        }
  -    }
  +            return attValueHandle;
   
  -    /** 
  -     * Checks that all declared elements refer to declared elements
  -     * in their content models. This method calls out to the error
  -     * handler to indicate warnings.
  -     */
  -    private void checkDeclaredElements() throws Exception {
  +        } // normalize(QName,QName,int,int,int):int
   
  -		//****DEBUG****
  -		if (DEBUG) print("(???) XMLValidator.checkDeclaredElements\n");
  -		//****DEBUG****
  +        //
  +        // Package methods
  +        //
   
  -        for (int i = 0; i < fElementCount; i++) {
  -            int type = getContentSpecType(i);
  -            if (type == fMIXEDSymbol || type == fCHILDRENSymbol) {
  -                int chunk = i >> CHUNK_SHIFT;
  -                int index = i &  CHUNK_MASK;
  -                int contentSpecIndex = fContentSpec[chunk][index];
  -                checkDeclaredElements(i, contentSpecIndex);
  +        /** Returns true if invalid standalone attribute definition. */
  +        boolean invalidStandaloneAttDef(QName element, QName attribute) {
  +            if (fStandaloneReader == -1) {
  +                return false;
               }
  +            // we are normalizing a default att value...  this ok?
  +            if (element.rawname == -1) {
  +                return false;
  +            }
  +            return getAttDefIsExternal(element, attribute);
           }
  -    }
   
  -    /** 
  -     * Does a recursive (if necessary) check on the specified element's
  -     * content spec to make sure that all children refer to declared
  -     * elements.
  -     * <p>
  -     * This method assumes that it will only be called when there is
  -     * a validation handler.
  +    } // class AttValidatorNOTATION
  +
  +    /**
  +     * AttValidatorENUMERATION.
        */
  -    private void checkDeclaredElements(int elementIndex, int contentSpecIndex) throws Exception {
  -        
  -		//****DEBUG****
  -		if (DEBUG) print("(???) XMLValidator.checkDeclaredElements\n");
  -		//****DEBUG****
  +    final class AttValidatorENUMERATION 
  +        implements AttributeValidator {
   
  -        // get spec type and value
  -        int chunk = contentSpecIndex >> CHUNK_SHIFT;
  -        int index = contentSpecIndex &  CHUNK_MASK;
  -        int type  = fNodeType[chunk][index];
  -        int value = fNodeValue[chunk][index];
  +        //
  +        // AttributeValidator methods
  +        //
   
  -        // handle type
  -        switch (type) {
  -        
  -            // #PCDATA | element
  -            case XMLContentSpec.CONTENTSPECNODE_LEAF: {
  -                // perform check for declared element
  -                if (value != -1 && fStringPool.getDeclaration(value) == -1) {
  -                    int elemChunk = elementIndex >> CHUNK_SHIFT;
  -                    int elemIndex = elementIndex &  CHUNK_MASK;
  -                    int elementType = fElementType[elemChunk][elemIndex];
  -                    Object[] args = { fStringPool.toString(elementType),
  -                                      fStringPool.toString(value) };
  -                    fErrorReporter.reportError(fErrorReporter.getLocator(),
  -                                               XMLMessages.XML_DOMAIN,
  -                                               XMLMessages.MSG_UNDECLARED_ELEMENT_IN_CONTENTSPEC,
  -                                               XMLMessages.P45_UNDECLARED_ELEMENT_IN_CONTENTSPEC,
  -                                               args,
  -                                               XMLErrorReporter.ERRORTYPE_WARNING);
  +        /** Normalize. */
  +        public int normalize(QName element, QName attribute, 
  +                             int attValueHandle, int attType, 
  +                             int enumHandle) throws Exception {
  +            //
  +            // Normalize attribute based upon attribute type...
  +            //
  +            String attValue = fStringPool.toString(attValueHandle);
  +            String newAttValue = attValue.trim();
  +            if (fValidating) {
  +                // REVISIT - can we release the old string?
  +                if (newAttValue != attValue) {
  +                    if (invalidStandaloneAttDef(element, attribute)) {
  +                        reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
  +                                                  XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
  +                                                  fStringPool.toString(attribute.rawname), attValue, newAttValue);
  +                    }
  +                    attValueHandle = fStringPool.addSymbol(newAttValue);
  +                } 
  +                else {
  +                    attValueHandle = fStringPool.addSymbol(attValueHandle);
                   }
  -                break;
  +                //
  +                // ENUMERATION - check that value is in the AttDef enumeration (V_TAG9)
  +                //
  +                if (!fStringPool.stringInList(enumHandle, attValueHandle)) {
  +                    reportRecoverableXMLError(XMLMessages.MSG_ATTRIBUTE_VALUE_NOT_IN_LIST,
  +                                              XMLMessages.VC_ENUMERATION,
  +                                              fStringPool.toString(attribute.rawname),
  +                                              newAttValue, fStringPool.stringListAsString(enumHandle));
  +                }
  +            } 
  +            else if (newAttValue != attValue) {
  +                // REVISIT - can we release the old string?
  +                attValueHandle = fStringPool.addSymbol(newAttValue);
               }
  +            return attValueHandle;
   
  -            // (...)? | (...)* | (...)+
  -            case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE:
  -            case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE: 
  -            case XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE: {
  -                checkDeclaredElements(elementIndex, value);
  -                break;
  -            }
  +        } // normalize(QName,QName,int,int,int):int
   
  -            // (... , ...) | (... | ...)
  -            case XMLContentSpec.CONTENTSPECNODE_CHOICE:
  -            case XMLContentSpec.CONTENTSPECNODE_SEQ: {
  -                checkDeclaredElements(elementIndex, value);
  -                if (++index == CHUNK_SIZE) {
  -                    chunk++;
  -                    index = 0;
  -                }
  -                checkDeclaredElements(elementIndex, fNodeValue[chunk][index]);
  -                break;
  +        //
  +        // Package methods
  +        //
  +
  +        /** Returns true if invalid standalone attribute definition. */
  +        boolean invalidStandaloneAttDef(QName element, QName attribute) {
  +            if (fStandaloneReader == -1) {
  +                return false;
  +            }
  +            // we are normalizing a default att value...  this ok?
  +            if (element.rawname == -1) {
  +                return false;
               }
  +            return getAttDefIsExternal(element, attribute);
           }
  -    }
  -}
  +
  +    } // class AttValidatorENUMERATION
  +
  +} // class XMLValidator
  
  
  
  1.2       +816 -0    xml-xerces/java/src/org/apache/xerces/validators/common/Grammar.java
  
  
  
  
  1.2       +275 -0    xml-xerces/java/src/org/apache/xerces/validators/common/GrammarPool.java
  
  
  
  
  1.2       +147 -0    xml-xerces/java/src/org/apache/xerces/validators/common/GrammarResolver.java
  
  
  
  
  1.2       +289 -0    xml-xerces/java/src/org/apache/xerces/validators/common/GrammarResolverImpl.java
  
  
  
  
  1.2       +168 -0    xml-xerces/java/src/org/apache/xerces/validators/common/XMLAttributeDecl.java
  
  
  
  
  1.2       +149 -0    xml-xerces/java/src/org/apache/xerces/validators/common/XMLElementDecl.java
  
  
  
  
  1.3       +97 -20    xml-xerces/java/src/org/apache/xerces/validators/datatype/BinaryValidator.java
  
  Index: BinaryValidator.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/validators/datatype/BinaryValidator.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- BinaryValidator.java	2000/01/06 17:59:04	1.2
  +++ BinaryValidator.java	2000/05/17 18:33:11	1.3
  @@ -60,7 +60,12 @@
   import java.util.Enumeration;
   import java.util.Hashtable;
   import java.util.Locale;
  +import java.util.Vector;
  +import org.apache.xerces.validators.schema.SchemaSymbols;
  +import org.apache.xerces.utils.regex.RegularExpression;
  +import org.apache.xerces.utils.Base64;
   
  +
   /**
    *
    * binaryValidator validates that XML content is a W3C binary type.
  @@ -68,11 +73,22 @@
    * @author Ted Leung
    * @version Revision: %M% %I% %W% %Q%
    */
  +
  +public class BinaryValidator implements DatatypeValidator {
  +    private Locale    fLocale          = null;
  +    private String    fBaseValidator   = "native";
  +
  +    private int       _length          = 0;
  +    private int       _maxLength       = 0;
  +    private int       _minLength       = 0;
  +    private String    _pattern         = null;
  +    private Vector    _enumeration     = null;
  +    private int       _facetsDefined   = 0;
  +    private String    _encoding        = SchemaSymbols.ATTVAL_BASE64;//default
   
  -public class BinaryValidator implements InternalDatatypeValidator {
  +    private int       _derivedBy       = DatatypeValidator.DERIVED_BY_RESTRICTION;//default
   
  -    private Locale fLocale;
  -    
  +
       /**
        * validate that a string is a W3C binary type
        *
  @@ -84,31 +100,87 @@
        * @exception throws InvalidDatatypeException if the content is
        *  not a W3C binary type
        */
  -    public void validate(String content) throws InvalidDatatypeValueException {
  -        // just say yes
  +    public void validate(String content ) throws InvalidDatatypeValueException {
  +        if( _derivedBy == DatatypeValidator.DERIVED_BY_RESTRICTION ){
  +           if( Base64.isBase64( content ) == false ){
  +               throw new InvalidDatatypeValueException( "Value '"+content+ "'  must be" +
  +                                "is not encoded in Base64" );
  +           }
  +        }else {
  +        }
       }
   
  -    public void validate(int contentIndex) throws InvalidDatatypeValueException {
  -        // just say yes
  -    }
   
  -    public void setFacets(Hashtable facets) throws UnknownFacetException, IllegalFacetException, IllegalFacetValueException {
  -        for (Enumeration e = facets.keys(); e.hasMoreElements();) {
  -            String key = (String) e.nextElement();
  -            if (key.equals(DatatypeValidator.LENGTH)) {
  -            } else if (key.equals(DatatypeValidator.MINLENGTH)) {
  -            } else if (key.equals(DatatypeValidator.MAXLENGTH)) {
  -            } else if (key.equals(DatatypeValidator.ENCODING)) {
  -            } else {
  -                throw new IllegalFacetException();
  +    public void setFacets(Hashtable facets, String derivationBy ) throws UnknownFacetException, 
  +    IllegalFacetException,IllegalFacetValueException, ConstrainException {
  +        if ( derivationBy.equals( SchemaSymbols.ATTVAL_RESTRICTION ) ) {
  +            _derivedBy = DatatypeValidator.DERIVED_BY_RESTRICTION;
  +            for (Enumeration e = facets.keys(); e.hasMoreElements();) {
  +                String key = (String) e.nextElement();
  +                if ( key.equals(SchemaSymbols.ELT_LENGTH) ) {
  +                    _facetsDefined += DatatypeValidator.FACET_LENGTH;
  +                    String lengthValue = (String)facets.get(key);
  +                    try {
  +                        _length     = Integer.parseInt( lengthValue );
  +                    } catch (NumberFormatException nfe) {
  +                        throw new IllegalFacetValueException("Length value '"+lengthValue+"' is invalid.");
  +                    }
  +                    if ( _length < 0 )
  +                        throw new IllegalFacetValueException("Length value '"+lengthValue+"'  must be a nonNegativeInteger.");
  +
  +                } else if (key.equals(SchemaSymbols.ELT_MINLENGTH) ) {
  +                    _facetsDefined += DatatypeValidator.FACET_MINLENGTH;
  +                    String minLengthValue = (String)facets.get(key);
  +                    try {
  +                        _minLength     = Integer.parseInt( minLengthValue );
  +                    } catch (NumberFormatException nfe) {
  +                        throw new IllegalFacetValueException("maxLength value '"+minLengthValue+"' is invalid.");
  +                    }
  +                } else if (key.equals(SchemaSymbols.ELT_MAXLENGTH) ) {
  +                    _facetsDefined += DatatypeValidator.FACET_MAXLENGTH;
  +                    String maxLengthValue = (String)facets.get(key);
  +                    try {
  +                        _maxLength     = Integer.parseInt( maxLengthValue );
  +                    } catch (NumberFormatException nfe) {
  +                        throw new IllegalFacetValueException("maxLength value '"+maxLengthValue+"' is invalid.");
  +                    }
  +                } else if (key.equals(SchemaSymbols.ELT_PATTERN)) {
  +                    _facetsDefined += DatatypeValidator.FACET_PATTERN;
  +                    _pattern = (String)facets.get(key);
  +                } else if (key.equals(SchemaSymbols.ELT_ENUMERATION)) {
  +                    _facetsDefined += DatatypeValidator.FACET_ENUMERATION;
  +                    _enumeration = (Vector)facets.get(key);
  +                } else if (key.equals(SchemaSymbols.ELT_ENCODING )) {
  +                    _facetsDefined += DatatypeValidator.FACET_MAXINCLUSIVE;
  +                    _encoding = (String)facets.get(key);
  +                } else {
  +                    throw new IllegalFacetException();
  +                }
  +            }
  +            if (((_facetsDefined & DatatypeValidator.FACET_LENGTH ) != 0 ) ) {
  +                if (((_facetsDefined & DatatypeValidator.FACET_MAXLENGTH ) != 0 ) ) {
  +                    throw new ConstrainException(
  +                                                "It is an error for both length and maxLength to be members of facets." );  
  +                } else if (((_facetsDefined & DatatypeValidator.FACET_MINLENGTH ) != 0 ) ) {
  +                    throw new ConstrainException(
  +                                                "It is an error for both length and minLength to be members of facets." );
  +                }
               }
  +
  +            if ( ( (_facetsDefined & ( DatatypeValidator.FACET_MINLENGTH |
  +                                       DatatypeValidator.FACET_MAXLENGTH) ) != 0 ) ) {
  +                if ( _minLength < _maxLength ) {
  +                    throw new ConstrainException( "Value of minLength = " + _minLength +
  +                                                  "must be greater that the value of maxLength" + _maxLength );
  +                }
  +            }
  +        } else {  //Derivation by List 
  +
           }
  -    }
   
  -    public void setFacets(int facets[]) throws UnknownFacetException, IllegalFacetException, IllegalFacetValueException {
       }
   
  -    public void setBasetype(DatatypeValidator base) {
  +    public void setBasetype(String base) {
       }
   
       /**
  @@ -117,4 +189,9 @@
       public void setLocale(Locale locale) {
           fLocale = locale;
       }
  +
  +    public int compare( DatatypeValidator o1, DatatypeValidator o2){
  +        return 0;
  +    }
  +
   }
  
  
  
  1.3       +111 -38   xml-xerces/java/src/org/apache/xerces/validators/datatype/BooleanValidator.java
  
  Index: BooleanValidator.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/validators/datatype/BooleanValidator.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- BooleanValidator.java	1999/12/18 04:25:38	1.2
  +++ BooleanValidator.java	2000/05/17 18:33:12	1.3
  @@ -2,7 +2,7 @@
    * The Apache Software License, Version 1.1
    *
    *
  - * Copyright (c) 1999 The Apache Software Foundation.  All rights 
  + * Copyright (c) 1999, 2000 The Apache Software Foundation.  All rights 
    * reserved.
    *
    * Redistribution and use in source and binary forms, with or without
  @@ -59,52 +59,96 @@
   
   import java.util.Hashtable;
   import java.util.Locale;
  -
  +import java.util.Enumeration;
  +import org.apache.xerces.validators.schema.SchemaSymbols;
  +import org.apache.xerces.utils.regex.RegularExpression;
  +import org.apache.xerces.validators.schema.SchemaSymbols;
   /**
    *
    * BooleanValidator validates that content satisfies the W3C XML Datatype for Boolean
    *
    * @author Ted Leung 
  + * @author Jeffrey Rodriguez
    * @version
    */
  +
  +public class BooleanValidator implements DatatypeValidator {
  +    private Locale fLocale        = null;
  +    private String fBaseValidator = "native";
  +    private String _pattern       = null;
  +    private int    _facetsDefined = 0;
  +    private DatatypeMessageProvider fMessageProvider = new DatatypeMessageProvider();
  +    private static  final String _valueSpace[]  = { "false", "true", "0", "1" };
  +    private int       _derivedBy       = DatatypeValidator.DERIVED_BY_RESTRICTION;//default
   
  -public class BooleanValidator implements InternalDatatypeValidator {
  -    private Locale fLocale = null;
  -	private DatatypeMessageProvider fMessageProvider = new DatatypeMessageProvider();
  -	/**
  +    /**
        * validate that a string matches the boolean datatype
  -     *
  -     * validate returns true or false depending on whether the string content is a
  -     * W3C integer type.
  -     * 
        * @param content A string containing the content to be validated
        *
        * @exception throws InvalidDatatypeException if the content is
  -     *  is not a W3C integer type
  +     * is not valid.
  +     */
  +
  +    public void validate(String content) throws InvalidDatatypeValueException {
  +        if ( _facetsDefined == 0 )// No Facets to validate against
  +            return;
  +
  +
  +        if( _derivedBy == DatatypeValidator.DERIVED_BY_RESTRICTION  ){ 
  +
  +            ;// What does it mean?
  +        } else {
  +            checkContent( content );
  +        }
  +    }
  +
  +
  +    /**
  +     * Sets the allowable constraining facets
  +     * for the datatype.
  +     * 
  +     * boolean has the following constraining facets:
  +     * pattern
  +     * 
  +     * @param facets Hashtable containing constraining
  +     *               information passed from the
  +     *               DatatypeValidatorRegistry.
  +     * @exception UnknownFacetException
  +     * @exception IllegalFacetException
  +     * @exception IllegalFacetValueException
  +     * @exception ConstrainException
  +     */
  +    public void setFacets(Hashtable facets, String derivationBy) throws UnknownFacetException,
  +    IllegalFacetException, IllegalFacetValueException, ConstrainException {
  +
  +        if ( derivationBy.equals( SchemaSymbols.ATTVAL_RESTRICTION ) ) {
  +           _derivedBy = DatatypeValidator.DERIVED_BY_RESTRICTION;
  +
  +            for (Enumeration e = facets.keys(); e.hasMoreElements();) {
  +                String key = (String) e.nextElement();
  +
  +                if (key.equals(SchemaSymbols.ELT_PATTERN)) {
  +                    _facetsDefined += DatatypeValidator.FACET_PATTERN;
  +                    _pattern = (String)facets.get(key);
  +                } else {
  +                    throw new IllegalFacetException();
  +                }
  +            }
  +        }else { // By List
  +
  +        }
  +    }
  +
  +
  +    /**
  +     * Sets the base datatype name.
  +     * 
  +     * @param base
        */
  +    public void setBasetype(String base) {
  +        fBaseValidator = base;
  +    }
   
  -	public void validate(String content) throws InvalidDatatypeValueException {
  -        if (!content.equals("true") && !content.equals("false"))
  -            throw new InvalidDatatypeValueException(
  -				getErrorString(DatatypeMessageProvider.NotBoolean,
  -							   DatatypeMessageProvider.MSG_NONE,
  -							   new Object[] { content }));
  -	}
  -	
  -	public void validate(int contentIndex) throws InvalidDatatypeValueException {
  -	}
  -	
  -	public void setFacets(Hashtable facets) throws UnknownFacetException, IllegalFacetException, IllegalFacetValueException {
  -	    throw new IllegalFacetException(); // boolean supports no facets
  -	}
  -	
  -	public void setFacets(int facets[]) throws UnknownFacetException, IllegalFacetException, IllegalFacetValueException {
  -	    throw new IllegalFacetException(); // boolean supports no facets
  -	}
  -	
  -	public void setBasetype(DatatypeValidator base) {
  -	}
  -	
       /**
        * set the locate to be used for error messages
        */
  @@ -112,11 +156,40 @@
           fLocale = locale;
       }
   
  +    public int compare( DatatypeValidator o1, DatatypeValidator o2){
  +      return 0;
  +    }
  +
       private String getErrorString(int major, int minor, Object args[]) {
  -         try {
  -             return fMessageProvider.createMessage(fLocale, major, minor, args);
  -         } catch (Exception e) {
  -             return "Illegal Errorcode "+minor;
  -         }
  +        try {
  +            return fMessageProvider.createMessage(fLocale, major, minor, args);
  +        } catch (Exception e) {
  +            return "Illegal Errorcode "+minor;
  +        }
  +    }
  +
  +    /**
  +     * Checks content for validity.
  +     * 
  +     * @param content
  +     * @exception InvalidDatatypeValueException
  +     */
  +    private void checkContent( String content )throws InvalidDatatypeValueException {
  +        boolean  isContentInDomain = false;
  +        for( int i = 0;i<_valueSpace.length;i++ ){
  +            if( content.equals(_valueSpace[i] ) )
  +                isContentInDomain = true;
  +        }
  +        if (isContentInDomain == false)
  +           throw new InvalidDatatypeValueException(
  +                                                  getErrorString(DatatypeMessageProvider.NotBoolean,
  +                                                                 DatatypeMessageProvider.MSG_NONE,
  +                                                                 new Object[] { content}));
  +        if ( (_facetsDefined & DatatypeValidator.FACET_PATTERN ) != 0 ) {
  +            RegularExpression regex = new RegularExpression(_pattern, "X" );
  +            if ( regex.matches( content) == false )
  +                throw new InvalidDatatypeValueException("Value'"+content+
  +                                                        "does not match regular expression facet" + _pattern );
  +        }
       }
   }
  
  
  
  1.3       +1 -0      xml-xerces/java/src/org/apache/xerces/validators/datatype/DatatypeMessageProvider.java
  
  Index: DatatypeMessageProvider.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/validators/datatype/DatatypeMessageProvider.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- DatatypeMessageProvider.java	2000/01/06 00:14:58	1.2
  +++ DatatypeMessageProvider.java	2000/05/17 18:33:12	1.3
  @@ -179,4 +179,5 @@
           "PrecisionExceeded",            //  16, "{0} has exceeded the precision Facet {1}"},
           "ScaleExceeded",                //  17, "{0} has execeed the scale Facet {1}"},
       };
  +
   }
  
  
  
  1.4       +80 -61    xml-xerces/java/src/org/apache/xerces/validators/datatype/DatatypeValidator.java
  
  Index: DatatypeValidator.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/validators/datatype/DatatypeValidator.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- DatatypeValidator.java	2000/03/11 01:17:06	1.3
  +++ DatatypeValidator.java	2000/05/17 18:33:12	1.4
  @@ -61,81 +61,100 @@
   import java.util.Locale;
   
   /**
  - *
    * DataTypeValidator defines the interface that data type validators must obey.
    * These validators can be supplied by the application writer and may be useful as
    * standalone code as well as plugins to the validator architecture.
    * Note: there is no support for facets in this API, since we are trying to convince
    * W3C to remove facets from the data type spec.
  - *
  - * @author Ted Leung
  - * @author Kito D. Mann -- changed the MAXLENGTH and MINLENGTH as per 12/17 spec.
  - * @version
  + * 
  + * @author Jeffrey Rodriguez-
    */
  -
   public interface DatatypeValidator {
  -	
  -	public static final String MININCLUSIVE = "minInclusive";
  -	public static final String MINEXCLUSIVE = "minExclusive";
  -	public static final String MAXINCLUSIVE = "maxInclusive";
  -	public static final String MAXEXCLUSIVE = "maxExclusive";
  -	
  -	public static final String PRECISION = "precision";
  -	public static final String SCALE = "scale";
  -	
  -	public static final String LENGTH = "length";
  -    public static final String MINLENGTH = "minlength";
  -	public static final String MAXLENGTH = "maxlength";
  -	public static final String ENUMERATION = "enumeration";
  -	public static final String LITERAL = "literal";
  -	public static final String LEXICALREPRESENTATION = "lexicalRepresentation";
  -	public static final String LEXICAL = "lexical";
  -	public static final String ENCODING = "encoding";
  -    public static final String PERIOD = "period";
  -	public static final String PATTERN = "pattern";
  -	
  -	/**
  -     * validate that a string matches a datatype
  -     *
  -     * validate returns true or false depending on whether the string content is an
  -     * instance of the data type represented by this validator.
  +    public static final int FACET_LENGTH       = 1;
  +    public static final int FACET_MINLENGTH    = 1<<1;
  +    public static final int FACET_MAXLENGTH    = 1<<2;
  +    public static final int FACET_PATTERN      = 1<<3; 
  +    public static final int FACET_ENUMERATION  = 1<<4;
  +    public static final int FACET_MAXINCLUSIVE = 1<<5;
  +    public static final int FACET_MAXEXCLUSIVE = 1<<6;
  +    public static final int FACET_MININCLUSIVE = 1<<7;
  +    public static final int FACET_MINEXCLUSIVE = 1<<8;
  +    public static final int FACET_PRECISSION   = 1<<9;
  +    public static final int FACET_SCALE        = 1<<10;
  +    public static final int FACET_ENCODING     = 1<<11;
  +    public static final int FACET_DURATION     = 1<<12;
  +    public static final int FACET_PERIOD       = 1<<13;
  +    public static final int DERIVED_BY_RESTRICTION   = 1;
  +    public static final int DERIVED_BY_LIST          = 1<<1;
  +
  +
  +
  +    /**
  +     * Checks that "content" string is valid 
  +     * datatype.
  +     * If invalid a Datatype validation exception is thrown.
        * 
        * @param content A string containing the content to be validated
  -     *
  +     * @param derivedBylist
  +     *                Flag which is true when type
  +     *                is derived by list otherwise it
  +     *                it is derived by extension.
  +     *                
        * @exception throws InvalidDatatypeException if the content is
  -     *  invalid according to the rules for the validators
  +     *                   invalid according to the rules for the validators
  +     * @exception InvalidDatatypeValueException
  +     * @see         org.apache.xerces.validators.datatype.InvalidDatatypeValueException
        */
  -	public void validate(String content) throws InvalidDatatypeValueException;
  -	
  -	/**
  -	 * set the facets for this datatype
  -	 *
  -	 * setFacets is responsible for ensuring that the supplied facets do not contradict each
  -	 * other
  -	 *
  -	 * @param facets A hashtable where facet names are keys and facet values are stored
  -	 *        in the hashtable.  Usually facet values are strings, except for the 
  -	 *        enumeration facet.  The value for this facet is a Vector of strings, one
  -	 *        per enumeration value
  -	 *
  -	 * @exception throws UnknownFacetException
  -	 * @exception throws IllegalFacetException
  -	 * @exception throws IllegalFacetValueException
  -	 */
  -	public void setFacets(Hashtable facets) throws UnknownFacetException, IllegalFacetException, IllegalFacetValueException; 
  -	
  -	/**
  -	 * set the base type for this datatype
  -	 *
  -	 * @param base the validator for this type's base type
  -	 *
  -	 */
  -	public void setBasetype(DatatypeValidator base);
  +    public void validate(String content ) throws InvalidDatatypeValueException;
   
  +    /**
  +     * set the facets for this datatype
  +     * 
  +     * setFacets is responsible for ensuring that the supplied facets do not contradict each
  +     * other.
  +     * 
  +     * @param facets A hashtable where facet name Symbols  are keys and facet values are stored
  +     *               in the hashtable.  Usually facet values are strings, except for the
  +     *               enumeration facet.  The value for this facet is a Vector of strings, one
  +     *               per enumeration value
  +     * @exception throws UnknownFacetException
  +     * @exception throws IllegalFacetException
  +     * @exception throws IllegalFacetValueException
  +     * @exception UnknownFacetException
  +     * @exception IllegalFacetException
  +     * @exception IllegalFacetValueException
  +     * @exception ConstrainException
  +     * @see org.apache.xerces.validators.schema.SchemaSymbols
  +     * @see org.apache.xerces.validators.datatype.IllegalFacetException
  +     * @see org.apache.xerces.validators.datatype.IllegalFacetValueException
  +     * @see org.apache.xerces.validators.datatype.ConstrainException
  +     */
  +    public void setFacets(Hashtable facets,String  derivationType ) throws UnknownFacetException, 
  +        IllegalFacetException, IllegalFacetValueException,  ConstrainException; 
   
  -	
       /**
  -     * set the locate to be used for error messages
  +     * Name of base type as a string.
  +     * A Native datatype has the string "native"  as its
  +     * base type.
  +     * 
  +     * @param base   the validator for this type's base type
        */
  +    public void setBasetype(String base);
  +
  +
  +    /**
  +    * set the locate to be used for error messages
  +    */
       public void setLocale(Locale locale);
  +
  +    /**
  +     * REVISIT
  +     * Compares two Datatype for order
  +     * 
  +     * @param o1
  +     * @param o2
  +     * @return 
  +     */
  +    public int compare( DatatypeValidator o1, DatatypeValidator o2);
  +
   }
  
  
  
  1.5       +158 -156  xml-xerces/java/src/org/apache/xerces/validators/datatype/DecimalValidator.java
  
  Index: DecimalValidator.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/validators/datatype/DecimalValidator.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- DecimalValidator.java	2000/01/06 23:17:40	1.4
  +++ DecimalValidator.java	2000/05/17 18:33:13	1.5
  @@ -63,6 +63,7 @@
   import java.util.Hashtable;
   import java.util.Locale;
   import java.util.Vector;
  +import org.apache.xerces.validators.schema.SchemaSymbols;
   
   /**
    *
  @@ -72,27 +73,27 @@
    * @version
    */
   
  -public class DecimalValidator implements InternalDatatypeValidator {
  -	
  -	BigDecimal fMaxInclusive = null;
  -	boolean fIsMaxInclusive = false;
  -	BigDecimal fMaxExclusive = null;
  -	boolean fIsMaxExclusive = false;
  -	BigDecimal fMinInclusive = null;
  -	boolean fIsMinInclusive = false;
  -	BigDecimal fMinExclusive = null;
  -	boolean fIsMinExclusive = false;
  -	BigDecimal fEnumValues[] = null;
  -	boolean fHasEnums = false;
  +public class DecimalValidator implements DatatypeValidator {
  +
  +    BigDecimal fMaxInclusive = null;
  +    boolean fIsMaxInclusive = false;
  +    BigDecimal fMaxExclusive = null;
  +    boolean fIsMaxExclusive = false;
  +    BigDecimal fMinInclusive = null;
  +    boolean fIsMinInclusive = false;
  +    BigDecimal fMinExclusive = null;
  +    boolean fIsMinExclusive = false;
  +    BigDecimal fEnumValues[] = null;
  +    boolean fHasEnums = false;
       int fPrecision = 0;
       boolean fIsPrecision = false;
       int fScale = 0;
       boolean fIsScale = false;
  -	DecimalValidator fBaseValidator = null;
  -	private DatatypeMessageProvider fMessageProvider = new DatatypeMessageProvider();
  -	private Locale fLocale = null;
  -	
  -	/**
  +    DecimalValidator fBaseValidator = null;
  +    private DatatypeMessageProvider fMessageProvider = new DatatypeMessageProvider();
  +    private Locale fLocale = null;
  +
  +    /**
        * validate that a string matches the decimal datatype
        *
        * validate returns true or false depending on whether the string content is a
  @@ -104,166 +105,163 @@
        *  is not a W3C decimal type
        */
   
  -	public void validate(String content) throws InvalidDatatypeValueException {
  -	    BigDecimal d = null;
  +    public void validate(String content) throws InvalidDatatypeValueException {
  +        BigDecimal d = null;
           try {
               d = new BigDecimal(content);
           } catch (NumberFormatException nfe) {
               throw new InvalidDatatypeValueException(
  -				getErrorString(DatatypeMessageProvider.NotDecimal,
  -							   DatatypeMessageProvider.MSG_NONE,
  -							   new Object[] { content }));
  +                                                   getErrorString(DatatypeMessageProvider.NotDecimal,
  +                                                                  DatatypeMessageProvider.MSG_NONE,
  +                                                                  new Object[] { content}));
           }
           if (fIsScale)
               if (d.scale() > fScale)
                   throw new InvalidDatatypeValueException(
  -                    getErrorString(DatatypeMessageProvider.ScaleExceeded,
  -                                   DatatypeMessageProvider.MSG_NONE,
  -                                   new Object[] { content }));
  +                                                       getErrorString(DatatypeMessageProvider.ScaleExceeded,
  +                                                                      DatatypeMessageProvider.MSG_NONE,
  +                                                                      new Object[] { content}));
           if (fIsPrecision) {
               int precision = d.movePointRight(d.scale()).toString().length() - 
  -                ((d.signum() < 0) ? 1 : 0); // account for minus sign
  -            if (precision > fPrecision) 
  +                            ((d.signum() < 0) ? 1 : 0); // account for minus sign
  +            if (precision > fPrecision)
                   throw new InvalidDatatypeValueException(
  -                    getErrorString(DatatypeMessageProvider.PrecisionExceeded,
  -                                   DatatypeMessageProvider.MSG_NONE,
  -                                   new Object[] {content} ));
  +                                                       getErrorString(DatatypeMessageProvider.PrecisionExceeded,
  +                                                                      DatatypeMessageProvider.MSG_NONE,
  +                                                                      new Object[] {content} ));
           }
           boundsCheck(d);
           if (fHasEnums)
               enumCheck(d);
  -	}
  -			
  -	public void validate(int contentIndex) throws InvalidDatatypeValueException {
  -	}
  -	
  -	//REVISIT: candidate for public API
  -	boolean ensureFacetsAreConsistent(Hashtable facets) {
  -	    boolean facetsAreConsistent = true;
  -	    for (Enumeration e = facets.keys(); facetsAreConsistent && e.hasMoreElements();) {
  -	        String key = (String) e.nextElement();
  -	        String value = null;
  -	        if (key.equals(DatatypeValidator.ENUMERATION)) 
  +    }
  +
  +    public void validate(int contentIndex) throws InvalidDatatypeValueException {
  +    }
  +
  +    //REVISIT: candidate for public API
  +    boolean ensureFacetsAreConsistent(Hashtable facets) {
  +        boolean facetsAreConsistent = true;
  +        for (Enumeration e = facets.keys(); facetsAreConsistent && e.hasMoreElements();) {
  +            String key = (String) e.nextElement();
  +            String value = null;
  +            if (key.equals(SchemaSymbols.ELT_ENUMERATION))
                   continue;  // ENUM values passed as a vector & handled after bounds facets	    
  -    	    value = (String) facets.get(key);   
  -	        BigDecimal decimalValue = null;
  -	        try {
  -	            decimalValue = new BigDecimal(value);
  -	        } catch (NumberFormatException nfe) {
  +            value = (String) facets.get(key);   
  +            BigDecimal decimalValue = null;
  +            try {
  +                decimalValue = new BigDecimal(value);
  +            } catch (NumberFormatException nfe) {
                   facetsAreConsistent = false;
  -	        }
  -	        if (key.equals(DatatypeValidator.MININCLUSIVE) && fIsMinInclusive) {
  +            }
  +            if (key.equals(SchemaSymbols.ELT_MININCLUSIVE ) && fIsMinInclusive) {
                   facetsAreConsistent = (fMinInclusive.compareTo(decimalValue) < 0);
  -	        } else if (key.equals(DatatypeValidator.MINEXCLUSIVE) && fIsMinExclusive) {
  -	            facetsAreConsistent = (fMinExclusive.compareTo(decimalValue) < 0);
  -	        } else if (key.equals(DatatypeValidator.MAXINCLUSIVE) && fIsMaxInclusive) {
  -	            facetsAreConsistent = (fMaxInclusive.compareTo(decimalValue) >= 0);
  -	        } else if (key.equals(DatatypeValidator.MAXEXCLUSIVE) && fIsMaxExclusive) {
  -	            facetsAreConsistent = (fMaxExclusive.compareTo(decimalValue) > 0);
  -	        } else if (key.equals(DatatypeValidator.SCALE) && fIsScale && fIsPrecision){
  +            } else if (key.equals(SchemaSymbols.ELT_MINEXCLUSIVE) && fIsMinExclusive) {
  +                facetsAreConsistent = (fMinExclusive.compareTo(decimalValue) < 0);
  +            } else if (key.equals(SchemaSymbols.ELT_MAXINCLUSIVE) && fIsMaxInclusive) {
  +                facetsAreConsistent = (fMaxInclusive.compareTo(decimalValue) >= 0);
  +            } else if (key.equals(SchemaSymbols.ELT_MAXEXCLUSIVE) && fIsMaxExclusive) {
  +                facetsAreConsistent = (fMaxExclusive.compareTo(decimalValue) > 0);
  +            } else if (key.equals(SchemaSymbols.ELT_SCALE) && fIsScale && fIsPrecision) {
                   facetsAreConsistent = fScale <= fPrecision;
               }
  -	    }
  -	    return facetsAreConsistent;
  -	}
  -	
  -	public void setFacets(Hashtable facets) throws UnknownFacetException, IllegalFacetException, IllegalFacetValueException {
  +        }
  +        return facetsAreConsistent;
  +    }
  +
  +    public void setFacets(Hashtable facets, String derivationBy) throws UnknownFacetException, IllegalFacetException, IllegalFacetValueException {
           if (fBaseValidator != null)
               if (!fBaseValidator.ensureFacetsAreConsistent(facets))
                   throw new IllegalFacetValueException(
  -					getErrorString(DatatypeMessageProvider.FacetsInconsistent,
  -								   DatatypeMessageProvider.MSG_NONE, 
  -								   null));
  +                                                    getErrorString(DatatypeMessageProvider.FacetsInconsistent,
  +                                                                   DatatypeMessageProvider.MSG_NONE, 
  +                                                                   null));
   
   
  -	    fIsMinInclusive = fIsMinExclusive = fIsMaxInclusive = fIsMaxExclusive = fHasEnums = false;
  -	    for (Enumeration e = facets.keys(); e.hasMoreElements();) {
  -	        String key = (String) e.nextElement();
  -	        String value = null;
  -	        if (key.equals(DatatypeValidator.ENUMERATION)) 
  +        fIsMinInclusive = fIsMinExclusive = fIsMaxInclusive = fIsMaxExclusive = fHasEnums = false;
  +        for (Enumeration e = facets.keys(); e.hasMoreElements();) {
  +            String key = (String) e.nextElement();
  +            String value = null;
  +            if (key.equals(SchemaSymbols.ELT_ENUMERATION))
                   continue;  // ENUM values passed as a vector & handled after bounds facets	    
  -    	    value = (String) facets.get(key);   
  -	        BigDecimal decimalValue = null;
  -	        try {
  -	            decimalValue = new BigDecimal(value);
  -	        } catch (NumberFormatException nfe) {
  -	            throw new IllegalFacetValueException(
  -					getErrorString(DatatypeMessageProvider.IllegalFacetValue,
  -								   DatatypeMessageProvider.MSG_NONE,
  -								   new Object [] { value, key }));
  -	        }
  -	        if (key.equals(DatatypeValidator.MININCLUSIVE)) {
  +            value = (String) facets.get(key);   
  +            BigDecimal decimalValue = null;
  +            try {
  +                decimalValue = new BigDecimal(value);
  +            } catch (NumberFormatException nfe) {
  +                throw new IllegalFacetValueException(
  +                                                    getErrorString(DatatypeMessageProvider.IllegalFacetValue,
  +                                                                   DatatypeMessageProvider.MSG_NONE,
  +                                                                   new Object [] { value, key}));
  +            }
  +            if (key.equals(SchemaSymbols.ELT_MININCLUSIVE)) {
                   fIsMinInclusive = true;
  -	            fMinInclusive = decimalValue;
  -	        } else if (key.equals(DatatypeValidator.MINEXCLUSIVE)) {
  -	            fIsMinExclusive = true;
  -	            fMinExclusive = decimalValue;
  -	        } else if (key.equals(DatatypeValidator.MAXINCLUSIVE)) {
  -	            fIsMaxInclusive = true;
  -	            fMaxInclusive = decimalValue;
  -	        } else if (key.equals(DatatypeValidator.MAXEXCLUSIVE)) {
  -	            fIsMaxExclusive = true;
  -	            fMaxExclusive = decimalValue;
  -	        } else if (key.equals(DatatypeValidator.ENUMERATION)) {
  -	        } else if (key.equals(DatatypeValidator.PRECISION)) {
  +                fMinInclusive = decimalValue;
  +            } else if (key.equals(SchemaSymbols.ELT_MINEXCLUSIVE)) {
  +                fIsMinExclusive = true;
  +                fMinExclusive = decimalValue;
  +            } else if (key.equals(SchemaSymbols.ELT_MAXINCLUSIVE)) {
  +                fIsMaxInclusive = true;
  +                fMaxInclusive = decimalValue;
  +            } else if (key.equals(SchemaSymbols.ELT_MAXEXCLUSIVE)) {
  +                fIsMaxExclusive = true;
  +                fMaxExclusive = decimalValue;
  +            } else if (key.equals(SchemaSymbols.ELT_ENUMERATION)) {
  +            } else if (key.equals(SchemaSymbols.ELT_PRECISION)) {
                   fIsPrecision = true;
                   fPrecision = decimalValue.intValue();
  -	        } else if (key.equals(DatatypeValidator.SCALE)) {
  +            } else if (key.equals(SchemaSymbols.ELT_SCALE)) {
                   fIsScale = true;
                   fScale = decimalValue.intValue();
  -	        } else if (key.equals(DatatypeValidator.LENGTH) ||
  -	                 key.equals(DatatypeValidator.MINLENGTH) ||
  -                     key.equals(DatatypeValidator.MAXLENGTH) ||
  -                     key.equals(DatatypeValidator.LITERAL) ||
  -                     key.equals(DatatypeValidator.ENCODING) ||
  -                     key.equals(DatatypeValidator.PERIOD) ||
  -                     key.equals(DatatypeValidator.PATTERN) ||
  -                     key.equals(DatatypeValidator.LEXICALREPRESENTATION) ||
  -                     key.equals(DatatypeValidator.LEXICAL))
  +            } else if (key.equals(SchemaSymbols.ELT_LENGTH) ||
  +                       key.equals(SchemaSymbols.ELT_MINLENGTH) ||
  +                       key.equals(SchemaSymbols.ELT_MAXLENGTH) ||
  +                       key.equals(SchemaSymbols.ELT_ENCODING) ||
  +                       key.equals(SchemaSymbols.ELT_PERIOD) ||
  +                       key.equals(SchemaSymbols.ELT_PATTERN) )
                   throw new IllegalFacetException(
  -					getErrorString(DatatypeMessageProvider.IllegalDecimalFacet,
  -								   DatatypeMessageProvider.MSG_NONE,
  -								   null));
  -            else 
  +                                               getErrorString(DatatypeMessageProvider.IllegalDecimalFacet,
  +                                                              DatatypeMessageProvider.MSG_NONE,
  +                                                              null));
  +            else
                   throw new UnknownFacetException(
  -					getErrorString(DatatypeMessageProvider.UnknownFacet,
  -								   DatatypeMessageProvider.MSG_NONE,
  -								   new Object [] { key }));
  -	    }
  -	    
  +                                               getErrorString(DatatypeMessageProvider.UnknownFacet,
  +                                                              DatatypeMessageProvider.MSG_NONE,
  +                                                              new Object [] { key}));
  +        }
  +
           // check for scale <= precision
           if (fIsScale && fIsPrecision && fScale > fPrecision)
  -          throw new IllegalFacetException(
  -            getErrorString(DatatypeMessageProvider.ScaleLargerThanPrecision,
  -                           DatatypeMessageProvider.MSG_NONE,
  -                           null));
  -        
  +            throw new IllegalFacetException(
  +                                           getErrorString(DatatypeMessageProvider.ScaleLargerThanPrecision,
  +                                                          DatatypeMessageProvider.MSG_NONE,
  +                                                          null));
  +
           // check the enum values after any range constraints are in place
  -        Vector v = (Vector) facets.get(DatatypeValidator.ENUMERATION);    
  -	    if (v != null) {
  -	        fHasEnums = true;
  -	        fEnumValues = new BigDecimal[v.size()];
  -	        for (int i = 0; i < v.size(); i++)
  -	            try {
  -	                fEnumValues[i] = new BigDecimal((String) v.elementAt(i));
  -	                boundsCheck(fEnumValues[i]);
  -	            } catch (InvalidDatatypeValueException idve) {
  -	                throw new IllegalFacetValueException(
  -						getErrorString(DatatypeMessageProvider.InvalidEnumValue,
  -									   DatatypeMessageProvider.MSG_NONE,
  -									   new Object [] { v.elementAt(i)}));
  -	            } catch (NumberFormatException nfe) {
  -	                System.out.println("Internal Error parsing enumerated values for decimal type");
  -	            }
  -	    }
  -
  -	}
  -	
  -	public void setFacets(int facets[]) throws UnknownFacetException, IllegalFacetException, IllegalFacetValueException {
  -	}
  +        Vector v = (Vector) facets.get(SchemaSymbols.ELT_ENUMERATION);    
  +        if (v != null) {
  +            fHasEnums = true;
  +            fEnumValues = new BigDecimal[v.size()];
  +            for (int i = 0; i < v.size(); i++)
  +                try {
  +                    fEnumValues[i] = new BigDecimal((String) v.elementAt(i));
  +                    boundsCheck(fEnumValues[i]);
  +                } catch (InvalidDatatypeValueException idve) {
  +                    throw new IllegalFacetValueException(
  +                                                        getErrorString(DatatypeMessageProvider.InvalidEnumValue,
  +                                                                       DatatypeMessageProvider.MSG_NONE,
  +                                                                       new Object [] { v.elementAt(i)}));
  +                } catch (NumberFormatException nfe) {
  +                    System.out.println("Internal Error parsing enumerated values for decimal type");
  +                }
  +        }
  +
  +    }
  +
  +    public void setFacets(int facets[]) throws UnknownFacetException, IllegalFacetException, IllegalFacetValueException, ConstrainException {
  +    }
   
  -    public void setBasetype(DatatypeValidator base) {
  -	    fBaseValidator = (DecimalValidator) base;
  +    public void setBasetype(String base) {
  +        //fBaseValidator = (DecimalValidator) base;
       }
   
       /*
  @@ -276,30 +274,30 @@
               maxOk = (d.compareTo(fMaxInclusive) <= 0);
           else if (fIsMaxExclusive)
               maxOk = (d.compareTo(fMaxExclusive) < 0);
  -        else 
  +        else
               maxOk = (!fIsMaxInclusive && !fIsMaxExclusive);
  -        
  +
           if (fIsMinInclusive)
               minOk = (d.compareTo(fMinInclusive) >= 0);
  -        else if (fIsMinExclusive) 
  +        else if (fIsMinExclusive)
               minOk = (d.compareTo(fMinInclusive) > 0);
  -        else 
  +        else
               minOk = (!fIsMinInclusive && !fIsMinExclusive);
           if (!(minOk && maxOk))
               throw new InvalidDatatypeValueException(
  -				getErrorString(DatatypeMessageProvider.OutOfBounds,
  -							   DatatypeMessageProvider.MSG_NONE,
  -							   new Object [] { d }));
  +                                                   getErrorString(DatatypeMessageProvider.OutOfBounds,
  +                                                                  DatatypeMessageProvider.MSG_NONE,
  +                                                                  new Object [] { d}));
       }
  -    
  +
       private void enumCheck(BigDecimal v) throws InvalidDatatypeValueException {
           for (int i = 0; i < fEnumValues.length; i++) {
               if (v == fEnumValues[i]) return;
           }
           throw new InvalidDatatypeValueException(
  -			getErrorString(DatatypeMessageProvider.NotAnEnumValue,
  -						   DatatypeMessageProvider.MSG_NONE,
  -						   new Object [] { v }));
  +                                               getErrorString(DatatypeMessageProvider.NotAnEnumValue,
  +                                                              DatatypeMessageProvider.MSG_NONE,
  +                                                              new Object [] { v}));
       }
   
       /**
  @@ -310,11 +308,11 @@
       }
   
       private String getErrorString(int major, int minor, Object args[]) {
  -         try {
  -             return fMessageProvider.createMessage(fLocale, major, minor, args);
  -         } catch (Exception e) {
  -             return "Illegal Errorcode "+minor;
  -         }
  +        try {
  +            return fMessageProvider.createMessage(fLocale, major, minor, args);
  +        } catch (Exception e) {
  +            return "Illegal Errorcode "+minor;
  +        }
       }
   
       /*
  @@ -337,4 +335,8 @@
           }
       }
       */
  +
  +    public int compare( DatatypeValidator o1, DatatypeValidator o2){
  +        return 0;
  +    }
   }
  
  
  
  1.2       +191 -186  xml-xerces/java/src/org/apache/xerces/validators/datatype/DoubleValidator.java
  
  Index: DoubleValidator.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/validators/datatype/DoubleValidator.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- DoubleValidator.java	1999/12/18 04:25:38	1.1
  +++ DoubleValidator.java	2000/05/17 18:33:13	1.2
  @@ -61,210 +61,210 @@
   import java.util.Hashtable;
   import java.util.Locale;
   import java.util.Vector;
  +import org.apache.xerces.validators.schema.SchemaSymbols;
   
   /**
    *
  - * RealValidator validates that content satisfies the W3C XML Datatype for Real
  - *
    * @author Ted Leung
  + * @author Jeffrey Rodriguez
    * @version
    */
  +
  +public class DoubleValidator implements DatatypeValidator {
  +   private Locale    fLocale           = null;
  +   private String    fBaseValidator    = "native";
  +   private int       _derivationBy     = DatatypeValidator.DERIVED_BY_RESTRICTION;
  +   private double[]  _enumDoubles      = null;
  +   private String    _pattern          = null;
  +   
  +   private double    _maxInclusive    = Double.MAX_VALUE;
  +   private double    _maxExclusive    = Double.MAX_VALUE;
  +   private double    _minInclusive    = Double.MIN_VALUE;
  +   private double    _minExclusive    = Double.MIN_VALUE;
  +
  +   private int       _facetsDefined   = 0;
  +
  +   private boolean isMaxExclusiveDefined = false;
  +   private boolean isMaxInclusiveDefined = false;
  +   private boolean isMinExclusiveDefined = false;
  +   private boolean isMinInclusiveDefined = false;
  +
  +   private DatatypeMessageProvider fMessageProvider = new DatatypeMessageProvider();
   
  -public class DoubleValidator implements InternalDatatypeValidator {
  -	
  -	double fMaxInclusive = 0;
  -	boolean fIsMaxInclusive = false;
  -	double fMaxExclusive = 0;
  -	boolean fIsMaxExclusive = false;
  -	double fMinInclusive = 0;
  -	boolean fIsMinInclusive = false;
  -	double fMinExclusive = 0;
  -	boolean fIsMinExclusive = false;
  -	double fEnumValues[] = null;
  -	boolean fHasEnums = false;
  -	RealValidator fBaseValidator = null;
  -	private DatatypeMessageProvider fMessageProvider = new DatatypeMessageProvider();
  -	private Locale fLocale = null;
  -	
  -	/**
  +    /**
        * validate that a string matches the real datatype
  -     *
  -     * validate returns true or false depending on whether the string content is a
  -     * W3C real type.
  -     * 
        * @param content A string containing the content to be validated
  -     *
        * @exception throws InvalidDatatypeException if the content is
        *  is not a W3C real type
        */
   
  -	public void validate(String content) throws InvalidDatatypeValueException {
  -	    double d = 0;
  -        try {
  -            d = Double.valueOf(content).doubleValue();
  -        } catch (NumberFormatException nfe) {
  -            throw new InvalidDatatypeValueException(
  -				getErrorString(DatatypeMessageProvider.NotReal,
  -							   DatatypeMessageProvider.MSG_NONE,
  -							   new Object [] { content }));
  -        }
  -        boundsCheck(d);
  -        if (fHasEnums)
  -            enumCheck(d);
  -	}
  -			
  -	public void validate(int contentIndex) throws InvalidDatatypeValueException {
  -	}
  -	
  -	//REVISIT: candidate for public API
  -	boolean ensureFacetsAreConsistent(Hashtable facets) {
  -	    boolean facetsAreConsistent = true;
  -	    for (Enumeration e = facets.keys(); facetsAreConsistent && e.hasMoreElements();) {
  -	        String key = (String) e.nextElement();
  -	        String value = null;
  -	        if (key.equals(DatatypeValidator.ENUMERATION)) 
  -                continue;  // ENUM values passed as a vector & handled after bounds facets	    
  -    	    value = (String) facets.get(key);   
  -	        double realValue = 0;
  -	        try {
  -	            realValue = Double.valueOf(value).doubleValue();
  -	        } catch (NumberFormatException nfe) {
  -                facetsAreConsistent = false;
  -	        }
  -	        if (key.equals(DatatypeValidator.MININCLUSIVE) && fIsMinInclusive) {
  -                facetsAreConsistent = fMinInclusive <= realValue;
  -	        } else if (key.equals(DatatypeValidator.MINEXCLUSIVE) && fIsMinExclusive) {
  -	            facetsAreConsistent = fMinExclusive < realValue;
  -	        } else if (key.equals(DatatypeValidator.MAXINCLUSIVE) && fIsMaxInclusive) {
  -	            facetsAreConsistent = fMaxInclusive >= realValue;
  -	        } else if (key.equals(DatatypeValidator.MAXEXCLUSIVE) && fIsMaxExclusive) {
  -	            facetsAreConsistent = fMaxExclusive > realValue;
  -	        }
  -	    }
  -	    return facetsAreConsistent;
  -	}
  -	
  -	public void setFacets(Hashtable facets) throws UnknownFacetException, IllegalFacetException, IllegalFacetValueException {
  -        if (fBaseValidator != null)
  -            if (!fBaseValidator.ensureFacetsAreConsistent(facets))
  -                throw new IllegalFacetValueException(
  -					getErrorString(DatatypeMessageProvider.FacetsInconsistent,
  -								   DatatypeMessageProvider.MSG_NONE,
  -								   null));
  -
  -	    fIsMinInclusive = fIsMinExclusive = fIsMaxInclusive = fIsMaxExclusive = fHasEnums = false;
  -	    for (Enumeration e = facets.keys(); e.hasMoreElements();) {
  -	        String key = (String) e.nextElement();
  -	        String value = null;
  -	        if (key.equals(DatatypeValidator.ENUMERATION)) 
  -                continue;  // ENUM values passed as a vector & handled after bounds facets	    
  -    	    value = (String) facets.get(key);   
  -	        double realValue = 0;
  -	        try {
  -	            realValue = Double.valueOf(value).doubleValue();
  -	        } catch (NumberFormatException nfe) {
  -	            throw new IllegalFacetValueException(
  -					getErrorString(DatatypeMessageProvider.IllegalFacetValue,
  -								   DatatypeMessageProvider.MSG_NONE,
  -								   new Object [] { value, key }));
  -	        }
  -	        if (key.equals(DatatypeValidator.MININCLUSIVE)) {
  -                fIsMinInclusive = true;
  -	            fMinInclusive = realValue;
  -	        } else if (key.equals(DatatypeValidator.MINEXCLUSIVE)) {
  -	            fIsMinExclusive = true;
  -	            fMinExclusive = realValue;
  -	        } else if (key.equals(DatatypeValidator.MAXINCLUSIVE)) {
  -	            fIsMaxInclusive = true;
  -	            fMaxInclusive = realValue;
  -	        } else if (key.equals(DatatypeValidator.MAXEXCLUSIVE)) {
  -	            fIsMaxExclusive = true;
  -	            fMaxExclusive = realValue;
  -	        } else if (key.equals(DatatypeValidator.ENUMERATION)) {
  -	        } else if (key.equals(DatatypeValidator.PRECISION) ||
  -                     key.equals(DatatypeValidator.SCALE) ||
  -                     key.equals(DatatypeValidator.LENGTH) ||
  -                     key.equals(DatatypeValidator.MINLENGTH) ||
  -                     key.equals(DatatypeValidator.MAXLENGTH) ||
  -                     key.equals(DatatypeValidator.LITERAL) ||
  -                     key.equals(DatatypeValidator.PERIOD) ||
  -                     key.equals(DatatypeValidator.ENCODING) ||
  -                     key.equals(DatatypeValidator.PATTERN) ||
  -                     key.equals(DatatypeValidator.LEXICALREPRESENTATION) ||
  -                     key.equals(DatatypeValidator.LEXICAL))
  -                throw new IllegalFacetException(
  -					getErrorString(DatatypeMessageProvider.IllegalRealFacet,
  -								   DatatypeMessageProvider.MSG_NONE,
  -								   null));
  -            else 
  -                throw new UnknownFacetException(
  -					getErrorString(DatatypeMessageProvider.UnknownFacet,
  -								   DatatypeMessageProvider.MSG_NONE,
  -								   new Object [] { key }));
  -	    }
  -	    
  -        // check the enum values after any range constraints are in place
  -        Vector v = (Vector) facets.get(DatatypeValidator.ENUMERATION);    
  -	    if (v != null) {
  -	        fHasEnums = true;
  -	        fEnumValues = new double[v.size()];
  -	        for (int i = 0; i < v.size(); i++)
  -	            try {
  -	                fEnumValues[i] = Double.valueOf((String) v.elementAt(i)).doubleValue();
  -	                boundsCheck(fEnumValues[i]);
  -	            } catch (InvalidDatatypeValueException idve) {
  -	                throw new IllegalFacetValueException(
  -						getErrorString(DatatypeMessageProvider.InvalidEnumValue,
  -									   DatatypeMessageProvider.MSG_NONE,
  -									   new Object [] { v.elementAt(i) }));
  -	            } catch (NumberFormatException nfe) {
  -	                System.out.println("Internal Error parsing enumerated values for real type");
  -	            }
  -	    }
  -
  -	}
  -	
  -	public void setFacets(int facets[]) throws UnknownFacetException, IllegalFacetException, IllegalFacetValueException {
  -	}
  +    public void validate(String content) 
  +                  throws InvalidDatatypeValueException {
  +        if( _derivationBy == DatatypeValidator.DERIVED_BY_RESTRICTION  ){ 
  +             double d = 0.0;
  +             try {
  +                 d = Double.valueOf(content).doubleValue();
  +             } catch (NumberFormatException nfe) {
  +                 throw new InvalidDatatypeValueException(
  +                                                       getErrorString(DatatypeMessageProvider.NotReal,
  +                                                       DatatypeMessageProvider.MSG_NONE,
  +                                                       new Object [] { content }));
  +             }
  +             boundsCheck(d);
  +
  +             if (((_facetsDefined & DatatypeValidator.FACET_ENUMERATION ) != 0 ) )
  +                 enumCheck(d);
  +
  +             } 
  +         else {
  +             ;// TODO Derived by list 
  +             }
  +    }
  +
  +    public void setFacets(Hashtable facets, String derivationBy) throws UnknownFacetException, 
  +                           IllegalFacetException, IllegalFacetValueException, ConstrainException {
  +
  +         for (Enumeration e = facets.keys(); e.hasMoreElements();) {
  +             String key = (String) e.nextElement();
  +
  +             if (key.equals(SchemaSymbols.ELT_PATTERN)) {
  +                 _facetsDefined += DatatypeValidator.FACET_PATTERN;
  +                 _pattern = (String)facets.get(key);
  +             } else if (key.equals(SchemaSymbols.ELT_ENUMERATION)) {
  +                 _facetsDefined += DatatypeValidator.FACET_ENUMERATION;
  +                 continue; //Treat the enumaration after this for loop
  +             } else if (key.equals(SchemaSymbols.ELT_MAXINCLUSIVE)) {
  +                 _facetsDefined += DatatypeValidator.FACET_MAXINCLUSIVE;
  +                 String value = null;
  +                 try {
  +                      value  = ((String)facets.get(key));
  +                     _maxInclusive = Double.valueOf(value).doubleValue();
  +                 } catch (NumberFormatException ex ) {
  +                     throw new IllegalFacetValueException( getErrorString(
  +                        DatatypeMessageProvider.IllegalFacetValue, 
  +                        DatatypeMessageProvider.MSG_NONE, new Object [] { value, key}));
  +                 }
  +             } else if (key.equals(SchemaSymbols.ELT_MAXEXCLUSIVE)) {
  +                 _facetsDefined += DatatypeValidator.FACET_MAXEXCLUSIVE;
  +                 String value = null;
  +                 try  {
  +                      value  = ((String)facets.get(key));
  +                    _maxExclusive = Double.valueOf(value).doubleValue();
  +                 } catch (NumberFormatException ex ) {
  +                     throw new IllegalFacetValueException( getErrorString(
  +                        DatatypeMessageProvider.IllegalFacetValue, 
  +                        DatatypeMessageProvider.MSG_NONE, new Object [] { value, key}));
  +                 }    
  +             } else if (key.equals(SchemaSymbols.ELT_MININCLUSIVE)) {
  +                 _facetsDefined += DatatypeValidator.FACET_MININCLUSIVE;
  +                 String value = null;
  +                 try {
  +                     value  = ((String)facets.get(key));
  +                    _minInclusive  = Double.valueOf(value).doubleValue();
  +                 } catch (NumberFormatException ex ) {
  +                     throw new IllegalFacetValueException( getErrorString(
  +                        DatatypeMessageProvider.IllegalFacetValue, 
  +                        DatatypeMessageProvider.MSG_NONE, new Object [] { value, key}));
  +                 }
  +             } else if (key.equals(SchemaSymbols.ELT_MINEXCLUSIVE)) {
  +                 _facetsDefined += DatatypeValidator.FACET_MININCLUSIVE;
  +                 String value = null;
  +                 try {
  +                    value  = ((String)facets.get(key));
  +                   _minExclusive  = Double.valueOf(value).doubleValue();
  +                 } catch (NumberFormatException ex ) {
  +                    throw new IllegalFacetValueException( getErrorString(
  +                       DatatypeMessageProvider.IllegalFacetValue, 
  +                       DatatypeMessageProvider.MSG_NONE, new Object [] { value, key}));
  +                 }
  +             } else {
  +                 throw new IllegalFacetException( getErrorString(  DatatypeMessageProvider.MSG_FORMAT_FAILURE,
  +                                                                   DatatypeMessageProvider.MSG_NONE,
  +                                                                   null));
  +             }
  +         }
  +        isMaxExclusiveDefined = ((_facetsDefined & 
  +                                  DatatypeValidator.FACET_MAXEXCLUSIVE ) != 0 )?true:false;
  +        isMaxInclusiveDefined = ((_facetsDefined & 
  +                                  DatatypeValidator.FACET_MAXINCLUSIVE ) != 0 )?true:false;
  +        isMinExclusiveDefined = ((_facetsDefined &
  +                                  DatatypeValidator.FACET_MINEXCLUSIVE ) != 0 )?true:false;
  +        isMinInclusiveDefined = ((_facetsDefined &
  +                                  DatatypeValidator.FACET_MININCLUSIVE ) != 0 )?true:false;
  +
  +
  +        if ( isMaxExclusiveDefined && isMaxInclusiveDefined ) {
  +           throw new ConstrainException(
  +                                       "It is an error for both maxInclusive and maxExclusive to be specified for the same datatype." ); 
  +        }
  +        if ( isMinExclusiveDefined && isMinInclusiveDefined ) {
  +           throw new ConstrainException(
  +                                       "It is an error for both minInclusive and minExclusive to be specified for the same datatype." ); 
  +        }
   
  -    public void setBasetype(DatatypeValidator base) {
  -	    fBaseValidator = (RealValidator) base;
  +
  +
  +        if( (_facetsDefined & DatatypeValidator.FACET_ENUMERATION ) != 0 ){
  +            Vector v = (Vector) facets.get(SchemaSymbols.ELT_ENUMERATION);    
  +            if (v != null) {
  +                 _enumDoubles = new double[v.size()];
  +                 for (int i = 0; i < v.size(); i++)
  +                     try {
  +                         _enumDoubles[i] = Double.valueOf((String) v.elementAt(i)).doubleValue();
  +                         boundsCheck(_enumDoubles[i]); // Check against max,min Inclusive, Exclusives
  +                 } catch (InvalidDatatypeValueException idve) {
  +                    throw new IllegalFacetValueException(
  +                                                        getErrorString(DatatypeMessageProvider.InvalidEnumValue,
  +                                                                       DatatypeMessageProvider.MSG_NONE,
  +                                                                       new Object [] { v.elementAt(i)}));
  +                } catch (NumberFormatException nfe) {
  +                    System.out.println("Internal Error parsing enumerated values for real type");
  +                }
  +            }
  +        }
       }
   
  +
  +    public void setBasetype(String base) {
  +        fBaseValidator =  base;
  +    }
  +
  +
  +
       /*
        * check that a facet is in range, assumes that facets are compatible -- compatibility ensured by setFacets
        */
       private void boundsCheck(double d) throws InvalidDatatypeValueException {
  -        boolean minOk = false;
  -        boolean maxOk = false;
  -        if (fIsMaxInclusive)
  -            maxOk = (d <= fMaxInclusive);
  -        else if (fIsMaxExclusive)
  -            maxOk = (d < fMaxExclusive);
  -        else 
  -            maxOk = (!fIsMaxInclusive && !fIsMaxExclusive);
  -        
  -        if (fIsMinInclusive)
  -            minOk = (d >= fMinInclusive);
  -        else if (fIsMinExclusive) 
  -            minOk = (d > fMinInclusive);
  -        else 
  -            minOk = (!fIsMinInclusive && !fIsMinExclusive);
  -        if (!(minOk && maxOk))
  -            throw new InvalidDatatypeValueException(
  -				getErrorString(DatatypeMessageProvider.OutOfBounds,
  -							   DatatypeMessageProvider.MSG_NONE,
  -							   new Object [] { new Double(d) }));
  +        boolean inUpperBound = false;
  +        boolean inLowerBound = false;
  +
  +        if( isMaxInclusiveDefined ){
  +            inUpperBound = ( d <= _maxInclusive );
  +        }else if( isMaxExclusiveDefined ){
  +            inUpperBound = ( d <  _maxExclusive );
  +        }
  +
  +        if( isMinInclusiveDefined ){
  +            inLowerBound = ( d >= _minInclusive );
  +        }else if( isMinExclusiveDefined ){
  +            inLowerBound = ( d >  _minExclusive );
  +        }
  +
  +        if( inUpperBound == false  || inLowerBound == false ) { // within bounds ?
  +            getErrorString(DatatypeMessageProvider.OutOfBounds,
  +                           DatatypeMessageProvider.MSG_NONE,
  +                           new Object [] { new Double(d)});
  +        }
       }
  -    
  +
       private void enumCheck(double v) throws InvalidDatatypeValueException {
  -        for (int i = 0; i < fEnumValues.length; i++) {
  -            if (v == fEnumValues[i]) return;
  +        for (int i = 0; i < _enumDoubles.length; i++) {
  +            if (v == _enumDoubles[i]) return;
           }
  -		throw new InvalidDatatypeValueException(
  -			getErrorString(DatatypeMessageProvider.NotAnEnumValue,
  -						   DatatypeMessageProvider.MSG_NONE,
  -						   new Object [] { new Double(v) }));
  +        throw new InvalidDatatypeValueException(
  +                                               getErrorString(DatatypeMessageProvider.NotAnEnumValue,
  +                                                              DatatypeMessageProvider.MSG_NONE,
  +                                                              new Object [] { new Double(v)}));
       }
   
       /**
  @@ -274,11 +274,16 @@
           fLocale = locale;
       }
   
  +    public int compare( DatatypeValidator o1, DatatypeValidator o2){
  +        return 0;
  +    }
  +
       private String getErrorString(int major, int minor, Object args[]) {
  -         try {
  -             return fMessageProvider.createMessage(fLocale, major, minor, args);
  -         } catch (Exception e) {
  -             return "Illegal Errorcode "+minor;
  -         }
  +        try {
  +            return fMessageProvider.createMessage(fLocale, major, minor, args);
  +        } catch (Exception e) {
  +            return "Illegal Errorcode "+minor;
  +        }
       }
  +
   }
  
  
  
  1.2       +192 -186  xml-xerces/java/src/org/apache/xerces/validators/datatype/FloatValidator.java
  
  Index: FloatValidator.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/validators/datatype/FloatValidator.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- FloatValidator.java	1999/12/18 04:25:38	1.1
  +++ FloatValidator.java	2000/05/17 18:33:13	1.2
  @@ -61,210 +61,211 @@
   import java.util.Hashtable;
   import java.util.Locale;
   import java.util.Vector;
  +import org.apache.xerces.validators.schema.SchemaSymbols;
   
   /**
    *
  - * RealValidator validates that content satisfies the W3C XML Datatype for Real
  - *
    * @author Ted Leung
  + * @author Jeffrey Rodriguez
    * @version
    */
  +
  +public class FloatValidator implements DatatypeValidator {
  +   private Locale    fLocale        = null;
  +   private String    fBaseValidator = "native";
  +   private float[] _enumFloats      = null;
  +   private String  _pattern         = null;
  +   private int       _derivationBy     = DatatypeValidator.DERIVED_BY_RESTRICTION;
  +
  +   
  +   private float   _maxInclusive    = Float.MAX_VALUE;
  +   private float   _maxExclusive    = Float.MAX_VALUE;
  +   private float   _minInclusive    = Float.MIN_VALUE;
  +   private float   _minExclusive    = Float.MIN_VALUE;
  +
  +   private int     _facetsDefined   = 0;
  +
  +   private boolean isMaxExclusiveDefined = false;
  +   private boolean isMaxInclusiveDefined = false;
  +   private boolean isMinExclusiveDefined = false;
  +   private boolean isMinInclusiveDefined = false;
  +
  +   private DatatypeMessageProvider fMessageProvider = new DatatypeMessageProvider();
   
  -public class FloatValidator implements InternalDatatypeValidator {
  -	
  -	double fMaxInclusive = 0;
  -	boolean fIsMaxInclusive = false;
  -	double fMaxExclusive = 0;
  -	boolean fIsMaxExclusive = false;
  -	double fMinInclusive = 0;
  -	boolean fIsMinInclusive = false;
  -	double fMinExclusive = 0;
  -	boolean fIsMinExclusive = false;
  -	float fEnumValues[] = null;
  -	boolean fHasEnums = false;
  -	RealValidator fBaseValidator = null;
  -	private DatatypeMessageProvider fMessageProvider = new DatatypeMessageProvider();
  -	private Locale fLocale = null;
  -	
  -	/**
  +    /**
        * validate that a string matches the real datatype
  -     *
  -     * validate returns true or false depending on whether the string content is a
  -     * W3C real type.
  -     * 
        * @param content A string containing the content to be validated
  -     *
        * @exception throws InvalidDatatypeException if the content is
        *  is not a W3C real type
        */
   
  -	public void validate(String content) throws InvalidDatatypeValueException {
  -	    float f = 0;
  -        try {
  -            f = Float.valueOf(content).floatValue();
  -        } catch (NumberFormatException nfe) {
  -            throw new InvalidDatatypeValueException(
  -				getErrorString(DatatypeMessageProvider.NotReal,
  -							   DatatypeMessageProvider.MSG_NONE,
  -							   new Object [] { content }));
  -        }
  -        boundsCheck(f);
  -        if (fHasEnums)
  -            enumCheck(f);
  -	}
  -			
  -	public void validate(int contentIndex) throws InvalidDatatypeValueException {
  -	}
  -	
  -	//REVISIT: candidate for public API
  -	boolean ensureFacetsAreConsistent(Hashtable facets) {
  -	    boolean facetsAreConsistent = true;
  -	    for (Enumeration e = facets.keys(); facetsAreConsistent && e.hasMoreElements();) {
  -	        String key = (String) e.nextElement();
  -	        String value = null;
  -	        if (key.equals(DatatypeValidator.ENUMERATION)) 
  -                continue;  // ENUM values passed as a vector & handled after bounds facets	    
  -    	    value = (String) facets.get(key);   
  -	        float realValue = 0;
  -	        try {
  -	            realValue = Float.valueOf(value).floatValue();
  -	        } catch (NumberFormatException nfe) {
  -                facetsAreConsistent = false;
  -	        }
  -	        if (key.equals(DatatypeValidator.MININCLUSIVE) && fIsMinInclusive) {
  -                facetsAreConsistent = fMinInclusive <= realValue;
  -	        } else if (key.equals(DatatypeValidator.MINEXCLUSIVE) && fIsMinExclusive) {
  -	            facetsAreConsistent = fMinExclusive < realValue;
  -	        } else if (key.equals(DatatypeValidator.MAXINCLUSIVE) && fIsMaxInclusive) {
  -	            facetsAreConsistent = fMaxInclusive >= realValue;
  -	        } else if (key.equals(DatatypeValidator.MAXEXCLUSIVE) && fIsMaxExclusive) {
  -	            facetsAreConsistent = fMaxExclusive > realValue;
  -	        }
  -	    }
  -	    return facetsAreConsistent;
  -	}
  -	
  -	public void setFacets(Hashtable facets) throws UnknownFacetException, IllegalFacetException, IllegalFacetValueException {
  -        if (fBaseValidator != null)
  -            if (!fBaseValidator.ensureFacetsAreConsistent(facets))
  -                throw new IllegalFacetValueException(
  -					getErrorString(DatatypeMessageProvider.FacetsInconsistent,
  -								   DatatypeMessageProvider.MSG_NONE,
  -								   null));
  -
  -	    fIsMinInclusive = fIsMinExclusive = fIsMaxInclusive = fIsMaxExclusive = fHasEnums = false;
  -	    for (Enumeration e = facets.keys(); e.hasMoreElements();) {
  -	        String key = (String) e.nextElement();
  -	        String value = null;
  -	        if (key.equals(DatatypeValidator.ENUMERATION)) 
  -                continue;  // ENUM values passed as a vector & handled after bounds facets	    
  -    	    value = (String) facets.get(key);   
  -	        float realValue = 0;
  -	        try {
  -	            realValue = Float.valueOf(value).floatValue();
  -	        } catch (NumberFormatException nfe) {
  -	            throw new IllegalFacetValueException(
  -					getErrorString(DatatypeMessageProvider.IllegalFacetValue,
  -								   DatatypeMessageProvider.MSG_NONE,
  -								   new Object [] { value, key }));
  -	        }
  -	        if (key.equals(DatatypeValidator.MININCLUSIVE)) {
  -                fIsMinInclusive = true;
  -	            fMinInclusive = realValue;
  -	        } else if (key.equals(DatatypeValidator.MINEXCLUSIVE)) {
  -	            fIsMinExclusive = true;
  -	            fMinExclusive = realValue;
  -	        } else if (key.equals(DatatypeValidator.MAXINCLUSIVE)) {
  -	            fIsMaxInclusive = true;
  -	            fMaxInclusive = realValue;
  -	        } else if (key.equals(DatatypeValidator.MAXEXCLUSIVE)) {
  -	            fIsMaxExclusive = true;
  -	            fMaxExclusive = realValue;
  -	        } else if (key.equals(DatatypeValidator.ENUMERATION)) {
  -	        } else if (key.equals(DatatypeValidator.PRECISION) ||
  -                     key.equals(DatatypeValidator.SCALE) ||
  -                     key.equals(DatatypeValidator.LENGTH) ||
  -                     key.equals(DatatypeValidator.MINLENGTH) ||
  -                     key.equals(DatatypeValidator.MAXLENGTH) ||
  -                     key.equals(DatatypeValidator.LITERAL) ||
  -                     key.equals(DatatypeValidator.ENCODING) ||
  -                     key.equals(DatatypeValidator.PERIOD) ||
  -                     key.equals(DatatypeValidator.PATTERN) ||
  -                     key.equals(DatatypeValidator.LEXICALREPRESENTATION) ||
  -                     key.equals(DatatypeValidator.LEXICAL))
  -                throw new IllegalFacetException(
  -					getErrorString(DatatypeMessageProvider.IllegalRealFacet,
  -								   DatatypeMessageProvider.MSG_NONE,
  -								   null));
  -            else 
  -                throw new UnknownFacetException(
  -					getErrorString(DatatypeMessageProvider.UnknownFacet,
  -								   DatatypeMessageProvider.MSG_NONE,
  -								   new Object [] { key }));
  -	    }
  -	    
  -        // check the enum values after any range constraints are in place
  -        Vector v = (Vector) facets.get(DatatypeValidator.ENUMERATION);    
  -	    if (v != null) {
  -	        fHasEnums = true;
  -	        fEnumValues = new float[v.size()];
  -	        for (int i = 0; i < v.size(); i++)
  -	            try {
  -	                fEnumValues[i] = Float.valueOf((String) v.elementAt(i)).floatValue();
  -	                boundsCheck(fEnumValues[i]);
  -	            } catch (InvalidDatatypeValueException idve) {
  -	                throw new IllegalFacetValueException(
  -						getErrorString(DatatypeMessageProvider.InvalidEnumValue,
  -									   DatatypeMessageProvider.MSG_NONE,
  -									   new Object [] { v.elementAt(i) }));
  -	            } catch (NumberFormatException nfe) {
  -	                System.out.println("Internal Error parsing enumerated values for real type");
  -	            }
  -	    }
  -
  -	}
  -	
  -	public void setFacets(int facets[]) throws UnknownFacetException, IllegalFacetException, IllegalFacetValueException {
  -	}
  +    public void validate(String content) 
  +                  throws InvalidDatatypeValueException {
  +        if( _derivationBy == DatatypeValidator.DERIVED_BY_RESTRICTION  ){ 
  +             float f = 0;
  +             try {
  +                 f = Float.valueOf(content).floatValue();
  +             } catch (NumberFormatException nfe) {
  +                 throw new InvalidDatatypeValueException(
  +                                                       getErrorString(DatatypeMessageProvider.NotReal,
  +                                                       DatatypeMessageProvider.MSG_NONE,
  +                                                       new Object [] { content }));
  +             }
  +             boundsCheck(f);
  +
  +             if (((_facetsDefined & DatatypeValidator.FACET_ENUMERATION ) != 0 ) )
  +                 enumCheck(f);
  +
  +             } 
  +         else {
  +             ;// TODO Derived by list 
  +             }
  +    }
  +
  +    public void setFacets(Hashtable facets, String derivationBy) throws UnknownFacetException, 
  +                           IllegalFacetException, IllegalFacetValueException, ConstrainException {
  +
  +         for (Enumeration e = facets.keys(); e.hasMoreElements();) {
  +             String key = (String) e.nextElement();
  +
  +             if (key.equals(SchemaSymbols.ELT_PATTERN)) {
  +                 _facetsDefined += DatatypeValidator.FACET_PATTERN;
  +                 _pattern = (String)facets.get(key);
  +             } else if (key.equals(SchemaSymbols.ELT_ENUMERATION)) {
  +                 _facetsDefined += DatatypeValidator.FACET_ENUMERATION;
  +                 continue; //Treat the enumaration after this for loop
  +             } else if (key.equals(SchemaSymbols.ELT_MAXINCLUSIVE)) {
  +                 _facetsDefined += DatatypeValidator.FACET_MAXINCLUSIVE;
  +                 String value = null;
  +                 try {
  +                      value  = ((String)facets.get(key));
  +                     _maxInclusive = Float.valueOf(value).floatValue();
  +                 } catch (NumberFormatException ex ) {
  +                     throw new IllegalFacetValueException( getErrorString(
  +                        DatatypeMessageProvider.IllegalFacetValue, 
  +                        DatatypeMessageProvider.MSG_NONE, new Object [] { value, key}));
  +                 }
  +             } else if (key.equals(SchemaSymbols.ELT_MAXEXCLUSIVE)) {
  +                 _facetsDefined += DatatypeValidator.FACET_MAXEXCLUSIVE;
  +                 String value = null;
  +                 try  {
  +                      value  = ((String)facets.get(key));
  +                    _maxExclusive = Float.valueOf(value).floatValue();
  +                 } catch (NumberFormatException ex ) {
  +                     throw new IllegalFacetValueException( getErrorString(
  +                        DatatypeMessageProvider.IllegalFacetValue, 
  +                        DatatypeMessageProvider.MSG_NONE, new Object [] { value, key}));
  +                 }    
  +             } else if (key.equals(SchemaSymbols.ELT_MININCLUSIVE)) {
  +                 _facetsDefined += DatatypeValidator.FACET_MININCLUSIVE;
  +                 String value = null;
  +                 try {
  +                     value  = ((String)facets.get(key));
  +                    _minInclusive  = Float.valueOf(value).floatValue();
  +                 } catch (NumberFormatException ex ) {
  +                     throw new IllegalFacetValueException( getErrorString(
  +                        DatatypeMessageProvider.IllegalFacetValue, 
  +                        DatatypeMessageProvider.MSG_NONE, new Object [] { value, key}));
  +                 }
  +             } else if (key.equals(SchemaSymbols.ELT_MINEXCLUSIVE)) {
  +                 _facetsDefined += DatatypeValidator.FACET_MININCLUSIVE;
  +                 String value = null;
  +                 try {
  +                    value  = ((String)facets.get(key));
  +                   _minExclusive  = Float.valueOf(value).floatValue();
  +                 } catch (NumberFormatException ex ) {
  +                    throw new IllegalFacetValueException( getErrorString(
  +                       DatatypeMessageProvider.IllegalFacetValue, 
  +                       DatatypeMessageProvider.MSG_NONE, new Object [] { value, key}));
  +                 }
  +             } else {
  +                 throw new IllegalFacetException( getErrorString(  DatatypeMessageProvider.MSG_FORMAT_FAILURE,
  +                                                                   DatatypeMessageProvider.MSG_NONE,
  +                                                                   null));
  +             }
  +         }
  +        isMaxExclusiveDefined = ((_facetsDefined & 
  +                                  DatatypeValidator.FACET_MAXEXCLUSIVE ) != 0 )?true:false;
  +        isMaxInclusiveDefined = ((_facetsDefined & 
  +                                  DatatypeValidator.FACET_MAXINCLUSIVE ) != 0 )?true:false;
  +        isMinExclusiveDefined = ((_facetsDefined &
  +                                  DatatypeValidator.FACET_MINEXCLUSIVE ) != 0 )?true:false;
  +        isMinInclusiveDefined = ((_facetsDefined &
  +                                  DatatypeValidator.FACET_MININCLUSIVE ) != 0 )?true:false;
  +
  +
  +        if ( isMaxExclusiveDefined && isMaxInclusiveDefined ) {
  +           throw new ConstrainException(
  +                                       "It is an error for both maxInclusive and maxExclusive to be specified for the same datatype." ); 
  +        }
  +        if ( isMinExclusiveDefined && isMinInclusiveDefined ) {
  +           throw new ConstrainException(
  +                                       "It is an error for both minInclusive and minExclusive to be specified for the same datatype." ); 
  +        }
   
  -    public void setBasetype(DatatypeValidator base) {
  -	    fBaseValidator = (RealValidator) base;
  +
  +
  +        if( (_facetsDefined & DatatypeValidator.FACET_ENUMERATION ) != 0 ){
  +            Vector v = (Vector) facets.get(SchemaSymbols.ELT_ENUMERATION);    
  +            if (v != null) {
  +                 _enumFloats = new float[v.size()];
  +                 for (int i = 0; i < v.size(); i++)
  +                     try {
  +                         _enumFloats[i] = Float.valueOf((String) v.elementAt(i)).floatValue();
  +                         boundsCheck(_enumFloats[i]); // Check against max,min Inclusive, Exclusives
  +                 } catch (InvalidDatatypeValueException idve) {
  +                    throw new IllegalFacetValueException(
  +                                                        getErrorString(DatatypeMessageProvider.InvalidEnumValue,
  +                                                                       DatatypeMessageProvider.MSG_NONE,
  +                                                                       new Object [] { v.elementAt(i)}));
  +                } catch (NumberFormatException nfe) {
  +                    System.out.println("Internal Error parsing enumerated values for real type");
  +                }
  +            }
  +        }
       }
   
  +
  +    public void setBasetype(String base) {
  +        fBaseValidator =  base;
  +    }
  +
  +
  +
       /*
        * check that a facet is in range, assumes that facets are compatible -- compatibility ensured by setFacets
        */
       private void boundsCheck(float f) throws InvalidDatatypeValueException {
  -        boolean minOk = false;
  -        boolean maxOk = false;
  -        if (fIsMaxInclusive)
  -            maxOk = (f <= fMaxInclusive);
  -        else if (fIsMaxExclusive)
  -            maxOk = (f < fMaxExclusive);
  -        else 
  -            maxOk = (!fIsMaxInclusive && !fIsMaxExclusive);
  -        
  -        if (fIsMinInclusive)
  -            minOk = (f >= fMinInclusive);
  -        else if (fIsMinExclusive) 
  -            minOk = (f > fMinInclusive);
  -        else 
  -            minOk = (!fIsMinInclusive && !fIsMinExclusive);
  -        if (!(minOk && maxOk))
  -            throw new InvalidDatatypeValueException(
  -				getErrorString(DatatypeMessageProvider.OutOfBounds,
  -							   DatatypeMessageProvider.MSG_NONE,
  -							   new Object [] { new Float(f) }));
  +        boolean inUpperBound = false;
  +        boolean inLowerBound = false;
  +
  +        if( isMaxInclusiveDefined ){
  +            inUpperBound = ( f <= _maxInclusive );
  +        }else if( isMaxExclusiveDefined ){
  +            inUpperBound = ( f <  _maxExclusive );
  +        }
  +
  +        if( isMinInclusiveDefined ){
  +            inLowerBound = ( f >= _minInclusive );
  +        }else if( isMinExclusiveDefined ){
  +            inLowerBound = ( f >  _minExclusive );
  +        }
  +
  +        if( inUpperBound == false  || inLowerBound == false ) { // within bounds ?
  +            getErrorString(DatatypeMessageProvider.OutOfBounds,
  +                           DatatypeMessageProvider.MSG_NONE,
  +                           new Object [] { new Float(f)});
  +        }
       }
  -    
  +
       private void enumCheck(float v) throws InvalidDatatypeValueException {
  -        for (int i = 0; i < fEnumValues.length; i++) {
  -            if (v == fEnumValues[i]) return;
  +        for (int i = 0; i < _enumFloats.length; i++) {
  +            if (v == _enumFloats[i]) return;
           }
  -		throw new InvalidDatatypeValueException(
  -			getErrorString(DatatypeMessageProvider.NotAnEnumValue,
  -						   DatatypeMessageProvider.MSG_NONE,
  -						   new Object [] { new Float(v) }));
  +        throw new InvalidDatatypeValueException(
  +                                               getErrorString(DatatypeMessageProvider.NotAnEnumValue,
  +                                                              DatatypeMessageProvider.MSG_NONE,
  +                                                              new Object [] { new Float(v)}));
       }
   
       /**
  @@ -274,11 +275,16 @@
           fLocale = locale;
       }
   
  +    public int compare( DatatypeValidator o1, DatatypeValidator o2){
  +        return 0;
  +    }
  +
       private String getErrorString(int major, int minor, Object args[]) {
  -         try {
  -             return fMessageProvider.createMessage(fLocale, major, minor, args);
  -         } catch (Exception e) {
  -             return "Illegal Errorcode "+minor;
  -         }
  +        try {
  +            return fMessageProvider.createMessage(fLocale, major, minor, args);
  +        } catch (Exception e) {
  +            return "Illegal Errorcode "+minor;
  +        }
       }
  +
   }
  
  
  
  1.5       +16 -6     xml-xerces/java/src/org/apache/xerces/validators/datatype/Makefile
  
  Index: Makefile
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/validators/datatype/Makefile,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- Makefile	2000/02/29 02:02:21	1.4
  +++ Makefile	2000/05/17 18:33:14	1.5
  @@ -1,20 +1,30 @@
   # Makefile for directory ./org/apache/xerces/validators/datatype
   
   TARGETS=\
  +	BinaryValidator.class\
   	BooleanValidator.class\
   	DatatypeMessageProvider.class\
   	DatatypeValidator.class\
  +	DatatypeValidatorRegistry.class\
   	DecimalValidator.class\
  +	DoubleValidator.class\
  +	FloatValidator.class\
  +	ConstrainException.class\
   	IllegalFacetException.class\
   	IllegalFacetValueException.class\
  -	IntegerValidator.class\
  -	InternalDatatypeValidator.class\
   	InvalidDatatypeValueException.class\
  -	RealValidator.class\
  +	RecurringDurationValidator.class\
   	StringValidator.class\
  -        TimeDurationValidator.java \
  -        TimeInstantValidator.java \
  -	UnknownFacetException.class
  +	TimeDurationValidator.class\
  +	UnknownFacetException.class\
  +	URIReferenceValidator.class \
  +	IDValidator.class \
  +	IDREFValidator.class \
  +	ENTITYValidator.class \
  +	NOTATIONValidator.class \
  +	QNameValidator.class\
  +	URIReferenceValidator.class \
  +	DatatypeValidatorRegistry.class 
   
   DIRS = 
   
  
  
  
  1.6       +275 -72   xml-xerces/java/src/org/apache/xerces/validators/datatype/StringValidator.java
  
  Index: StringValidator.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/validators/datatype/StringValidator.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- StringValidator.java	2000/01/29 00:26:58	1.5
  +++ StringValidator.java	2000/05/17 18:33:15	1.6
  @@ -61,99 +61,302 @@
   import java.util.Vector;
   import java.util.Enumeration;
   import java.util.Locale;
  +import java.text.Collator;
   import java.util.Enumeration;
  +import java.util.StringTokenizer;
  +import java.util.NoSuchElementException;
  +import org.apache.xerces.validators.schema.SchemaSymbols;
  +import org.apache.xerces.utils.regex.RegularExpression;
   
   /**
  - *
    * StringValidator validates that XML content is a W3C string type.
  - *
    * @author Ted Leung
  - * @version
  + * @author Kito D. Mann, Virtua Communications Corp.
  + * @author Jeffrey Rodriguez
    */
  +public class StringValidator implements DatatypeValidator {
  +    private Locale    fLocale          = null;
  +    private String    fBaseValidator   = "native";
   
  -public class StringValidator implements InternalDatatypeValidator {
  -	
  -    private Locale fLocale = null;
  -    Hashtable facetData = null;
  -    StringValidator fBaseValidator = null;
  -    int fMaxLength = 0;
  -    boolean fIsMaxLength = false;
  -	
  -	/**
  +    private int       _length          = 0;
  +    private int       _maxLength       = 0;
  +    private int       _minLength       = 0;
  +    private String    _pattern         = null;
  +    private Vector    _enumeration     = null;
  +    private String    _maxInclusive    = null;
  +    private String    _maxExclusive    = null;
  +    private String    _minInclusive    = null;
  +    private String    _minExclusive    = null;
  +    private int       _facetsDefined   = 0;
  +    private int       _derivedBy       = DatatypeValidator.DERIVED_BY_RESTRICTION;//default
  +
  +    private boolean isMaxExclusiveDefined = false;
  +    private boolean isMaxInclusiveDefined = false;
  +    private boolean isMinExclusiveDefined = false;
  +    private boolean isMinInclusiveDefined = false;
  +
  +    /**
        * validate that a string is a W3C string type
  -     *
  -     * validate returns true or false depending on whether the string content is an
  -     * instance of the W3C string datatype
        * 
        * @param content A string containing the content to be validated
  -     *
  +     * @param list
        * @exception throws InvalidDatatypeException if the content is
  -     *  not a W3C string type
  +     *                   not a W3C string type
  +     * @exception InvalidDatatypeValueException
        */
  +    public void validate(String content)  throws InvalidDatatypeValueException
  +    {
  +        if ( _facetsDefined == 0 )// No Facets to validate against
  +            return;
  +
  +        if( _derivedBy == DatatypeValidator.DERIVED_BY_RESTRICTION  ){ 
  +            checkContent( content );
   
  -	public void validate(String content) throws InvalidDatatypeValueException {
  +        } else {
  +            StringTokenizer parsedList = new StringTokenizer( content );
  +            try {
  +               while ( parsedList.hasMoreTokens() ) {
  +                   checkContentList( parsedList.nextToken() );
  +               }
  +            } catch ( NoSuchElementException e ) {
  +                e.printStackTrace();
  +            }
  +        }
  +    }
   
  -        if (facetData == null)return;
   
  -        Enumeration eee = facetData.keys();
  -        while(eee.hasMoreElements()) {
  -            String key = (String)eee.nextElement();
  -            if (key.equals(DatatypeValidator.ENUMERATION)) {
  -                Vector value = (Vector)facetData.get(key);
  -                String vvv = value.toString();
  -                if (!value.contains(content)) 
  -                    throw new InvalidDatatypeValueException("Value '"+content+"' must be one of "+vvv);
  -            }
  -            else if (key.equals(DatatypeValidator.MAXLENGTH)) {
  -                if (fIsMaxLength && content.length() > fMaxLength)
  -                    throw new InvalidDatatypeValueException("Value '"+content+"' with length '"+content.length()+"' exceeds maximum length of "+fMaxLength+".");
  -            }
  -        }
  -	}
  -			
  -	public void validate(int contentIndex) throws InvalidDatatypeValueException {
  -	}
  -	
  -	public void setFacets(Hashtable facets) throws UnknownFacetException, IllegalFacetException, IllegalFacetValueException {
  -	    facetData = new Hashtable(); // reset old facets
  -        for (Enumeration e = facets.keys(); e.hasMoreElements();) {
  -            String key = (String) e.nextElement();
  -            if (key.equals(DatatypeValidator.LENGTH)) {
  -            } else if (key.equals(DatatypeValidator.MINLENGTH)) {
  -            } else if (key.equals(DatatypeValidator.MAXLENGTH)) {
  -                int vvv;
  -                String value = (String)facetData.get(key);
  -                try {
  -                    vvv = Integer.parseInt(value);
  -                } catch(NumberFormatException nfe) {
  -                    throw new IllegalFacetValueException("maxLength value '"+value+"' is invalid.");
  +    public void setFacets(Hashtable facets, String derivationBy) throws UnknownFacetException,
  +    IllegalFacetException, IllegalFacetValueException, ConstrainException 
  +    {
  +        if( facets == null )
  +            return;// No facets to set.
  +
  +
  +        if( derivationBy.equals( SchemaSymbols.ATTVAL_RESTRICTION )){
  +            for (Enumeration e = facets.keys(); e.hasMoreElements();) {
  +                String key = (String) e.nextElement();
  +
  +                if ( key.equals(SchemaSymbols.ELT_LENGTH) ) {
  +                    _facetsDefined += DatatypeValidator.FACET_LENGTH;
  +                    String lengthValue = (String)facets.get(key);
  +                    try {
  +                        _length     = Integer.parseInt( lengthValue );
  +                    } catch (NumberFormatException nfe) {
  +                        throw new IllegalFacetValueException("Length value '"+lengthValue+"' is invalid.");
  +                    }
  +                    if ( _length < 0 )
  +                        throw new IllegalFacetValueException("Length value '"+lengthValue+"'  must be a nonNegativeInteger.");
  +
  +                } else if (key.equals(SchemaSymbols.ELT_MINLENGTH) ) {
  +                    _facetsDefined += DatatypeValidator.FACET_MINLENGTH;
  +                    String minLengthValue = (String)facets.get(key);
  +                    try {
  +                        _minLength     = Integer.parseInt( minLengthValue );
  +                    } catch (NumberFormatException nfe) {
  +                        throw new IllegalFacetValueException("maxLength value '"+minLengthValue+"' is invalid.");
  +                    }
  +                } else if (key.equals(SchemaSymbols.ELT_MAXLENGTH) ) {
  +                    _facetsDefined += DatatypeValidator.FACET_MAXLENGTH;
  +                    String maxLengthValue = (String)facets.get(key);
  +                    try {
  +                        _maxLength     = Integer.parseInt( maxLengthValue );
  +                    } catch (NumberFormatException nfe) {
  +                        throw new IllegalFacetValueException("maxLength value '"+maxLengthValue+"' is invalid.");
  +                    }
  +                } else if (key.equals(SchemaSymbols.ELT_PATTERN)) {
  +                    _facetsDefined += DatatypeValidator.FACET_PATTERN;
  +                    _pattern = (String)facets.get(key);
  +                } else if (key.equals(SchemaSymbols.ELT_ENUMERATION)) {
  +                    _facetsDefined += DatatypeValidator.FACET_ENUMERATION;
  +                    _enumeration = (Vector)facets.get(key);
  +                } else if (key.equals(SchemaSymbols.ELT_MAXINCLUSIVE)) {
  +                    _facetsDefined += DatatypeValidator.FACET_MAXINCLUSIVE;
  +                    _maxInclusive = (String)facets.get(key);
  +                } else if (key.equals(SchemaSymbols.ELT_MAXEXCLUSIVE)) {
  +                    _facetsDefined += DatatypeValidator.FACET_MAXEXCLUSIVE;
  +                    _maxExclusive = (String)facets.get(key);
  +                } else if (key.equals(SchemaSymbols.ELT_MININCLUSIVE)) {
  +                    _facetsDefined += DatatypeValidator.FACET_MININCLUSIVE;
  +                    _minInclusive = (String)facets.get(key);
  +                } else if (key.equals(SchemaSymbols.ELT_MINEXCLUSIVE)) {
  +                    _facetsDefined += DatatypeValidator.FACET_MININCLUSIVE;
  +                    _minExclusive = (String)facets.get(key);
  +                } else {
  +                    throw new IllegalFacetException();
                   }
  -                fMaxLength = vvv;
  -                fIsMaxLength = true;
  -            } else if (key.equals(DatatypeValidator.MAXINCLUSIVE)) {
  -            } else if (key.equals(DatatypeValidator.MAXEXCLUSIVE)) {
  -            } else if (key.equals(DatatypeValidator.MININCLUSIVE)) {
  -            } else if (key.equals(DatatypeValidator.MINEXCLUSIVE)) {
  -            } else if (key.equals(DatatypeValidator.PATTERN)) {
  -            } else if (key.equals(DatatypeValidator.ENUMERATION)) {
  -                facetData.put(key,facets.get(key));
  -            } else {
  -                throw new IllegalFacetException();
  -            }
  -        }
  -	}
  -	
  -	public void setFacets(int facets[]) throws UnknownFacetException, IllegalFacetException, IllegalFacetValueException {
  -	}
  -
  -	public void setBasetype(DatatypeValidator base) {
  -        fBaseValidator = (StringValidator) base;
  -	}
  +            }
  +
  +            if (((_facetsDefined & DatatypeValidator.FACET_LENGTH ) != 0 ) ) {
  +                if (((_facetsDefined & DatatypeValidator.FACET_MAXLENGTH ) != 0 ) ) {
  +                    throw new ConstrainException(
  +                                                "It is an error for both length and maxLength to be members of facets." );  
  +                } else if (((_facetsDefined & DatatypeValidator.FACET_MINLENGTH ) != 0 ) ) {
  +                    throw new ConstrainException(
  +                                                "It is an error for both length and minLength to be members of facets." );
  +                }
  +            }
  +
  +            if ( ( (_facetsDefined & ( DatatypeValidator.FACET_MINLENGTH |
  +                                       DatatypeValidator.FACET_MAXLENGTH) ) != 0 ) ) {
  +                if ( _minLength < _maxLength ) {
  +                    throw new ConstrainException( "Value of minLength = " + _minLength +
  +                                                  "must be greater that the value of maxLength" + _maxLength );
  +                }
  +            }
  +
  +            isMaxExclusiveDefined = ((_facetsDefined & 
  +                                      DatatypeValidator.FACET_MAXEXCLUSIVE ) != 0 )?true:false;
  +            isMaxInclusiveDefined = ((_facetsDefined & 
  +                                      DatatypeValidator.FACET_MAXINCLUSIVE ) != 0 )?true:false;
  +            isMinExclusiveDefined = ((_facetsDefined &
  +                                      DatatypeValidator.FACET_MINEXCLUSIVE ) != 0 )?true:false;
  +            isMinInclusiveDefined = ((_facetsDefined &
  +                                      DatatypeValidator.FACET_MININCLUSIVE ) != 0 )?true:false;
  +
  +            if ( isMaxExclusiveDefined && isMaxInclusiveDefined ) {
  +                throw new ConstrainException(
  +                                            "It is an error for both maxInclusive and maxExclusive to be specified for the same datatype." ); 
  +            }
  +            if ( isMinExclusiveDefined && isMinInclusiveDefined ) {
  +                throw new ConstrainException(
  +                                            "It is an error for both minInclusive and minExclusive to be specified for the same datatype." ); 
  +            }
  +         } else { //derived by list
  +             for (Enumeration e = facets.keys(); e.hasMoreElements();) {
  +               String key = (String) e.nextElement();
  +               if ( key.equals(SchemaSymbols.ELT_LENGTH) ) {
  +                   _facetsDefined += DatatypeValidator.FACET_LENGTH;
  +                   String lengthValue = (String)facets.get(key);
  +                   try {
  +                       _length     = Integer.parseInt( lengthValue );
  +                   } catch (NumberFormatException nfe) {
  +                       throw new IllegalFacetValueException("Length value '"+lengthValue+"' is invalid.");
  +                   }
  +                   if ( _length < 0 )
  +                       throw new IllegalFacetValueException("Length value '"+lengthValue+"'  must be a nonNegativeInteger.");
  +
  +               } else if (key.equals(SchemaSymbols.ELT_MINLENGTH) ) {
  +                   _facetsDefined += DatatypeValidator.FACET_MINLENGTH;
  +                   String minLengthValue = (String)facets.get(key);
  +                   try {
  +                       _minLength     = Integer.parseInt( minLengthValue );
  +                   } catch (NumberFormatException nfe) {
  +                       throw new IllegalFacetValueException("maxLength value '"+minLengthValue+"' is invalid.");
  +                   }
  +               } else if (key.equals(SchemaSymbols.ELT_MAXLENGTH) ) {
  +                   _facetsDefined += DatatypeValidator.FACET_MAXLENGTH;
  +                   String maxLengthValue = (String)facets.get(key);
  +                   try {
  +                       _maxLength     = Integer.parseInt( maxLengthValue );
  +                   } catch (NumberFormatException nfe) {
  +                       throw new IllegalFacetValueException("maxLength value '"+maxLengthValue+"' is invalid.");
  +                   }
  +               } else if (key.equals(SchemaSymbols.ELT_ENUMERATION)) {
  +                   _facetsDefined += DatatypeValidator.FACET_ENUMERATION;
  +                   _enumeration    = (Vector)facets.get(key);
  +               } else {
  +                   throw new IllegalFacetException();
  +               }
  +             }
  +             if (((_facetsDefined & DatatypeValidator.FACET_LENGTH ) != 0 ) ) {
  +                 if (((_facetsDefined & DatatypeValidator.FACET_MAXLENGTH ) != 0 ) ) {
  +                     throw new ConstrainException(
  +                                              "It is an error for both length and maxLength to be members of facets." );  
  +                 } else if (((_facetsDefined & DatatypeValidator.FACET_MINLENGTH ) != 0 ) ) {
  +                     throw new ConstrainException(
  +                                              "It is an error for both length and minLength to be members of facets." );
  +                 }
  +             }
  +
  +             if ( ( (_facetsDefined & ( DatatypeValidator.FACET_MINLENGTH |
  +                                     DatatypeValidator.FACET_MAXLENGTH) ) != 0 ) ) {
  +                 if ( _minLength < _maxLength ) {
  +                     throw new ConstrainException( "Value of minLength = " + _minLength +
  +                                                "must be greater that the value of maxLength" + _maxLength );
  +                 }
  +             }
  +         }
  +    }
   
  +    public void setBasetype( String base) {
  +        fBaseValidator = base;
  +    }
  +
       /**
        * set the locate to be used for error messages
        */
       public void setLocale(Locale locale) {
           fLocale = locale;
       }
  +
  +    public int compare( DatatypeValidator o1, DatatypeValidator o2){
  +        return 0;
  +    }
  +
  +    private void checkContent( String content )throws InvalidDatatypeValueException
  +    {
  +        if ( (_facetsDefined & DatatypeValidator.FACET_MAXLENGTH) != 0 ) {
  +            if ( content.length() > _maxLength ) {
  +                throw new InvalidDatatypeValueException("Value '"+content+
  +                                                        "' with length '"+content.length()+
  +                                                        "' exceeds maximum length of "+_maxLength+".");
  +            }
  +        }
  +        if ( (_facetsDefined & DatatypeValidator.FACET_ENUMERATION) != 0 ) {
  +            if ( _enumeration.contains( content ) == false )
  +                throw new InvalidDatatypeValueException("Value '"+content+"' must be one of "+_enumeration);
  +        }
  +
  +        if ( isMaxExclusiveDefined == true ) {
  +            int comparisonResult;
  +            comparisonResult  = compare( content, _maxExclusive );
  +            if ( comparisonResult > 0 ) {
  +                throw new InvalidDatatypeValueException( "Value '"+content+ "'  must be" +
  +                                                         "lexicographically less than" + _maxExclusive );
  +
  +            }
  +
  +        }
  +        if ( isMaxInclusiveDefined == true ) {
  +            int comparisonResult;
  +            comparisonResult  = compare( content, _maxInclusive );
  +            if ( comparisonResult >= 0 )
  +                throw new InvalidDatatypeValueException( "Value '"+content+ "' must be" +
  +                                                         "lexicographically less or equal than" + _maxInclusive );
  +        }
  +
  +        if ( isMinExclusiveDefined == true ) {
  +            int comparisonResult;
  +            comparisonResult  = compare( content, _minExclusive );
  +            if ( comparisonResult < 0 )
  +                throw new InvalidDatatypeValueException( "Value '"+content+ "' must be" +
  +                                                         "lexicographically greater than" + _minExclusive );
  +        }
  +        if ( isMinInclusiveDefined == true ) {
  +            int comparisonResult;
  +            comparisonResult = compare( content, _minInclusive );
  +            if ( comparisonResult <= 0 )
  +                throw new InvalidDatatypeValueException( "Value '"+content+ "' must be" +
  +                                                         "lexicographically greater or equal than" + _minInclusive );
  +        }
  +
  +        if ( (_facetsDefined & DatatypeValidator.FACET_PATTERN ) != 0 ) {
  +            RegularExpression regex = new RegularExpression(_pattern, "X" );
  +            if ( regex.matches( content) == false )
  +                throw new InvalidDatatypeValueException("Value'"+content+
  +                                                        "does not match regular expression facet" + _pattern );
  +        }
  +
  +    }
  +    private void checkContentList( String content )throws InvalidDatatypeValueException
  +    {
  +        //Revisit
  +    }
  +    private int compare( String content, String facetValue ){
  +        Locale    loc       = Locale.getDefault();
  +        Collator  collator  = Collator.getInstance( loc );
  +        return collator.compare( content, facetValue );
  +    }
  +
   }
  +
  
  
  
  1.2       +44 -408   xml-xerces/java/src/org/apache/xerces/validators/datatype/TimeDurationValidator.java
  
  Index: TimeDurationValidator.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/validators/datatype/TimeDurationValidator.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- TimeDurationValidator.java	2000/01/25 02:39:33	1.1
  +++ TimeDurationValidator.java	2000/05/17 18:33:16	1.2
  @@ -64,6 +64,7 @@
   import java.util.Calendar;
   import java.util.GregorianCalendar;
   import java.text.ParseException;
  +import org.apache.xerces.validators.schema.SchemaSymbols;
   
   /**
    *
  @@ -73,425 +74,60 @@
    * @version
    */
   
  -public class TimeDurationValidator implements InternalDatatypeValidator {
  +public class TimeDurationValidator implements DatatypeValidator {
   
  -	public static final int CACHE_LIMIT = 300;
  -	public static final int CACHE_INITIAL_SIZE = 307;
  -	
  -	long fMaxInclusive = 0;
  -	boolean fIsMaxInclusive = false;
  -	long fMaxExclusive = 0;
  -	boolean fIsMaxExclusive = false;
  -	long fMinInclusive = 0;
  -	boolean fIsMinInclusive = false;
  -	long fMinExclusive = 0;
  -	boolean fIsMinExclusive = false;
  -	long fEnumValues[] = null;
  -	boolean fHasEnums = false;
  -	String ovalue = null;
  -	Locale fLocale = null;
  -	Hashtable facetData = null;	
  -	TimeDurationValidator fBaseValidator = null;
  -	private DatatypeMessageProvider fMessageProvider = new DatatypeMessageProvider();
  -	private Hashtable cache = new Hashtable(CACHE_INITIAL_SIZE);
   
  -	/**
  -     * validate that a string is a W3C timeDuration type
  +    /**
  +   * 
  +   * validate that a string matches a datatype
  +   * 
  +   * validate returns true or false depending on whether the string content is an
  +   * instance of the data type represented by this validator.
  +   * 
  +   * @param content A string containing the content to be validated
  +   * @exception throws InvalidDatatypeException if the content is
  +   *                   invalid according to the rules for the validators
  +   * @exception InvalidDatatypeValueException
  +   */
  +    public void validate(String content) throws InvalidDatatypeValueException{
  +    }
  +
  +    /**
  +     * set the facets for this datatype
  +     *
  +     * setFacets is responsible for ensuring that the supplied facets do not contradict each
  +     * other
        *
  -     * validate returns true or false depending on whether the string content is an
  -     * instance of the W3C timeDuration datatype
  -     * 
  -     * @param content A string containing the content to be validated
  +     * @param facets A hashtable where facet names are keys and facet values are stored
  +     *        in the hashtable.  Usually facet values are strings, except for the 
  +     *        enumeration facet.  The value for this facet is a Vector of strings, one
  +     *        per enumeration value
        *
  -     * @exception throws InvalidDatatypeException if the content is
  -     *  not a W3C timeDuration type
  +     * @exception throws UnknownFacetException
  +     * @exception throws IllegalFacetException
  +     * @exception throws IllegalFacetValueException
        */
  -
  -	public void validate(String content) throws InvalidDatatypeValueException 
  -	{
  -		ovalue=content;
  -		Long d = ((Long)cache.get(content));
  -		if (d==null)
  -		{
  -			d = new Long(normalizeDuration(content.toCharArray(), 0, content.length()));
  -			if (cache.size() < CACHE_LIMIT) cache.put(content, d);
  -		}
  -      boundsCheck(d.longValue());
  -      if (fHasEnums)enumCheck(d.longValue());
  -		return;
  -	}
  -			
  -	public void validate(int contentIndex) throws InvalidDatatypeValueException {
  -	}
  -	
  -	public void setFacets(Hashtable facets) throws UnknownFacetException, IllegalFacetException, IllegalFacetValueException {
  -        if (fBaseValidator != null)
  -            if (!fBaseValidator.ensureFacetsAreConsistent(facets))
  -                throw new IllegalFacetValueException(
  -					getErrorString(DatatypeMessageProvider.FacetsInconsistent,
  -								   DatatypeMessageProvider.MSG_NONE,
  -								   null));
  -
  -	    fIsMinInclusive = fIsMinExclusive = fIsMaxInclusive = fIsMaxExclusive = fHasEnums = false;
  -	    for (Enumeration e = facets.keys(); e.hasMoreElements();) {
  -	        String key = (String) e.nextElement();
  -	        String value = null;
  -	        if (key.equals(DatatypeValidator.ENUMERATION)) 
  -                continue;  // ENUM values passed as a vector & handled after bounds facets	    
  -    	    value = (String) facets.get(key);   
  -	        long dValue = 0;
  -	        try {
  -	            dValue = normalizeDuration(value.toCharArray(), 0, value.length());
  -	        } catch (InvalidDatatypeValueException nfe) {
  -	            throw new IllegalFacetValueException(
  -					getErrorString(DatatypeMessageProvider.IllegalFacetValue,
  -								   DatatypeMessageProvider.MSG_NONE,
  -								   new Object [] { value, key }));
  -	        }
  -	        if (key.equals(DatatypeValidator.MININCLUSIVE)) {
  -                fIsMinInclusive = true;
  -	            fMinInclusive = dValue;
  -	        } else if (key.equals(DatatypeValidator.MINEXCLUSIVE)) {
  -	            fIsMinExclusive = true;
  -	            fMinExclusive = dValue;
  -	        } else if (key.equals(DatatypeValidator.MAXINCLUSIVE)) {
  -	            fIsMaxInclusive = true;
  -	            fMaxInclusive = dValue;
  -	        } else if (key.equals(DatatypeValidator.MAXEXCLUSIVE)) {
  -	            fIsMaxExclusive = true;
  -	            fMaxExclusive = dValue;
  -	        } else if (key.equals(DatatypeValidator.ENUMERATION)) {
  -	        } else if (key.equals(DatatypeValidator.PRECISION) ||
  -                     key.equals(DatatypeValidator.SCALE) ||
  -                     key.equals(DatatypeValidator.LENGTH) ||
  -                     key.equals(DatatypeValidator.MINLENGTH) ||
  -                     key.equals(DatatypeValidator.MAXLENGTH) ||
  -                     key.equals(DatatypeValidator.LITERAL) ||
  -                     key.equals(DatatypeValidator.ENCODING) ||
  -                     key.equals(DatatypeValidator.PERIOD) ||
  -                     key.equals(DatatypeValidator.PATTERN) ||
  -                     key.equals(DatatypeValidator.LEXICALREPRESENTATION) ||
  -                     key.equals(DatatypeValidator.LEXICAL))
  -                throw new IllegalFacetException(
  -					getErrorString(DatatypeMessageProvider.IllegalIntegerFacet,
  -								   DatatypeMessageProvider.MSG_NONE,
  -								   null));
  -            else 
  -                throw new UnknownFacetException(
  -					getErrorString(DatatypeMessageProvider.UnknownFacet,
  -								   DatatypeMessageProvider.MSG_NONE,
  -								   new Object [] { key }));
  -	    }
  -	    
  -        // check the enum values after any range constraints are in place
  -        Vector v = (Vector) facets.get(DatatypeValidator.ENUMERATION);    
  -	    if (v != null) {
  -	        fHasEnums = true;
  -	        fEnumValues = new long[v.size()];
  -	        for (int i = 0; i < v.size(); i++)
  -	            try {
  -	                fEnumValues[i] = normalizeDuration(((String)v.elementAt(i)).toCharArray(), 0, ((String)v.elementAt(i)).length());
  -	                boundsCheck(fEnumValues[i]);
  -	            } catch (InvalidDatatypeValueException idve) {
  -	                throw new IllegalFacetValueException(
  -						getErrorString(DatatypeMessageProvider.InvalidEnumValue,
  -									   DatatypeMessageProvider.MSG_NONE,
  -									   new Object [] { v.elementAt(i)}));
  -	            } catch (NumberFormatException nfe) {
  -	                System.out.println("Internal Error parsing enumerated values for timeDuration type");
  -	            }
  -	    }
  -
  -	}
  +    public void setFacets(Hashtable facets,String derivationBy ) throws UnknownFacetException, IllegalFacetException, IllegalFacetValueException, ConstrainException {
  +    }
   
  -	public void setBasetype(DatatypeValidator base) {
  -	    fBaseValidator = (TimeDurationValidator) base;
  +    /**
  +     * set the base type for this datatype
  +     *
  +     * @param base the validator for this type's base type
  +     *
  +     */
  +    public void setBasetype(String base) {
  +    }
   
  -	}
   
       /**
  -     * set the locate to be used for error messages
  -     */
  +    * set the locate to be used for error messages
  +    */
       public void setLocale(Locale locale) {
  -        fLocale = locale;
       }
  -	boolean ensureFacetsAreConsistent(Hashtable facets) {
  -	    boolean facetsAreConsistent = true;
  -	    for (Enumeration e = facets.keys(); facetsAreConsistent && e.hasMoreElements();) {
  -	        String key = (String) e.nextElement();
  -	        String value = null;
  -	        if (key.equals(DatatypeValidator.ENUMERATION)) 
  -                continue;  // ENUM values passed as a vector & handled after bounds facets	    
  -    	    value = (String) facets.get(key);   
  -	        long dValue = 0;
  -	        try {
  -	            dValue = normalizeDuration(value.toCharArray(), 0, value.length());
  -	        } catch (InvalidDatatypeValueException nfe) {
  -                facetsAreConsistent = false;
  -	        }
  -	        if (key.equals(DatatypeValidator.MININCLUSIVE) && fIsMinInclusive) {
  -                facetsAreConsistent = fMinInclusive <= dValue;
  -	        } else if (key.equals(DatatypeValidator.MINEXCLUSIVE) && fIsMinExclusive) {
  -	            facetsAreConsistent = fMinExclusive < dValue;
  -	        } else if (key.equals(DatatypeValidator.MAXINCLUSIVE) && fIsMaxInclusive) {
  -	            facetsAreConsistent = fMaxInclusive >= dValue;
  -	        } else if (key.equals(DatatypeValidator.MAXEXCLUSIVE) && fIsMaxExclusive) {
  -	            facetsAreConsistent = fMaxExclusive > dValue;
  -	        }
  -	    }
  -	    return facetsAreConsistent;
  -	}
  -    private void boundsCheck(long d) throws InvalidDatatypeValueException {
  -        boolean minOk = false;
  -        boolean maxOk = false;
  -        if (fIsMaxInclusive)
  -            maxOk = (d <= fMaxInclusive);
  -        else if (fIsMaxExclusive)
  -            maxOk = (d < fMaxExclusive);
  -        else 
  -            maxOk = (!fIsMaxInclusive && !fIsMaxExclusive);
  -        
  -        if (fIsMinInclusive)
  -            minOk = (d >= fMinInclusive);
  -        else if (fIsMinExclusive) 
  -            minOk = (d > fMinInclusive);
  -        else 
  -            minOk = (!fIsMinInclusive && !fIsMinExclusive);
  -        if (!(minOk && maxOk))
  -            throw new InvalidDatatypeValueException(
  -				getErrorString(DatatypeMessageProvider.OutOfBounds,
  -							   DatatypeMessageProvider.MSG_NONE,
  -							   new Object [] { ovalue }));
  -    }
  +
       
  -    private void enumCheck(long d) throws InvalidDatatypeValueException {
  -        for (int i = 0; i < fEnumValues.length; i++) {
  -            if (d == fEnumValues[i]) return;
  -        }
  -        throw new InvalidDatatypeValueException(
  -			getErrorString(DatatypeMessageProvider.NotAnEnumValue,
  -						   DatatypeMessageProvider.MSG_NONE,
  -						   new Object [] { ovalue }));
  -    }
  -	public void setFacets(int facets[]) throws UnknownFacetException, IllegalFacetException, IllegalFacetValueException {
  -	}
  -    private String getErrorString(int major, int minor, Object args[]) {
  -         try {
  -             return fMessageProvider.createMessage(fLocale, major, minor, args);
  -         } catch (Exception e) {
  -             return "Illegal Errorcode "+minor;
  -         }
  +    public int compare( DatatypeValidator o1, DatatypeValidator o2){
  +         return 0;
       }
  -	public static long normalizeDuration(char[] value, int start, int length) throws InvalidDatatypeValueException
  -	{
  -		int i=0, j=0, k=0, l=0, m=0;
  -		int sepindex=0;
  -		int index=start;
  -		int lindex=0;
  -		int endindex=(start+length)-1;
  -		int pendindex=endindex;
  -
  -		final char[] dseps = {'Y','M','D'};
  -		final char[] tseps = {'H','M','S'};
  -		final char[] msc = {'0','0','0'};
  -
  -		final int[] buckets = new int[Calendar.FIELD_COUNT];
  -		for(i=0;i<buckets.length;i++) buckets[i]=0;
  -		boolean intime=false;
  -		boolean fixed=false;
  -		boolean p1negative=false;
  -		boolean p2negative=false;
  -		boolean p1specified=false;
  -		boolean p2specified=false;
  -		GregorianCalendar cstart = null;
  -		GregorianCalendar cend = null;
  -
  -//	Start phase 1: capture start and/or end instant.
  -		try
  -		{
  -			if (value[index]=='-')
  -			{
  -				p1negative=true;
  -			}
  -//	Look for the forward slash.
  -			int ix = TimeInstantValidator.indexOf(value, start, '/');
  -
  -			if (ix > -1 && ix < endindex)
  -			{
  -				if (value[ix+1]=='-') 
  -				{
  -					p2negative=true;
  -				}
  -//  If the first term starts with a 'P', pin it for later parsing 
  -				if (value[(p1negative?index+1:index)]=='P')
  -				{
  -					if(p1negative)index++;
  -					p1specified=true;
  -					pendindex=ix-1;
  -				}
  -//	Otherwise parse it for a timeInstant
  -				else
  -				{
  -					cstart = (GregorianCalendar)TimeInstantValidator.normalizeInstant(value, index, ix-index);
  -				}
  -//  If the second term starts with a 'P', pin it for later parsing 
  -				if (value[(p2negative?(ix+2):(ix+1))]=='P')
  -				{
  -					p2specified=true;
  -					index=(p2negative?(ix+2):(ix+1));
  -				}
  -//	Otherwise parse it for a timeInstant
  -				else
  -				{
  -					ix++;
  -					cend = (GregorianCalendar)TimeInstantValidator.normalizeInstant(value,ix,(endindex-ix)+1);
  -				}
  -			}
  -//	Only one term specified.
  -			else
  -			{
  -			 	index=(p1negative?(start+1):(start));
  -			}
  -//	If both terms are instants, return the millisecond difference
  -			if(cstart != null && cend != null)
  -			{
  -				return((cend.getTime().getTime() - cstart.getTime().getTime()));
  -			}
  -// If both terms are 'P', error.
  -			if (p1specified && p2specified)
  -				throw new ParseException("Period cannot be expressed as 2 durations.", 0);
  -	
  -			if (p1specified && value[index] != 'P')
  -			{
  -				throw new ParseException("Invalid start character for timeDuration:"+value[index], index);
  -			}
  -			if (p2specified && value[index] != 'P')
  -			{
  -				throw new ParseException("Invalid start character for timeDuration:"+value[index], index);
  -			}
  -		}
  -		catch(Exception e)
  -		{
  -			throw new InvalidDatatypeValueException(e.toString());
  -		}
  -//	Second phase....parse 'P' term
  -		try
  -		{
  -
  -			lindex=index+1;
  -			for(i=index+1;i<=pendindex;i++)
  -			{
  -//	Accumulate digits.
  -				if (Character.isDigit(value[i]) || value[i]=='.')
  -				{
  -					if (value[i]=='.')fixed=true;
  -					continue;
  -				}
  -				if (value[i]=='T')
  -				{
  -					intime=true;
  -					sepindex=0;
  -					lindex=i+1;
  -					continue;
  -				}
  -//	If you get a separator, it must be appropriate for the section.
  -				sepindex = TimeInstantValidator.indexOf((intime?tseps:dseps), sepindex, value[i]);
  -				if (sepindex == -1)
  -					throw new ParseException("Illegal or misplaced separator.", i);
  -				sepindex++;
  -//	Fractional digits are allowed only for seconds.
  -				if (fixed && value[i]!='S')
  -					throw new ParseException("Fractional digits allowed only for 'seconds'.", i);
  -
  -				j=0;
  -				switch(value[i])
  -				{
  -					case('Y'):
  -					{
  -						if(intime)throw new ParseException("Year must be specified before 'T' separator.", i);
  -						buckets[Calendar.YEAR]=TimeInstantValidator.parseInt(value, lindex, i-lindex);
  -						break;
  -					}
  -					case('D'):
  -					{
  -						if(intime)throw new ParseException("Days must be specified before 'T' separator.", i);
  -						buckets[Calendar.DAY_OF_MONTH]=TimeInstantValidator.parseInt(value, lindex, i-lindex);
  -						break;
  -					}
  -					case('H'):
  -					{
  -						if(!intime)throw new ParseException("Hours must be specified after 'T' separator.", i);
  -						buckets[Calendar.HOUR_OF_DAY]=TimeInstantValidator.parseInt(value, lindex, i-lindex);
  -						break;
  -					}
  -					case('M'):
  -					{
  -						buckets[(intime?Calendar.MINUTE:Calendar.MONTH)]=TimeInstantValidator.parseInt(value, lindex, i-lindex);
  -						break;
  -					}
  -					case('S'):
  -					{
  -						if(!intime)throw new ParseException("Seconds must be specified after 'T' separator.", i);
  -						if(!fixed)buckets[Calendar.SECOND]=TimeInstantValidator.parseInt(value, lindex, i-lindex);
  -						else
  -						{
  -							int ps = TimeInstantValidator.indexOf(value, lindex, '.');
  -							buckets[Calendar.SECOND]=TimeInstantValidator.parseInt(value, lindex, ps-lindex);
  -							ps++;k=0;
  -							while((ps <= pendindex) && (k<3) && Character.isDigit(value[ps]))
  -								msc[k++]=value[ps++];
  -							buckets[Calendar.MILLISECOND]=TimeInstantValidator.parseInt(msc, 0, 3);
  -							fixed=false;
  -						}
  -						break;
  -					}
  -					default:
  -					{
  -						throw new ParseException("Illegal 'picture' character: "+value[i], i);
  -					}
  -				}
  -			lindex=i+1;
  -			}
  -		}
  -		catch(Exception e)
  -		{
  -			throw new InvalidDatatypeValueException(e.toString());
  -		}
  -//	Third phase, make the calculations.
  -		try
  -		{
  -//	Roll the start calendar forward and return difference.
  -			if (cstart !=null)
  -			{
  -				long st = cstart.getTime().getTime();
  -				for(k=0;k<buckets.length;k++)
  -					if(buckets[k]!=0)cstart.add(k, (p2negative?-buckets[k]:buckets[k]));
  -				long ms = cstart.getTime().getTime();
  -				return((ms-st));
  -			}
  -//	Roll the end calendar backward and return difference.
  -			if (cend !=null)
  -			{
  -				long st = cend.getTime().getTime();
  -				for(k=0;k<buckets.length;k++) 
  -					if(buckets[k]>0) cend.add(k, (p1negative?buckets[k]:-buckets[k]));
  -				long ms = cend.getTime().getTime();
  -				return((ms-st));
  -			}
  -//	Otherwise roll the relative specification forward and reverse the sing as appropriate.	
  -			long r=(((long)(( (buckets[Calendar.YEAR]*31104000L)+
  -									(buckets[Calendar.MONTH]*2592000L)+
  -									(buckets[Calendar.DAY_OF_MONTH]*86400L)+
  -									(buckets[Calendar.HOUR_OF_DAY]*3600L)+
  -									(buckets[Calendar.MINUTE]*60L)+
  -									(buckets[Calendar.SECOND]))*1000L)+
  -									(buckets[Calendar.MILLISECOND])));
  -	
  -	  		return((p1negative?-r:r));
  -		}
  -		catch(Exception e)
  -		{
  -			throw new InvalidDatatypeValueException(e.toString());
  -		}
  -   }
   }
  
  
  
  1.2       +70 -0     xml-xerces/java/src/org/apache/xerces/validators/datatype/ConstrainException.java
  
  
  
  
  1.2       +297 -0    xml-xerces/java/src/org/apache/xerces/validators/datatype/DatatypeValidatorRegistry.java
  
  
  
  
  1.2       +143 -0    xml-xerces/java/src/org/apache/xerces/validators/datatype/ENTITYValidator.java
  
  
  
  
  1.2       +143 -0    xml-xerces/java/src/org/apache/xerces/validators/datatype/IDREFValidator.java
  
  
  
  
  1.2       +143 -0    xml-xerces/java/src/org/apache/xerces/validators/datatype/IDValidator.java
  
  
  
  
  1.2       +143 -0    xml-xerces/java/src/org/apache/xerces/validators/datatype/NOTATIONValidator.java
  
  
  
  
  1.2       +310 -0    xml-xerces/java/src/org/apache/xerces/validators/datatype/QNameValidator.java
  
  
  
  
  1.2       +126 -0    xml-xerces/java/src/org/apache/xerces/validators/datatype/RecurringDurationValidator.java
  
  
  
  
  1.2       +101 -0    xml-xerces/java/src/org/apache/xerces/validators/datatype/URIReferenceValidator.java
  
  
  
  
  1.2       +63 -137   xml-xerces/java/src/org/apache/xerces/validators/dtd/DTDImporter.java
  
  Index: DTDImporter.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/validators/dtd/DTDImporter.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- DTDImporter.java	2000/04/04 19:38:39	1.1
  +++ DTDImporter.java	2000/05/17 18:33:22	1.2
  @@ -64,16 +64,23 @@
   import org.apache.xerces.readers.DefaultEntityHandler;
   import org.apache.xerces.readers.XMLEntityHandler;
   import org.apache.xerces.utils.ChunkyCharArray;
  +import org.apache.xerces.utils.QName;
   import org.apache.xerces.utils.StringPool;
   import org.apache.xerces.utils.XMLCharacterProperties;
   import org.apache.xerces.utils.XMLMessages;
   import org.apache.xerces.validators.common.XMLValidator;
   
  -public final class DTDImporter implements XMLDTDScanner.EventHandler
  -{
  -    //
  +public final class DTDImporter 
  +    implements XMLDTDScanner.EventHandler {
  +
  +    // REVISIT: DTDs don't have a namespace so we must bind the
  +    //          empty namespace, "", so that validation works when
  +    //          namespace processing is turned on.
  +
       //
  +    // Data
       //
  +
       private StringPool fStringPool = null;
       private boolean fValidating = false;
       private int fStandaloneReader = -1;
  @@ -86,14 +93,17 @@
       private int fIDSymbol = -1;
       private boolean fDeclsAreExternal = false;
       private XMLValidator fValidator = null;
  -    //
  +
       //
  +    // Constructors
       //
  +
  +    /** Constructs a DTD importer. */
       public DTDImporter(StringPool stringPool,
                          XMLErrorReporter errorReporter,
                          DefaultEntityHandler entityHandler,
  -                       XMLValidator validator)
  -    {
  +                       XMLValidator validator) {
  +
           fStringPool = stringPool;
           fErrorReporter = errorReporter;
           fEntityHandler = entityHandler;
  @@ -101,13 +111,14 @@
           fDTDScanner = new XMLDTDScanner(fStringPool, fErrorReporter, fEntityHandler, new ChunkyCharArray(fStringPool));
           fDTDScanner.setEventHandler(this);
           init();
  -    }
  -    /**
  -     */
  -    public void initHandlers(XMLDocumentHandler.DTDHandler dtdHandler)
  -    {
  +
  +    } // <init>(StringPool,XMLErrorReporter,DefaultEntityHandler,XMLValidator)
  +
  +    /** Initialize handlers. */
  +    public void initHandlers(XMLDocumentHandler.DTDHandler dtdHandler) {
           fDTDHandler = dtdHandler;
       }
  +
       public void setValidating(boolean validating) {
           fValidating = validating;
       }
  @@ -152,19 +163,6 @@
           fDeclsAreExternal = fStandaloneReader != -1 && readerId != fStandaloneReader;
       }
   
  -    public boolean scanDoctypeDecl(boolean standalone) throws Exception {
  -        fStandaloneReader = standalone ? fEntityHandler.getReaderId() : -1;
  -        fDeclsAreExternal = false;
  -        if (!fDTDScanner.scanDoctypeDecl()) {
  -            return false;
  -        }
  -        if (fDTDScanner.getReadingExternalEntity()) {
  -            fDTDScanner.scanDecls(true);
  -        }
  -        fDTDHandler.endDTD();
  -        return true;
  -    }
  -
       //
       // XMLDTDScanner.EventHandler interface
       //
  @@ -203,55 +201,63 @@
       //    public int scanDefaultAttValue(int elementType, int attrName, int attType, int enumeration) throws Exception;
       //    public void internalSubset(int internalSubset) throws Exception;
       //
  -    public boolean validVersionNum(String version) {
  -        return XMLCharacterProperties.validVersionNum(version);
  -    }
  -    public boolean validEncName(String encoding) {
  -        return XMLCharacterProperties.validEncName(encoding);
  -    }
  -    public int validPublicId(String publicId) {
  -        return XMLCharacterProperties.validPublicId(publicId);
  -    }
       public void callTextDecl(int version, int encoding) throws Exception {
           fDTDHandler.textDecl(version, encoding);
  -    }
  -    public void doctypeDecl(int rootElementType, int publicId, int systemId) throws Exception {
  -        fValidator.setRootElementType(rootElementType);
  -        fDTDHandler.startDTD(rootElementType, publicId, systemId);
  -    }
  -    public void startReadingFromExternalSubset(int publicId, int systemId) throws Exception {
  -        fEntityHandler.startReadingFromExternalSubset(fStringPool.toString(publicId),
  -                                                      fStringPool.toString(systemId),
  -                                                      fDTDScanner.markupDepth());
       }
  -    public void stopReadingFromExternalSubset() throws Exception {
  -        fEntityHandler.stopReadingFromExternalSubset();
  +    public void doctypeDecl(QName rootElement, int publicId, int systemId) throws Exception {
  +        rootElement.uri = StringPool.EMPTY_STRING; // REVISIT: DTD + Namespaces
  +        fValidator.setRootElementType(rootElement);
  +        fDTDHandler.startDTD(rootElement, publicId, systemId);
       }
  -    public int addElementDecl(int elementType) throws Exception {
  -        int elementIndex = fValidator.addElement(elementType);
  +
  +    /** Adds an element declaration. */ 
  +    public int addElementDecl(QName elementDecl) throws Exception {
  +        elementDecl.uri = StringPool.EMPTY_STRING; // REVISIT: DTD + Namespaces
  +        int elementIndex = fValidator.addElement(elementDecl);
           return elementIndex;
       }
  -    public int addElementDecl(int elementType, int contentSpecType, int contentSpec) throws Exception {
  -        int elementIndex = fValidator.addElementDecl(elementType, contentSpecType, contentSpec, fDeclsAreExternal);
  +
  +    /** Adds an element declaration. */
  +    public int addElementDecl(QName elementDecl, 
  +                              int contentSpecType, int contentSpec) 
  +        throws Exception {
  +
  +        elementDecl.uri = StringPool.EMPTY_STRING; // REVISIT: DTD + Namespaces
  +        int elementIndex = fValidator.addElementDecl(elementDecl, contentSpecType, contentSpec, fDeclsAreExternal);
           if (elementIndex == -1) {
               if (fValidating) {
                   reportRecoverableXMLError(XMLMessages.MSG_ELEMENT_ALREADY_DECLARED,
                                             XMLMessages.VC_UNIQUE_ELEMENT_TYPE_DECLARATION,
  -                                          elementType);
  +                                          elementDecl.rawname);
               }
  -        } else {
  -            fDTDHandler.elementDecl(elementType, fValidator.getContentSpec(elementIndex));
  +        } 
  +        else {
  +            fDTDHandler.elementDecl(elementDecl, fValidator.getContentSpec(elementIndex));
           }
           return elementIndex;
  -    }
  -    public int addAttDef(int elementIndex, int attName, int attType, int enumeration, int attDefaultType, int attDefaultValue) throws Exception {
  -        int attDefIndex = fValidator.addAttDef(elementIndex, attName, attType, enumeration, attDefaultType, attDefaultValue, fDeclsAreExternal);
  +
  +    } // addElementDecl(QName,int,int):int
  +
  +    public int addAttDef(QName elementDecl, QName attributeDecl, 
  +                         int attType, int enumeration, 
  +                         int attDefaultType, int attDefaultValue) throws Exception {
  +
  +        elementDecl.uri = StringPool.EMPTY_STRING; // REVISIT: DTD + Namespaces
  +        attributeDecl.uri = StringPool.EMPTY_STRING; // REVISIT: DTD + Namespaces
  +        int attDefIndex = fValidator.addAttDef(elementDecl, attributeDecl, 
  +                                               attType, enumeration, 
  +                                               attDefaultType, attDefaultValue, 
  +                                               fDeclsAreExternal);
           if (attDefIndex != -1) {
               String enumString = (enumeration == -1) ? null : fStringPool.stringListAsString(enumeration);
  -            fDTDHandler.attlistDecl(fValidator.getElementType(elementIndex), attName, attType, enumString, attDefaultType, attDefaultValue);
  +            fDTDHandler.attlistDecl(elementDecl, attributeDecl, 
  +                                    attType, enumString, 
  +                                    attDefaultType, attDefaultValue);
           }
           return attDefIndex;
  -    }
  +
  +    } // addAttDef(QName,QName,int,int,int,int):int
  +
       public int addUniqueLeafNode(int nodeValue) throws Exception {
           int csn = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_LEAF, nodeValue, -1, true);
           if (csn == -1 && fValidating) {
  @@ -340,88 +346,8 @@
       }
       public void callProcessingInstruction(int target, int data) throws Exception {
           fDTDHandler.processingInstruction(target, data);
  -    }
  -    public int scanElementType(XMLEntityHandler.EntityReader entityReader, char fastchar) throws Exception {
  -        if (!fNamespacesEnabled) {
  -            return entityReader.scanName(fastchar);
  -        }
  -        int elementType = entityReader.scanQName(fastchar);
  -        if (entityReader.lookingAtChar(':', false)) {
  -            fErrorReporter.reportError(fErrorReporter.getLocator(),
  -                                       XMLMessages.XML_DOMAIN,
  -                                       XMLMessages.MSG_TWO_COLONS_IN_QNAME,
  -                                       XMLMessages.P5_INVALID_CHARACTER,
  -                                       null,
  -                                       XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
  -            entityReader.skipPastNmtoken(' ');
  -        }
  -        return elementType;
  -    }
  -    public int checkForElementTypeWithPEReference(XMLEntityHandler.EntityReader entityReader, char fastchar) throws Exception {
  -        if (!fNamespacesEnabled) {
  -            return entityReader.scanName(fastchar);
  -        }
  -        int elementType = entityReader.scanQName(fastchar);
  -        if (entityReader.lookingAtChar(':', false)) {
  -            fErrorReporter.reportError(fErrorReporter.getLocator(),
  -                                       XMLMessages.XML_DOMAIN,
  -                                       XMLMessages.MSG_TWO_COLONS_IN_QNAME,
  -                                       XMLMessages.P5_INVALID_CHARACTER,
  -                                       null,
  -                                       XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
  -            entityReader.skipPastNmtoken(' ');
  -        }
  -        return elementType;
       }
  -    public int checkForAttributeNameWithPEReference(XMLEntityHandler.EntityReader entityReader, char fastchar) throws Exception {
  -        if (!fNamespacesEnabled) {
  -            return entityReader.scanName(fastchar);
  -        }
  -        int attrName = entityReader.scanQName(fastchar);
  -        if (entityReader.lookingAtChar(':', false)) {
  -            fErrorReporter.reportError(fErrorReporter.getLocator(),
  -                                       XMLMessages.XML_DOMAIN,
  -                                       XMLMessages.MSG_TWO_COLONS_IN_QNAME,
  -                                       XMLMessages.P5_INVALID_CHARACTER,
  -                                       null,
  -                                       XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
  -            entityReader.skipPastNmtoken(' ');
  -        }
  -        return attrName;
  -    }
  -    public int checkForNameWithPEReference(XMLEntityHandler.EntityReader entityReader, char fastcheck) throws Exception {
  -        //
  -        // REVISIT - what does this have to do with PE references?
  -        //
  -        int valueIndex = entityReader.scanName(fastcheck);
  -        return valueIndex;
  -    }
  -    public int checkForNmtokenWithPEReference(XMLEntityHandler.EntityReader entityReader, char fastcheck) throws Exception {
  -        //
  -        // REVISIT - what does this have to do with PE references?
  -        //
  -        int nameOffset = entityReader.currentOffset();
  -        entityReader.skipPastNmtoken(fastcheck);
  -        int nameLength = entityReader.currentOffset() - nameOffset;
  -        if (nameLength == 0)
  -            return -1;
  -        int valueIndex = entityReader.addSymbol(nameOffset, nameLength);
  -        return valueIndex;
  -    }
  -    public int scanDefaultAttValue(int elementType, int attrName, int attType, int enumeration) throws Exception {
  -        if (fValidating && attType == fIDSymbol) {
  -            reportRecoverableXMLError(XMLMessages.MSG_ID_DEFAULT_TYPE_INVALID,
  -                                      XMLMessages.VC_ID_ATTRIBUTE_DEFAULT,
  -                                      attrName);
  -        }
  -        int defaultAttValue = fDTDScanner.scanDefaultAttValue(elementType, attrName);
  -        if (defaultAttValue == -1)
  -            return -1;
  -        if (attType != fCDATASymbol) {
  -            defaultAttValue = fValidator.normalizeAttValue(-1, attrName, defaultAttValue, attType, enumeration);
  -        }
  -        return defaultAttValue;
  -    }
  +
       public void internalSubset(int internalSubset) throws Exception {
           fDTDHandler.internalSubset(internalSubset);
       }
  
  
  
  1.5       +1 -1      xml-xerces/java/src/org/apache/xerces/validators/dtd/Makefile
  
  Index: Makefile
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/validators/dtd/Makefile,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- Makefile	2000/04/04 19:53:00	1.4
  +++ Makefile	2000/05/17 18:33:22	1.5
  @@ -1,7 +1,7 @@
   # Makefile for directory ./org/apache/xerces/validators/dtd
   
   TARGETS=\
  -	DTDImporter.class
  +	DTDGrammar.class
   
   DIRS = 
   
  
  
  
  1.2       +1119 -0   xml-xerces/java/src/org/apache/xerces/validators/dtd/DTDGrammar.java
  
  
  
  
  1.3       +14 -13    xml-xerces/java/src/org/apache/xerces/validators/schema/DatatypeContentModel.java
  
  Index: DatatypeContentModel.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/validators/schema/DatatypeContentModel.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- DatatypeContentModel.java	2000/04/04 20:11:07	1.2
  +++ DatatypeContentModel.java	2000/05/17 18:33:24	1.3
  @@ -59,20 +59,22 @@
   
   import org.apache.xerces.framework.XMLContentSpec;
   import org.apache.xerces.utils.StringPool;
  -import org.apache.xerces.validators.common.XMLValidator;
  +import org.apache.xerces.validators.common.Grammar;
   import org.apache.xerces.validators.common.XMLContentModel;
   import org.apache.xerces.validators.common.InsertableElementsInfo;
   import org.apache.xerces.validators.datatype.DatatypeValidator;
   import org.apache.xerces.validators.datatype.InvalidDatatypeValueException;
  +import org.apache.xerces.utils.QName;
   
   /**
    * DatatypeContentModel provides a content model that knows
    * how to check content against datatypes
  + * @version $Id:
    */
   public class DatatypeContentModel implements XMLContentModel
   {
  -    SchemaImporter.DatatypeValidatorRegistry fDatatypeRegistry = null;
  -    XMLValidator fValidator = null;
  +    TraverseSchema.DatatypeValidatorRegistry fDatatypeRegistry = null;
  +    Grammar fGrammar = null;
       StringPool fStringPool = null;
       int fChild = -1;
   
  @@ -82,13 +84,13 @@
   
       /**
        */
  -    public DatatypeContentModel(  SchemaImporter.DatatypeValidatorRegistry reg,
  -                                  XMLValidator validator,
  +    public DatatypeContentModel(  TraverseSchema.DatatypeValidatorRegistry reg,
  +                                  Grammar grammar,
                                     StringPool stringPool,
                                     int childIndex)
       {
           fDatatypeRegistry = reg;
  -        fValidator = validator;
  +        fGrammar = grammar;
           fStringPool = stringPool;
           fChild = childIndex;
       }
  @@ -121,7 +123,7 @@
        *
        * @exception Exception Thrown on error.
        */
  -    public int validateContent(int childCount, int[] children) throws Exception
  +    public int validateContent(int childCount, QName[] children) throws Exception
       {
           boolean DEBUG_DATATYPES = false;
   /*
  @@ -129,7 +131,7 @@
               System.out.println("Checking content of datatype");
               String strTmp = fStringPool.toString(elementTypeIndex);
               int contentSpecIndex = fElementDeclPool.getContentSpec(elementIndex);
  -            XMLContentSpec.Node csn = new XMLContentSpec.Node();
  +            XMLContentSpec csn = new XMLContentSpec();
               fElementDeclPool.getContentSpecNode(contentSpecIndex, csn);
               String contentSpecString = fStringPool.toString(csn.value);
               System.out.println
  @@ -154,13 +156,12 @@
           }
   */
           try { // REVISIT - integrate w/ error handling
  -            XMLContentSpec cs = fValidator.getContentSpec(fChild);
  -            XMLContentSpec.Node csn = new XMLContentSpec.Node();
  -            cs.getNode(cs.getHandle(), csn);
  -            String type = fStringPool.toString(csn.value);
  +            XMLContentSpec cs = new XMLContentSpec();
  +	    fGrammar.getContentSpec(fChild,cs);
  +            String type = fStringPool.toString(cs.value);
               DatatypeValidator v = fDatatypeRegistry.getValidatorFor(type);
               if (v != null) 
  -                v.validate(fStringPool.toString(children[0]));
  +                v.validate(fStringPool.toString(children[0].localpart));
               else
                   System.out.println("No validator for datatype "+type);
           } catch (InvalidDatatypeValueException idve) {
  
  
  
  1.6       +3 -4      xml-xerces/java/src/org/apache/xerces/validators/schema/Makefile
  
  Index: Makefile
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/validators/schema/Makefile,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- Makefile	2000/04/04 22:11:10	1.5
  +++ Makefile	2000/05/17 18:33:24	1.6
  @@ -1,11 +1,10 @@
   # Makefile for directory ./org/apache/xerces/validators/schema
   
   TARGETS=\
  -	DatatypeContentModel.class\
  -	SchemaImporter.class\
  -	SchemaParser.class\
  -	Schema.class\
  +	SchemaGrammar.class\
   	SchemaMessageProvider.class\
  +	SchemaSymbols.class \
  +	TraverseSchema.class \
   	XUtil.class
   
   DIRS = 
  
  
  
  1.2       +219 -1035 xml-xerces/java/src/org/apache/xerces/validators/schema/SchemaImporter.java
  
  Index: SchemaImporter.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/validators/schema/SchemaImporter.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- SchemaImporter.java	2000/04/04 19:56:29	1.1
  +++ SchemaImporter.java	2000/05/17 18:33:25	1.2
  @@ -58,8 +58,8 @@
   package org.apache.xerces.validators.schema;
   
   import java.io.IOException;
  -import java.util.Hashtable; // REVISIT replace
  -import java.util.Vector; // REVISIT replace
  +import java.util.Hashtable; 
  +import java.util.Vector; 
   
   import org.w3c.dom.Document;
   import org.w3c.dom.DocumentType;
  @@ -71,8 +71,12 @@
   import org.xml.sax.SAXParseException;
   import org.xml.sax.EntityResolver;
   import org.xml.sax.ErrorHandler;
  +import org.xml.sax.SAXNotSupportedException;
   import org.xml.sax.SAXException;
  +import org.xml.sax.SAXNotRecognizedException;
  +import java.io.IOException;
   
  +
   import org.apache.xerces.dom.DocumentImpl;
   import org.apache.xerces.dom.DocumentTypeImpl;
   import org.apache.xerces.framework.XMLContentSpec;
  @@ -98,76 +102,33 @@
   import org.apache.xerces.validators.datatype.TimeInstantValidator;
   import org.apache.xerces.validators.datatype.BinaryValidator;
   import org.apache.xerces.validators.datatype.URIValidator;
  +import org.apache.xerces.utils.QName;
  +
   
   /**
    * SchemaImporter is an <font color="red"><b>experimental</b></font> implementation
    * of a validator for the W3C Schema Language.  All of its implementation is subject
    * to change.
  + * 
  + * This class is being factored out to the Grammar class
    */
   public class SchemaImporter {
  -    //
  -    //
  -    //
  -
  -	private Schema fSchema = null;
  -
  -    private XMLValidator fValidator = null;
  -    private XMLErrorReporter fErrorReporter = null;
  -    private DefaultEntityHandler fEntityHandler = null;
  -    private StringPool fStringPool = null;
  +    private Schema                    fSchema           = null;
  +    private XMLValidator              fValidator        = null;
  +    private XMLErrorReporter          fErrorReporter    = null;
  +    private DefaultEntityHandler      fEntityHandler    = null;
  +    private StringPool                fStringPool       = null;
       private DatatypeValidatorRegistry fDatatypeRegistry = new DatatypeValidatorRegistry();
  -    private int fTypeCount = 0;
  -    private int fGroupCount = 0;
  -    private int fModelGroupCount = 0;
  -    private int fAttributeGroupCount = 0;
  -    private int fDatatypeCount = 0;
  -    private Hashtable fForwardRefs = new Hashtable(); // REVISIT w/ more efficient structure later
  -    private Hashtable fAttrGroupUses = new Hashtable();
  -
  -    // constants
  -
  -    private static final String ELT_COMMENT = "comment";
  -    private static final String ELT_DATATYPEDECL = "datatype";
  -    private static final String ELT_ARCHETYPEDECL = "type";
  -    private static final String ELT_ELEMENTDECL = "element";
  -    private static final String ELT_GROUPDECL = "group";
  -    private static final String ELT_ATTRGROUPDECL = "attributeGroup";
  -//    private static final String ELT_TEXTENTITYDECL = "textEntity";
  -//    private static final String ELT_EXTERNALENTITYDECL = "externalEntity";
  -//    private static final String ELT_UNPARSEDENTITYDECL = "unparsedEntity";
  -    private static final String ELT_NOTATIONDECL = "notation";
  -//    private static final String ELT_REFINES = "refines";
  -    private static final String ELT_RESTRICTIONS = "restrictions";
  -    private static final String ELT_ATTRIBUTEDECL = "attribute";
  -    private static final String ELT_ANNOTATION = "annotation";
  -    private static final String ELT_ANY = "any";
  -    private static final String ATT_NAME = "name";
  -    private static final String ATT_CONTENT = "content";
  -    private static final String ATT_MODEL = "model";
  -    private static final String ATT_ORDER = "order";
  -    private static final String ATT_TYPE = "type";
  -    private static final String ATT_DEFAULT = "default";
  -    private static final String ATT_FIXED = "fixed";
  -    private static final String ATT_COLLECTION = "collection";
  -    private static final String ATT_REF = "ref";
  -    private static final String ATT_ARCHREF = "archRef";
  -    private static final String ATT_SCHEMAABBREV = "schemaAbbrev";
  -    private static final String ATT_SCHEMANAME = "schemaName";
  -    private static final String ATT_MINOCCURS = "minOccurs";
  -    private static final String ATT_MAXOCCURS = "maxOccurs";
  -//    private static final String ATT_EXPORT = "export";
  -    private static final String ATT_SOURCE = "source";
  -    private static final String ATT_VALUE = "value";
  -    private static final String ATTVAL_ANY = "any";
  -    private static final String ATTVAL_MIXED = "mixed";
  -    private static final String ATTVAL_EMPTY = "empty";
  -    private static final String ATTVAL_CHOICE = "choice";
  -    private static final String ATTVAL_SEQ = "seq";
  -    private static final String ATTVAL_ALL = "all";
  -    private static final String ATTVAL_ELEMONLY = "elementOnly";
  -    private static final String ATTVAL_TEXTONLY = "textOnly";
  +    private int                       fTypeCount        = 0;
  +    private int                       fGroupCount       = 0;
  +    private int                       fModelGroupCount  = 0;
  +    private int                       fAttributeGroupCount = 0;
  +    private int                       fDatatypeCount    = 0;
  +    private Hashtable                 fForwardRefs      = new Hashtable(); // REVISIT w/ more efficient structure later
  +    private Hashtable                 fAttrGroupUses    = new Hashtable();
  +
   
  -    private Document fSchemaDocument = null;
  +    private Document fSchemaDocument                    = null;//The Schema Document
   
       //
       //
  @@ -176,37 +137,64 @@
                             XMLErrorReporter errorReporter,
                             DefaultEntityHandler entityHandler,
                             XMLValidator validator) {
  -        fErrorReporter = errorReporter;
  -        fEntityHandler = entityHandler;
  -        fStringPool = stringPool;
  -        fValidator = validator;
  +        fErrorReporter  = errorReporter;
  +        fEntityHandler  = entityHandler;
  +        fStringPool     = stringPool;
  +        fValidator      = validator;
           fDatatypeRegistry.initializeRegistry();
  -		fSchema = new Schema (fErrorReporter, fValidator);
  +        fSchema = new Schema (fErrorReporter, fValidator);
       }
  -    //
  -    //
  -    //
  +
  +
  +    /**
  +     * Resets SchemaImporter- This function will move
  +     * to the Grammar class
  +     * 
  +     * @param stringPool StringPool entry
  +     * @exception Exception
  +     */
       public void reset(StringPool stringPool) throws Exception {
           fStringPool = stringPool;
           // need to reset the datatype registry !!
           fDatatypeRegistry = new DatatypeValidatorRegistry();
           fDatatypeRegistry.initializeRegistry();
  -		fSchema = new Schema (fErrorReporter, fValidator);
  +        fSchema = new Schema (fErrorReporter, fValidator);
       }
  -    //
  -    //
  -    //
  +
  +    /**
  +     * Get a Schema document - This method will
  +     * move to Grammar
  +     * 
  +     * @return        Returns a DOM Document. Future implementation
  +     *         will return a DOM Schema.
  +     */
       public Document getSchemaDocument() {
           return fSchemaDocument;
       }
  -    //
  -    //
  -    //
  +
  +    /**
  +     * Revisit- A dummy now
  +     * 
  +     * @param elementType
  +     *               An index to a pool
  +     * @return 
  +     */
       private int getContentSpecHandleForElementType(int elementType) {
  -        return fValidator.getContentSpecHandle(fStringPool.getDeclaration(elementType));
  +        // REVISIT: ???
  +        //return fValidator.getContentSpecHandle(fStringPool.getDeclaration(elementType));
  +        return -1;
       }
  +    /**
  +     * A Dummy now
  +     * 
  +     * @param elementType
  +     *               Index to pool
  +     * @return 
  +     */
       private int getContentSpecTypeForElementType(int elementType) {
  -        return fValidator.getContentSpecType(fStringPool.getDeclaration(elementType));
  +        // REVISIT: ???
  +        //return fValidator.getContentSpecType(fStringPool.getDeclaration(elementType));
  +        return -1;
       }
   
       // content spec node types
  @@ -222,20 +210,24 @@
   
       private DOMParser fSchemaParser = null;
   
  +    /**
  +     * Builds a DOM Schema representation of a Grammar.
  +     * 
  +     * @param is     Input source which represents the Schema grammar( an .xsd file)
  +     */
       public void loadSchema(InputSource is) {
   
   
  -		SchemaParser parser = new SchemaParser (fSchema);
  -		try {
  +        DOMParser parser = new DOMParser (); //WORK
  +        try {
               parser.setEntityResolver(new Resolver());
               parser.setErrorHandler(new ErrorHandler());
               //parser.setFeature("http://xml.org/sax/features/validation", true);
  -			parser.parse (is);
  -		} 
  -		catch (Exception e) {
  +            parser.parse (is);
  +        } catch (Exception e) {
               e.printStackTrace();
  -			System.exit (1);
  -		}
  +            System.exit (1);
  +        }
   
   
           // create parser for schema
  @@ -248,40 +240,44 @@
               fSchemaParser.setErrorHandler(new ErrorHandler());
           }
   
  -        // parser schema file
  -        try {
   
  -            fSchemaParser.setFeature("http://xml.org/sax/features/validation", true);
  -            fSchemaParser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", false);
  -            fSchemaParser.parse(is);
  -        }
  -        catch (SAXException se) {
  -            se.getException().printStackTrace();
  -            System.err.println("error parsing schema file");
  -//            System.exit(1);
  -        }
  -        catch (Exception e) {
  +        try {
  +        fSchemaParser.setFeature("http://xml.org/sax/features/validation", true);
  +        fSchemaParser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", false);
  +        fSchemaParser.parse(is);
  +        } catch( SAXNotSupportedException e ){
  +            e.printStackTrace();  
  +        } catch( SAXNotRecognizedException e ){
  +            e.printStackTrace();
  +        } catch( IOException e ){
  +            e.printStackTrace();
  +        } catch( SAXException e ){
               e.printStackTrace();
  -            System.err.println("error parsing schema file");
  -//            System.exit(1);
           }
  +
           fSchemaDocument = fSchemaParser.getDocument();
           if (fSchemaDocument == null) {
               System.err.println("error: couldn't load schema file!");
               return;
           }
  +
   
  -        // traverse schema
           try {
  -            Element root = fSchemaDocument.getDocumentElement();
  -            traverseSchema(root);
  -        }
  -        catch (Exception e) {
  +            Element root = fSchemaDocument.getDocumentElement(); // Get root of grammar tree representation
  +            traverseSchema(root); //start traversing and filling Grammar structures                                                        
  +        } catch (Exception e) {
               e.printStackTrace(System.err);
  -//            System.exit(1);
  +            System.exit(1);
           }
       }
   
  +    /**
  +     * We traverse recursively through Document and build 
  +     * Grammar as we go along.
  +     * 
  +     * @param root   Element
  +     * @exception Exception
  +     */
       private void traverseSchema(Element root) throws Exception {
           // is there anything to do?
           if (root == null) {
  @@ -290,64 +286,30 @@
   
           // run through children
           for (Element child = XUtil.getFirstChildElement(root);
  -             child != null;
  -             child = XUtil.getNextSiblingElement(child)) {
  -            //System.out.println("child: "+child.getNodeName()+' '+child.getAttribute(ATT_NAME));
  +            child != null;
  +            child = XUtil.getNextSiblingElement(child)) {
  +            //System.out.println("child: "+child.getNodeName()+' '+child.getAttribute(SchemaSymbols.ATT_NAME));
   
               //
               // Element type
               //
   
               String name = child.getNodeName();
  -			if (name.equals(ELT_COMMENT)) {
  -				traverseComment(child);
  -            } else if (name.equals(ELT_DATATYPEDECL)) {
  -				traverseDatatypeDecl(child);
  -            } else if (name.equals(ELT_ARCHETYPEDECL)) {
  -				traverseTypeDecl(child);
  -			} else if (name.equals(ELT_ELEMENTDECL)) { // && child.getAttribute(ATT_REF).equals("")) {
  -				traverseElementDecl(child);
  -			} else if (name.equals(ELT_ATTRGROUPDECL)) {
  -				traverseAttrGroup(child);
  -			} else if (name.equals(ELT_GROUPDECL) && child.getAttribute(ATT_REF).equals("")) {
  -				traverseGroup(child);
  -			}
  +            if (name.equals(SchemaSymbols.ELT_ANNOTATION) ) {
  +                traverseComment(child);
  +            } else if (name.equals(SchemaSymbols.ELT_SIMPLETYPE )) {
  +                traverseDatatypeDecl(child);
  +            } else if (name.equals(SchemaSymbols.ELT_COMPLEXTYPE )) {
  +                traverseTypeDecl(child);
  +            } else if (name.equals(SchemaSymbols.ELT_ELEMENT )) { // && child.getAttribute(SchemaSymbols.ATT_REF).equals("")) {
  +                traverseElementDecl(child);
  +            } else if (name.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) {
  +                traverseAttrGroup(child);
  +            } else if (name.equals(SchemaSymbols.ELT_GROUP) && child.getAttribute(SchemaSymbols.ATT_REF).equals("")) {
  +                traverseGroup(child);
  +            } else if (name.equals(SchemaSymbols.ELT_NOTATION)) {
   
  -            //
  -            // Entities
  -            //
  -/*
  -            else if (name.equals(ELT_TEXTENTITYDECL) ||
  -                     name.equals(ELT_EXTERNALENTITYDECL) ||
  -                     name.equals(ELT_UNPARSEDENTITYDECL)) {
  -
  -                int entityName = fStringPool.addSymbol(child.getAttribute(ATT_NAME));
  -
  -                if (name.equals(ELT_TEXTENTITYDECL)) {
  -                    int value = fStringPool.addString(child.getFirstChild().getFirstChild().getNodeValue());
  -                    fEntityHandler.addInternalEntityDecl(entityName, value, true);
  -                }
  -                else {
  -                    int publicId = fStringPool.addString(child.getAttribute("public"));
  -                    int systemId = fStringPool.addString(child.getAttribute("system"));
  -
  -                    if (name.equals(ELT_EXTERNALENTITYDECL)) {
  -                        fEntityHandler.addExternalEntityDecl(entityName, publicId, systemId, true);
  -                    }
  -                    else {
  -                        int notationName = fStringPool.addSymbol(child.getAttribute("notation"));
  -                        fEntityHandler.addUnparsedEntityDecl(entityName, publicId, systemId, notationName, true);
  -                    }
  -                }
  -            }
  -*/
  -            //
  -            // Notation
  -            //
  -
  -            else if (name.equals(ELT_NOTATIONDECL)) {
  -
  -                int notationName = fStringPool.addSymbol(child.getAttribute(ATT_NAME));
  +                int notationName = fStringPool.addSymbol(child.getAttribute(SchemaSymbols.ATT_NAME));
                   int publicId = fStringPool.addString(child.getAttribute("public"));
                   int systemId = fStringPool.addString(child.getAttribute("system"));
                   fEntityHandler.addNotationDecl(notationName, publicId, systemId, true);
  @@ -355,711 +317,61 @@
   
           } // for each child node
   
  -        cleanupForwardReferences();
       } // traverseSchema(Element)
   
  -    /**
  -     * this method is going to be needed to handle any elementDecl derived constructs which
  -     * need to copy back attributes that haven't been declared yet.
  -     * right now that's just attributeGroups and types -- grrr.
  -     */
  -    private void cleanupForwardReferences() {
  -        for (java.util.Enumeration keys = fForwardRefs.keys(); keys.hasMoreElements();) {
  -            Object k = keys.nextElement();
  -            int ik = ((Integer) k).intValue();
  -            cleanupForwardReferencesTo(ik);
  -        }
  +
  +    private void traverseComment(Element comment) {
  +        return; // do nothing
       }
   
  -    private void cleanupForwardReferencesTo(int r) {
  -        Vector referrers = (Vector) fForwardRefs.get(new Integer(r));
  -        if (referrers == null) return;
  -//        System.out.println("referee "+r+" csnIndex= "+getContentSpec(getElement(r)));
  -        for (int i = 0; i < referrers.size(); i++) {
  -            int ref = ((Integer) referrers.elementAt(i)).intValue();
  -//            System.out.println("referrer "+referrers.elementAt(i)+ " csnIndex = "+getContentSpec(getElement(((Integer)referrers.elementAt(i)).intValue())));
  -//            System.out.println("copying from "+fStringPool.toString(r)+" to "+fStringPool.toString(ref));
  -            fValidator.copyAtts(r, ((Integer) referrers.elementAt(i)).intValue());
  -//            try {
  -//                fValidator.fixupDeclaredElements(ref, r);
  -//            } catch (Exception e) {
  -//                System.out.println("Error while cleaning up");
  -//            }
  -//            cleanupForwardReferencesTo(ref);
  -        }
  +    private int traverseTypeDecl(Element typeDecl) throws Exception {
  +        return 0;
       }
   
  -	private void traverseComment(Element comment) {
  -        return; // do nothing
  -	}
  +    private int traverseGroup(Element groupDecl) throws Exception {
  +        return 0;
  +    }
   
  -	private int traverseTypeDecl(Element typeDecl) throws Exception {
  -		String typeName = typeDecl.getAttribute(ATT_NAME);
  -		String content = typeDecl.getAttribute(ATT_CONTENT);
  -		String source = typeDecl.getAttribute(ATT_SOURCE);
  -
  -		if (typeName.equals("")) { // gensym a unique name
  -		    typeName = "http://www.apache.org/xml/xerces/internalType"+fTypeCount++;
  -		}
  -		
  -		Element child = null;
  -        int contentSpecType = 0;
  -        int csnType = 0;
  -        int left = -2;
  -        int right = -2;
  -        Vector uses = new Vector();
  -		
  -   		// skip refinement and annotations
  -        child = null;
  -		for (child = XUtil.getFirstChildElement(typeDecl);
  -		     child != null && (child.getNodeName().equals(ELT_RESTRICTIONS) ||
  -		                       child.getNodeName().equals(ELT_ANNOTATION));
  -		     child = XUtil.getNextSiblingElement(child)) {
  -    		if (child.getNodeName().equals(ELT_RESTRICTIONS))
  -	    		reportSchemaError(SchemaMessageProvider.FeatureUnsupported,
  -		    					  new Object [] { "Restriction" });
  -	    }
  -
  -        // if content = textonly, source is a datatype
  -        if (content.equals(ATTVAL_TEXTONLY)) {
  -            if (fDatatypeRegistry.getValidatorFor(source) == null) // must be datatype
  -	    		reportSchemaError(SchemaMessageProvider.NotADatatype,
  -		    					  new Object [] { source }); //REVISIT check forward refs
  -            //handle datatypes
  -            contentSpecType = fStringPool.addSymbol("DATATYPE");
  -            left = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_LEAF,
  -									                   fStringPool.addSymbol(source),
  -													   -1, false);
  -            
  -        } else {   
  -            contentSpecType = fStringPool.addSymbol("CHILDREN");
  -            csnType = XMLContentSpec.CONTENTSPECNODE_SEQ;
  -            boolean mixedContent = false;
  -            boolean elementContent = false;
  -            boolean textContent = false;
  -            left = -2;
  -            right = -2;
  -            boolean hadContent = false;
  -		
  -            if (content.equals(ATTVAL_EMPTY)) {
  -                contentSpecType = fStringPool.addSymbol("EMPTY");
  -                left = -1; // no contentSpecNode needed
  -            } else if (content.equals(ATTVAL_MIXED) || content.equals("")) {
  -                contentSpecType = fStringPool.addSymbol("MIXED");
  -                mixedContent = true;
  -                csnType = XMLContentSpec.CONTENTSPECNODE_CHOICE;
  -            } else if (content.equals(ATTVAL_ELEMONLY)) {
  -                elementContent = true;
  -            } else if (content.equals(ATTVAL_TEXTONLY)) {
  -                textContent = true;
  -            }
  -            
  -            if (mixedContent) {
  -                // a    dd #PCDATA leaf
  -                left = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_LEAF,
  -                                                           -1, // -1 means "#PCDATA" is name
  -                                                           -1, false);
  -            }
  +    private int traverseGroupRef(Element groupRef) {
  +        return 0;
  +    }
   
  -            for (;
  -                 child != null;
  -                 child = XUtil.getNextSiblingElement(child)) {
  -                int index = -2;
  -                hadContent = true;
  -                String childName = child.getNodeName();
  -                if (childName.equals(ELT_ELEMENTDECL)) {
  -                    if (child.getAttribute(ATT_REF).equals("") && 
  -                        child.getAttribute(ATT_TYPE).equals("")) { // elt decl
  -                        if (elementContent)   //R   EVISIT: no support for nested type declarations
  -                            reportSchemaError(SchemaMessageProvider.FeatureUnsupported,
  -                                              new Object [] { "Nesting element declarations" });
  -                        else
  -                            reportSchemaError(SchemaMessageProvider.NestedOnlyInElemOnly, null);
  -                    } else if (mixedContent || elementContent) {
  -                        if (!child.getAttribute(ATT_TYPE).equals("")) {
  -                            int elementNameIndex = traverseElementDecl(child);
  -                            index = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_LEAF,
  -                                                                        elementNameIndex,
  -                                                                        -1, false);
  -                        } else // ATT_REF != ""
  -                            index = traverseElementRef(child);
  -                    } else {
  -                        reportSchemaError(SchemaMessageProvider.EltRefOnlyInMixedElemOnly, null);
  -                    }
  -                } else if (childName.equals(ELT_GROUPDECL)) {
  -                    if (elementContent) {
  -                        int groupNameIndex = 0;
  -                        if (child.getAttribute(ATT_REF).equals("")) {
  -                            groupNameIndex = traverseGroup(child);
  -                        } else
  -                            groupNameIndex = traverseGroupRef(child);
  -                        index = getContentSpecHandleForElementType(groupNameIndex);
  -                    } else if (!elementContent)
  -                        reportSchemaError(SchemaMessageProvider.OnlyInEltContent,
  -                                          new Object [] { "group" });
  -                    else // buildAll    
  -                        reportSchemaError(SchemaMessageProvider.OrderIsAll,
  -                                          new Object [] { "group" } );
  -                } else if (childName.equals(ELT_ATTRIBUTEDECL) ||
  -                           childName.equals(ELT_ATTRGROUPDECL)) {
  -                    break; // attr processing is done be    low
  -                } else if (childName.equals(ELT_ANY)) {
  -                    contentSpecType = fStringPool.addSymbol("ANY");
  -                    left = -1;
  -                } else { // datatype qual   
  -                    if (source.equals(""))
  -                        reportSchemaError(SchemaMessageProvider.DatatypeWithType, null);
  -                    else
  -                        reportSchemaError(SchemaMessageProvider.DatatypeQualUnsupported,
  -                                          new Object [] { childName });
  -                }
  -                uses.addElement(new Integer(index));
  -                if (left == -2) {
  -                    left = index;
  -                } else if (right == -2) {
  -                    right = index;
  -                } else {
  -                    left = fValidator.addContentSpecNode(csnType, left, right, false);
  -                    right = index;
  -                }
  -            }
  -            
  -            if (hadContent && right != -2)
  -                left = fValidator.addContentSpecNode(csnType, left, right, false);
  -		
  -            if (mixedContent && hadContent) {
  -                // set occurrence count
  -                left = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE,
  -                                                           left, -1, false);
  -            }
  -        }
  -		// stick in ElementDeclPool as a hack
  -		int typeNameIndex = fStringPool.addSymbol(typeName); //REVISIT namespace clashes possible
  -		int typeIndex = fValidator.addElementDecl(typeNameIndex, contentSpecType, left, false);
  -
  -        for (int x = 0; x < uses.size(); x++)
  -            addUse(typeNameIndex, (Integer)uses.elementAt(x));
  -
  -		// (attribute | attrGroupRef)*
  -		for (;
  -			 child != null;
  -			 child = XUtil.getNextSiblingElement(child)) {
  -			String childName = child.getNodeName();
  -			if (childName.equals(ELT_ATTRIBUTEDECL)) {
  -				traverseAttributeDecl(child, typeIndex);
  -			} else if (childName.equals(ELT_ATTRGROUPDECL) && !child.getAttribute(ATT_REF).equals("")) {
  -    			int index = traverseAttrGroupRef(child);
  -    			if (getContentSpecHandleForElementType(index) == -1) {
  -					reportSchemaError(SchemaMessageProvider.FeatureUnsupported,
  -									  new Object [] { "Forward References to attrGroup" });
  -    			    Vector v = null;
  -    			    Integer i = new Integer(index);
  -    			    if ((v = (Vector) fForwardRefs.get(i)) == null)
  -    			        v = new Vector();
  -                    v.addElement(new Integer(typeNameIndex));
  -    			    fForwardRefs.put(i,v);
  -                    addUse(typeNameIndex, index);
  -    			} else
  -        			fValidator.copyAtts(index, typeNameIndex);
  -			}
  -		}
  -		
  -        return typeNameIndex;
  -	}
  -
  -	private int traverseGroup(Element groupDecl) throws Exception {
  -		String groupName = groupDecl.getAttribute(ATT_NAME);
  -		String collection = groupDecl.getAttribute(ATT_COLLECTION);
  -		String order = groupDecl.getAttribute(ATT_ORDER);
  -		
  -		if (groupName.equals("")) { // gensym a unique name
  -		    groupName = "http://www.apache.org/xml/xerces/internalGroup"+fGroupCount++;
  -		}
  -		
  -		Element child = XUtil.getFirstChildElement(groupDecl);
  -        while (child != null && child.getNodeName().equals(ELT_ANNOTATION))
  -            child = XUtil.getNextSiblingElement(child);
  -
  -		int contentSpecType = 0;
  -		int csnType = 0;
  -        boolean buildAll = false;
  -        int allChildren[] = null;
  -        int allChildCount = 0;
  -		
  -		if (order.equals(ATTVAL_CHOICE)) {
  -			csnType = XMLContentSpec.CONTENTSPECNODE_CHOICE;
  -			contentSpecType = fStringPool.addSymbol("CHILDREN");
  -		} else if (order.equals(ATTVAL_SEQ)) {
  -			csnType = XMLContentSpec.CONTENTSPECNODE_SEQ;
  -			contentSpecType = fStringPool.addSymbol("CHILDREN");
  -		} else if (order.equals(ATTVAL_ALL)) {
  -            buildAll = true;
  -            allChildren = new int[((org.apache.xerces.dom.NodeImpl)groupDecl).getLength()];
  -            allChildCount = 0;
  -		}
  -		int left = -2;
  -		int right = -2;
  -		boolean hadContent = false;
  -		int groupIndices[] = new int [((org.apache.xerces.dom.NodeImpl)groupDecl).getLength()];
  -		int numGroups = 0;
  -
  -		for (;
  -			 child != null;
  -			 child = XUtil.getNextSiblingElement(child)) {
  -			int index = -2;
  -            hadContent = true;
  -			String childName = child.getNodeName();
  -			if (childName.equals(ELT_ELEMENTDECL)) {
  -			    if (child.getAttribute(ATT_REF).equals("") && 
  -                    child.getAttribute(ATT_TYPE).equals("")) { //elt decl
  -					reportSchemaError(SchemaMessageProvider.FeatureUnsupported,
  -									  new Object [] { "Nesting element declarations" });
  -                } else {
  -                    if (!child.getAttribute(ATT_TYPE).equals("")) {
  -    			       int elementNameIndex = traverseElementDecl(child);
  -    			       index = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_LEAF,
  -    			                                                   elementNameIndex,
  -    			                                                   -1, false);
  -    			       
  -                    } else {
  -                        index = traverseElementRef(child); 
  -                    }
  -                }
  -			} else if (childName.equals(ELT_GROUPDECL)) {
  -			    if (!buildAll) {
  -    			    int groupNameIndex = traverseGroup(child);
  -	    			groupIndices[numGroups++] = groupNameIndex;
  -		    		index = getContentSpecHandleForElementType(groupNameIndex);
  -		    	} else
  -					reportSchemaError(SchemaMessageProvider.OrderIsAll,
  -									  new Object [] { "group" } );
  -			} else {
  -				reportSchemaError(SchemaMessageProvider.GroupContentRestricted,
  -								  new Object [] { "group", childName });
  -			}
  -			if (buildAll) {
  -			    allChildren[allChildCount++] = index;
  -			} else if (left == -2) {
  -				left = index;
  -			} else if (right == -2) {
  -				right = index;
  -			} else {
  -   				left = fValidator.addContentSpecNode(csnType, left, right, false);
  -    			right = index;
  -   			}
  -		}
  -		if (buildAll) {
  -		    left = buildAllModel(allChildren,allChildCount);
  -		} else {
  -			if (hadContent && right != -2)
  -				left = fValidator.addContentSpecNode(csnType, left, right, false);
  -		}
  -		left = expandContentModel(left, groupDecl);
  -	
  -		// stick in ElementDeclPool as a hack
  -		int groupNameIndex = fStringPool.addSymbol(groupName); //REVISIT namespace clashes possible
  -		int groupIndex = fValidator.addElementDecl(groupNameIndex, contentSpecType, left, false);
  -
  -        return groupNameIndex;
  -	}
  -
  -	private int traverseGroupRef(Element groupRef) {
  -	    String name = groupRef.getAttribute(ATT_REF);
  -	    int index = fStringPool.addSymbol(name);
  -	    return index;
  -	}
  -
  -	public int traverseDatatypeDecl(Element datatypeDecl) throws Exception {
  -		int newTypeName;
  -		
  - 		if (datatypeDecl.getAttribute(ATT_NAME).equals("")) {
  -    		String newTypeString = "http://www.apache.org/xml/xerces/internalDatatype"+fGroupCount++;
  -		    newTypeName = fStringPool.addSymbol(newTypeString);
  -	 	} else
  -    		newTypeName = fStringPool.addSymbol(datatypeDecl.getAttribute(ATT_NAME));
  -		int basetype = fStringPool.addSymbol(datatypeDecl.getAttribute(ATT_SOURCE));
  -
  -		// check that base type is defined
  -		//REVISIT: how do we do the extension mechanism? hardwired type name?
  -		DatatypeValidator baseValidator = fDatatypeRegistry.getValidatorFor(datatypeDecl.getAttribute(ATT_SOURCE));
  -		if (baseValidator == null) {
  -			reportSchemaError(SchemaMessageProvider.UnknownBaseDatatype,
  -							  new Object [] { datatypeDecl.getAttribute(ATT_SOURCE), datatypeDecl.getAttribute(ATT_NAME) });
  -			return -1;
  -		}
  -
  -		// build facet list
  -		int numFacets = 0;
  -		int numEnumerationLiterals = 0;
  -		Hashtable facetData = new Hashtable();
  -		Vector enumData = new Vector();
  -
  -        // Skip annotations
  -		Node facet = datatypeDecl.getFirstChild();
  -		while (facet != null && facet.getNodeName().equals(ELT_ANNOTATION))
  -		    facet = facet.getNextSibling();
  -		while (facet != null) {
  -			if (facet.getNodeType() == Node.ELEMENT_NODE) {
  -			    Element facetElt = (Element) facet;
  -				numFacets++;
  -    			if (facetElt.getNodeName().equals(DatatypeValidator.ENUMERATION)) {
  -					numEnumerationLiterals++;
  -					enumData.addElement(facetElt.getAttribute(ATT_VALUE));
  -				} else {
  -					facetData.put(facetElt.getNodeName(),facetElt.getAttribute(ATT_VALUE));
  -				}
  -			}
  -			facet = facet.getNextSibling();
  -		}
  -		if (numEnumerationLiterals > 0) {
  -			facetData.put(DatatypeValidator.ENUMERATION, enumData);
  -		}
  -
  -		// create & register validator for "generated" type if it doesn't exist
  -		try {
  -			DatatypeValidator newValidator = (DatatypeValidator) baseValidator.getClass().newInstance();
  -			if (numFacets > 0)
  -				newValidator.setFacets(facetData);
  -			fDatatypeRegistry.addValidator(fStringPool.toString(newTypeName),newValidator);
  -		} catch (Exception e) {
  -			reportSchemaError(SchemaMessageProvider.DatatypeError,
  -							  new Object [] { e.getMessage() });
  -		}
  -        return newTypeName;
  -	}
  -
  -	private int traverseElementDecl(Element elementDecl) throws Exception {
  -		int contentSpecType      = -1;
  -		int contentSpecNodeIndex = -1;
  -        int typeNameIndex = -1;
  -
  -		String name = elementDecl.getAttribute(ATT_NAME);
  -		String ref = elementDecl.getAttribute(ATT_REF);
  -		String type = elementDecl.getAttribute(ATT_TYPE);
  -		String minOccurs = elementDecl.getAttribute(ATT_MINOCCURS);
  -		String maxOccurs = elementDecl.getAttribute(ATT_MAXOCCURS);
  -		String dflt = elementDecl.getAttribute(ATT_DEFAULT);
  -		String fixed = elementDecl.getAttribute(ATT_FIXED);
  -
  -        int attrCount = 0;
  -		if (!ref.equals("")) attrCount++;
  -		if (!type.equals("")) attrCount++;
  -		//REVISIT top level check for ref & archref
  -		if (attrCount > 1)
  -			reportSchemaError(SchemaMessageProvider.OneOfTypeRefArchRef, null);
  -		
  -		if (!ref.equals("")) {
  -		    if (XUtil.getFirstChildElement(elementDecl) != null)
  -				reportSchemaError(SchemaMessageProvider.NoContentForRef, null);
  -		   	int typeName = fStringPool.addSymbol(ref);
  -		   	contentSpecNodeIndex = getContentSpecHandleForElementType(typeName);
  -		   	contentSpecType = getContentSpecTypeForElementType(typeName);
  -
  -		   	int elementNameIndex = fStringPool.addSymbol(name);
  -            int elementIndex = -1;
  -
  -		   	if (contentSpecNodeIndex == -1) {
  -		   	    contentSpecType = XMLContentSpec.CONTENTSPECNODE_LEAF;
  -            	contentSpecNodeIndex = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_LEAF,
  -	        							                                   elementNameIndex, -1, false);
  -                fValidator.addElementDecl(elementNameIndex, contentSpecType, contentSpecNodeIndex, true);
  -				reportSchemaError(SchemaMessageProvider.FeatureUnsupported,
  -								  new Object [] { "Forward references to archetypes" });
  -    			Vector v = null;
  -    			Integer i = new Integer(typeName);
  -    			if ((v = (Vector) fForwardRefs.get(i)) == null)
  -    			     v = new Vector();
  -                v.addElement(new Integer(elementNameIndex));
  -    			fForwardRefs.put(i,v);
  -    			addUse(elementNameIndex, typeName);
  -		   	} else {
  -                fValidator.addElementDecl(elementNameIndex, contentSpecType, contentSpecNodeIndex, true);
  -                // copy up attribute decls from type object
  -                fValidator.copyAtts(typeName, elementNameIndex);
  -            }
  -		    return elementNameIndex;
  -		}
  -		
  -		// element has a single child element, either a datatype or a type, null if primitive
  -		Element content = XUtil.getFirstChildElement(elementDecl);
  -        while (content != null && content.getNodeName().equals(ELT_ANNOTATION))
  -            content = XUtil.getNextSiblingElement(content);
  -
  -		if (content != null) {
  -			String contentName = content.getNodeName();
  -			if (contentName.equals(ELT_ARCHETYPEDECL)) {
  -				typeNameIndex = traverseTypeDecl(content);
  -				contentSpecNodeIndex = getContentSpecHandleForElementType(typeNameIndex);
  -				contentSpecType = getContentSpecTypeForElementType(typeNameIndex);
  -			} else if (contentName.equals(ELT_DATATYPEDECL)) {
  -				reportSchemaError(SchemaMessageProvider.FeatureUnsupported,
  -								  new Object [] { "Nesting datatype declarations" });
  -				// contentSpecNodeIndex = traverseDatatypeDecl(content);
  -				// contentSpecType = fStringPool.addSymbol("DATATYPE");
  -			} else if (!type.equals("")) { // datatype
  -				contentSpecType = fStringPool.addSymbol("DATATYPE");
  -
  -				// set content spec node index to leaf
  -				contentSpecNodeIndex = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_LEAF,
  -																		   fStringPool.addSymbol(content.getAttribute(ATT_NAME)),
  -																		   -1, false);
  -				// set occurrance count
  -				contentSpecNodeIndex = expandContentModel(contentSpecNodeIndex, content);
  -			} else if (type.equals("")) { // "untyped" leaf
  -			    // untyped leaf element decl
  -	    		contentSpecType = fStringPool.addSymbol("CHILDREN");
  -
  -    			// add leaf
  -				int leftIndex = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_LEAF,
  -																	fStringPool.addSymbol(content.getAttribute(ATT_NAME)),
  -																	-1, false);
  -
  -    			// set occurrence count
  -	    		contentSpecNodeIndex = expandContentModel(contentSpecNodeIndex, content);
  -			} else {
  -				System.out.println("unhandled case in element decl code");
  -			}
  -		} else if (!type.equals("")) { // type specified in attribute, not content
  -			contentSpecType = fStringPool.addSymbol("DATATYPE");
  -
  -			// set content spec node index to leaf
  -			contentSpecNodeIndex = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_LEAF,
  -																	   fStringPool.addSymbol(type),
  -																	   -1, false);
  -			// set occurrance count
  -			contentSpecNodeIndex = expandContentModel(contentSpecNodeIndex, elementDecl);
  -		}
  -
  -		//
  -		// Create element decl
  -		//
  -
  -		int elementNameIndex     = fStringPool.addSymbol(elementDecl.getAttribute(ATT_NAME));
  -
  -		// add element decl to pool
  -		int elementIndex = fValidator.addElementDecl(elementNameIndex, contentSpecType, contentSpecNodeIndex, true);
  -//        System.out.println("elementIndex:"+elementIndex+" "+elementDecl.getAttribute(ATT_NAME)+" eltType:"+elementName+" contentSpecType:"+contentSpecType+
  -//                           " SpecNodeIndex:"+ contentSpecNodeIndex);
  -
  -        // copy up attribute decls from type object
  -        if (typeNameIndex != -1)
  -            fValidator.copyAtts(typeNameIndex, elementNameIndex);
  +    public int traverseDatatypeDecl(Element datatypeDecl) throws Exception {
  +        return 0;
  +    }
   
  -        return elementNameIndex;
  -	}
  +    private int traverseElementDecl(Element elementDecl) throws Exception {
  +        return 0;
  +    }
   
       private int traverseElementRef(Element elementRef) {
  -        String elementName = elementRef.getAttribute(ATT_REF);
  -        int elementTypeIndex = fStringPool.addSymbol(elementName);
  -        int contentSpecNodeIndex = 0;
  -        try {
  -        	contentSpecNodeIndex = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_LEAF,
  -	    							                                   elementTypeIndex, -1, false);
  -            contentSpecNodeIndex = expandContentModel(contentSpecNodeIndex, elementRef);
  -        } catch (Exception e) {
  -            //REVISIT: integrate w/ error handling
  -            e.printStackTrace();
  -        }
  -        return contentSpecNodeIndex;
  +        return 0;
       }
   
  -	//REVISIT: elementIndex API is ugly
  -	private void traverseAttributeDecl(Element attrDecl, int elementIndex) throws Exception {
  -		// attribute name
  -		int attName = fStringPool.addSymbol(attrDecl.getAttribute(ATT_NAME));
  -
  -		// attribute type
  -		int attType = -1;
  -		int enumeration = -1;
  -		String datatype = attrDecl.getAttribute(ATT_TYPE);
  -		if (datatype.equals("")) {
  -		    Element child = XUtil.getFirstChildElement(attrDecl);
  -		    while (child != null && !child.getNodeName().equals(ELT_DATATYPEDECL))
  -		        child = XUtil.getNextSiblingElement(child);
  -		    if (child != null && child.getNodeName().equals(ELT_DATATYPEDECL)) {
  -		        attType = fStringPool.addSymbol("DATATYPE");
  -		        enumeration = traverseDatatypeDecl(child);
  -		    } else 
  -    			attType = fStringPool.addSymbol("CDATA");
  -		} else {
  -			if (datatype.equals("string")) {
  -				attType = fStringPool.addSymbol("CDATA");
  -			} else if (datatype.equals("ID")) {
  -				attType = fStringPool.addSymbol("ID");
  -			} else if (datatype.equals("IDREF")) {
  -				attType = fStringPool.addSymbol("IDREF");
  -			} else if (datatype.equals("IDREFS")) {
  -				attType = fStringPool.addSymbol("IDREFS");
  -			} else if (datatype.equals("ENTITY")) {
  -				attType = fStringPool.addSymbol("ENTITY");
  -			} else if (datatype.equals("ENTITIES")) {
  -				attType = fStringPool.addSymbol("ENTITIES");
  -			} else if (datatype.equals("NMTOKEN")) {
  -				Element e = XUtil.getFirstChildElement(attrDecl, "enumeration");
  -				if (e == null) {
  -					attType = fStringPool.addSymbol("NMTOKEN");
  -				} else {
  -					attType = fStringPool.addSymbol("ENUMERATION");
  -					enumeration = fStringPool.startStringList();
  -					for (Element literal = XUtil.getFirstChildElement(e, "literal");
  -						 literal != null;
  -						 literal = XUtil.getNextSiblingElement(literal, "literal")) {
  -			    		int stringIndex = fStringPool.addSymbol(literal.getFirstChild().getNodeValue());
  -						fStringPool.addStringToList(enumeration, stringIndex);
  -					}
  -					fStringPool.finishStringList(enumeration);
  -				}
  -			} else if (datatype.equals("NMTOKENS")) {
  -				attType = fStringPool.addSymbol("NMTOKENS");
  -			} else if (datatype.equals(ELT_NOTATIONDECL)) {
  -				attType = fStringPool.addSymbol("NOTATION");
  -			} else { // REVISIT: Danger: assuming all other ATTR types are datatypes
  -				//REVISIT check against list of validators to ensure valid type name
  -				attType = fStringPool.addSymbol("DATATYPE");
  -				enumeration = fStringPool.addSymbol(datatype);
  -			}
  -		}
  -
  -		// attribute default type
  -		int attDefaultType = -1;
  -		int attDefaultValue = -1;
  -		boolean required = attrDecl.getAttribute("minOccurs").equals("1");
  -		if (required) {
  -			attDefaultType = fStringPool.addSymbol("#REQUIRED");
  -		} else {
  -			String fixed = attrDecl.getAttribute(ATT_FIXED);
  -			if (!fixed.equals("")) {
  -				attDefaultType = fStringPool.addSymbol("#FIXED");
  -				attDefaultValue = fStringPool.addString(fixed);
  -			} else {
  -				// attribute default value
  -				String defaultValue = attrDecl.getAttribute(ATT_DEFAULT);
  -				if (!defaultValue.equals("")) {
  -					attDefaultType = fStringPool.addSymbol("");
  -					attDefaultValue = fStringPool.addString(defaultValue);
  -				} else {
  -					attDefaultType = fStringPool.addSymbol("#IMPLIED");
  -				}
  -			}
  -			// check default value is valid for the datatype.
  -			if (attType == fStringPool.addSymbol("DATATYPE") && attDefaultValue != -1) {
  -        		try { // REVISIT - integrate w/ error handling
  -                    String type = fStringPool.toString(enumeration);
  -                    DatatypeValidator v = fDatatypeRegistry.getValidatorFor(type);
  -                    if (v != null)
  -                        v.validate(fStringPool.toString(attDefaultValue));
  -                    else
  -						reportSchemaError(SchemaMessageProvider.NoValidatorFor,
  -										  new Object [] { type });
  -                } catch (InvalidDatatypeValueException idve) {
  -					reportSchemaError(SchemaMessageProvider.IncorrectDefaultType,
  -									  new Object [] { attrDecl.getAttribute(ATT_NAME), idve.getMessage() });
  -                } catch (Exception e) {
  -                    e.printStackTrace();
  -                    System.out.println("Internal error in attribute datatype validation");
  -                }
  -            }
  -		}
  +    private void traverseAttributeDecl(Element attrDecl, int elementIndex) throws Exception {
  +        return ;
  +    }
   
  -		// add attribute to element decl pool
  -		fValidator.addAttDef(elementIndex, attName, attType, enumeration, attDefaultType, attDefaultValue, true);
  -	}
  -
  -	private int traverseAttrGroup(Element attrGroupDecl) throws Exception {
  -
  -		String attrGroupName = attrGroupDecl.getAttribute(ATT_NAME);
  -		
  -		if (attrGroupName.equals("")) { // gensym a unique name
  -		    attrGroupName = "http://www.apache.org/xml/xerces/internalGroup"+fGroupCount++;
  -		}
  -		
  -		Element child = XUtil.getFirstChildElement(attrGroupDecl);
  -        while (child != null && child.getNodeName().equals(ELT_ANNOTATION))
  -            child = XUtil.getNextSiblingElement(child);
  -
  -		int groupIndices[] = new int [((org.apache.xerces.dom.NodeImpl)attrGroupDecl).getLength()];
  -		int numGroups = 0;
  -
  -		for (;
  -			 child != null;
  -			 child = XUtil.getNextSiblingElement(child)) {
  -			String childName = child.getNodeName();
  -			if (childName.equals(ELT_ATTRGROUPDECL) && !child.getAttribute(ATT_REF).equals("")) {
  -			    groupIndices[numGroups++] = traverseAttrGroupRef(child);
  -			    if (getContentSpecHandleForElementType(groupIndices[numGroups-1]) == -1) {
  -					reportSchemaError(SchemaMessageProvider.FeatureUnsupported,
  -									  new Object [] { "Forward reference to AttrGroup" });
  -			    }
  -			} else if (childName.equals(ELT_ATTRIBUTEDECL)) {
  -                continue;
  -   			} else {
  -				reportSchemaError(SchemaMessageProvider.IllegalAttContent,
  -								  new Object [] { childName });
  -   			}
  -		}
  -	
  -		// stick in ElementDeclPool as a hack
  -		int attrGroupNameIndex = fStringPool.addSymbol(attrGroupName); //REVISIT namespace clashes possible
  -		int attrGroupIndex = fValidator.addElementDecl(attrGroupNameIndex, 0, 0, false);
  -//        System.out.println("elementIndex:"+groupIndex+" "+groupName+" eltType:"+groupNameIndex+" SpecType:"+contentSpecType+
  -//                           " SpecNodeIndex:"+ left);
  -
  -		// (attribute | attrGroupRef)*
  -		for (child = XUtil.getFirstChildElement(attrGroupDecl);  // start from the beginning to just do attrs
  -			 child != null;
  -			 child = XUtil.getNextSiblingElement(child)) {
  -			String childName = child.getNodeName();
  -			if (childName.equals(ELT_ATTRIBUTEDECL)) {
  -				traverseAttributeDecl(child, attrGroupIndex);
  -			} else if (childName.equals(ELT_ATTRGROUPDECL)) {
  -    			int index = traverseAttrGroupRef(child);
  -    			if (getContentSpecHandleForElementType(index) == -1) {
  -					reportSchemaError(SchemaMessageProvider.FeatureUnsupported,
  -									  new Object [] { "Forward reference to AttrGroup" });
  -    			    Vector v = null;
  -    			    Integer i = new Integer(index);
  -    			    if ((v = (Vector) fForwardRefs.get(i)) == null)
  -    			        v = new Vector();
  -                    v.addElement(new Integer(attrGroupNameIndex));
  -    			    fForwardRefs.put(i,v);
  -    			    addUse(attrGroupNameIndex, index);
  -    			} else
  -    			    groupIndices[numGroups++] = getContentSpecHandleForElementType(index);
  -			}
  -		}
  -		
  -        // copy up attribute decls from nested groups
  -		for (int i = 0; i < numGroups; i++) {
  -            fValidator.copyAtts(groupIndices[i], attrGroupNameIndex);
  -        }
  -
  -        return attrGroupNameIndex;
  -	}
  -
  -	private int traverseAttrGroupRef(Element attrGroupRef) {
  -	    String name = attrGroupRef.getAttribute(ATT_REF);
  -	    int index = fStringPool.addSymbol(name);
  -        return index;
  -	}
  -	
  -	private void addUse(int def, int use) {
  -        addUse(def, new Integer(use));
  -	}
  -
  -	private void addUse(int def, Integer use) {
  -        Vector v = (Vector) fAttrGroupUses.get(new Integer(def));
  -        if (v == null) v = new Vector();
  -    		 v.addElement(use);
  -	}
  +    private int traverseAttrGroup(Element attrGroupDecl) throws Exception {
  +        return 0;
  +    }
  +
  +    private int traverseAttrGroupRef(Element attrGroupRef) {
  +        return 0;
  +    }
  +
  +    private void addUse(int def, int use) {
  +        return ;
  +    }
   
  +
       /** builds the all content model */
       private int buildAllModel(int children[], int count) throws Exception {
  -
           // build all model
           if (count > 1) {
   
               // create and initialize singletons
  -            XMLContentSpec.Node choice = new XMLContentSpec.Node();
  +            XMLContentSpec choice = new XMLContentSpec();
   
               choice.type = XMLContentSpec.CONTENTSPECNODE_CHOICE;
               choice.value = -1;
  @@ -1081,15 +393,14 @@
   
       /** Builds the all model. */
       private int buildAllModel(int src[], int offset,
  -                              XMLContentSpec.Node choice) throws Exception {
  +                              XMLContentSpec choice) throws Exception {
   
           // swap last two places
           if (src.length - offset == 2) {
               int seqIndex = createSeq(src);
               if (choice.value == -1) {
                   choice.value = seqIndex;
  -            }
  -            else {
  +            } else {
                   if (choice.otherValue != -1) {
                       choice.value = fValidator.addContentSpecNode(choice.type, choice.value, choice.otherValue, false);
                   }
  @@ -1099,8 +410,7 @@
               seqIndex = createSeq(src);
               if (choice.value == -1) {
                   choice.value = seqIndex;
  -            }
  -            else {
  +            } else {
                   if (choice.otherValue != -1) {
                       choice.value = fValidator.addContentSpecNode(choice.type, choice.value, choice.otherValue, false);
                   }
  @@ -1132,12 +442,12 @@
   
           for (int i = 2; i < src.length; i++) {
               left = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_SEQ,
  -                                                       left, right, false);
  +                                                 left, right, false);
               right = src[i];
           }
   
           return fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_SEQ,
  -                                                   left, right, false);
  +                                             left, right, false);
   
       } // createSeq(int[]):int
   
  @@ -1180,163 +490,51 @@
   
       } // swap(int[],int,int)
   
  -    /***
  -    private void print(int indexes[], int offset, boolean mark) {
  -
  -        for (int i = 0; i < indexes.length; i++) {
  -            System.out.print(offset==i?'.':' ');
  -            System.out.print(indexes[i]);
  -        }
  -        if (mark) {
  -            System.out.print(" *");
  -        }
  -        System.out.println();
  -
  -    } // print(int[],int,boolean)
  -    /***/
  -
  -    /** Builds the children content model. */
  -/*    private int buildChildrenModel(Element model, int type) throws Exception {
  -
  -        // is there anything to do?
  -        if (model == null) {
  -            return -1;
  -        }
  -
  -        // fill parent node
  -        int parentValue = -1;
  -        int parentOtherValue = -1;
  -
  -        // build content model bottom-up
  -        int index = -1;
  -        for (Element child = XUtil.getFirstChildElement(model);
  -             child != null;
  -             child = XUtil.getNextSiblingElement(child)) {
  -
  -            //
  -            // leaf
  -            //
  -
  -            String childName = child.getNodeName();
  -            if (childName.equals("elementTypeRef")) {
  -
  -                // add element name to symbol table
  -                String elementType = child.getAttribute(ATT_NAME);
  -                int elementTypeIndex = fStringPool.addSymbol(elementType);
  -
  -                // create leaf node
  -                index = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_LEAF,
  -                                                            elementTypeIndex, -1, false);
  -
  -                // set occurrence count
  -                index = expandContentModel(index, child);
  -
  -            }
  -
  -            //
  -            // all
  -            //
  -
  -            else if (childName.equals(ATTVAL_ALL)) {
  -
  -                index = buildAllModel(child);
  -
  -            }
  -
  -            //
  -            // choice or sequence
  -            //
  -
  -            else {
  -                int childType = childName.equals(ATTVAL_CHOICE)
  -                              ? XMLContentSpec.CONTENTSPECNODE_CHOICE
  -                              : XMLContentSpec.CONTENTSPECNODE_SEQ;
  -                index = buildChildrenModel(child, childType);
  -            }
  -
  -            // add to parent node
  -            if (parentValue == -1) {
  -                parentValue = index;
  -            }
  -            else if (parentOtherValue == -1) {
  -                parentOtherValue = index;
  -            }
  -            else {
  -                parentValue = fValidator.addContentSpecNode(type, parentValue, parentOtherValue, false);
  -                parentOtherValue = index;
  -            }
  -
  -        } // for all children
  -
  -        // set model type
  -        index = fValidator.addContentSpecNode(type, parentValue, parentOtherValue, false);
  -
  -        // set occurrence count
  -        index = expandContentModel(index, model);
  -
  -        // return last content spec node
  -        return index;
  -
  -    } // buildChildrenModel(Element,int):int
  -*/
       private int expandContentModel(int contentSpecNodeIndex, Element element) throws Exception {
   
           // set occurrence count
           int occurs = getOccurrenceCount(element);
           int m = 1, n = 1;
           if (!isSimpleOccurrenceCount(occurs)) {
  -            try { m = Integer.parseInt(element.getAttribute(ATT_MINOCCURS)); }
  -            catch (NumberFormatException e) {
  -				reportSchemaError(SchemaMessageProvider.ValueNotInteger,
  -								  new Object [] { ATT_MINOCCURS });
  -			}
  -            try { n = Integer.parseInt(element.getAttribute(ATT_MAXOCCURS)); }
  -            catch (NumberFormatException e) {
  -				reportSchemaError(SchemaMessageProvider.ValueNotInteger,
  -								  new Object [] { ATT_MAXOCCURS });
  -			}
  +            try {
  +                m = Integer.parseInt(element.getAttribute(SchemaSymbols.ATT_MINOCCURS));
  +            } catch (NumberFormatException e) {
  +                reportSchemaError(SchemaMessageProvider.ValueNotInteger,
  +                                  new Object [] { SchemaSymbols.ATT_MINOCCURS });
  +            }
  +            try {
  +                n = Integer.parseInt(element.getAttribute(SchemaSymbols.ATT_MAXOCCURS));
  +            } catch (NumberFormatException e) {
  +                reportSchemaError(SchemaMessageProvider.ValueNotInteger,
  +                                  new Object [] { SchemaSymbols.ATT_MAXOCCURS});
  +            }
           }
   
  -		switch (occurs) {
  -
  -            //
  -            // +
  -            //
  +        switch (occurs) {
   
  -            case XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE: {
  +        
  +        case XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE: {
                   //System.out.println("occurs = +");
                   contentSpecNodeIndex = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE,
  -                                                            contentSpecNodeIndex, -1, false);
  +                                                                     contentSpecNodeIndex, -1, false);
                   break;
               }
   
  -            //
  -            // *
  -            //
  -
  -            case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE: {
  +        case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE: {
                   //System.out.println("occurs = *");
                   contentSpecNodeIndex = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE,
  -                                                            contentSpecNodeIndex, -1, false);
  +                                                                     contentSpecNodeIndex, -1, false);
                   break;
               }
   
  -            //
  -            // ?
  -            //
  -
  -            case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE: {
  +        case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE: {
                   //System.out.println("occurs = ?");
                   contentSpecNodeIndex = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE,
  -                                                            contentSpecNodeIndex, -1, false);
  +                                                                     contentSpecNodeIndex, -1, false);
                   break;
               }
  -
  -            //
  -            // M -> *
  -            //
   
  -            case CONTENTSPECNODE_M_OR_MORE: {
  +        case CONTENTSPECNODE_M_OR_MORE: {
                   //System.out.println("occurs = "+m+" -> *");
   
                   // create sequence node
  @@ -1347,25 +545,25 @@
                   for (int i = 1; i < m; i++) {
                       if (otherValue != -1) {
                           value = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_SEQ,
  -                                                                    value, otherValue, false);
  +                                                              value, otherValue, false);
                       }
                       otherValue = contentSpecNodeIndex;
                   }
   
                   // create optional content model node
                   contentSpecNodeIndex = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE,
  -                                                            contentSpecNodeIndex, -1, false);
  +                                                                     contentSpecNodeIndex, -1, false);
   
                   // add optional part
                   if (otherValue != -1) {
                       value = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_SEQ,
  -                                                                value, otherValue, false);
  +                                                          value, otherValue, false);
                   }
                   otherValue = contentSpecNodeIndex;
   
                   // set expanded content model index
                   contentSpecNodeIndex = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_SEQ,
  -                                                            value, otherValue, false);
  +                                                                     value, otherValue, false);
                   break;
               }
   
  @@ -1373,7 +571,7 @@
               // M -> N
               //
   
  -            case CONTENTSPECNODE_M_TO_N: {
  +        case CONTENTSPECNODE_M_TO_N: {
                   //System.out.println("occurs = "+m+" -> "+n);
   
                   // create sequence node
  @@ -1384,27 +582,27 @@
                   for (int i = 1; i < m; i++) {
                       if (otherValue != -1) {
                           value = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_SEQ,
  -                                                                    value, otherValue, false);
  +                                                              value, otherValue, false);
                       }
                       otherValue = contentSpecNodeIndex;
                   }
   
                   // create optional content model node
                   contentSpecNodeIndex = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE,
  -                                                            contentSpecNodeIndex, -1, false);
  +                                                                     contentSpecNodeIndex, -1, false);
   
                   // add optional number
                   for (int i = n; i > m; i--) {
                       if (otherValue != -1) {
                           value = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_SEQ,
  -                                                                        value, otherValue, false);
  +                                                              value, otherValue, false);
                       }
                       otherValue = contentSpecNodeIndex;
                   }
   
                   // set expanded content model index
                   contentSpecNodeIndex = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_SEQ,
  -                                                            value, otherValue, false);
  +                                                                     value, otherValue, false);
                   break;
               }
   
  @@ -1412,12 +610,12 @@
               // 0 -> N
               //
   
  -            case CONTENTSPECNODE_ZERO_TO_N: {
  +        case CONTENTSPECNODE_ZERO_TO_N: {
                   //System.out.println("occurs = 0 -> "+n);
   
                   // create optional content model node
                   contentSpecNodeIndex = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE,
  -                                                            contentSpecNodeIndex, -1, false);
  +                                                                     contentSpecNodeIndex, -1, false);
   
                   int value = contentSpecNodeIndex;
                   int otherValue = -1;
  @@ -1426,14 +624,14 @@
                   for (int i = 1; i < n; i++) {
                       if (otherValue != -1) {
                           value = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_SEQ,
  -                                                                    value, otherValue, false);
  +                                                              value, otherValue, false);
                       }
                       otherValue = contentSpecNodeIndex;
                   }
   
                   // set expanded content model index
                   contentSpecNodeIndex = fValidator.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_SEQ,
  -                                                            value, otherValue, false);
  +                                                                     value, otherValue, false);
                   break;
               }
   
  @@ -1446,40 +644,34 @@
   
       private boolean isSimpleOccurrenceCount(int occurs) {
           return occurs == -1 ||
  -               occurs == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE ||
  -               occurs == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE ||
  -               occurs == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE;
  +        occurs == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE ||
  +        occurs == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE ||
  +        occurs == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE;
       }
   
       private int getOccurrenceCount(Element element) {
   
  -        String minOccur = element.getAttribute(ATT_MINOCCURS);
  -        String maxOccur = element.getAttribute(ATT_MAXOCCURS);
  +        String minOccur = element.getAttribute(SchemaSymbols.ATT_MINOCCURS);
  +        String maxOccur = element.getAttribute(SchemaSymbols.ATT_MAXOCCURS);
   
           if (minOccur.equals("0")) {
               if (maxOccur.equals("1") || maxOccur.length() == 0) {
                   return XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE;
  -            }
  -            else if (maxOccur.equals("*")) {
  +            } else if (maxOccur.equals("*")) {
                   return XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE;
  -            }
  -            else {
  +            } else {
                   return CONTENTSPECNODE_ZERO_TO_N;
               }
  -        }
  -        else if (minOccur.equals("1") || minOccur.length() == 0) {
  +        } else if (minOccur.equals("1") || minOccur.length() == 0) {
               if (maxOccur.equals("*")) {
                   return XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE;
  -            }
  -            else if (!maxOccur.equals("1") && maxOccur.length() > 0) {
  +            } else if (!maxOccur.equals("1") && maxOccur.length() > 0) {
                   return CONTENTSPECNODE_M_TO_N;
               }
  -        }
  -        else {
  +        } else {
               if (maxOccur.equals("*")) {
                   return CONTENTSPECNODE_M_OR_MORE;
  -            }
  -            else {
  +            } else {
                   return CONTENTSPECNODE_M_TO_N;
               }
           }
  @@ -1488,18 +680,14 @@
           return -1;
       }
   
  -	private void reportSchemaError(int major, Object args[]) throws Exception {
  -//	    try {
  -    		fErrorReporter.reportError(fErrorReporter.getLocator(),
  -	    							   SchemaMessageProvider.SCHEMA_DOMAIN,
  -		    						   major,
  -			    					   SchemaMessageProvider.MSG_NONE,
  -				    				   args,
  -					    			   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
  -//		} catch (Exception e) {
  -//		    e.printStackTrace();
  -//		}
  -	}
  +    private void reportSchemaError(int major, Object args[]) throws Exception {
  +        fErrorReporter.reportError(fErrorReporter.getLocator(),
  +                                   SchemaMessageProvider.SCHEMA_DOMAIN,
  +                                   major,
  +                                   SchemaMessageProvider.MSG_NONE,
  +                                   args,
  +                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
  +    }
   
       //
       // Classes
  @@ -1511,15 +699,15 @@
               "http://www.w3.org/TR/2000/WD-xmlschema-1-20000225/structures.dtd",
               "http://www.w3.org/TR/2000/WD-xmlschema-2-20000225/datatypes.dtd",
               "http://www.w3.org/TR/2000/WD-xmlschema-1-20000225/versionInfo.ent",
  -            };
  +        };
           private static final String PATH[] = {
               "structures.dtd",
               "datatypes.dtd",
               "versionInfo.ent",
  -            };
  +        };
   
           public InputSource resolveEntity(String publicId, String systemId)
  -            throws IOException {
  +        throws IOException {
   
               // looking for the schema DTDs?
               for (int i = 0; i < SYSTEM.length; i++) {
  @@ -1539,21 +727,18 @@
       } // 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] "+
  @@ -1561,7 +746,6 @@
                                  ex.getMessage());
               throw ex;
           }
  -
           //
           // Private methods
           //
  @@ -1636,7 +820,7 @@
           }
   
           DatatypeValidator getValidatorFor(String type) {
  -            return (DatatypeValidator) fRegistry.get(type);
  +            return(DatatypeValidator) fRegistry.get(type);
           }
   
           void addValidator(String name, DatatypeValidator v) {
  @@ -1648,7 +832,7 @@
       //
       //
       final class AttValidatorDATATYPE implements XMLValidator.AttributeValidator {
  -        public int normalize(int elementType, int attrName, int attValueHandle, int attType, int enumHandle) throws Exception {
  +        public int normalize(QName elementType1, QName attrName, int attValueHandle, int attType, int enumHandle) throws Exception {
               //
               // Normalize attribute based upon attribute type...
               //
  @@ -1659,10 +843,10 @@
                       v.validate(fStringPool.toString(attValueHandle));
                   else
                       reportSchemaError(SchemaMessageProvider.NoValidatorFor,
  -                                        new Object [] { type });
  +                                      new Object [] { type});
               } catch (InvalidDatatypeValueException idve) {
                   reportSchemaError(SchemaMessageProvider.IncorrectDatatype,
  -                                    new Object [] { idve.getMessage() });
  +                                  new Object [] { idve.getMessage()});
               } catch (Exception e) {
                   e.printStackTrace();
                   System.out.println("Internal error in attribute datatype validation");
  
  
  
  1.3       +1 -1      xml-xerces/java/src/org/apache/xerces/validators/schema/SchemaMessageProvider.java
  
  Index: SchemaMessageProvider.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/validators/schema/SchemaMessageProvider.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- SchemaMessageProvider.java	2000/04/04 20:11:07	1.2
  +++ SchemaMessageProvider.java	2000/05/17 18:33:25	1.3
  @@ -2,7 +2,7 @@
    * The Apache Software License, Version 1.1
    *
    *
  - * Copyright (c) 1999 The Apache Software Foundation.  All rights 
  + * Copyright (c) 2000 The Apache Software Foundation.  All rights 
    * reserved.
    *
    * Redistribution and use in source and binary forms, with or without
  
  
  
  1.3       +72 -37    xml-xerces/java/src/org/apache/xerces/validators/schema/SchemaParser.java
  
  Index: SchemaParser.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/validators/schema/SchemaParser.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- SchemaParser.java	2000/04/05 20:12:57	1.2
  +++ SchemaParser.java	2000/05/17 18:33:26	1.3
  @@ -72,9 +72,9 @@
   import org.apache.xerces.framework.XMLParser;
   import org.apache.xerces.readers.XMLEntityHandler;
   import org.apache.xerces.framework.XMLErrorReporter;
  +import org.apache.xerces.utils.QName;
   import org.apache.xerces.utils.StringPool;
   
  -
   public class SchemaParser
       extends XMLParser
       implements XMLDocumentHandler, XMLDocumentHandler.DTDHandler {
  @@ -165,46 +165,62 @@
   	 *
   	 */
   
  -    public void startElement(int elementType, XMLAttrList attrList, int attrListIndex) throws Exception 
  +    public void startElement(QName element, 
  +                             XMLAttrList attrList, int attrListIndex) throws Exception 
   	{
   		if ( fSchemaDocument == null ) {
  -			if ( elementType == fStringPool.addSymbol(Schema.ELT_SCHEMA) ) {
  +            // REVISIT: Validation
  +			if ( element.localpart == fStringPool.addSymbol(Schema.ELT_SCHEMA) ) {
   				startSchema (attrList, attrListIndex);
   			} else {
   				reportGenericSchemaError ( "Invalid root element" );
   			}
   		} else {
  -			if ( elementType == fStringPool.addSymbol(Schema.ELT_ANNOTATION) ) {
  +            // REVISIT: Validation
  +			if ( element.localpart == fStringPool.addSymbol(Schema.ELT_ANNOTATION) ) {
   				startAnnotation ();
  -			} else if ( elementType == fStringPool.addSymbol(Schema.ELT_DOCUMENTATION) ) {
  +            // REVISIT: Validation
  +			} else if ( element.localpart == fStringPool.addSymbol(Schema.ELT_DOCUMENTATION) ) {
   				startDocumentation ();
  -			} else if ( elementType == fStringPool.addSymbol(Schema.ELT_APPINFO) ) {
  +            // REVISIT: Validation
  +			} else if ( element.localpart == fStringPool.addSymbol(Schema.ELT_APPINFO) ) {
   				startAppInfo ();
   			} else if ( fInSimpleType ) {
  -				startFacet (elementType, attrList, attrListIndex);
  +                // REVISIT: Validation
  +				startFacet (element.localpart, attrList, attrListIndex);
   			} else {
  -				if ( elementType == fStringPool.addSymbol(Schema.ELT_SIMPLETYPE) ) {
  +                // REVISIT: Validation
  +				if ( element.localpart == fStringPool.addSymbol(Schema.ELT_SIMPLETYPE) ) {
   					startSimpleTypeDef (attrList, attrListIndex);
  -				} else if ( elementType == fStringPool.addSymbol(Schema.ELT_COMPLEXTYPE) ) {
  +                // REVISIT: Validation
  +				} else if ( element.localpart == fStringPool.addSymbol(Schema.ELT_COMPLEXTYPE) ) {
   					startComplexTypeDef (attrList, attrListIndex);
  -				} else if ( elementType == fStringPool.addSymbol(Schema.ELT_GROUP) ) {
  +                // REVISIT: Validation
  +				} else if ( element.localpart == fStringPool.addSymbol(Schema.ELT_GROUP) ) {
   					startGroupDef (attrList, attrListIndex);
  -				} else if ( elementType == fStringPool.addSymbol(Schema.ELT_CHOICE) ) {
  +                // REVISIT: Validation
  +				} else if ( element.localpart == fStringPool.addSymbol(Schema.ELT_CHOICE) ) {
   					startChoice (attrList, attrListIndex);
  -				} else if ( elementType == fStringPool.addSymbol(Schema.ELT_SEQUENCE) ) {
  +                // REVISIT: Validation
  +				} else if ( element.localpart == fStringPool.addSymbol(Schema.ELT_SEQUENCE) ) {
   					startSeq (attrList, attrListIndex);
  -				} else if ( elementType == fStringPool.addSymbol(Schema.ELT_ALL) ) {
  +                // REVISIT: Validation
  +				} else if ( element.localpart == fStringPool.addSymbol(Schema.ELT_ALL) ) {
   					startAll (attrList, attrListIndex);
  -				} else if ( elementType == fStringPool.addSymbol(Schema.ELT_ATTRGROUP) ) {
  +                // REVISIT: Validation
  +				} else if ( element.localpart == fStringPool.addSymbol(Schema.ELT_ATTRGROUP) ) {
   					startAttrGroupDef (attrList, attrListIndex);
  -				} else if ( elementType == fStringPool.addSymbol(Schema.ELT_ELEMENT) ) {
  +                // REVISIT: Validation
  +				} else if ( element.localpart == fStringPool.addSymbol(Schema.ELT_ELEMENT) ) {
   					startElementDecl (attrList, attrListIndex);
  -				} else if ( elementType == fStringPool.addSymbol(Schema.ELT_ATTRIBUTE) ) { 
  +                // REVISIT: Validation
  +				} else if ( element.localpart == fStringPool.addSymbol(Schema.ELT_ATTRIBUTE) ) { 
   					startAttributeDecl (attrList, attrListIndex);
  -				} else if ( elementType == fStringPool.addSymbol(Schema.ELT_NOTATION) ) {
  +                // REVISIT: Validation
  +				} else if ( element.localpart == fStringPool.addSymbol(Schema.ELT_NOTATION) ) {
   					startNotationDecl (attrList, attrListIndex);
   				} else {
  -					reportGenericSchemaError ( "Invalid element(" + fStringPool.toString (elementType) + ")" );
  +					reportGenericSchemaError ( "Invalid element(" + fStringPool.toString (element.rawname) + ")" );
   				} 
   			}
   		}
  @@ -228,44 +244,58 @@
   	 *
   	 */ 
   
  -    public void endElement(int elementType) throws Exception 
  +    public void endElement(QName element) throws Exception 
   	{
   	
  -		if ( elementType == fStringPool.addSymbol(Schema.ELT_ANNOTATION) ) {
  +        // REVISIT: Validation.
  +		if ( element.localpart == fStringPool.addSymbol(Schema.ELT_ANNOTATION) ) {
   			endAnnotation ();
  -		} else if ( elementType == fStringPool.addSymbol(Schema.ELT_DOCUMENTATION) ) {
  +        // REVISIT: Validation.
  +		} else if ( element.localpart == fStringPool.addSymbol(Schema.ELT_DOCUMENTATION) ) {
   			endDocumentation ();
  -		} else if ( elementType == fStringPool.addSymbol(Schema.ELT_APPINFO) ) {
  +        // REVISIT: Validation.
  +		} else if ( element.localpart == fStringPool.addSymbol(Schema.ELT_APPINFO) ) {
   			endAppInfo ();
   		} else if ( fInSimpleType ) {
  -			if ( elementType == fStringPool.addSymbol(Schema.ELT_SIMPLETYPE) ) {
  +            // REVISIT: Validation.
  +			if ( element.localpart == fStringPool.addSymbol(Schema.ELT_SIMPLETYPE) ) {
   				endSimpleTypeDef ();
   			} else {
   				endFacet ();
   			}
   		} else {
  -			if ( elementType == fStringPool.addSymbol(Schema.ELT_COMPLEXTYPE) ) {
  +            // REVISIT: Validation.
  +			if ( element.localpart == fStringPool.addSymbol(Schema.ELT_COMPLEXTYPE) ) {
   				endComplexTypeDef ();
  -			} else if ( elementType == fStringPool.addSymbol(Schema.ELT_GROUP) ) {
  +            // REVISIT: Validation.
  +			} else if ( element.localpart == fStringPool.addSymbol(Schema.ELT_GROUP) ) {
   				endGroupDef ();
  -			} else if ( elementType == fStringPool.addSymbol(Schema.ELT_CHOICE) ) {
  +            // REVISIT: Validation.
  +			} else if ( element.localpart == fStringPool.addSymbol(Schema.ELT_CHOICE) ) {
   				endChoice ();
  -			} else if ( elementType == fStringPool.addSymbol(Schema.ELT_SEQUENCE) ) {
  +            // REVISIT: Validation.
  +			} else if ( element.localpart == fStringPool.addSymbol(Schema.ELT_SEQUENCE) ) {
   				endSeq ();
  -			} else if ( elementType == fStringPool.addSymbol(Schema.ELT_ALL) ) {
  +            // REVISIT: Validation.
  +			} else if ( element.localpart == fStringPool.addSymbol(Schema.ELT_ALL) ) {
   				endAll ();
  -			} else if ( elementType == fStringPool.addSymbol(Schema.ELT_ATTRGROUP) ) {
  +            // REVISIT: Validation.
  +			} else if ( element.localpart == fStringPool.addSymbol(Schema.ELT_ATTRGROUP) ) {
   				endAttrGroupDef ();
  -			} else if ( elementType == fStringPool.addSymbol(Schema.ELT_ELEMENT) ) {
  +            // REVISIT: Validation.
  +			} else if ( element.localpart == fStringPool.addSymbol(Schema.ELT_ELEMENT) ) {
   				endElementDecl ();
  -			} else if ( elementType == fStringPool.addSymbol(Schema.ELT_ATTRIBUTE) ) { 
  +            // REVISIT: Validation.
  +			} else if ( element.localpart == fStringPool.addSymbol(Schema.ELT_ATTRIBUTE) ) { 
   				endAttributeDecl ();
  -			} else if ( elementType == fStringPool.addSymbol(Schema.ELT_NOTATION) ) {
  +            // REVISIT: Validation.
  +			} else if ( element.localpart == fStringPool.addSymbol(Schema.ELT_NOTATION) ) {
   				endNotationDecl ();
  -			} else if ( elementType == fStringPool.addSymbol(Schema.ELT_SCHEMA) ) {
  +            // REVISIT: Validation.
  +			} else if ( element.localpart == fStringPool.addSymbol(Schema.ELT_SCHEMA) ) {
   				endSchema ();
   			} else {	
  -				reportGenericSchemaError ( "Invalid element (" + fStringPool.toString (elementType) + ")" );
  +				reportGenericSchemaError ( "Invalid element (" + fStringPool.toString (element.rawname) + ")" );
   			}
   		}
       }
  @@ -373,13 +403,18 @@
   	//
   	// DTDHandler Methods (NOP)
   	//
  +
  +    //public void startDTD (int rootElementType, int publicId, int systemId) throws Exception {}
   
  -	public void startDTD (int rootElementType, int publicId, int systemId) throws Exception {}
  +    public void startDTD (QName qname,  int publicId, int systemId) throws Exception {}
       public void internalSubset(int internalSubset) throws Exception {}
       public void textDecl(int version, int encoding) throws Exception {}
       public void endDTD() throws Exception {}
  -    public void elementDecl(int elementType, XMLContentSpec contentSpec) throws Exception {}
  -    public void attlistDecl(int elementType,int attrName, int attType, String enumString, int attDefaultType, int attDefaultValue) throws Exception {}
  +    public void elementDecl(QName qname, XMLContentSpec contentSpec) throws Exception {}
  +    public void attlistDecl(QName qname1,QName qname2, int attType, String enumString, int attDefaultType, int attDefaultValue) throws Exception {}
  +
  +    //public void elementDecl(int elementType, XMLContentSpec contentSpec) throws Exception {}
  +    //public void attlistDecl(int elementType,int attrName, int attType, String enumString, int attDefaultType, int attDefaultValue) throws Exception {}
       public void internalPEDecl(int entityName, int entityValue) throws Exception {}
       public void externalPEDecl(int entityName, int publicId, int systemId) throws Exception {}
       public void internalEntityDecl(int entityName, int entityValue) throws Exception {}
  
  
  
  1.4       +22 -26    xml-xerces/java/src/org/apache/xerces/validators/schema/datatypes.dtd
  
  Index: datatypes.dtd
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/validators/schema/datatypes.dtd,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- datatypes.dtd	2000/04/06 03:55:13	1.3
  +++ datatypes.dtd	2000/05/17 18:33:28	1.4
  @@ -1,17 +1,11 @@
   <!-- DTD for XML Schemas: Part 2: Datatypes -->
  -<!-- $Id: datatypes.dtd,v 1.3 2000/04/06 03:55:13 jeffreyr Exp $ -->
  +<!-- $Id: datatypes.dtd,v 1.4 2000/05/17 18:33:28 jeffreyr Exp $ -->
   <!-- Note this DTD is NOT the normative datatypes DTD - - the
        prose copy in the datatypes REC is the normative version (which
        shouldn't differ from this one except for this comment and entity
        expansions, but just in case -->
   <!ENTITY % p ''> <!-- can be overriden in the internal subset of a
                         schema document to establish a namespace prefix -->
  -<!ENTITY % dts ':dt'>
  -<!ENTITY % dtp 'dt:'>
  -<!ENTITY % dtpv '"%dtp;"'>
  -<!ENTITY % dtnds 'xmlns%dts;'>
  -<!ENTITY dtp %dtpv;>
  -
   <!-- Define all the element names, with optional prefix -->
   <!ENTITY % simpleType "%p;simpleType">
   <!ENTITY % maxExclusive "%p;maxExclusive">
  @@ -21,12 +15,13 @@
   <!ENTITY % precision "%p;precision">
   <!ENTITY % scale "%p;scale">
   <!ENTITY % length "%p;length">
  -<!ENTITY % minlength "%p;minlength">
  -<!ENTITY % maxlength "%p;maxlength">
  +<!ENTITY % minLength "%p;minLength">
  +<!ENTITY % maxLength "%p;maxLength">
   <!ENTITY % enumeration "%p;enumeration">
   <!ENTITY % pattern "%p;pattern">
   <!ENTITY % encoding "%p;encoding">
   <!ENTITY % period "%p;period">
  +<!ENTITY % duration "%p;duration">
   
   <!-- Customisation entities for the ATTLIST of each element type.
        Define one of these if your schema takes advantage of the
  @@ -40,12 +35,13 @@
   <!ENTITY % precisionAttrs ''>
   <!ENTITY % scaleAttrs ''>
   <!ENTITY % lengthAttrs ''>
  -<!ENTITY % minlengthAttrs ''>
  -<!ENTITY % maxlengthAttrs ''>
  +<!ENTITY % minLengthAttrs ''>
  +<!ENTITY % maxLengthAttrs ''>
   <!ENTITY % enumerationAttrs ''>
   <!ENTITY % patternAttrs ''>
   <!ENTITY % encodingAttrs ''>
   <!ENTITY % periodAttrs ''>
  +<!ENTITY % durationAttrs ''>
   <!ENTITY % appinfoAttrs ''>
   <!ENTITY % documentationAttrs ''>
   
  @@ -60,17 +56,15 @@
   <!ENTITY % URIref "CDATA">
   <!ENTITY % QName "CDATA">
   <!ENTITY % NCName "NMTOKEN">
  -<!ENTITY % non-negative-integer "NMTOKEN">
  +<!ENTITY % nonNegativeInteger "NMTOKEN">
   <!ENTITY % boolean "(true|false)">
  -<!ENTITY % simpleDerivationChoice "(list|restriction|reproduction)">
  -<!ENTITY % simpleDerivationSet "CDATA">
  -      <!-- #all or space-separated list drawn from derivationChoice -->
  +<!ENTITY % simpleDerivationChoice "(list|restriction)">
   
   <!-- Note that the use of 'facet' below is less restrictive than is
        really intended:  There should in fact be no more than one of each of
        minInclusive, minExclusive, maxInclusive, maxExclusive,
        precision, scale,
  -     length, maxlength, minlength, encoding, period within datatype,
  +     length, maxLength, minLength, encoding, period within datatype,
        and the min- and max- variants of Inclusive and Exclusive are
        mutually exclusive.
        On the other hand,  pattern and enumeration may repeat -->
  @@ -80,8 +74,8 @@
   <!ENTITY % numeric '%precision; | %scale;'>
   <!ENTITY % ordered '%bounds; | %numeric;'>
   <!ENTITY % unordered
  -   '%pattern; | %enumeration; | %length; | %maxlength; | %minlength;
  -    | %encoding; | %period;'>
  +   '%pattern; | %enumeration; | %length; | %maxLength; | %minLength;
  +    | %encoding; | %period; | %duration;'>
   <!ENTITY % facet '%ordered; | %unordered;'>
   <!ENTITY % facetAttr 'value CDATA #REQUIRED'>
   <!ENTITY % facetModel '(%annotation;)?'>
  @@ -89,8 +83,6 @@
   <!ATTLIST %simpleType;
       name      %NCName;                 #IMPLIED
       base      %QName;                  #REQUIRED
  -    abstract  %boolean;                'false'
  -    final     %simpleDerivationSet;    ''
       derivedBy %simpleDerivationChoice; 'restriction'
       %simpleTypeAttrs;>
   <!-- name is required at top level -->
  @@ -119,12 +111,12 @@
   <!ELEMENT %length; %facetModel;>
   <!ATTLIST %length; %facetAttr;
             %lengthAttrs;>
  -<!ELEMENT %minlength; %facetModel;>
  -<!ATTLIST %minlength; %facetAttr;
  -          %minlengthAttrs;>
  -<!ELEMENT %maxlength; %facetModel;>
  -<!ATTLIST %maxlength; %facetAttr;
  -          %maxlengthAttrs;>
  +<!ELEMENT %minLength; %facetModel;>
  +<!ATTLIST %minLength; %facetAttr;
  +          %minLengthAttrs;>
  +<!ELEMENT %maxLength; %facetModel;>
  +<!ATTLIST %maxLength; %facetAttr;
  +          %maxLengthAttrs;>
   
   <!-- This one can be repeated -->
   <!ELEMENT %enumeration; %facetModel;>
  @@ -142,6 +134,9 @@
   <!ELEMENT %period; %facetModel;>
   <!ATTLIST %period; %facetAttr;
             %periodAttrs;>
  +<!ELEMENT %duration; %facetModel;>
  +<!ATTLIST %duration; %facetAttr;
  +          %durationAttrs;>
   
   <!-- Annotation is either application information or documentation -->
   <!-- By having these here they are available for datatypes as well
  @@ -160,3 +155,4 @@
             source     %URIref;   #IMPLIED
             xml:lang   CDATA      #IMPLIED
             %documentationAttrs;>
  +
  
  
  
  1.4       +48 -40    xml-xerces/java/src/org/apache/xerces/validators/schema/structures.dtd
  
  Index: structures.dtd
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/validators/schema/structures.dtd,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- structures.dtd	2000/04/06 03:55:13	1.3
  +++ structures.dtd	2000/05/17 18:33:28	1.4
  @@ -1,5 +1,5 @@
   <!-- DTD for XML Schemas: Part 1: Structures -->
  -<!-- $Id: structures.dtd,v 1.3 2000/04/06 03:55:13 jeffreyr Exp $ -->
  +<!-- $Id: structures.dtd,v 1.4 2000/05/17 18:33:28 jeffreyr Exp $ -->
   <!-- Note this DTD is NOT the normative structures DTD - - the
        prose copy in the structures REC is the normative version (which
        shouldn't differ from this one except for this comment and entity
  @@ -11,7 +11,7 @@
        are defined in XML Schema: Part 2: Datatypes -->
   <!-- Note %p is defined in datatypes.dtd -->
   <!ENTITY % xs-datatypes PUBLIC 'datatypes'
  -                     '../WD-xmlschema-2-20000225/datatypes.dtd' >
  +                     "http://www.w3.org/TR/2000/WD-xmlschema-1-20000407/datatypes.dtd" >
   %xs-datatypes;
   
   <!ENTITY % s ''> <!-- if %p is defined (e.g. as foo:) then you must
  @@ -34,7 +34,6 @@
   <!ENTITY % sequence "%p;sequence">
   <!ENTITY % any "%p;any">
   <!ENTITY % anyAttribute "%p;anyAttribute">
  -<!ENTITY % sic "%p;sic">
   <!ENTITY % attribute "%p;attribute">
   <!ENTITY % attributeGroup "%p;attributeGroup">
   <!ENTITY % include "%p;include">
  @@ -63,37 +62,39 @@
   <!ENTITY % importAttrs ''>
   <!ENTITY % notationAttrs ''>
   
  -<!ENTITY % complexDerivationChoice "(extension|restriction|reproduction)">
  +<!ENTITY % complexDerivationChoice "(extension|restriction)">
   <!ENTITY % complexDerivationSet "CDATA">
         <!-- #all or space-separated list drawn from derivationChoice -->
   <!ENTITY % blockSet "CDATA">
         <!-- #all or space-separated list drawn from
  -                      derivationChoice + 'equivClass' and 'list' -->
  +                      derivationChoice + 'equivClass' -->
   
   <!ENTITY % mgs '%all; | %choice; | %sequence;'>
   <!ENTITY % cs '%choice; | %sequence;'>
  +<!ENTITY % formValues '(qualified|unqualified)'>
   
   <!-- the duplication below is to produce an unambiguous content model
        which allows annotation everywhere -->
   <!ELEMENT %schema; ((%include; | %import; | %annotation;)*,
                       (%simpleType; | %complexType;
  -                     | %element;
  +                     | %element; | %attribute;
                        | %attributeGroup; | %group;
                        | %notation; ),
                       (%annotation;
                        | %simpleType; | %complexType;
  -                     | %element;
  +                     | %element; | %attribute;
                        | %attributeGroup; | %group;
                        | %notation; )* )>
   <!ATTLIST %schema;
  -     targetNamespace    %URIref;               #IMPLIED
  -     version            CDATA                  #IMPLIED
  -     %nds;              %URIref;               #FIXED '&XMLSchemaNS;'
  -     %dtnds;            %URIref;               #FIXED '&XMLSchemaNS;/datatypes'
  -     finalDefault       %complexDerivationSet; ''
  -     blockDefault       %blockSet;             ''
  -     id                 ID                     #IMPLIED
  -     %schemaAttrs;>
  +   targetNamespace      %URIref;               #IMPLIED
  +   version              CDATA                  #IMPLIED
  +   %nds;                %URIref;               #FIXED '&XMLSchemaNS;'
  +   finalDefault         %complexDerivationSet; ''
  +   blockDefault         %blockSet;             ''
  +   id                   ID                     #IMPLIED
  +   elementFormDefault   %formValues;           'unqualified'
  +   attributeFormDefault %formValues;           'unqualified'
  +   %schemaAttrs;>
   <!-- Note the xmlns declaration is NOT in the Schema for Schemas,
        because at the Infoset level where schemas operate,
        xmlns(:prefix) is NOT an attribute! -->
  @@ -126,7 +127,7 @@
   
   <!-- facets only if derivedBy='restriction' -->
   <!-- (element|group|any) only if content=mixed or =elementOnly
  -     and NO derivedBy at all, i.e. a root type -->
  +     and no base at all, i.e. a root type, or base is a complex type -->
   <!-- content defaults to base's if there is a complex base,
        textonly if there's a simple base,
        'mixed' if no base (because that's the urType's content)
  @@ -140,7 +141,7 @@
        This is
          <sequence minOccurs='1' maxOccurs='1'>
        unless content='mixed', in which case it's
  -       <choice minOccurs='0' maxOccurs='*'> -->
  +       <choice minOccurs='0' maxOccurs='unbounded'> -->
   
   <!-- If anyAttribute appears in one or more referenced attributeGroups
        and/or explicitly, the intersection of the permissions is used -->
  @@ -156,14 +157,14 @@
   
   <!ELEMENT %element; ((%annotation;)?, (%complexType;| %simpleType;)?,
                        (%unique; | %key; | %keyref;)*)>
  -<!-- type or datatype only if no type|ref attribute -->
  +<!-- simpleType or complexType only if no type|ref attribute -->
   <!-- ref not allowed at top level -->
   <!ATTLIST %element;
               name        %NCName;               #IMPLIED
               id          ID                     #IMPLIED
               ref         %QName;                #IMPLIED
               type        %QName;                #IMPLIED
  -            minOccurs   %non-negative-integer; '1'
  +            minOccurs   %nonNegativeInteger;   '1'
               maxOccurs   CDATA                  #IMPLIED
               nullable    %boolean;              'false'
               equivClass  %QName;                #IMPLIED
  @@ -172,6 +173,7 @@
               block       %blockSet;             ''
               default     CDATA                  #IMPLIED
               fixed       CDATA                  #IMPLIED
  +            form        %formValues;           #IMPLIED
               %elementAttrs;>
   <!-- type and ref are mutually exclusive.
        name and ref are mutually exculsive, one is required -->
  @@ -184,28 +186,28 @@
   <!ATTLIST %group; 
             name        %NCName;               #IMPLIED
             ref         %QName;                #IMPLIED
  -          minOccurs   %non-negative-integer; '1'
  +          minOccurs   %nonNegativeInteger;   '1'
             maxOccurs   CDATA                  #IMPLIED
             id          ID                     #IMPLIED
             %groupAttrs;>
   
   <!ELEMENT %all; ((%annotation;)?, (%element;| %group;| %cs; | %any;)*)>
   <!ATTLIST %all;
  -          minOccurs   %non-negative-integer; '1'
  +          minOccurs   %nonNegativeInteger;   '1'
             maxOccurs   CDATA                  #IMPLIED
             id          ID                     #IMPLIED
             %allAttrs;>
   
   <!ELEMENT %choice; ((%annotation;)?, (%element;| %group;| %cs; | %any;)*)>
   <!ATTLIST %choice;
  -          minOccurs   %non-negative-integer; '1'
  +          minOccurs   %nonNegativeInteger;   '1'
             maxOccurs   CDATA                  #IMPLIED
             id          ID                     #IMPLIED
             %choiceAttrs;>
   
   <!ELEMENT %sequence; ((%annotation;)?, (%element;| %group;| %cs; | %any;)*)>
   <!ATTLIST %sequence;
  -          minOccurs   %non-negative-integer; '1'
  +          minOccurs   %nonNegativeInteger;   '1'
             maxOccurs   CDATA                  #IMPLIED
             id          ID                     #IMPLIED
             %sequenceAttrs;>
  @@ -219,11 +221,11 @@
   <!-- If order is 'all', minOccurs==maxOccurs==1 on element/any inside -->
   <!-- Should allow minOccurs=0 inside order='all' . . . -->
   
  -<!ELEMENT %any; EMPTY>
  +<!ELEMENT %any; (%annotation;)?>
   <!ATTLIST %any;
               namespace       CDATA                  '##any'
               processContents (skip|lax|strict)      'strict'
  -            minOccurs       %non-negative-integer; '1'
  +            minOccurs       %nonNegativeInteger;   '1'
               maxOccurs       CDATA                  #IMPLIED
               %anyAttrs;>
   
  @@ -241,26 +243,30 @@
                     ##targetNamespace may appear in the above list, with the
                      obvious meaning -->
   
  -<!ELEMENT %anyAttribute; EMPTY>
  +<!ELEMENT %anyAttribute; (%annotation;)?>
   <!ATTLIST %anyAttribute;
               namespace    CDATA   '##any'
               %anyAttributeAttrs;>
   <!-- namespace is interpreted as for 'any' above -->
   
  -
  -<!-- for use inside basetype to copy down corresponding content
  -     model particle from the basetype's content model -->
  -<!ELEMENT %sic; EMPTY>
  -
  +<!-- simpleType only if no type|ref attribute -->
  +<!-- ref not allowed at top level, name iff at top level -->
   <!ELEMENT %attribute; ((%annotation;)?, (%simpleType;)?)>
   <!ATTLIST %attribute;
  -          name      %NCName;      #REQUIRED
  +          name      %NCName;      #IMPLIED
  +          id        ID            #IMPLIED
  +          ref       %QName;       #IMPLIED
             type      %QName;       #IMPLIED
  -          use	    CDATA         #IMPLIED
  -          value		CDATA         #IMPLIED
  +          use       (prohibited|optional|required|fixed|default) #IMPLIED
  +          value     CDATA         #IMPLIED
  +          form      %formValues;  #IMPLIED
             %attributeAttrs;>
  -<!-- default and fixed are mutually exclusive -->
  -<!-- type attr and datatype content are mutually exclusive -->
  +<!-- type and ref are mutually exclusive.
  +     name and ref are mutually exculsive, one is required -->
  +<!-- value only if use is fixed, required or default, or name -->
  +<!-- name and use are mutually exclusive -->
  +<!-- default for use is optional when nested, none otherwise -->
  +<!-- type attr and simpleType content are mutually exclusive -->
   
   <!-- an attributeGroup is a named collection of attribute decls, or a
        reference thereto -->
  @@ -297,16 +303,16 @@
   <!ELEMENT %field; (#PCDATA)>
   
   <!-- Schema combination mechanisms -->
  -<!ELEMENT %include; EMPTY>
  +<!ELEMENT %include; (%annotation;)?>
   <!ATTLIST %include; schemaLocation %URIref; #REQUIRED
                       %includeAttrs;>
   
  -<!ELEMENT %import; EMPTY>
  -<!ATTLIST %import; namespace      %URIref; #REQUIRED
  +<!ELEMENT %import; (%annotation;)?>
  +<!ATTLIST %import; namespace      %URIref; #IMPLIED
                      schemaLocation %URIref; #IMPLIED
                      %importAttrs;>
   
  -<!ELEMENT %notation; EMPTY>
  +<!ELEMENT %notation; (%annotation;)?>
   <!ATTLIST %notation;
                    name        %NCName;    #REQUIRED
                    id          ID          #IMPLIED
  @@ -318,3 +324,5 @@
              '&XSP1.URI;.xsd' >
   <!NOTATION XML PUBLIC 'REC-xml-1998-0210'
                  'http://www.w3.org/TR/1998/REC-xml-19980210' >
  +
  +
  
  
  
  1.3       +24 -21    xml-xerces/java/src/org/apache/xerces/validators/schema/versionInfo.ent
  
  Index: versionInfo.ent
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/validators/schema/versionInfo.ent,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- versionInfo.ent	2000/04/06 04:04:12	1.2
  +++ versionInfo.ent	2000/05/17 18:33:29	1.3
  @@ -1,37 +1,40 @@
   <!-- Path and date information for XML Schema recommendation documents -->
  -<!-- $Id: versionInfo.ent,v 1.2 2000/04/06 04:04:12 jeffreyr Exp $ -->
  +<!-- $Id: versionInfo.ent,v 1.3 2000/05/17 18:33:29 jeffreyr Exp $ -->
   <!ENTITY draft.year "2000">
   <!ENTITY draft.YY "2000">
  -<!ENTITY draft.month "February">
  -<!ENTITY draft.MM "02">
  -<!ENTITY draft.day "25">
  -<!ENTITY draft.DD "25">
  -<!ENTITY draft.base "http://www.w3.org/TR/2000/WD-xmlschema">
  -<!ENTITY % WD-XSP1 'structures'>
  +<!ENTITY draft.month "April">
  +<!ENTITY draft.MM "04">
  +<!ENTITY draft.base "http://www.w3.org/XML/Group/xmlschema-current">
  +<!-- "file:///d:/henry/xmlschema"> -->
  +<!ENTITY % WD-XSP1 "structures">
  +<!ENTITY draft.day "2">
  +<!ENTITY draft.DD "02">
   <!ENTITY % WD-XSP1d '"%WD-XSP1;"'>
   <!ENTITY WD-XSP1 %WD-XSP1d;>
  -<!ENTITY XSP0.base "&draft.base;-0-&draft.YY;&draft.MM;&draft.DD;">
  -<!ENTITY XSP1.base "&draft.base;-1-&draft.YY;&draft.MM;&draft.DD;">
  +<!ENTITY XSP0.base "&draft.base;/structures">
  +<!ENTITY XSP1.base "&draft.base;/structures">
   <!ENTITY XSP1.URI "&XSP1.base;/structures">
   <!ENTITY WD-XSP2 "datatypes">
  -<!ENTITY XSP2.base "&draft.base;-2-&draft.YY;&draft.MM;&draft.DD;">
  +<!ENTITY XSP2.base "&draft.base;/datatypes">
   <!ENTITY XSP2.URI "&XSP2.base;/datatypes">
   <!ENTITY XMLSchemaNS "http://www.w3.org/1999/XMLSchema">
   <!ENTITY XMLSchemaInstanceNS "http://www.w3.org/1999/XMLSchema/instance">
  -<!ENTITY % reldatadtd "'../WD-xmlschema-2-20000225/datatypes.dtd'">
  +<!ENTITY % reldatadtd "'../datatypes/datatypes.dtd'">
   
  -<!ENTITY % schemaProper '"structures.xsd"'>
  -<!ENTITY schemaProper SYSTEM "structures.xsd" NDATA xmlschema>
  +<!ENTITY % schemaProper '"http://www.w3.org/TR/2000/WD-xmlschema-1-20000407/structures.dtd"'>
  +<!ENTITY schemaProper SYSTEM %schemaProper; NDATA xmlschema>
   
  -<!ENTITY % datatypeSchemaProper '"datatypes.xsd"'>
  -<!ENTITY datatypeSchemaProper SYSTEM "datatypes.xsd" NDATA xmlschema>
  +<!ENTITY % datatypeSchemaProper '"http://www.w3.org/TR/2000/WD-xmlschema-1-20000407/datatypes.dtd"'>
  +<!ENTITY datatypeSchemaProper SYSTEM %datatypeSchemaProper; NDATA xmlschema>
   <!ENTITY % datatypeSchemaDump '"datatypes.xsd,dmp"'>
  -<!ENTITY datatypeSchemaDump SYSTEM "datatypes.xsd,dmp" NDATA xmlschema>
  +<!ENTITY datatypeSchemaDump SYSTEM %datatypeSchemaDump; NDATA xmlschema>
   <!ENTITY % builtinsSchemaProper '"builtins.xsd"'>
  -<!ENTITY builtinsSchemaProper SYSTEM "builtins.xsd" NDATA xmlschema>
  -<!ENTITY % schemaDump '"structures.xsd,dmp"'>
  -<!ENTITY schemaDump SYSTEM "structures.xsd,dmp" NDATA xmlschema>
  -<!ENTITY % schemaExample '"example.xsd,dmp"'>
  -<!ENTITY schemaExample SYSTEM "example.xsd,dmp" NDATA xmlschema>
  +<!ENTITY builtinsSchemaProper SYSTEM %builtinsSchemaProper; NDATA xmlschema>
  +<!ENTITY % schemaDump '"structures/structures.xsd,dmp"'>
  +<!ENTITY schemaDump SYSTEM %schemaDump; NDATA xmlschema>
  +<!ENTITY % schemaExample '"structures/example.xsd,dmp"'>
  +<!ENTITY schemaExample SYSTEM %schemaExample; NDATA xmlschema>
   <!NOTATION xmlschema PUBLIC 'structures' '&XSP1.URI;.xsd' >
   <!ENTITY expo '<bibref ref="bib-expo"/>'>
  +
  +
  
  
  
  1.2       +414 -0    xml-xerces/java/src/org/apache/xerces/validators/schema/SchemaGrammar.java
  
  
  
  
  1.2       +188 -0    xml-xerces/java/src/org/apache/xerces/validators/schema/SchemaSymbols.java
  
  
  
  
  1.2       +3015 -0   xml-xerces/java/src/org/apache/xerces/validators/schema/TraverseSchema.java