/*
 * reserved comment block
 * DO NOT REMOVE OR ALTER!
 */
/*
 * Copyright 1999-2004 The Apache Software Foundation.
 *
 * Licensed 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: DTMManagerDefault.java,v 1.2.4.1 2005/09/15 08:15:02 suresh_emailid Exp $
 */
package com.sun.org.apache.xml.internal.dtm.ref;

import com.sun.org.apache.xalan.internal.utils.FactoryImpl;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamSource;

import com.sun.org.apache.xml.internal.dtm.DTM;
import com.sun.org.apache.xml.internal.dtm.DTMException;
import com.sun.org.apache.xml.internal.dtm.DTMFilter;
import com.sun.org.apache.xml.internal.dtm.DTMIterator;
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.dom2dtm.DOM2DTM;
import com.sun.org.apache.xml.internal.dtm.ref.sax2dtm.SAX2DTM;
import com.sun.org.apache.xml.internal.dtm.ref.sax2dtm.SAX2RTFDTM;
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.PrefixResolver;
import com.sun.org.apache.xml.internal.utils.SystemIDResolver;
import com.sun.org.apache.xml.internal.utils.XMLReaderManager;
import com.sun.org.apache.xml.internal.utils.XMLStringFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Node;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

/**
 * The default implementation for the DTMManager.
 *
 * %REVIEW% There is currently a reentrancy issue, since the finalizer
 * for XRTreeFrag (which runs in the GC thread) wants to call
 * DTMManager.release(), and may do so at the same time that the main
 * transformation thread is accessing the manager. Our current solution is
 * to make most of the manager's methods <code>synchronized</code>.
 * Early tests suggest that doing so is not causing a significant
 * performance hit in Xalan. However, it should be noted that there
 * is a possible alternative solution: rewrite release() so it merely
 * posts a request for release onto a threadsafe queue, and explicitly
 * process that queue on an infrequent basis during main-thread
 * activity (eg, when getDTM() is invoked). The downside of that solution
 * would be a greater delay before the DTM's storage is actually released
 * for reuse.
 * */
public class DTMManagerDefault extends DTMManager
{
  //static final boolean JKESS_XNI_EXPERIMENT=true;

  /** Set this to true if you want a dump of the DTM after creation. */
  private static final boolean DUMPTREE = false;

  /** Set this to true if you want a basic diagnostics. */
  private static final boolean DEBUG = false;

  /**
   * Map from DTM identifier numbers to DTM objects that this manager manages.
   * One DTM may have several prefix numbers, if extended node indexing
   * is in use; in that case, m_dtm_offsets[] will used to control which
   * prefix maps to which section of the DTM.
   *
   * This array grows as necessary; see addDTM().
   *
   * This array grows as necessary; see addDTM(). Growth is uncommon... but
   * access needs to be blindingly fast since it's used in node addressing.
   */
  protected DTM m_dtms[] = new DTM[256];

  /** Map from DTM identifier numbers to offsets. For small DTMs with a
   * single identifier, this will always be 0. In overflow addressing, where
   * additional identifiers are allocated to access nodes beyond the range of
   * a single Node Handle, this table is used to map the handle's node field
   * into the actual node identifier.
   *
   * This array grows as necessary; see addDTM().
   *
   * This array grows as necessary; see addDTM(). Growth is uncommon... but
   * access needs to be blindingly fast since it's used in node addressing.
   * (And at the moment, that includes accessing it from DTMDefaultBase,
   * which is why this is not Protected or Private.)
   */
  int m_dtm_offsets[] = new int[256];

  /**
   * The cache for XMLReader objects to be used if the user did not
   * supply an XMLReader for a SAXSource or supplied a StreamSource.
   */
  protected XMLReaderManager m_readerManager = null;

  /**
   * The default implementation of ContentHandler, DTDHandler and ErrorHandler.
   */
  protected DefaultHandler m_defaultHandler = new DefaultHandler();

  /**
   * Add a DTM to the DTM table. This convenience call adds it as the
   * "base DTM ID", with offset 0. The other version of addDTM should
   * be used if you want to add "extended" DTM IDs with nonzero offsets.
   *
   * @param dtm Should be a valid reference to a DTM.
   * @param id Integer DTM ID to be bound to this DTM
   */
  synchronized public void addDTM(DTM dtm, int id) {    addDTM(dtm,id,0); }


  /**
   * Add a DTM to the DTM table.
   *
   * @param dtm Should be a valid reference to a DTM.
   * @param id Integer DTM ID to be bound to this DTM.
   * @param offset Integer addressing offset. The internal DTM Node ID is
   * obtained by adding this offset to the node-number field of the
   * public DTM Handle. For the first DTM ID accessing each DTM, this is 0;
   * for overflow addressing it will be a multiple of 1<<IDENT_DTM_NODE_BITS.
   */
  synchronized public void addDTM(DTM dtm, int id, int offset)
  {
                if(id>=IDENT_MAX_DTMS)
                {
                        // TODO: %REVIEW% Not really the right error message.
            throw new DTMException(XMLMessages.createXMLMessage(XMLErrorResources.ER_NO_DTMIDS_AVAIL, null)); //"No more DTM IDs are available!");
                }

                // We used to just allocate the array size to IDENT_MAX_DTMS.
                // But we expect to increase that to 16 bits, and I'm not willing
                // to allocate that much space unless needed. We could use one of our
                // handy-dandy Fast*Vectors, but this will do for now.
                // %REVIEW%
                int oldlen=m_dtms.length;
                if(oldlen<=id)
                {
                        // Various growth strategies are possible. I think we don't want
                        // to over-allocate excessively, and I'm willing to reallocate
                        // more often to get that. See also Fast*Vector classes.
                        //
                        // %REVIEW% Should throw a more diagnostic error if we go over the max...
                        int newlen=Math.min((id+256),IDENT_MAX_DTMS);

                        DTM new_m_dtms[] = new DTM[newlen];
                        System.arraycopy(m_dtms,0,new_m_dtms,0,oldlen);
                        m_dtms=new_m_dtms;
                        int new_m_dtm_offsets[] = new int[newlen];
                        System.arraycopy(m_dtm_offsets,0,new_m_dtm_offsets,0,oldlen);
                        m_dtm_offsets=new_m_dtm_offsets;
                }

    m_dtms[id] = dtm;
                m_dtm_offsets[id]=offset;
    dtm.documentRegistration();
                // The DTM should have been told who its manager was when we created it.
                // Do we need to allow for adopting DTMs _not_ created by this manager?
  }

  /**
   * Get the first free DTM ID available. %OPT% Linear search is inefficient!
   */
  synchronized public int getFirstFreeDTMID()
  {
    int n = m_dtms.length;
    for (int i = 1; i < n; i++)
    {
      if(null == m_dtms[i])
      {
        return i;
      }
    }
                return n; // count on addDTM() to throw exception if out of range
  }

  /**
   * The default table for exandedNameID lookups.
   */
  private ExpandedNameTable m_expandedNameTable =
    new ExpandedNameTable();

  /**
   * Constructor DTMManagerDefault
   *
   */
  public DTMManagerDefault(){}


  /**
   * Get an instance of a DTM, loaded with the content from the
   * specified source.  If the unique flag is true, a new instance will
   * always be returned.  Otherwise it is up to the DTMManager to return a
   * new instance or an instance that it already created and may be being used
   * by someone else.
   *
   * A bit of magic in this implementation: If the source is null, unique is true,
   * and incremental and doIndexing are both false, we return an instance of
   * SAX2RTFDTM, which see.
   *
   * (I think more parameters will need to be added for error handling, and entity
   * resolution, and more explicit control of the RTF situation).
   *
   * @param source the specification of the source object.
   * @param unique true if the returned DTM must be unique, probably because it
   * is going to be mutated.
   * @param whiteSpaceFilter Enables filtering of whitespace nodes, and may
   *                         be null.
   * @param incremental true if the DTM should be built incrementally, if
   *                    possible.
   * @param doIndexing true if the caller considers it worth it to use
   *                   indexing schemes.
   *
   * @return a non-null DTM reference.
   */
  synchronized public DTM getDTM(Source source, boolean unique,
                                 DTMWSFilter whiteSpaceFilter,
                                 boolean incremental, boolean doIndexing)
  {

    if(DEBUG && null != source)
      System.out.println("Starting "+
                         (unique ? "UNIQUE" : "shared")+
                         " source: "+source.getSystemId()
                         );

    XMLStringFactory xstringFactory = m_xsf;
    int dtmPos = getFirstFreeDTMID();
    int documentID = dtmPos << IDENT_DTM_NODE_BITS;

    if ((null != source) && source instanceof DOMSource)
    {
      DOM2DTM dtm = new DOM2DTM(this, (DOMSource) source, documentID,
                                whiteSpaceFilter, xstringFactory, doIndexing);

      addDTM(dtm, dtmPos, 0);

      //      if (DUMPTREE)
      //      {
      //        dtm.dumpDTM();
      //      }

      return dtm;
    }
    else
    {
      boolean isSAXSource = (null != source)
        ? (source instanceof SAXSource) : true;
      boolean isStreamSource = (null != source)
        ? (source instanceof StreamSource) : false;

      if (isSAXSource || isStreamSource) {
        XMLReader reader = null;
        SAX2DTM dtm;

        try {
          InputSource xmlSource;

          if (null == source) {
            xmlSource = null;
          } else {
            reader = getXMLReader(source);
            xmlSource = SAXSource.sourceToInputSource(source);

            String urlOfSource = xmlSource.getSystemId();

            if (null != urlOfSource) {
              try {
                urlOfSource = SystemIDResolver.getAbsoluteURI(urlOfSource);
              } catch (Exception e) {
                // %REVIEW% Is there a better way to send a warning?
                System.err.println("Can not absolutize URL: " + urlOfSource);
              }

              xmlSource.setSystemId(urlOfSource);
            }
          }

          if (source==null && unique && !incremental && !doIndexing) {
            // Special case to support RTF construction into shared DTM.
            // It should actually still work for other uses,
            // but may be slightly deoptimized relative to the base
            // to allow it to deal with carrying multiple documents.
            //
            // %REVIEW% This is a sloppy way to request this mode;
            // we need to consider architectural improvements.
            dtm = new SAX2RTFDTM(this, source, documentID, whiteSpaceFilter,
                                 xstringFactory, doIndexing);
          }
          /**************************************************************
          // EXPERIMENTAL 3/22/02
          else if(JKESS_XNI_EXPERIMENT && m_incremental) {
            dtm = new XNI2DTM(this, source, documentID, whiteSpaceFilter,
                              xstringFactory, doIndexing);
          }
          **************************************************************/
          // Create the basic SAX2DTM.
          else {
            dtm = new SAX2DTM(this, source, documentID, whiteSpaceFilter,
                              xstringFactory, doIndexing);
          }

          // Go ahead and add the DTM to the lookup table.  This needs to be
          // done before any parsing occurs. Note offset 0, since we've just
          // created a new DTM.
          addDTM(dtm, dtmPos, 0);


          boolean haveXercesParser =
                     (null != reader)
                     && (reader.getClass()
                               .getName()
                               .equals("com.sun.org.apache.xerces.internal.parsers.SAXParser") );

          if (haveXercesParser) {
            incremental = true;  // No matter what.  %REVIEW%
          }

          // If the reader is null, but they still requested an incremental
          // build, then we still want to set up the IncrementalSAXSource stuff.
          if (m_incremental && incremental
               /* || ((null == reader) && incremental) */) {
            IncrementalSAXSource coParser=null;

            if (haveXercesParser) {
              // IncrementalSAXSource_Xerces to avoid threading.
              try {
                coParser = new com.sun.org.apache.xml.internal.dtm.ref.IncrementalSAXSource_Xerces();
              }  catch( Exception ex ) {
                ex.printStackTrace();
                coParser=null;
              }
            }

            if (coParser==null ) {
              // Create a IncrementalSAXSource to run on the secondary thread.
              if (null == reader) {
                coParser = new IncrementalSAXSource_Filter();
              } else {
                IncrementalSAXSource_Filter filter =
                         new IncrementalSAXSource_Filter();
                filter.setXMLReader(reader);
                coParser=filter;
              }
            }


            /**************************************************************
            // EXPERIMENTAL 3/22/02
            if (JKESS_XNI_EXPERIMENT && m_incremental &&
                  dtm instanceof XNI2DTM &&
                  coParser instanceof IncrementalSAXSource_Xerces) {
                com.sun.org.apache.xerces.internal.xni.parser.XMLPullParserConfiguration xpc=
                      ((IncrementalSAXSource_Xerces)coParser)
                                           .getXNIParserConfiguration();
              if (xpc!=null) {
                // Bypass SAX; listen to the XNI stream
                ((XNI2DTM)dtm).setIncrementalXNISource(xpc);
              } else {
                  // Listen to the SAX stream (will fail, diagnostically...)
                dtm.setIncrementalSAXSource(coParser);
              }
            } else
            ***************************************************************/

            // Have the DTM set itself up as IncrementalSAXSource's listener.
            dtm.setIncrementalSAXSource(coParser);

            if (null == xmlSource) {

              // Then the user will construct it themselves.
              return dtm;
            }

            if (null == reader.getErrorHandler()) {
              reader.setErrorHandler(dtm);
            }
            reader.setDTDHandler(dtm);

            try {
              // Launch parsing coroutine.  Launches a second thread,
              // if we're using IncrementalSAXSource.filter().

              coParser.startParse(xmlSource);
            } catch (RuntimeException re) {

              dtm.clearCoRoutine();

              throw re;
            } catch (Exception e) {

              dtm.clearCoRoutine();

              throw new com.sun.org.apache.xml.internal.utils.WrappedRuntimeException(e);
            }
          } else {
            if (null == reader) {

              // Then the user will construct it themselves.
              return dtm;
            }

            // not incremental
            reader.setContentHandler(dtm);
            reader.setDTDHandler(dtm);
            if (null == reader.getErrorHandler()) {
              reader.setErrorHandler(dtm);
            }

            try {
              reader.setProperty(
                               "http://xml.org/sax/properties/lexical-handler",
                               dtm);
            } catch (SAXNotRecognizedException e){}
              catch (SAXNotSupportedException e){}

            try {
              reader.parse(xmlSource);
            } catch (RuntimeException re) {
              dtm.clearCoRoutine();

              throw re;
            } catch (Exception e) {
              dtm.clearCoRoutine();

              throw new com.sun.org.apache.xml.internal.utils.WrappedRuntimeException(e);
            }
          }

          if (DUMPTREE) {
            System.out.println("Dumping SAX2DOM");
            dtm.dumpDTM(System.err);
          }

          return dtm;
        } finally {
          // Reset the ContentHandler, DTDHandler, ErrorHandler to the DefaultHandler
          // after creating the DTM.
          if (reader != null && !(m_incremental && incremental)) {
            reader.setContentHandler(m_defaultHandler);
            reader.setDTDHandler(m_defaultHandler);
            reader.setErrorHandler(m_defaultHandler);

            // Reset the LexicalHandler to null after creating the DTM.
            try {
              reader.setProperty("http://xml.org/sax/properties/lexical-handler", null);
            }
            catch (Exception e) {}
          }
          releaseXMLReader(reader);
        }
      } else {

        // It should have been handled by a derived class or the caller
        // made a mistake.
        throw new DTMException(XMLMessages.createXMLMessage(XMLErrorResources.ER_NOT_SUPPORTED, new Object[]{source})); //"Not supported: " + source);
      }
    }
  }

  /**
   * Given a W3C DOM node, try and return a DTM handle.
   * Note: calling this may be non-optimal, and there is no guarantee that
   * the node will be found in any particular DTM.
   *
   * @param node Non-null reference to a DOM node.
   *
   * @return a valid DTM handle.
   */
  synchronized public int getDTMHandleFromNode(org.w3c.dom.Node node)
  {
    if(null == node)
      throw new IllegalArgumentException(XMLMessages.createXMLMessage(XMLErrorResources.ER_NODE_NON_NULL, null)); //"node must be non-null for getDTMHandleFromNode!");

    if (node instanceof com.sun.org.apache.xml.internal.dtm.ref.DTMNodeProxy)
      return ((com.sun.org.apache.xml.internal.dtm.ref.DTMNodeProxy) node).getDTMNodeNumber();

    else
    {
      // Find the DOM2DTMs wrapped around this Document (if any)
      // and check whether they contain the Node in question.
      //
      // NOTE that since a DOM2DTM may represent a subtree rather
      // than a full document, we have to be prepared to check more
      // than one -- and there is no guarantee that we will find
      // one that contains ancestors or siblings of the node we're
      // seeking.
      //
      // %REVIEW% We could search for the one which contains this
      // node at the deepest level, and thus covers the widest
      // subtree, but that's going to entail additional work
      // checking more DTMs... and getHandleOfNode is not a
      // cheap operation in most implementations.
                        //
                        // TODO: %REVIEW% If overflow addressing, we may recheck a DTM
                        // already examined. Ouch. But with the increased number of DTMs,
                        // scanning back to check this is painful.
                        // POSSIBLE SOLUTIONS:
                        //   Generate a list of _unique_ DTM objects?
                        //   Have each DTM cache last DOM node search?
                        int max = m_dtms.length;
      for(int i = 0; i < max; i++)
        {
          DTM thisDTM=m_dtms[i];
          if((null != thisDTM) && thisDTM instanceof DOM2DTM)
          {
            int handle=((DOM2DTM)thisDTM).getHandleOfNode(node);
            if(handle!=DTM.NULL) return handle;
          }
         }

                        // Not found; generate a new DTM.
                        //
                        // %REVIEW% Is this really desirable, or should we return null
                        // and make folks explicitly instantiate from a DOMSource? The
                        // latter is more work but gives the caller the opportunity to
                        // explicitly add the DTM to a DTMManager... and thus to know when
                        // it can be discarded again, which is something we need to pay much
                        // more attention to. (Especially since only DTMs which are assigned
                        // to a manager can use the overflow addressing scheme.)
                        //
                        // %BUG% If the source node was a DOM2DTM$defaultNamespaceDeclarationNode
                        // and the DTM wasn't registered with this DTMManager, we will create
                        // a new DTM and _still_ not be able to find the node (since it will
                        // be resynthesized). Another reason to push hard on making all DTMs
                        // be managed DTMs.

                        // Since the real root of our tree may be a DocumentFragment, we need to
      // use getParent to find the root, instead of getOwnerDocument.  Otherwise
      // DOM2DTM#getHandleOfNode will be very unhappy.
      Node root = node;
      Node p = (root.getNodeType() == Node.ATTRIBUTE_NODE) ? ((org.w3c.dom.Attr)root).getOwnerElement() : root.getParentNode();
      for (; p != null; p = p.getParentNode())
      {
        root = p;
      }

      DOM2DTM dtm = (DOM2DTM) getDTM(new javax.xml.transform.dom.DOMSource(root),
                                                                                                                                                 false, null, true, true);

      int handle;

      if(node instanceof com.sun.org.apache.xml.internal.dtm.ref.dom2dtm.DOM2DTMdefaultNamespaceDeclarationNode)
      {
                                // Can't return the same node since it's unique to a specific DTM,
                                // but can return the equivalent node -- find the corresponding
                                // Document Element, then ask it for the xml: namespace decl.
                                handle=dtm.getHandleOfNode(((org.w3c.dom.Attr)node).getOwnerElement());
                                handle=dtm.getAttributeNode(handle,node.getNamespaceURI(),node.getLocalName());
      }
      else
                                handle = ((DOM2DTM)dtm).getHandleOfNode(node);

      if(DTM.NULL == handle)
        throw new RuntimeException(XMLMessages.createXMLMessage(XMLErrorResources.ER_COULD_NOT_RESOLVE_NODE, null)); //"Could not resolve the node to a handle!");

      return handle;
    }
  }

  /**
   * This method returns the SAX2 parser to use with the InputSource
   * obtained from this URI.
   * It may return null if any SAX2-conformant XML parser can be used,
   * or if getInputSource() will also return null. The parser must
   * be free for use (i.e., not currently in use for another parse().
   * After use of the parser is completed, the releaseXMLReader(XMLReader)
   * must be called.
   *
   * @param inputSource The value returned from the URIResolver.
   * @return  a SAX2 XMLReader to use to resolve the inputSource argument.
   *
   * @return non-null XMLReader reference ready to parse.
   */
  synchronized public XMLReader getXMLReader(Source inputSource)
  {

    try
    {
      XMLReader reader = (inputSource instanceof SAXSource)
                         ? ((SAXSource) inputSource).getXMLReader() : null;

      // If user did not supply a reader, ask for one from the reader manager
      if (null == reader) {
        if (m_readerManager == null) {
            m_readerManager = XMLReaderManager.getInstance(super.useServicesMechnism());
        }

        reader = m_readerManager.getXMLReader();
      }

      return reader;

    } catch (SAXException se) {
      throw new DTMException(se.getMessage(), se);
    }
  }

  /**
   * Indicates that the XMLReader object is no longer in use for the transform.
   *
   * Note that the getXMLReader method may return an XMLReader that was
   * specified on the SAXSource object by the application code.  Such a
   * reader should still be passed to releaseXMLReader, but the reader manager
   * will only re-use XMLReaders that it created.
   *
   * @param reader The XMLReader to be released.
   */
  synchronized public void releaseXMLReader(XMLReader reader) {
    if (m_readerManager != null) {
      m_readerManager.releaseXMLReader(reader);
    }
  }

  /**
   * Return the DTM object containing a representation of this node.
   *
   * @param nodeHandle DTM Handle indicating which node to retrieve
   *
   * @return a reference to the DTM object containing this node.
   */
  synchronized public DTM getDTM(int nodeHandle)
  {
    try
    {
      // Performance critical function.
      return m_dtms[nodeHandle >>> IDENT_DTM_NODE_BITS];
    }
    catch(java.lang.ArrayIndexOutOfBoundsException e)
    {
      if(nodeHandle==DTM.NULL)
                                return null;            // Accept as a special case.
      else
                                throw e;                // Programming error; want to know about it.
    }
  }

  /**
   * Given a DTM, find the ID number in the DTM tables which addresses
   * the start of the document. If overflow addressing is in use, other
   * DTM IDs may also be assigned to this DTM.
   *
   * @param dtm The DTM which (hopefully) contains this node.
   *
   * @return The DTM ID (as the high bits of a NodeHandle, not as our
   * internal index), or -1 if the DTM doesn't belong to this manager.
   */
  synchronized public int getDTMIdentity(DTM dtm)
  {
        // Shortcut using DTMDefaultBase's extension hooks
        // %REVIEW% Should the lookup be part of the basic DTM API?
        if(dtm instanceof DTMDefaultBase)
        {
                DTMDefaultBase dtmdb=(DTMDefaultBase)dtm;
                if(dtmdb.getManager()==this)
                        return dtmdb.getDTMIDs().elementAt(0);
                else
                        return -1;
        }

    int n = m_dtms.length;

    for (int i = 0; i < n; i++)
    {
      DTM tdtm = m_dtms[i];

      if (tdtm == dtm && m_dtm_offsets[i]==0)
        return i << IDENT_DTM_NODE_BITS;
    }

    return -1;
  }

  /**
   * Release the DTMManager's reference(s) to a DTM, making it unmanaged.
   * This is typically done as part of returning the DTM to the heap after
   * we're done with it.
   *
   * @param dtm the DTM to be released.
   *
   * @param shouldHardDelete If false, this call is a suggestion rather than an
   * order, and we may not actually release the DTM. This is intended to
   * support intelligent caching of documents... which is not implemented
   * in this version of the DTM manager.
   *
   * @return true if the DTM was released, false if shouldHardDelete was set
   * and we decided not to.
   */
  synchronized public boolean release(DTM dtm, boolean shouldHardDelete)
  {
    if(DEBUG)
    {
      System.out.println("Releasing "+
                         (shouldHardDelete ? "HARD" : "soft")+
                         " dtm="+
                         // Following shouldn't need a nodeHandle, but does...
                         // and doesn't seem to report the intended value
                         dtm.getDocumentBaseURI()
                         );
    }

    if (dtm instanceof SAX2DTM)
    {
      ((SAX2DTM) dtm).clearCoRoutine();
    }

                // Multiple DTM IDs may be assigned to a single DTM.
                // The Right Answer is to ask which (if it supports
                // extension, the DTM will need a list anyway). The
                // Wrong Answer, applied if the DTM can't help us,
                // is to linearly search them all; this may be very
                // painful.
                //
                // %REVIEW% Should the lookup move up into the basic DTM API?
                if(dtm instanceof DTMDefaultBase)
                {
                        com.sun.org.apache.xml.internal.utils.SuballocatedIntVector ids=((DTMDefaultBase)dtm).getDTMIDs();
                        for(int i=ids.size()-1;i>=0;--i)
                                m_dtms[ids.elementAt(i)>>>DTMManager.IDENT_DTM_NODE_BITS]=null;
                }
                else
                {
                        int i = getDTMIdentity(dtm);
                    if (i >= 0)
                        {
                                m_dtms[i >>> DTMManager.IDENT_DTM_NODE_BITS] = null;
                        }
                }

    dtm.documentRelease();
    return true;
  }

  /**
   * Method createDocumentFragment
   *
   *
   * NEEDSDOC (createDocumentFragment) @return
   */
  synchronized public DTM createDocumentFragment()
  {

    try
    {
      DocumentBuilderFactory dbf = FactoryImpl.getDOMFactory(super.useServicesMechnism());
      dbf.setNamespaceAware(true);

      DocumentBuilder db = dbf.newDocumentBuilder();
      Document doc = db.newDocument();
      Node df = doc.createDocumentFragment();

      return getDTM(new DOMSource(df), true, null, false, false);
    }
    catch (Exception e)
    {
      throw new DTMException(e);
    }
  }

  /**
   * NEEDSDOC Method createDTMIterator
   *
   *
   * NEEDSDOC @param whatToShow
   * NEEDSDOC @param filter
   * NEEDSDOC @param entityReferenceExpansion
   *
   * NEEDSDOC (createDTMIterator) @return
   */
  synchronized public DTMIterator createDTMIterator(int whatToShow, DTMFilter filter,
                                       boolean entityReferenceExpansion)
  {

    /** @todo: implement this com.sun.org.apache.xml.internal.dtm.DTMManager abstract method */
    return null;
  }

  /**
   * NEEDSDOC Method createDTMIterator
   *
   *
   * NEEDSDOC @param xpathString
   * NEEDSDOC @param presolver
   *
   * NEEDSDOC (createDTMIterator) @return
   */
  synchronized public DTMIterator createDTMIterator(String xpathString,
                                       PrefixResolver presolver)
  {

    /** @todo: implement this com.sun.org.apache.xml.internal.dtm.DTMManager abstract method */
    return null;
  }

  /**
   * NEEDSDOC Method createDTMIterator
   *
   *
   * NEEDSDOC @param node
   *
   * NEEDSDOC (createDTMIterator) @return
   */
  synchronized public DTMIterator createDTMIterator(int node)
  {

    /** @todo: implement this com.sun.org.apache.xml.internal.dtm.DTMManager abstract method */
    return null;
  }

  /**
   * NEEDSDOC Method createDTMIterator
   *
   *
   * NEEDSDOC @param xpathCompiler
   * NEEDSDOC @param pos
   *
   * NEEDSDOC (createDTMIterator) @return
   */
  synchronized public DTMIterator createDTMIterator(Object xpathCompiler, int pos)
  {

    /** @todo: implement this com.sun.org.apache.xml.internal.dtm.DTMManager abstract method */
    return null;
  }

  /**
   * return the expanded name table.
   *
   * NEEDSDOC @param dtm
   *
   * NEEDSDOC ($objectName$) @return
   */
  public ExpandedNameTable getExpandedNameTable(DTM dtm)
  {
    return m_expandedNameTable;
  }
}
