14c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson/*
24c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * Licensed to the Apache Software Foundation (ASF) under one
34c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * or more contributor license agreements. See the NOTICE file
44c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * distributed with this work for additional information
54c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * regarding copyright ownership. The ASF licenses this file
64c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * to you under the Apache License, Version 2.0 (the  "License");
74c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * you may not use this file except in compliance with the License.
84c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * You may obtain a copy of the License at
94c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson *
104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson *     http://www.apache.org/licenses/LICENSE-2.0
114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson *
124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * Unless required by applicable law or agreed to in writing, software
134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS,
144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * See the License for the specific language governing permissions and
164c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * limitations under the License.
174c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */
184c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson/*
194c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * $Id: XPathContext.java 524809 2007-04-02 15:51:51Z zongaro $
204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */
214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonpackage org.apache.xpath;
224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport java.lang.reflect.Method;
244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport java.util.Stack;
254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport java.util.Vector;
264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport java.util.HashMap;
274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport java.util.Iterator;
284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport javax.xml.transform.ErrorListener;
304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport javax.xml.transform.SourceLocator;
314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport javax.xml.transform.TransformerException;
324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport javax.xml.transform.URIResolver;
334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xalan.extensions.ExpressionContext;
354c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xalan.res.XSLMessages;
364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xml.dtm.Axis;
374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xml.dtm.DTM;
384c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xml.dtm.DTMFilter;
394c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xml.dtm.DTMIterator;
404c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xml.dtm.DTMManager;
414c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xml.dtm.DTMWSFilter;
424c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xml.dtm.ref.sax2dtm.SAX2RTFDTM;
434c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xml.utils.IntStack;
444c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xml.utils.NodeVector;
454c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xml.utils.ObjectStack;
464c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xml.utils.PrefixResolver;
474c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xml.utils.SAXSourceLocator;
484c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xml.utils.XMLString;
494c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xpath.axes.SubContextList;
504c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xpath.objects.XObject;
514c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xpath.objects.DTMXRTreeFrag;
524c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xpath.objects.XString;
534c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xpath.res.XPATHErrorResources;
544c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
554c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.xml.sax.XMLReader;
564c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
574c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson/**
584c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * Default class for the runtime execution context for XPath.
594c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson *
604c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * <p>This class extends DTMManager but does not directly implement it.</p>
614c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @xsl.usage advanced
624c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */
634c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonpublic class XPathContext extends DTMManager // implements ExpressionContext
644c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson{
654c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	IntStack m_last_pushed_rtfdtm=new IntStack();
664c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
674c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Stack of cached "reusable" DTMs for Result Tree Fragments.
684c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * This is a kluge to handle the problem of starting an RTF before
694c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * the old one is complete.
704c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
714c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * %REVIEW% I'm using a Vector rather than Stack so we can reuse
724c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * the DTMs if the problem occurs multiple times. I'm not sure that's
734c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * really a net win versus discarding the DTM and starting a new one...
744c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * but the retained RTF DTM will have been tail-pruned so should be small.
754c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
764c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  private Vector m_rtfdtm_stack=null;
774c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /** Index of currently active RTF DTM in m_rtfdtm_stack */
784c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  private int m_which_rtfdtm=-1;
794c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
804c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson /**
814c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Most recent "reusable" DTM for Global Result Tree Fragments. No stack is
824c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * required since we're never going to pop these.
834c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
844c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  private SAX2RTFDTM m_global_rtfdtm=null;
854c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
864c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
874c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * HashMap of cached the DTMXRTreeFrag objects, which are identified by DTM IDs.
884c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * The object are just wrappers for DTMs which are used in  XRTreeFrag.
894c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
904c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  private HashMap m_DTMXRTreeFrags = null;
914c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
924c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
934c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * state of the secure processing feature.
944c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
954c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  private boolean m_isSecureProcessing = false;
964c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
974c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
984c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Though XPathContext context extends
994c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * the DTMManager, it really is a proxy for this object, which
1004c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * is the real DTMManager.
1014c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
1024c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  protected DTMManager m_dtmManager = DTMManager.newInstance(
1034c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                   org.apache.xpath.objects.XMLStringFactoryImpl.getFactory());
1044c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1054c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
1064c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Return the DTMManager object.  Though XPathContext context extends
1074c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * the DTMManager, it really is a proxy for the real DTMManager.  If a
1084c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * caller needs to make a lot of calls to the DTMManager, it is faster
1094c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * if it gets the real one from this function.
1104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
1114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   public DTMManager getDTMManager()
1124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   {
1134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     return m_dtmManager;
1144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   }
1154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1164c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
1174c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Set the state of the secure processing feature
1184c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
1194c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public void setSecureProcessing(boolean flag)
1204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
1214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_isSecureProcessing = flag;
1224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
1234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
1254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Return the state of the secure processing feature
1264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
1274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public boolean isSecureProcessing()
1284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
1294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return m_isSecureProcessing;
1304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
1314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
1334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Get an instance of a DTM, loaded with the content from the
1344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * specified source.  If the unique flag is true, a new instance will
1354c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * always be returned.  Otherwise it is up to the DTMManager to return a
1364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * new instance or an instance that it already created and may be being used
1374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * by someone else.
1384c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * (I think more parameters will need to be added for error handling, and entity
1394c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * resolution).
1404c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
1414c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param source the specification of the source object, which may be null,
1424c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *               in which case it is assumed that node construction will take
1434c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *               by some other means.
1444c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param unique true if the returned DTM must be unique, probably because it
1454c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * is going to be mutated.
1464c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param wsfilter Enables filtering of whitespace nodes, and may be null.
1474c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param incremental true if the construction should try and be incremental.
1484c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param doIndexing true if the caller considers it worth it to use
1494c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *                   indexing schemes.
1504c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
1514c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return a non-null DTM reference.
1524c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
1534c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public DTM getDTM(javax.xml.transform.Source source, boolean unique,
1544c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                    DTMWSFilter wsfilter,
1554c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                    boolean incremental,
1564c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                    boolean doIndexing)
1574c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
1584c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return m_dtmManager.getDTM(source, unique, wsfilter,
1594c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                               incremental, doIndexing);
1604c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
1614c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1624c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
1634c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Get an instance of a DTM that "owns" a node handle.
1644c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
1654c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param nodeHandle the nodeHandle.
1664c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
1674c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return a non-null DTM reference.
1684c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
1694c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public DTM getDTM(int nodeHandle)
1704c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
1714c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return m_dtmManager.getDTM(nodeHandle);
1724c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
1734c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1744c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
1754c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Given a W3C DOM node, try and return a DTM handle.
1764c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Note: calling this may be non-optimal.
1774c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
1784c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param node Non-null reference to a DOM node.
1794c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
1804c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return a valid DTM handle.
1814c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
1824c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public int getDTMHandleFromNode(org.w3c.dom.Node node)
1834c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
1844c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return m_dtmManager.getDTMHandleFromNode(node);
1854c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
1864c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson//
1874c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson//
1884c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
1894c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * %TBD% Doc
1904c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
1914c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public int getDTMIdentity(DTM dtm)
1924c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
1934c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return m_dtmManager.getDTMIdentity(dtm);
1944c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
1954c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson//
1964c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
1974c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Creates an empty <code>DocumentFragment</code> object.
1984c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return A new <code>DocumentFragment handle</code>.
1994c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
2004c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public DTM createDocumentFragment()
2014c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
2024c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return m_dtmManager.createDocumentFragment();
2034c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
2044c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson//
2054c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
2064c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Release a DTM either to a lru pool, or completely remove reference.
2074c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * DTMs without system IDs are always hard deleted.
2084c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * State: experimental.
2094c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
2104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param dtm The DTM to be released.
2114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param shouldHardDelete True if the DTM should be removed no matter what.
2124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return true if the DTM was removed, false if it was put back in a lru pool.
2134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
2144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public boolean release(DTM dtm, boolean shouldHardDelete)
2154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
2164c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    // %REVIEW% If it's a DTM which may contain multiple Result Tree
2174c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    // Fragments, we can't discard it unless we know not only that it
2184c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    // is empty, but that the XPathContext itself is going away. So do
2194c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    // _not_ accept the request. (May want to do it as part of
2204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    // reset(), though.)
2214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    if(m_rtfdtm_stack!=null && m_rtfdtm_stack.contains(dtm))
2224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    {
2234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      return false;
2244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
2254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
2264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return m_dtmManager.release(dtm, shouldHardDelete);
2274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
2284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
2294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
2304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Create a new <code>DTMIterator</code> based on an XPath
2314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * <a href="http://www.w3.org/TR/xpath#NT-LocationPath>LocationPath</a> or
2324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * a <a href="http://www.w3.org/TR/xpath#NT-UnionExpr">UnionExpr</a>.
2334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
2344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param xpathCompiler ??? Somehow we need to pass in a subpart of the
2354c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * expression.  I hate to do this with strings, since the larger expression
2364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * has already been parsed.
2374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
2384c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param pos The position in the expression.
2394c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return The newly created <code>DTMIterator</code>.
2404c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
2414c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public DTMIterator createDTMIterator(Object xpathCompiler, int pos)
2424c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
2434c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return m_dtmManager.createDTMIterator(xpathCompiler, pos);
2444c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
2454c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson//
2464c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
2474c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Create a new <code>DTMIterator</code> based on an XPath
2484c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * <a href="http://www.w3.org/TR/xpath#NT-LocationPath>LocationPath</a> or
2494c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * a <a href="http://www.w3.org/TR/xpath#NT-UnionExpr">UnionExpr</a>.
2504c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
2514c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param xpathString Must be a valid string expressing a
2524c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * <a href="http://www.w3.org/TR/xpath#NT-LocationPath>LocationPath</a> or
2534c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * a <a href="http://www.w3.org/TR/xpath#NT-UnionExpr">UnionExpr</a>.
2544c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
2554c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param presolver An object that can resolve prefixes to namespace URLs.
2564c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
2574c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return The newly created <code>DTMIterator</code>.
2584c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
2594c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public DTMIterator createDTMIterator(String xpathString,
2604c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          PrefixResolver presolver)
2614c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
2624c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return m_dtmManager.createDTMIterator(xpathString, presolver);
2634c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
2644c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson//
2654c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
2664c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Create a new <code>DTMIterator</code> based only on a whatToShow and
2674c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * a DTMFilter.  The traversal semantics are defined as the descendant
2684c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * access.
2694c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
2704c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param whatToShow This flag specifies which node types may appear in
2714c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *   the logical view of the tree presented by the iterator. See the
2724c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *   description of <code>NodeFilter</code> for the set of possible
2734c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *   <code>SHOW_</code> values.These flags can be combined using
2744c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *   <code>OR</code>.
2754c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param filter The <code>NodeFilter</code> to be used with this
2764c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *   <code>TreeWalker</code>, or <code>null</code> to indicate no filter.
2774c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param entityReferenceExpansion The value of this flag determines
2784c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *   whether entity reference nodes are expanded.
2794c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
2804c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return The newly created <code>NodeIterator</code>.
2814c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
2824c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public DTMIterator createDTMIterator(int whatToShow,
2834c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          DTMFilter filter, boolean entityReferenceExpansion)
2844c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
2854c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return m_dtmManager.createDTMIterator(whatToShow, filter, entityReferenceExpansion);
2864c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
2874c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
2884c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
2894c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Create a new <code>DTMIterator</code> that holds exactly one node.
2904c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
2914c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param node The node handle that the DTMIterator will iterate to.
2924c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
2934c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return The newly created <code>DTMIterator</code>.
2944c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
2954c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public DTMIterator createDTMIterator(int node)
2964c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
2974c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    // DescendantIterator iter = new DescendantIterator();
2984c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    DTMIterator iter = new org.apache.xpath.axes.OneStepIteratorForward(Axis.SELF);
2994c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    iter.setRoot(node, this);
3004c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return iter;
3014c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    // return m_dtmManager.createDTMIterator(node);
3024c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
3034c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
3044c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
3054c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Create an XPathContext instance.  This is equivalent to calling
3064c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * the {@link #XPathContext(boolean)} constructor with the value
3074c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * <code>true</code>.
3084c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
3094c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public XPathContext() {
3104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    this(true);
3114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
3124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
3134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
3144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Create an XPathContext instance.
3154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param recursiveVarContext A <code>boolean</code> value indicating whether
3164c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *             the XPath context needs to support pushing of scopes for
3174c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *             variable resolution
3184c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
3194c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public XPathContext(boolean recursiveVarContext) {
3204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_prefixResolvers.push(null);
3214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_currentNodes.push(DTM.NULL);
3224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_currentExpressionNodes.push(DTM.NULL);
3234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_saxLocations.push(null);
3244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_variableStacks = recursiveVarContext ? new VariableStack()
3254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                                           : new VariableStack(1);
3264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
3274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
3284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
3294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Create an XPathContext instance.  This is equivalent to calling the
3304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * constructor {@link #XPathContext(java.lang.Object,boolean)} with the
3314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * value of the second parameter set to <code>true</code>.
3324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param owner Value that can be retrieved via the getOwnerObject() method.
3334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @see #getOwnerObject
3344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
3354c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public XPathContext(Object owner)
3364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
3374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    this(owner, true);
3384c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
3394c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
3404c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
3414c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Create an XPathContext instance.
3424c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param owner Value that can be retrieved via the getOwnerObject() method.
3434c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @see #getOwnerObject
3444c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param recursiveVarContext A <code>boolean</code> value indicating whether
3454c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *             the XPath context needs to support pushing of scopes for
3464c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *             variable resolution
3474c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
3484c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public XPathContext(Object owner, boolean recursiveVarContext) {
3494c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    this(recursiveVarContext);
3504c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_owner = owner;
3514c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    try {
3524c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      m_ownerGetErrorListener = m_owner.getClass().getMethod("getErrorListener", new Class[] {});
3534c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
3544c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    catch (NoSuchMethodException nsme) {}
3554c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
3564c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
3574c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
3584c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Reset for new run.
3594c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
3604c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public void reset()
3614c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
3624c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    releaseDTMXRTreeFrags();
3634c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	// These couldn't be disposed of earlier (see comments in release()); zap them now.
3644c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	if(m_rtfdtm_stack!=null)
3654c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  		 for (java.util.Enumeration e = m_rtfdtm_stack.elements() ; e.hasMoreElements() ;)
3664c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  		 	m_dtmManager.release((DTM)e.nextElement(), true);
3674c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
3684c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_rtfdtm_stack=null; // drop our references too
3694c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_which_rtfdtm=-1;
3704c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
3714c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    if(m_global_rtfdtm!=null)
3724c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  		 	m_dtmManager.release(m_global_rtfdtm,true);
3734c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_global_rtfdtm=null;
3744c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
3754c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
3764c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_dtmManager = DTMManager.newInstance(
3774c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                   org.apache.xpath.objects.XMLStringFactoryImpl.getFactory());
3784c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
3794c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_saxLocations.removeAllElements();
3804c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	m_axesIteratorStack.removeAllElements();
3814c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	m_contextNodeLists.removeAllElements();
3824c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	m_currentExpressionNodes.removeAllElements();
3834c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	m_currentNodes.removeAllElements();
3844c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	m_iteratorRoots.RemoveAllNoClear();
3854c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	m_predicatePos.removeAllElements();
3864c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	m_predicateRoots.RemoveAllNoClear();
3874c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	m_prefixResolvers.removeAllElements();
3884c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
3894c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	m_prefixResolvers.push(null);
3904c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_currentNodes.push(DTM.NULL);
3914c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_currentExpressionNodes.push(DTM.NULL);
3924c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_saxLocations.push(null);
3934c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
3944c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
3954c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /** The current stylesheet locator. */
3964c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  ObjectStack m_saxLocations = new ObjectStack(RECURSIONLIMIT);
3974c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
3984c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
3994c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Set the current locater in the stylesheet.
4004c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
4014c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param location The location within the stylesheet.
4024c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
4034c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public void setSAXLocator(SourceLocator location)
4044c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
4054c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_saxLocations.setTop(location);
4064c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
4074c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
4084c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
4094c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Set the current locater in the stylesheet.
4104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
4114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param location The location within the stylesheet.
4124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
4134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public void pushSAXLocator(SourceLocator location)
4144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
4154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_saxLocations.push(location);
4164c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
4174c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
4184c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
4194c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Push a slot on the locations stack so that setSAXLocator can be
4204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * repeatedly called.
4214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
4224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
4234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public void pushSAXLocatorNull()
4244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
4254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_saxLocations.push(null);
4264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
4274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
4284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
4294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
4304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Pop the current locater.
4314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
4324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public void popSAXLocator()
4334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
4344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_saxLocations.pop();
4354c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
4364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
4374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
4384c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Get the current locater in the stylesheet.
4394c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
4404c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return The location within the stylesheet, or null if not known.
4414c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
4424c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public SourceLocator getSAXLocator()
4434c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
4444c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return (SourceLocator) m_saxLocations.peek();
4454c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
4464c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
4474c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /** The owner context of this XPathContext.  In the case of XSLT, this will be a
4484c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *  Transformer object.
4494c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
4504c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  private Object m_owner;
4514c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
4524c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /** The owner context of this XPathContext.  In the case of XSLT, this will be a
4534c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *  Transformer object.
4544c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
4554c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  private Method m_ownerGetErrorListener;
4564c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
4574c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
4584c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Get the "owner" context of this context, which should be,
4594c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * in the case of XSLT, the Transformer object.  This is needed
4604c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * so that XSLT functions can get the Transformer.
4614c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return The owner object passed into the constructor, or null.
4624c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
4634c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public Object getOwnerObject()
4644c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
4654c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return m_owner;
4664c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
4674c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
4684c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  // ================ VarStack ===================
4694c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
4704c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
4714c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * The stack of Variable stacks.  A VariableStack will be
4724c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * pushed onto this stack for each template invocation.
4734c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
4744c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  private VariableStack m_variableStacks;
4754c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
4764c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
4774c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Get the variable stack, which is in charge of variables and
4784c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * parameters.
4794c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
4804c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return the variable stack, which should not be null.
4814c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
4824c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final VariableStack getVarStack()
4834c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
4844c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return m_variableStacks;
4854c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
4864c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
4874c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
4884c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Get the variable stack, which is in charge of variables and
4894c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * parameters.
4904c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
4914c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param varStack non-null reference to the variable stack.
4924c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
4934c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final void setVarStack(VariableStack varStack)
4944c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
4954c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_variableStacks = varStack;
4964c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
4974c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
4984c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  // ================ SourceTreeManager ===================
4994c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
5004c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /** The source tree manager, which associates Source objects to source
5014c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *  tree nodes. */
5024c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  private SourceTreeManager m_sourceTreeManager = new SourceTreeManager();
5034c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
5044c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
5054c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Get the SourceTreeManager associated with this execution context.
5064c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
5074c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return the SourceTreeManager associated with this execution context.
5084c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
5094c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final SourceTreeManager getSourceTreeManager()
5104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
5114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return m_sourceTreeManager;
5124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
5134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
5144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
5154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Set the SourceTreeManager associated with this execution context.
5164c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
5174c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param mgr the SourceTreeManager to be associated with this
5184c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *        execution context.
5194c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
5204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public void setSourceTreeManager(SourceTreeManager mgr)
5214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
5224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_sourceTreeManager = mgr;
5234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
5244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
5254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  // =================================================
5264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
5274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /** The ErrorListener where errors and warnings are to be reported.   */
5284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  private ErrorListener m_errorListener;
5294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
5304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /** A default ErrorListener in case our m_errorListener was not specified and our
5314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *  owner either does not have an ErrorListener or has a null one.
5324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
5334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  private ErrorListener m_defaultErrorListener;
5344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
5354c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
5364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Get the ErrorListener where errors and warnings are to be reported.
5374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
5384c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return A non-null ErrorListener reference.
5394c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
5404c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final ErrorListener getErrorListener()
5414c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
5424c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
5434c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    if (null != m_errorListener)
5444c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        return m_errorListener;
5454c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
5464c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    ErrorListener retval = null;
5474c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
5484c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    try {
5494c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      if (null != m_ownerGetErrorListener)
5504c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        retval = (ErrorListener) m_ownerGetErrorListener.invoke(m_owner, new Object[] {});
5514c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
5524c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    catch (Exception e) {}
5534c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
5544c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    if (null == retval)
5554c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    {
5564c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      if (null == m_defaultErrorListener)
5574c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        m_defaultErrorListener = new org.apache.xml.utils.DefaultErrorHandler();
5584c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      retval = m_defaultErrorListener;
5594c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
5604c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
5614c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return retval;
5624c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
5634c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
5644c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
5654c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Set the ErrorListener where errors and warnings are to be reported.
5664c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
5674c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param listener A non-null ErrorListener reference.
5684c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
5694c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public void setErrorListener(ErrorListener listener) throws IllegalArgumentException
5704c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
5714c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    if (listener == null)
5724c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      throw new IllegalArgumentException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NULL_ERROR_HANDLER, null)); //"Null error handler");
5734c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_errorListener = listener;
5744c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
5754c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
5764c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
5774c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  // =================================================
5784c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
5794c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /** The TrAX URI Resolver for resolving URIs from the document(...)
5804c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *  function to source tree nodes.  */
5814c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  private URIResolver m_uriResolver;
5824c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
5834c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
5844c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Get the URIResolver associated with this execution context.
5854c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
5864c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return a URI resolver, which may be null.
5874c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
5884c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final URIResolver getURIResolver()
5894c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
5904c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return m_uriResolver;
5914c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
5924c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
5934c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
5944c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Set the URIResolver associated with this execution context.
5954c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
5964c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param resolver the URIResolver to be associated with this
5974c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *        execution context, may be null to clear an already set resolver.
5984c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
5994c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public void setURIResolver(URIResolver resolver)
6004c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
6014c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_uriResolver = resolver;
6024c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
6034c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
6044c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  // =================================================
6054c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
6064c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /** The reader of the primary source tree.    */
6074c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public XMLReader m_primaryReader;
6084c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
6094c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
6104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Get primary XMLReader associated with this execution context.
6114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
6124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return The reader of the primary source tree.
6134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
6144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final XMLReader getPrimaryReader()
6154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
6164c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return m_primaryReader;
6174c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
6184c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
6194c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
6204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Set primary XMLReader associated with this execution context.
6214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
6224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param reader The reader of the primary source tree.
6234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
6244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public void setPrimaryReader(XMLReader reader)
6254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
6264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_primaryReader = reader;
6274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
6284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
6294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  // =================================================
6304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
6314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
6324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /** Misnamed string manager for XPath messages.  */
6334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  // private static XSLMessages m_XSLMessages = new XSLMessages();
6344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
6354c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
6364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Tell the user of an assertion error, and probably throw an
6374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * exception.
6384c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
6394c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param b  If false, a TransformerException will be thrown.
6404c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param msg The assertion message, which should be informative.
6414c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
6424c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @throws javax.xml.transform.TransformerException if b is false.
6434c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
6444c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  private void assertion(boolean b, String msg) throws javax.xml.transform.TransformerException
6454c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
6464c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    if (!b)
6474c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    {
6484c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      ErrorListener errorHandler = getErrorListener();
6494c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
6504c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      if (errorHandler != null)
6514c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      {
6524c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        errorHandler.fatalError(
6534c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          new TransformerException(
6544c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            XSLMessages.createMessage(
6554c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson              XPATHErrorResources.ER_INCORRECT_PROGRAMMER_ASSERTION,
6564c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson              new Object[]{ msg }), (SAXSourceLocator)this.getSAXLocator()));
6574c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      }
6584c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
6594c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
6604c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
6614c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  //==========================================================
6624c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  // SECTION: Execution context state tracking
6634c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  //==========================================================
6644c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
6654c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
6664c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * The current context node list.
6674c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
6684c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  private Stack m_contextNodeLists = new Stack();
6694c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
6704c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public Stack getContextNodeListsStack() { return m_contextNodeLists; }
6714c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public void setContextNodeListsStack(Stack s) { m_contextNodeLists = s; }
6724c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
6734c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
6744c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Get the current context node list.
6754c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
6764c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return  the <a href="http://www.w3.org/TR/xslt#dt-current-node-list">current node list</a>,
6774c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * also refered to here as a <term>context node list</term>.
6784c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
6794c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final DTMIterator getContextNodeList()
6804c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
6814c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
6824c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    if (m_contextNodeLists.size() > 0)
6834c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      return (DTMIterator) m_contextNodeLists.peek();
6844c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    else
6854c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      return null;
6864c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
6874c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
6884c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
6894c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Set the current context node list.
6904c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
6914c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param nl the <a href="http://www.w3.org/TR/xslt#dt-current-node-list">current node list</a>,
6924c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * also refered to here as a <term>context node list</term>.
6934c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @xsl.usage internal
6944c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
6954c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final void pushContextNodeList(DTMIterator nl)
6964c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
6974c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_contextNodeLists.push(nl);
6984c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
6994c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
7004c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
7014c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Pop the current context node list.
7024c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @xsl.usage internal
7034c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
7044c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final void popContextNodeList()
7054c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
7064c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	if(m_contextNodeLists.isEmpty())
7074c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	  System.err.println("Warning: popContextNodeList when stack is empty!");
7084c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	else
7094c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      m_contextNodeLists.pop();
7104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
7114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
7124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
7134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * The ammount to use for stacks that record information during the
7144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * recursive execution.
7154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
7164c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public static final int RECURSIONLIMIT = (1024*4);
7174c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
7184c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /** The stack of <a href="http://www.w3.org/TR/xslt#dt-current-node">current node</a> objects.
7194c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *  Not to be confused with the current node list.  %REVIEW% Note that there
7204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *  are no bounds check and resize for this stack, so if it is blown, it's all
7214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *  over.  */
7224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  private IntStack m_currentNodes = new IntStack(RECURSIONLIMIT);
7234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
7244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson//  private NodeVector m_currentNodes = new NodeVector();
7254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
7264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public IntStack getCurrentNodeStack() {return m_currentNodes; }
7274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public void setCurrentNodeStack(IntStack nv) { m_currentNodes = nv; }
7284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
7294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
7304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Get the current context node.
7314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
7324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return the <a href="http://www.w3.org/TR/xslt#dt-current-node">current node</a>.
7334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
7344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final int getCurrentNode()
7354c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
7364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return m_currentNodes.peek();
7374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
7384c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
7394c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
7404c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Set the current context node and expression node.
7414c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
7424c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param cn the <a href="http://www.w3.org/TR/xslt#dt-current-node">current node</a>.
7434c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param en the sub-expression context node.
7444c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
7454c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final void pushCurrentNodeAndExpression(int cn, int en)
7464c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
7474c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_currentNodes.push(cn);
7484c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_currentExpressionNodes.push(cn);
7494c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
7504c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
7514c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
7524c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Set the current context node.
7534c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
7544c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final void popCurrentNodeAndExpression()
7554c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
7564c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_currentNodes.quickPop(1);
7574c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_currentExpressionNodes.quickPop(1);
7584c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
7594c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
7604c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
7614c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Push the current context node, expression node, and prefix resolver.
7624c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
7634c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param cn the <a href="http://www.w3.org/TR/xslt#dt-current-node">current node</a>.
7644c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param en the sub-expression context node.
7654c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param nc the namespace context (prefix resolver.
7664c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
7674c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final void pushExpressionState(int cn, int en, PrefixResolver nc)
7684c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
7694c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_currentNodes.push(cn);
7704c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_currentExpressionNodes.push(cn);
7714c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_prefixResolvers.push(nc);
7724c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
7734c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
7744c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
7754c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Pop the current context node, expression node, and prefix resolver.
7764c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
7774c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final void popExpressionState()
7784c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
7794c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_currentNodes.quickPop(1);
7804c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_currentExpressionNodes.quickPop(1);
7814c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_prefixResolvers.pop();
7824c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
7834c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
7844c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
7854c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
7864c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
7874c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Set the current context node.
7884c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
7894c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param n the <a href="http://www.w3.org/TR/xslt#dt-current-node">current node</a>.
7904c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
7914c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final void pushCurrentNode(int n)
7924c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
7934c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_currentNodes.push(n);
7944c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
7954c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
7964c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
7974c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Pop the current context node.
7984c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
7994c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final void popCurrentNode()
8004c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
8014c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_currentNodes.quickPop(1);
8024c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
8034c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
8044c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
8054c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Set the current predicate root.
8064c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
8074c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final void pushPredicateRoot(int n)
8084c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
8094c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_predicateRoots.push(n);
8104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
8114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
8124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
8134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Pop the current predicate root.
8144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
8154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final void popPredicateRoot()
8164c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
8174c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_predicateRoots.popQuick();
8184c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
8194c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
8204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
8214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Get the current predicate root.
8224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
8234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final int getPredicateRoot()
8244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
8254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return m_predicateRoots.peepOrNull();
8264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
8274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
8284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
8294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Set the current location path iterator root.
8304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
8314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final void pushIteratorRoot(int n)
8324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
8334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_iteratorRoots.push(n);
8344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
8354c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
8364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
8374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Pop the current location path iterator root.
8384c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
8394c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final void popIteratorRoot()
8404c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
8414c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_iteratorRoots.popQuick();
8424c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
8434c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
8444c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
8454c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Get the current location path iterator root.
8464c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
8474c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final int getIteratorRoot()
8484c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
8494c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return m_iteratorRoots.peepOrNull();
8504c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
8514c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
8524c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /** A stack of the current sub-expression nodes.  */
8534c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  private NodeVector m_iteratorRoots = new NodeVector();
8544c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
8554c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /** A stack of the current sub-expression nodes.  */
8564c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  private NodeVector m_predicateRoots = new NodeVector();
8574c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
8584c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /** A stack of the current sub-expression nodes.  */
8594c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  private IntStack m_currentExpressionNodes = new IntStack(RECURSIONLIMIT);
8604c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
8614c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
8624c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public IntStack getCurrentExpressionNodeStack() { return m_currentExpressionNodes; }
8634c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public void setCurrentExpressionNodeStack(IntStack nv) { m_currentExpressionNodes = nv; }
8644c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
8654c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  private IntStack m_predicatePos = new IntStack();
8664c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
8674c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final int getPredicatePos()
8684c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
8694c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return m_predicatePos.peek();
8704c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
8714c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
8724c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final void pushPredicatePos(int n)
8734c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
8744c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_predicatePos.push(n);
8754c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
8764c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
8774c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final void popPredicatePos()
8784c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
8794c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_predicatePos.pop();
8804c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
8814c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
8824c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
8834c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Get the current node that is the expression's context (i.e. for current() support).
8844c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
8854c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return The current sub-expression node.
8864c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
8874c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final int getCurrentExpressionNode()
8884c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
8894c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return m_currentExpressionNodes.peek();
8904c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
8914c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
8924c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
8934c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Set the current node that is the expression's context (i.e. for current() support).
8944c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
8954c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param n The sub-expression node to be current.
8964c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
8974c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final void pushCurrentExpressionNode(int n)
8984c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
8994c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_currentExpressionNodes.push(n);
9004c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
9014c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
9024c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
9034c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Pop the current node that is the expression's context
9044c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * (i.e. for current() support).
9054c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
9064c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final void popCurrentExpressionNode()
9074c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
9084c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_currentExpressionNodes.quickPop(1);
9094c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
9104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
9114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  private ObjectStack m_prefixResolvers
9124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                                   = new ObjectStack(RECURSIONLIMIT);
9134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
9144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
9154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Get the current namespace context for the xpath.
9164c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
9174c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return the current prefix resolver for resolving prefixes to
9184c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *         namespace URLs.
9194c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
9204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final PrefixResolver getNamespaceContext()
9214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
9224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return (PrefixResolver) m_prefixResolvers.peek();
9234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
9244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
9254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
9264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Get the current namespace context for the xpath.
9274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
9284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param pr the prefix resolver to be used for resolving prefixes to
9294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *         namespace URLs.
9304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
9314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final void setNamespaceContext(PrefixResolver pr)
9324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
9334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_prefixResolvers.setTop(pr);
9344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
9354c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
9364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
9374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Push a current namespace context for the xpath.
9384c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
9394c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param pr the prefix resolver to be used for resolving prefixes to
9404c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *         namespace URLs.
9414c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
9424c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final void pushNamespaceContext(PrefixResolver pr)
9434c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
9444c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_prefixResolvers.push(pr);
9454c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
9464c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
9474c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
9484c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Just increment the namespace contest stack, so that setNamespaceContext
9494c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * can be used on the slot.
9504c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
9514c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final void pushNamespaceContextNull()
9524c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
9534c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_prefixResolvers.push(null);
9544c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
9554c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
9564c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
9574c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Pop the current namespace context for the xpath.
9584c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
9594c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final void popNamespaceContext()
9604c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
9614c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_prefixResolvers.pop();
9624c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
9634c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
9644c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  //==========================================================
9654c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  // SECTION: Current TreeWalker contexts (for internal use)
9664c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  //==========================================================
9674c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
9684c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
9694c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Stack of AxesIterators.
9704c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
9714c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  private Stack m_axesIteratorStack = new Stack();
9724c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
9734c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public Stack getAxesIteratorStackStacks() { return m_axesIteratorStack; }
9744c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public void setAxesIteratorStackStacks(Stack s) { m_axesIteratorStack = s; }
9754c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
9764c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
9774c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Push a TreeWalker on the stack.
9784c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
9794c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param iter A sub-context AxesWalker.
9804c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @xsl.usage internal
9814c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
9824c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final void pushSubContextList(SubContextList iter)
9834c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
9844c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_axesIteratorStack.push(iter);
9854c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
9864c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
9874c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
9884c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Pop the last pushed axes iterator.
9894c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @xsl.usage internal
9904c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
9914c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final void popSubContextList()
9924c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
9934c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_axesIteratorStack.pop();
9944c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
9954c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
9964c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
9974c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Get the current axes iterator, or return null if none.
9984c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
9994c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return the sub-context node list.
10004c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @xsl.usage internal
10014c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
10024c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public SubContextList getSubContextList()
10034c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
10044c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return m_axesIteratorStack.isEmpty()
10054c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson           ? null : (SubContextList) m_axesIteratorStack.peek();
10064c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
10074c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
10084c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
10094c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Get the <a href="http://www.w3.org/TR/xslt#dt-current-node-list">current node list</a>
10104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * as defined by the XSLT spec.
10114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
10124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return the <a href="http://www.w3.org/TR/xslt#dt-current-node-list">current node list</a>.
10134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @xsl.usage internal
10144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
10154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
10164c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public org.apache.xpath.axes.SubContextList getCurrentNodeList()
10174c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
10184c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return m_axesIteratorStack.isEmpty()
10194c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson           ? null : (SubContextList) m_axesIteratorStack.elementAt(0);
10204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
10214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  //==========================================================
10224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  // SECTION: Implementation of ExpressionContext interface
10234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  //==========================================================
10244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
10254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
10264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Get the current context node.
10274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return The current context node.
10284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
10294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final int getContextNode()
10304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
10314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return this.getCurrentNode();
10324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
10334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
10344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
10354c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Get the current context node list.
10364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return An iterator for the current context list, as
10374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * defined in XSLT.
10384c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
10394c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public final DTMIterator getContextNodes()
10404c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
10414c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
10424c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    try
10434c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    {
10444c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      DTMIterator cnl = getContextNodeList();
10454c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
10464c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      if (null != cnl)
10474c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        return cnl.cloneWithReset();
10484c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      else
10494c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        return null;  // for now... this might ought to be an empty iterator.
10504c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
10514c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    catch (CloneNotSupportedException cnse)
10524c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    {
10534c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      return null;  // error reporting?
10544c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
10554c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
10564c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
10574c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  XPathExpressionContext expressionContext = new XPathExpressionContext();
10584c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
10594c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
10604c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * The the expression context for extensions for this context.
10614c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
10624c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return An object that implements the ExpressionContext.
10634c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
10644c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public ExpressionContext getExpressionContext()
10654c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
10664c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return expressionContext;
10674c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
10684c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
10694c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public class XPathExpressionContext implements ExpressionContext
10704c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
10714c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    /**
10724c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * Return the XPathContext associated with this XPathExpressionContext.
10734c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * Extensions should use this judiciously and only when special processing
10744c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * requirements cannot be met another way.  Consider requesting an enhancement
10754c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * to the ExpressionContext interface to avoid having to call this method.
10764c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * @return the XPathContext associated with this XPathExpressionContext.
10774c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     */
10784c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     public XPathContext getXPathContext()
10794c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     {
10804c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson       return XPathContext.this;
10814c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     }
10824c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
10834c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    /**
10844c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * Return the DTMManager object.  Though XPathContext context extends
10854c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * the DTMManager, it really is a proxy for the real DTMManager.  If a
10864c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * caller needs to make a lot of calls to the DTMManager, it is faster
10874c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * if it gets the real one from this function.
10884c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     */
10894c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     public DTMManager getDTMManager()
10904c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     {
10914c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson       return m_dtmManager;
10924c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     }
10934c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
10944c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    /**
10954c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * Get the current context node.
10964c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * @return The current context node.
10974c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     */
10984c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    public org.w3c.dom.Node getContextNode()
10994c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    {
11004c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      int context = getCurrentNode();
11014c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
11024c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      return getDTM(context).getNode(context);
11034c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
11044c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
11054c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    /**
11064c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * Get the current context node list.
11074c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * @return An iterator for the current context list, as
11084c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * defined in XSLT.
11094c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     */
11104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    public org.w3c.dom.traversal.NodeIterator getContextNodes()
11114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    {
11124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      return new org.apache.xml.dtm.ref.DTMNodeIterator(getContextNodeList());
11134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
11144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
11154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    /**
11164c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * Get the error listener.
11174c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * @return The registered error listener.
11184c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     */
11194c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    public ErrorListener getErrorListener()
11204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    {
11214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      return XPathContext.this.getErrorListener();
11224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
11234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
11244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    /**
11254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * Get the value of a node as a number.
11264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * @param n Node to be converted to a number.  May be null.
11274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * @return value of n as a number.
11284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     */
11294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    public double toNumber(org.w3c.dom.Node n)
11304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    {
11314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      // %REVIEW% You can't get much uglier than this...
11324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      int nodeHandle = getDTMHandleFromNode(n);
11334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      DTM dtm = getDTM(nodeHandle);
11344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      XString xobj = (XString)dtm.getStringValue(nodeHandle);
11354c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      return xobj.num();
11364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
11374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
11384c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    /**
11394c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * Get the value of a node as a string.
11404c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * @param n Node to be converted to a string.  May be null.
11414c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * @return value of n as a string, or an empty string if n is null.
11424c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     */
11434c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    public String toString(org.w3c.dom.Node n)
11444c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    {
11454c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      // %REVIEW% You can't get much uglier than this...
11464c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      int nodeHandle = getDTMHandleFromNode(n);
11474c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      DTM dtm = getDTM(nodeHandle);
11484c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      XMLString strVal = dtm.getStringValue(nodeHandle);
11494c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      return strVal.toString();
11504c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
11514c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
11524c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    /**
11534c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * Get a variable based on it's qualified name.
11544c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * @param qname The qualified name of the variable.
11554c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * @return The evaluated value of the variable.
11564c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * @throws javax.xml.transform.TransformerException
11574c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     */
11584c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
11594c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    public final XObject getVariableOrParam(org.apache.xml.utils.QName qname)
11604c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson              throws javax.xml.transform.TransformerException
11614c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    {
11624c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      return m_variableStacks.getVariableOrParam(XPathContext.this, qname);
11634c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
11644c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
11654c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
11664c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
11674c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson /**
11684c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Get a DTM to be used as a container for a global Result Tree
11694c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Fragment. This will always be an instance of (derived from? equivalent to?)
11704c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * SAX2DTM, since each RTF is constructed by temporarily redirecting our SAX
11714c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * output to it. It may be a single DTM containing for multiple fragments,
11724c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * if the implementation supports that.
11734c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
11744c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Note: The distinction between this method and getRTFDTM() is that the latter
11754c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * allocates space from the dynamic variable stack (m_rtfdtm_stack), which may
11764c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * be pruned away again as the templates which defined those variables are exited.
11774c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Global variables may be bound late (see XUnresolvedVariable), and never want to
11784c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * be discarded, hence we need to allocate them separately and don't actually need
11794c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * a stack to track them.
11804c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
11814c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return a non-null DTM reference.
11824c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
11834c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public DTM getGlobalRTFDTM()
11844c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
11854c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	// We probably should _NOT_ be applying whitespace filtering at this stage!
11864c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	//
11874c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	// Some magic has been applied in DTMManagerDefault to recognize this set of options
11884c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	// and generate an instance of DTM which can contain multiple documents
11894c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	// (SAX2RTFDTM). Perhaps not the optimal way of achieving that result, but
11904c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	// I didn't want to change the manager API at this time, or expose
11914c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	// too many dependencies on its internals. (Ideally, I'd like to move
11924c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	// isTreeIncomplete all the way up to DTM, so we wouldn't need to explicitly
11934c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	// specify the subclass here.)
11944c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
11954c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	// If it doesn't exist, or if the one already existing is in the middle of
11964c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	// being constructed, we need to obtain a new DTM to write into. I'm not sure
11974c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	// the latter will ever arise, but I'd rather be just a bit paranoid..
11984c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	if( m_global_rtfdtm==null || m_global_rtfdtm.isTreeIncomplete() )
11994c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	{
12004c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  		m_global_rtfdtm=(SAX2RTFDTM)m_dtmManager.getDTM(null,true,null,false,false);
12014c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	}
12024c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return m_global_rtfdtm;
12034c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
12044c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
12054c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
12064c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
12074c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
12084c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
12094c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Get a DTM to be used as a container for a dynamic Result Tree
12104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Fragment. This will always be an instance of (derived from? equivalent to?)
12114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * SAX2DTM, since each RTF is constructed by temporarily redirecting our SAX
12124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * output to it. It may be a single DTM containing for multiple fragments,
12134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * if the implementation supports that.
12144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
12154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return a non-null DTM reference.
12164c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
12174c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public DTM getRTFDTM()
12184c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
12194c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	SAX2RTFDTM rtfdtm;
12204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
12214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	// We probably should _NOT_ be applying whitespace filtering at this stage!
12224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	//
12234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	// Some magic has been applied in DTMManagerDefault to recognize this set of options
12244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	// and generate an instance of DTM which can contain multiple documents
12254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	// (SAX2RTFDTM). Perhaps not the optimal way of achieving that result, but
12264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	// I didn't want to change the manager API at this time, or expose
12274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	// too many dependencies on its internals. (Ideally, I'd like to move
12284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	// isTreeIncomplete all the way up to DTM, so we wouldn't need to explicitly
12294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	// specify the subclass here.)
12304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
12314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	if(m_rtfdtm_stack==null)
12324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	{
12334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson		m_rtfdtm_stack=new Vector();
12344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  		rtfdtm=(SAX2RTFDTM)m_dtmManager.getDTM(null,true,null,false,false);
12354c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_rtfdtm_stack.addElement(rtfdtm);
12364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson		++m_which_rtfdtm;
12374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	}
12384c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	else if(m_which_rtfdtm<0)
12394c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	{
12404c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson		rtfdtm=(SAX2RTFDTM)m_rtfdtm_stack.elementAt(++m_which_rtfdtm);
12414c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	}
12424c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	else
12434c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	{
12444c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson		rtfdtm=(SAX2RTFDTM)m_rtfdtm_stack.elementAt(m_which_rtfdtm);
12454c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
12464c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	  	// It might already be under construction -- the classic example would be
12474c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 	 	// an xsl:variable which uses xsl:call-template as part of its value. To
12484c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  		// handle this recursion, we have to start a new RTF DTM, pushing the old
12494c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  		// one onto a stack so we can return to it. This is not as uncommon a case
12504c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  		// as we might wish, unfortunately, as some folks insist on coding XSLT
12514c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  		// as if it were a procedural language...
12524c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  		if(rtfdtm.isTreeIncomplete())
12534c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	  	{
12544c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	  		if(++m_which_rtfdtm < m_rtfdtm_stack.size())
12554c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson				rtfdtm=(SAX2RTFDTM)m_rtfdtm_stack.elementAt(m_which_rtfdtm);
12564c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	  		else
12574c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	  		{
12584c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson		  		rtfdtm=(SAX2RTFDTM)m_dtmManager.getDTM(null,true,null,false,false);
12594c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          m_rtfdtm_stack.addElement(rtfdtm);
12604c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	  		}
12614c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 	 	}
12624c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	}
12634c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
12644c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return rtfdtm;
12654c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
12664c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
12674c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /** Push the RTFDTM's context mark, to allows discarding RTFs added after this
12684c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * point. (If it doesn't exist we don't push, since we might still be able to
12694c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * get away with not creating it. That requires that excessive pops be harmless.)
12704c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * */
12714c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public void pushRTFContext()
12724c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
12734c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	m_last_pushed_rtfdtm.push(m_which_rtfdtm);
12744c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	if(null!=m_rtfdtm_stack)
12754c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	  	((SAX2RTFDTM)(getRTFDTM())).pushRewindMark();
12764c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
12774c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
12784c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /** Pop the RTFDTM's context mark. This discards any RTFs added after the last
12794c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * mark was set.
12804c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
12814c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * If there is no RTF DTM, there's nothing to pop so this
12824c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * becomes a no-op. If pushes were issued before this was called, we count on
12834c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * the fact that popRewindMark is defined such that overpopping just resets
12844c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * to empty.
12854c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
12864c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Complicating factor: We need to handle the case of popping back to a previous
12874c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * RTF DTM, if one of the weird produce-an-RTF-to-build-an-RTF cases arose.
12884c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Basically: If pop says this DTM is now empty, then return to the previous
12894c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * if one exists, in whatever state we left it in. UGLY, but hopefully the
12904c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * situation which forces us to consider this will arise exceedingly rarely.
12914c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * */
12924c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public void popRTFContext()
12934c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
12944c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	int previous=m_last_pushed_rtfdtm.pop();
12954c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	if(null==m_rtfdtm_stack)
12964c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  		return;
12974c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
12984c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	if(m_which_rtfdtm==previous)
12994c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	{
13004c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  		if(previous>=0) // guard against none-active
13014c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  		{
13024c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	  		boolean isEmpty=((SAX2RTFDTM)(m_rtfdtm_stack.elementAt(previous))).popRewindMark();
13034c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  		}
13044c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	}
13054c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	else while(m_which_rtfdtm!=previous)
13064c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	{
13074c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  		// Empty each DTM before popping, so it's ready for reuse
13084c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  		// _DON'T_ pop the previous, since it's still open (which is why we
13094c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  		// stacked up more of these) and did not receive a mark.
13104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  		boolean isEmpty=((SAX2RTFDTM)(m_rtfdtm_stack.elementAt(m_which_rtfdtm))).popRewindMark();
13114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  		--m_which_rtfdtm;
13124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	}
13134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
13144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
13154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
13164c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Gets DTMXRTreeFrag object if one has already been created.
13174c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Creates new DTMXRTreeFrag object and adds to m_DTMXRTreeFrags  HashMap,
13184c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * otherwise.
13194c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param dtmIdentity
13204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return DTMXRTreeFrag
13214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
13224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public DTMXRTreeFrag getDTMXRTreeFrag(int dtmIdentity){
13234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    if(m_DTMXRTreeFrags == null){
13244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      m_DTMXRTreeFrags = new HashMap();
13254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
13264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
13274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    if(m_DTMXRTreeFrags.containsKey(new Integer(dtmIdentity))){
13284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson       return (DTMXRTreeFrag)m_DTMXRTreeFrags.get(new Integer(dtmIdentity));
13294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }else{
13304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      final DTMXRTreeFrag frag = new DTMXRTreeFrag(dtmIdentity,this);
13314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      m_DTMXRTreeFrags.put(new Integer(dtmIdentity),frag);
13324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      return frag ;
13334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
13344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
13354c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
13364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
13374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Cleans DTMXRTreeFrag objects by removing references
13384c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * to DTM and XPathContext objects.
13394c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
13404c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  private final void releaseDTMXRTreeFrags(){
13414c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    if(m_DTMXRTreeFrags == null){
13424c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      return;
13434c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
13444c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    final Iterator iter = (m_DTMXRTreeFrags.values()).iterator();
13454c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    while(iter.hasNext()){
13464c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      DTMXRTreeFrag frag = (DTMXRTreeFrag)iter.next();
13474c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      frag.destruct();
13484c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      iter.remove();
13494c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
13504c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_DTMXRTreeFrags = null;
13514c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson }
13524c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson}
1353