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

import java.util.Hashtable;
import java.util.Vector;
import javax.xml.transform.Source;
import javax.xml.transform.SourceLocator;

import org.apache.xml.dtm.*;
import org.apache.xml.dtm.ref.*;
import org.apache.xml.utils.StringVector;
import org.apache.xml.utils.IntVector;
import org.apache.xml.utils.FastStringBuffer;
import org.apache.xml.utils.IntStack;
import org.apache.xml.utils.SuballocatedIntVector;
import org.apache.xml.utils.SystemIDResolver;
import org.apache.xml.utils.WrappedRuntimeException;
import org.apache.xml.utils.XMLCharacterRecognizer;
import org.apache.xml.utils.XMLString;
import org.apache.xml.utils.XMLStringFactory;
import org.xml.sax.*;
import org.xml.sax.ext.*;

/**
 * This is a subclass of SAX2DTM which has been modified to meet the needs of
 * Result Tree Frameworks (RTFs). The differences are:
 *
 * 1) Multiple XML trees may be appended to the single DTM. This means
 * that the root node of each document is _not_ node 0. Some code has
 * had to be deoptimized to support this mode of operation, and an
 * explicit mechanism for obtaining the Node Handle of the root node
 * has been provided.
 *
 * 2) A stack of these documents is maintained, allowing us to "tail-prune" the
 * most recently added trees off the end of the DTM as stylesheet elements 
 * (and thus variable contexts) are exited.
 *
 * PLEASE NOTE that this class may be _heavily_ dependent upon the
 * internals of the SAX2DTM superclass, and must be maintained in
 * parallel with that code.  Arguably, they should be conditionals
 * within a single class... but they have deen separated for
 * performance reasons. (In fact, one could even argue about which is
 * the superclass and which is the subclass; the current arrangement
 * is as much about preserving stability of existing code during
 * development as anything else.)
 * 
 * %REVIEW% In fact, since the differences are so minor, I think it
 * may be possible/practical to fold them back into the base
 * SAX2DTM. Consider that as a future code-size optimization.
 * */
public class SAX2RTFDTM extends SAX2DTM
{
  /** Set true to monitor SAX events and similar diagnostic info. */
  private static final boolean DEBUG = false;
  
  /** Most recently started Document, or null if the DTM is empty.  */
  private int m_currentDocumentNode=NULL;
  
  /** Tail-pruning mark: Number of nodes in use */
  IntStack mark_size=new IntStack();
  /** Tail-pruning mark: Number of data items in use */
  IntStack mark_data_size=new IntStack();
  /** Tail-pruning mark: Number of size-of-data fields in use */
  IntStack mark_char_size=new IntStack();
  /** Tail-pruning mark: Number of dataOrQName slots in use */
  IntStack mark_doq_size=new IntStack();
  /** Tail-pruning mark: Number of namespace declaration sets in use
   * %REVIEW% I don't think number of NS sets is ever different from number
   * of NS elements. We can probabably reduce these to a single stack and save
   * some storage.
   * */
  IntStack mark_nsdeclset_size=new IntStack();
  /** Tail-pruning mark: Number of naespace declaration elements in use
   * %REVIEW% I don't think number of NS sets is ever different from number
   * of NS elements. We can probabably reduce these to a single stack and save
   * some storage.
   */
  IntStack mark_nsdeclelem_size=new IntStack();
  
  public SAX2RTFDTM(DTMManager mgr, Source source, int dtmIdentity,
                 DTMWSFilter whiteSpaceFilter,
                 XMLStringFactory xstringfactory,
                 boolean doIndexing)
  {
    super(mgr, source, dtmIdentity, whiteSpaceFilter, 
          xstringfactory, doIndexing);
          
    // NEVER track source locators for RTFs; they aren't meaningful. I think.
    // (If we did track them, we'd need to tail-prune these too.)
    m_useSourceLocationProperty=false; //org.apache.xalan.processor.TransformerFactoryImpl.m_source_location;
    m_sourceSystemId = (m_useSourceLocationProperty) ? new StringVector() : null;
 	m_sourceLine = (m_useSourceLocationProperty) ?  new IntVector() : null;
    m_sourceColumn = (m_useSourceLocationProperty) ?  new IntVector() : null;
    
  }
  
  /**
   * Given a DTM, find the owning document node. In the case of
   * SAX2RTFDTM, which may contain multiple documents, this returns
   * the <b>most recently started</b> document, or null if the DTM is
   * empty or no document is currently under construction.
   *
   * %REVIEW% Should we continue to report the most recent after
   * construction has ended? I think not, given that it may have been
   * tail-pruned.
   *
   *  @param nodeHandle the id of the node.
   *  @return int Node handle of Document node, or null if this DTM does not
   *  contain an "active" document.
   * */
  public int getDocument()
  {
    return makeNodeHandle(m_currentDocumentNode);
  }

  /**
   * Given a node handle, find the owning document node, using DTM semantics
   * (Document owns itself) rather than DOM semantics (Document has no owner).
   *
   * (I'm counting on the fact that getOwnerDocument() is implemented on top
   * of this call, in the superclass, to avoid having to rewrite that one.
   * Be careful if that code changes!)
   *
   * @param nodeHandle the id of the node.
   * @return int Node handle of owning document
   */
  public int getDocumentRoot(int nodeHandle)
  {
    for(int id=makeNodeIdentity(nodeHandle);
		id!=NULL;
		id=_parent(id))
		if(_type(id)==DTM.DOCUMENT_NODE)
  			return makeNodeHandle(id);

    return DTM.NULL; // Safety net; should never happen
  }
  
  /**
   * Given a node identifier, find the owning document node.  Unlike the DOM,
   * this considers the owningDocument of a Document to be itself. Note that
   * in shared DTMs this may not be zero.
   *
   * @param nodeIdentifier the id of the starting node.
   * @return int Node identifier of the root of this DTM tree
   */
  protected int _documentRoot(int nodeIdentifier)
  {
  	if(nodeIdentifier==NULL) return NULL;
  	
    for(int parent=_parent(nodeIdentifier);
    	parent!=NULL;
    	nodeIdentifier=parent,parent=_parent(nodeIdentifier))
    	;
    
    return nodeIdentifier;
  }

  /**
   * Receive notification of the beginning of a new RTF document.
   *
   * %REVIEW% Y'know, this isn't all that much of a deoptimization. We
   * might want to consider folding the start/endDocument changes back
   * into the main SAX2DTM so we don't have to expose so many fields
   * (even as Protected) and carry the additional code.
   *
   * @throws SAXException Any SAX exception, possibly
   *            wrapping another exception. 
   * @see org.xml.sax.ContentHandler#startDocument
   * */
  public void startDocument() throws SAXException
  {
    // Re-initialize the tree append process
    m_endDocumentOccured = false;
    m_prefixMappings = new java.util.Vector();
    m_contextIndexes = new IntStack();
    m_parents = new IntStack();
    
    m_currentDocumentNode=m_size;
    super.startDocument();
  }
  
  /**
   * Receive notification of the end of the document.
   *
   * %REVIEW% Y'know, this isn't all that much of a deoptimization. We
   * might want to consider folding the start/endDocument changes back
   * into the main SAX2DTM so we don't have to expose so many fields
   * (even as Protected).
   *
   * @throws SAXException Any SAX exception, possibly
   *            wrapping another exception.
   * @see org.xml.sax.ContentHandler#endDocument
   * */
  public void endDocument() throws SAXException
  {
    charactersFlush();

    m_nextsib.setElementAt(NULL,m_currentDocumentNode);

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

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

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

    m_currentDocumentNode= NULL; // no longer open
    m_endDocumentOccured = true;
  }
  

  /** "Tail-pruning" support for RTFs.
   * 
   * This function pushes information about the current size of the
   * DTM's data structures onto a stack, for use by popRewindMark()
   * (which see).
   * 
   * %REVIEW% I have no idea how to rewind m_elemIndexes. However,
   * RTFs will not be indexed, so I can simply panic if that case
   * arises. Hey, it works...
   * */
  public void pushRewindMark()
  {
    if(m_indexing || m_elemIndexes!=null) 
      throw new java.lang.NullPointerException("Coding error; Don't try to mark/rewind an indexed DTM");

    // Values from DTMDefaultBase
    // %REVIEW% Can the namespace stack sizes ever differ? If not, save space!
    mark_size.push(m_size);
    mark_nsdeclset_size.push( (m_namespaceDeclSets==null) ? 0 : m_namespaceDeclSets.size() );
    mark_nsdeclelem_size.push( (m_namespaceDeclSetElements==null) ? 0 : m_namespaceDeclSetElements.size() );
    
    // Values from SAX2DTM
    mark_data_size.push(m_data.size());
    mark_char_size.push(m_chars.size());
    mark_doq_size.push(m_dataOrQName.size());	
  }
  
  /** "Tail-pruning" support for RTFs.
   * 
   * This function pops the information previously saved by
   * pushRewindMark (which see) and uses it to discard all nodes added
   * to the DTM after that time. We expect that this will allow us to
   * reuse storage more effectively.
   * 
   * This is _not_ intended to be called while a document is still being
   * constructed -- only between endDocument and the next startDocument
   * 
   * %REVIEW% WARNING: This is the first use of some of the truncation
   * methods.  If Xalan blows up after this is called, that's a likely
   * place to check.
   * 
   * %REVIEW% Our original design for DTMs permitted them to share
   * string pools.  If there any risk that this might be happening, we
   * can _not_ rewind and recover the string storage. One solution
   * might to assert that DTMs used for RTFs Must Not take advantage
   * of that feature, but this seems excessively fragile. Another, much
   * less attractive, would be to just let them leak... Nah.
   * 
   * @return true if and only if the pop completely emptied the
   * RTF. That response is used when determining how to unspool
   * RTF-started-while-RTF-open situations.
   * */
  public boolean popRewindMark()
  {
    boolean top=mark_size.empty();
    
    m_size=top ? 0 : mark_size.pop();
    m_exptype.setSize(m_size);
    m_firstch.setSize(m_size);
    m_nextsib.setSize(m_size);
    m_prevsib.setSize(m_size);
    m_parent.setSize(m_size);

    m_elemIndexes=null;

    int ds= top ? 0 : mark_nsdeclset_size.pop();
    if (m_namespaceDeclSets!=null)
      m_namespaceDeclSets.setSize(ds);
      
    int ds1= top ? 0 : mark_nsdeclelem_size.pop();
    if (m_namespaceDeclSetElements!=null)
      m_namespaceDeclSetElements.setSize(ds1);
  
    // Values from SAX2DTM
    m_data.setSize(top ? 0 : mark_data_size.pop());
    m_chars.setLength(top ? 0 : mark_char_size.pop());
    m_dataOrQName.setSize(top ? 0 : mark_doq_size.pop());

    // Return true iff DTM now empty
    return m_size==0;
  }
  
  /** @return true if a DTM tree is currently under construction.
   * */
  public boolean isTreeIncomplete()
  {
  	return !m_endDocumentOccured;
  	
  }
}
