/*
 * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
 */
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * $Id: SAX2DTM.java,v 1.2.4.1 2005/09/15 08:15:11 suresh_emailid Exp $
 */
package com.sun.org.apache.xml.internal.dtm.ref.sax2dtm;


import com.sun.org.apache.xml.internal.dtm.DTM;
import com.sun.org.apache.xml.internal.dtm.DTMManager;
import com.sun.org.apache.xml.internal.dtm.DTMWSFilter;
import com.sun.org.apache.xml.internal.dtm.ref.DTMDefaultBaseIterators;
import com.sun.org.apache.xml.internal.dtm.ref.DTMManagerDefault;
import com.sun.org.apache.xml.internal.dtm.ref.DTMStringPool;
import com.sun.org.apache.xml.internal.dtm.ref.DTMTreeWalker;
import com.sun.org.apache.xml.internal.dtm.ref.IncrementalSAXSource;
import com.sun.org.apache.xml.internal.dtm.ref.NodeLocator;
import com.sun.org.apache.xml.internal.res.XMLErrorResources;
import com.sun.org.apache.xml.internal.res.XMLMessages;
import com.sun.org.apache.xml.internal.utils.FastStringBuffer;
import com.sun.org.apache.xml.internal.utils.IntStack;
import com.sun.org.apache.xml.internal.utils.IntVector;
import com.sun.org.apache.xml.internal.utils.StringVector;
import com.sun.org.apache.xml.internal.utils.SuballocatedIntVector;
import com.sun.org.apache.xml.internal.utils.SystemIDResolver;
import com.sun.org.apache.xml.internal.utils.WrappedRuntimeException;
import com.sun.org.apache.xml.internal.utils.XMLString;
import com.sun.org.apache.xml.internal.utils.XMLStringFactory;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;
import javax.xml.transform.Source;
import javax.xml.transform.SourceLocator;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.DTDHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.ext.DeclHandler;
import org.xml.sax.ext.LexicalHandler;

/**
 * This class implements a DTM that tends to be optimized more for speed than
 * for compactness, that is constructed via SAX2 ContentHandler events.
 */
public class SAX2DTM extends DTMDefaultBaseIterators
        implements EntityResolver, DTDHandler, ContentHandler, ErrorHandler,
                   DeclHandler, LexicalHandler
{
  /** Set true to monitor SAX events and similar diagnostic info. */
  private static final boolean DEBUG = false;

  /**
   * 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 setIncrementalSAXSource
   */
  private IncrementalSAXSource m_incrementalSAXSource = null;

  /**
   * All the character content, including attribute values, are stored in
   * this buffer.
   *
   * %REVIEW% Should this have an option of being shared across DTMs?
   * Sequentially only; not threadsafe... Currently, I think not.
   *
   * %REVIEW% Initial size was pushed way down to reduce weight of RTFs.
   * pending reduction in number of RTF DTMs. Now that we're sharing a DTM
   * between RTFs, and tail-pruning... consider going back to the larger/faster.
   *
   * Made protected rather than private so SAX2RTFDTM can access it.
   */
  //private FastStringBuffer m_chars = new FastStringBuffer(13, 13);
  protected FastStringBuffer m_chars;

  /** This vector holds offset and length data.
   */
  protected SuballocatedIntVector m_data;

  /** The parent stack, needed only for construction.
   * Made protected rather than private so SAX2RTFDTM can access it.
   */
  transient protected IntStack m_parents;

  /** The current previous node, needed only for construction time.
   * Made protected rather than private so SAX2RTFDTM can access it.
   */
  transient protected int m_previous = 0;

  /** Namespace support, only relevent at construction time.
   * Made protected rather than private so SAX2RTFDTM can access it.
   */
  transient protected java.util.Vector m_prefixMappings =
    new java.util.Vector();

  /** Namespace support, only relevent at construction time.
   * Made protected rather than private so SAX2RTFDTM can access it.
   */
  transient protected IntStack m_contextIndexes;

  /** Type of next characters() event within text block in prgress. */
  transient protected int m_textType = DTM.TEXT_NODE;

  /**
   * Type of coalesced text block. See logic in the characters()
   * method.
   */
  transient protected int m_coalescedTextType = DTM.TEXT_NODE;

  /** The SAX Document locator */
  transient protected Locator m_locator = null;

  /** The SAX Document system-id */
  transient private String m_systemId = null;

  /** We are inside the DTD.  This is used for ignoring comments.  */
  transient protected boolean m_insideDTD = false;

  /** Tree Walker for dispatchToEvents. */
  protected DTMTreeWalker m_walker = new DTMTreeWalker();

  /** pool of string values that come as strings. */
  protected DTMStringPool m_valuesOrPrefixes;

  /** End document has been reached.
   * Made protected rather than private so SAX2RTFDTM can access it.
   */
  protected boolean m_endDocumentOccured = false;

  /** Data or qualified name values, one array element for each node. */
  protected SuballocatedIntVector m_dataOrQName;

  /**
   * This table holds the ID string to node associations, for
   * XML IDs.
   */
  protected Map<String, Integer> m_idAttributes = new HashMap<>();

  /**
   * fixed dom-style names.
   */
  private static final String[] m_fixednames = { null,
                    null,  // nothing, Element
                    null, "#text",  // Attr, Text
                    "#cdata_section", null,  // CDATA, EntityReference
                    null, null,  // Entity, PI
                    "#comment", "#document",  // Comment, Document
                    null, "#document-fragment",  // Doctype, DocumentFragment
                    null };  // Notation

  /**
   * Vector of entities.  Each record is composed of four Strings:
   *  publicId, systemID, notationName, and name.
   */
  private Vector m_entities = null;

  /** m_entities public ID offset. */
  private static final int ENTITY_FIELD_PUBLICID = 0;

  /** m_entities system ID offset. */
  private static final int ENTITY_FIELD_SYSTEMID = 1;

  /** m_entities notation name offset. */
  private static final int ENTITY_FIELD_NOTATIONNAME = 2;

  /** m_entities name offset. */
  private static final int ENTITY_FIELD_NAME = 3;

  /** Number of entries per record for m_entities. */
  private static final int ENTITY_FIELDS_PER = 4;

  /**
   * The starting offset within m_chars for the text or
   * CDATA_SECTION node currently being acumulated,
   * or -1 if there is no text node in progress
   */
  protected int m_textPendingStart = -1;

  /**
   * Describes whether information about document source location
   * should be maintained or not.
   *
   * Made protected for access by SAX2RTFDTM.
   */
  protected boolean m_useSourceLocationProperty = false;

   /** Made protected for access by SAX2RTFDTM.
   */
  protected StringVector m_sourceSystemId;
   /** Made protected for access by SAX2RTFDTM.
   */
  protected IntVector m_sourceLine;
   /** Made protected for access by SAX2RTFDTM.
   */
  protected IntVector m_sourceColumn;

  /**
   * Construct a SAX2DTM object using the default block size.
   *
   * @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 SAX2DTM(DTMManager mgr, Source source, int dtmIdentity,
                 DTMWSFilter whiteSpaceFilter,
                 XMLStringFactory xstringfactory,
                 boolean doIndexing)
  {

    this(mgr, source, dtmIdentity, whiteSpaceFilter,
          xstringfactory, doIndexing, DEFAULT_BLOCKSIZE, true, false);
  }

  /**
   * Construct a SAX2DTM object ready to be constructed from SAX2
   * 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.
   * @param blocksize The block size of the DTM.
   * @param usePrevsib true if we want to build the previous sibling node array.
   * @param newNameTable true if we want to use a new ExpandedNameTable for this DTM.
   */
  public SAX2DTM(DTMManager mgr, Source source, int dtmIdentity,
                 DTMWSFilter whiteSpaceFilter,
                 XMLStringFactory xstringfactory,
                 boolean doIndexing,
                 int blocksize,
                 boolean usePrevsib,
                 boolean newNameTable)
  {

    super(mgr, source, dtmIdentity, whiteSpaceFilter,
          xstringfactory, doIndexing, blocksize, usePrevsib, newNameTable);

    // %OPT% Use smaller sizes for all internal storage units when
    // the blocksize is small. This reduces the cost of creating an RTF.
    if (blocksize <= 64)
    {
      m_data = new SuballocatedIntVector(blocksize, DEFAULT_NUMBLOCKS_SMALL);
      m_dataOrQName = new SuballocatedIntVector(blocksize, DEFAULT_NUMBLOCKS_SMALL);
      m_valuesOrPrefixes = new DTMStringPool(16);
      m_chars = new FastStringBuffer(7, 10);
      m_contextIndexes = new IntStack(4);
      m_parents = new IntStack(4);
    }
    else
    {
      m_data = new SuballocatedIntVector(blocksize, DEFAULT_NUMBLOCKS);
      m_dataOrQName = new SuballocatedIntVector(blocksize, DEFAULT_NUMBLOCKS);
      m_valuesOrPrefixes = new DTMStringPool();
      m_chars = new FastStringBuffer(10, 13);
      m_contextIndexes = new IntStack();
      m_parents = new IntStack();
    }

    // %REVIEW%  Initial size pushed way down to reduce weight of RTFs
    // (I'm not entirely sure 0 would work, so I'm playing it safe for now.)
    //m_data = new SuballocatedIntVector(doIndexing ? (1024*2) : 512, 1024);
    //m_data = new SuballocatedIntVector(blocksize);

    m_data.addElement(0);   // Need placeholder in case index into here must be <0.

    //m_dataOrQName = new SuballocatedIntVector(blocksize);

    // m_useSourceLocationProperty=com.sun.org.apache.xalan.internal.processor.TransformerFactoryImpl.m_source_location;
    m_useSourceLocationProperty = mgr.getSource_location();
    m_sourceSystemId = (m_useSourceLocationProperty) ? new StringVector() : null;
        m_sourceLine = (m_useSourceLocationProperty) ?  new IntVector() : null;
    m_sourceColumn = (m_useSourceLocationProperty) ?  new IntVector() : null;
  }

  /**
   * Set whether information about document source location
   * should be maintained or not.
   */
  public void setUseSourceLocation(boolean useSourceLocation)
  {
    m_useSourceLocationProperty = useSourceLocation;
  }

  /**
   * Get the data or qualified name for the given node identity.
   *
   * @param identity The node identity.
   *
   * @return The data or qualified name, or DTM.NULL.
   */
  protected int _dataOrQName(int identity)
  {

    if (identity < m_size)
      return m_dataOrQName.elementAt(identity);

    // Check to see if the information requested has been processed, and,
    // if not, advance the iterator until we the information has been
    // processed.
    while (true)
    {
      boolean isMore = nextNode();

      if (!isMore)
        return NULL;
      else if (identity < m_size)
        return m_dataOrQName.elementAt(identity);
    }
  }

  /**
   * Ask the CoRoutine parser to doTerminate and clear the reference.
   */
  public void clearCoRoutine()
  {
    clearCoRoutine(true);
  }

  /**
   * Ask the CoRoutine parser to doTerminate and clear the reference. If
   * the CoRoutine parser has already been cleared, this will have no effect.
   *
   * @param callDoTerminate true of doTerminate should be called on the
   * coRoutine parser.
   */
  public void clearCoRoutine(boolean callDoTerminate)
  {

    if (null != m_incrementalSAXSource)
    {
      if (callDoTerminate)
        m_incrementalSAXSource.deliverMoreNodes(false);

      m_incrementalSAXSource = null;
    }
  }

  /**
   * Bind a IncrementalSAXSource 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 IncrementalSAXSource, since we don't
   * know what source it's reading from, what thread that source will run in,
   * or when it will run.
   *
   * @param incrementalSAXSource The parser that we want to recieve events from
   * on demand.
   */
  public void setIncrementalSAXSource(IncrementalSAXSource incrementalSAXSource)
  {

    // Establish coroutine link so we can request more data
    //
    // Note: It's possible that some versions of IncrementalSAXSource 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
    // IncrementalSAXSource.do...() methods.)
    m_incrementalSAXSource = incrementalSAXSource;

    // Establish SAX-stream link so we can receive the requested data
    incrementalSAXSource.setContentHandler(this);
    incrementalSAXSource.setLexicalHandler(this);
    incrementalSAXSource.setDTDHandler(this);

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

  /**
   * getContentHandler returns "our SAX builder" -- the thing that
   * someone else should send SAX events to in order to extend this
   * DTM model.
   *
   * %REVIEW% Should this return null if constrution already done/begun?
   *
   * @return null if this model doesn't respond to SAX events,
   * "this" if the DTM object has a built-in SAX ContentHandler,
   * the IncrementalSAXSource if we're bound to one and should receive
   * the SAX stream via it for incremental build purposes...
   *
   * Note that IncrementalSAXSource_Filter is package private, hence
   * it can be statically referenced using instanceof (CR 6537912).
   */
  public ContentHandler getContentHandler()
  {

    if (m_incrementalSAXSource.getClass()
        .getName().equals("com.sun.org.apache.xml.internal.dtm.ref.IncrementalSAXSource_Filter"))
      return (ContentHandler) m_incrementalSAXSource;
    else
      return this;
  }

  /**
   * Return this DTM's lexical handler.
   *
   * %REVIEW% Should this return null if constrution already done/begun?
   *
   * @return null if this model doesn't respond to lexical SAX events,
   * "this" if the DTM object has a built-in SAX ContentHandler,
   * the IncrementalSAXSource if we're bound to one and should receive
   * the SAX stream via it for incremental build purposes...
   *
   * Note that IncrementalSAXSource_Filter is package private, hence
   * it can be statically referenced using instanceof (CR 6537912).
   */
  public LexicalHandler getLexicalHandler()
  {

    if (m_incrementalSAXSource.getClass()
        .getName().equals("com.sun.org.apache.xml.internal.dtm.ref.IncrementalSAXSource_Filter"))
      return (LexicalHandler) m_incrementalSAXSource;
    else
      return this;
  }

  /**
   * Return this DTM's EntityResolver.
   *
   * @return null if this model doesn't respond to SAX entity ref events.
   */
  public EntityResolver getEntityResolver()
  {
    return this;
  }

  /**
   * Return this DTM's DTDHandler.
   *
   * @return null if this model doesn't respond to SAX dtd events.
   */
  public DTDHandler getDTDHandler()
  {
    return this;
  }

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

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

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

  /**
   * Directly call the
   * characters method on the passed ContentHandler for the
   * string-value of the given node (see http://www.w3.org/TR/xpath#data-model
   * for the definition of a node's string-value). Multiple calls to the
   * ContentHandler's characters methods may well occur for a single call to
   * this method.
   *
   * @param nodeHandle The node ID.
   * @param ch A non-null reference to a ContentHandler.
   * @param normalize true if the content should be normalized according to
   * the rules for the XPath
   * <a href="http://www.w3.org/TR/xpath#function-normalize-space">normalize-space</a>
   * function.
   *
   * @throws SAXException
   */
  public void dispatchCharactersEvents(int nodeHandle, ContentHandler ch,
                                       boolean normalize)
          throws SAXException
  {

    int identity = makeNodeIdentity(nodeHandle);

    if (identity == DTM.NULL)
      return;

    int type = _type(identity);

    if (isTextType(type))
    {
      int dataIndex = m_dataOrQName.elementAt(identity);
      int offset = m_data.elementAt(dataIndex);
      int length = m_data.elementAt(dataIndex + 1);

      if(normalize)
        m_chars.sendNormalizedSAXcharacters(ch, offset, length);
      else
        m_chars.sendSAXcharacters(ch, offset, length);
    }
    else
    {
      int firstChild = _firstch(identity);

      if (DTM.NULL != firstChild)
      {
        int offset = -1;
        int length = 0;
        int startNode = identity;

        identity = firstChild;

        do {
          type = _type(identity);

          if (isTextType(type))
          {
            int dataIndex = _dataOrQName(identity);

            if (-1 == offset)
            {
              offset = m_data.elementAt(dataIndex);
            }

            length += m_data.elementAt(dataIndex + 1);
          }

          identity = getNextNodeIdentity(identity);
        } while (DTM.NULL != identity && (_parent(identity) >= startNode));

        if (length > 0)
        {
          if(normalize)
            m_chars.sendNormalizedSAXcharacters(ch, offset, length);
          else
            m_chars.sendSAXcharacters(ch, offset, length);
        }
      }
      else if(type != DTM.ELEMENT_NODE)
      {
        int dataIndex = _dataOrQName(identity);

        if (dataIndex < 0)
        {
          dataIndex = -dataIndex;
          dataIndex = m_data.elementAt(dataIndex + 1);
        }

        String str = m_valuesOrPrefixes.indexToString(dataIndex);

          if(normalize)
            FastStringBuffer.sendNormalizedSAXcharacters(str.toCharArray(),
                                                         0, str.length(), ch);
          else
            ch.characters(str.toCharArray(), 0, str.length());
      }
    }
  }


  /**
   * Given a node handle, return its DOM-style node name. This will
   * include names such as #text or #document.
   *
   * @param nodeHandle the id of the node.
   * @return String Name of this node, which may be an empty string.
   * %REVIEW% Document when empty string is possible...
   * %REVIEW-COMMENT% It should never be empty, should it?
   */
  public String getNodeName(int nodeHandle)
  {

    int expandedTypeID = getExpandedTypeID(nodeHandle);
    // If just testing nonzero, no need to shift...
    int namespaceID = m_expandedNameTable.getNamespaceID(expandedTypeID);

    if (0 == namespaceID)
    {
      // Don't retrieve name until/unless needed
      // String name = m_expandedNameTable.getLocalName(expandedTypeID);
      int type = getNodeType(nodeHandle);

      if (type == DTM.NAMESPACE_NODE)
      {
        if (null == m_expandedNameTable.getLocalName(expandedTypeID))
          return "xmlns";
        else
          return "xmlns:" + m_expandedNameTable.getLocalName(expandedTypeID);
      }
      else if (0 == m_expandedNameTable.getLocalNameID(expandedTypeID))
      {
        return m_fixednames[type];
      }
      else
        return m_expandedNameTable.getLocalName(expandedTypeID);
    }
    else
    {
      int qnameIndex = m_dataOrQName.elementAt(makeNodeIdentity(nodeHandle));

      if (qnameIndex < 0)
      {
        qnameIndex = -qnameIndex;
        qnameIndex = m_data.elementAt(qnameIndex);
      }

      return m_valuesOrPrefixes.indexToString(qnameIndex);
    }
  }

  /**
   * Given a node handle, return the XPath node name.  This should be
   * the name as described by the XPath data model, NOT the DOM-style
   * name.
   *
   * @param nodeHandle the id of the node.
   * @return String Name of this node, which may be an empty string.
   */
  public String getNodeNameX(int nodeHandle)
  {

    int expandedTypeID = getExpandedTypeID(nodeHandle);
    int namespaceID = m_expandedNameTable.getNamespaceID(expandedTypeID);

    if (0 == namespaceID)
    {
      String name = m_expandedNameTable.getLocalName(expandedTypeID);

      if (name == null)
        return "";
      else
        return name;
    }
    else
    {
      int qnameIndex = m_dataOrQName.elementAt(makeNodeIdentity(nodeHandle));

      if (qnameIndex < 0)
      {
        qnameIndex = -qnameIndex;
        qnameIndex = m_data.elementAt(qnameIndex);
      }

      return m_valuesOrPrefixes.indexToString(qnameIndex);
    }
  }

  /**
   *     5. [specified] A flag indicating whether this attribute was actually
   *        specified in the start-tag of its element, or was defaulted from the
   *        DTD.
   *
   * @param attributeHandle Must be a valid handle to an attribute node.
   * @return <code>true</code> if the attribute was specified;
   *         <code>false</code> if it was defaulted.
   */
  public boolean isAttributeSpecified(int attributeHandle)
  {

    // I'm not sure if I want to do anything with this...
    return true;  // ??
  }

  /**
   *   A document type declaration information item has the following properties:
   *
   *     1. [system identifier] The system identifier of the external subset, if
   *        it exists. Otherwise this property has no value.
   *
   * @return the system identifier String object, or null if there is none.
   */
  public String getDocumentTypeDeclarationSystemIdentifier()
  {

    /** @todo: implement this com.sun.org.apache.xml.internal.dtm.DTMDefaultBase abstract method */
    error(XMLMessages.createXMLMessage(XMLErrorResources.ER_METHOD_NOT_SUPPORTED, null));//"Not yet supported!");

    return null;
  }

  /**
   * Get the next node identity value in the list, and call the iterator
   * if it hasn't been added yet.
   *
   * @param identity The node identity (index).
   * @return identity+1, or DTM.NULL.
   */
  protected int getNextNodeIdentity(int identity)
  {

    identity += 1;

    while (identity >= m_size)
    {
      if (null == m_incrementalSAXSource)
        return DTM.NULL;

      nextNode();
    }

    return identity;
  }

  /**
   * Directly create SAX parser events from a subtree.
   *
   * @param nodeHandle The node ID.
   * @param ch A non-null reference to a ContentHandler.
   *
   * @throws org.xml.sax.SAXException
   */
  public void dispatchToEvents(int nodeHandle, org.xml.sax.ContentHandler ch)
          throws org.xml.sax.SAXException
  {

    DTMTreeWalker treeWalker = m_walker;
    ContentHandler prevCH = treeWalker.getcontentHandler();

    if (null != prevCH)
    {
      treeWalker = new DTMTreeWalker();
    }

    treeWalker.setcontentHandler(ch);
    treeWalker.setDTM(this);

    try
    {
      treeWalker.traverse(nodeHandle);
    }
    finally
    {
      treeWalker.setcontentHandler(null);
    }
  }

  /**
   * Get the number of nodes that have been added.
   *
   * @return The number of that are currently in the tree.
   */
  public int getNumberOfNodes()
  {
    return m_size;
  }

  /**
   * This method should try and build one or more nodes in the table.
   *
   * @return The true if a next node is found or false if
   *         there are no more nodes.
   */
  protected boolean nextNode()
  {

    if (null == m_incrementalSAXSource)
      return false;

    if (m_endDocumentOccured)
    {
      clearCoRoutine();

      return false;
    }

    Object gotMore = m_incrementalSAXSource.deliverMoreNodes(true);

    // gotMore may be a Boolean (TRUE if still parsing, FALSE if
    // EOF) or an exception if IncrementalSAXSource malfunctioned
    // (code error rather than user error).
    //
    // %REVIEW% Currently the ErrorHandlers sketched herein are
    // no-ops, so I'm going to initially leave this also as a
    // no-op.
    if (!(gotMore instanceof Boolean))
    {
      if(gotMore instanceof RuntimeException)
      {
        throw (RuntimeException)gotMore;
      }
      else if(gotMore instanceof Exception)
      {
        throw new WrappedRuntimeException((Exception)gotMore);
      }
      // for now...
      clearCoRoutine();

      return false;

      // %TBD%
    }

    if (gotMore != Boolean.TRUE)
    {

      // EOF reached without satisfying the request
      clearCoRoutine();  // Drop connection, stop trying

      // %TBD% deregister as its listener?
    }

    return true;
  }

  /**
   * Bottleneck determination of text type.
   *
   * @param type oneof DTM.XXX_NODE.
   *
   * @return true if this is a text or cdata section.
   */
  private final boolean isTextType(int type)
  {
    return (DTM.TEXT_NODE == type || DTM.CDATA_SECTION_NODE == type);
  }

//    /**
//     * Ensure that the size of the information arrays can hold another entry
//     * at the given index.
//     *
//     * @param on exit from this function, the information arrays sizes must be
//     * at least index+1.
//     *
//     * NEEDSDOC @param index
//     */
//    protected void ensureSize(int index)
//    {
//          // dataOrQName is an SuballocatedIntVector and hence self-sizing.
//          // But DTMDefaultBase may need fixup.
//        super.ensureSize(index);
//    }

  /**
   * Construct the node map from the node.
   *
   * @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.
   *
   * @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)
  {
    // Common to all nodes:
    int nodeIndex = m_size++;

    // Have we overflowed a DTM Identity's addressing range?
    if(m_dtmIdent.size() == (nodeIndex>>>DTMManager.IDENT_DTM_NODE_BITS))
    {
      addNewDTMID(nodeIndex);
    }

    m_firstch.addElement(canHaveFirstChild ? NOTPROCESSED : DTM.NULL);
    m_nextsib.addElement(NOTPROCESSED);
    m_parent.addElement(parentIndex);
    m_exptype.addElement(expandedTypeID);
    m_dataOrQName.addElement(dataOrPrefix);

    if (m_prevsib != null) {
      m_prevsib.addElement(previousSibling);
    }

    if (DTM.NULL != previousSibling) {
      m_nextsib.setElementAt(nodeIndex,previousSibling);
    }

    if (m_locator != null && m_useSourceLocationProperty) {
      setSourceLocation();
    }

    // Note that nextSibling is not processed until charactersFlush()
    // is called, to handle successive characters() events.

    // Special handling by type: Declare namespaces, attach first child
    switch(type)
    {
    case DTM.NAMESPACE_NODE:
      declareNamespaceInContext(parentIndex,nodeIndex);
      break;
    case DTM.ATTRIBUTE_NODE:
      break;
    default:
      if (DTM.NULL == previousSibling && DTM.NULL != parentIndex) {
        m_firstch.setElementAt(nodeIndex,parentIndex);
      }
      break;
    }

    return nodeIndex;
  }

  /**
   * Get a new DTM ID beginning at the specified node index.
   * @param  nodeIndex The node identity at which the new DTM ID will begin
   * addressing.
   */
  protected void addNewDTMID(int nodeIndex) {
    try
    {
      if(m_mgr==null)
        throw new ClassCastException();

                              // Handle as Extended Addressing
      DTMManagerDefault mgrD=(DTMManagerDefault)m_mgr;
      int id=mgrD.getFirstFreeDTMID();
      mgrD.addDTM(this,id,nodeIndex);
      m_dtmIdent.addElement(id<<DTMManager.IDENT_DTM_NODE_BITS);
    }
    catch(ClassCastException e)
    {
      // %REVIEW% Wrong error message, but I've been told we're trying
      // not to add messages right not for I18N reasons.
      // %REVIEW% Should this be a Fatal Error?
      error(XMLMessages.createXMLMessage(XMLErrorResources.ER_NO_DTMIDS_AVAIL, null));//"No more DTM IDs are available";
    }
  }

  /**
    * Migrate a DTM built with an old DTMManager to a new DTMManager.
    * After the migration, the new DTMManager will treat the DTM as
    * one that is built by itself.
    * This is used to support DTM sharing between multiple transformations.
    * @param manager the DTMManager
    */
  public void migrateTo(DTMManager manager) {
    super.migrateTo(manager);

    // We have to reset the information in m_dtmIdent and
    // register the DTM with the new manager.
    int numDTMs = m_dtmIdent.size();
    int dtmId = m_mgrDefault.getFirstFreeDTMID();
    int nodeIndex = 0;
    for (int i = 0; i < numDTMs; i++)
    {
      m_dtmIdent.setElementAt(dtmId << DTMManager.IDENT_DTM_NODE_BITS, i);
      m_mgrDefault.addDTM(this, dtmId, nodeIndex);
      dtmId++;
      nodeIndex += (1 << DTMManager.IDENT_DTM_NODE_BITS);
    }
  }

  /**
   * Store the source location of the current node.  This method must be called
   * as every node is added to the DTM or for no node.
   */
  protected void setSourceLocation() {
    m_sourceSystemId.addElement(m_locator.getSystemId());
    m_sourceLine.addElement(m_locator.getLineNumber());
    m_sourceColumn.addElement(m_locator.getColumnNumber());

    //%REVIEW% %BUG% Prevent this from arising in the first place
    // by not allowing the enabling conditions to change after we start
    // building the document.
    if (m_sourceSystemId.size() != m_size) {
        String msg = "CODING ERROR in Source Location: " + m_size + " != "
                    + m_sourceSystemId.size();
        System.err.println(msg);
        throw new RuntimeException(msg);
    }
  }

  /**
   * Given a node handle, return its node value. This is mostly
   * as defined by the DOM, but may ignore some conveniences.
   * <p>
   *
   * @param nodeHandle The node id.
   * @return String Value of this node, or null if not
   * meaningful for this node type.
   */
  public String getNodeValue(int nodeHandle)
  {

    int identity = makeNodeIdentity(nodeHandle);
    int type = _type(identity);

    if (isTextType(type))
    {
      int dataIndex = _dataOrQName(identity);
      int offset = m_data.elementAt(dataIndex);
      int length = m_data.elementAt(dataIndex + 1);

      // %OPT% We should cache this, I guess.
      return m_chars.getString(offset, length);
    }
    else if (DTM.ELEMENT_NODE == type || DTM.DOCUMENT_FRAGMENT_NODE == type
             || DTM.DOCUMENT_NODE == type)
    {
      return null;
    }
    else
    {
      int dataIndex = _dataOrQName(identity);

      if (dataIndex < 0)
      {
        dataIndex = -dataIndex;
        dataIndex = m_data.elementAt(dataIndex + 1);
      }

      return m_valuesOrPrefixes.indexToString(dataIndex);
    }
  }

  /**
   * Given a node handle, return its XPath-style localname.
   * (As defined in Namespaces, this is the portion of the name after any
   * colon character).
   *
   * @param nodeHandle the id of the node.
   * @return String Local name of this node.
   */
  public String getLocalName(int nodeHandle)
  {
    return m_expandedNameTable.getLocalName(_exptype(makeNodeIdentity(nodeHandle)));
  }

  /**
   * The getUnparsedEntityURI function returns the URI of the unparsed
   * entity with the specified name in the same document as the context
   * node (see [3.3 Unparsed Entities]). It returns the empty string if
   * there is no such entity.
   * <p>
   * XML processors may choose to use the System Identifier (if one
   * is provided) to resolve the entity, rather than the URI in the
   * Public Identifier. The details are dependent on the processor, and
   * we would have to support some form of plug-in resolver to handle
   * this properly. Currently, we simply return the System Identifier if
   * present, and hope that it a usable URI or that our caller can
   * map it to one.
   * TODO: Resolve Public Identifiers... or consider changing function name.
   * <p>
   * If we find a relative URI
   * reference, XML expects it to be resolved in terms of the base URI
   * of the document. The DOM doesn't do that for us, and it isn't
   * entirely clear whether that should be done here; currently that's
   * pushed up to a higher level of our application. (Note that DOM Level
   * 1 didn't store the document's base URI.)
   * TODO: Consider resolving Relative URIs.
   * <p>
   * (The DOM's statement that "An XML processor may choose to
   * completely expand entities before the structure model is passed
   * to the DOM" refers only to parsed entities, not unparsed, and hence
   * doesn't affect this function.)
   *
   * @param name A string containing the Entity Name of the unparsed
   * entity.
   *
   * @return String containing the URI of the Unparsed Entity, or an
   * empty string if no such entity exists.
   */
  public String getUnparsedEntityURI(String name)
  {

    String url = "";

    if (null == m_entities)
      return url;

    int n = m_entities.size();

    for (int i = 0; i < n; i += ENTITY_FIELDS_PER)
    {
      String ename = (String) m_entities.elementAt(i + ENTITY_FIELD_NAME);

      if (null != ename && ename.equals(name))
      {
        String nname = (String) m_entities.elementAt(i
                         + ENTITY_FIELD_NOTATIONNAME);

        if (null != nname)
        {

          // The draft says: "The XSLT processor may use the public
          // identifier to generate a URI for the entity instead of the URI
          // specified in the system identifier. If the XSLT processor does
          // not use the public identifier to generate the URI, it must use
          // the system identifier; if the system identifier is a relative
          // URI, it must be resolved into an absolute URI using the URI of
          // the resource containing the entity declaration as the base
          // URI [RFC2396]."
          // So I'm falling a bit short here.
          url = (String) m_entities.elementAt(i + ENTITY_FIELD_SYSTEMID);

          if (null == url)
          {
            url = (String) m_entities.elementAt(i + ENTITY_FIELD_PUBLICID);
          }
        }

        break;
      }
    }

    return url;
  }

  /**
   * Given a namespace handle, return the prefix that the namespace decl is
   * mapping.
   * Given a node handle, return the prefix used to map to the namespace.
   *
   * <p> %REVIEW% Are you sure you want "" for no prefix?  </p>
   * <p> %REVIEW-COMMENT% I think so... not totally sure. -sb  </p>
   *
   * @param nodeHandle the id of the node.
   * @return String prefix of this node's name, or "" if no explicit
   * namespace prefix was given.
   */
  public String getPrefix(int nodeHandle)
  {

    int identity = makeNodeIdentity(nodeHandle);
    int type = _type(identity);

    if (DTM.ELEMENT_NODE == type)
    {
      int prefixIndex = _dataOrQName(identity);

      if (0 == prefixIndex)
        return "";
      else
      {
        String qname = m_valuesOrPrefixes.indexToString(prefixIndex);

        return getPrefix(qname, null);
      }
    }
    else if (DTM.ATTRIBUTE_NODE == type)
    {
      int prefixIndex = _dataOrQName(identity);

      if (prefixIndex < 0)
      {
        prefixIndex = m_data.elementAt(-prefixIndex);

        String qname = m_valuesOrPrefixes.indexToString(prefixIndex);

        return getPrefix(qname, null);
      }
    }

    return "";
  }

  /**
   * Retrieves an attribute node by by qualified name and namespace URI.
   *
   * @param nodeHandle int Handle of the node upon which to look up this attribute..
   * @param namespaceURI The namespace URI of the attribute to
   *   retrieve, or null.
   * @param name The local name of the attribute to
   *   retrieve.
   * @return The attribute node handle with the specified name (
   *   <code>nodeName</code>) or <code>DTM.NULL</code> if there is no such
   *   attribute.
   */
  public int getAttributeNode(int nodeHandle, String namespaceURI,
                              String name)
  {

    for (int attrH = getFirstAttribute(nodeHandle); DTM.NULL != attrH;
            attrH = getNextAttribute(attrH))
    {
      String attrNS = getNamespaceURI(attrH);
      String attrName = getLocalName(attrH);
      boolean nsMatch = namespaceURI == attrNS
                        || (namespaceURI != null
                            && namespaceURI.equals(attrNS));

      if (nsMatch && name.equals(attrName))
        return attrH;
    }

    return DTM.NULL;
  }

  /**
   * 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.
   *
   * @return the public identifier String object, or null if there is none.
   */
  public String getDocumentTypeDeclarationPublicIdentifier()
  {

    /** @todo: implement this com.sun.org.apache.xml.internal.dtm.DTMDefaultBase abstract method */
    error(XMLMessages.createXMLMessage(XMLErrorResources.ER_METHOD_NOT_SUPPORTED, null));//"Not yet supported!");

    return null;
  }

  /**
   * Given a node handle, return its DOM-style namespace URI
   * (As defined in Namespaces, this is the declared URI which this node's
   * prefix -- or default in lieu thereof -- was mapped to.)
   *
   * <p>%REVIEW% Null or ""? -sb</p>
   *
   * @param nodeHandle the id of the node.
   * @return String URI value of this node's namespace, or null if no
   * namespace was resolved.
   */
  public String getNamespaceURI(int nodeHandle)
  {

    return m_expandedNameTable.getNamespace(_exptype(makeNodeIdentity(nodeHandle)));
  }

  /**
   * Get the string-value of a node as a String object
   * (see http://www.w3.org/TR/xpath#data-model
   * for the definition of a node's string-value).
   *
   * @param nodeHandle The node ID.
   *
   * @return A string object that represents the string-value of the given node.
   */
  public XMLString getStringValue(int nodeHandle)
  {
    int identity = makeNodeIdentity(nodeHandle);
    int type;
    if(identity==DTM.NULL) // Separate lines because I wanted to breakpoint it
      type = DTM.NULL;
    else
      type= _type(identity);

    if (isTextType(type))
    {
      int dataIndex = _dataOrQName(identity);
      int offset = m_data.elementAt(dataIndex);
      int length = m_data.elementAt(dataIndex + 1);

      return m_xstrf.newstr(m_chars, offset, length);
    }
    else
    {
      int firstChild = _firstch(identity);

      if (DTM.NULL != firstChild)
      {
        int offset = -1;
        int length = 0;
        int startNode = identity;

        identity = firstChild;

        do {
          type = _type(identity);

          if (isTextType(type))
          {
            int dataIndex = _dataOrQName(identity);

            if (-1 == offset)
            {
              offset = m_data.elementAt(dataIndex);
            }

            length += m_data.elementAt(dataIndex + 1);
          }

          identity = getNextNodeIdentity(identity);
        } while (DTM.NULL != identity && (_parent(identity) >= startNode));

        if (length > 0)
        {
          return m_xstrf.newstr(m_chars, offset, length);
        }
      }
      else if(type != DTM.ELEMENT_NODE)
      {
        int dataIndex = _dataOrQName(identity);

        if (dataIndex < 0)
        {
          dataIndex = -dataIndex;
          dataIndex = m_data.elementAt(dataIndex + 1);
        }
        return m_xstrf.newstr(m_valuesOrPrefixes.indexToString(dataIndex));
      }
    }

    return m_xstrf.emptystr();
  }

  /**
   * Determine if the string-value of a node is whitespace
   *
   * @param nodeHandle The node Handle.
   *
   * @return Return true if the given node is whitespace.
   */
  public boolean isWhitespace(int nodeHandle)
  {
    int identity = makeNodeIdentity(nodeHandle);
    int type;
    if(identity==DTM.NULL) // Separate lines because I wanted to breakpoint it
      type = DTM.NULL;
    else
      type= _type(identity);

    if (isTextType(type))
    {
      int dataIndex = _dataOrQName(identity);
      int offset = m_data.elementAt(dataIndex);
      int length = m_data.elementAt(dataIndex + 1);

      return m_chars.isWhitespace(offset, length);
    }
    return false;
  }

  /**
   * Returns the <code>Element</code> whose <code>ID</code> is given by
   * <code>elementId</code>. If no such element exists, returns
   * <code>DTM.NULL</code>. Behavior is not defined if more than one element
   * has this <code>ID</code>. Attributes (including those
   * with the name "ID") are not of type ID unless so defined by DTD/Schema
   * information available to the DTM implementation.
   * Implementations that do not know whether attributes are of type ID or
   * not are expected to return <code>DTM.NULL</code>.
   *
   * <p>%REVIEW% Presumably IDs are still scoped to a single document,
   * and this operation searches only within a single document, right?
   * Wouldn't want collisions between DTMs in the same process.</p>
   *
   * @param elementId The unique <code>id</code> value for an element.
   * @return The handle of the matching element.
   */
  public int getElementById(String elementId)
  {

    Integer intObj;
    boolean isMore = true;

    do
    {
      intObj = m_idAttributes.get(elementId);

      if (null != intObj)
        return makeNodeHandle(intObj.intValue());

      if (!isMore || m_endDocumentOccured)
        break;

      isMore = nextNode();
    }
    while (null == intObj);

    return DTM.NULL;
  }

  /**
   * Get a prefix either from the qname or from the uri mapping, or just make
   * one up!
   *
   * @param qname The qualified name, which may be null.
   * @param uri The namespace URI, which may be null.
   *
   * @return The prefix if there is one, or null.
   */
  public String getPrefix(String qname, String uri)
  {

    String prefix;
    int uriIndex = -1;

    if (null != uri && uri.length() > 0)
    {

      do
      {
        uriIndex = m_prefixMappings.indexOf(uri, ++uriIndex);
      } while ( (uriIndex & 0x01) == 0);

      if (uriIndex >= 0)
      {
        prefix = (String) m_prefixMappings.elementAt(uriIndex - 1);
      }
      else if (null != qname)
      {
        int indexOfNSSep = qname.indexOf(':');

        if (qname.equals("xmlns"))
          prefix = "";
        else if (qname.startsWith("xmlns:"))
          prefix = qname.substring(indexOfNSSep + 1);
        else
          prefix = (indexOfNSSep > 0)
                   ? qname.substring(0, indexOfNSSep) : null;
      }
      else
      {
        prefix = null;
      }
    }
    else if (null != qname)
    {
      int indexOfNSSep = qname.indexOf(':');

      if (indexOfNSSep > 0)
      {
        if (qname.startsWith("xmlns:"))
          prefix = qname.substring(indexOfNSSep + 1);
        else
          prefix = qname.substring(0, indexOfNSSep);
      }
      else
      {
        if (qname.equals("xmlns"))
          prefix = "";
        else
          prefix = null;
      }
    }
    else
    {
      prefix = null;
    }

    return prefix;
  }

  /**
   * Get a prefix either from the uri mapping, or just make
   * one up!
   *
   * @param uri The namespace URI, which may be null.
   *
   * @return The prefix if there is one, or null.
   */
  public int getIdForNamespace(String uri)
  {

     return m_valuesOrPrefixes.stringToIndex(uri);

  }

    /**
   * Get a prefix either from the qname or from the uri mapping, or just make
   * one up!
   *
   * @return The prefix if there is one, or null.
   */
  public String getNamespaceURI(String prefix)
  {

    String uri = "";
    int prefixIndex = m_contextIndexes.peek() - 1 ;

    if(null == prefix)
      prefix = "";

      do
      {
        prefixIndex = m_prefixMappings.indexOf(prefix, ++prefixIndex);
      } while ( (prefixIndex >= 0) && (prefixIndex & 0x01) == 0x01);

      if (prefixIndex > -1)
      {
        uri = (String) m_prefixMappings.elementAt(prefixIndex + 1);
      }


    return uri;
  }

  /**
   * Set an ID string to node association in the ID table.
   *
   * @param id The ID string.
   * @param elem The associated element handle.
   */
  public void setIDAttribute(String id, int elem)
  {
    m_idAttributes.put(id, elem);
  }

  /**
   * Check whether accumulated text should be stripped; if not,
   * append the appropriate flavor of text/cdata node.
   */
  protected void charactersFlush()
  {

    if (m_textPendingStart >= 0)  // -1 indicates no-text-in-progress
    {
      int length = m_chars.size() - m_textPendingStart;
      boolean doStrip = false;

      if (getShouldStripWhitespace())
      {
        doStrip = m_chars.isWhitespace(m_textPendingStart, length);
      }

      if (doStrip) {
        m_chars.setLength(m_textPendingStart);  // Discard accumulated text
      } else {
        // Guard against characters/ignorableWhitespace events that
        // contained no characters.  They should not result in a node.
        if (length > 0) {
          int exName = m_expandedNameTable.getExpandedTypeID(DTM.TEXT_NODE);
          int dataIndex = m_data.size();

          m_previous = addNode(m_coalescedTextType, exName,
                               m_parents.peek(), m_previous, dataIndex, false);

          m_data.addElement(m_textPendingStart);
          m_data.addElement(length);
        }
      }

      // Reset for next text block
      m_textPendingStart = -1;
      m_textType = m_coalescedTextType = DTM.TEXT_NODE;
    }
  }

  ////////////////////////////////////////////////////////////////////
  // Implementation of the EntityResolver interface.
  ////////////////////////////////////////////////////////////////////

  /**
   * Resolve an external entity.
   *
   * <p>Always return null, so that the parser will use the system
   * identifier provided in the XML document.  This method implements
   * the SAX default behaviour: application writers can override it
   * in a subclass to do special translations such as catalog lookups
   * or URI redirection.</p>
   *
   * @param publicId The public identifer, or null if none is
   *                 available.
   * @param systemId The system identifier provided in the XML
   *                 document.
   * @return The new input source, or null to require the
   *         default behaviour.
   * @throws SAXException Any SAX exception, possibly
   *            wrapping another exception.
   * @see org.xml.sax.EntityResolver#resolveEntity
   *
   * @throws SAXException
   */
  public InputSource resolveEntity(String publicId, String systemId)
          throws SAXException
  {
    return null;
  }

  ////////////////////////////////////////////////////////////////////
  // Implementation of DTDHandler interface.
  ////////////////////////////////////////////////////////////////////

  /**
   * 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 SAXException Any SAX exception, possibly
   *            wrapping another exception.
   * @see org.xml.sax.DTDHandler#notationDecl
   *
   * @throws SAXException
   */
  public void notationDecl(String name, String publicId, String systemId)
          throws SAXException
  {

    // 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 SAXException Any SAX exception, possibly
   *            wrapping another exception.
   * @see org.xml.sax.DTDHandler#unparsedEntityDecl
   *
   * @throws SAXException
   */
  public void unparsedEntityDecl(
          String name, String publicId, String systemId, String notationName)
            throws SAXException
  {

    if (null == m_entities)
    {
      m_entities = new Vector();
    }

    try
    {
      systemId = SystemIDResolver.getAbsoluteURI(systemId,
                                                 getDocumentBaseURI());
    }
    catch (Exception e)
    {
      throw new org.xml.sax.SAXException(e);
    }

    //  private static final int ENTITY_FIELD_PUBLICID = 0;
    m_entities.addElement(publicId);

    //  private static final int ENTITY_FIELD_SYSTEMID = 1;
    m_entities.addElement(systemId);

    //  private static final int ENTITY_FIELD_NOTATIONNAME = 2;
    m_entities.addElement(notationName);

    //  private static final int ENTITY_FIELD_NAME = 3;
    m_entities.addElement(name);
  }

  ////////////////////////////////////////////////////////////////////
  // Implementation of ContentHandler interface.
  ////////////////////////////////////////////////////////////////////

  /**
   * 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 SAX document events.
   * @see org.xml.sax.ContentHandler#setDocumentLocator
   * @see org.xml.sax.Locator
   */
  public void setDocumentLocator(Locator locator)
  {
    m_locator = locator;
    m_systemId = locator.getSystemId();
  }

  /**
   * Receive notification of the beginning of the document.
   *
   * @throws SAXException Any SAX exception, possibly
   *            wrapping another exception.
   * @see org.xml.sax.ContentHandler#startDocument
   */
  public void startDocument() throws SAXException
  {
    if (DEBUG)
      System.out.println("startDocument");


    int doc = addNode(DTM.DOCUMENT_NODE,
                      m_expandedNameTable.getExpandedTypeID(DTM.DOCUMENT_NODE),
                      DTM.NULL, DTM.NULL, 0, true);

    m_parents.push(doc);
    m_previous = DTM.NULL;

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

  /**
   * Receive notification of the end of the document.
   *
   * @throws SAXException Any SAX exception, possibly
   *            wrapping another exception.
   * @see org.xml.sax.ContentHandler#endDocument
   */
  public void endDocument() throws SAXException
  {
    if (DEBUG)
      System.out.println("endDocument");

                charactersFlush();

    m_nextsib.setElementAt(NULL,0);

    if (m_firstch.elementAt(0) == NOTPROCESSED)
      m_firstch.setElementAt(NULL,0);

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

    m_parents = null;
    m_prefixMappings = null;
    m_contextIndexes = null;

    m_endDocumentOccured = true;

    // Bugzilla 4858: throw away m_locator. we cache m_systemId
    m_locator = null;
  }

  /**
   * 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 SAXException Any SAX exception, possibly
   *            wrapping another exception.
   * @see org.xml.sax.ContentHandler#startPrefixMapping
   */
  public void startPrefixMapping(String prefix, String uri)
          throws SAXException
  {

    if (DEBUG)
      System.out.println("startPrefixMapping: prefix: " + prefix + ", uri: "
                         + uri);

    if(null == prefix)
      prefix = "";
    m_prefixMappings.addElement(prefix);  // JDK 1.1.x compat -sc
    m_prefixMappings.addElement(uri);  // JDK 1.1.x compat -sc
  }

  /**
   * 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 SAXException Any SAX exception, possibly
   *            wrapping another exception.
   * @see org.xml.sax.ContentHandler#endPrefixMapping
   */
  public void endPrefixMapping(String prefix) throws SAXException
  {
    if (DEBUG)
      System.out.println("endPrefixMapping: prefix: " + prefix);

    if(null == prefix)
      prefix = "";

    int index = m_contextIndexes.peek() - 1;

    do
    {
      index = m_prefixMappings.indexOf(prefix, ++index);
    } while ( (index >= 0) && ((index & 0x01) == 0x01) );


    if (index > -1)
    {
      m_prefixMappings.setElementAt("%@$#^@#", index);
      m_prefixMappings.setElementAt("%@$#^@#", index + 1);
    }

    // no op
  }

  /**
   * Check if a declaration has already been made for a given prefix.
   *
   * @param prefix non-null prefix string.
   *
   * @return true if the declaration has already been declared in the
   *         current context.
   */
  protected boolean declAlreadyDeclared(String prefix)
  {

    int startDecls = m_contextIndexes.peek();
    java.util.Vector prefixMappings = m_prefixMappings;
    int nDecls = prefixMappings.size();

    for (int i = startDecls; i < nDecls; i += 2)
    {
      String prefixDecl = (String) prefixMappings.elementAt(i);

      if (prefixDecl == null)
        continue;

      if (prefixDecl.equals(prefix))
        return true;
    }

    return false;
  }

        boolean m_pastFirstElement=false;

  /**
   * 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 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 SAXException Any SAX exception, possibly
   *            wrapping another exception.
   * @see org.xml.sax.ContentHandler#startElement
   */
  public void startElement(
          String uri, String localName, String qName, Attributes attributes)
            throws SAXException
  {
   if (DEBUG)
         {
      System.out.println("startElement: uri: " + uri + ", localname: "
                                                                                                 + localName + ", qname: "+qName+", atts: " + attributes);

                        boolean DEBUG_ATTRS=true;
                        if(DEBUG_ATTRS & 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)
                                                                                                                 );
                        }
         }

    charactersFlush();

    int exName = m_expandedNameTable.getExpandedTypeID(uri, localName, DTM.ELEMENT_NODE);
    String prefix = getPrefix(qName, uri);
    int prefixIndex = (null != prefix)
                      ? m_valuesOrPrefixes.stringToIndex(qName) : 0;

    int elemNode = addNode(DTM.ELEMENT_NODE, exName,
                           m_parents.peek(), m_previous, prefixIndex, true);

    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);
      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);

      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;

       String attrLocalName = attributes.getLocalName(i);

      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);
      prev = addNode(nodeType, exName, elemNode, prev, val,
                     false);
    }

    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 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 SAXException Any SAX exception, possibly
   *            wrapping another exception.
   * @see org.xml.sax.ContentHandler#endElement
   */
  public void endElement(String uri, String localName, String qName)
          throws SAXException
  {
   if (DEBUG)
      System.out.println("endElement: uri: " + uri + ", localname: "
                                                                                                 + localName + ", qname: "+qName);

    charactersFlush();

    // If no one noticed, startPrefixMapping is a drag.
    // Pop the context for the last child (the one pushed by startElement)
    m_contextIndexes.quickPop(1);

    // Do it again for this one (the one pushed by the last endElement).
    int topContextIndex = m_contextIndexes.peek();
    if (topContextIndex != m_prefixMappings.size()) {
      m_prefixMappings.setSize(topContextIndex);
    }

    int lastNode = m_previous;

    m_previous = m_parents.pop();

    // If lastNode is still DTM.NULL, this element had no children
    if (DTM.NULL == lastNode)
      m_firstch.setElementAt(DTM.NULL,m_previous);
    else
      m_nextsib.setElementAt(DTM.NULL,lastNode);

    popShouldStripWhitespace();
  }

  /**
   * 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 SAXException Any SAX exception, possibly
   *            wrapping another exception.
   * @see org.xml.sax.ContentHandler#characters
   */
  public void characters(char ch[], int start, int length) throws SAXException
  {
    if (m_textPendingStart == -1)  // First one in this block
    {
      m_textPendingStart = m_chars.size();
      m_coalescedTextType = m_textType;
    }
    // Type logic: If all adjacent text is CDATASections, the
    // concatentated text is treated as a single CDATASection (see
    // initialization above).  If any were ordinary Text, the whole
    // thing is treated as Text. This may be worth %REVIEW%ing.
    else if (m_textType == DTM.TEXT_NODE)
    {
      m_coalescedTextType = DTM.TEXT_NODE;
    }

    m_chars.append(ch, start, length);
  }

  /**
   * 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 SAXException Any SAX exception, possibly
   *            wrapping another exception.
   * @see org.xml.sax.ContentHandler#ignorableWhitespace
   */
  public void ignorableWhitespace(char ch[], int start, int length)
          throws SAXException
  {

    // %OPT% We can probably take advantage of the fact that we know this
    // is whitespace.
    characters(ch, start, length);
  }

  /**
   * 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 SAXException Any SAX exception, possibly
   *            wrapping another exception.
   * @see org.xml.sax.ContentHandler#processingInstruction
   */
  public void processingInstruction(String target, String data)
          throws SAXException
  {
    if (DEBUG)
                 System.out.println("processingInstruction: target: " + target +", data: "+data);

    charactersFlush();

    int exName = m_expandedNameTable.getExpandedTypeID(null, target,
                                         DTM.PROCESSING_INSTRUCTION_NODE);
    int dataIndex = m_valuesOrPrefixes.stringToIndex(data);

    m_previous = addNode(DTM.PROCESSING_INSTRUCTION_NODE, exName,
                         m_parents.peek(), m_previous,
                         dataIndex, false);
  }

  /**
   * Receive notification of a skipped entity.
   *
   * <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 name The name of the skipped entity.
   * @throws SAXException Any SAX exception, possibly
   *            wrapping another exception.
   * @see org.xml.sax.ContentHandler#processingInstruction
   */
  public void skippedEntity(String name) throws SAXException
  {

    // %REVIEW% What should be done here?
    // no op
  }

  ////////////////////////////////////////////////////////////////////
  // Implementation of the ErrorHandler interface.
  ////////////////////////////////////////////////////////////////////

  /**
   * Receive notification of a parser warning.
   *
   * <p>The default implementation does nothing.  Application writers
   * may override this method in a subclass to take specific actions
   * for each warning, such as inserting the message in a log file or
   * printing it to the console.</p>
   *
   * @param e The warning information encoded as an exception.
   * @throws SAXException Any SAX exception, possibly
   *            wrapping another exception.
   * @see org.xml.sax.ErrorHandler#warning
   * @see org.xml.sax.SAXParseException
   */
  public void warning(SAXParseException e) throws SAXException
  {

    // %REVIEW% Is there anyway to get the JAXP error listener here?
    System.err.println(e.getMessage());
  }

  /**
   * Receive notification of a recoverable parser error.
   *
   * <p>The default implementation does nothing.  Application writers
   * may override this method in a subclass to take specific actions
   * for each error, such as inserting the message in a log file or
   * printing it to the console.</p>
   *
   * @param e The warning information encoded as an exception.
   * @throws SAXException Any SAX exception, possibly
   *            wrapping another exception.
   * @see org.xml.sax.ErrorHandler#warning
   * @see org.xml.sax.SAXParseException
   */
  public void error(SAXParseException e) throws SAXException
  {
    throw e;
  }

  /**
   * Report a fatal XML parsing error.
   *
   * <p>The default implementation throws a SAXParseException.
   * Application writers may override this method in a subclass if
   * they need to take specific actions for each fatal error (such as
   * collecting all of the errors into a single report): in any case,
   * the application must stop all regular processing when this
   * method is invoked, since the document is no longer reliable, and
   * the parser may no longer report parsing events.</p>
   *
   * @param e The error information encoded as an exception.
   * @throws SAXException Any SAX exception, possibly
   *            wrapping another exception.
   * @see org.xml.sax.ErrorHandler#fatalError
   * @see org.xml.sax.SAXParseException
   */
  public void fatalError(SAXParseException e) throws SAXException
  {
    throw e;
  }

  ////////////////////////////////////////////////////////////////////
  // Implementation of the DeclHandler interface.
  ////////////////////////////////////////////////////////////////////

  /**
   * Report an element type declaration.
   *
   * <p>The content model will consist of the string "EMPTY", the
   * string "ANY", or a parenthesised group, optionally followed
   * by an occurrence indicator.  The model will be normalized so
   * that all whitespace is removed,and will include the enclosing
   * parentheses.</p>
   *
   * @param name The element type name.
   * @param model The content model as a normalized string.
   * @throws SAXException The application may raise an exception.
   */
  public void elementDecl(String name, String model) throws SAXException
  {

    // no op
  }

  /**
   * Report an attribute type declaration.
   *
   * <p>Only the effective (first) declaration for an attribute will
   * be reported.  The type will be one of the strings "CDATA",
   * "ID", "IDREF", "IDREFS", "NMTOKEN", "NMTOKENS", "ENTITY",
   * "ENTITIES", or "NOTATION", or a parenthesized token group with
   * the separator "|" and all whitespace removed.</p>
   *
   * @param eName The name of the associated element.
   * @param aName The name of the attribute.
   * @param type A string representing the attribute type.
   * @param valueDefault A string representing the attribute default
   *        ("#IMPLIED", "#REQUIRED", or "#FIXED") or null if
   *        none of these applies.
   * @param value A string representing the attribute's default value,
   *        or null if there is none.
   * @throws SAXException The application may raise an exception.
   */
  public void attributeDecl(
          String eName, String aName, String type, String valueDefault, String value)
            throws SAXException
  {

    // no op
  }

  /**
   * Report an internal entity declaration.
   *
   * <p>Only the effective (first) declaration for each entity
   * will be reported.</p>
   *
   * @param name The name of the entity.  If it is a parameter
   *        entity, the name will begin with '%'.
   * @param value The replacement text of the entity.
   * @throws SAXException The application may raise an exception.
   * @see #externalEntityDecl
   * @see org.xml.sax.DTDHandler#unparsedEntityDecl
   */
  public void internalEntityDecl(String name, String value)
          throws SAXException
  {

    // no op
  }

  /**
   * Report a parsed external entity declaration.
   *
   * <p>Only the effective (first) declaration for each entity
   * will be reported.</p>
   *
   * @param name The name of the entity.  If it is a parameter
   *        entity, the name will begin with '%'.
   * @param publicId The declared public identifier of the entity, or
   *        null if none was declared.
   * @param systemId The declared system identifier of the entity.
   * @throws SAXException The application may raise an exception.
   * @see #internalEntityDecl
   * @see org.xml.sax.DTDHandler#unparsedEntityDecl
   */
  public void externalEntityDecl(
          String name, String publicId, String systemId) throws SAXException
  {

    // no op
  }

  ////////////////////////////////////////////////////////////////////
  // Implementation of the LexicalHandler interface.
  ////////////////////////////////////////////////////////////////////

  /**
   * Report the start of DTD declarations, if any.
   *
   * <p>Any declarations are assumed to be in the internal subset
   * unless otherwise indicated by a {@link #startEntity startEntity}
   * event.</p>
   *
   * <p>Note that the start/endDTD events will appear within
   * the start/endDocument events from ContentHandler and
   * before the first startElement event.</p>
   *
   * @param name The document type name.
   * @param publicId The declared public identifier for the
   *        external DTD subset, or null if none was declared.
   * @param systemId The declared system identifier for the
   *        external DTD subset, or null if none was declared.
   * @throws SAXException The application may raise an
   *            exception.
   * @see #endDTD
   * @see #startEntity
   */
  public void startDTD(String name, String publicId, String systemId)
          throws SAXException
  {

    m_insideDTD = true;
  }

  /**
   * Report the end of DTD declarations.
   *
   * @throws SAXException The application may raise an exception.
   * @see #startDTD
   */
  public void endDTD() throws SAXException
  {

    m_insideDTD = false;
  }

  /**
   * 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 startEntity(String name) throws SAXException
  {

    // 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 endEntity(String name) throws SAXException
  {

    // 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() throws SAXException
  {
    m_textType = DTM.CDATA_SECTION_NODE;
  }

  /**
   * Report the end of a CDATA section.
   *
   * @throws SAXException The application may raise an exception.
   * @see #startCDATA
   */
  public void endCDATA() throws SAXException
  {
    m_textType = DTM.TEXT_NODE;
  }

  /**
   * 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(char ch[], int start, int length) throws SAXException
  {

    if (m_insideDTD)      // ignore comments if we're inside the DTD
      return;

    charactersFlush();

    int exName = m_expandedNameTable.getExpandedTypeID(DTM.COMMENT_NODE);

    // For now, treat comments as strings...  I guess we should do a
    // seperate FSB buffer instead.
    int dataIndex = m_valuesOrPrefixes.stringToIndex(new String(ch, start,
                      length));


    m_previous = addNode(DTM.COMMENT_NODE, exName,
                         m_parents.peek(), m_previous, dataIndex, false);
  }

  /**
   * Set a run time property for this DTM instance.
   *
   * %REVIEW% Now that we no longer use this method to support
   * getSourceLocatorFor, can we remove it?
   *
   * @param property a <code>String</code> value
   * @param value an <code>Object</code> value
   */
  public void setProperty(String property, Object value)
  {
  }

  /** Retrieve the SourceLocator associated with a specific node.
   * This is only meaningful if the XalanProperties.SOURCE_LOCATION flag was
   * set True using setProperty; if it was never set, or was set false, we
   * will return null.
   *
   * (We _could_ return a locator with the document's base URI and bogus
   * line/column information. Trying that; see the else clause.)
   * */
  public SourceLocator getSourceLocatorFor(int node)
  {
    if (m_useSourceLocationProperty)
    {

      node = makeNodeIdentity(node);


      return new NodeLocator(null,
                             m_sourceSystemId.elementAt(node),
                             m_sourceLine.elementAt(node),
                             m_sourceColumn.elementAt(node));
    }
    else if(m_locator!=null)
    {
        return new NodeLocator(null,m_locator.getSystemId(),-1,-1);
    }
    else if(m_systemId!=null)
    {
        return new NodeLocator(null,m_systemId,-1,-1);
    }
    return null;
  }

  public String getFixedNames(int type){
    return m_fixednames[type];
  }
}
