/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights 
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer. 
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:  
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written 
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, Lotus
 * Development Corporation., http://www.lotus.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
package org.apache.xml.dtm.ref.xni2dtm;

import java.util.Hashtable;
import java.util.Vector;
import javax.xml.transform.Source;
import javax.xml.transform.SourceLocator;
import org.apache.xalan.transformer.XalanProperties;
import org.apache.xalan.res.XSLTErrorResources;
import org.apache.xalan.res.XSLMessages;

import org.apache.xml.dtm.*;
import org.apache.xml.dtm.ref.*;
import org.apache.xml.utils.StringVector;
import org.apache.xml.utils.IntVector;
import org.apache.xml.utils.FastStringBuffer;
import org.apache.xml.utils.IntStack;
import org.apache.xml.utils.SuballocatedIntVector;
import org.apache.xml.utils.SystemIDResolver;
import org.apache.xml.utils.WrappedRuntimeException;
import org.apache.xml.utils.XMLCharacterRecognizer;
import org.apache.xml.utils.SparseVector;

//import org.xml.sax.*;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
//import org.xml.sax.ext.*;

import org.apache.xerces.xni.*;
import org.apache.xerces.xni.psvi.*;
import org.apache.xerces.xni.parser.XMLPullParserConfiguration;
import org.apache.xerces.xni.parser.XMLErrorHandler;
import org.apache.xerces.xni.parser.XMLParseException;

import org.apache.xerces.xni.psvi.ElementPSVI;
import org.apache.xerces.xni.psvi.AttributePSVI;
import org.apache.xerces.xni.psvi.ItemPSVI;
import org.apache.xerces.impl.xs.ElementPSVImpl;
import org.apache.xerces.impl.xs.AttributePSVImpl;
import org.apache.xerces.impl.xs.XSTypeDecl;
import org.apache.xerces.impl.validation.ValidationContext;
import org.apache.xerces.impl.validation.ValidationState;
import org.apache.xerces.impl.dv.ValidatedInfo;
import org.apache.xerces.impl.dv.xs.XSSimpleTypeDecl;
import org.apache.xerces.impl.dv.InvalidDatatypeValueException;

/**
 * This class implements a DTM that is constructed via an XNI data stream.
 * 
 * Please note that it this is a PROTOTYPE, since the Xerces post-schema 
 * validation infoset (PSVI) APIs it is using are themselves prototypes and
 * subject to change without warning. The most recent such change was from
 * "lightweight" to "heavyweight" schema models.
 * 
 * This version is derived from SAX2DTM for ease of implementation and
 * support, but deliberately blocks external access to
 * the SAX-listener calls to make our testing a bit more rigorous.
 * 
 * Note to developers: Both XNI and Xalan have classes called XMLString.
 * Don't confuse them!
 * 
 * %REVIEW% Should we re-unify this with SAX2DTM? 
 * Should we merge that with SAX2RTFDTM? "And what about Naomi?"
 */
public class XNI2DTM 
  extends org.apache.xml.dtm.ref.sax2dtm.SAX2DTM
  implements XMLDocumentHandler, XMLErrorHandler, XMLDTDHandler
{
  /** DEBUGGING FLAG: Set true to monitor XNI events and similar diagnostic info. */
  private static final boolean DEBUG = true;
  
  /** %OPT% %REVIEW% PROTOTYPE: Schema Type information, datatype as instantiated.
   * See discussion in addNode */
  protected SparseVector m_schemaTypeOverride=new SparseVector();
  

  /**
   * If we're building the model incrementally on demand, we need to
   * be able to tell the source when to send us more data.
   *
   * Note that if this has not been set, and you attempt to read ahead
   * of the current build point, we'll probably throw a null-pointer
   * exception. We could try to wait-and-retry instead, as a very poor
   * fallback, but that has all the known problems with multithreading
   * on multiprocessors and we Don't Want to Go There.
   *
   * @see setIncrementalXNISource
   */
  private XMLPullParserConfiguration m_incrementalXNISource = null;

  /** The XNI Document locator 
   * %REVIEW% Should we be storing a SAX locator instead? */
  transient private LocatorWrapper m_locator_wrapper = new LocatorWrapper();
  
  /** Manefest constant: Schema namespace string */
  private static final String SCHEMANS="http://www.w3.org/2001/XMLSchema";
  
  /** Manefest constant: Message for SAX-disablement stubs */
  static final String UNEXPECTED="XNI2DTM UNEXPECTED SAX ";

  /**
   * Construct a XNI2DTM object ready to be constructed from XNI
   * ContentHandler events.
   *
   * @param mgr The DTMManager who owns this DTM.
   * @param source the JAXP 1.1 Source object for this DTM.
   * @param dtmIdentity The DTM identity ID for this DTM.
   * @param whiteSpaceFilter The white space filter for this DTM, which may
   *                         be null.
   * @param xstringfactory XMLString factory for creating character content.
   * @param doIndexing true if the caller considers it worth it to use 
   *                   indexing schemes.
   */
  public XNI2DTM(DTMManager mgr, Source source, int dtmIdentity,
                 DTMWSFilter whiteSpaceFilter,
                 org.apache.xml.utils.XMLStringFactory xstringfactory,
                 boolean doIndexing)
  {
    super(mgr, source, dtmIdentity, whiteSpaceFilter, 
          xstringfactory, doIndexing);
  }

  
  /** ADDED for XNI, SUPPLEMENTS non-schema-typed addNode:
   * 
   * Construct the node map from the node. EXTENDED to carry PSVI type data
   * delivered via XNI. This is currently using non-published Xerces APIs, which
   * are subject to change as their PSVI support becomes more official.
   *
   * @param type raw type ID, one of DTM.XXX_NODE.
   * @param expandedTypeID The expended type ID.
   * @param parentIndex The current parent index.
   * @param previousSibling The previous sibling index.
   * @param dataOrPrefix index into m_data table, or string handle.
   * @param canHaveFirstChild true if the node can have a first child, false
   *                          if it is atomic.
   * @param expectedType Xerces Schema type object as declared in the schema
   *    %REVIEW% NOTE that the 3/28/03 query datamodel no longer records the 
   *    type-as-declared, so this field can probably be eliminated!
   * @param actualType Schema type object as resolved in actual instance document
   *
   * @return The index identity of the node that was added.
   */
  protected int addNode(int type, int expandedTypeID,
                        int parentIndex, int previousSibling,
                        int dataOrPrefix, boolean canHaveFirstChild,
                        XPath2Type actualType)
  {
    int identity=super.addNode(type,expandedTypeID,
                               parentIndex,previousSibling,
                               dataOrPrefix,canHaveFirstChild);

    // The goal is to not consume storage for types unless they actualy exist,
    // and to minimize per-node overhead.
    //
    // NOTE: Record first-seen as default even if it is null, because
    // otherwise late changes of type will bash previously recorded
    // nodes. This is NOT necessarily maximally efficient, but to really
    // optimize we would have to rewrite data to make the default the most
    // common -- and since Scott insists that overrides will be uncommon,
    // I don't want to go there.
    //
    // NOTE: Element schema-types aren't fully resolved until endElement, and
    // need to be dealt with there.
    if(type!=ELEMENT_NODE)
    {
      // Try to record as default for this nodetype
      if(!m_expandedNameTable.setSchemaType(m_exptype.elementAt(identity),
                                            actualType)
         )
      {
        m_schemaTypeOverride.setElementAt(actualType,identity);
      }
    }

    return identity;
  }

  /** ADDED FOR XPATH2: Query schema type name of a given node.
   * 
   * %REVIEW% Is this actually needed?
   * 
   * @param nodeHandle DTM Node Handle of Node to be queried
   * @return null if no type known, else returns the expanded-QName (namespace URI
   *    rather than prefix) of the type actually
   *    resolved in the instance document. Note that this may be derived from,
   *    rather than identical to, the type declared in the schema.
   */
  public String getSchemaTypeName(int nodeHandle)
  {
    int identity=makeNodeIdentity(nodeHandle);
        
    if(identity!=DTM.NULL)
    {
      XPath2Type actualType=(XPath2Type)m_schemaTypeOverride.elementAt(identity);
      if(actualType==null)
        actualType=(XPath2Type)m_expandedNameTable.getSchemaType(m_exptype.elementAt(identity));

      if(actualType!=null)
      {
        String nsuri=actualType.getTargetNamespace();
        String local=actualType.getTypeName();
        return (nsuri==null)
          ? local
          : nsuri+":"+local;
      }
    }
        
    return null;
  }
        
  /** ADDED FOR XPATH2: Query schema type namespace of a given node.
   * 
   * %REVIEW% Is this actually needed?
   * 
   * @param nodeHandle DTM Node Handle of Node to be queried
   * @return null if no type known, else returns the namespace URI
   *    of the type actually resolved in the instance document. This may
   *    be null if the default/unspecified namespace was used.
   *    Note that this may be derived from,
   *    rather than identical to, the type declared in the schema.
   */
  public String getSchemaTypeNamespace(int nodeHandle)
  {
    int identity=makeNodeIdentity(nodeHandle);
        
    if(identity!=DTM.NULL)
    {
      XPath2Type actualType=(XPath2Type)m_schemaTypeOverride.elementAt(identity);
      if(actualType==null)
        actualType=(XPath2Type)m_expandedNameTable.getSchemaType(m_exptype.elementAt(identity));
      if(actualType!=null)
      {
        return actualType.getTargetNamespace();
      }
    }
        
    return null;
  }

  /** ADDED FOR XPATH2: Query schema type localname of a given node.
   * 
   * %REVIEW% Is this actually needed?
   * 
   * @param nodeHandle DTM Node Handle of Node to be queried
   * @return null if no type known, else returns the localname of the type
   *    resolved in the instance document. Note that this may be derived from,
   *    rather than identical to, the type declared in the schema.
   */
  public String getSchemaTypeLocalName(int nodeHandle)
  {
    int identity=makeNodeIdentity(nodeHandle);
        
    if(identity!=DTM.NULL)
    {
      XPath2Type actualType=(XPath2Type)m_schemaTypeOverride.elementAt(identity);
      if(actualType==null)
        actualType=(XPath2Type)m_expandedNameTable.getSchemaType(m_exptype.elementAt(identity));
      if(actualType!=null)
      {
        return actualType.getTypeName();
      }
    }
        
    return null;
  }

  /** ADDED FOR XPATH2: Query whether node's type is derived from a specific type
   * 
   * @param nodeHandle DTM Node Handle of Node to be queried
   * @param namespace String containing URI of namespace for the type we're intersted in
   * @param localname String containing local name for the type we're intersted in
   * @return true if node has a Schema Type which equals or is derived from 
   *    the specified type. False if the node has no type or that type is not
   *    derived from the specified type.
   */
  public boolean isNodeSchemaType(int nodeHandle, String namespace, String localname)
  {
    int identity=makeNodeIdentity(nodeHandle);
        
    if(identity!=DTM.NULL)
    {
      XPath2Type actualType=(XPath2Type)m_schemaTypeOverride.elementAt(identity);
      if(actualType==null)
        actualType=(XPath2Type)m_expandedNameTable.getSchemaType(m_exptype.elementAt(identity));
      if(actualType!=null)
        return actualType.derivedFrom(namespace,localname);
    }
        
    return false;
  }
  
  /** ADDED FOR XPATH2: Retrieve the typed value(s), based on the schema type
   * */
  public XSequence getTypedValue(int nodeHandle)
  {
    // Determine whether instance of built-in type, or list thereof
    // If so, map to corresponding Java type
    // Retrieve string content (as always, for element this spans children
    // If type was xs:string (or untyped?) just return that in a collection.
    // Else parse into collection object, return that
        
    int identity=makeNodeIdentity(nodeHandle);
    if(identity==DTM.NULL)
      return XSequence.EMPTY;
                
    XPath2Type actualType=(XPath2Type)m_schemaTypeOverride.elementAt(identity);
    if(actualType==null)
      actualType=(XPath2Type)m_expandedNameTable.getSchemaType(m_exptype.elementAt(identity));

    if(actualType==null)
      return XSequence.EMPTY;
                
        /* %REVIEW% Efficiency issues; value may be in FSB, in which case
                generating a Java String may arguably be wasteful. */
        //GONK lists;
        //GONK efficiency;
        
    String textvalue=getNodeValue(nodeHandle);
        
    return actualType.typedValue(textvalue);
  }
  
  
  //===========================================================================

  /** OVERRIDDEN FOR XNI:
   * 
   * Ask the CoRoutine parser to terminate and clear the reference. If
   * the parser has already been cleared, this will have no effect.
   *
   * @param callDoTerminate true if parsing should be terminated
   */
  public void clearCoRoutine(boolean callDoTerminate)
  {

    if (null != m_incrementalXNISource)
    {
      if (callDoTerminate)
        m_incrementalXNISource.cleanup();

      m_incrementalXNISource = null;
    }
  }

  /** ADDED FOR XNI, REPLACES setIncrementalSAXSource:
   * 
   * Bind a IncrementalXNISource to this DTM. If we discover we need nodes
   * that have not yet been built, we will ask this object to send us more
   * events, and it will manage interactions with its data sources.
   *
   * Note that we do not actually build the IncrementalXNISource, since we don't
   * know what source it's reading from, what thread that source will run in,
   * or when it will run.
   *
   * @param incrementalXNISource The parser that we want to recieve events from
   * on demand.
   * @param appCoRID The CoRoutine ID for the application.
   */
  public void setIncrementalXNISource(XMLPullParserConfiguration incrementalXNISource)
  {

    // Establish coroutine link so we can request more data
    //
    // Note: It's possible that some versions of IncrementalXNISource may
    // not actually use a CoroutineManager, and hence may not require
    // that we obtain an Application Coroutine ID. (This relies on the
    // coroutine transaction details having been encapsulated in the
    // IncrementalXNISource.do...() methods.)
    m_incrementalXNISource = incrementalXNISource;

    // Establish XNI-stream link so we can receive the requested data
    incrementalXNISource.setDocumentHandler(this);

    // Are the following really needed? incrementalXNISource doesn't yet
    // support them, and they're mostly no-ops here...
    incrementalXNISource.setErrorHandler(this);
    incrementalXNISource.setDTDHandler(this);
  }

  /** DISABLED FOR XNI:
   * 
   * getContentHandler returns "our SAX builder" -- the thing that
   * someone else should send SAX events to in order to extend this
   * DTM model.
   * 
   * %REVIEW% We _could_ leave SAX support in place and have a single model
   * that handles both kinds of event streams. I've chosen to block it
   * during development for better isolation of XNI support.
   *
   * @return null since this model doesn't respond to SAX events
   */
  public org.xml.sax.ContentHandler getContentHandler()
  {
    return null;
  }

  /**
   * Return this DTM's lexical handler.
   *
   * %REVIEW% Should this return null if constrution already done/begun?
   * 
   * %REVIEW% We _could_ leave SAX support in place and have a single model
   * that handles both kinds of event streams. I've chosen to block it
   * during development for better isolation of XNI support.
   *
   * @return null since this model doesn't respond to SAX events
   */
  public org.xml.sax.ext.LexicalHandler getLexicalHandler()
  {
    return null;
  }

  /**
   * Return this DTM's DTDHandler.
   * 
   * %REVIEW% We _could_ leave SAX support in place and have a single model
   * that handles both kinds of event streams. I've chosen to block it
   * during development for better isolation of XNI support.
   *
   * @return null since this model doesn't respond to SAX events
   */
  public org.xml.sax.DTDHandler getDTDHandler()
  {
    return null;
  }

  /**
   * Return this DTM's ErrorHandler.
   *
   * @return null if this model doesn't respond to SAX error events.
   */
  public org.xml.sax.ErrorHandler getErrorHandler()
  {
    //return this;
    return null;
  }

  /**
   * Return this DTM's DeclHandler.
   *
   * @return null if this model doesn't respond to SAX Decl events.
   */
  public org.xml.sax.ext.DeclHandler getDeclHandler()
  {
    //return this;
    return null;
  }

  /** OVERRIDDEN FOR XNI:
   * 
   * @return true iff we're building this model incrementally (eg
   * we're partnered with a IncrementalXNISource) and thus require that the
   * transformation and the parse run simultaneously. Guidance to the
   * DTMManager.
   */
  public boolean needsTwoThreads()
  {
    return null != m_incrementalXNISource;
  }

  /** OVERRIDDEN FOR XNI:
   * 
   * This method should try and build one or more nodes in the table.
   * 
   * %REVIEW% Is it worth factoring out the actual request for more events
   * into a subroutine, isolating it better? Consider if/when we re-merge
   * with SAX2DTM.
   *
   * @return The true if a next node is found or false if
   *         there are no more nodes.
   */
  protected boolean nextNode()
  {

    if (null == m_incrementalXNISource)
      return false;

    if (m_endDocumentOccured)
    {
      clearCoRoutine();

      return false;
    }

    try
    {
      boolean gotMore = m_incrementalXNISource.parse(false);
      if (!gotMore)
      {
        // EOF reached without satisfying the request
        clearCoRoutine();  // Drop connection, stop trying
        // %TBD% deregister as its listener?
      }
      return gotMore;
    }
    catch(RuntimeException e)
    {
      throw e;
    }
    catch(Exception e)
    {
      throw new WrappedRuntimeException(e);
    }

    // %REVIEW% dead code
    //clearCoRoutine();
    //return false;
  }
  
  /** %REVIEW% XNI should let us support this better...
   * 
   * Return the public identifier of the external subset,
   * normalized as described in 4.2.2 External Entities [XML]. If there is
   * no external subset or if it has no public identifier, this property
   * has no value.
   *
   * @param the document type declaration handle
   *
   * @return the public identifier String object, or null if there is none.
   */
  public String getDocumentTypeDeclarationPublicIdentifier()
  {
    return super.getDocumentTypeDeclarationPublicIdentifier();
  }



  ////////////////////////////////////////////////////////////////////
  // Implementation of XNI XMLDocumentHandler interface.
  //
  // %REVIEW% Hand off the SAX2DTM SAX event code, or copy/adapt method
  // bodies? Performance may favor latter approach, but former is no worse
  // than what's been happening on the parser's side of the fence and
  // simplifies maintainance.
  ////////////////////////////////////////////////////////////////////

  /**
   * Receive notification of a notation declaration.
   *
   * <p>By default, do nothing.  Application writers may override this
   * method in a subclass if they wish to keep track of the notations
   * declared in a document.</p>
   *
   * @param name The notation name.
   * @param publicId The notation public identifier, or null if not
   *                 available.
   * @param systemId The notation system identifier.
   * @throws XNIException Any XNI exception, possibly
   *            wrapping another exception.
   * @see org.xml.sax.DTDHandler#notationDecl
   *
   * @throws XNIException
   */
  public void notationDecl(String name, String publicId, String systemId)
    throws XNIException
  {
    // no op
  }

  /**
   * Receive notification of an unparsed entity declaration.
   *
   * <p>By default, do nothing.  Application writers may override this
   * method in a subclass to keep track of the unparsed entities
   * declared in a document.</p>
   *
   * @param name The entity name.
   * @param publicId The entity public identifier, or null if not
   *                 available.
   * @param systemId The entity system identifier.
   * @param notationName The name of the associated notation.
   * @throws XNIException Any XNI exception, possibly
   *            wrapping another exception.
   * @see org.xml.sax.DTDHandler#unparsedEntityDecl
   *
   * @throws XNIException
   */
  public void unparsedEntityDecl(
                                 String name, String publicId, String systemId, String notationName)
    throws XNIException
  {
    try
    {
      super.unparsedEntityDecl(name,publicId,systemId,notationName);
    } 
    catch(SAXException e)
    {
      throw new XNIException(e);
    }
  }

  /**
   * Receive a Locator object for document events.
   *
   * <p>By default, do nothing.  Application writers may override this
   * method in a subclass if they wish to store the locator for use
   * with other document events.</p>
   *
   * @param locator A locator for all XNI document events.
   * @see org.xml.sax.ContentHandler#setDocumentLocator
   * @see org.xml.sax.Locator
   */
  public void setDocumentLocator(XMLLocator locator)
  {
    m_locator_wrapper.setLocator(locator);
    super.setDocumentLocator(m_locator_wrapper);
  }

  /**
   * Receive notification of the beginning of the document.
   *
   * @throws XNIException Any XNI exception, possibly
   *            wrapping another exception.
   * @see org.xml.sax.ContentHandler#startDocument
   */
  public void startDocument(XMLLocator locator,String encoding,Augmentations augs)
    throws XNIException
  {
    if (DEBUG)
      System.out.println("startDocument");
 
    try
    {    
      super.startDocument();
    } 
    catch(SAXException e)
    {
      throw new XNIException(e);
    }
  }

  /**
   * Receive notification of the end of the document.
   *
   * @throws XNIException Any XNI exception, possibly
   *            wrapping another exception.
   * @see org.xml.sax.ContentHandler#endDocument
   */
  public void endDocument(Augmentations augs) throws XNIException
  {
    if (DEBUG)
      System.out.println("endDocument");
      
    try
    {
      super.endDocument();
    } 
    catch(SAXException e)
    {
      throw new XNIException(e);
    }
  }

  /**
   * Receive notification of the start of a Namespace mapping.
   *
   * <p>By default, do nothing.  Application writers may override this
   * method in a subclass to take specific actions at the start of
   * each Namespace prefix scope (such as storing the prefix mapping).</p>
   *
   * @param prefix The Namespace prefix being declared.
   * @param uri The Namespace URI mapped to the prefix.
   * @throws XNIException Any XNI exception, possibly
   *            wrapping another exception.
   * @see org.xml.sax.ContentHandler#startPrefixMapping
   */
  public void startPrefixMapping(String prefix,String uri,Augmentations augs)
    throws XNIException
  {
    if (DEBUG)
      System.out.println("startPrefixMapping: prefix: " + prefix + ", uri: "
                         + uri);
    try
    {                        
      if(augs!=null &&
         null!=augs.getItem(DTM2XNI.DTM2XNI_ADDED_STRUCTURE))
      {
        if (DEBUG)
          System.out.println("\t***** Added by DTM2XNI; ignored here");
                  
        return; // Ignore it!
      }
                
                  
      super.startPrefixMapping(prefix,uri);
    } 
    catch(SAXException e)
    {
      throw new XNIException(e);
    }
  }

  /**
   * Receive notification of the end of a Namespace mapping.
   *
   * <p>By default, do nothing.  Application writers may override this
   * method in a subclass to take specific actions at the end of
   * each prefix mapping.</p>
   *
   * @param prefix The Namespace prefix being declared.
   * @throws XNIException Any XNI exception, possibly
   *            wrapping another exception.
   * @see org.xml.sax.ContentHandler#endPrefixMapping
   */
  public void endPrefixMapping(String prefix, Augmentations augs) 
    throws XNIException
  {
    if (DEBUG)
      System.out.println("endPrefixMapping: prefix: " + prefix);

    try
    {
      if(augs!=null &&
         null!=augs.getItem(DTM2XNI.DTM2XNI_ADDED_STRUCTURE))
      {
        if (DEBUG)
          System.out.println("\t***** Added by DTM2XNI; ignored here");
                  
        return; // Ignore it!
      }
                
      super.endPrefixMapping(prefix);
    } 
    catch(SAXException e)
    {
      throw new XNIException(e);
    }
  }

  /**
   * Receive notification of the start of an element.
   *
   * <p>By default, do nothing.  Application writers may override this
   * method in a subclass to take specific actions at the start of
   * each element (such as allocating a new tree node or writing
   * output to a file).</p>
   *
   * @param name The element type name.
   *
   * @param uri The Namespace URI, or the empty string if the
   *        element has no Namespace URI or if Namespace
   *        processing is not being performed.
   * @param localName The local name (without prefix), or the
   *        empty string if Namespace processing is not being
   *        performed.
   * @param qName The qualified name (with prefix), or the
   *        empty string if qualified names are not available.
   * @param attributes The specified or defaulted attributes.
   * @throws XNIException Any XNI exception, possibly
   *            wrapping another exception.
   * @see org.xml.sax.ContentHandler#startElement
   */
  public void startElement(QName element, XMLAttributes attributes,
                           Augmentations augs)
    //String uri, String localName, String qName, Attributes attributes)
    throws XNIException
  {
    // %REVIEW% I've copied this verbatim and altered it for XNI.
    // Is that overkill? Can we hand any of it back to the SAX layer?
    // (I suspect not, darn it....)
    
    if (DEBUG)
    {
      System.out.println("startElement: uri: " + element.uri + 
                         ", localname: " + element.localpart + 
                         ", qname: "+element.rawname+", atts: " + attributes);    
    }
      
    boolean syntheticElement=false;
        
    // Augs might be null if schema support not turned on in parser. 
    // Shouldn't arise in final operation (?); may arise during debugging
    ElementPSVImpl elemPSVI=null;
    XSTypeDecl actualType =null;
    XPath2Type xp2type=null;
    if(augs!=null)
    {
      // Node added by DTM2XNI?
      syntheticElement = null!=augs.getItem(DTM2XNI.DTM2XNI_ADDED_STRUCTURE);
        
      // Extract Experimental Xerces PSVI data          
      elemPSVI=(ElementPSVImpl)augs.getItem(org.apache.xerces.impl.Constants.ELEMENT_PSVI);
      xp2type=new XPath2Type(elemPSVI,false);
      actualType =
        (elemPSVI==null) ? null : elemPSVI.getTypeDefinition();
      org.apache.xerces.impl.xs.XSElementDecl expectedDecl =  // %REVIEW% OBSOLETE?
        (elemPSVI==null) ? null : elemPSVI.getElementDecl();
      XSTypeDecl expectedType = // %REVIEW% OBSOLETE?
        (expectedDecl==null) ? actualType : expectedDecl.fType;

      if (DEBUG)
      {
        String actualExpandedQName=xp2type.getTargetNamespace()+":"+xp2type.getTypeName();

        System.out.println("\ttypeDefinition (actual): "+ actualType +
                           "\n\t\ttype expanded-qname: " + actualExpandedQName +
                           "\n\telementDecl  (expected): " + expectedDecl +
                           "\n\tDerived from expected (after null recovery): " + actualType.derivedFrom(expectedType) +
                           "\n\tDerived from builtin string: " + actualType.derivedFrom(SCHEMANS,"string") +
                           "\n\tSynthesized by DTM2XNI: "+syntheticElement
                           );
      } //DEBUG
    }// augs
    
    if(DEBUG && attributes!=null)  
    {
      int n = attributes.getLength();
      if(n==0)
        System.out.println("\tempty attribute list");
      else for (int i = 0; i < n; i++)
      {
        System.out.println("\t attr: uri: " + attributes.getURI(i) +
                           ", localname: " + attributes.getLocalName(i) +
                           ", qname: " + attributes.getQName(i) +
                           ", type: " + attributes.getType(i) +
                           ", value: " + attributes.getValue(i)                                                                                                          
                           );
        // Experimental Xerces PSVI data
        Augmentations attrAugs=attributes.getAugmentations(i);
        AttributePSVImpl attrPSVI=(AttributePSVImpl)attrAugs.getItem(org.apache.xerces.impl.Constants.ATTRIBUTE_PSVI);
        XPath2Type xp2attrtype=new XPath2Type(attrPSVI,true);
        XSTypeDecl actualAttrType=(attrPSVI==null) ? null : attrPSVI.getTypeDefinition();
        org.apache.xerces.impl.xs.XSAttributeDecl expectedAttrDecl= // %REVIEW% Obsolete?
          (attrPSVI==null) ? null : attrPSVI.getAttributeDecl();                              
        XSTypeDecl expectedType=(expectedAttrDecl==null) ? actualAttrType : expectedAttrDecl.fType;
        String actualExpandedQName=(actualAttrType==null) ? null : actualAttrType.getTargetNamespace()+":"+actualAttrType.getTypeName();
        // Node added by DTM2XNI?
        boolean syntheticAttribute = null!=attrAugs.getItem(DTM2XNI.DTM2XNI_ADDED_STRUCTURE);

        actualExpandedQName=xp2attrtype.getTargetNamespace()+
        	":"+ xp2attrtype.getTypeName();
        
        System.out.println("\t\ttypeDefinition (actual): "+ actualAttrType +
                           "\n\t\t\ttype expanded-qname: " + actualExpandedQName +
                           "\n\t\tattrDecl (expected): " + expectedAttrDecl
                           );
        if(actualAttrType!=null)                                                
          System.out.println("\n\t\tDerived from expected (after null recovery): " + actualAttrType.derivedFrom(expectedType) +
                             "\n\t\tDerived from builtin string: "+ actualAttrType.derivedFrom(SCHEMANS,"string") +
                             "\n\t\tTyped value: " + xp2attrtype.typedValue(attributes.getValue(i))+
                             "\n\t\tSynthesized by DTM2XNI: "+syntheticAttribute
                             );
      } // dump all attrs
    } // DEBUG

    
    if(syntheticElement)
    {
      if (DEBUG)
        System.out.println("\t***** Added by DTM2XNI; ignored here");
      
      return; // Ignore it!
    }
    
    charactersFlush();


    int exName = m_expandedNameTable.getExpandedTypeID(element.uri, element.localpart, DTM.ELEMENT_NODE);
    String prefix = getPrefix(element.rawname, element.uri);
    int prefixIndex = (null != element.prefix)
      ? m_valuesOrPrefixes.stringToIndex(element.rawname) : 0;
    int elemNode = addNode(DTM.ELEMENT_NODE, exName,
                           m_parents.peek(), m_previous, prefixIndex, true,
                           xp2type);

    if(m_indexing)
      indexNode(exName, elemNode);
    
    m_parents.push(elemNode);

    int startDecls = m_contextIndexes.peek();
    int nDecls = m_prefixMappings.size();
    int prev = DTM.NULL;

    if(!m_pastFirstElement)
    {
      // SPECIAL CASE: Implied declaration at root element
      prefix="xml";
      String declURL = "http://www.w3.org/XML/1998/namespace";
      exName = m_expandedNameTable.getExpandedTypeID(null, prefix, DTM.NAMESPACE_NODE);
      int val = m_valuesOrPrefixes.stringToIndex(declURL);
      // %REVIEW% I don't _think_ we need datatype on namespaces...?
      prev = addNode(DTM.NAMESPACE_NODE, exName, elemNode,
                     prev, val, false);
      m_pastFirstElement=true;
    }
                        
    for (int i = startDecls; i < nDecls; i += 2)
    {
      prefix = (String) m_prefixMappings.elementAt(i);

      if (prefix == null)
        continue;

      String declURL = (String) m_prefixMappings.elementAt(i + 1);

      exName = m_expandedNameTable.getExpandedTypeID(null, prefix, DTM.NAMESPACE_NODE);

      int val = m_valuesOrPrefixes.stringToIndex(declURL);

      // %REVIEW% I don't _think_ we need datatype on namespaces...?
      prev = addNode(DTM.NAMESPACE_NODE, exName, elemNode,
                     prev, val, false);
    }

    int n = attributes.getLength();

    for (int i = 0; i < n; i++)
    {
      String attrUri = attributes.getURI(i);
      String attrQName = attributes.getQName(i);
      String valString = attributes.getValue(i);

      prefix = getPrefix(attrQName, attrUri);

      int nodeType;

      if ((null != attrQName)
          && (attrQName.equals("xmlns")
              || attrQName.startsWith("xmlns:")))
      {
        if (declAlreadyDeclared(prefix))
          continue;  // go to the next attribute.

        nodeType = DTM.NAMESPACE_NODE;
      }
      else
      {
        nodeType = DTM.ATTRIBUTE_NODE;

        if (attributes.getType(i).equalsIgnoreCase("ID"))
          setIDAttribute(valString, elemNode);
      }
      
      // Bit of a hack... if somehow valString is null, stringToIndex will 
      // return -1, which will make things very unhappy.
      if(null == valString)
        valString = "";

      int val = m_valuesOrPrefixes.stringToIndex(valString);
      String attrLocalName = attributes.getLocalName(i);

      if (null != prefix)
      {
        
        prefixIndex = m_valuesOrPrefixes.stringToIndex(attrQName);

        int dataIndex = m_data.size();

        m_data.addElement(prefixIndex);
        m_data.addElement(val);

        val = -dataIndex;
      }

      exName = m_expandedNameTable.getExpandedTypeID(attrUri, attrLocalName, nodeType);

      // Experimental Xerces PSVI data
      Augmentations attrAugs=attributes.getAugmentations(i);
      boolean syntheticAttribute= null != attrAugs.getItem(DTM2XNI.DTM2XNI_ADDED_STRUCTURE);
      if(syntheticAttribute)
      {
        if (DEBUG)
          System.out.println("\t***** Attr {"+attrUri+"}"+attrLocalName+" added by DTM2XNI; ignored here");
        return; // Ignore it!
      }
      
      AttributePSVImpl attrPSVI=(AttributePSVImpl)attrAugs.getItem(org.apache.xerces.impl.Constants.ATTRIBUTE_PSVI);
      XPath2Type xp2attrtype=new XPath2Type(attrPSVI,true);
      
      prev = addNode(nodeType, exName, elemNode, prev, val,
                     false, xp2attrtype);
    }

    if (DTM.NULL != prev)
      m_nextsib.setElementAt(DTM.NULL,prev);

    if (null != m_wsfilter)
    {
      short wsv = m_wsfilter.getShouldStripSpace(makeNodeHandle(elemNode), this);
      boolean shouldStrip = (DTMWSFilter.INHERIT == wsv)
        ? getShouldStripWhitespace()
        : (DTMWSFilter.STRIP == wsv);

      pushShouldStripWhitespace(shouldStrip);
    }

    m_previous = DTM.NULL;

    m_contextIndexes.push(m_prefixMappings.size());  // for the children.
  }

  /**
   * Receive notification of the end of an element.
   *
   * <p>By default, do nothing.  Application writers may override this
   * method in a subclass to take specific actions at the end of
   * each element (such as finalising a tree node or writing
   * output to a file).</p>
   *
   * @param name The element type name.
   * @param attributes The specified or defaulted attributes.
   *
   * @param uri The Namespace URI, or the empty string if the
   *        element has no Namespace URI or if Namespace
   *        processing is not being performed.
   * @param localName The local name (without prefix), or the
   *        empty string if Namespace processing is not being
   *        performed.
   * @param qName The qualified XML 1.0 name (with prefix), or the
   *        empty string if qualified names are not available.
   * @throws XNIException Any XNI exception, possibly
   *            wrapping another exception.
   * @see org.xml.sax.ContentHandler#endElement
   */
  public void endElement(QName element,Augmentations augs) throws XNIException
  {
    if (DEBUG)
      System.out.println("endElement: uri: " + element.uri + 
                         ", localname: " + element.localpart + ", qname: "+element.rawname);
                         
    if(null!=augs && null!=augs.getItem(DTM2XNI.DTM2XNI_ADDED_STRUCTURE))
    {
      if (DEBUG)
        System.out.println("\t***** Added by DTM2XNI; ignored here");
      
      return; // Ignore it!
    }

    try
    {
      super.endElement(element.uri,element.localpart,element.rawname);
    } 
    catch(SAXException e)
    {
      throw new XNIException(e);
    }
    
    // The goal is to not consume storage for types unless they actualy exist,
    // and to minimize per-node overhead.
    //
    // NOTE: Record first-seen as default even if it is null, because
    // otherwise late changes of type will bash previously recorded
    // nodes. This is NOT necessarily maximally efficient, but to really
    // optimize we would have to rewrite data to make the default the most
    // common -- and since Scott insists that overrides will be uncommon,
    // I don't want to go there.
    //
    // NOTE: Element schema-types aren't fully resolved until endElement, and
    // need to be dealt with there.
    {
      // After super.endElement, m_previous is the element we're ending.	
      // Try to record as default for this nodetype
      ElementPSVImpl elemPSVI=null;
      XSTypeDecl actualType =null;
      if(augs!=null)
      {
        elemPSVI=(ElementPSVImpl)augs.getItem(org.apache.xerces.impl.Constants.ELEMENT_PSVI);
        actualType =
          (elemPSVI==null) ? null : elemPSVI.getTypeDefinition();
      }

      if(!m_expandedNameTable.setSchemaType(m_exptype.elementAt(m_previous),
                                            actualType)
         )
      {
        m_schemaTypeOverride.setElementAt(actualType,m_previous);
      }
    }
    
  }

  /** An empty element.
   * 
   * @param element - The name of the element.
   * @param attributes - The element attributes.
   * @param augs - Additional information that may include infoset augmentations
   * @throws XNIException - Thrown by handler to signal an error.
   * */
  public void emptyElement(QName element,
                           XMLAttributes attributes,
                           Augmentations augs)
    throws XNIException
  {
    // %OPT% We could skip the pushes and pops and save some cycles...
      startElement(element,attributes,augs);
      endElement(element,augs);
  }

  /**
   * Receive notification of character data inside an element.
   *
   * <p>By default, do nothing.  Application writers may override this
   * method to take specific actions for each chunk of character data
   * (such as adding the data to a node or buffer, or printing it to
   * a file).</p>
   *
   * @param ch The characters.
   * @param start The start position in the character array.
   * @param length The number of characters to use from the
   *               character array.
   * @throws XNIException Any XNI exception, possibly
   *            wrapping another exception.
   * @see org.xml.sax.ContentHandler#characters
   */
  public void characters(org.apache.xerces.xni.XMLString text,Augmentations augs) throws XNIException
  {
    try
    {
      super.characters(text.ch, text.offset, text.length);
    } 
    catch(SAXException e)
    {
      throw new XNIException(e);
    }
  }

  /**
   * Receive notification of ignorable whitespace in element content.
   *
   * <p>By default, do nothing.  Application writers may override this
   * method to take specific actions for each chunk of ignorable
   * whitespace (such as adding data to a node or buffer, or printing
   * it to a file).</p>
   *
   * @param ch The whitespace characters.
   * @param start The start position in the character array.
   * @param length The number of characters to use from the
   *               character array.
   * @throws XNIException Any XNI exception, possibly
   *            wrapping another exception.
   * @see org.xml.sax.ContentHandler#ignorableWhitespace
   */
  public void ignorableWhitespace(org.apache.xerces.xni.XMLString text, Augmentations augs)
    throws XNIException
  {
    // %OPT% We can probably take advantage of the fact that we know this 
    // is whitespace... or has that been dealt with at the source?
    try
    {
      super.characters(text.ch, text.offset, text.length);
    } 
    catch(SAXException e)
    {
      throw new XNIException(e);
    }
  }

  /**
   * Receive notification of a processing instruction.
   *
   * <p>By default, do nothing.  Application writers may override this
   * method in a subclass to take specific actions for each
   * processing instruction, such as setting status variables or
   * invoking other methods.</p>
   *
   * @param target The processing instruction target.
   * @param data The processing instruction data, or null if
   *             none is supplied.
   * @throws XNIException Any XNI exception, possibly
   *            wrapping another exception.
   * @see org.xml.sax.ContentHandler#processingInstruction
   */
  public void processingInstruction(String target,org.apache.xerces.xni.XMLString data,Augmentations augs)
    throws XNIException
  {
    if (DEBUG)
      System.out.println("processingInstruction: target: " + target +", data: "+data);

    try
    {
      // %REVIEW% Can we avoid toString? I don't think so, given our 
      // current data structures, but that bears reconsideration
      super.processingInstruction(target,data.toString());
    } 
    catch(SAXException e)
    {
      throw new XNIException(e);
    }
  }

  /**
   * Report the beginning of an entity in content.
   *
   * <p><strong>NOTE:</entity> entity references in attribute
   * values -- and the start and end of the document entity --
   * are never reported.</p>
   *
   * <p>The start and end of the external DTD subset are reported
   * using the pseudo-name "[dtd]".  All other events must be
   * properly nested within start/end entity events.</p>
   *
   * <p>Note that skipped entities will be reported through the
   * {@link org.xml.sax.ContentHandler#skippedEntity skippedEntity}
   * event, which is part of the ContentHandler interface.</p>
   *
   * @param name The name of the entity.  If it is a parameter
   *        entity, the name will begin with '%'.
   * @throws SAXException The application may raise an exception.
   * @see #endEntity
   * @see org.xml.sax.ext.DeclHandler#internalEntityDecl
   * @see org.xml.sax.ext.DeclHandler#externalEntityDecl
   */
  public void startGeneralEntity(String name,XMLResourceIdentifier identifier,
                                 String encoding,Augmentations augs) 
    throws XNIException
  {

    // no op
  }

  /**
   * Report the end of an entity.
   *
   * @param name The name of the entity that is ending.
   * @throws SAXException The application may raise an exception.
   * @see #startEntity
   */
  public void endGeneralEntity(String name,Augmentations augs) throws XNIException
  {

    // no op
  }
  
  /** Notifies of the presence of an XMLDecl line in the document. 
   * If present, this method will be called immediately following 
   * the startDocument call.
   * @param version - The XML version.
   * @param encoding - The IANA encoding name of the document, or null if not
   *    specified.
   * @param standalone - The standalone value, or null if not specified.
   * @param augs - Additional information that may include infoset augmentations
   * @throws XNIException - Thrown by handler to signal an error.
   * */
  public void xmlDecl(String version,String encoding,String standalone,
                      Augmentations augs)
    throws XNIException
  {

    // no op
  }
             
        
  /** Notifies of the presence of a TextDecl line in an entity. If present, this
   * method will be called immediately following the startEntity call. 
   * 
   * Note: This method will never be called for the document entity; it is only
   * called for external general entities referenced in document content. 
   * 
   * Note: This method is not called for entity references appearing as part of
   * attribute values.
   * @param version - The XML version, or null if not specified.
   * @param encoding - The IANA encoding name of the entity.
   * @param augs - Additional information that may include infoset augmentations
   * @throws XNIException - Thrown by handler to signal an error.
   * */
  public void textDecl(String version,String encoding,Augmentations augs)
    throws XNIException
  {

    // no op
  }
              

  /**
   * Report the start of a CDATA section.
   *
   * <p>The contents of the CDATA section will be reported through
   * the regular {@link org.xml.sax.ContentHandler#characters
   * characters} event.</p>
   *
   * @throws SAXException The application may raise an exception.
   * @see #endCDATA
   */
  public void startCDATA(Augmentations augs) throws XNIException
  {
    try
    {
      super.startCDATA();
    } 
    catch(SAXException e)
    {
      throw new XNIException(e);
    }
        
  }

  /**
   * Report the end of a CDATA section.
   *
   * @throws SAXException The application may raise an exception.
   * @see #startCDATA
   */
  public void endCDATA(Augmentations augs) throws XNIException
  {
    try
    {
      super.endCDATA();
    } 
    catch(SAXException e)
    {
      throw new XNIException(e);
    }
  }

  /**
   * Report an XML comment anywhere in the document.
   *
   * <p>This callback will be used for comments inside or outside the
   * document element, including comments in the external DTD
   * subset (if read).</p>
   *
   * @param ch An array holding the characters in the comment.
   * @param start The starting position in the array.
   * @param length The number of characters to use from the array.
   * @throws SAXException The application may raise an exception.
   */
  public void comment(org.apache.xerces.xni.XMLString text,Augmentations augs) throws XNIException
  {
    try
    {
      super.comment(text.ch,text.offset,text.length);
    } 
    catch(SAXException e)
    {
      throw new XNIException(e);
    }
  }


  /** Helper class: Present XNI Locator info as SAX Locator
   * */
  private class LocatorWrapper 
    implements org.xml.sax.Locator
  {
    XMLLocator locator;
    String publicId=null;
    String systemId=null;
        
    public void setLocator(XMLLocator locator)
    { this.locator=locator; }
        
    public void setPublicId(String publicId)
    { this.publicId=publicId; }
        
    public void setSystemId(String systemId)
    { this.systemId=systemId; }
        
    public int getColumnNumber() 
    {
      return locator.getColumnNumber();
    }
    public int getLineNumber() 
    {
      return locator.getLineNumber();
    }
    public String getPublicId() 
    {
      return publicId;
    }
    public String getSystemId()         
    {
      return systemId;
    }
  }
  
  /** Notifies of the presence of the DOCTYPE line in the document.
         *  @param rootElement - The name of the root element.
         * @param publicId - The public identifier if an external DTD or null if the
         *        external DTD is specified using SYSTEM.
         * @param systemId - The system identifier if an external DTD, null otherwise.
         * @param augs - Additional information that may include infoset augmentations
         * @throws XNIException - Thrown by handler to signal an error.
         * */
  public void doctypeDecl(String rootElement,String publicId,String systemId,
                          Augmentations augs)
    throws XNIException
  {
    // no op
  }
    
  ////////////////////////////////////////////////////////////////////
  // XNI error handler
  
  public void warning(java.lang.String domain,
                      java.lang.String key,
                      XMLParseException exception)
    throws XNIException
  {
    // %REVIEW% Is there anyway to get the JAXP error listener here?
    System.err.println(exception);
  }
  public void error(java.lang.String domain,
                    java.lang.String key,
                    XMLParseException exception)
    throws XNIException
  {
    throw exception;
  }
  public void fatalError(java.lang.String domain,
                         java.lang.String key,
                         XMLParseException exception)
    throws XNIException
  {
    throw exception;
  }
  
  ////////////////////////////////////////////////////////////////////
  // XNI DTD handler. Needed for unparsed entities, but to get that
  // have to accept the other calls... which means we need to know the start
  // and end of the DTD to prevent DTD comments from being taken as
  // part of the main document.
  
  public void startDTD(XMLLocator locator,
                       Augmentations augmentations)
    throws XNIException
  {
    try
    {
      super.startDTD("unknownDocumentTypeName",locator.getPublicId(),locator.getLiteralSystemId());
    } 
    catch(SAXException e)
    {
      throw new XNIException(e);
    }
  }
  
  public void startParameterEntity(java.lang.String name,
                                   XMLResourceIdentifier identifier,
                                   java.lang.String encoding,
                                   Augmentations augmentations)
    throws XNIException
  {
    // no op
  }
  
  // textDecl already handled
  
  public void endParameterEntity(java.lang.String name,
                                 Augmentations augmentations)
    throws XNIException  
  {
    // no op
  }
  public void startExternalSubset(Augmentations augmentations)
    throws XNIException  
  {
    // no op
  }
  public void endExternalSubset(Augmentations augmentations)
    throws XNIException  
  {
    // no op
  }  
  
  // comment already handled, including suppression during the DTD
  // processing instruction already handled. NOT currently suppressed during DTD?
  
  public void elementDecl(java.lang.String name,
                          java.lang.String contentModel,
                          Augmentations augmentations)
    throws XNIException
  {
    //no op
  }
  public void startAttlist(java.lang.String elementName,
                           Augmentations augmentations)
    throws XNIException
  {
    //no op
  }
  
  public void attributeDecl(String elementName,String attributeName, 
                            java.lang.String type, java.lang.String[] enumeration, 
                            String defaultType, XMLString defaultValue,
                            XMLString nonNormalizedDefaultValue, Augmentations augmentations)
    throws XNIException
  { 
    // no op
  }
  
  public void endAttlist(Augmentations augmentations)
    throws XNIException  
  {
    //no op
  }
  public void internalEntityDecl(String name, XMLString text, 
                                 XMLString nonNormalizedText,
                                 Augmentations augmentations) 
    throws XNIException
  {
    //no op
  }
  public void externalEntityDecl(java.lang.String name,
                                 XMLResourceIdentifier identifier,
                                 Augmentations augmentations)
    throws XNIException
  {
    //no op
  }
  
  public void unparsedEntityDecl(java.lang.String name,
                                 XMLResourceIdentifier identifier,
                                 java.lang.String notation,
                                 Augmentations augmentations)
    throws XNIException
  {
    // This one's the wnole point of the exercise...
    try
    {
      super.unparsedEntityDecl(name,identifier.getPublicId(),identifier.getLiteralSystemId(),notation);
    } 
    catch(SAXException e)
    {
      throw new XNIException(e);
    }
  }     
 
  public void notationDecl(java.lang.String name,
                           XMLResourceIdentifier identifier,
                           Augmentations augmentations)
    throws XNIException
  {
    // no op
  }
  public void startConditional(short type,
                               Augmentations augmentations)
    throws XNIException
  {
    // no op
  }
  
  public void ignoredCharacters(XMLString text, Augmentations augmentations)
    throws XNIException
  {
    // no op
  }
  public void endConditional(Augmentations augmentations)
    throws XNIException
  {
    // no op
  }
  
  public void endDTD(Augmentations augmentations)
    throws XNIException
  {
    try
    {
      super.endDTD();
    } 
    catch(SAXException e)
    {
      throw new XNIException(e);
    }
  }     
 
  ////////////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////
  // %REVIEW% SAX APIs are currently _blocked_ for debugging purposes. We can
  // re-enable them if/when we fold the XNI support back into the main SAX2DTM
  ////////////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////
  
 
  // Implementation of DTDHandler interface.

  // SAME AS XNI? OR DID WE RETAIN THEM ABOVE FOR OTHER REASONS?
  //public void notationDecl(String name, String publicId, String systemId)
  //        throws SAXException
  // public void unparsedEntityDecl(
  //        String name, String publicId, String systemId, String notationName)
  //        throws SAXException

  // Implementation of ContentHandler interface.

  public void setDocumentLocator(org.xml.sax.Locator locator)
  {
    throw new RuntimeException(UNEXPECTED+"setDocumentLocator");
  }
  public void startDocument() throws SAXException
  {
    throw new SAXException(UNEXPECTED+"startDocument");
  }
  public void endDocument() throws SAXException
  {
    throw new SAXException(UNEXPECTED+"endDocument");
  }
  public void startPrefixMapping(String prefix, String uri)
    throws SAXException
  {
    throw new SAXException(UNEXPECTED+"startPrefixMapping");
  }
  public void endPrefixMapping(String prefix) throws SAXException
  {
    throw new SAXException(UNEXPECTED+"endPrefixMapping");
  }
  public void startElement(
                           String uri, String localName, String qName, org.xml.sax.Attributes attributes)
    throws SAXException
  {
    throw new SAXException(UNEXPECTED+"startElement");
  }
  public void endElement(String uri, String localName, String qName)
    throws SAXException
  {
    throw new SAXException(UNEXPECTED+"endElement");
  }
  public void characters(char ch[], int start, int length) throws SAXException
  {
    throw new SAXException(UNEXPECTED+"characters");
  }
  public void ignorableWhitespace(char ch[], int start, int length)
    throws SAXException
  {
    throw new SAXException(UNEXPECTED+"ignorableWhitespace");
  }
  public void processingInstruction(String target, String data)
    throws SAXException
  {
    throw new SAXException(UNEXPECTED+"processingInstruction");
  }
  public void skippedEntity(String name) throws SAXException
  {
    throw new SAXException(UNEXPECTED+"skippedEntity");
  }
  
  // Implementation of SAX error handler

  public void warning(SAXParseException e) throws SAXException
  {
    // %REVIEW% Is there anyway to get the JAXP error listener here?
    throw new SAXException(UNEXPECTED+"Warning: "+e.getMessage());
  }
  public void error(SAXParseException e) throws SAXException
  {
    throw new SAXException(UNEXPECTED+"Error: "+e.getMessage());
  }
  public void fatalError(SAXParseException e) throws SAXException
  {
    throw new SAXException(UNEXPECTED+"Fatal Error: "+e.getMessage());
  }

  // Implementation of SAX DeclHandler interface.
  
  public void elementDecl(String name, String model) throws SAXException
  {
    throw new SAXException(UNEXPECTED+"elementDecl "+name);
  }
  public void attributeDecl(
                            String eName, String aName, String type, String valueDefault, String value)
    throws SAXException
  {
    throw new SAXException(UNEXPECTED+"attributeDecl "+aName);
  }
  public void internalEntityDecl(String name, String value)
    throws SAXException
  {
    throw new SAXException(UNEXPECTED+"internalEntityDecl "+name);
  }
  public void externalEntityDecl(
                                 String name, String publicId, String systemId) throws SAXException
  {
    throw new SAXException(UNEXPECTED+"externalEntityDecl "+name);
  }

  // Implementation of the LexicalHandler interface.
  public void startDTD(String name, String publicId, String systemId)
    throws SAXException
  {
    throw new SAXException(UNEXPECTED+"startDTD");
  }
  public void endDTD() throws SAXException
  {
    throw new SAXException(UNEXPECTED+"endDTD");
  }


  //============================================================/  
  
  /** Inner class: The full XNI ItemPSVI is far too heavy-weight for
   * our needs. But their XSTypeDecl isn't quite heavy enough; it gives
   * us the actual member type, but that may be anonymous... so to get
   * what XPath2 considers the proper typename, we need to examine
   * additional fields as well. This class is an attempt to compromise by
   * resolving the typename and storing that alongside the member type.
   * 
   * A more efficient solution undoubtedly exists. But since XNI's PSVI
   * APIs are still in flux, and since I'm just trying to get an initial
   * demo running, this will suffice for now.
   * %REVIEW% periodically!
   * */
  protected class XPath2Type
  {
  	public XSTypeDecl m_xniType;
  	public String m_namespace;
  	public String m_localName;
  	
  	/** Constructor for our internal type representation
  	 *   We will extract the low-level XSTypeDecl for the Member Type,
  	 *   and determine the proper namespace and localname. Other data
  	 *   can (hopefully) be GC'd after we're done. This is still NOT
  	 *   a lightweight beast.
  	 * 
  	 * @param psvi XNI Post-Schema-Validation Infoset annotation.
  	 * @param isAttr True iff we're defining type for an attribute.
  	 * */
  	public XPath2Type(ItemPSVI psvi, boolean isAttr)
  	{
  		// First get the member type. Need to go down a level...
  		// not sure whether there's a shared interface
  		if(psvi==null)
	  		m_xniType=null;
  		else if(!isAttr)
	  		m_xniType=((ElementPSVImpl)psvi).getTypeDefinition();
  		else
	  		m_xniType=((AttributePSVImpl)psvi).getTypeDefinition();
  	
  		// Now resolve the typename.
  		// There are some quibbles about algorithm; see comments on
  		// the resolve methods.
  		lightResolveTypeName(psvi,isAttr);
  	}
  	
  	/** Identity needs to be defined so we can do sparse storage.
  	 * %REVIEW% I'm not sure all three fields need to be checked, but...
  	 * */
  	public boolean equals(XPath2Type other)
  	{
		// Could cache hashCode()'s result and use that to accelerate
		// doesn't-equal testing at the cost of some storage and
		// slowing down does-equal tests. Not convinced it's useful here.
		// %REVIEW%
  		return (m_xniType==other.m_xniType ||
  			m_xniType!=null && m_xniType.equals(other.m_xniType)) &&
  			// These two won't be null
  			m_namespace.equals(other.m_namespace) &&
  			m_localName.equals(other.m_localName);
  	}
  	  	
  	/** Identity needs to be defined so we can do sparse storage.
  	 * %REVIEW% I'm not sure all three fields need to be checked, but...
  	 * */
  	public int hashCode()
  	{
  		// Could cache hashCode(). See discussion in equals().
  		// %REVIEW%
  		return m_namespace.hashCode()+m_localName.hashCode()+
  			(m_xniType==null ? 0 : m_xniType.hashCode());
  	}
  	
  	public String getTargetNamespace() {return m_namespace;}
  	public String getTypeName() {return m_localName;}
  	
  	public boolean derivedFrom(String namespace,String localname)
  	{
  		if(m_xniType!=null)
	  		return m_xniType.derivedFrom(namespace,localname);
	  		
	  	// Fallback in case no PSVI info was passed in: exact match
	  	// (it's got to be the correct m_any*Type).
	  	else return(m_namespace.equals(namespace) && m_localName.equals(localname));
  	}
  	
  /** Broken out into a subroutine so I can use it for debugging purposes.
   * This logic is adapted from the Xerces SimpleTypeUsage.validateString() example.
   * 
   * %REVIEW% May be more efficient to fold it back in.
   * 
   * @param actualType Xerces PSVI type declaration object
   * @param textValue Text content to be interpreted
   * @return DTM_XSequence containing one or more Java values, as appropriate
   *   to the Built-In Type we have inherited from -- or null if no such 
   *   mapping exists (eg, if actualType was complex)
   * */         
  public XSequence typedValue(String textvalue)
  {
    Object value;
    DTM_XSequence seq=null;

    if(m_xniType instanceof XSSimpleTypeDecl)
    {           
      //create an instance of 'ValidatedInfo' to get back information (like actual value,
      //normalizedValue etc..)after content is validated.
      ValidatedInfo validatedInfo = new ValidatedInfo(); // %REVIEW% Can we reuse???

      //get proper validation context , this is very important we need to get appropriate validation context while validating content
      //validation context passed is generally different while validating content and  creating simple type (applyFacets)
      ValidationContext validationState = new ValidationState();
      // This may need to be refined using:
      //validationState.setNamespaceSupport(...);
      //validationState.setSymbolTable(....);
      //validationState.setFacetChecking(true);
      //validationState.setExtraChecking(false);        

      // Validate and parse the string
      try{
        ((XSSimpleTypeDecl)m_xniType).validate(textvalue, validationState, validatedInfo);
      } catch(InvalidDatatypeValueException ex){
        // Should never happen, since we've already validated...?
        System.err.println(ex.getMessage());
        ex.printStackTrace();
      }

      //now 'validatedInfo' object contains information

      // for number types (decimal, double, float, and types derived from them),
      // Object return is BigDecimal, Double, Float respectively.
      // Boolean is handled similarly.
      // Some types (string and derived) just return the string itself.
      value = validatedInfo.actualValue;

      //The normalized value of a string type
      // (Should we check for stings and return this instead?)
      String normalizedValue = validatedInfo.normalizedValue ;

      // If the type is a union type, then the member type which
      // actually validated the string value will be:
      // XSSimpleType memberType = validatedInfo.memberType ;

      // %REVIEW% I presume this handles lists by returning arrays...?
                
      seq=new DTM_XSequence(value,(XSSimpleTypeDecl)m_xniType);
    }
        
    return seq==null ? XSequence.EMPTY : seq;
  }

  /** Implementation of the XPath2 type-name resolution algorithm
   * (data model 3.5). 
   * 
   * Code donated by Sandy Gao, using the proposed
   * Heavy-Weight PSVI interfaces (not yet implemented in Xerces)
   * 
   * @param psvi  the psvi information for the current node
   * @param attr false for element (fallback is xs:anyType)
   *              true for attribute (fallback is xs:anySimpleType)
   * */  
  protected void heavyResolveTypeName(ItemPSVI psvi, boolean attr)
  {
  	/* Not compatable with old light-weight schema APIs

  	// NAME OF THIS CONSTANT IS IN FLUX
  	//int VALID=ItemPSVI.VALIDITY_VALID;
  	int VALID=ItemPSVI.VALID_VALIDITY;
  	
        // check whether the node is valid
        if (psvi == null ||
            psvi.getValidity() != VALID) {
            // if the node is not valid, then return xs:anyType
            m_namespace = "http://www.w3.org/2001/XMLSchema";
            m_localName = attr ? "anySimpleType" : "anyType";
            return;
        }
        
        // try to get the member type definition, and return its name
        XSSimpleTypeDefinition member = psvi.getMemberTypeDefinition();
        if (member != null) {
            m_namespace = member.getNamespace();
            m_localName = member.getName();
            return;
        }
        
        // try to get the type definition, and return its name
        XSTypeDefinition type = psvi.getTypeDefinition();
        if (type != null) {
            m_namespace = type.getNamespace();
            m_localName = type.getName();
            return;
        }
        
        
  	// Member type definitions promised to be available;
  	// can't proceed to check names independently

        // all failed, return xs:anyType
        m_namespace = "http://www.w3.org/2001/XMLSchema";
        m_localName = attr ? "anySimpleType" : "anyType";
        return;
  */ throw new java.lang.UnsupportedOperationException("Xerces Heavyweight PSVI not yet avaialble"); /**/       
  }
  
  /** Modification of the XPath2 type-name resolution algorithm
   * to reflect Sandy Gao's concerns about the official version
   * not tolerating processors that implement the "lightweight" version
   * of PSVI.
   * 
   * Code donated by Sandy Gao, using the proposed
   * Heavy-Weight PSVI interfaces (not yet implemented in Xerces)
   * 
   * @param psvi  the psvi information for the current node
   * @param attr false for element (fallback is xs:anyType)
   *              true for attribute (fallback is xs:anySimpleType)
   * */  
  protected void proposedHeavyResolveTypeName(ItemPSVI psvi, boolean attr)
  {
  	/* Not compatable with old light-weight schema APIs

  	// NAME OF THIS CONSTANT IS IN FLUX
  	//int VALID=ItemPSVI.VALIDITY_VALID;
  	int VALID=ItemPSVI.VALID_VALIDITY;
  	
        // check whether the node is valid
        if (psvi == null ||
            psvi.getValidity() != VALID) {
            // if the node is not valid, then return xs:anyType
            m_namespace = "http://www.w3.org/2001/XMLSchema";
	        m_localName = attr ? "anySimpleType" : "anyType";
            return;
        }
        
        // try to get the member type definition, and return its name
        XSSimpleTypeDefinition member = psvi.getMemberTypeDefinition();
        if (member != null && member.getName() != null) {
            m_namespace = member.getNamespace();
            m_localName = member.getName();
            return;
        }
        
        // try to get the type definition, and return its name
        XSTypeDefinition type = psvi.getTypeDefinition();
        if (type != null && type.getName() != null) {
            m_namespace = type.getNamespace();
            m_localName = type.getName();
            return;
        }
        
  	// Member type definitions promised to be available;
  	// can't proceed to check names independently

        // all failed, return xs:anyType
        m_namespace = "http://www.w3.org/2001/XMLSchema";
        m_localName = attr ? "anySimpleType" : "anyType";
        return;
  */ throw new java.lang.UnsupportedOperationException("Xerces Heavyweight PSVI not yet avaialble"); /**/       
  }
  
  /** Attempt to write a simplified version of the type resolution
   * algorithm (data model 3.5) using only the Light-Weight PSVI
   * interfaces currently supported in Xerces (which I believe will be
   * phased out when heavyweight come into play).
   * 
   * Basd on code donated by Sandy Gao
   * 
   * @param psvi  the psvi information for the current node
   * @param ret   a String array with size 2
   *              index 0 is used to return the namespace name;
   *              index 1 is used to return the local name.
   * @param attr false for element (fallback is xs:anyType)
   *              true for attribute (fallback is xs:anySimpleType)
   * */  
  protected void lightResolveTypeName(ItemPSVI psvi, boolean attr)
  {
  	/* Not compatable with new heavy-weight schema APIs
  	*/
  	
  	int VALID=ItemPSVI.VALID_VALIDITY;
  	
        // check whether the node is valid
        if (psvi == null ||
            psvi.getValidity() != VALID) {
            // if the node is not valid, then return xs:anyType
            m_namespace = "http://www.w3.org/2001/XMLSchema";
            m_localName = attr ? "anySimpleType" : "anyType";
            return;
        }
        
	  	// Member type definitions promised NOT to be available;
 	 	// proceed to check names independently

		// Need the second test, apparently
        if (!psvi.isMemberTypeAnonymous() && null!=psvi.getMemberTypeName() ) {
            m_namespace = psvi.getMemberTypeNamespace();
            m_localName = psvi.getMemberTypeName();
            return;
        }
        
		// Need the second test, apparently
        if (!psvi.isTypeAnonymous() && null!=psvi.getTypeName()) {
            m_namespace = psvi.getTypeNamespace();
            m_localName = psvi.getTypeName();
            return;
        }
        
        // all failed, return xs:anyType
        m_namespace = "http://www.w3.org/2001/XMLSchema";
        m_localName = attr ? "anySimpleType" : "anyType";
        return;
  // throw new java.lang.UnsupportedOperationException("Xerces Lightweight PSVI phased out"); /**/
  }
  } // XPath2Type
} // XNI2DTM
