Ignore:
Timestamp:
11/24/06 14:20:40 (6 years ago)
Author:
sys
Message:

cleanup incrementalSax

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Res_Xalan/org/apache/xpath/XPathContext.java

    r7031 r7489  
    5858public class XPathContext extends DTMManager // implements ExpressionContext 
    5959{ 
    60         IntStack m_last_pushed_rtfdtm=new IntStack();    
    61   /** 
    62    * Stack of cached "reusable" DTMs for Result Tree Fragments. 
    63    * This is a kluge to handle the problem of starting an RTF before 
    64    * the old one is complete. 
    65    *  
    66    * %REVIEW% I'm using a Vector rather than Stack so we can reuse 
    67    * the DTMs if the problem occurs multiple times. I'm not sure that's 
    68    * really a net win versus discarding the DTM and starting a new one... 
    69    * but the retained RTF DTM will have been tail-pruned so should be small. 
    70    */ 
    71   private Vector m_rtfdtm_stack=null; 
    72   /** Index of currently active RTF DTM in m_rtfdtm_stack */ 
    73   private int m_which_rtfdtm=-1; 
    74    
    75  /** 
    76    * Most recent "reusable" DTM for Global Result Tree Fragments. No stack is 
    77    * required since we're never going to pop these. 
    78    */ 
    79   private SAX2RTFDTM m_global_rtfdtm=null; 
    80    
    81          
    82   /** 
    83    * Though XPathContext context extends  
    84    * the DTMManager, it really is a proxy for this object, which  
    85    * is the real DTMManager. 
    86    */ 
    87   protected DTMManager m_dtmManager = DTMManager.newInstance( 
    88                    org.apache.xpath.objects.XMLStringFactoryImpl.getFactory()); 
    89    
    90   /** 
    91    * Return the DTMManager object.  Though XPathContext context extends  
    92    * the DTMManager, it really is a proxy for the real DTMManager.  If a  
    93    * caller needs to make a lot of calls to the DTMManager, it is faster  
    94    * if it gets the real one from this function. 
    95    */ 
    96    public DTMManager getDTMManager() 
    97    { 
    98      return m_dtmManager; 
    99    } 
    100    
    101   /** 
    102    * Get an instance of a DTM, loaded with the content from the 
    103    * specified source.  If the unique flag is true, a new instance will 
    104    * always be returned.  Otherwise it is up to the DTMManager to return a 
    105    * new instance or an instance that it already created and may be being used 
    106    * by someone else. 
    107    * (I think more parameters will need to be added for error handling, and entity 
    108    * resolution). 
    109    * 
    110    * @param source the specification of the source object, which may be null,  
    111    *               in which case it is assumed that node construction will take  
    112    *               by some other means. 
    113    * @param unique true if the returned DTM must be unique, probably because it 
    114    * is going to be mutated. 
    115    * @param whiteSpaceFilter Enables filtering of whitespace nodes, and may  
    116    *                         be null. 
    117    * @param incremental true if the construction should try and be incremental. 
    118    * @param doIndexing true if the caller considers it worth it to use  
    119    *                   indexing schemes. 
    120    * 
    121    * @return a non-null DTM reference. 
    122    */ 
    123   public DTM getDTM(javax.xml.transform.Source source, boolean unique,  
    124                     DTMWSFilter wsfilter, 
    125                     boolean incremental, 
    126                     boolean doIndexing) 
    127   { 
    128     return m_dtmManager.getDTM(source, unique, wsfilter,  
    129                                incremental, doIndexing); 
    130   } 
    131                               
    132   /** 
    133    * Get an instance of a DTM that "owns" a node handle.  
    134    * 
    135    * @param nodeHandle the nodeHandle. 
    136    * 
    137    * @return a non-null DTM reference. 
    138    */ 
    139   public DTM getDTM(int nodeHandle) 
    140   { 
    141     return m_dtmManager.getDTM(nodeHandle); 
    142   } 
    143  
    144   /** 
    145    * Given a W3C DOM node, try and return a DTM handle. 
    146    * Note: calling this may be non-optimal. 
    147    *  
    148    * @param node Non-null reference to a DOM node. 
    149    *  
    150    * @return a valid DTM handle. 
    151    */ 
    152   public int getDTMHandleFromNode(org.w3c.dom.Node node) 
    153   { 
    154     return m_dtmManager.getDTMHandleFromNode(node); 
    155   } 
    156 // 
    157 //   
    158   /** 
    159    * %TBD% Doc 
    160    */ 
    161   public int getDTMIdentity(DTM dtm) 
    162   { 
    163     return m_dtmManager.getDTMIdentity(dtm); 
    164   } 
    165 //   
    166   /** 
    167    * Creates an empty <code>DocumentFragment</code> object.  
    168    * @return A new <code>DocumentFragment handle</code>. 
    169    */ 
    170   public DTM createDocumentFragment() 
    171   { 
    172     return m_dtmManager.createDocumentFragment(); 
    173   } 
    174 //   
    175   /** 
    176    * Release a DTM either to a lru pool, or completely remove reference. 
    177    * DTMs without system IDs are always hard deleted. 
    178    * State: experimental. 
    179    *  
    180    * @param dtm The DTM to be released. 
    181    * @param shouldHardDelete True if the DTM should be removed no matter what. 
    182    * @return true if the DTM was removed, false if it was put back in a lru pool. 
    183    */ 
    184   public boolean release(DTM dtm, boolean shouldHardDelete) 
    185   { 
    186     // %REVIEW% If it's a DTM which may contain multiple Result Tree 
    187     // Fragments, we can't discard it unless we know not only that it 
    188     // is empty, but that the XPathContext itself is going away. So do 
    189     // _not_ accept the request. (May want to do it as part of 
    190     // reset(), though.) 
    191     if(m_rtfdtm_stack!=null && m_rtfdtm_stack.contains(dtm)) 
    192     { 
    193       return false; 
    194     } 
    195          
    196     return m_dtmManager.release(dtm, shouldHardDelete); 
    197   } 
    198  
    199   /** 
    200    * Create a new <code>DTMIterator</code> based on an XPath 
    201    * <a href="http://www.w3.org/TR/xpath#NT-LocationPath>LocationPath</a> or 
    202    * a <a href="http://www.w3.org/TR/xpath#NT-UnionExpr">UnionExpr</a>. 
    203    * 
    204    * @param xpathCompiler ??? Somehow we need to pass in a subpart of the 
    205    * expression.  I hate to do this with strings, since the larger expression 
    206    * has already been parsed. 
    207    * 
    208    * @param pos The position in the expression. 
    209    * @return The newly created <code>DTMIterator</code>. 
    210    */ 
    211   public DTMIterator createDTMIterator(Object xpathCompiler, int pos) 
    212   { 
    213     return m_dtmManager.createDTMIterator(xpathCompiler, pos); 
    214   } 
    215 // 
    216   /** 
    217    * Create a new <code>DTMIterator</code> based on an XPath 
    218    * <a href="http://www.w3.org/TR/xpath#NT-LocationPath>LocationPath</a> or 
    219    * a <a href="http://www.w3.org/TR/xpath#NT-UnionExpr">UnionExpr</a>. 
    220    * 
    221    * @param xpathString Must be a valid string expressing a 
    222    * <a href="http://www.w3.org/TR/xpath#NT-LocationPath>LocationPath</a> or 
    223    * a <a href="http://www.w3.org/TR/xpath#NT-UnionExpr">UnionExpr</a>. 
    224    * 
    225    * @param presolver An object that can resolve prefixes to namespace URLs. 
    226    * 
    227    * @return The newly created <code>DTMIterator</code>. 
    228    */ 
    229   public DTMIterator createDTMIterator(String xpathString, 
    230           PrefixResolver presolver) 
    231   { 
    232     return m_dtmManager.createDTMIterator(xpathString, presolver); 
    233   } 
    234 // 
    235   /** 
    236    * Create a new <code>DTMIterator</code> based only on a whatToShow and 
    237    * a DTMFilter.  The traversal semantics are defined as the descendant 
    238    * access. 
    239    * 
    240    * @param whatToShow This flag specifies which node types may appear in 
    241    *   the logical view of the tree presented by the iterator. See the 
    242    *   description of <code>NodeFilter</code> for the set of possible 
    243    *   <code>SHOW_</code> values.These flags can be combined using 
    244    *   <code>OR</code>. 
    245    * @param filter The <code>NodeFilter</code> to be used with this 
    246    *   <code>TreeWalker</code>, or <code>null</code> to indicate no filter. 
    247    * @param entityReferenceExpansion The value of this flag determines 
    248    *   whether entity reference nodes are expanded. 
    249    * 
    250    * @return The newly created <code>NodeIterator</code>. 
    251    */ 
    252   public DTMIterator createDTMIterator(int whatToShow, 
    253           DTMFilter filter, boolean entityReferenceExpansion) 
    254   { 
    255     return m_dtmManager.createDTMIterator(whatToShow, filter, entityReferenceExpansion); 
    256   } 
    257    
    258   /** 
    259    * Create a new <code>DTMIterator</code> that holds exactly one node. 
    260    * 
    261    * @param node The node handle that the DTMIterator will iterate to. 
    262    * 
    263    * @return The newly created <code>DTMIterator</code>. 
    264    */ 
    265   public DTMIterator createDTMIterator(int node) 
    266   { 
    267     // DescendantIterator iter = new DescendantIterator(); 
    268     DTMIterator iter = new org.apache.xpath.axes.OneStepIteratorForward(Axis.SELF); 
    269     iter.setRoot(node, this); 
    270     return iter; 
    271     // return m_dtmManager.createDTMIterator(node); 
    272   } 
    273  
    274   /** 
    275    * Create an XPathContext instance. 
    276    */ 
    277   public XPathContext() 
    278   { 
    279     m_prefixResolvers.push(null); 
    280     m_currentNodes.push(DTM.NULL); 
    281     m_currentExpressionNodes.push(DTM.NULL); 
    282     m_saxLocations.push(null); 
    283   } 
    284  
    285   /** 
    286    * Create an XPathContext instance. 
    287    * @param owner Value that can be retrieved via the getOwnerObject() method. 
    288    * @see #getOwnerObject 
    289    */ 
    290   public XPathContext(Object owner) 
    291   { 
    292     m_owner = owner; 
    293     try { 
    294       m_ownerGetErrorListener = m_owner.getClass().getMethod("getErrorListener", new Class[] {}); 
    295     } 
    296     catch (NoSuchMethodException nsme) {} 
    297     m_prefixResolvers.push(null); 
    298     m_currentNodes.push(DTM.NULL); 
    299     m_currentExpressionNodes.push(DTM.NULL); 
    300     m_saxLocations.push(null); 
    301   } 
    302  
    303   /** 
    304    * Reset for new run. 
    305    */ 
    306   public void reset() 
    307   { 
    308         // These couldn't be disposed of earlier (see comments in release()); zap them now. 
    309         if(m_rtfdtm_stack!=null) 
    310                  for (java.util.Enumeration e = m_rtfdtm_stack.elements() ; e.hasMoreElements() ;)  
    311                         m_dtmManager.release((DTM)e.nextElement(), true); 
    312  
    313     m_rtfdtm_stack=null; // drop our references too 
    314     m_which_rtfdtm=-1; 
    315      
    316     if(m_global_rtfdtm!=null) 
    317                         m_dtmManager.release(m_global_rtfdtm,true); 
    318     m_global_rtfdtm=null; 
    319          
    320     m_dtmManager = DTMManager.newInstance( 
    321                    org.apache.xpath.objects.XMLStringFactoryImpl.getFactory()); 
    322                     
    323     m_saxLocations.removeAllElements();    
    324         m_axesIteratorStack.removeAllElements(); 
    325         m_contextNodeLists.removeAllElements(); 
    326         m_currentExpressionNodes.removeAllElements(); 
    327         m_currentNodes.removeAllElements(); 
    328         m_iteratorRoots.RemoveAllNoClear(); 
    329         m_predicatePos.removeAllElements(); 
    330         m_predicateRoots.RemoveAllNoClear(); 
    331         m_prefixResolvers.removeAllElements(); 
    332          
    333         m_prefixResolvers.push(null); 
    334     m_currentNodes.push(DTM.NULL); 
    335     m_currentExpressionNodes.push(DTM.NULL); 
    336     m_saxLocations.push(null); 
    337   } 
    338  
    339   /** The current stylesheet locator. */ 
    340   ObjectStack m_saxLocations = new ObjectStack(RECURSIONLIMIT); 
    341  
    342   /** 
    343    * Set the current locater in the stylesheet. 
    344    * 
    345    * @param location The location within the stylesheet. 
    346    */ 
    347   public void setSAXLocator(SourceLocator location) 
    348   { 
    349     m_saxLocations.setTop(location); 
    350   } 
    351    
    352   /** 
    353    * Set the current locater in the stylesheet. 
    354    * 
    355    * @param location The location within the stylesheet. 
    356    */ 
    357   public void pushSAXLocator(SourceLocator location) 
    358   { 
    359     m_saxLocations.push(location); 
    360   } 
    361    
    362   /** 
    363    * Push a slot on the locations stack so that setSAXLocator can be  
    364    * repeatedly called. 
    365    * 
    366    * @param location The location within the stylesheet. 
    367    */ 
    368   public void pushSAXLocatorNull() 
    369   { 
    370     m_saxLocations.push(null); 
    371   } 
    372  
    373  
    374   /** 
    375    * Pop the current locater. 
    376    */ 
    377   public void popSAXLocator() 
    378   { 
    379     m_saxLocations.pop(); 
    380   } 
    381  
    382   /** 
    383    * Get the current locater in the stylesheet. 
    384    * 
    385    * @return The location within the stylesheet, or null if not known. 
    386    */ 
    387   public SourceLocator getSAXLocator() 
    388   { 
    389     return (SourceLocator) m_saxLocations.peek(); 
    390   } 
    391  
    392   /** The owner context of this XPathContext.  In the case of XSLT, this will be a 
    393    *  Transformer object. 
    394    */ 
    395   private Object m_owner; 
    396  
    397   /** The owner context of this XPathContext.  In the case of XSLT, this will be a 
    398    *  Transformer object. 
    399    */ 
    400   private Method m_ownerGetErrorListener; 
    401  
    402   /** 
    403    * Get the "owner" context of this context, which should be, 
    404    * in the case of XSLT, the Transformer object.  This is needed 
    405    * so that XSLT functions can get the Transformer. 
    406    * @return The owner object passed into the constructor, or null. 
    407    */ 
    408   public Object getOwnerObject() 
    409   { 
    410     return m_owner; 
    411   } 
    412  
    413   // ================ VarStack =================== 
    414  
    415   /** 
    416    * The stack of Variable stacks.  A VariableStack will be 
    417    * pushed onto this stack for each template invocation. 
    418    */ 
    419   private VariableStack m_variableStacks = new VariableStack(); 
    420  
    421   /** 
    422    * Get the variable stack, which is in charge of variables and 
    423    * parameters. 
    424    * 
    425    * @return the variable stack, which should not be null. 
    426    */ 
    427   public final VariableStack getVarStack() 
    428   { 
    429     return m_variableStacks; 
    430   } 
    431  
    432   /**  
    433    * Get the variable stack, which is in charge of variables and 
    434    * parameters. 
    435    * 
    436    * @param varStack non-null reference to the variable stack. 
    437    */ 
    438   public final void setVarStack(VariableStack varStack) 
    439   { 
    440     m_variableStacks = varStack; 
    441   } 
    442  
    443   // ================ SourceTreeManager =================== 
    444  
    445   /** The source tree manager, which associates Source objects to source  
    446    *  tree nodes. */ 
    447   private SourceTreeManager m_sourceTreeManager = new SourceTreeManager(); 
    448  
    449   /** 
    450    * Get the SourceTreeManager associated with this execution context. 
    451    * 
    452    * @return the SourceTreeManager associated with this execution context. 
    453    */ 
    454   public final SourceTreeManager getSourceTreeManager() 
    455   { 
    456     return m_sourceTreeManager; 
    457   } 
    458  
    459   /** 
    460    * Set the SourceTreeManager associated with this execution context. 
    461    * 
    462    * @param mgr the SourceTreeManager to be associated with this  
    463    *        execution context. 
    464    */ 
    465   public void setSourceTreeManager(SourceTreeManager mgr) 
    466   { 
    467     m_sourceTreeManager = mgr; 
    468   } 
    469    
    470   // ================================================= 
    471  
    472   /** The ErrorListener where errors and warnings are to be reported.   */ 
    473   private ErrorListener m_errorListener; 
    474  
    475   /** A default ErrorListener in case our m_errorListener was not specified and our 
    476    *  owner either does not have an ErrorListener or has a null one. 
    477    */ 
    478   private ErrorListener m_defaultErrorListener; 
    479  
    480   /** 
    481    * Get the ErrorListener where errors and warnings are to be reported. 
    482    * 
    483    * @return A non-null ErrorListener reference. 
    484    */ 
    485   public final ErrorListener getErrorListener() 
    486   { 
    487  
    488     if (null != m_errorListener) 
    489         return m_errorListener; 
    490  
    491     ErrorListener retval = null; 
    492  
    493     try { 
    494       if (null != m_ownerGetErrorListener) 
    495         retval = (ErrorListener) m_ownerGetErrorListener.invoke(m_owner, new Object[] {}); 
    496     } 
    497     catch (Exception e) {} 
    498  
    499     if (null == retval) 
    500     { 
    501       if (null == m_defaultErrorListener)  
    502         m_defaultErrorListener = new org.apache.xml.utils.DefaultErrorHandler(); 
    503       retval = m_defaultErrorListener; 
    504     } 
    505  
    506     return retval; 
    507   } 
    508  
    509   /** 
    510    * Set the ErrorListener where errors and warnings are to be reported. 
    511    * 
    512    * @param listener A non-null ErrorListener reference. 
    513    */ 
    514   public void setErrorListener(ErrorListener listener) throws IllegalArgumentException 
    515   { 
    516     if (listener == null)  
    517       throw new IllegalArgumentException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NULL_ERROR_HANDLER, null)); //"Null error handler"); 
    518     m_errorListener = listener; 
    519   } 
    520  
    521  
    522   // ================================================= 
    523  
    524   /** The TrAX URI Resolver for resolving URIs from the document(...) 
    525    *  function to source tree nodes.  */ 
    526   private URIResolver m_uriResolver; 
    527  
    528   /** 
    529    * Get the URIResolver associated with this execution context. 
    530    * 
    531    * @return a URI resolver, which may be null. 
    532    */ 
    533   public final URIResolver getURIResolver() 
    534   { 
    535     return m_uriResolver; 
    536   } 
    537  
    538   /** 
    539    * Set the URIResolver associated with this execution context. 
    540    * 
    541    * @param resolver the URIResolver to be associated with this  
    542    *        execution context, may be null to clear an already set resolver. 
    543    */ 
    544   public void setURIResolver(URIResolver resolver) 
    545   { 
    546     m_uriResolver = resolver; 
    547   } 
    548  
    549   // ================================================= 
    550  
    551   /** The reader of the primary source tree.    */ 
    552   public XMLReader m_primaryReader; 
    553  
    554   /** 
    555    * Get primary XMLReader associated with this execution context. 
    556    * 
    557    * @return The reader of the primary source tree. 
    558    */ 
    559   public final XMLReader getPrimaryReader() 
    560   { 
    561     return m_primaryReader; 
    562   } 
    563  
    564   /** 
    565    * Set primary XMLReader associated with this execution context. 
    566    * 
    567    * @param reader The reader of the primary source tree. 
    568    */ 
    569   public void setPrimaryReader(XMLReader reader) 
    570   { 
    571     m_primaryReader = reader; 
    572   } 
    573  
    574   // ================================================= 
    575  
    576  
    577   /** Misnamed string manager for XPath messages.  */ 
    578   // private static XSLMessages m_XSLMessages = new XSLMessages(); 
    579  
    580   /** 
    581    * Tell the user of an assertion error, and probably throw an 
    582    * exception. 
    583    * 
    584    * @param b  If false, a TransformerException will be thrown. 
    585    * @param msg The assertion message, which should be informative. 
    586    *  
    587    * @throws javax.xml.transform.TransformerException if b is false. 
    588    */ 
    589   private void assertion(boolean b, String msg) throws javax.xml.transform.TransformerException 
    590   { 
    591     if (!b)  
    592     { 
    593       ErrorListener errorHandler = getErrorListener(); 
    594  
    595       if (errorHandler != null) 
    596       { 
    597         errorHandler.fatalError( 
    598           new TransformerException( 
    599             XSLMessages.createMessage( 
    600               XPATHErrorResources.ER_INCORRECT_PROGRAMMER_ASSERTION, 
    601               new Object[]{ msg }), (SAXSourceLocator)this.getSAXLocator())); 
    602       } 
    603     } 
    604   } 
    605  
    606   //========================================================== 
    607   // SECTION: Execution context state tracking 
    608   //========================================================== 
    609    
    610   /** 
    611    * The current context node list. 
    612    */ 
    613   private Stack m_contextNodeLists = new Stack(); 
    614    
    615   public Stack getContextNodeListsStack() { return m_contextNodeLists; } 
    616   public void setContextNodeListsStack(Stack s) { m_contextNodeLists = s; } 
    617  
    618   /** 
    619    * Get the current context node list. 
    620    * 
    621    * @return  the <a href="http://www.w3.org/TR/xslt#dt-current-node-list">current node list</a>, 
    622    * also refered to here as a <term>context node list</term>. 
    623    */ 
    624   public final DTMIterator getContextNodeList() 
    625   { 
    626  
    627     if (m_contextNodeLists.size() > 0) 
    628       return (DTMIterator) m_contextNodeLists.peek(); 
    629     else 
    630       return null; 
    631   } 
    632  
    633   /** 
    634    * Set the current context node list. 
    635    * 
    636    * @param nl the <a href="http://www.w3.org/TR/xslt#dt-current-node-list">current node list</a>, 
    637    * also refered to here as a <term>context node list</term>. 
    638    * @xsl.usage internal 
    639    */ 
    640   public final void pushContextNodeList(DTMIterator nl) 
    641   { 
    642     m_contextNodeLists.push(nl); 
    643   } 
    644  
    645   /** 
    646    * Pop the current context node list. 
    647    * @xsl.usage internal 
    648    */ 
    649   public final void popContextNodeList() 
    650   { 
    651         if(m_contextNodeLists.isEmpty()) 
    652           System.err.println("Warning: popContextNodeList when stack is empty!"); 
    653         else 
    654       m_contextNodeLists.pop(); 
    655   } 
    656  
    657   /** 
    658    * The ammount to use for stacks that record information during the  
    659    * recursive execution. 
    660    */ 
    661   public static final int RECURSIONLIMIT = (1024*4); 
    662  
    663   /** The stack of <a href="http://www.w3.org/TR/xslt#dt-current-node">current node</a> objects. 
    664    *  Not to be confused with the current node list.  %REVIEW% Note that there  
    665    *  are no bounds check and resize for this stack, so if it is blown, it's all  
    666    *  over.  */ 
    667   private IntStack m_currentNodes = new IntStack(RECURSIONLIMIT); 
    668     
    669 //  private NodeVector m_currentNodes = new NodeVector(); 
    670    
    671   public IntStack getCurrentNodeStack() {return m_currentNodes; } 
    672   public void setCurrentNodeStack(IntStack nv) { m_currentNodes = nv; } 
    673  
    674   /** 
    675    * Get the current context node. 
    676    * 
    677    * @return the <a href="http://www.w3.org/TR/xslt#dt-current-node">current node</a>. 
    678    */ 
    679   public final int getCurrentNode() 
    680   { 
    681     return m_currentNodes.peek(); 
    682   } 
    683    
    684   /** 
    685    * Set the current context node and expression node. 
    686    * 
    687    * @param cn the <a href="http://www.w3.org/TR/xslt#dt-current-node">current node</a>. 
    688    * @param en the sub-expression context node. 
    689    */ 
    690   public final void pushCurrentNodeAndExpression(int cn, int en) 
    691   { 
    692     m_currentNodes.push(cn); 
    693     m_currentExpressionNodes.push(cn); 
    694   } 
    695  
    696   /** 
    697    * Set the current context node. 
    698    */ 
    699   public final void popCurrentNodeAndExpression() 
    700   { 
    701     m_currentNodes.quickPop(1); 
    702     m_currentExpressionNodes.quickPop(1); 
    703   } 
    704    
    705   /** 
    706    * Push the current context node, expression node, and prefix resolver. 
    707    * 
    708    * @param cn the <a href="http://www.w3.org/TR/xslt#dt-current-node">current node</a>. 
    709    * @param en the sub-expression context node. 
    710    * @param nc the namespace context (prefix resolver. 
    711    */ 
    712   public final void pushExpressionState(int cn, int en, PrefixResolver nc) 
    713   { 
    714     m_currentNodes.push(cn); 
    715     m_currentExpressionNodes.push(cn); 
    716     m_prefixResolvers.push(nc); 
    717   } 
    718    
    719   /** 
    720    * Pop the current context node, expression node, and prefix resolver. 
    721    */ 
    722   public final void popExpressionState() 
    723   { 
    724     m_currentNodes.quickPop(1); 
    725     m_currentExpressionNodes.quickPop(1); 
    726     m_prefixResolvers.pop(); 
    727   } 
    728  
    729  
    730  
    731   /** 
    732    * Set the current context node. 
    733    * 
    734    * @param n the <a href="http://www.w3.org/TR/xslt#dt-current-node">current node</a>. 
    735    */ 
    736   public final void pushCurrentNode(int n) 
    737   { 
    738     m_currentNodes.push(n); 
    739   } 
    740    
    741   /** 
    742    * Pop the current context node. 
    743    */ 
    744   public final void popCurrentNode() 
    745   { 
    746     m_currentNodes.quickPop(1); 
    747   } 
    748    
    749   /** 
    750    * Set the current predicate root. 
    751    */ 
    752   public final void pushPredicateRoot(int n) 
    753   { 
    754     m_predicateRoots.push(n); 
    755   } 
    756  
    757   /** 
    758    * Pop the current predicate root. 
    759    */ 
    760   public final void popPredicateRoot() 
    761   { 
    762     m_predicateRoots.popQuick(); 
    763   } 
    764  
    765   /** 
    766    * Get the current predicate root. 
    767    */ 
    768   public final int getPredicateRoot() 
    769   { 
    770     return m_predicateRoots.peepOrNull(); 
    771   } 
    772    
    773   /** 
    774    * Set the current location path iterator root. 
    775    */ 
    776   public final void pushIteratorRoot(int n) 
    777   { 
    778     m_iteratorRoots.push(n); 
    779   } 
    780  
    781   /** 
    782    * Pop the current location path iterator root. 
    783    */ 
    784   public final void popIteratorRoot() 
    785   { 
    786     m_iteratorRoots.popQuick(); 
    787   } 
    788  
    789   /** 
    790    * Get the current location path iterator root. 
    791    */ 
    792   public final int getIteratorRoot() 
    793   { 
    794     return m_iteratorRoots.peepOrNull(); 
    795   } 
    796    
    797   /** A stack of the current sub-expression nodes.  */ 
    798   private NodeVector m_iteratorRoots = new NodeVector(); 
    799  
    800   /** A stack of the current sub-expression nodes.  */ 
    801   private NodeVector m_predicateRoots = new NodeVector(); 
    802  
    803   /** A stack of the current sub-expression nodes.  */ 
    804   private IntStack m_currentExpressionNodes = new IntStack(RECURSIONLIMIT); 
    805    
    806       
    807   public IntStack getCurrentExpressionNodeStack() { return m_currentExpressionNodes; } 
    808   public void setCurrentExpressionNodeStack(IntStack nv) { m_currentExpressionNodes = nv; } 
    809    
    810   private IntStack m_predicatePos = new IntStack(); 
    811    
    812   public final int getPredicatePos() 
    813   { 
    814     return m_predicatePos.peek(); 
    815   } 
    816  
    817   public final void pushPredicatePos(int n) 
    818   { 
    819     m_predicatePos.push(n); 
    820   } 
    821  
    822   public final void popPredicatePos() 
    823   { 
    824     m_predicatePos.pop(); 
    825   } 
    826  
    827   /** 
    828    * Get the current node that is the expression's context (i.e. for current() support). 
    829    * 
    830    * @return The current sub-expression node. 
    831    */ 
    832   public final int getCurrentExpressionNode() 
    833   { 
    834     return m_currentExpressionNodes.peek(); 
    835   } 
    836  
    837   /** 
    838    * Set the current node that is the expression's context (i.e. for current() support). 
    839    * 
    840    * @param n The sub-expression node to be current. 
    841    */ 
    842   public final void pushCurrentExpressionNode(int n) 
    843   { 
    844     m_currentExpressionNodes.push(n); 
    845   } 
    846  
    847   /** 
    848    * Pop the current node that is the expression's context  
    849    * (i.e. for current() support). 
    850    */ 
    851   public final void popCurrentExpressionNode() 
    852   { 
    853     m_currentExpressionNodes.quickPop(1); 
    854   } 
    855    
    856   private ObjectStack m_prefixResolvers  
    857                                    = new ObjectStack(RECURSIONLIMIT); 
    858  
    859   /** 
    860    * Get the current namespace context for the xpath. 
    861    * 
    862    * @return the current prefix resolver for resolving prefixes to  
    863    *         namespace URLs. 
    864    */ 
    865   public final PrefixResolver getNamespaceContext() 
    866   { 
    867     return (PrefixResolver) m_prefixResolvers.peek(); 
    868   } 
    869  
    870   /** 
    871    * Get the current namespace context for the xpath. 
    872    * 
    873    * @param pr the prefix resolver to be used for resolving prefixes to  
    874    *         namespace URLs. 
    875    */ 
    876   public final void setNamespaceContext(PrefixResolver pr) 
    877   { 
    878     m_prefixResolvers.setTop(pr); 
    879   } 
    880  
    881   /** 
    882    * Push a current namespace context for the xpath. 
    883    * 
    884    * @param pr the prefix resolver to be used for resolving prefixes to  
    885    *         namespace URLs. 
    886    */ 
    887   public final void pushNamespaceContext(PrefixResolver pr) 
    888   { 
    889     m_prefixResolvers.push(pr); 
    890   } 
    891    
    892   /** 
    893    * Just increment the namespace contest stack, so that setNamespaceContext 
    894    * can be used on the slot. 
    895    */ 
    896   public final void pushNamespaceContextNull() 
    897   { 
    898     m_prefixResolvers.push(null); 
    899   } 
    900  
    901   /** 
    902    * Pop the current namespace context for the xpath. 
    903    */ 
    904   public final void popNamespaceContext() 
    905   { 
    906     m_prefixResolvers.pop(); 
    907   } 
    908  
    909   //========================================================== 
    910   // SECTION: Current TreeWalker contexts (for internal use) 
    911   //========================================================== 
    912  
    913   /** 
    914    * Stack of AxesIterators. 
    915    */ 
    916   private Stack m_axesIteratorStack = new Stack(); 
    917    
    918   public Stack getAxesIteratorStackStacks() { return m_axesIteratorStack; } 
    919   public void setAxesIteratorStackStacks(Stack s) { m_axesIteratorStack = s; } 
    920  
    921   /** 
    922    * Push a TreeWalker on the stack. 
    923    * 
    924    * @param iter A sub-context AxesWalker. 
    925    * @xsl.usage internal 
    926    */ 
    927   public final void pushSubContextList(SubContextList iter) 
    928   { 
    929     m_axesIteratorStack.push(iter); 
    930   } 
    931  
    932   /** 
    933    * Pop the last pushed axes iterator. 
    934    * @xsl.usage internal 
    935    */ 
    936   public final void popSubContextList() 
    937   { 
    938     m_axesIteratorStack.pop(); 
    939   } 
    940  
    941   /** 
    942    * Get the current axes iterator, or return null if none. 
    943    * 
    944    * @return the sub-context node list. 
    945    * @xsl.usage internal 
    946    */ 
    947   public SubContextList getSubContextList() 
    948   { 
    949     return m_axesIteratorStack.isEmpty() 
    950            ? null : (SubContextList) m_axesIteratorStack.peek(); 
    951   } 
    952    
    953   /** 
    954    * Get the <a href="http://www.w3.org/TR/xslt#dt-current-node-list">current node list</a>  
    955    * as defined by the XSLT spec. 
    956    * 
    957    * @return the <a href="http://www.w3.org/TR/xslt#dt-current-node-list">current node list</a>. 
    958    * @xsl.usage internal 
    959    */ 
    960  
    961   public org.apache.xpath.axes.SubContextList getCurrentNodeList() 
    962   { 
    963     return m_axesIteratorStack.isEmpty() 
    964            ? null : (SubContextList) m_axesIteratorStack.elementAt(0); 
    965   } 
    966   //========================================================== 
    967   // SECTION: Implementation of ExpressionContext interface 
    968   //========================================================== 
    969  
    970   /** 
    971    * Get the current context node. 
    972    * @return The current context node. 
    973    */ 
    974   public final int getContextNode() 
    975   { 
    976     return this.getCurrentNode(); 
    977   } 
    978  
    979   /** 
    980    * Get the current context node list. 
    981    * @return An iterator for the current context list, as 
    982    * defined in XSLT. 
    983    */ 
    984   public final DTMIterator getContextNodes() 
    985   { 
    986  
    987     try 
    988     { 
    989       DTMIterator cnl = getContextNodeList(); 
    990  
    991       if (null != cnl) 
    992         return cnl.cloneWithReset(); 
    993       else 
    994         return null;  // for now... this might ought to be an empty iterator. 
    995     } 
    996     catch (CloneNotSupportedException cnse) 
    997     { 
    998       return null;  // error reporting? 
    999     } 
    1000   } 
    1001    
    1002   XPathExpressionContext expressionContext = new XPathExpressionContext(); 
    1003    
    1004   /** 
    1005    * The the expression context for extensions for this context. 
    1006    *  
    1007    * @return An object that implements the ExpressionContext. 
    1008    */ 
    1009   public ExpressionContext getExpressionContext() 
    1010   { 
    1011     return expressionContext; 
    1012   } 
    1013    
    1014   public class XPathExpressionContext implements ExpressionContext 
    1015   { 
    1016     /** 
    1017      * Return the XPathContext associated with this XPathExpressionContext. 
    1018      * Extensions should use this judiciously and only when special processing 
    1019      * requirements cannot be met another way.  Consider requesting an enhancement 
    1020      * to the ExpressionContext interface to avoid having to call this method. 
    1021      * @return the XPathContext associated with this XPathExpressionContext. 
    1022      */ 
    1023      public XPathContext getXPathContext() 
    1024      { 
    1025        return XPathContext.this; 
    1026      } 
    1027  
    1028     /** 
    1029      * Return the DTMManager object.  Though XPathContext context extends  
    1030      * the DTMManager, it really is a proxy for the real DTMManager.  If a  
    1031      * caller needs to make a lot of calls to the DTMManager, it is faster  
    1032      * if it gets the real one from this function. 
    1033      */ 
    1034      public DTMManager getDTMManager() 
    1035      { 
    1036        return m_dtmManager; 
    1037      } 
    1038      
    1039     /** 
    1040      * Get the current context node. 
    1041      * @return The current context node. 
    1042      */ 
    1043     public org.w3c.dom.Node getContextNode() 
    1044     { 
    1045       int context = getCurrentNode(); 
    1046        
    1047       return getDTM(context).getNode(context); 
    1048     } 
    1049    
    1050     /** 
    1051      * Get the current context node list. 
    1052      * @return An iterator for the current context list, as 
    1053      * defined in XSLT. 
    1054      */ 
    1055     public org.w3c.dom.traversal.NodeIterator getContextNodes() 
    1056     { 
    1057       return new org.apache.xml.dtm.ref.DTMNodeIterator(getContextNodeList()); 
    1058     } 
    1059  
    1060     /** 
    1061      * Get the error listener. 
    1062      * @return The registered error listener. 
    1063      */ 
    1064     public ErrorListener getErrorListener() 
    1065     { 
    1066       return XPathContext.this.getErrorListener(); 
    1067     } 
    1068    
    1069     /** 
    1070      * Get the value of a node as a number. 
    1071      * @param n Node to be converted to a number.  May be null. 
    1072      * @return value of n as a number. 
    1073      */ 
    1074     public double toNumber(org.w3c.dom.Node n) 
    1075     { 
    1076       // %REVIEW% You can't get much uglier than this... 
    1077       int nodeHandle = getDTMHandleFromNode(n); 
    1078       DTM dtm = getDTM(nodeHandle); 
    1079       XString xobj = (XString)dtm.getStringValue(nodeHandle); 
    1080       return xobj.num(); 
    1081     } 
    1082    
    1083     /** 
    1084      * Get the value of a node as a string. 
    1085      * @param n Node to be converted to a string.  May be null. 
    1086      * @return value of n as a string, or an empty string if n is null. 
    1087      */ 
    1088     public String toString(org.w3c.dom.Node n) 
    1089     { 
    1090       // %REVIEW% You can't get much uglier than this... 
    1091       int nodeHandle = getDTMHandleFromNode(n); 
    1092       DTM dtm = getDTM(nodeHandle); 
    1093       XMLString strVal = dtm.getStringValue(nodeHandle); 
    1094       return strVal.toString(); 
    1095     } 
    1096  
    1097     /** 
    1098      * Get a variable based on it's qualified name. 
    1099      * @param qname The qualified name of the variable. 
    1100      * @return The evaluated value of the variable. 
    1101      * @throws javax.xml.transform.TransformerException 
    1102      */ 
    1103  
    1104     public final XObject getVariableOrParam(org.apache.xml.utils.QName qname) 
    1105               throws javax.xml.transform.TransformerException 
    1106     { 
    1107       return m_variableStacks.getVariableOrParam(XPathContext.this, qname); 
    1108     } 
    1109  
    1110   } 
    1111  
    1112  /** 
    1113    * Get a DTM to be used as a container for a global Result Tree 
    1114    * Fragment. This will always be an instance of (derived from? equivalent to?)  
    1115    * SAX2DTM, since each RTF is constructed by temporarily redirecting our SAX  
    1116    * output to it. It may be a single DTM containing for multiple fragments,  
    1117    * if the implementation supports that. 
    1118    *  
    1119    * Note: The distinction between this method and getRTFDTM() is that the latter 
    1120    * allocates space from the dynamic variable stack (m_rtfdtm_stack), which may 
    1121    * be pruned away again as the templates which defined those variables are exited. 
    1122    * Global variables may be bound late (see XUnresolvedVariable), and never want to 
    1123    * be discarded, hence we need to allocate them separately and don't actually need 
    1124    * a stack to track them. 
    1125    *  
    1126    * @return a non-null DTM reference. 
    1127    */ 
    1128   public DTM getGlobalRTFDTM() 
    1129   { 
    1130         // We probably should _NOT_ be applying whitespace filtering at this stage! 
    1131         // 
    1132         // Some magic has been applied in DTMManagerDefault to recognize this set of options 
    1133         // and generate an instance of DTM which can contain multiple documents 
    1134         // (SAX2RTFDTM). Perhaps not the optimal way of achieving that result, but 
    1135         // I didn't want to change the manager API at this time, or expose  
    1136         // too many dependencies on its internals. (Ideally, I'd like to move 
    1137         // isTreeIncomplete all the way up to DTM, so we wouldn't need to explicitly 
    1138         // specify the subclass here.) 
    1139  
    1140         // If it doesn't exist, or if the one already existing is in the middle of 
    1141         // being constructed, we need to obtain a new DTM to write into. I'm not sure 
    1142         // the latter will ever arise, but I'd rather be just a bit paranoid.. 
    1143         if( m_global_rtfdtm==null || m_global_rtfdtm.isTreeIncomplete() ) 
    1144         { 
    1145                 m_global_rtfdtm=(SAX2RTFDTM)m_dtmManager.getDTM(null,true,null,false,false); 
    1146         } 
    1147     return m_global_rtfdtm; 
    1148   } 
    1149    
    1150  
    1151  
    1152  
    1153   /** 
    1154    * Get a DTM to be used as a container for a dynamic Result Tree 
    1155    * Fragment. This will always be an instance of (derived from? equivalent to?)  
    1156    * SAX2DTM, since each RTF is constructed by temporarily redirecting our SAX  
    1157    * output to it. It may be a single DTM containing for multiple fragments,  
    1158    * if the implementation supports that. 
    1159    *  
    1160    * @return a non-null DTM reference. 
    1161    */ 
    1162   public DTM getRTFDTM() 
    1163   { 
    1164         SAX2RTFDTM rtfdtm; 
    1165  
    1166         // We probably should _NOT_ be applying whitespace filtering at this stage! 
    1167         // 
    1168         // Some magic has been applied in DTMManagerDefault to recognize this set of options 
    1169         // and generate an instance of DTM which can contain multiple documents 
    1170         // (SAX2RTFDTM). Perhaps not the optimal way of achieving that result, but 
    1171         // I didn't want to change the manager API at this time, or expose  
    1172         // too many dependencies on its internals. (Ideally, I'd like to move 
    1173         // isTreeIncomplete all the way up to DTM, so we wouldn't need to explicitly 
    1174         // specify the subclass here.) 
    1175  
    1176         if(m_rtfdtm_stack==null) 
    1177         { 
    1178                 m_rtfdtm_stack=new Vector(); 
    1179                 rtfdtm=(SAX2RTFDTM)m_dtmManager.getDTM(null,true,null,false,false); 
    1180     m_rtfdtm_stack.addElement(rtfdtm); 
    1181                 ++m_which_rtfdtm; 
    1182         } 
    1183         else if(m_which_rtfdtm<0) 
    1184         { 
    1185                 rtfdtm=(SAX2RTFDTM)m_rtfdtm_stack.elementAt(++m_which_rtfdtm); 
    1186         } 
    1187         else 
    1188         { 
    1189                 rtfdtm=(SAX2RTFDTM)m_rtfdtm_stack.elementAt(m_which_rtfdtm); 
    1190                  
    1191                 // It might already be under construction -- the classic example would be 
    1192                 // an xsl:variable which uses xsl:call-template as part of its value. To 
    1193                 // handle this recursion, we have to start a new RTF DTM, pushing the old 
    1194                 // one onto a stack so we can return to it. This is not as uncommon a case 
    1195                 // as we might wish, unfortunately, as some folks insist on coding XSLT 
    1196                 // as if it were a procedural language... 
    1197                 if(rtfdtm.isTreeIncomplete()) 
    1198                 { 
    1199                         if(++m_which_rtfdtm < m_rtfdtm_stack.size()) 
    1200                                 rtfdtm=(SAX2RTFDTM)m_rtfdtm_stack.elementAt(m_which_rtfdtm); 
    1201                         else 
    1202                         { 
    1203                                 rtfdtm=(SAX2RTFDTM)m_dtmManager.getDTM(null,true,null,false,false); 
    1204           m_rtfdtm_stack.addElement(rtfdtm);     
    1205                         } 
    1206                 } 
    1207         } 
    1208                  
    1209     return rtfdtm; 
    1210   } 
    1211    
    1212   /** Push the RTFDTM's context mark, to allows discarding RTFs added after this 
    1213    * point. (If it doesn't exist we don't push, since we might still be able to  
    1214    * get away with not creating it. That requires that excessive pops be harmless.) 
    1215    * */ 
    1216   public void pushRTFContext() 
    1217   { 
    1218         m_last_pushed_rtfdtm.push(m_which_rtfdtm); 
    1219         if(null!=m_rtfdtm_stack) 
    1220                 ((SAX2RTFDTM)(getRTFDTM())).pushRewindMark(); 
    1221   } 
    1222    
    1223   /** Pop the RTFDTM's context mark. This discards any RTFs added after the last 
    1224    * mark was set.  
    1225    *  
    1226    * If there is no RTF DTM, there's nothing to pop so this 
    1227    * becomes a no-op. If pushes were issued before this was called, we count on 
    1228    * the fact that popRewindMark is defined such that overpopping just resets 
    1229    * to empty. 
    1230    *  
    1231    * Complicating factor: We need to handle the case of popping back to a previous 
    1232    * RTF DTM, if one of the weird produce-an-RTF-to-build-an-RTF cases arose. 
    1233    * Basically: If pop says this DTM is now empty, then return to the previous 
    1234    * if one exists, in whatever state we left it in. UGLY, but hopefully the 
    1235    * situation which forces us to consider this will arise exceedingly rarely. 
    1236    * */ 
    1237   public void popRTFContext() 
    1238   { 
    1239         int previous=m_last_pushed_rtfdtm.pop(); 
    1240         if(null==m_rtfdtm_stack) 
    1241                 return; 
    1242    
    1243         if(m_which_rtfdtm==previous) 
    1244         { 
    1245                 if(previous>=0) // guard against none-active 
    1246                 { 
    1247                         boolean isEmpty=((SAX2RTFDTM)(m_rtfdtm_stack.elementAt(previous))).popRewindMark(); 
    1248                 } 
    1249         } 
    1250         else while(m_which_rtfdtm!=previous) 
    1251         { 
    1252                 // Empty each DTM before popping, so it's ready for reuse 
    1253                 // _DON'T_ pop the previous, since it's still open (which is why we 
    1254                 // stacked up more of these) and did not receive a mark. 
    1255                 boolean isEmpty=((SAX2RTFDTM)(m_rtfdtm_stack.elementAt(m_which_rtfdtm))).popRewindMark(); 
    1256                 --m_which_rtfdtm;  
    1257         } 
    1258   } 
     60        IntStack m_last_pushed_rtfdtm = new IntStack(); 
     61 
     62        /** 
     63         * Stack of cached "reusable" DTMs for Result Tree Fragments. 
     64         * This is a kluge to handle the problem of starting an RTF before 
     65         * the old one is complete. 
     66         *  
     67         * %REVIEW% I'm using a Vector rather than Stack so we can reuse 
     68         * the DTMs if the problem occurs multiple times. I'm not sure that's 
     69         * really a net win versus discarding the DTM and starting a new one... 
     70         * but the retained RTF DTM will have been tail-pruned so should be small. 
     71         */ 
     72        private Vector m_rtfdtm_stack = null; 
     73 
     74        /** Index of currently active RTF DTM in m_rtfdtm_stack */ 
     75        private int m_which_rtfdtm = -1; 
     76 
     77        /** 
     78         * Most recent "reusable" DTM for Global Result Tree Fragments. No stack is 
     79         * required since we're never going to pop these. 
     80         */ 
     81        private SAX2RTFDTM m_global_rtfdtm = null; 
     82 
     83        /** 
     84         * Though XPathContext context extends  
     85         * the DTMManager, it really is a proxy for this object, which  
     86         * is the real DTMManager. 
     87         */ 
     88        protected DTMManager m_dtmManager = DTMManager.newInstance(org.apache.xpath.objects.XMLStringFactoryImpl.getFactory()); 
     89 
     90        /** 
     91         * Return the DTMManager object.  Though XPathContext context extends  
     92         * the DTMManager, it really is a proxy for the real DTMManager.  If a  
     93         * caller needs to make a lot of calls to the DTMManager, it is faster  
     94         * if it gets the real one from this function. 
     95         */ 
     96        public DTMManager getDTMManager() { 
     97                return m_dtmManager; 
     98        } 
     99 
     100        /** 
     101         * Get an instance of a DTM, loaded with the content from the 
     102         * specified source.  If the unique flag is true, a new instance will 
     103         * always be returned.  Otherwise it is up to the DTMManager to return a 
     104         * new instance or an instance that it already created and may be being used 
     105         * by someone else. 
     106         * (I think more parameters will need to be added for error handling, and entity 
     107         * resolution). 
     108         * 
     109         * @param source the specification of the source object, which may be null,  
     110         *               in which case it is assumed that node construction will take  
     111         *               by some other means. 
     112         * @param unique true if the returned DTM must be unique, probably because it 
     113         * is going to be mutated. 
     114         * @param whiteSpaceFilter Enables filtering of whitespace nodes, and may  
     115         *                         be null. 
     116         * @param incremental true if the construction should try and be incremental. 
     117         * @param doIndexing true if the caller considers it worth it to use  
     118         *                   indexing schemes. 
     119         * 
     120         * @return a non-null DTM reference. 
     121         */ 
     122        public DTM getDTM(javax.xml.transform.Source source, boolean unique, DTMWSFilter wsfilter, boolean incremental, boolean doIndexing) { 
     123                return m_dtmManager.getDTM(source, unique, wsfilter, incremental, doIndexing); 
     124        } 
     125 
     126        /** 
     127         * Get an instance of a DTM that "owns" a node handle.  
     128         * 
     129         * @param nodeHandle the nodeHandle. 
     130         * 
     131         * @return a non-null DTM reference. 
     132         */ 
     133        public DTM getDTM(int nodeHandle) { 
     134                return m_dtmManager.getDTM(nodeHandle); 
     135        } 
     136 
     137        /** 
     138         * Given a W3C DOM node, try and return a DTM handle. 
     139         * Note: calling this may be non-optimal. 
     140         *  
     141         * @param node Non-null reference to a DOM node. 
     142         *  
     143         * @return a valid DTM handle. 
     144         */ 
     145        public int getDTMHandleFromNode(org.w3c.dom.Node node) { 
     146                return m_dtmManager.getDTMHandleFromNode(node); 
     147        } 
     148 
     149        // 
     150        //   
     151        /** 
     152         * %TBD% Doc 
     153         */ 
     154        public int getDTMIdentity(DTM dtm) { 
     155                return m_dtmManager.getDTMIdentity(dtm); 
     156        } 
     157 
     158        //   
     159        /** 
     160         * Creates an empty <code>DocumentFragment</code> object.  
     161         * @return A new <code>DocumentFragment handle</code>. 
     162         */ 
     163        public DTM createDocumentFragment() { 
     164                return m_dtmManager.createDocumentFragment(); 
     165        } 
     166 
     167        //   
     168        /** 
     169         * Release a DTM either to a lru pool, or completely remove reference. 
     170         * DTMs without system IDs are always hard deleted. 
     171         * State: experimental. 
     172         *  
     173         * @param dtm The DTM to be released. 
     174         * @param shouldHardDelete True if the DTM should be removed no matter what. 
     175         * @return true if the DTM was removed, false if it was put back in a lru pool. 
     176         */ 
     177        public boolean release(DTM dtm, boolean shouldHardDelete) { 
     178                // %REVIEW% If it's a DTM which may contain multiple Result Tree 
     179                // Fragments, we can't discard it unless we know not only that it 
     180                // is empty, but that the XPathContext itself is going away. So do 
     181                // _not_ accept the request. (May want to do it as part of 
     182                // reset(), though.) 
     183                if (m_rtfdtm_stack != null && m_rtfdtm_stack.contains(dtm)) { return false; } 
     184 
     185                return m_dtmManager.release(dtm, shouldHardDelete); 
     186        } 
     187 
     188        /** 
     189         * Create a new <code>DTMIterator</code> based on an XPath 
     190         * <a href="http://www.w3.org/TR/xpath#NT-LocationPath>LocationPath</a> or 
     191         * a <a href="http://www.w3.org/TR/xpath#NT-UnionExpr">UnionExpr</a>. 
     192         * 
     193         * @param xpathCompiler ??? Somehow we need to pass in a subpart of the 
     194         * expression.  I hate to do this with strings, since the larger expression 
     195         * has already been parsed. 
     196         * 
     197         * @param pos The position in the expression. 
     198         * @return The newly created <code>DTMIterator</code>. 
     199         */ 
     200        public DTMIterator createDTMIterator(Object xpathCompiler, int pos) { 
     201                return m_dtmManager.createDTMIterator(xpathCompiler, pos); 
     202        } 
     203 
     204        // 
     205        /** 
     206         * Create a new <code>DTMIterator</code> based on an XPath 
     207         * <a href="http://www.w3.org/TR/xpath#NT-LocationPath>LocationPath</a> or 
     208         * a <a href="http://www.w3.org/TR/xpath#NT-UnionExpr">UnionExpr</a>. 
     209         * 
     210         * @param xpathString Must be a valid string expressing a 
     211         * <a href="http://www.w3.org/TR/xpath#NT-LocationPath>LocationPath</a> or 
     212         * a <a href="http://www.w3.org/TR/xpath#NT-UnionExpr">UnionExpr</a>. 
     213         * 
     214         * @param presolver An object that can resolve prefixes to namespace URLs. 
     215         * 
     216         * @return The newly created <code>DTMIterator</code>. 
     217         */ 
     218        public DTMIterator createDTMIterator(String xpathString, PrefixResolver presolver) { 
     219                return m_dtmManager.createDTMIterator(xpathString, presolver); 
     220        } 
     221 
     222        // 
     223        /** 
     224         * Create a new <code>DTMIterator</code> based only on a whatToShow and 
     225         * a DTMFilter.  The traversal semantics are defined as the descendant 
     226         * access. 
     227         * 
     228         * @param whatToShow This flag specifies which node types may appear in 
     229         *   the logical view of the tree presented by the iterator. See the 
     230         *   description of <code>NodeFilter</code> for the set of possible 
     231         *   <code>SHOW_</code> values.These flags can be combined using 
     232         *   <code>OR</code>. 
     233         * @param filter The <code>NodeFilter</code> to be used with this 
     234         *   <code>TreeWalker</code>, or <code>null</code> to indicate no filter. 
     235         * @param entityReferenceExpansion The value of this flag determines 
     236         *   whether entity reference nodes are expanded. 
     237         * 
     238         * @return The newly created <code>NodeIterator</code>. 
     239         */ 
     240        public DTMIterator createDTMIterator(int whatToShow, DTMFilter filter, boolean entityReferenceExpansion) { 
     241                return m_dtmManager.createDTMIterator(whatToShow, filter, entityReferenceExpansion); 
     242        } 
     243 
     244        /** 
     245         * Create a new <code>DTMIterator</code> that holds exactly one node. 
     246         * 
     247         * @param node The node handle that the DTMIterator will iterate to. 
     248         * 
     249         * @return The newly created <code>DTMIterator</code>. 
     250         */ 
     251        public DTMIterator createDTMIterator(int node) { 
     252                // DescendantIterator iter = new DescendantIterator(); 
     253                DTMIterator iter = new org.apache.xpath.axes.OneStepIteratorForward(Axis.SELF); 
     254                iter.setRoot(node, this); 
     255                return iter; 
     256                // return m_dtmManager.createDTMIterator(node); 
     257        } 
     258 
     259        /** 
     260         * Create an XPathContext instance. 
     261         */ 
     262        public XPathContext() { 
     263                m_prefixResolvers.push(null); 
     264                m_currentNodes.push(DTM.NULL); 
     265                m_currentExpressionNodes.push(DTM.NULL); 
     266                m_saxLocations.push(null); 
     267        } 
     268 
     269        /** 
     270         * Create an XPathContext instance. 
     271         * @param owner Value that can be retrieved via the getOwnerObject() method. 
     272         * @see #getOwnerObject 
     273         */ 
     274        public XPathContext(Object owner) { 
     275                m_owner = owner; 
     276                try { 
     277                        m_ownerGetErrorListener = m_owner.getClass().getMethod("getErrorListener", new Class[] {}); 
     278                } catch (NoSuchMethodException nsme) { 
     279                } 
     280                m_prefixResolvers.push(null); 
     281                m_currentNodes.push(DTM.NULL); 
     282                m_currentExpressionNodes.push(DTM.NULL); 
     283                m_saxLocations.push(null); 
     284        } 
     285 
     286        /** 
     287         * Reset for new run. 
     288         */ 
     289        public void reset() { 
     290                // These couldn't be disposed of earlier (see comments in release()); zap them now. 
     291                if (m_rtfdtm_stack != null) for (java.util.Enumeration e = m_rtfdtm_stack.elements(); e.hasMoreElements();) 
     292                        m_dtmManager.release((DTM) e.nextElement(), true); 
     293 
     294                m_rtfdtm_stack = null; // drop our references too 
     295                m_which_rtfdtm = -1; 
     296 
     297                if (m_global_rtfdtm != null) m_dtmManager.release(m_global_rtfdtm, true); 
     298                m_global_rtfdtm = null; 
     299 
     300                m_dtmManager = DTMManager.newInstance(org.apache.xpath.objects.XMLStringFactoryImpl.getFactory()); 
     301 
     302                m_saxLocations.removeAllElements(); 
     303                m_axesIteratorStack.removeAllElements(); 
     304                m_contextNodeLists.removeAllElements(); 
     305                m_currentExpressionNodes.removeAllElements(); 
     306                m_currentNodes.removeAllElements(); 
     307                m_iteratorRoots.RemoveAllNoClear(); 
     308                m_predicatePos.removeAllElements(); 
     309                m_predicateRoots.RemoveAllNoClear(); 
     310                m_prefixResolvers.removeAllElements(); 
     311 
     312                m_prefixResolvers.push(null); 
     313                m_currentNodes.push(DTM.NULL); 
     314                m_currentExpressionNodes.push(DTM.NULL); 
     315                m_saxLocations.push(null); 
     316        } 
     317 
     318        /** The current stylesheet locator. */ 
     319        ObjectStack m_saxLocations = new ObjectStack(RECURSIONLIMIT); 
     320 
     321        /** 
     322         * Set the current locater in the stylesheet. 
     323         * 
     324         * @param location The location within the stylesheet. 
     325         */ 
     326        public void setSAXLocator(SourceLocator location) { 
     327                m_saxLocations.setTop(location); 
     328        } 
     329 
     330        /** 
     331         * Set the current locater in the stylesheet. 
     332         * 
     333         * @param location The location within the stylesheet. 
     334         */ 
     335        public void pushSAXLocator(SourceLocator location) { 
     336                m_saxLocations.push(location); 
     337        } 
     338 
     339        /** 
     340         * Push a slot on the locations stack so that setSAXLocator can be  
     341         * repeatedly called. 
     342         * 
     343         * @param location The location within the stylesheet. 
     344         */ 
     345        public void pushSAXLocatorNull() { 
     346                m_saxLocations.push(null); 
     347        } 
     348 
     349        /** 
     350         * Pop the current locater. 
     351         */ 
     352        public void popSAXLocator() { 
     353                m_saxLocations.pop(); 
     354        } 
     355 
     356        /** 
     357         * Get the current locater in the stylesheet. 
     358         * 
     359         * @return The location within the stylesheet, or null if not known. 
     360         */ 
     361        public SourceLocator getSAXLocator() { 
     362                return (SourceLocator) m_saxLocations.peek(); 
     363        } 
     364 
     365        /** The owner context of this XPathContext.  In the case of XSLT, this will be a 
     366         *  Transformer object. 
     367         */ 
     368        private Object m_owner; 
     369 
     370        /** The owner context of this XPathContext.  In the case of XSLT, this will be a 
     371         *  Transformer object. 
     372         */ 
     373        private Method m_ownerGetErrorListener; 
     374 
     375        /** 
     376         * Get the "owner" context of this context, which should be, 
     377         * in the case of XSLT, the Transformer object.  This is needed 
     378         * so that XSLT functions can get the Transformer. 
     379         * @return The owner object passed into the constructor, or null. 
     380         */ 
     381        public Object getOwnerObject() { 
     382                return m_owner; 
     383        } 
     384 
     385        // ================ VarStack =================== 
     386 
     387        /** 
     388         * The stack of Variable stacks.  A VariableStack will be 
     389         * pushed onto this stack for each template invocation. 
     390         */ 
     391        private VariableStack m_variableStacks = new VariableStack(); 
     392 
     393        /** 
     394         * Get the variable stack, which is in charge of variables and 
     395         * parameters. 
     396         * 
     397         * @return the variable stack, which should not be null. 
     398         */ 
     399        public final VariableStack getVarStack() { 
     400                return m_variableStacks; 
     401        } 
     402 
     403        /**  
     404         * Get the variable stack, which is in charge of variables and 
     405         * parameters. 
     406         * 
     407         * @param varStack non-null reference to the variable stack. 
     408         */ 
     409        public final void setVarStack(VariableStack varStack) { 
     410                m_variableStacks = varStack; 
     411        } 
     412 
     413        // ================ SourceTreeManager =================== 
     414 
     415        /** The source tree manager, which associates Source objects to source  
     416         *  tree nodes. */ 
     417        private SourceTreeManager m_sourceTreeManager = new SourceTreeManager(); 
     418 
     419        /** 
     420         * Get the SourceTreeManager associated with this execution context. 
     421         * 
     422         * @return the SourceTreeManager associated with this execution context. 
     423         */ 
     424        public final SourceTreeManager getSourceTreeManager() { 
     425                return m_sourceTreeManager; 
     426        } 
     427 
     428        /** 
     429         * Set the SourceTreeManager associated with this execution context. 
     430         * 
     431         * @param mgr the SourceTreeManager to be associated with this  
     432         *        execution context. 
     433         */ 
     434        public void setSourceTreeManager(SourceTreeManager mgr) { 
     435                m_sourceTreeManager = mgr; 
     436        } 
     437 
     438        // ================================================= 
     439 
     440        /** The ErrorListener where errors and warnings are to be reported.   */ 
     441        private ErrorListener m_errorListener; 
     442 
     443        /** A default ErrorListener in case our m_errorListener was not specified and our 
     444         *  owner either does not have an ErrorListener or has a null one. 
     445         */ 
     446        private ErrorListener m_defaultErrorListener; 
     447 
     448        /** 
     449         * Get the ErrorListener where errors and warnings are to be reported. 
     450         * 
     451         * @return A non-null ErrorListener reference. 
     452         */ 
     453        public final ErrorListener getErrorListener() { 
     454 
     455                if (null != m_errorListener) return m_errorListener; 
     456 
     457                ErrorListener retval = null; 
     458 
     459                try { 
     460                        if (null != m_ownerGetErrorListener) retval = (ErrorListener) m_ownerGetErrorListener.invoke(m_owner, new Object[] {}); 
     461                } catch (Exception e) { 
     462                } 
     463 
     464                if (null == retval) { 
     465                        if (null == m_defaultErrorListener) m_defaultErrorListener = new org.apache.xml.utils.DefaultErrorHandler(); 
     466                        retval = m_defaultErrorListener; 
     467                } 
     468 
     469                return retval; 
     470        } 
     471 
     472        /** 
     473         * Set the ErrorListener where errors and warnings are to be reported. 
     474         * 
     475         * @param listener A non-null ErrorListener reference. 
     476         */ 
     477        public void setErrorListener(ErrorListener listener) throws IllegalArgumentException { 
     478                if (listener == null) throw new IllegalArgumentException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NULL_ERROR_HANDLER, null)); //"Null error handler"); 
     479                m_errorListener = listener; 
     480        } 
     481 
     482        // ================================================= 
     483 
     484        /** The TrAX URI Resolver for resolving URIs from the document(...) 
     485         *  function to source tree nodes.  */ 
     486        private URIResolver m_uriResolver; 
     487 
     488        /** 
     489         * Get the URIResolver associated with this execution context. 
     490         * 
     491         * @return a URI resolver, which may be null. 
     492         */ 
     493        public final URIResolver getURIResolver() { 
     494                return m_uriResolver; 
     495        } 
     496 
     497        /** 
     498         * Set the URIResolver associated with this execution context. 
     499         * 
     500         * @param resolver the URIResolver to be associated with this  
     501         *        execution context, may be null to clear an already set resolver. 
     502         */ 
     503        public void setURIResolver(URIResolver resolver) { 
     504                m_uriResolver = resolver; 
     505        } 
     506 
     507        // ================================================= 
     508 
     509        /** The reader of the primary source tree.    */ 
     510        public XMLReader m_primaryReader; 
     511 
     512        /** 
     513         * Get primary XMLReader associated with this execution context. 
     514         * 
     515         * @return The reader of the primary source tree. 
     516         */ 
     517        public final XMLReader getPrimaryReader() { 
     518                return m_primaryReader; 
     519        } 
     520 
     521        /** 
     522         * Set primary XMLReader associated with this execution context. 
     523         * 
     524         * @param reader The reader of the primary source tree. 
     525         */ 
     526        public void setPrimaryReader(XMLReader reader) { 
     527                m_primaryReader = reader; 
     528        } 
     529 
     530        // ================================================= 
     531 
     532        /** Misnamed string manager for XPath messages.  */ 
     533        // private static XSLMessages m_XSLMessages = new XSLMessages(); 
     534        /** 
     535         * Tell the user of an assertion error, and probably throw an 
     536         * exception. 
     537         * 
     538         * @param b  If false, a TransformerException will be thrown. 
     539         * @param msg The assertion message, which should be informative. 
     540         *  
     541         * @throws javax.xml.transform.TransformerException if b is false. 
     542         */ 
     543        private void assertion(boolean b, String msg) throws javax.xml.transform.TransformerException { 
     544                if (!b) { 
     545                        ErrorListener errorHandler = getErrorListener(); 
     546 
     547                        if (errorHandler != null) { 
     548                                errorHandler.fatalError(new TransformerException(XSLMessages.createMessage(XPATHErrorResources.ER_INCORRECT_PROGRAMMER_ASSERTION, new Object[] { msg }), (SAXSourceLocator) this.getSAXLocator())); 
     549                        } 
     550                } 
     551        } 
     552 
     553        //========================================================== 
     554        // SECTION: Execution context state tracking 
     555        //========================================================== 
     556 
     557        /** 
     558         * The current context node list. 
     559         */ 
     560        private Stack m_contextNodeLists = new Stack(); 
     561 
     562        public Stack getContextNodeListsStack() { 
     563                return m_contextNodeLists; 
     564        } 
     565 
     566        public void setContextNodeListsStack(Stack s) { 
     567                m_contextNodeLists = s; 
     568        } 
     569 
     570        /** 
     571         * Get the current context node list. 
     572         * 
     573         * @return  the <a href="http://www.w3.org/TR/xslt#dt-current-node-list">current node list</a>, 
     574         * also refered to here as a <term>context node list</term>. 
     575         */ 
     576        public final DTMIterator getContextNodeList() { 
     577 
     578                if (m_contextNodeLists.size() > 0) 
     579                        return (DTMIterator) m_contextNodeLists.peek(); 
     580                else return null; 
     581        } 
     582 
     583        /** 
     584         * Set the current context node list. 
     585         * 
     586         * @param nl the <a href="http://www.w3.org/TR/xslt#dt-current-node-list">current node list</a>, 
     587         * also refered to here as a <term>context node list</term>. 
     588         * @xsl.usage internal 
     589         */ 
     590        public final void pushContextNodeList(DTMIterator nl) { 
     591                m_contextNodeLists.push(nl); 
     592        } 
     593 
     594        /** 
     595         * Pop the current context node list. 
     596         * @xsl.usage internal 
     597         */ 
     598        public final void popContextNodeList() { 
     599                if (m_contextNodeLists.isEmpty()) 
     600                        System.err.println("Warning: popContextNodeList when stack is empty!"); 
     601                else m_contextNodeLists.pop(); 
     602        } 
     603 
     604        /** 
     605         * The ammount to use for stacks that record information during the  
     606         * recursive execution. 
     607         */ 
     608        public static final int RECURSIONLIMIT = (1024 * 4); 
     609 
     610        /** The stack of <a href="http://www.w3.org/TR/xslt#dt-current-node">current node</a> objects. 
     611         *  Not to be confused with the current node list.  %REVIEW% Note that there  
     612         *  are no bounds check and resize for this stack, so if it is blown, it's all  
     613         *  over.  */ 
     614        private IntStack m_currentNodes = new IntStack(RECURSIONLIMIT); 
     615 
     616        //  private NodeVector m_currentNodes = new NodeVector(); 
     617 
     618        public IntStack getCurrentNodeStack() { 
     619                return m_currentNodes; 
     620        } 
     621 
     622        public void setCurrentNodeStack(IntStack nv) { 
     623                m_currentNodes = nv; 
     624        } 
     625 
     626        /** 
     627         * Get the current context node. 
     628         * 
     629         * @return the <a href="http://www.w3.org/TR/xslt#dt-current-node">current node</a>. 
     630         */ 
     631        public final int getCurrentNode() { 
     632                return m_currentNodes.peek(); 
     633        } 
     634 
     635        /** 
     636         * Set the current context node and expression node. 
     637         * 
     638         * @param cn the <a href="http://www.w3.org/TR/xslt#dt-current-node">current node</a>. 
     639         * @param en the sub-expression context node. 
     640         */ 
     641        public final void pushCurrentNodeAndExpression(int cn, int en) { 
     642                m_currentNodes.push(cn); 
     643                m_currentExpressionNodes.push(cn); 
     644        } 
     645 
     646        /** 
     647         * Set the current context node. 
     648         */ 
     649        public final void popCurrentNodeAndExpression() { 
     650                m_currentNodes.quickPop(1); 
     651                m_currentExpressionNodes.quickPop(1); 
     652        } 
     653 
     654        /** 
     655         * Push the current context node, expression node, and prefix resolver. 
     656         * 
     657         * @param cn the <a href="http://www.w3.org/TR/xslt#dt-current-node">current node</a>. 
     658         * @param en the sub-expression context node. 
     659         * @param nc the namespace context (prefix resolver. 
     660         */ 
     661        public final void pushExpressionState(int cn, int en, PrefixResolver nc) { 
     662                m_currentNodes.push(cn); 
     663                m_currentExpressionNodes.push(cn); 
     664                m_prefixResolvers.push(nc); 
     665        } 
     666 
     667        /** 
     668         * Pop the current context node, expression node, and prefix resolver. 
     669         */ 
     670        public final void popExpressionState() { 
     671                m_currentNodes.quickPop(1); 
     672                m_currentExpressionNodes.quickPop(1); 
     673                m_prefixResolvers.pop(); 
     674        } 
     675 
     676        /** 
     677         * Set the current context node. 
     678         * 
     679         * @param n the <a href="http://www.w3.org/TR/xslt#dt-current-node">current node</a>. 
     680         */ 
     681        public final void pushCurrentNode(int n) { 
     682                m_currentNodes.push(n); 
     683        } 
     684 
     685        /** 
     686         * Pop the current context node. 
     687         */ 
     688        public final void popCurrentNode() { 
     689                m_currentNodes.quickPop(1); 
     690        } 
     691 
     692        /** 
     693         * Set the current predicate root. 
     694         */ 
     695        public final void pushPredicateRoot(int n) { 
     696                m_predicateRoots.push(n); 
     697        } 
     698 
     699        /** 
     700         * Pop the current predicate root. 
     701         */ 
     702        public final void popPredicateRoot() { 
     703                m_predicateRoots.popQuick(); 
     704        } 
     705 
     706        /** 
     707         * Get the current predicate root. 
     708         */ 
     709        public final int getPredicateRoot() { 
     710                return m_predicateRoots.peepOrNull(); 
     711        } 
     712 
     713        /** 
     714         * Set the current location path iterator root. 
     715         */ 
     716        public final void pushIteratorRoot(int n) { 
     717                m_iteratorRoots.push(n); 
     718        } 
     719 
     720        /** 
     721         * Pop the current location path iterator root. 
     722         */ 
     723        public final void popIteratorRoot() { 
     724                m_iteratorRoots.popQuick(); 
     725        } 
     726 
     727        /** 
     728         * Get the current location path iterator root. 
     729         */ 
     730        public final int getIteratorRoot() { 
     731                return m_iteratorRoots.peepOrNull(); 
     732        } 
     733 
     734        /** A stack of the current sub-expression nodes.  */ 
     735        private NodeVector m_iteratorRoots = new NodeVector(); 
     736 
     737        /** A stack of the current sub-expression nodes.  */ 
     738        private NodeVector m_predicateRoots = new NodeVector(); 
     739 
     740        /** A stack of the current sub-expression nodes.  */ 
     741        private IntStack m_currentExpressionNodes = new IntStack(RECURSIONLIMIT); 
     742 
     743        public IntStack getCurrentExpressionNodeStack() { 
     744                return m_currentExpressionNodes; 
     745        } 
     746 
     747        public void setCurrentExpressionNodeStack(IntStack nv) { 
     748                m_currentExpressionNodes = nv; 
     749        } 
     750 
     751        private IntStack m_predicatePos = new IntStack(); 
     752 
     753        public final int getPredicatePos() { 
     754                return m_predicatePos.peek(); 
     755        } 
     756 
     757        public final void pushPredicatePos(int n) { 
     758                m_predicatePos.push(n); 
     759        } 
     760 
     761        public final void popPredicatePos() { 
     762                m_predicatePos.pop(); 
     763        } 
     764 
     765        /** 
     766         * Get the current node that is the expression's context (i.e. for current() support). 
     767         * 
     768         * @return The current sub-expression node. 
     769         */ 
     770        public final int getCurrentExpressionNode() { 
     771                return m_currentExpressionNodes.peek(); 
     772        } 
     773 
     774        /** 
     775         * Set the current node that is the expression's context (i.e. for current() support). 
     776         * 
     777         * @param n The sub-expression node to be current. 
     778         */ 
     779        public final void pushCurrentExpressionNode(int n) { 
     780                m_currentExpressionNodes.push(n); 
     781        } 
     782 
     783        /** 
     784         * Pop the current node that is the expression's context  
     785         * (i.e. for current() support). 
     786         */ 
     787        public final void popCurrentExpressionNode() { 
     788                m_currentExpressionNodes.quickPop(1); 
     789        } 
     790 
     791        private ObjectStack m_prefixResolvers = new ObjectStack(RECURSIONLIMIT); 
     792 
     793        /** 
     794         * Get the current namespace context for the xpath. 
     795         * 
     796         * @return the current prefix resolver for resolving prefixes to  
     797         *         namespace URLs. 
     798         */ 
     799        public final PrefixResolver getNamespaceContext() { 
     800                return (PrefixResolver) m_prefixResolvers.peek(); 
     801        } 
     802 
     803        /** 
     804         * Get the current namespace context for the xpath. 
     805         * 
     806         * @param pr the prefix resolver to be used for resolving prefixes to  
     807         *         namespace URLs. 
     808         */ 
     809        public final void setNamespaceContext(PrefixResolver pr) { 
     810                m_prefixResolvers.setTop(pr); 
     811        } 
     812 
     813        /** 
     814         * Push a current namespace context for the xpath. 
     815         * 
     816         * @param pr the prefix resolver to be used for resolving prefixes to  
     817         *         namespace URLs. 
     818         */ 
     819        public final void pushNamespaceContext(PrefixResolver pr) { 
     820                m_prefixResolvers.push(pr); 
     821        } 
     822 
     823        /** 
     824         * Just increment the namespace contest stack, so that setNamespaceContext 
     825         * can be used on the slot. 
     826         */ 
     827        public final void pushNamespaceContextNull() { 
     828                m_prefixResolvers.push(null); 
     829        } 
     830 
     831        /** 
     832         * Pop the current namespace context for the xpath. 
     833         */ 
     834        public final void popNamespaceContext() { 
     835                m_prefixResolvers.pop(); 
     836        } 
     837 
     838        //========================================================== 
     839        // SECTION: Current TreeWalker contexts (for internal use) 
     840        //========================================================== 
     841 
     842        /** 
     843         * Stack of AxesIterators. 
     844         */ 
     845        private Stack m_axesIteratorStack = new Stack(); 
     846 
     847        public Stack getAxesIteratorStackStacks() { 
     848                return m_axesIteratorStack; 
     849        } 
     850 
     851        public void setAxesIteratorStackStacks(Stack s) { 
     852                m_axesIteratorStack = s; 
     853        } 
     854 
     855        /** 
     856         * Push a TreeWalker on the stack. 
     857         * 
     858         * @param iter A sub-context AxesWalker. 
     859         * @xsl.usage internal 
     860         */ 
     861        public final void pushSubContextList(SubContextList iter) { 
     862                m_axesIteratorStack.push(iter); 
     863        } 
     864 
     865        /** 
     866         * Pop the last pushed axes iterator. 
     867         * @xsl.usage internal 
     868         */ 
     869        public final void popSubContextList() { 
     870                m_axesIteratorStack.pop(); 
     871        } 
     872 
     873        /** 
     874         * Get the current axes iterator, or return null if none. 
     875         * 
     876         * @return the sub-context node list. 
     877         * @xsl.usage internal 
     878         */ 
     879        public SubContextList getSubContextList() { 
     880                return m_axesIteratorStack.isEmpty() ? null : (SubContextList) m_axesIteratorStack.peek(); 
     881        } 
     882 
     883        /** 
     884         * Get the <a href="http://www.w3.org/TR/xslt#dt-current-node-list">current node list</a>  
     885         * as defined by the XSLT spec. 
     886         * 
     887         * @return the <a href="http://www.w3.org/TR/xslt#dt-current-node-list">current node list</a>. 
     888         * @xsl.usage internal 
     889         */ 
     890 
     891        public org.apache.xpath.axes.SubContextList getCurrentNodeList() { 
     892                return m_axesIteratorStack.isEmpty() ? null : (SubContextList) m_axesIteratorStack.elementAt(0); 
     893        } 
     894 
     895        //========================================================== 
     896        // SECTION: Implementation of ExpressionContext interface 
     897        //========================================================== 
     898 
     899        /** 
     900         * Get the current context node. 
     901         * @return The current context node. 
     902         */ 
     903        public final int getContextNode() { 
     904                return this.getCurrentNode(); 
     905        } 
     906 
     907        /** 
     908         * Get the current context node list. 
     909         * @return An iterator for the current context list, as 
     910         * defined in XSLT. 
     911         */ 
     912        public final DTMIterator getContextNodes() { 
     913 
     914                try { 
     915                        DTMIterator cnl = getContextNodeList(); 
     916 
     917                        if (null != cnl) 
     918                                return cnl.cloneWithReset(); 
     919                        else return null; // for now... this might ought to be an empty iterator. 
     920                } catch (CloneNotSupportedException cnse) { 
     921                        return null; // error reporting? 
     922                } 
     923        } 
     924 
     925        XPathExpressionContext expressionContext = new XPathExpressionContext(); 
     926 
     927        /** 
     928         * The the expression context for extensions for this context. 
     929         *  
     930         * @return An object that implements the ExpressionContext. 
     931         */ 
     932        public ExpressionContext getExpressionContext() { 
     933                return expressionContext; 
     934        } 
     935 
     936        public class XPathExpressionContext implements ExpressionContext { 
     937                /** 
     938                 * Return the XPathContext associated with this XPathExpressionContext. 
     939                 * Extensions should use this judiciously and only when special processing 
     940                 * requirements cannot be met another way.  Consider requesting an enhancement 
     941                 * to the ExpressionContext interface to avoid having to call this method. 
     942                 * @return the XPathContext associated with this XPathExpressionContext. 
     943                 */ 
     944                public XPathContext getXPathContext() { 
     945                        return XPathContext.this; 
     946                } 
     947 
     948                /** 
     949                 * Return the DTMManager object.  Though XPathContext context extends  
     950                 * the DTMManager, it really is a proxy for the real DTMManager.  If a  
     951                 * caller needs to make a lot of calls to the DTMManager, it is faster  
     952                 * if it gets the real one from this function. 
     953                 */ 
     954                public DTMManager getDTMManager() { 
     955                        return m_dtmManager; 
     956                } 
     957 
     958                /** 
     959                 * Get the current context node. 
     960                 * @return The current context node. 
     961                 */ 
     962                public org.w3c.dom.Node getContextNode() { 
     963                        int context = getCurrentNode(); 
     964 
     965                        return getDTM(context).getNode(context); 
     966                } 
     967 
     968                /** 
     969                 * Get the current context node list. 
     970                 * @return An iterator for the current context list, as 
     971                 * defined in XSLT. 
     972                 */ 
     973                public org.w3c.dom.traversal.NodeIterator getContextNodes() { 
     974                        return new org.apache.xml.dtm.ref.DTMNodeIterator(getContextNodeList()); 
     975                } 
     976 
     977                /** 
     978                 * Get the error listener. 
     979                 * @return The registered error listener. 
     980                 */ 
     981                public ErrorListener getErrorListener() { 
     982                        return XPathContext.this.getErrorListener(); 
     983                } 
     984 
     985                /** 
     986                 * Get the value of a node as a number. 
     987                 * @param n Node to be converted to a number.  May be null. 
     988                 * @return value of n as a number. 
     989                 */ 
     990                public double toNumber(org.w3c.dom.Node n) { 
     991                        // %REVIEW% You can't get much uglier than this... 
     992                        int nodeHandle = getDTMHandleFromNode(n); 
     993                        DTM dtm = getDTM(nodeHandle); 
     994                        XString xobj = (XString) dtm.getStringValue(nodeHandle); 
     995                        return xobj.num(); 
     996                } 
     997 
     998                /** 
     999                 * Get the value of a node as a string. 
     1000                 * @param n Node to be converted to a string.  May be null. 
     1001                 * @return value of n as a string, or an empty string if n is null. 
     1002                 */ 
     1003                public String toString(org.w3c.dom.Node n) { 
     1004                        // %REVIEW% You can't get much uglier than this... 
     1005                        int nodeHandle = getDTMHandleFromNode(n); 
     1006                        DTM dtm = getDTM(nodeHandle); 
     1007                        XMLString strVal = dtm.getStringValue(nodeHandle); 
     1008                        return strVal.toString(); 
     1009                } 
     1010 
     1011                /** 
     1012                 * Get a variable based on it's qualified name. 
     1013                 * @param qname The qualified name of the variable. 
     1014                 * @return The evaluated value of the variable. 
     1015                 * @throws javax.xml.transform.TransformerException 
     1016                 */ 
     1017 
     1018                public final XObject getVariableOrParam(org.apache.xml.utils.QName qname) throws javax.xml.transform.TransformerException { 
     1019                        return m_variableStacks.getVariableOrParam(XPathContext.this, qname); 
     1020                } 
     1021 
     1022        } 
     1023 
     1024        /** 
     1025         * Get a DTM to be used as a container for a global Result Tree 
     1026         * Fragment. This will always be an instance of (derived from? equivalent to?)  
     1027         * SAX2DTM, since each RTF is constructed by temporarily redirecting our SAX  
     1028         * output to it. It may be a single DTM containing for multiple fragments,  
     1029         * if the implementation supports that. 
     1030         *  
     1031         * Note: The distinction between this method and getRTFDTM() is that the latter 
     1032         * allocates space from the dynamic variable stack (m_rtfdtm_stack), which may 
     1033         * be pruned away again as the templates which defined those variables are exited. 
     1034         * Global variables may be bound late (see XUnresolvedVariable), and never want to 
     1035         * be discarded, hence we need to allocate them separately and don't actually need 
     1036         * a stack to track them. 
     1037         *  
     1038         * @return a non-null DTM reference. 
     1039         */ 
     1040        public DTM getGlobalRTFDTM() { 
     1041                // We probably should _NOT_ be applying whitespace filtering at this stage! 
     1042                // 
     1043                // Some magic has been applied in DTMManagerDefault to recognize this set of options 
     1044                // and generate an instance of DTM which can contain multiple documents 
     1045                // (SAX2RTFDTM). Perhaps not the optimal way of achieving that result, but 
     1046                // I didn't want to change the manager API at this time, or expose  
     1047                // too many dependencies on its internals. (Ideally, I'd like to move 
     1048                // isTreeIncomplete all the way up to DTM, so we wouldn't need to explicitly 
     1049                // specify the subclass here.) 
     1050 
     1051                // If it doesn't exist, or if the one already existing is in the middle of 
     1052                // being constructed, we need to obtain a new DTM to write into. I'm not sure 
     1053                // the latter will ever arise, but I'd rather be just a bit paranoid.. 
     1054                if (m_global_rtfdtm == null || m_global_rtfdtm.isTreeIncomplete()) { 
     1055                        m_global_rtfdtm = (SAX2RTFDTM) m_dtmManager.getDTM(null, true, null, false, false); 
     1056                } 
     1057                return m_global_rtfdtm; 
     1058        } 
     1059 
     1060        /** 
     1061         * Get a DTM to be used as a container for a dynamic Result Tree 
     1062         * Fragment. This will always be an instance of (derived from? equivalent to?)  
     1063         * SAX2DTM, since each RTF is constructed by temporarily redirecting our SAX  
     1064         * output to it. It may be a single DTM containing for multiple fragments,  
     1065         * if the implementation supports that. 
     1066         *  
     1067         * @return a non-null DTM reference. 
     1068         */ 
     1069        public DTM getRTFDTM() { 
     1070                SAX2RTFDTM rtfdtm; 
     1071 
     1072                // We probably should _NOT_ be applying whitespace filtering at this stage! 
     1073                // 
     1074                // Some magic has been applied in DTMManagerDefault to recognize this set of options 
     1075                // and generate an instance of DTM which can contain multiple documents 
     1076                // (SAX2RTFDTM). Perhaps not the optimal way of achieving that result, but 
     1077                // I didn't want to change the manager API at this time, or expose  
     1078                // too many dependencies on its internals. (Ideally, I'd like to move 
     1079                // isTreeIncomplete all the way up to DTM, so we wouldn't need to explicitly 
     1080                // specify the subclass here.) 
     1081 
     1082                if (m_rtfdtm_stack == null) { 
     1083                        m_rtfdtm_stack = new Vector(); 
     1084                        rtfdtm = (SAX2RTFDTM) m_dtmManager.getDTM(null, true, null, false, false); 
     1085                        m_rtfdtm_stack.addElement(rtfdtm); 
     1086                        ++m_which_rtfdtm; 
     1087                } else if (m_which_rtfdtm < 0) { 
     1088                        rtfdtm = (SAX2RTFDTM) m_rtfdtm_stack.elementAt(++m_which_rtfdtm); 
     1089                } else { 
     1090                        rtfdtm = (SAX2RTFDTM) m_rtfdtm_stack.elementAt(m_which_rtfdtm); 
     1091 
     1092                        // It might already be under construction -- the classic example would be 
     1093                        // an xsl:variable which uses xsl:call-template as part of its value. To 
     1094                        // handle this recursion, we have to start a new RTF DTM, pushing the old 
     1095                        // one onto a stack so we can return to it. This is not as uncommon a case 
     1096                        // as we might wish, unfortunately, as some folks insist on coding XSLT 
     1097                        // as if it were a procedural language... 
     1098                        if (rtfdtm.isTreeIncomplete()) { 
     1099                                if (++m_which_rtfdtm < m_rtfdtm_stack.size()) 
     1100                                        rtfdtm = (SAX2RTFDTM) m_rtfdtm_stack.elementAt(m_which_rtfdtm); 
     1101                                else { 
     1102                                        rtfdtm = (SAX2RTFDTM) m_dtmManager.getDTM(null, true, null, false, false); 
     1103                                        m_rtfdtm_stack.addElement(rtfdtm); 
     1104                                } 
     1105                        } 
     1106                } 
     1107 
     1108                return rtfdtm; 
     1109        } 
     1110 
     1111        /** Push the RTFDTM's context mark, to allows discarding RTFs added after this 
     1112         * point. (If it doesn't exist we don't push, since we might still be able to  
     1113         * get away with not creating it. That requires that excessive pops be harmless.) 
     1114         * */ 
     1115        public void pushRTFContext() { 
     1116                m_last_pushed_rtfdtm.push(m_which_rtfdtm); 
     1117                if (null != m_rtfdtm_stack) ((SAX2RTFDTM) (getRTFDTM())).pushRewindMark(); 
     1118        } 
     1119 
     1120        /** Pop the RTFDTM's context mark. This discards any RTFs added after the last 
     1121         * mark was set.  
     1122         *  
     1123         * If there is no RTF DTM, there's nothing to pop so this 
     1124         * becomes a no-op. If pushes were issued before this was called, we count on 
     1125         * the fact that popRewindMark is defined such that overpopping just resets 
     1126         * to empty. 
     1127         *  
     1128         * Complicating factor: We need to handle the case of popping back to a previous 
     1129         * RTF DTM, if one of the weird produce-an-RTF-to-build-an-RTF cases arose. 
     1130         * Basically: If pop says this DTM is now empty, then return to the previous 
     1131         * if one exists, in whatever state we left it in. UGLY, but hopefully the 
     1132         * situation which forces us to consider this will arise exceedingly rarely. 
     1133         * */ 
     1134        public void popRTFContext() { 
     1135                int previous = m_last_pushed_rtfdtm.pop(); 
     1136                if (null == m_rtfdtm_stack) return; 
     1137 
     1138                if (m_which_rtfdtm == previous) { 
     1139                        if (previous >= 0) // guard against none-active 
     1140                        { 
     1141                                ((SAX2RTFDTM) (m_rtfdtm_stack.elementAt(previous))).popRewindMark(); 
     1142                        } 
     1143                } else while (m_which_rtfdtm != previous) { 
     1144                        // Empty each DTM before popping, so it's ready for reuse 
     1145                        // _DON'T_ pop the previous, since it's still open (which is why we 
     1146                        // stacked up more of these) and did not receive a mark. 
     1147                        ((SAX2RTFDTM) (m_rtfdtm_stack.elementAt(m_which_rtfdtm))).popRewindMark(); 
     1148                        --m_which_rtfdtm; 
     1149                } 
     1150        } 
    12591151} 
Note: See TracChangeset for help on using the changeset viewer.