You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by sb...@apache.org on 2002/03/22 02:04:45 UTC

cvs commit: xml-xalan/java/src/org/apache/xpath/patterns FunctionPattern.java NodeTest.java StepPattern.java UnionPattern.java

sboag       02/03/21 17:04:45

  Modified:    java/src/org/apache/xalan Version.java
               java/src/org/apache/xalan/lib/sql DTMDocument.java
               java/src/org/apache/xalan/processor ProcessorKey.java
                        ProcessorPreserveSpace.java
                        ProcessorStripSpace.java StylesheetHandler.java
                        XSLTAttributeDef.java XSLTElementProcessor.java
               java/src/org/apache/xalan/templates AVT.java AVTPart.java
                        AVTPartSimple.java AVTPartXPath.java
                        ElemApplyTemplates.java ElemAttribute.java
                        ElemCallTemplate.java ElemChoose.java
                        ElemCopyOf.java ElemElement.java
                        ElemExtensionCall.java ElemForEach.java ElemIf.java
                        ElemLiteralResult.java ElemNumber.java
                        ElemTemplateElement.java ElemValueOf.java
                        ElemVariable.java ElemWhen.java ElemWithParam.java
                        FuncDocument.java FuncKey.java Stylesheet.java
                        WhiteSpaceInfo.java
               java/src/org/apache/xalan/trace TraceManager.java
               java/src/org/apache/xalan/transformer KeyIterator.java
                        KeyManager.java KeyRefIterator.java KeyTable.java
                        NodeSorter.java ResultTreeHandler.java
                        TransformerHandlerImpl.java
               java/src/org/apache/xml/utils NodeVector.java
               java/src/org/apache/xpath Expression.java VariableStack.java
                        XPath.java
               java/src/org/apache/xpath/axes AttributeIterator.java
                        AxesWalker.java ChildIterator.java
                        ChildTestIterator.java DescendantIterator.java
                        FilterExprWalker.java IteratorPool.java
                        LocPathIterator.java MatchPatternIterator.java
                        OneStepIterator.java OneStepIteratorForward.java
                        PredicatedNodeTest.java ReverseAxesWalker.java
                        SelfIteratorNoPredicate.java UnionPathIterator.java
                        WalkerFactory.java WalkingIterator.java
                        WalkingIteratorSorted.java
               java/src/org/apache/xpath/compiler Compiler.java
               java/src/org/apache/xpath/functions FuncBoolean.java
                        FuncCount.java FuncExtFunction.java Function.java
                        Function2Args.java Function3Args.java
                        FunctionMultiArgs.java FunctionOneArg.java
               java/src/org/apache/xpath/objects XBoolean.java
                        XNodeSet.java XNodeSetForDOM.java XNumber.java
                        XObject.java XRTreeFrag.java
                        XRTreeFragSelectWrapper.java XString.java
                        XStringForFSB.java
               java/src/org/apache/xpath/operations Bool.java Equals.java
                        Operation.java UnaryOperation.java Variable.java
               java/src/org/apache/xpath/patterns FunctionPattern.java
                        NodeTest.java StepPattern.java UnionPattern.java
  Added:       java/src/org/apache/xalan/processor WhitespaceInfoPaths.java
               java/src/org/apache/xalan/templates AbsPathChecker.java
                        ElemVariablePsuedo.java
                        RedundentExprEliminator.java VarNameCollector.java
                        XSLTVisitable.java XSLTVisitor.java
                        XUnresolvedVariableSimple.java
               java/src/org/apache/xpath ExpressionNode.java
                        ExpressionOwner.java XPathVisitable.java
                        XPathVisitor.java
               java/src/org/apache/xpath/axes BasicTestIterator.java
                        FilterExprIterator.java
                        FilterExprIteratorSimple.java
                        HasPositionalPredChecker.java NodeSequence.java
                        PathComponent.java UnionChildIterator.java
               java/src/org/apache/xpath/operations VariableSafeAbsRef.java
  Removed:     java/src/org/apache/xalan/transformer KeyWalker.java
  Log:
  Redundent Expression Elimination branch merge.
  
  Major architectural changes
  1) Rip out cacheing in all iterators, and move the caching into XNodeSet (actually NodeSequence where the caching is done derives from XObject and XNodeSet derives from NodeSequence).Lots of other changes went into this, including rewriting of some of the xsl:key stuff.
  
  2) Implementation of a Visitor mechanism for the stylesheet and xpath components.Each component for an XPath event is passed an ExpressionOwner, which just has a getExpression and setExpression method, which allows us to create a list of these, and then be able to do rewrites.This should be a generally useful mechanism for all sorts of stuff, and should be considered a public API.
  
  3) Implementation of deepEquality methods for all XPath components, which allows us to see if two components are equal.
  
  4) Implementation of RedundentExprEliminator, which is a derivative from the new XSLTVisitor class, which runs over the stylesheet collecting xpaths within the same scope, and absolute xpaths that are not context dependent.These are then each reduced by walking the list and checking for deep equality (though global paths are always reduced).Reduction takes place by creating variables that have a special namespace and a non-legal local name.Both full and partial path reduction done.
  
  Not done yet: Add back in the xsl:key caching that I ripped out (not a big deal).Could be skipped, with some risk.
  
  Not done yet: Implement isLast function.With the new stuff, the last() function will be slower, so, since most cases are just checking to see if an item is the last, I want to rewrite foo[last()] patterns to foo[xalan:isLast()].Could be skipped, with some risk.
  
  Davanum performance test result: 4x increase in performance.
  
  Datapower performance suite results: very slight decrease in overall performance.:-(
  
  Smoke test results: All clear when run with Xerces 1.
  
  Revision  Changes    Path
  1.6       +5 -1      xml-xalan/java/src/org/apache/xalan/Version.java
  
  Index: Version.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/Version.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- Version.java	6 Feb 2002 19:30:34 -0000	1.5
  +++ Version.java	22 Mar 2002 01:04:39 -0000	1.6
  @@ -102,7 +102,7 @@
      */
     public static String getProduct()
     {
  -    return org.apache.xalan.processor.XSLProcessorVersion.PRODUCT;
  +    return "Xalan";
     }
   
     /**
  @@ -126,6 +126,7 @@
      */
     public static int getMajorVersionNum()
     {
  +    // return 2;
       // NOTE: In post 2.2 builds, we should remove XSLProcessorVersion
       //  and simply store this info here or in the build.xml and use 
       //  Ant's filtering capability to replace it here
  @@ -143,6 +144,7 @@
      */
     public static int getReleaseVersionNum()
     {
  +    //return 2;
       return org.apache.xalan.processor.XSLProcessorVersion.RELEASE;
     }
   
  @@ -157,6 +159,7 @@
      */
     public static int getMaintenanceVersionNum()
     {
  +    //return 0;
       return org.apache.xalan.processor.XSLProcessorVersion.MAINTENANCE;
     }
   
  @@ -179,6 +182,7 @@
      */
     public static int getDevelopmentVersionNum()
     {
  +    //return 13;
       return org.apache.xalan.processor.XSLProcessorVersion.DEVELOPMENT;
     }
   }
  
  
  
  1.8       +1 -13     xml-xalan/java/src/org/apache/xalan/lib/sql/DTMDocument.java
  
  Index: DTMDocument.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/lib/sql/DTMDocument.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- DTMDocument.java	8 Feb 2002 23:33:49 -0000	1.7
  +++ DTMDocument.java	22 Mar 2002 01:04:39 -0000	1.8
  @@ -1469,8 +1469,7 @@
       return super._firstch( parm1);
     }
   
  -  /** This call should follow DOM semantics, where the owner of a Document node
  -   * is null.
  +  /**
      * @param parm1
      * @return
      */
  @@ -1478,17 +1477,6 @@
     {
       if (DEBUG) System.out.println("getOwnerDoc("+parm1+")");
       return super.getOwnerDocument( parm1);
  -  }
  -
  -  /** This call should follow DTM semantics, where the owner of a Document node
  -   * is itself.
  -   * @param parm1
  -   * @return
  -   */
  -  public int getDocumentRoot( int parm1 )
  -  {
  -    if (DEBUG) System.out.println("getOwnerDoc("+parm1+")");
  -    return super.getDocumentRoot( parm1);
     }
   
     /**
  
  
  
  1.10      +2 -1      xml-xalan/java/src/org/apache/xalan/processor/ProcessorKey.java
  
  Index: ProcessorKey.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/processor/ProcessorKey.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- ProcessorKey.java	30 Nov 2000 09:57:30 -0000	1.9
  +++ ProcessorKey.java	22 Mar 2002 01:04:40 -0000	1.10
  @@ -121,7 +121,8 @@
      * @param target The target element where the properties will be set.
      */
     void setPropertiesFromAttributes(
  -          StylesheetHandler handler, String rawName, Attributes attributes, Object target)
  +          StylesheetHandler handler, String rawName, Attributes attributes, 
  +          org.apache.xalan.templates.ElemTemplateElement target)
               throws org.xml.sax.SAXException
     {
   
  
  
  
  1.8       +7 -37     xml-xalan/java/src/org/apache/xalan/processor/ProcessorPreserveSpace.java
  
  Index: ProcessorPreserveSpace.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/processor/ProcessorPreserveSpace.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- ProcessorPreserveSpace.java	30 Nov 2000 09:57:30 -0000	1.7
  +++ ProcessorPreserveSpace.java	22 Mar 2002 01:04:40 -0000	1.8
  @@ -75,38 +75,6 @@
   {
   
     /**
  -   * Bean property to allow setPropertiesFromAttributes to
  -   * get the elements attribute.
  -   */
  -  private Vector m_elements;
  -
  -  /**
  -   * Set from the elements attribute.  This is a list of 
  -   * whitespace delimited element qualified names that specify
  -   * preservation of whitespace.
  -   *
  -   * @param elems Should be a non-null reference to a list 
  -   *              of {@link org.apache.xpath.XPath} objects.
  -   */
  -  public void setElements(Vector elems)
  -  {
  -    m_elements = elems;
  -  }
  -
  -  /**
  -   * Get the property set by setElements().  This is a list of 
  -   * whitespace delimited element qualified names that specify
  -   * preservation of whitespace.
  -   *
  -   * @return A reference to a list of {@link org.apache.xpath.XPath} objects, 
  -   *         or null.
  -   */
  -  Vector getElements()
  -  {
  -    return m_elements;
  -  }
  -
  -  /**
      * Receive notification of the start of an preserve-space element.
      *
      * @param handler The calling StylesheetHandler/TemplatesBuilder.
  @@ -123,14 +91,15 @@
      *        Attributes object.
      */
     public void startElement(
  -          StylesheetHandler handler, String uri, String localName, String rawName, Attributes attributes)
  +          StylesheetHandler handler, String uri, String localName, String rawName, 
  +          Attributes attributes)
               throws org.xml.sax.SAXException
     {
  -
  -    setPropertiesFromAttributes(handler, rawName, attributes, this);
  -
       Stylesheet thisSheet = handler.getStylesheet();
  -    Vector xpaths = getElements();
  +	WhitespaceInfoPaths paths = new WhitespaceInfoPaths(thisSheet);
  +    setPropertiesFromAttributes(handler, rawName, attributes, paths);
  +
  +    Vector xpaths = paths.getElements();
   
       for (int i = 0; i < xpaths.size(); i++)
       {
  @@ -139,5 +108,6 @@
   
         thisSheet.setPreserveSpaces(wsi);
       }
  +    paths.clearElements();
     }
   }
  
  
  
  1.8       +5 -3      xml-xalan/java/src/org/apache/xalan/processor/ProcessorStripSpace.java
  
  Index: ProcessorStripSpace.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/processor/ProcessorStripSpace.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- ProcessorStripSpace.java	30 Nov 2000 09:57:30 -0000	1.7
  +++ ProcessorStripSpace.java	22 Mar 2002 01:04:40 -0000	1.8
  @@ -94,10 +94,11 @@
             StylesheetHandler handler, String uri, String localName, String rawName, Attributes attributes)
               throws org.xml.sax.SAXException
     {
  -    setPropertiesFromAttributes(handler, rawName, attributes, this);
  -
       Stylesheet thisSheet = handler.getStylesheet();
  -    Vector xpaths = getElements();
  +	WhitespaceInfoPaths paths = new WhitespaceInfoPaths(thisSheet);
  +    setPropertiesFromAttributes(handler, rawName, attributes, paths);
  +
  +    Vector xpaths = paths.getElements();
   
       for (int i = 0; i < xpaths.size(); i++)
       {
  @@ -106,6 +107,7 @@
   
         thisSheet.setStripSpaces(wsi);
       }
  +    paths.clearElements();
   
     }
   }
  
  
  
  1.49      +4 -5      xml-xalan/java/src/org/apache/xalan/processor/StylesheetHandler.java
  
  Index: StylesheetHandler.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/processor/StylesheetHandler.java,v
  retrieving revision 1.48
  retrieving revision 1.49
  diff -u -r1.48 -r1.49
  --- StylesheetHandler.java	4 Mar 2002 18:21:31 -0000	1.48
  +++ StylesheetHandler.java	22 Mar 2002 01:04:40 -0000	1.49
  @@ -190,11 +190,11 @@
      * @throws javax.xml.transform.TransformerException if the expression can not be processed.
      * @see <a href="http://www.w3.org/TR/xslt#section-Expressions">Section 4 Expressions in XSLT Specification</a>
      */
  -  public XPath createXPath(String str)
  +  public XPath createXPath(String str, ElemTemplateElement owningTemplate)
             throws javax.xml.transform.TransformerException
     {
       ErrorListener handler = m_stylesheetProcessor.getErrorListener();
  -    return new XPath(str, getLocator(), this, XPath.SELECT, handler);
  +    return new XPath(str, owningTemplate, this, XPath.SELECT, handler);
     }
   
     /**
  @@ -207,11 +207,11 @@
      * @throws javax.xml.transform.TransformerException if the pattern can not be processed.
      * @see <a href="http://www.w3.org/TR/xslt#patterns">Section 5.2 Patterns in XSLT Specification</a>
      */
  -  XPath createMatchPatternXPath(String str)
  +  XPath createMatchPatternXPath(String str, ElemTemplateElement owningTemplate)
             throws javax.xml.transform.TransformerException
     {
       ErrorListener handler = m_stylesheetProcessor.getErrorListener();
  -    return new XPath(str, getLocator(), this, XPath.MATCH, handler);
  +    return new XPath(str, owningTemplate, this, XPath.MATCH, handler);
     }
   
     /**
  @@ -725,7 +725,6 @@
       {
   
         // If it's whitespace, just ignore it, otherwise flag an error.
  -      // %ISSUE% What about whitesace within scope of xsl:space="preserve"?
         if (!XMLCharacterRecognizer.isWhiteSpace(ch, start, length))
           error(
             "Non-whitespace text is not allowed in this position in the stylesheet!",
  
  
  
  1.21      +22 -16    xml-xalan/java/src/org/apache/xalan/processor/XSLTAttributeDef.java
  
  Index: XSLTAttributeDef.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/processor/XSLTAttributeDef.java,v
  retrieving revision 1.20
  retrieving revision 1.21
  diff -u -r1.20 -r1.21
  --- XSLTAttributeDef.java	1 Aug 2001 16:50:33 -0000	1.20
  +++ XSLTAttributeDef.java	22 Mar 2002 01:04:40 -0000	1.21
  @@ -465,13 +465,14 @@
      * in the attribute value template string.
      */
     AVT processAVT(
  -          StylesheetHandler handler, String uri, String name, String rawName, String value)
  +          StylesheetHandler handler, String uri, String name, String rawName, String value,
  +          ElemTemplateElement owner)
               throws org.xml.sax.SAXException
     {
   
       try
       {
  -      AVT avt = new AVT(handler, uri, name, rawName, value);
  +      AVT avt = new AVT(handler, uri, name, rawName, value, owner);
   
         return avt;
       }
  @@ -566,13 +567,14 @@
      * string contains a syntax error.
      */
     Object processEXPR(
  -          StylesheetHandler handler, String uri, String name, String rawName, String value)
  +          StylesheetHandler handler, String uri, String name, String rawName, String value,
  +          ElemTemplateElement owner)
               throws org.xml.sax.SAXException
     {
   
       try
       {
  -      XPath expr = handler.createXPath(value);
  +      XPath expr = handler.createXPath(value, owner);
   
         return expr;
       }
  @@ -618,13 +620,14 @@
      * string contains a syntax error.
      */
     Object processPATTERN(
  -          StylesheetHandler handler, String uri, String name, String rawName, String value)
  +          StylesheetHandler handler, String uri, String name, String rawName, String value,
  +          ElemTemplateElement owner)
               throws org.xml.sax.SAXException
     {
   
       try
       {
  -      XPath pattern = handler.createMatchPatternXPath(value);
  +      XPath pattern = handler.createMatchPatternXPath(value, owner);
   
         return pattern;
       }
  @@ -741,7 +744,8 @@
      * strings contains a syntax error.
      */
     Vector processSIMPLEPATTERNLIST(
  -          StylesheetHandler handler, String uri, String name, String rawName, String value)
  +          StylesheetHandler handler, String uri, String name, String rawName, String value,
  +          ElemTemplateElement owner)
               throws org.xml.sax.SAXException
     {
   
  @@ -754,7 +758,7 @@
         for (int i = 0; i < nPatterns; i++)
         {
           XPath pattern =
  -          handler.createMatchPatternXPath(tokenizer.nextToken());
  +          handler.createMatchPatternXPath(tokenizer.nextToken(), owner);
   
           patterns.addElement(pattern);
         }
  @@ -895,7 +899,8 @@
      * @throws org.xml.sax.SAXException if the attribute value can not be processed.
      */
     Object processValue(
  -          StylesheetHandler handler, String uri, String name, String rawName, String value)
  +          StylesheetHandler handler, String uri, String name, String rawName, String value,
  +          ElemTemplateElement owner)
               throws org.xml.sax.SAXException
     {
   
  @@ -905,7 +910,7 @@
       switch (type)
       {
       case T_AVT :
  -      processedValue = processAVT(handler, uri, name, rawName, value);
  +      processedValue = processAVT(handler, uri, name, rawName, value, owner);
         break;
       case T_CDATA :
         processedValue = processCDATA(handler, uri, name, rawName, value);
  @@ -917,13 +922,13 @@
         processedValue = processENUM(handler, uri, name, rawName, value);
         break;
       case T_EXPR :
  -      processedValue = processEXPR(handler, uri, name, rawName, value);
  +      processedValue = processEXPR(handler, uri, name, rawName, value, owner);
         break;
       case T_NMTOKEN :
         processedValue = processNMTOKEN(handler, uri, name, rawName, value);
         break;
       case T_PATTERN :
  -      processedValue = processPATTERN(handler, uri, name, rawName, value);
  +      processedValue = processPATTERN(handler, uri, name, rawName, value, owner);
         break;
       case T_PRIORITY :
         processedValue = processPRIORITY(handler, uri, name, rawName, value);
  @@ -936,7 +941,7 @@
         break;
       case T_SIMPLEPATTERNLIST :
         processedValue = processSIMPLEPATTERNLIST(handler, uri, name, rawName,
  -                                                value);
  +                                                value, owner);
         break;
       case T_URL :
         processedValue = processURL(handler, uri, name, rawName, value);
  @@ -966,7 +971,7 @@
      * @throws org.xml.sax.SAXException wraps an invocation exception if the
      * setter method can not be invoked on the object.
      */
  -  void setDefAttrValue(StylesheetHandler handler, Object elem)
  +  void setDefAttrValue(StylesheetHandler handler, ElemTemplateElement elem)
             throws org.xml.sax.SAXException
     {
       setAttrValue(handler, this.getNamespace(), this.getName(),
  @@ -1042,7 +1047,8 @@
      * @throws org.xml.sax.SAXException
      */
     void setAttrValue(
  -          StylesheetHandler handler, String attrUri, String attrLocalName, String attrRawName, String attrValue, Object elem)
  +          StylesheetHandler handler, String attrUri, String attrLocalName, 
  +          String attrRawName, String attrValue, ElemTemplateElement elem)
               throws org.xml.sax.SAXException
     {
       if(attrRawName.equals("xmlns") || attrRawName.startsWith("xmlns:"))
  @@ -1076,7 +1082,7 @@
           else
           {
             Object value = processValue(handler, attrUri, attrLocalName,
  -                                      attrRawName, attrValue);
  +                                      attrRawName, attrValue, elem);
                                         
             // First try to match with the primative value.
             Class[] argTypes = new Class[]{ getPrimativeClass(value) };
  
  
  
  1.13      +5 -3      xml-xalan/java/src/org/apache/xalan/processor/XSLTElementProcessor.java
  
  Index: XSLTElementProcessor.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/processor/XSLTElementProcessor.java,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- XSLTElementProcessor.java	28 Jul 2001 00:25:57 -0000	1.12
  +++ XSLTElementProcessor.java	22 Mar 2002 01:04:40 -0000	1.13
  @@ -79,7 +79,7 @@
    * processors, and deals with things that are common to all elements.
    * @see <a href="http://www.w3.org/TR/xslt#dtd">XSLT DTD</a>
    */
  -public class XSLTElementProcessor
  +public class XSLTElementProcessor extends ElemTemplateElement
   {
   
     /**
  @@ -305,7 +305,8 @@
      * @param target The target element where the properties will be set.
      */
     void setPropertiesFromAttributes(
  -          StylesheetHandler handler, String rawName, Attributes attributes, Object target)
  +          StylesheetHandler handler, String rawName, Attributes attributes, 
  +          ElemTemplateElement target)
               throws org.xml.sax.SAXException
     {
       setPropertiesFromAttributes(handler, rawName, attributes, target, true);
  @@ -326,7 +327,8 @@
      * @throws TransformerException
      */
     Attributes setPropertiesFromAttributes(
  -          StylesheetHandler handler, String rawName, Attributes attributes, Object target, boolean throwError)
  +          StylesheetHandler handler, String rawName, Attributes attributes, 
  +          ElemTemplateElement target, boolean throwError)
               throws org.xml.sax.SAXException
     {
   
  
  
  
  1.2       +60 -0     xml-xalan/java/src/org/apache/xalan/processor/WhitespaceInfoPaths.java
  
  
  
  
  1.17      +24 -3     xml-xalan/java/src/org/apache/xalan/templates/AVT.java
  
  Index: AVT.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/AVT.java,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- AVT.java	9 Oct 2001 15:15:07 -0000	1.16
  +++ AVT.java	22 Mar 2002 01:04:40 -0000	1.17
  @@ -79,7 +79,7 @@
    * <meta name="usage" content="advanced"/>
    * Class to hold an Attribute Value Template.
    */
  -public class AVT implements java.io.Serializable
  +public class AVT implements java.io.Serializable, XSLTVisitable
   {
   
     /**
  @@ -185,7 +185,9 @@
      *
      * @throws javax.xml.transform.TransformerException
      */
  -  public AVT(StylesheetHandler handler, String uri, String name, String rawName, String stringedValue)
  +  public AVT(StylesheetHandler handler, String uri, String name, 
  +             String rawName, String stringedValue,
  +             ElemTemplateElement owner)
             throws javax.xml.transform.TransformerException
     {
   
  @@ -324,7 +326,7 @@
                             buffer.setLength(0);
   
                             XPath xpath =
  -                                       handler.createXPath(exprBuffer.toString());
  +                                       handler.createXPath(exprBuffer.toString(), owner);
   
                             m_parts.addElement(new AVTPartXPath(xpath));
   
  @@ -611,4 +613,23 @@
         }
       }
     }
  +  
  +  /**
  +   * @see XSLTVisitable#callVisitors(XSLTVisitor)
  +   */
  +  public void callVisitors(XSLTVisitor visitor)
  +  {
  +  	if(visitor.visitAVT(this) && (null != m_parts))
  +  	{
  +      int n = m_parts.size();
  +
  +      for (int i = 0; i < n; i++)
  +      {
  +        AVTPart part = (AVTPart) m_parts.elementAt(i);
  +
  +        part.callVisitors(visitor);
  +      }  		
  +  	}
  +  }
  +
   }
  
  
  
  1.11      +1 -1      xml-xalan/java/src/org/apache/xalan/templates/AVTPart.java
  
  Index: AVTPart.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/AVTPart.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- AVTPart.java	12 Jun 2001 19:15:05 -0000	1.10
  +++ AVTPart.java	22 Mar 2002 01:04:40 -0000	1.11
  @@ -67,7 +67,7 @@
    * Class to hold a part, either a string or XPath,
    * of an Attribute Value Template.
    */
  -public abstract class AVTPart implements java.io.Serializable
  +public abstract class AVTPart implements java.io.Serializable, XSLTVisitable
   {
   
     /**
  
  
  
  1.11      +8 -0      xml-xalan/java/src/org/apache/xalan/templates/AVTPartSimple.java
  
  Index: AVTPartSimple.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/AVTPartSimple.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- AVTPartSimple.java	12 Jun 2001 19:15:05 -0000	1.10
  +++ AVTPartSimple.java	22 Mar 2002 01:04:40 -0000	1.11
  @@ -127,4 +127,12 @@
     {
       buf.append(m_val);
     }
  +  /**
  +   * @see XSLTVisitable#callVisitors(XSLTVisitor)
  +   */
  +  public void callVisitors(XSLTVisitor visitor)
  +  {
  +  	// Don't do anything for the subpart for right now.
  +  }
  +
   }
  
  
  
  1.14      +10 -0     xml-xalan/java/src/org/apache/xalan/templates/AVTPartXPath.java
  
  Index: AVTPartXPath.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/AVTPartXPath.java,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- AVTPartXPath.java	12 Jun 2001 19:15:06 -0000	1.13
  +++ AVTPartXPath.java	22 Mar 2002 01:04:40 -0000	1.14
  @@ -57,10 +57,12 @@
   package org.apache.xalan.templates;
   
   import org.apache.xpath.*;
  +import org.apache.xpath.Expression;
   import org.apache.xpath.objects.XObject;
   import org.apache.xpath.XPathContext;
   import org.apache.xpath.compiler.XPathParser;
   import org.apache.xml.utils.FastStringBuffer;
  +import org.apache.xpath.ExpressionOwner;
   
   //import org.w3c.dom.*;
   import org.apache.xml.dtm.DTM;
  @@ -177,4 +179,12 @@
         xobj.appendToFsb(buf);
       }
     }
  +  
  +  /**
  +   * @see XSLTVisitable#callVisitors(XSLTVisitor)
  +   */
  +  public void callVisitors(XSLTVisitor visitor)
  +  {
  +  	m_xpath.getExpression().callVisitors(m_xpath, visitor);
  +  }
   }
  
  
  
  1.20      +5 -5      xml-xalan/java/src/org/apache/xalan/templates/ElemApplyTemplates.java
  
  Index: ElemApplyTemplates.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/ElemApplyTemplates.java,v
  retrieving revision 1.19
  retrieving revision 1.20
  diff -u -r1.19 -r1.20
  --- ElemApplyTemplates.java	31 Jan 2002 16:33:25 -0000	1.19
  +++ ElemApplyTemplates.java	22 Mar 2002 01:04:40 -0000	1.20
  @@ -267,9 +267,11 @@
           sourceNodes = sortNodes(xctxt, keys, sourceNodes);
   
         if (TransformerImpl.S_DEBUG)
  +      {
           transformer.getTraceManager().fireSelectedEvent(sourceNode, this,
                   "select", new XPath(m_selectExpression),
                   new org.apache.xpath.objects.XNodeSet(sourceNodes));
  +      }
   
         final ResultTreeHandler rth = transformer.getResultTreeHandler();
         ContentHandler chandler = rth.getContentHandler();
  @@ -277,6 +279,9 @@
         final TemplateList tl = sroot.getTemplateListComposed();
         final boolean quiet = transformer.getQuietConflictWarnings();
         
  +      // Should be able to get this from the iterator but there must be a bug.
  +      DTM dtm = xctxt.getDTM(sourceNode);
  +      
         int argsFrame = -1;
         if(nParams > 0)
         {
  @@ -308,11 +313,6 @@
         xctxt.pushContextNodeList(sourceNodes);
         transformer.pushElemTemplateElement(null);
         // pushParams(transformer, xctxt);
  -
  -      // Should be able to get this from the iterator but there must be a bug.
  -      DTM dtm = xctxt.getDTM(sourceNode);
  -      
  -      
         
         int child;
         while (DTM.NULL != (child = sourceNodes.nextNode()))
  
  
  
  1.16      +0 -2      xml-xalan/java/src/org/apache/xalan/templates/ElemAttribute.java
  
  Index: ElemAttribute.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/ElemAttribute.java,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- ElemAttribute.java	12 Jun 2001 19:15:06 -0000	1.15
  +++ ElemAttribute.java	22 Mar 2002 01:04:40 -0000	1.16
  @@ -113,8 +113,6 @@
      * @see <a href="http://www.w3.org/TR/xslt#creating-attributes">creating-attributes in XSLT Specification</a>
      *
      * @param transformer non-null reference to the the current transform-time state.
  -   * @param sourceNode non-null reference to the <a href="http://www.w3.org/TR/xslt#dt-current-node">current source node</a>.
  -   * @param mode reference, which may be null, to the <a href="http://www.w3.org/TR/xslt#modes">current mode</a>.
      *
      * @throws TransformerException
      */
  
  
  
  1.20      +25 -11    xml-xalan/java/src/org/apache/xalan/templates/ElemCallTemplate.java
  
  Index: ElemCallTemplate.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/ElemCallTemplate.java,v
  retrieving revision 1.19
  retrieving revision 1.20
  diff -u -r1.19 -r1.20
  --- ElemCallTemplate.java	18 Oct 2001 20:30:44 -0000	1.19
  +++ ElemCallTemplate.java	22 Mar 2002 01:04:40 -0000	1.20
  @@ -56,19 +56,13 @@
    */
   package org.apache.xalan.templates;
   
  -import java.util.Vector;
  -
  -import org.w3c.dom.*;
  -
  -import org.xml.sax.*;
  -
  -import org.apache.xpath.*;
  -import org.apache.xml.utils.QName;
  -import org.apache.xalan.res.XSLTErrorResources;
  -import org.apache.xpath.VariableStack;
  -import org.apache.xalan.transformer.TransformerImpl;
   import javax.xml.transform.SourceLocator;
   import javax.xml.transform.TransformerException;
  +import org.apache.xalan.res.XSLTErrorResources;
  +import org.apache.xalan.transformer.TransformerImpl;
  +import org.apache.xml.utils.QName;
  +import org.apache.xpath.VariableStack;
  +import org.apache.xpath.XPathContext;
   import org.apache.xpath.objects.XObject;
   
   /**
  @@ -378,4 +372,24 @@
       // contain a for-each, and other elements.
       return super.appendChild(newChild);
     }
  +  
  +    /**
  +     * Call the children visitors.
  +     * @param visitor The visitor whose appropriate method will be called.
  +     */
  +    public void callChildVisitors(XSLTVisitor visitor, boolean callAttrs)
  +    {
  +//      if (null != m_paramElems)
  +//      {
  +//        int size = m_paramElems.length;
  +//
  +//        for (int i = 0; i < size; i++)
  +//        {
  +//          ElemWithParam ewp = m_paramElems[i];
  +//          ewp.callVisitors(visitor);
  +//        }
  +//      }
  +
  +      super.callChildVisitors(visitor, callAttrs);
  +    }
   }
  
  
  
  1.13      +15 -0     xml-xalan/java/src/org/apache/xalan/templates/ElemChoose.java
  
  Index: ElemChoose.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/ElemChoose.java,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- ElemChoose.java	18 Jun 2001 21:42:49 -0000	1.12
  +++ ElemChoose.java	22 Mar 2002 01:04:40 -0000	1.13
  @@ -141,6 +141,11 @@
           // must be xsl:when
           XPathContext xctxt = transformer.getXPathContext();
           int sourceNode = xctxt.getCurrentNode();
  +        
  +        // System.err.println("\""+when.getTest().getPatternString()+"\"");
  +        
  +        // if(when.getTest().getPatternString().equals("COLLECTION/icuser/ictimezone/LITERAL='GMT +13:00 Pacific/Tongatapu'"))
  +        // 	System.err.println("Found COLLECTION/icuser/ictimezone/LITERAL");
   
           if (TransformerImpl.S_DEBUG)
           {
  @@ -216,4 +221,14 @@
   
       return super.appendChild(newChild);
     }
  +  
  +  /**
  +   * Tell if this element can accept variable declarations.
  +   * @return true if the element can accept and process variable declarations.
  +   */
  +  public boolean canAcceptVariables()
  +  {
  +  	return false;
  +  }
  +
   }
  
  
  
  1.13      +12 -0     xml-xalan/java/src/org/apache/xalan/templates/ElemCopyOf.java
  
  Index: ElemCopyOf.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/ElemCopyOf.java,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- ElemCopyOf.java	15 Jun 2001 17:54:03 -0000	1.12
  +++ ElemCopyOf.java	22 Mar 2002 01:04:40 -0000	1.13
  @@ -274,4 +274,16 @@
       //" to " + this.m_elemName);
       return null;
     }
  +  
  +  /**
  +   * Call the children visitors.
  +   * @param visitor The visitor whose appropriate method will be called.
  +   */
  +  protected void callChildVisitors(XSLTVisitor visitor, boolean callAttrs)
  +  {
  +  	if(callAttrs)
  +  		m_selectExpression.getExpression().callVisitors(m_selectExpression, visitor);
  +    super.callChildVisitors(visitor, callAttrs);
  +  }
  +
   }
  
  
  
  1.24      +19 -2     xml-xalan/java/src/org/apache/xalan/templates/ElemElement.java
  
  Index: ElemElement.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/ElemElement.java,v
  retrieving revision 1.23
  retrieving revision 1.24
  diff -u -r1.23 -r1.24
  --- ElemElement.java	13 Sep 2001 14:36:28 -0000	1.23
  +++ ElemElement.java	22 Mar 2002 01:04:40 -0000	1.24
  @@ -271,8 +271,6 @@
      * for the attributes and children of the created element.
      *
      * @param transformer non-null reference to the the current transform-time state.
  -   * @param sourceNode non-null reference to the <a href="http://www.w3.org/TR/xslt#dt-current-node">current source node</a>.
  -   * @param mode reference, which may be null, to the <a href="http://www.w3.org/TR/xslt#modes">current mode</a>.
      *
      * @throws TransformerException
      */
  @@ -430,4 +428,23 @@
         throw new TransformerException(se);
       }
     }
  +  
  +  /**
  +   * Call the children visitors.
  +   * @param visitor The visitor whose appropriate method will be called.
  +   */
  +  protected void callChildVisitors(XSLTVisitor visitor, boolean callAttrs)
  +  {
  +  	if(callAttrs)
  +  	{
  +  	  if(null != m_name_avt)
  +  		m_name_avt.callVisitors(visitor);
  +  		
  +  	  if(null != m_namespace_avt)
  +  		m_namespace_avt.callVisitors(visitor);
  +  	}
  +  		
  +    super.callChildVisitors(visitor, callAttrs);
  +  }
  +
   }
  
  
  
  1.27      +13 -0     xml-xalan/java/src/org/apache/xalan/templates/ElemExtensionCall.java
  
  Index: ElemExtensionCall.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/ElemExtensionCall.java,v
  retrieving revision 1.26
  retrieving revision 1.27
  diff -u -r1.26 -r1.27
  --- ElemExtensionCall.java	28 Jul 2001 00:25:58 -0000	1.26
  +++ ElemExtensionCall.java	22 Mar 2002 01:04:40 -0000	1.27
  @@ -406,4 +406,17 @@
       return null;
     }
     
  +  /**
  +   * Accept a visitor and call the appropriate method 
  +   * for this class.
  +   * 
  +   * @param visitor The visitor whose appropriate method will be called.
  +   * @return true if the children of the object should be visited.
  +   */
  +  protected boolean accept(XSLTVisitor visitor)
  +  {
  +  	return visitor.visitExtensionElement(this);
  +  }
  +
  +  
   }
  
  
  
  1.25      +68 -28    xml-xalan/java/src/org/apache/xalan/templates/ElemForEach.java
  
  Index: ElemForEach.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/ElemForEach.java,v
  retrieving revision 1.24
  retrieving revision 1.25
  diff -u -r1.24 -r1.25
  --- ElemForEach.java	8 Feb 2002 23:33:49 -0000	1.24
  +++ ElemForEach.java	22 Mar 2002 01:04:40 -0000	1.25
  @@ -68,6 +68,7 @@
   import org.xml.sax.*;
   
   import org.apache.xpath.*;
  +import org.apache.xpath.Expression;
   import org.apache.xpath.axes.ContextNodeList;
   import org.apache.xpath.objects.XObject;
   
  @@ -84,6 +85,7 @@
   
   import javax.xml.transform.SourceLocator;
   import javax.xml.transform.TransformerException;
  +import org.apache.xpath.ExpressionOwner;
   
   /**
    * <meta name="usage" content="advanced"/>
  @@ -103,7 +105,7 @@
    * </pre>
    * @see <a href="http://www.w3.org/TR/xslt#for-each">for-each in XSLT Specification</a>
    */
  -public class ElemForEach extends ElemTemplateElement
  +public class ElemForEach extends ElemTemplateElement implements ExpressionOwner
   {
     /** Set true to request some basic status reports */
     static final boolean DEBUG = false;
  @@ -333,7 +335,6 @@
     {
   
       NodeSorter sorter = new NodeSorter(xctxt);
  -
       sourceNodes.setShouldCacheNodes(true);
       sourceNodes.runTo(-1);
       xctxt.pushContextNodeList(sourceNodes);
  @@ -367,23 +368,25 @@
       final XPathContext xctxt = transformer.getXPathContext();
       final int sourceNode = xctxt.getCurrentNode();
       DTMIterator sourceNodes = m_selectExpression.asIterator(xctxt,
  -                                sourceNode);
  +            sourceNode);
   
       try
       {
   
         final Vector keys = (m_sortElems == null)
  -                          ? null
  -                          : transformer.processSortKeys(this, sourceNode);
  +              ? null
  +              : transformer.processSortKeys(this, sourceNode);
   
         // Sort if we need to.
         if (null != keys)
           sourceNodes = sortNodes(xctxt, keys, sourceNodes);
   
         if (TransformerImpl.S_DEBUG)
  +      {
           transformer.getTraceManager().fireSelectedEvent(sourceNode, this,
                   "select", new XPath(m_selectExpression),
                   new org.apache.xpath.objects.XNodeSet(sourceNodes));
  +      }
   
         final ResultTreeHandler rth = transformer.getResultTreeHandler();
         ContentHandler chandler = rth.getContentHandler();
  @@ -397,7 +400,7 @@
   
         int[] currentExpressionNodes = xctxt.getCurrentExpressionNodeStack();
         int currentExpressionNodePos =
  -        xctxt.getCurrentExpressionNodesFirstFree() - 1;
  +              xctxt.getCurrentExpressionNodesFirstFree() - 1;
   
         xctxt.pushSAXLocatorNull();
         xctxt.pushContextNodeList(sourceNodes);
  @@ -431,34 +434,34 @@
           // Loop through the children of the template, calling execute on 
           // each of them.
           for (ElemTemplateElement t = this.m_firstChild; t != null;
  -                t = t.m_nextSibling)
  +             t = t.m_nextSibling)
           {
             xctxt.setSAXLocator(t);
             transformer.setCurrentElement(t);
             t.execute(transformer);
           }
   
  -	// KLUGE: Implement <?xalan:doc_cache_off?> 
  -	// ASSUMPTION: This will be set only when the XPath was indeed
  -	// a call to the Document() function. Calling it in other
  -	// situations is likely to fry Xalan.
  -	//
  -	// %REVIEW% We need a MUCH cleaner solution -- one that will
  -	// handle cleaning up after document() and getDTM() in other
  -	// contexts. The whole SourceTreeManager mechanism should probably
  -	// be moved into DTMManager rather than being explicitly invoked in
  -	// FuncDocument and here.
  -	if(m_doc_cache_off)
  -	{
  -	  if(DEBUG)
  -	    System.out.println("JJK***** CACHE RELEASE *****\n"+
  -			       "\tdtm="+dtm.getDocumentBaseURI());
  - 	// NOTE: This will work because this is _NOT_ a shared DTM, and thus has
  - 	// only a single Document node. If it could ever be an RTF or other
  -	// shared DTM, this would require substantial rework.
  -	  xctxt.getSourceTreeManager().removeDocumentFromCache(dtm.getDocument());
  -	  xctxt.release(dtm,false);
  -	}
  +	 	// KLUGE: Implement <?xalan:doc_cache_off?> 
  +	 	// ASSUMPTION: This will be set only when the XPath was indeed
  +	 	// a call to the Document() function. Calling it in other
  +	 	// situations is likely to fry Xalan.
  +	 	//
  +	 	// %REVIEW% We need a MUCH cleaner solution -- one that will
  +	 	// handle cleaning up after document() and getDTM() in other
  +		// contexts. The whole SourceTreeManager mechanism should probably
  +	 	// be moved into DTMManager rather than being explicitly invoked in
  +	 	// FuncDocument and here.
  +	 	if(m_doc_cache_off)
  +		{
  +	 	  if(DEBUG)
  +	 	    System.out.println("JJK***** CACHE RELEASE *****\n"+
  +				       "\tdtm="+dtm.getDocumentBaseURI());
  +	  	// NOTE: This will work because this is _NOT_ a shared DTM, and thus has
  +	  	// only a single Document node. If it could ever be an RTF or other
  +	 	// shared DTM, this would require substantial rework.
  +	 	  xctxt.getSourceTreeManager().removeDocumentFromCache(dtm.getDocument());
  +	 	  xctxt.release(dtm,false);
  +	 	}
         }
       }
       finally
  @@ -503,4 +506,41 @@
       else
         return super.appendChild(newChild);
     }
  +  
  +  /**
  +   * Call the children visitors.
  +   * @param visitor The visitor whose appropriate method will be called.
  +   */
  +  public void callChildVisitors(XSLTVisitor visitor, boolean callAttributes)
  +  {
  +  	if(callAttributes && (null != m_selectExpression))
  +  		m_selectExpression.callVisitors(this, visitor);
  +  		
  +    int length = getSortElemCount();
  +
  +    for (int i = 0; i < length; i++)
  +    {
  +      getSortElem(i).callVisitors(visitor);
  +    }
  +
  +    super.callChildVisitors(visitor, callAttributes);
  +  }
  +
  +  /**
  +   * @see ExpressionOwner#getExpression()
  +   */
  +  public Expression getExpression()
  +  {
  +    return m_selectExpression;
  +  }
  +
  +  /**
  +   * @see ExpressionOwner#setExpression(Expression)
  +   */
  +  public void setExpression(Expression exp)
  +  {
  +  	exp.exprSetParent(this);
  +  	m_selectExpression = exp;
  +  }
  +
   }
  
  
  
  1.11      +13 -1     xml-xalan/java/src/org/apache/xalan/templates/ElemIf.java
  
  Index: ElemIf.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/ElemIf.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- ElemIf.java	12 Jun 2001 19:15:10 -0000	1.10
  +++ ElemIf.java	22 Mar 2002 01:04:40 -0000	1.11
  @@ -119,7 +119,7 @@
      * values that may be based on some other property that
      * depends on recomposition.
      *
  -   * NEEDSDOC @param sroot
  +   * @param sroot The root stylesheet.
      *
      * @throws TransformerException
      */
  @@ -200,4 +200,16 @@
         transformer.executeChildTemplates(this, true);
       }
     }
  +  
  +  /**
  +   * Call the children visitors.
  +   * @param visitor The visitor whose appropriate method will be called.
  +   */
  +  protected void callChildVisitors(XSLTVisitor visitor, boolean callAttrs)
  +  {
  +  	if(callAttrs)
  +  		m_test.getExpression().callVisitors(m_test, visitor);
  +    super.callChildVisitors(visitor, callAttrs);
  +  }
  +
   }
  
  
  
  1.32      +32 -0     xml-xalan/java/src/org/apache/xalan/templates/ElemLiteralResult.java
  
  Index: ElemLiteralResult.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/ElemLiteralResult.java,v
  retrieving revision 1.31
  retrieving revision 1.32
  diff -u -r1.31 -r1.32
  --- ElemLiteralResult.java	15 Oct 2001 21:41:22 -0000	1.31
  +++ ElemLiteralResult.java	22 Mar 2002 01:04:40 -0000	1.32
  @@ -737,4 +737,36 @@
     {
       return (null == m_avts) ? null : m_avts.elements();
     }
  +  
  +    /**
  +     * Accept a visitor and call the appropriate method 
  +     * for this class.
  +     * 
  +     * @param visitor The visitor whose appropriate method will be called.
  +     * @return true if the children of the object should be visited.
  +     */
  +    protected boolean accept(XSLTVisitor visitor)
  +    {
  +      return visitor.visitLiteralResultElement(this);
  +    }
  +
  +    /**
  +     * Call the children visitors.
  +     * @param visitor The visitor whose appropriate method will be called.
  +     */
  +    protected void callChildVisitors(XSLTVisitor visitor, boolean callAttrs)
  +    {
  +      if (callAttrs && null != m_avts)
  +      {
  +        int nAttrs = m_avts.size();
  +
  +        for (int i = (nAttrs - 1); i >= 0; i--)
  +        {
  +          AVT avt = (AVT) m_avts.elementAt(i);
  +          avt.callVisitors(visitor);
  +        }
  +      }
  +      super.callChildVisitors(visitor, callAttrs);
  +    }
  +
   }
  
  
  
  1.23      +32 -0     xml-xalan/java/src/org/apache/xalan/templates/ElemNumber.java
  
  Index: ElemNumber.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/ElemNumber.java,v
  retrieving revision 1.22
  retrieving revision 1.23
  diff -u -r1.22 -r1.23
  --- ElemNumber.java	8 Nov 2001 16:34:00 -0000	1.22
  +++ ElemNumber.java	22 Mar 2002 01:04:40 -0000	1.23
  @@ -1949,6 +1949,37 @@
   
       return roman;
     }  // end long2roman
  +  
  +  /**
  +   * Call the children visitors.
  +   * @param visitor The visitor whose appropriate method will be called.
  +   */
  +  public void callChildVisitors(XSLTVisitor visitor, boolean callAttrs)
  +  {
  +  	if(callAttrs)
  +  	{
  +	  	if(null != m_countMatchPattern)
  +	  		m_countMatchPattern.getExpression().callVisitors(m_countMatchPattern, visitor);
  +	  	if(null != m_fromMatchPattern)
  +	  		m_fromMatchPattern.getExpression().callVisitors(m_fromMatchPattern, visitor);
  +	  	if(null != m_valueExpr)
  +	  		m_valueExpr.getExpression().callVisitors(m_valueExpr, visitor);
  +	
  +	  	if(null != m_format_avt)
  +	  		m_format_avt.callVisitors(visitor);
  +	  	if(null != m_groupingSeparator_avt)
  +	  		m_groupingSeparator_avt.callVisitors(visitor);
  +	  	if(null != m_groupingSize_avt)
  +	  		m_groupingSize_avt.callVisitors(visitor);
  +	  	if(null != m_lang_avt)
  +	  		m_lang_avt.callVisitors(visitor);
  +	  	if(null != m_lettervalue_avt)
  +	  		m_lettervalue_avt.callVisitors(visitor);
  +  	}
  +
  +    super.callChildVisitors(visitor, callAttrs);
  +  }
  +
   
     /**
      * This class returns tokens using non-alphanumberic
  @@ -2101,4 +2132,5 @@
         return count;
       }
     }  // end NumberFormatStringTokenizer
  +
   }
  
  
  
  1.47      +173 -2    xml-xalan/java/src/org/apache/xalan/templates/ElemTemplateElement.java
  
  Index: ElemTemplateElement.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/ElemTemplateElement.java,v
  retrieving revision 1.46
  retrieving revision 1.47
  diff -u -r1.46 -r1.47
  --- ElemTemplateElement.java	5 Oct 2001 20:54:31 -0000	1.46
  +++ ElemTemplateElement.java	22 Mar 2002 01:04:40 -0000	1.47
  @@ -76,6 +76,7 @@
   import org.apache.xalan.transformer.ResultTreeHandler;
   import org.apache.xpath.VariableStack;
   import org.apache.xpath.WhitespaceStrippingElementMatcher;
  +import org.apache.xpath.ExpressionNode;
   
   // TRaX imports
   import javax.xml.transform.Templates;
  @@ -109,8 +110,8 @@
    * @see Stylesheet
    */
   public class ElemTemplateElement extends UnImplNode
  -        implements PrefixResolver, Serializable, SourceLocator, 
  -                   WhitespaceStrippingElementMatcher
  +        implements PrefixResolver, Serializable, ExpressionNode, 
  +                   WhitespaceStrippingElementMatcher, XSLTVisitable
   {
   
     /**
  @@ -506,6 +507,76 @@
       // oldChildElem.m_stylesheet = null;
       return newChildElem;
     }
  +  
  +  /**
  +   * Unimplemented. See org.w3c.dom.Node
  +   *
  +   * @param newChild New child node to insert
  +   * @param refChild Insert in front of this child
  +   *
  +   * @return null
  +   *
  +   * @throws DOMException
  +   */
  +  public Node insertBefore(Node newChild, Node refChild) throws DOMException
  +  {
  +  	if(null == refChild)
  +  	{
  +  		appendChild(newChild);
  +  		return newChild;
  +  	}
  +  	
  +  	if(newChild == refChild)
  +  	{
  +  		// hmm...
  +  		return newChild;
  +  	}
  +
  +    Node node = m_firstChild; 
  +    Node prev = null;  
  +    boolean foundit = false;
  +    
  +    while (null != node)
  +    {
  +    	// If the newChild is already in the tree, it is first removed.
  +    	if(newChild == node)
  +    	{
  +    		if(null != prev)
  +    			((ElemTemplateElement)prev).m_nextSibling = 
  +    				(ElemTemplateElement)node.getNextSibling();
  +    		else
  +    			m_firstChild = (ElemTemplateElement)node.getNextSibling();
  +    		node = node.getNextSibling();
  +    		continue; // prev remains the same.
  +    	}
  +    	if(refChild == node)
  +    	{
  +    		if(null != prev)
  +    		{
  +    			((ElemTemplateElement)prev).m_nextSibling = (ElemTemplateElement)newChild;
  +    		}
  +    		else
  +    		{
  +    			m_firstChild = (ElemTemplateElement)newChild;
  +    		}
  +    		((ElemTemplateElement)newChild).m_nextSibling = (ElemTemplateElement)refChild;
  +    		((ElemTemplateElement)newChild).setParentElem(this);
  +    		prev = newChild;
  +    		node = node.getNextSibling();
  +    		foundit = true;
  +    		continue;
  +    	}
  +    	prev = node;
  +    	node = node.getNextSibling();
  +    }
  +    
  +    if(!foundit)
  +    	throw new DOMException(DOMException.NOT_FOUND_ERR, 
  +    		"refChild was not found in insertBefore method!");
  +    else
  +    	return newChild;
  +  }
  +
   
     /**
      * Replace the old child with a new child.
  @@ -1471,5 +1542,105 @@
       StylesheetRoot sroot = this.getStylesheetRoot();
       return (null != sroot) ? sroot.canStripWhiteSpace() : false;
     }
  +  
  +  /**
  +   * Tell if this element can accept variable declarations.
  +   * @return true if the element can accept and process variable declarations.
  +   */
  +  public boolean canAcceptVariables()
  +  {
  +  	return true;
  +  }
  +  
  +  //=============== ExpressionNode methods ================
  +  
  +  /** 
  +   * Set the parent of this node.
  +   * @param n Must be a ElemTemplateElement.
  +   */
  +  public void exprSetParent(ExpressionNode n)
  +  {
  +  	// This obviously requires that only a ElemTemplateElement can 
  +  	// parent a node of this type.
  +  	setParentElem((ElemTemplateElement)n);
  +  }
  +  
  +  /**
  +   * Get the ExpressionNode parent of this node.
  +   */
  +  public ExpressionNode exprGetParent()
  +  {
  +  	return getParentElem();
  +  }
  +
  +  /** 
  +   * This method tells the node to add its argument to the node's
  +   * list of children. 
  +   * @param n Must be a ElemTemplateElement. 
  +   */
  +  public void exprAddChild(ExpressionNode n, int i)
  +  {
  +  	appendChild((ElemTemplateElement)n);
  +  }
  +
  +  /** This method returns a child node.  The children are numbered
  +     from zero, left to right. */
  +  public ExpressionNode exprGetChild(int i)
  +  {
  +  	return (ExpressionNode)item(i);
  +  }
  +
  +  /** Return the number of children the node has. */
  +  public int exprGetNumChildren()
  +  {
  +  	return getLength();
  +  }
  +  
  +  /**
  +   * Accept a visitor and call the appropriate method 
  +   * for this class.
  +   * 
  +   * @param visitor The visitor whose appropriate method will be called.
  +   * @return true if the children of the object should be visited.
  +   */
  +  protected boolean accept(XSLTVisitor visitor)
  +  {
  +  	return visitor.visitInstruction(this);
  +  }
  +
  +  /**
  +   * @see XSLTVisitable#callVisitors(XSLTVisitor)
  +   */
  +  public void callVisitors(XSLTVisitor visitor)
  +  {
  +  	if(accept(visitor))
  +  	{
  +		callChildVisitors(visitor);
  +  	}
  +  }
  +
  +  /**
  +   * Call the children visitors.
  +   * @param visitor The visitor whose appropriate method will be called.
  +   */
  +  protected void callChildVisitors(XSLTVisitor visitor, boolean callAttributes)
  +  {
  +    for (ElemTemplateElement node = m_firstChild;
  +      node != null;
  +      node = node.m_nextSibling)
  +      {
  +      node.callVisitors(visitor);
  +    }
  +  }
  +  
  +  /**
  +   * Call the children visitors.
  +   * @param visitor The visitor whose appropriate method will be called.
  +   */
  +  protected void callChildVisitors(XSLTVisitor visitor)
  +  {
  +  	callChildVisitors(visitor, true);
  +  }
   
  +
   }
  
  
  
  1.17      +12 -0     xml-xalan/java/src/org/apache/xalan/templates/ElemValueOf.java
  
  Index: ElemValueOf.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/ElemValueOf.java,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- ElemValueOf.java	15 Jun 2001 21:18:35 -0000	1.16
  +++ ElemValueOf.java	22 Mar 2002 01:04:40 -0000	1.17
  @@ -355,4 +355,16 @@
       //" to " + this.m_elemName);
       return null;
     }
  +  
  +  /**
  +   * Call the children visitors.
  +   * @param visitor The visitor whose appropriate method will be called.
  +   */
  +  protected void callChildVisitors(XSLTVisitor visitor, boolean callAttrs)
  +  {
  +  	if(callAttrs)
  +  		m_selectExpression.getExpression().callVisitors(m_selectExpression, visitor);
  +    super.callChildVisitors(visitor, callAttrs);
  +  }
  +
   }
  
  
  
  1.15      +40 -0     xml-xalan/java/src/org/apache/xalan/templates/ElemVariable.java
  
  Index: ElemVariable.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/ElemVariable.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- ElemVariable.java	4 Mar 2002 18:21:31 -0000	1.14
  +++ ElemVariable.java	22 Mar 2002 01:04:40 -0000	1.15
  @@ -62,6 +62,7 @@
   import org.xml.sax.*;
   
   import org.apache.xpath.*;
  +import org.apache.xpath.Expression;
   import org.apache.xpath.objects.XObject;
   import org.apache.xpath.objects.XString;
   import org.apache.xpath.objects.XRTreeFrag;
  @@ -467,5 +468,44 @@
       super.setParentElem(p);
       p.m_hasVariableDecl = true;
     }
  +  
  +  /**
  +   * Accept a visitor and call the appropriate method 
  +   * for this class.
  +   * 
  +   * @param visitor The visitor whose appropriate method will be called.
  +   * @return true if the children of the object should be visited.
  +   */
  +  protected boolean accept(XSLTVisitor visitor)
  +  {
  +  	return visitor.visitVariableOrParamDecl(this);
  +  }
   
  +  
  +  /**
  +   * Call the children visitors.
  +   * @param visitor The visitor whose appropriate method will be called.
  +   */
  +  protected void callChildVisitors(XSLTVisitor visitor, boolean callAttrs)
  +  {
  +  	if(null != m_selectPattern)
  +  		m_selectPattern.getExpression().callVisitors(m_selectPattern, visitor);
  +    super.callChildVisitors(visitor, callAttrs);
  +  }
  +  
  +  /**
  +   * Tell if this is a psuedo variable reference, declared by Xalan instead 
  +   * of by the user.
  +   */
  +  public boolean isPsuedoVar()
  +  {
  +  	java.lang.String ns = m_qname.getNamespaceURI();
  +  	if((null != ns) && ns.equals(RedundentExprEliminator.PSUEDOVARNAMESPACE))
  +  	{
  +  		if(m_qname.getLocalName().startsWith("#"))
  +  			return true;
  +  	}
  +  	return false;
  +  }
  +
   }
  
  
  
  1.7       +12 -0     xml-xalan/java/src/org/apache/xalan/templates/ElemWhen.java
  
  Index: ElemWhen.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/ElemWhen.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- ElemWhen.java	12 Jun 2001 19:15:12 -0000	1.6
  +++ ElemWhen.java	22 Mar 2002 01:04:40 -0000	1.7
  @@ -152,4 +152,16 @@
      *
      */
     public ElemWhen(){}
  +  
  +  /**
  +   * Call the children visitors.
  +   * @param visitor The visitor whose appropriate method will be called.
  +   */
  +  protected void callChildVisitors(XSLTVisitor visitor, boolean callAttrs)
  +  {
  +  	if(callAttrs)
  +  		m_test.getExpression().callVisitors(m_test, visitor);
  +    super.callChildVisitors(visitor, callAttrs);
  +  }
  +
   }
  
  
  
  1.8       +12 -0     xml-xalan/java/src/org/apache/xalan/templates/ElemWithParam.java
  
  Index: ElemWithParam.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/ElemWithParam.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- ElemWithParam.java	12 Jun 2001 19:15:12 -0000	1.7
  +++ ElemWithParam.java	22 Mar 2002 01:04:40 -0000	1.8
  @@ -265,6 +265,18 @@
   
       return var;
     }
  +  
  +  /**
  +   * Call the children visitors.
  +   * @param visitor The visitor whose appropriate method will be called.
  +   */
  +  protected void callChildVisitors(XSLTVisitor visitor, boolean callAttrs)
  +  {
  +  	if(callAttrs && (null != m_selectPattern))
  +  		m_selectPattern.getExpression().callVisitors(m_selectPattern, visitor);
  +    super.callChildVisitors(visitor, callAttrs);
  +  }
  +
   
   
   }
  
  
  
  1.26      +1 -0      xml-xalan/java/src/org/apache/xalan/templates/FuncDocument.java
  
  Index: FuncDocument.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/FuncDocument.java,v
  retrieving revision 1.25
  retrieving revision 1.26
  diff -u -r1.25 -r1.26
  --- FuncDocument.java	8 Feb 2002 23:33:49 -0000	1.25
  +++ FuncDocument.java	22 Mar 2002 01:04:40 -0000	1.26
  @@ -179,6 +179,7 @@
         // the tree representation of the stylesheet is exactly 
         // the same as if the XML document containing the stylesheet 
         // was the initial source document.
  +      assertion(null != xctxt.getNamespaceContext(), "Namespace context can not be null!");
         base = xctxt.getNamespaceContext().getBaseIdentifier();
       }
   
  
  
  
  1.14      +18 -13    xml-xalan/java/src/org/apache/xalan/templates/FuncKey.java
  
  Index: FuncKey.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/FuncKey.java,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- FuncKey.java	8 Feb 2002 23:33:49 -0000	1.13
  +++ FuncKey.java	22 Mar 2002 01:04:40 -0000	1.14
  @@ -104,7 +104,7 @@
       XNodeSet nodes = null;
       int context = xctxt.getCurrentNode();
       DTM dtm = xctxt.getDTM(context);
  -    int docContext = dtm.getDocumentRoot(context);
  +    int docContext = dtm.getDocument();
   
       if (DTM.NULL == docContext)
       {
  @@ -117,6 +117,16 @@
       XObject arg = getArg1().execute(xctxt);
       boolean argIsNodeSetDTM = (XObject.CLASS_NODESET == arg.getType());
       KeyManager kmgr = transformer.getKeyManager();
  +    
  +    // Don't bother with nodeset logic if the thing is only one node.
  +    if(argIsNodeSetDTM)
  +    {
  +    	XNodeSet ns = (XNodeSet)arg;
  +    	ns.setShouldCacheNodes(true);
  +    	int len = ns.getLength();
  +    	if(len <= 1)
  +    		argIsNodeSetDTM = false;
  +    }
   
       if (argIsNodeSetDTM)
       {
  @@ -124,6 +134,7 @@
         DTMIterator ni = arg.iter();
         int pos;
         UnionPathIterator upi = new UnionPathIterator();
  +      upi.exprSetParent(this);
   
         while (DTM.NULL != (pos = ni.nextNode()))
         {
  @@ -147,13 +158,15 @@
             usedrefs.put(ref, ISTRUE);
           }
   
  -        LocPathIterator nl =
  +        XNodeSet nl =
             kmgr.getNodeSetDTMByKey(xctxt, docContext, keyname, ref,
                                  xctxt.getNamespaceContext());
  +                               
  +        nl.setRoot(xctxt.getCurrentNode(), xctxt);
   
   //        try
   //        {
  -          upi.addIterator((LocPathIterator)nl.asIterator(xctxt, docContext));
  +          upi.addIterator(nl);
   //        }
   //        catch(CloneNotSupportedException cnse)
   //        {
  @@ -170,18 +183,10 @@
       else
       {
         XMLString ref = arg.xstr();
  -      LocPathIterator nl = kmgr.getNodeSetDTMByKey(xctxt, docContext, keyname,
  +      nodes = kmgr.getNodeSetDTMByKey(xctxt, docContext, keyname,
                                                   ref,
                                                   xctxt.getNamespaceContext());
  -
  -      try
  -      {
  -        nodes = new XNodeSet((LocPathIterator)nl.cloneWithReset());
  -      }
  -      catch(CloneNotSupportedException cnse)
  -      {
  -        // will never happen.
  -      }
  +      nodes.setRoot(xctxt.getCurrentNode(), xctxt);
       }
   
       return nodes;
  
  
  
  1.25      +133 -0    xml-xalan/java/src/org/apache/xalan/templates/Stylesheet.java
  
  Index: Stylesheet.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/Stylesheet.java,v
  retrieving revision 1.24
  retrieving revision 1.25
  diff -u -r1.24 -r1.25
  --- Stylesheet.java	28 Sep 2001 14:49:40 -0000	1.24
  +++ Stylesheet.java	22 Mar 2002 01:04:40 -0000	1.25
  @@ -1411,4 +1411,137 @@
       v.setStylesheet(this);
     }
     
  +    /**
  +     * Call the children visitors.
  +     * @param visitor The visitor whose appropriate method will be called.
  +     */
  +    protected void callChildVisitors(XSLTVisitor visitor, boolean callAttrs)
  +    {
  +      int s = getImportCount();
  +      for (int j = 0; j < s; j++)
  +      {
  +      	getImport(j).callVisitors(visitor);
  +      }
  +   
  +      s = getIncludeCount();
  +      for (int j = 0; j < s; j++)
  +      {
  +      	getInclude(j).callVisitors(visitor);
  +      }
  +
  +      s = getOutputCount();
  +      for (int j = 0; j < s; j++)
  +      {
  +        visitor.visitTopLevelInstruction(getOutput(j));
  +      }
  +
  +      // Next, add in the attribute-set elements
  +
  +      s = getAttributeSetCount();
  +      for (int j = 0; j < s; j++)
  +      {
  +      	ElemAttributeSet attrSet = getAttributeSet(j);
  +        if (visitor.visitTopLevelInstruction(attrSet))
  +        {
  +          attrSet.callChildVisitors(visitor);
  +        }
  +      }
  +      // Now the decimal-formats
  +
  +      s = getDecimalFormatCount();
  +      for (int j = 0; j < s; j++)
  +      {
  +        visitor.visitTopLevelInstruction(getDecimalFormat(j));
  +      }
  +
  +      // Now the keys
  +
  +      s = getKeyCount();
  +      for (int j = 0; j < s; j++)
  +      {
  +        visitor.visitTopLevelInstruction(getKey(j));
  +      }
  +
  +      // And the namespace aliases
  +
  +      s = getNamespaceAliasCount();
  +      for (int j = 0; j < s; j++)
  +      {
  +        visitor.visitTopLevelInstruction(getNamespaceAlias(j));
  +      }
  +
  +      // Next comes the templates
  +
  +      s = getTemplateCount();
  +      for (int j = 0; j < s; j++)
  +      {
  +        try
  +        {
  +          ElemTemplate template = getTemplate(j);
  +          if (visitor.visitTopLevelInstruction(template))
  +          {
  +            template.callChildVisitors(visitor);
  +          }
  +        }
  +        catch (TransformerException te)
  +        {
  +          throw new org.apache.xml.utils.WrappedRuntimeException(te);
  +        }
  +      }
  +
  +      // Then, the variables
  +
  +      s = getVariableOrParamCount();
  +      for (int j = 0; j < s; j++)
  +      {
  +      	ElemVariable var = getVariableOrParam(j);
  +        if (visitor.visitTopLevelVariableOrParamDecl(var))
  +        {
  +          var.callChildVisitors(visitor);
  +        }
  +      }
  +
  +      // And lastly the whitespace preserving and stripping elements
  +
  +      s = getStripSpaceCount();
  +      for (int j = 0; j < s; j++)
  +      {
  +        visitor.visitTopLevelInstruction(getStripSpace(j));
  +      }
  +
  +      s = getPreserveSpaceCount();
  +      for (int j = 0; j < s; j++)
  +      {
  +        visitor.visitTopLevelInstruction(getPreserveSpace(j));
  +      }
  +      
  +      if(null != m_NonXslTopLevel)
  +      {
  +      	java.util.Enumeration enum = m_NonXslTopLevel.elements();
  +      	while(enum.hasMoreElements())
  +      	{
  +      	  ElemTemplateElement elem = (ElemTemplateElement)enum.nextElement();
  +          if (visitor.visitTopLevelInstruction(elem))
  +          {
  +            elem.callChildVisitors(visitor);
  +          }
  +      		
  +      	}
  +      }
  +    }
  +        
  +          
  +  /**
  +   * Accept a visitor and call the appropriate method 
  +   * for this class.
  +   * 
  +   * @param visitor The visitor whose appropriate method will be called.
  +   * @return true if the children of the object should be visited.
  +   */
  +  protected boolean accept(XSLTVisitor visitor)
  +  {
  +  	return visitor.visitStylesheet(this);
  +  }
  +
  +  
   }
  
  
  
  1.8       +15 -0     xml-xalan/java/src/org/apache/xalan/templates/WhiteSpaceInfo.java
  
  Index: WhiteSpaceInfo.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/WhiteSpaceInfo.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- WhiteSpaceInfo.java	2 Jan 2001 03:36:47 -0000	1.7
  +++ WhiteSpaceInfo.java	22 Mar 2002 01:04:40 -0000	1.8
  @@ -81,6 +81,21 @@
     {
       return m_shouldStripSpace;
     }
  +  
  +  /**
  +   * Constructor WhiteSpaceInfo
  +   *
  +   *
  +   * @param matchPattern Match pattern
  +   * @param shouldStripSpace Flag indicating whether or not
  +   * to strip whitespaces
  +   * @param thisSheet The current stylesheet
  +   */
  +  public WhiteSpaceInfo(Stylesheet thisSheet)
  +  {
  +  	setStylesheet(thisSheet);
  +  }
  +
   
     /**
      * Constructor WhiteSpaceInfo
  
  
  
  1.2       +117 -0    xml-xalan/java/src/org/apache/xalan/templates/AbsPathChecker.java
  
  
  
  
  1.2       +48 -0     xml-xalan/java/src/org/apache/xalan/templates/ElemVariablePsuedo.java
  
  
  
  
  1.2       +1470 -0   xml-xalan/java/src/org/apache/xalan/templates/RedundentExprEliminator.java
  
  
  
  
  1.2       +60 -0     xml-xalan/java/src/org/apache/xalan/templates/VarNameCollector.java
  
  
  
  
  1.2       +20 -0     xml-xalan/java/src/org/apache/xalan/templates/XSLTVisitable.java
  
  
  
  
  1.2       +165 -0    xml-xalan/java/src/org/apache/xalan/templates/XSLTVisitor.java
  
  
  
  
  1.2       +64 -0     xml-xalan/java/src/org/apache/xalan/templates/XUnresolvedVariableSimple.java
  
  
  
  
  1.10      +2 -2      xml-xalan/java/src/org/apache/xalan/trace/TraceManager.java
  
  Index: TraceManager.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/trace/TraceManager.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- TraceManager.java	28 Jun 2001 21:33:57 -0000	1.9
  +++ TraceManager.java	22 Mar 2002 01:04:41 -0000	1.10
  @@ -219,7 +219,7 @@
       {
         Node source = m_transformer.getXPathContext().getDTM(
           sourceNode).getNode(sourceNode);
  -
  +        
         fireSelectedEvent(new SelectionEvent(m_transformer, source, styleNode,
                                              attributeName, xpath, selection));
       }
  @@ -246,7 +246,7 @@
       {
         Node source = m_transformer.getXPathContext().getDTM(
           sourceNode).getNode(sourceNode);
  -
  +        
         fireSelectedEndEvent(new EndSelectionEvent(m_transformer, source, styleNode,
                                              attributeName, xpath, selection));
       }
  
  
  
  1.12      +81 -119   xml-xalan/java/src/org/apache/xalan/transformer/KeyIterator.java
  
  Index: KeyIterator.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/transformer/KeyIterator.java,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- KeyIterator.java	8 Feb 2002 23:33:49 -0000	1.11
  +++ KeyIterator.java	22 Mar 2002 01:04:41 -0000	1.12
  @@ -58,42 +58,29 @@
   
   import java.util.Vector;
   
  -import org.apache.xpath.axes.WalkingIterator;
  -import org.apache.xml.utils.PrefixResolver;
  -import org.apache.xml.utils.XMLString;
  -import org.apache.xml.utils.QName;
  +import javax.xml.transform.TransformerException;
  +import org.apache.xalan.res.XSLMessages;
  +import org.apache.xalan.res.XSLTErrorResources;
   import org.apache.xalan.templates.KeyDeclaration;
  -import org.apache.xpath.XPathContext;
  -import org.apache.xpath.objects.XObject;
  +import org.apache.xml.dtm.Axis;
  +import org.apache.xml.dtm.DTMIterator;
  +import org.apache.xml.utils.QName;
   import org.apache.xpath.XPath;
  -
  -import org.apache.xml.dtm.DTM;
  -
  -import javax.xml.transform.TransformerException;
  +import org.apache.xpath.XPathContext;
  +import org.apache.xpath.axes.OneStepIteratorForward;
   
   /**
    * <meta name="usage" content="internal"/>
    * This class implements an optimized iterator for 
  - * "key()" patterns. This iterator incrementally walks the 
  - * source tree and finds all the nodes that match
  - * a given key name and match pattern.
  + * "key()" patterns, matching each node to the 
  + * match attribute in one or more xsl:key declarations.
    */
  -public class KeyIterator extends WalkingIterator
  +public class KeyIterator extends OneStepIteratorForward
   {
  -  
  -  /** The key table this iterator is associated to.
  -   *  @serial          */
  -  private KeyTable m_keyTable;
   
     /** Key name.
      *  @serial           */
     private QName m_name;
  -  
  -  /** 
  -   * Flag indicating whether the whole source tree has been walked.     
  -   * True if we still need to finish walking the tree.
  -   * */
  -  transient private boolean m_lookForMoreNodes = true;
   
     /**
      * Get the key name from a key declaration this iterator will process
  @@ -122,109 +109,84 @@
     }
   
     /**
  -   * Constructor KeyIterator
  -   *
  -   *
  -   * @param doc The document node
  -   * @param nscontext The prefix resolver for the execution context.
  -   * @param name The key name
  -   * @param keyDeclarations The key declarations from the stylesheet 
  -   * @param xctxt The XPath runtime state
  -   */
  -  public KeyIterator(int doc, PrefixResolver nscontext, QName name,
  -                     Vector keyDeclarations, XPathContext xctxt)
  +    * Create a KeyIterator object.
  +    *
  +    * @param compiler A reference to the Compiler that contains the op map.
  +    * @param opPos The position within the op map, which contains the
  +    * location path expression for this itterator.
  +    *
  +    * @throws javax.xml.transform.TransformerException
  +    */
  +  KeyIterator(QName name, Vector keyDeclarations)
     {
  -
  -    super(nscontext);
  -
  -    int current = xctxt.getCurrentNode();
  -    setRoot(current, xctxt);
  -
  -    m_name = name;
  +    super(Axis.ALL);
       m_keyDeclarations = keyDeclarations;
  -    m_firstWalker = new KeyWalker(this);
  -
  -    this.setLastUsedWalker(m_firstWalker);
  +    // m_prefixResolver = nscontext;
  +    m_name = name;
     }
   
     /**
  -   * Returns the next node in the set and advances the position of the
  -   * iterator in the set. After a NodeIterator is created, the first call
  -   * to nextNode() returns the first node in the set.
  +   *  Test whether a specified node is visible in the logical view of a
  +   * TreeWalker or NodeIterator. This function will be called by the
  +   * implementation of TreeWalker and NodeIterator; it is not intended to
  +   * be called directly from user code.
      * 
  -   * @return  The next <code>Node</code> in the set being iterated over, or
  -   *   <code>null</code> if there are no more members in that set.
  -   */
  -  public int nextNode()
  -  {
  -
  -    // If the cache is on, and the node has already been found, then 
  -    // just return from the list.
  -    int n = super.nextNode();
  -
  -    // System.out.println("--> "+((null == n) ? "null" : n.getNodeName()));
  -    return n;
  -  }
  -
  -  /**
  -   * Set the value of the key that this iterator will look for 
  +   * @param testnode  The node to check to see if it passes the filter or not.
      *
  -   *
  -   * @param lookupKey value of the key to look for
  +   * @return  a constant to determine whether the node is accepted,
  +   *   rejected, or skipped, as defined  above .
      */
  -  public void setLookupKey(XMLString lookupKey)
  +  public short acceptNode(int testNode)
     {
  -
  -    // System.out.println("setLookupKey - lookupKey: "+lookupKey);
  -    ((KeyWalker) m_firstWalker).m_lookupKey = lookupKey;
  -
  -    int context = getContext();
  -    DTM dtm = this.getDTM(context);
  -    m_firstWalker.setRoot(dtm.getDocumentRoot(context));
  -    this.setLastUsedWalker(m_firstWalker);
  -    this.setNextPosition(0);
  +    boolean foundKey = false;
  +    KeyIterator ki = (KeyIterator) m_lpi;
  +    org.apache.xpath.XPathContext xctxt = ki.getXPathContext();
  +    Vector keys = ki.getKeyDeclarations();
  +
  +    QName name = ki.getName();
  +    try
  +    {
  +      // System.out.println("lookupKey: "+lookupKey);
  +      int nDeclarations = keys.size();
  +
  +      // Walk through each of the declarations made with xsl:key
  +      for (int i = 0; i < nDeclarations; i++)
  +      {
  +        KeyDeclaration kd = (KeyDeclaration) keys.elementAt(i);
  +
  +        // Only continue if the name on this key declaration
  +        // matches the name on the iterator for this walker. 
  +        if (!kd.getName().equals(name))
  +          continue;
  +
  +        foundKey = true;
  +        // xctxt.setNamespaceContext(ki.getPrefixResolver());
  +
  +        // See if our node matches the given key declaration according to 
  +        // the match attribute on xsl:key.
  +        XPath matchExpr = kd.getMatch();
  +        double score = matchExpr.getMatchScore(xctxt, testNode);
  +
  +        if (score == kd.getMatch().MATCH_SCORE_NONE)
  +          continue;
  +
  +        return DTMIterator.FILTER_ACCEPT;
  +
  +      } // end for(int i = 0; i < nDeclarations; i++)
  +    }
  +    catch (TransformerException se)
  +    {
  +
  +      // TODO: What to do?
  +    }
  +
  +    if (!foundKey)
  +      throw new RuntimeException(
  +        XSLMessages.createMessage(
  +          XSLTErrorResources.ER_NO_XSLKEY_DECLARATION,
  +          new Object[] { name.getLocalName()}));
  +          
  +    return DTMIterator.FILTER_REJECT;
     }
  -  
  -  /**
  -   * Set the KeyTable associated with this iterator  
  -   *
  -   *
  -   * @param keyTable, the KeyTable associated with this iterator
  -   */
  -  void setKeyTable(KeyTable keyTable)
  -  {
  -    m_keyTable = keyTable;
  -  }  
  -  
  -  /**
  -   * Add this value(ref) to the refsTable in KeyTable  
  -   *
  -   *
  -   * @param ref Key value(ref)(from key use field)
  -   * @param node Node matching that ref 
  -   */
  -  void addRefNode(XMLString ref, int node)
  -  {
  -    m_keyTable.addRefNode(ref, node);
  -  }
  -  
  -  /**
  -   * Indicate whether we have walked the whole tree  
  -   *
  -   * @param b False if we have walked the whole tree
  -   */
  -  void setLookForMoreNodes(boolean b)
  -  {
  -    m_lookForMoreNodes = b;
  -  }
  -  
  -  /**
  -   * Get flag indicating whether we have walked the whole tree  
  -   *
  -   */
  -  boolean getLookForMoreNodes()
  -  {
  -    return m_lookForMoreNodes;
  -  }
  -  
  +
   }
  
  
  
  1.13      +3 -2      xml-xalan/java/src/org/apache/xalan/transformer/KeyManager.java
  
  Index: KeyManager.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/transformer/KeyManager.java,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- KeyManager.java	15 Jun 2001 05:14:07 -0000	1.12
  +++ KeyManager.java	22 Mar 2002 01:04:41 -0000	1.13
  @@ -68,6 +68,7 @@
   import org.apache.xml.utils.XMLString;
   import org.apache.xpath.XPathContext;
   import org.apache.xpath.axes.LocPathIterator;
  +import org.apache.xpath.objects.XNodeSet;
   
   /**
    * This class manages the key tables.
  @@ -94,12 +95,12 @@
      *
      * @throws javax.xml.transform.TransformerException
      */
  -  public LocPathIterator getNodeSetDTMByKey(
  +  public XNodeSet getNodeSetDTMByKey(
             XPathContext xctxt, int doc, QName name, XMLString ref, PrefixResolver nscontext)
               throws javax.xml.transform.TransformerException
     {
   
  -    LocPathIterator nl = null;
  +    XNodeSet nl = null;
       ElemTemplateElement template = (ElemTemplateElement) nscontext;  // yuck -sb
   
       if ((null != template)
  
  
  
  1.13      +116 -164  xml-xalan/java/src/org/apache/xalan/transformer/KeyRefIterator.java
  
  Index: KeyRefIterator.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/transformer/KeyRefIterator.java,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- KeyRefIterator.java	18 Sep 2001 20:08:16 -0000	1.12
  +++ KeyRefIterator.java	22 Mar 2002 01:04:41 -0000	1.13
  @@ -56,55 +56,25 @@
    */
   package org.apache.xalan.transformer;
   
  +import org.apache.xml.dtm.DTM;
  +import org.apache.xml.dtm.DTMIterator;
  +import org.apache.xml.utils.NodeVector;
  +import org.apache.xml.utils.XMLString;
  +import org.apache.xpath.objects.XNodeSet;
  +import org.apache.xpath.objects.XObject;
   import java.util.Vector;
  -
  -import org.apache.xpath.axes.LocPathIterator;
   import org.apache.xml.utils.QName;
  -import org.apache.xml.utils.XMLString;
   import org.apache.xalan.templates.KeyDeclaration;
  -import org.apache.xpath.NodeSetDTM;
  -
  -//import org.w3c.dom.Node;
  -//import org.w3c.dom.DOMException;
  -//import org.w3c.dom.traversal.NodeIterator;
  -import org.apache.xml.dtm.DTM;
  -import org.apache.xml.dtm.DTMIterator;
  +import org.apache.xalan.res.XSLMessages;
  +import org.apache.xalan.res.XSLTErrorResources;
   
   /**
    * <meta name="usage" content="internal"/>
  - * This class implements an optimized iterator for 
  - * "key()" patterns. It uses a KeyIterator to walk the 
  - * source tree and incrementally build a list of nodes that match
  - * a given key name, match pattern and value.  
  + * This class filters nodes from a key iterator, according to 
  + * whether or not the use value matches the ref value.  
    */
  -public class KeyRefIterator extends LocPathIterator
  +public class KeyRefIterator extends org.apache.xpath.axes.ChildTestIterator
   {
  -
  -  /** Key name.
  -   *  @serial         */
  -  private final QName m_name;    
  -  
  -  /** Use field of key function.
  -   *  @serial         */
  -  private final XMLString m_lookupKey;  
  -  
  -  /** Main Key iterator for this iterator.
  -   *  @serial    */
  -  private final KeyIterator m_ki;    
  -  
  -  /**
  -   * Get key name
  -   *
  -   *
  -   * @return Key name
  -   */
  -  public QName getName()
  -  {
  -    return m_name;
  -  }
  -  
  -  
  -
     /**
      * Constructor KeyRefIterator
      *
  @@ -112,142 +82,124 @@
      * @param ref Key value to match
      * @param ki The main key iterator used to walk the source tree 
      */
  -  public KeyRefIterator(XMLString ref, KeyIterator ki)
  +  public KeyRefIterator(QName name, XMLString ref, Vector keyDecls, DTMIterator ki)
     {
  -
  -    super(ki.getPrefixResolver());   
  -    m_ki = ki;
  -    m_name = ki.getName();
  -    m_lookupKey = ref;
  -    this.m_execContext = ki.getXPathContext();
  -    setShouldCacheNodes(true);
  +    super(null);
  +    m_name = name;
  +    m_ref = ref;
  +    m_keyDeclarations = keyDecls;
  +    m_keysNodes = ki;
  +    setWhatToShow(org.apache.xml.dtm.DTMFilter.SHOW_ALL);
     }
  -
  +  
  +  DTMIterator m_keysNodes;
  +  
     /**
  -   *  Returns the next node in the set and advances the position of the
  -   * iterator in the set. After a NodeIterator is created, the first call
  -   * to nextNode() returns the first node in the set.
  -   * 
  -   * @return  The next <code>Node</code> in the set being iterated over, or
  -   *   <code>null</code> if there are no more members in that set.
  +   * Get the next node via getNextXXX.  Bottlenecked for derived class override.
  +   * @return The next node on the axis, or DTM.NULL.
      */
  -  public int nextNode()
  -  {   
  -    
  -    // If the cache is on, and the node has already been found, then 
  -    // just return from the list.
  -    NodeSetDTM m_cachedNodes = getCachedNodes();
  -    
  -    // We are not using the NodeSetDTM methods getCurrentPos() and nextNode()
  -    // in this case because the nodeset is not cloned and therefore
  -    // the positions it indicates may not be associated with the 
  -    // current iterator.
  -    if ((null != m_cachedNodes)
  -        && (m_next < m_cachedNodes.size()))        
  -    {
  -      int next = m_cachedNodes.elementAt(m_next); 
  -      this.setCurrentPos(++m_next); 
  -      m_lastFetched = next;
  -      
  -      return next;
  -    }
  -    
  -    if (m_foundLast)
  -    {
  -      m_lastFetched = DTM.NULL;
  -      return DTM.NULL;
  -    }
  -
  -    int next = DTM.NULL;       
  -    if ( m_ki.getLookForMoreNodes()) 
  +  protected int getNextNode()
  +  {                  
  +  	int next;   
  +    while(DTM.NULL != (next = m_keysNodes.nextNode()))
       {
  -      ((KeyWalker)m_ki.getFirstWalker()).m_lookupKey = m_lookupKey;
  -      next = m_ki.nextNode();        
  -    }
  -    
  -    if (DTM.NULL != next)
  -    {  
  -      m_lastFetched = next;
  -      this.setCurrentPos(++m_next);
  -      return next;
  +    	if(DTMIterator.FILTER_ACCEPT == filterNode(next))
  +    		break;
       }
  -    else
  -      m_foundLast = true;                      
  +    m_lastFetched = next;
       
  -    m_lastFetched = DTM.NULL;
  -    return DTM.NULL;
  +    return next;
     }
  -  
  -  /**
  -   * Get a cloned LocPathIterator that holds the same 
  -   * position as this iterator.
  -   *
  -   * @return A clone of this iterator that holds the same node position.
  -   *
  -   * @throws CloneNotSupportedException 
  -   */
  -  public Object clone() throws CloneNotSupportedException
  -  {
  -    // I wonder if we really want to clone the second time.  Myriam review.
  -    KeyRefIterator clone = (KeyRefIterator)super.clone();
  -    // clone.m_ki = (KeyIterator)m_ki.clone();
   
  -    return clone;
  -  }
  -  
  -//  /**
  -//   * Get a cloned Iterator that is reset to the beginning 
  -//   * of the query.
  -//   *
  -//   * @return A cloned NodeIterator set of the start of the query.
  -//   *
  -//   * @throws CloneNotSupportedException
  -//   */
  -//  public NodeIterator cloneWithReset() throws CloneNotSupportedException
  -//  {
  -//    KeyRefIterator clone = (KeyRefIterator)super.cloneWithReset();
  -//
  -//    return clone;
  -//  }
  -  
  -  /**
  -   * Reset the iterator.
  -   */
  -  public void reset()
  -  {
  -    super.reset();
  -    // setShouldCacheNodes(true);
  -    setCurrentPos(0);
  -  }
  -  
  -  /**
  -   *  Detaches the iterator from the set which it iterated over, releasing
  -   * any computational resources and placing the iterator in the INVALID
  -   * state. After<code>detach</code> has been invoked, calls to
  -   * <code>nextNode</code> or<code>previousNode</code> will raise the
  -   * exception INVALID_STATE_ERR.
  -   */
  -  public void detach()
  -  {    
  -    // I don't think we want to detach at all for this iterator.
  -    // Myriam needs to review.  -sb.
  -  }
   
  -  
     /**
  -   * Add a node matching this ref to the cached nodes for this iterator 
  -   *
  +   *  Test whether a specified node is visible in the logical view of a
  +   * TreeWalker or NodeIterator. This function will be called by the
  +   * implementation of TreeWalker and NodeIterator; it is not intended to
  +   * be called directly from user code.
  +   * 
  +   * @param testnode  The node to check to see if it passes the filter or not.
      *
  -   * @param node Node to add to cached nodes
  +   * @return  a constant to determine whether the node is accepted,
  +   *   rejected, or skipped, as defined  above .
      */
  -  public void addNode(int node) 
  +  public short filterNode(int testNode)
     {
  -    NodeSetDTM m_cachedNodes = getCachedNodes();
  -    if (null != m_cachedNodes)
  +    boolean foundKey = false;
  +    Vector keys = m_keyDeclarations;
  +
  +    QName name = m_name;
  +    KeyIterator ki = (KeyIterator)(((XNodeSet)m_keysNodes).getContainedIter());
  +    org.apache.xpath.XPathContext xctxt = ki.getXPathContext();
  +    
  +    if(null == xctxt)
  +    	assertion(false, "xctxt can not be null here!");
  +
  +    try
  +    {
  +      XMLString lookupKey = m_ref;
  +
  +      // System.out.println("lookupKey: "+lookupKey);
  +      int nDeclarations = keys.size();
  +
  +      // Walk through each of the declarations made with xsl:key
  +      for (int i = 0; i < nDeclarations; i++)
  +      {
  +        KeyDeclaration kd = (KeyDeclaration) keys.elementAt(i);
  +
  +        // Only continue if the name on this key declaration
  +        // matches the name on the iterator for this walker. 
  +        if (!kd.getName().equals(name))
  +          continue;
  +
  +        foundKey = true;
  +        // xctxt.setNamespaceContext(ki.getPrefixResolver());
  +
  +        // Query from the node, according the the select pattern in the
  +        // use attribute in xsl:key.
  +        XObject xuse = kd.getUse().execute(xctxt, testNode, ki.getPrefixResolver());
  +
  +        if (xuse.getType() != xuse.CLASS_NODESET)
  +        {
  +          XMLString exprResult = xuse.xstr();
  +
  +          if (lookupKey.equals(exprResult))
  +            return DTMIterator.FILTER_ACCEPT;
  +        }
  +        else
  +        {
  +          DTMIterator nl = ((XNodeSet)xuse).iterRaw();
  +          int useNode;
  +          
  +          while (DTM.NULL != (useNode = nl.nextNode()))
  +          {
  +            DTM dtm = getDTM(useNode);
  +            XMLString exprResult = dtm.getStringValue(useNode);
  +            if ((null != exprResult) && lookupKey.equals(exprResult))
  +              return DTMIterator.FILTER_ACCEPT;
  +          }
  +        }
  +
  +      } // end for(int i = 0; i < nDeclarations; i++)
  +    }
  +    catch (javax.xml.transform.TransformerException te)
       {
  -      if(!m_cachedNodes.contains(node))
  -        m_cachedNodes.addElement(node);
  +      throw new org.apache.xml.utils.WrappedRuntimeException(te);
       }
  -  }  
  -       
  -}
  +
  +    if (!foundKey)
  +      throw new RuntimeException(
  +        XSLMessages.createMessage(
  +          XSLTErrorResources.ER_NO_XSLKEY_DECLARATION,
  +          new Object[] { name.getLocalName()}));
  +    return DTMIterator.FILTER_REJECT;
  +  }
  +
  +  protected XMLString m_ref;
  +  protected QName m_name;
  +
  +  /** Vector of Key declarations in the stylesheet.
  +   *  @serial          */
  +  protected Vector m_keyDeclarations;
  +
  +}
  \ No newline at end of file
  
  
  
  1.11      +25 -119   xml-xalan/java/src/org/apache/xalan/transformer/KeyTable.java
  
  Index: KeyTable.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/transformer/KeyTable.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- KeyTable.java	15 Jun 2001 05:14:09 -0000	1.10
  +++ KeyTable.java	22 Mar 2002 01:04:41 -0000	1.11
  @@ -56,29 +56,16 @@
    */
   package org.apache.xalan.transformer;
   
  -//import org.w3c.dom.Element;
  -//import org.w3c.dom.NamedNodeMap;
  -//import org.w3c.dom.Node;
  -//import org.w3c.dom.NodeList;
  -import org.apache.xml.dtm.DTM;
  -
   import java.util.Hashtable;
   import java.util.Vector;
  -import java.util.Enumeration;
   
  -import org.apache.xpath.NodeSetDTM;
  -import org.apache.xpath.objects.XObject;
  -import org.apache.xpath.XPathContext;
  -import org.apache.xpath.XPathContext;
  -//import org.apache.xpath.DOMHelper;
  -import org.apache.xml.utils.QName;
  -import org.apache.xalan.templates.KeyDeclaration;
  -import org.apache.xpath.XPathContext;
  +import javax.xml.transform.TransformerException;
  +import org.apache.xml.dtm.DTM;
   import org.apache.xml.utils.PrefixResolver;
  +import org.apache.xml.utils.QName;
   import org.apache.xml.utils.XMLString;
  -import org.apache.xpath.axes.LocPathIterator;
  -
  -// import org.apache.xalan.dtm.*;
  +import org.apache.xpath.XPathContext;
  +import org.apache.xpath.objects.XNodeSet;
   
   /**
    * <meta name="usage" content="advanced"/>
  @@ -111,16 +98,12 @@
      * The main iterator that will walk through the source  
      * tree for this key.
      */
  -  private KeyIterator m_keyIter;
  +  private XNodeSet m_keyNodes;
     
  -  /**
  -   * Hashtable of keys.
  -   * The table is:
  -   * a) keyed by key name,
  -   * b) with a value that is a hashtable keyed by key values 
  -   * with at value of KeyRefIterator(cloned).
  -   */
  -  private Hashtable m_defsTable;
  +  KeyIterator getKeyIterator()
  +  {
  +  	return (KeyIterator)(m_keyNodes.getContainedIter());
  +  }
   
     /**
      * Build a keys table.
  @@ -133,14 +116,17 @@
      * @throws javax.xml.transform.TransformerException
      */
     public KeyTable(
  -          int doc, PrefixResolver nscontext, QName name, Vector keyDeclarations, XPathContext xmlLiaison)
  +          int doc, PrefixResolver nscontext, QName name, Vector keyDeclarations, XPathContext xctxt)
               throws javax.xml.transform.TransformerException
     {
   
       m_docKey = doc;
  -    m_keyIter = new KeyIterator(doc, nscontext, name, keyDeclarations,
  -                                xmlLiaison);
  -    m_keyIter.setKeyTable(this);
  +    KeyIterator ki = new KeyIterator(name, keyDeclarations);
  +    
  +    m_keyNodes = new XNodeSet(ki);
  +    m_keyNodes.allowDetachToRelease(false);
  +    
  +    m_keyNodes.setRoot(xctxt.getDTM(doc).getDocument(), xctxt);
     }  
   
     /**
  @@ -152,55 +138,15 @@
      * if the identifier is not found, it will return null,
      * otherwise it will return a LocPathIterator instance.
      */
  -  public LocPathIterator getNodeSetDTMByKey(QName name, XMLString ref)
  +  public XNodeSet getNodeSetDTMByKey(QName name, XMLString ref)
     {
  +  	Vector keyDecls = getKeyIterator().getKeyDeclarations();
  +  	org.apache.xml.dtm.DTMIterator keyNodes = m_keyNodes.iter();
  +	XNodeSet refNodes = new XNodeSet( new KeyRefIterator(name, ref, keyDecls, keyNodes) );
  +	
  +	// I don't think setRoot needs to be called on refNodes!
  +	return refNodes;
   
  -    KeyIterator ki;
  -    KeyRefIterator kiRef;
  -    Hashtable refsTable = null;
  -
  -    // First look for the key in the existing key names table
  -    if (m_defsTable != null)
  -    {
  -      refsTable = (Hashtable)m_defsTable.get(name);
  -      if (refsTable != null)
  -      {
  -        Object kiObj = refsTable.get(ref);
  -        if (kiObj != null)
  -        {
  -          // An entry already exists for this key name and value.
  -          // Return a clone of the node iterator found.
  -          try
  -          {
  -            // clone with reset??
  -            kiRef = (KeyRefIterator)((KeyRefIterator)kiObj).clone();
  -            return kiRef;
  -          }
  -          catch (CloneNotSupportedException cnse)
  -          {
  -            ki = null;
  -          }
  -        }
  -      }
  -    }
  -
  -    // No entry was found for this key name and value. Create one.
  -    {
  -      if (m_defsTable == null)
  -        m_defsTable = new Hashtable();
  -      if (refsTable == null)
  -        refsTable = new Hashtable();
  -      
  -      // initialize walker only once!
  -      if (m_keyIter.getFirstWalker().getRoot() == DTM.NULL)
  -        m_keyIter.setLookupKey(ref);
  -      else
  -        ((KeyWalker)m_keyIter.getFirstWalker()).m_lookupKey = ref;
  -      kiRef = new KeyRefIterator(ref, m_keyIter);
  -      refsTable.put(ref, kiRef);
  -      m_defsTable.put(name,refsTable);
  -      return kiRef;              
  -    } 
     }
   
     /**
  @@ -211,47 +157,7 @@
      */
     public QName getKeyTableName()
     {
  -    return m_keyIter.getName();
  -  }
  -  
  -  /**
  -   * Add this node to the nodelist matching this key value. 
  -   * If there was no existing entry for that key value, create
  -   * one.   
  -   *
  -   * @param ref Key ref(from key use field)
  -   * @param node Node matching that ref 
  -   */
  -  void addRefNode(XMLString ref, int node)
  -  {
  -    KeyRefIterator kiRef = null;
  -    Hashtable refsTable = null;
  -    if (m_defsTable != null)
  -    {
  -      refsTable = (Hashtable)m_defsTable.get(getKeyTableName());
  -      if (refsTable != null)
  -      {
  -        Object kiObj = refsTable.get(ref);
  -        if (kiObj != null)
  -        {          
  -          kiRef = (KeyRefIterator)kiObj;            
  -        }
  -      }
  -    }
  -    if (kiRef == null)
  -    {  
  -      if (m_defsTable == null)
  -        m_defsTable = new Hashtable();
  -      if (refsTable == null)
  -      {  
  -        refsTable = new Hashtable();
  -        m_defsTable.put(getKeyTableName(),refsTable);
  -      }
  -      kiRef = new KeyRefIterator(ref, m_keyIter);
  -      refsTable.put(ref, kiRef);      
  -    }
  -    kiRef.addNode(node); 
  +    return getKeyIterator().getName();
     }
  -  
     
   }
  
  
  
  1.14      +1 -1      xml-xalan/java/src/org/apache/xalan/transformer/NodeSorter.java
  
  Index: NodeSorter.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/transformer/NodeSorter.java,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- NodeSorter.java	10 Aug 2001 21:30:08 -0000	1.13
  +++ NodeSorter.java	22 Mar 2002 01:04:41 -0000	1.14
  @@ -565,7 +565,7 @@
           if (r.getType() == XObject.CLASS_NODESET)
           {
             // %REVIEW%
  -          DTMIterator ni = (DTMIterator)r.object();
  +          DTMIterator ni = ((XNodeSet)r).iterRaw();
             int current = ni.getCurrentNode();
             if(DTM.NULL == current)
               current = ni.nextNode();
  
  
  
  1.55      +7 -4      xml-xalan/java/src/org/apache/xalan/transformer/ResultTreeHandler.java
  
  Index: ResultTreeHandler.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/transformer/ResultTreeHandler.java,v
  retrieving revision 1.54
  retrieving revision 1.55
  diff -u -r1.54 -r1.55
  --- ResultTreeHandler.java	29 Nov 2001 04:18:20 -0000	1.54
  +++ ResultTreeHandler.java	22 Mar 2002 01:04:41 -0000	1.55
  @@ -978,11 +978,14 @@
       int doc = obj.rtf();
       DTM dtm = support.getDTM(doc);
   
  -    for (int n = dtm.getFirstChild(doc); DTM.NULL != n;
  -            n = dtm.getNextSibling(n))
  +    if(null != dtm)
       {
  -      flushPending(true);  // I think.
  -      dtm.dispatchToEvents(n, this);
  +	    for (int n = dtm.getFirstChild(doc); DTM.NULL != n;
  +	            n = dtm.getNextSibling(n))
  +	    {
  +	      flushPending(true);  // I think.
  +	      dtm.dispatchToEvents(n, this);
  +	    }
       }
     }
   
  
  
  
  1.15      +0 -3      xml-xalan/java/src/org/apache/xalan/transformer/TransformerHandlerImpl.java
  
  Index: TransformerHandlerImpl.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/transformer/TransformerHandlerImpl.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- TransformerHandlerImpl.java	8 Feb 2002 23:33:49 -0000	1.14
  +++ TransformerHandlerImpl.java	22 Mar 2002 01:04:41 -0000	1.15
  @@ -429,9 +429,6 @@
       }
       else
       {
  -      // %REVIEW% If this could ever be a shared DTM, we might need to
  -      // retrieve the Document node _before_ issuing endDocument(), or
  -      // use the getDocumentRoot(nodeHandle) method.
         m_transformer.setSourceTreeDocForThread(m_dtm.getDocument());
         m_transformer.run();
       }
  
  
  
  1.6       +3 -0      xml-xalan/java/src/org/apache/xml/utils/NodeVector.java
  
  Index: NodeVector.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xml/utils/NodeVector.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- NodeVector.java	24 Jun 2001 01:20:23 -0000	1.5
  +++ NodeVector.java	22 Mar 2002 01:04:42 -0000	1.6
  @@ -561,6 +561,9 @@
         m_map = new int[m_blocksize];
         m_mapSize = m_blocksize;
       }
  +    
  +    if(index == -1)
  +    	addElement(node);
   
       m_map[index] = node;
     }
  
  
  
  1.18      +238 -22   xml-xalan/java/src/org/apache/xpath/Expression.java
  
  Index: Expression.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/Expression.java,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- Expression.java	28 Jul 2001 00:45:05 -0000	1.17
  +++ Expression.java	22 Mar 2002 01:04:42 -0000	1.18
  @@ -58,6 +58,7 @@
   
   //import org.w3c.dom.Node;
   import org.apache.xpath.objects.XObject;
  +import org.apache.xpath.objects.XNodeSet;
   import org.apache.xpath.res.XPATHErrorResources;
   import org.apache.xalan.res.XSLMessages;
   
  @@ -85,7 +86,7 @@
    * and walkers, which must be cloned in order to be used -- the original must
    * still be immutable.
    */
  -public abstract class Expression implements java.io.Serializable
  +public abstract class Expression implements java.io.Serializable, ExpressionNode, XPathVisitable
   {
   
     /**
  @@ -93,7 +94,7 @@
      *  messages. May be null.
      *  @serial
      */
  -  protected SourceLocator m_slocator;
  +  private ExpressionNode m_parent;
   
     /**
      * Tell if this expression or it's subexpressions can traverse outside
  @@ -105,18 +106,18 @@
     {
       return false;
     }
  -
  -  /**
  -   * Set the location where this expression was built from.
  -   *
  -   *
  -   * @param locator the location where this expression was built from, may be
  -   *                null.
  -   */
  -  public void setSourceLocator(SourceLocator locator)
  -  {
  -    m_slocator = locator;
  -  }
  +  
  +//  /**
  +//   * Set the location where this expression was built from.
  +//   *
  +//   *
  +//   * @param locator the location where this expression was built from, may be
  +//   *                null.
  +//   */
  +//  public void setSourceLocator(SourceLocator locator)
  +//  {
  +//    m_slocator = locator;
  +//  }
   
     /**
      * Execute an expression in the XPath runtime context, and return the
  @@ -179,11 +180,32 @@
       throws javax.xml.transform.TransformerException;
   
     /**
  +   * Execute an expression in the XPath runtime context, and return the
  +   * result of the expression, but tell that a "safe" object doesn't have 
  +   * to be returned.  The default implementation just calls execute(xctxt).
  +   *
  +   *
  +   * @param xctxt The XPath runtime context.
  +   * @param destructiveOK true if a "safe" object doesn't need to be returned.
  +   *
  +   * @return The result of the expression in the form of a <code>XObject</code>.
  +   *
  +   * @throws javax.xml.transform.TransformerException if a runtime exception
  +   *         occurs.
  +   */
  +  public XObject execute(XPathContext xctxt, boolean destructiveOK)
  +    throws javax.xml.transform.TransformerException
  +  {
  +  	return execute(xctxt);
  +  }
  +
  +
  +  /**
      * Evaluate expression to a number.
      *
      *
  -   * NEEDSDOC @param xctxt
  -   * @return 0.0
  +   * @param xctxt The XPath runtime context.
  +   * @return The expression evaluated as a double.
      *
      * @throws javax.xml.transform.TransformerException
      */
  @@ -197,7 +219,7 @@
      * Evaluate expression to a boolean.
      *
      *
  -   * NEEDSDOC @param xctxt
  +   * @param xctxt The XPath runtime context.
      * @return false
      *
      * @throws javax.xml.transform.TransformerException
  @@ -212,7 +234,7 @@
      * Cast result object to a string.
      *
      *
  -   * NEEDSDOC @param xctxt
  +   * @param xctxt The XPath runtime context.
      * @return The string this wraps or the empty string if null
      *
      * @throws javax.xml.transform.TransformerException
  @@ -244,7 +266,8 @@
     public int asNode(XPathContext xctxt)
             throws javax.xml.transform.TransformerException
     {
  -    return execute(xctxt).iter().nextNode();
  +  	DTMIterator iter = execute(xctxt).iter();
  +    return iter.nextNode();
     }
   
     /**
  @@ -256,7 +279,7 @@
      * @param contextNode The node that "." expresses.
      *
      *
  -   * NEEDSDOC ($objectName$) @return
  +   * @return A valid DTMIterator.
      * @throws TransformerException thrown if the active ProblemListener decides
      * the error condition is severe enough to halt processing.
      *
  @@ -277,6 +300,39 @@
         xctxt.popCurrentNodeAndExpression();
       }
     }
  +  
  +  /**
  +   * <meta name="usage" content="experimental"/>
  +   * Given an select expression and a context, evaluate the XPath
  +   * and return the resulting iterator, but do not clone.
  +   *
  +   * @param xctxt The execution context.
  +   * @param contextNode The node that "." expresses.
  +   *
  +   *
  +   * @return A valid DTMIterator.
  +   * @throws TransformerException thrown if the active ProblemListener decides
  +   * the error condition is severe enough to halt processing.
  +   *
  +   * @throws javax.xml.transform.TransformerException
  +   */
  +  public DTMIterator asIteratorRaw(XPathContext xctxt, int contextNode)
  +          throws javax.xml.transform.TransformerException
  +  {
  +
  +    try
  +    {
  +      xctxt.pushCurrentNodeAndExpression(contextNode, contextNode);
  +
  +      XNodeSet nodeset = (XNodeSet)execute(xctxt);
  +      return nodeset.iterRaw();
  +    }
  +    finally
  +    {
  +      xctxt.popCurrentNodeAndExpression();
  +    }
  +  }
  +
   
     /**
      * Execute an expression in the XPath runtime context, and return the
  @@ -301,6 +357,7 @@
       XObject obj = execute(xctxt);
   
       obj.dispatchCharactersEvents(handler);
  +    obj.detach();
     }
   
     /**
  @@ -328,6 +385,34 @@
      * NEEDSDOC @param globalsSize
      */
     public abstract void fixupVariables(java.util.Vector vars, int globalsSize);
  +  
  +  /**
  +   * Compare this object with another object and see 
  +   * if they are equal, include the sub heararchy.
  +   * 
  +   * @param expr Another expression object.
  +   * @return true if this objects class and the expr
  +   * object's class are the same, and the data contained 
  +   * within both objects are considered equal.
  +   */
  +  public abstract boolean deepEquals(Expression expr);
  +  
  +  /**
  +   * This is a utility method to tell if the passed in 
  +   * class is the same class as this.  It is to be used by
  +   * the deepEquals method.  I'm bottlenecking it here 
  +   * because I'm not totally confident that comparing the 
  +   * class objects is the best way to do this.
  +   * @return true of the passed in class is the exact same 
  +   * class as this class.
  +   */
  +  protected final boolean isSameClass(Expression expr)
  +  {
  +  	if(null == expr)
  +  	  return false;
  +  	  
  +  	return (getClass() == expr.getClass());
  +  }
   
     /**
      * Warn the user of an problem.
  @@ -371,7 +456,6 @@
      * @throws javax.xml.transform.TransformerException
      */
     public void assertion(boolean b, java.lang.String msg)
  -          throws javax.xml.transform.TransformerException
     {
   
       if (!b)
  @@ -409,9 +493,141 @@
       if (null != xctxt)
       {
         ErrorListener eh = xctxt.getErrorListener();
  -      TransformerException te = new TransformerException(fmsg, m_slocator);
  +      TransformerException te = new TransformerException(fmsg, this);
   
         eh.fatalError(te);
       }
  +  }
  +  
  +  /**
  +   * Get the first non-Expression parent of this node.
  +   * @return null or first ancestor that is not an Expression.
  +   */
  +  public ExpressionNode getExpressionOwner()
  +  {
  +  	ExpressionNode parent = exprGetParent();
  +  	while((null != parent) && (parent instanceof Expression))
  +  		parent = parent.exprGetParent();
  +  	return parent;
  +  }
  +  
  +  //=============== ExpressionNode methods ================
  +  
  +  /** This pair of methods are used to inform the node of its
  +    parent. */
  +  public void exprSetParent(ExpressionNode n)
  +  {
  +  	assertion(n != this, "Can not parent an expression to itself!");
  +  	m_parent = n;
  +  }
  +  
  +  public ExpressionNode exprGetParent()
  +  {
  +  	return m_parent;
  +  }
  +
  +  /** This method tells the node to add its argument to the node's
  +    list of children.  */
  +  public void exprAddChild(ExpressionNode n, int i)
  +  {
  +  	assertion(false, "exprAddChild method not implemented!");
  +  }
  +
  +  /** This method returns a child node.  The children are numbered
  +     from zero, left to right. */
  +  public ExpressionNode exprGetChild(int i)
  +  {
  +  	return null;
  +  }
  +
  +  /** Return the number of children the node has. */
  +  public int exprGetNumChildren()
  +  {
  +  	return 0;
  +  }
  +  
  +  //=============== SourceLocator methods ================
  +
  +  /**
  +   * Return the public identifier for the current document event.
  +   *
  +   * <p>The return value is the public identifier of the document
  +   * entity or of the external parsed entity in which the markup that
  +   * triggered the event appears.</p>
  +   *
  +   * @return A string containing the public identifier, or
  +   *         null if none is available.
  +   * @see #getSystemId
  +   */
  +  public String getPublicId()
  +  {
  +  	if(null == m_parent)
  +  	  return null;
  +  	return m_parent.getPublicId();
  +  }
  +
  +  /**
  +   * Return the system identifier for the current document event.
  +   *
  +   * <p>The return value is the system identifier of the document
  +   * entity or of the external parsed entity in which the markup that
  +   * triggered the event appears.</p>
  +   *
  +   * <p>If the system identifier is a URL, the parser must resolve it
  +   * fully before passing it to the application.</p>
  +   *
  +   * @return A string containing the system identifier, or null
  +   *         if none is available.
  +   * @see #getPublicId
  +   */
  +  public String getSystemId()
  +  {
  +  	if(null == m_parent)
  +  	  return null;
  +  	return m_parent.getSystemId();
  +  }
  +
  +  /**
  +   * Return the line number where the current document event ends.
  +   *
  +   * <p><strong>Warning:</strong> The return value from the method
  +   * is intended only as an approximation for the sake of error
  +   * reporting; it is not intended to provide sufficient information
  +   * to edit the character content of the original XML document.</p>
  +   *
  +   * <p>The return value is an approximation of the line number
  +   * in the document entity or external parsed entity where the
  +   * markup that triggered the event appears.</p>
  +   *
  +   * @return The line number, or -1 if none is available.
  +   * @see #getColumnNumber
  +   */
  +  public int getLineNumber()
  +  {
  +  	if(null == m_parent)
  +  	  return 0;
  +  	return m_parent.getLineNumber();
  +  }
  +
  +  /**
  +   * Return the character position where the current document event ends.
  +   *
  +   * <p><strong>Warning:</strong> The return value from the method
  +   * is intended only as an approximation for the sake of error
  +   * reporting; it is not intended to provide sufficient information
  +   * to edit the character content of the original XML document.</p>
  +   *
  +   * <p>The return value is an approximation of the column number
  +   * in the document entity or external parsed entity where the
  +   * markup that triggered the event appears.</p>
  +   *
  +   * @return The column number, or -1 if none is available.
  +   * @see #getLineNumber
  +   */
  +  public int getColumnNumber()
  +  {
  +  	if(null == m_parent)
  +  	  return 0;
  +  	return m_parent.getColumnNumber();
     }
   }
  
  
  
  1.40      +59 -0     xml-xalan/java/src/org/apache/xpath/VariableStack.java
  
  Index: VariableStack.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/VariableStack.java,v
  retrieving revision 1.39
  retrieving revision 1.40
  diff -u -r1.39 -r1.40
  --- VariableStack.java	4 Mar 2002 18:21:32 -0000	1.39
  +++ VariableStack.java	22 Mar 2002 01:04:42 -0000	1.40
  @@ -345,6 +345,38 @@
   
       return val;
     }
  +  
  +  /**
  +   * Get a local variable or parameter in the current stack frame.
  +   *
  +   *
  +   * @param xctxt The XPath context, which must be passed in order to
  +   * lazy evaluate variables.
  +   *
  +   * @param index Local variable index relative to the current stack
  +   * frame bottom.
  +   *
  +   * @return The value of the variable.
  +   *
  +   * @throws TransformerException
  +   */
  +  public XObject getLocalVariable(XPathContext xctxt, int index, boolean destructiveOK)
  +          throws TransformerException
  +  {
  +
  +    index += _currentFrameBottom;
  +
  +    XObject val = _stackFrames[index];
  +    
  +    if(null == val)
  +      throw new TransformerException("Variable accessed before it is bound!", xctxt.getSAXLocator());
  +
  +    // Lazy execution of variables.
  +    if (val.getType() == XObject.CLASS_UNRESOLVEDVARIABLE)
  +      return (_stackFrames[index] = val.execute(xctxt));
  +
  +    return destructiveOK ? val : val.getFresh();
  +  }
   
     /**
      * Tell if a local variable has been set or not.
  @@ -420,6 +452,33 @@
         return (_stackFrames[index] = val.execute(xctxt));
   
       return val;
  +  }
  +  
  +  /**
  +   * Get a global variable or parameter from the global stack frame.
  +   *
  +   *
  +   * @param xctxt The XPath context, which must be passed in order to
  +   * lazy evaluate variables.
  +   *
  +   * @param index Global variable index relative to the global stack
  +   * frame bottom.
  +   *
  +   * @return The value of the variable.
  +   *
  +   * @throws TransformerException
  +   */
  +  public XObject getGlobalVariable(XPathContext xctxt, final int index, boolean destructiveOK)
  +          throws TransformerException
  +  {
  +
  +    XObject val = _stackFrames[index];
  +
  +    // Lazy execution of variables.
  +    if (val.getType() == XObject.CLASS_UNRESOLVEDVARIABLE)
  +      return (_stackFrames[index] = val.execute(xctxt));
  +
  +    return destructiveOK ? val : val.getFresh();
     }
   
     /**
  
  
  
  1.23      +47 -43    xml-xalan/java/src/org/apache/xpath/XPath.java
  
  Index: XPath.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/XPath.java,v
  retrieving revision 1.22
  retrieving revision 1.23
  diff -u -r1.22 -r1.23
  --- XPath.java	14 Sep 2001 16:54:56 -0000	1.22
  +++ XPath.java	22 Mar 2002 01:04:42 -0000	1.23
  @@ -56,48 +56,31 @@
    */
   package org.apache.xpath;
   
  -//import org.w3c.dom.Node;
  -//import org.w3c.dom.Document;
  -//import org.w3c.dom.traversal.NodeIterator;
  -//import org.w3c.dom.DocumentFragment;
  -
  -import org.apache.xml.dtm.DTM;
  -import org.apache.xml.dtm.DTMIterator;
  -
  -import java.util.Vector;
  -
   import java.io.Serializable;
  -import java.io.ObjectInputStream;
  -import java.io.IOException;
  +import java.util.Vector;
   
  +import javax.xml.transform.ErrorListener;
  +import javax.xml.transform.SourceLocator;
  +import javax.xml.transform.TransformerException;
  +import org.apache.xalan.res.XSLMessages;
  +import org.apache.xml.dtm.DTM;
   import org.apache.xml.utils.PrefixResolver;
  -import org.apache.xml.utils.QName;
  -import org.apache.xpath.res.XPATHErrorResources;
  -import org.apache.xpath.functions.Function;
  -
  -// import org.apache.xpath.functions.FuncLoader;
  +import org.apache.xml.utils.SAXSourceLocator;
  +import org.apache.xml.utils.WrappedRuntimeException;
   import org.apache.xpath.compiler.Compiler;
  +import org.apache.xpath.compiler.FunctionTable;
   import org.apache.xpath.compiler.XPathParser;
  -import org.apache.xpath.compiler.OpMap;  // temp
  -import org.apache.xpath.compiler.OpCodes;  // temp
  -import org.apache.xpath.compiler.PsuedoNames;  // temp
  -import org.apache.xpath.compiler.FunctionTable;  // temp
  +import org.apache.xpath.functions.Function;
   import org.apache.xpath.objects.XObject;
  -import org.apache.xalan.res.XSLMessages;
  -import org.apache.xpath.objects.*;
  -
  -import javax.xml.transform.TransformerException;
  -import javax.xml.transform.SourceLocator;
  -import javax.xml.transform.ErrorListener;
  -import org.apache.xml.utils.SAXSourceLocator;
  -import org.apache.xpath.patterns.NodeTest;
  +import org.apache.xpath.res.XPATHErrorResources;
  +import org.w3c.dom.Node;
   
   /**
    * <meta name="usage" content="advanced"/>
    * The XPath class wraps an expression object and provides general services 
    * for execution of that expression.
    */
  -public class XPath implements Serializable
  +public class XPath implements Serializable, ExpressionOwner
   {
   
     /** The top of the expression tree. 
  @@ -138,6 +121,8 @@
      */
     public void setExpression(Expression exp)
     {
  +  	if(null != m_mainExp)
  +    	exp.exprSetParent(m_mainExp.exprGetParent()); // a bit bogus
       m_mainExp = exp;
     }
   
  @@ -149,21 +134,21 @@
      */
     public SourceLocator getLocator()
     {
  -    return m_mainExp.m_slocator;
  +    return m_mainExp;
     }
   
  -  /**
  -   * Set the SourceLocator on the expression object.
  -   *
  -   *
  -   * @param l the SourceLocator on the expression object, which may be null.
  -   */
  -  public void setLocator(SourceLocator l)
  -  {
  -    // Note potential hazards -- l may not be serializable, or may be changed
  -      // after being assigned here.
  -    m_mainExp.setSourceLocator(l);
  -  }
  +//  /**
  +//   * Set the SourceLocator on the expression object.
  +//   *
  +//   *
  +//   * @param l the SourceLocator on the expression object, which may be null.
  +//   */
  +//  public void setLocator(SourceLocator l)
  +//  {
  +//    // Note potential hazards -- l may not be serializable, or may be changed
  +//      // after being assigned here.
  +//    m_mainExp.setSourceLocator(l);
  +//  }
   
     /** The pattern string, mainly kept around for diagnostic purposes.
      *  @serial  */
  @@ -225,6 +210,11 @@
   
       // System.out.println("expr: "+expr);
       this.setExpression(expr);
  +    
  +    if((null != locator) && locator instanceof ExpressionNode)
  +    {
  +    	expr.exprSetParent((ExpressionNode)locator);
  +    }
   
     }
     
  @@ -574,6 +564,20 @@
                            + "; line " + slocator.getLineNumber() + "; column "
                            + slocator.getColumnNumber());
       }
  +  }
  +  
  +  /**
  +   * This will traverse the heararchy, calling the visitor for 
  +   * each member.  If the called visitor method returns 
  +   * false, the subtree should not be called.
  +   * 
  +   * @param owner The owner of the visitor, where that path may be 
  +   *              rewritten if needed.
  +   * @param visitor The visitor whose appropriate method will be called.
  +   */
  +  public void callVisitors(ExpressionOwner owner, XPathVisitor visitor)
  +  {
  +  	m_mainExp.callVisitors(this, visitor);
     }
   
     /**
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xpath/ExpressionNode.java
  
  Index: ExpressionNode.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:  
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Xalan" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 1999, Lotus
   * Development Corporation., http://www.lotus.com.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.xpath;
  
  import javax.xml.transform.SourceLocator;
  
  /**
   * A class that implements this interface can construct expressions, 
   * give information about child and parent expressions,
   * and give the originating source information.  A class that implements 
   * this interface does not lay any claim to being directly executable.
   * 
   * <p>Note: This interface should not be considered stable.  Only exprSetParent 
   * and exprGetParent can be counted on to work reliably.  Work in progress.</p>
   */
  public interface ExpressionNode extends SourceLocator
  {
    /** This pair of methods are used to inform the node of its
      parent. */
    public void exprSetParent(ExpressionNode n);
    public ExpressionNode exprGetParent();
  
    /** This method tells the node to add its argument to the node's
      list of children.  */
    public void exprAddChild(ExpressionNode n, int i);
  
    /** This method returns a child node.  The children are numbered
       from zero, left to right. */
    public ExpressionNode exprGetChild(int i);
  
    /** Return the number of children the node has. */
    public int exprGetNumChildren();
  }
  
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xpath/ExpressionOwner.java
  
  Index: ExpressionOwner.java
  ===================================================================
  package org.apache.xpath;
  
  /**
   * Classes that implement this interface own an expression, which 
   * can be rewritten.
   */
  public interface ExpressionOwner
  {
    /**
     * Get the raw Expression object that this class wraps.
     *
     * @return the raw Expression object, which should not normally be null.
     */
    public Expression getExpression();
  
    /**
     * Set the raw expression object for this object.
     *
     * @param exp the raw Expression object, which should not normally be null.
     */
    public void setExpression(Expression exp);
  
  
  }
  
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xpath/XPathVisitable.java
  
  Index: XPathVisitable.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:  
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Xalan" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 1999, Lotus
   * Development Corporation., http://www.lotus.com.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.xpath;
  
  /**
   * A class that implements this interface will call a XPathVisitor 
   * for itself and members within it's heararchy.  If the XPathVisitor's 
   * method returns false, the sub-member heararchy will not be 
   * traversed.
   */
  public interface XPathVisitable
  {
  	/**
  	 * This will traverse the heararchy, calling the visitor for 
  	 * each member.  If the called visitor method returns 
  	 * false, the subtree should not be called.
  	 * 
  	 * @param owner The owner of the visitor, where that path may be 
  	 *              rewritten if needed.
  	 * @param visitor The visitor whose appropriate method will be called.
  	 */
  	public void callVisitors(ExpressionOwner owner, XPathVisitor visitor);
  }
  
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xpath/XPathVisitor.java
  
  Index: XPathVisitor.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:  
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Xalan" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 1999, Lotus
   * Development Corporation., http://www.lotus.com.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.xpath;
  
  import org.apache.xpath.patterns.NodeTest;
  import org.apache.xpath.axes.LocPathIterator;
  import org.apache.xpath.axes.UnionPathIterator;
  import org.apache.xpath.functions.Function;
  import org.apache.xpath.objects.XNumber;
  import org.apache.xpath.objects.XString;
  import org.apache.xpath.operations.Operation;
  import org.apache.xpath.operations.UnaryOperation;
  import org.apache.xpath.operations.Variable;
  import org.apache.xpath.patterns.StepPattern;
  import org.apache.xpath.patterns.UnionPattern;
  
  /**
   * A derivation from this class can be passed to a class that implements 
   * the XPathVisitable interface, to have the appropriate method called 
   * for each component of the XPath.  Aside from possible other uses, the 
   * main intention is to provide a reasonable means to perform expression 
   * rewriting.
   * 
   * <p>Each method has the form 
   * <code>boolean visitComponentType(ExpressionOwner owner, ComponentType compType)</code>. 
   * The ExpressionOwner argument is the owner of the component, and can 
   * be used to reset the expression for rewriting.  If a method returns 
   * false, the sub hierarchy will not be traversed.</p>
   * 
   * <p>This class is meant to be a base class that will be derived by concrete classes, 
   * and doesn't much except return true for each method.</p>
   */
  public class XPathVisitor
  {
  	/**
  	 * Visit a LocationPath.
  	 * @param owner The owner of the expression, to which the expression can 
  	 *              be reset if rewriting takes place.
  	 * @param path The LocationPath object.
  	 * @return true if the sub expressions should be traversed.
  	 */
  	public boolean visitLocationPath(ExpressionOwner owner, LocPathIterator path)
  	{
  		return true;
  	}
  
  	/**
  	 * Visit a UnionPath.
  	 * @param owner The owner of the expression, to which the expression can 
  	 *              be reset if rewriting takes place.
  	 * @param path The UnionPath object.
  	 * @return true if the sub expressions should be traversed.
  	 */
  	public boolean visitUnionPath(ExpressionOwner owner, UnionPathIterator path)
  	{
  		return true;
  	}
  	
  	/**
  	 * Visit a step within a location path.
  	 * @param owner The owner of the expression, to which the expression can 
  	 *              be reset if rewriting takes place.
  	 * @param step The Step object.
  	 * @return true if the sub expressions should be traversed.
  	 */
  	public boolean visitStep(ExpressionOwner owner, NodeTest step)
  	{
  		return true;
  	}
  		
  	/**
  	 * Visit a predicate within a location path.  Note that there isn't a 
  	 * proper unique component for predicates, and that the expression will 
  	 * be called also for whatever type Expression is.
  	 * 
  	 * @param owner The owner of the expression, to which the expression can 
  	 *              be reset if rewriting takes place.
  	 * @param pred The predicate object.
  	 * @return true if the sub expressions should be traversed.
  	 */
  	public boolean visitPredicate(ExpressionOwner owner, Expression pred)
  	{
  		return true;
  	}
  
  	/**
  	 * Visit a binary operation.
  	 * @param owner The owner of the expression, to which the expression can 
  	 *              be reset if rewriting takes place.
  	 * @param op The operation object.
  	 * @return true if the sub expressions should be traversed.
  	 */
  	public boolean visitBinaryOperation(ExpressionOwner owner, Operation op)
  	{
  		return true;
  	}
  
  	/**
  	 * Visit a unary operation.
  	 * @param owner The owner of the expression, to which the expression can 
  	 *              be reset if rewriting takes place.
  	 * @param op The operation object.
  	 * @return true if the sub expressions should be traversed.
  	 */
  	public boolean visitUnaryOperation(ExpressionOwner owner, UnaryOperation op)
  	{
  		return true;
  	}
  	
  	/**
  	 * Visit a variable reference.
  	 * @param owner The owner of the expression, to which the expression can 
  	 *              be reset if rewriting takes place.
  	 * @param var The variable reference object.
  	 * @return true if the sub expressions should be traversed.
  	 */
  	public boolean visitVariableRef(ExpressionOwner owner, Variable var)
  	{
  		return true;
  	}
  
  	/**
  	 * Visit a function.
  	 * @param owner The owner of the expression, to which the expression can 
  	 *              be reset if rewriting takes place.
  	 * @param func The function reference object.
  	 * @return true if the sub expressions should be traversed.
  	 */
  	public boolean visitFunction(ExpressionOwner owner, Function func)
  	{
  		return true;
  	}
  	
  	/**
  	 * Visit a match pattern.
  	 * @param owner The owner of the expression, to which the expression can 
  	 *              be reset if rewriting takes place.
  	 * @param pattern The match pattern object.
  	 * @return true if the sub expressions should be traversed.
  	 */
  	public boolean visitMatchPattern(ExpressionOwner owner, StepPattern pattern)
  	{
  		return true;
  	}
  	
  	/**
  	 * Visit a union pattern.
  	 * @param owner The owner of the expression, to which the expression can 
  	 *              be reset if rewriting takes place.
  	 * @param pattern The union pattern object.
  	 * @return true if the sub expressions should be traversed.
  	 */
  	public boolean visitUnionPattern(ExpressionOwner owner, UnionPattern pattern)
  	{
  		return true;
  	}
  	
  	/**
  	 * Visit a string literal.
  	 * @param owner The owner of the expression, to which the expression can 
  	 *              be reset if rewriting takes place.
  	 * @param str The string literal object.
  	 * @return true if the sub expressions should be traversed.
  	 */
  	public boolean visitStringLiteral(ExpressionOwner owner, XString str)
  	{
  		return true;
  	}
  
  
  	/**
  	 * Visit a number literal.
  	 * @param owner The owner of the expression, to which the expression can 
  	 *              be reset if rewriting takes place.
  	 * @param num The number literal object.
  	 * @return true if the sub expressions should be traversed.
  	 */
  	public boolean visitNumberLiteral(ExpressionOwner owner, XNumber num)
  	{
  		return true;
  	}
  
  
  }
  
  
  
  
  1.10      +1 -1      xml-xalan/java/src/org/apache/xpath/axes/AttributeIterator.java
  
  Index: AttributeIterator.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/axes/AttributeIterator.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- AttributeIterator.java	7 Aug 2001 19:16:43 -0000	1.9
  +++ AttributeIterator.java	22 Mar 2002 01:04:42 -0000	1.10
  @@ -90,7 +90,7 @@
     {
       super(compiler, opPos, analysis);
     }
  -  
  +    
     /**
      * Get the next node via getFirstAttribute && getNextAttribute.
      */
  
  
  
  1.23      +88 -22    xml-xalan/java/src/org/apache/xpath/axes/AxesWalker.java
  
  Index: AxesWalker.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/axes/AxesWalker.java,v
  retrieving revision 1.22
  retrieving revision 1.23
  diff -u -r1.22 -r1.23
  --- AxesWalker.java	8 Aug 2001 03:55:51 -0000	1.22
  +++ AxesWalker.java	22 Mar 2002 01:04:42 -0000	1.23
  @@ -56,36 +56,25 @@
    */
   package org.apache.xpath.axes;
   
  -import java.util.Stack;
   import java.util.Vector;
   
  -// Xalan imports
  -import org.apache.xpath.axes.LocPathIterator;
  -import org.apache.xml.utils.PrefixResolver;
  -import org.apache.xpath.axes.SubContextList;
  -import org.apache.xpath.compiler.Compiler;
  -import org.apache.xpath.compiler.OpCodes;
  -import org.apache.xpath.Expression;
  -import org.apache.xpath.objects.XObject;
  -import org.apache.xpath.patterns.NodeTestFilter;
  -import org.apache.xpath.patterns.NodeTest;
  -import org.apache.xpath.XPathContext;
  -import org.apache.xpath.XPath;
  -
  +import javax.xml.transform.TransformerException;
   import org.apache.xml.dtm.DTM;
  -import org.apache.xml.dtm.DTMIterator;
  -import org.apache.xml.dtm.DTMFilter;
   import org.apache.xml.dtm.DTMAxisTraverser;
  -import org.apache.xml.dtm.Axis;
  -
  -import org.apache.xml.utils.XMLString;
  +import org.apache.xml.dtm.DTMIterator;
  +import org.apache.xpath.Expression;
  +import org.apache.xpath.ExpressionOwner;
  +import org.apache.xpath.XPathContext;
  +import org.apache.xpath.XPathVisitor;
  +import org.apache.xpath.compiler.Compiler;
  +import org.apache.xpath.patterns.NodeTest;
   
   /**
    * Serves as common interface for axes Walkers, and stores common
    * state variables.
    */
   public class AxesWalker extends PredicatedNodeTest
  -        implements Cloneable
  +        implements Cloneable, PathComponent, ExpressionOwner
   {
     
     /**
  @@ -215,6 +204,19 @@
       return null;    
     }
     
  +  /**
  +   * Detaches the walker from the set which it iterated over, releasing
  +   * any computational resources and placing the iterator in the INVALID
  +   * state.
  +   */
  +  public void detach()
  +  { 
  +  	m_currentNode = DTM.NULL;
  +  	m_dtm = null;
  +  	m_isFresh = true;
  +  	m_root = DTM.NULL;
  +  }
  +  
     //=============== TreeWalker Implementation ===============
   
     /**
  @@ -227,6 +229,17 @@
     {
       return m_root;
     }
  +  
  +  /** 
  +   * Get the analysis bits for this walker, as defined in the WalkerFactory.
  +   * @return One of WalkerFactory#BIT_DESCENDANT, etc.
  +   */
  +  public int getAnalysisBits()
  +  {
  +  	int axis = getAxis();
  +  	int bit = WalkerFactory.getAnalysisBitFromAxes(axis);
  +  	return bit;
  +  }
   
     /**
      * Set the root node of the TreeWalker.
  @@ -237,7 +250,8 @@
     public void setRoot(int root)
     {
       // %OPT% Get this directly from the lpi.
  -    m_dtm = wi().getXPathContext().getDTM(root);
  +    XPathContext xctxt = wi().getXPathContext();
  +    m_dtm = xctxt.getDTM(root);
       m_traverser = m_dtm.getAxisTraverser(m_axis);
       m_isFresh = true;
       m_foundLast = false;
  @@ -527,7 +541,59 @@
     {
       return m_axis;
     }
  +  
  +  /**
  +   * This will traverse the heararchy, calling the visitor for 
  +   * each member.  If the called visitor method returns 
  +   * false, the subtree should not be called.
  +   * 
  +   * @param owner The owner of the visitor, where that path may be 
  +   *              rewritten if needed.
  +   * @param visitor The visitor whose appropriate method will be called.
  +   */
  +  public void callVisitors(ExpressionOwner owner, XPathVisitor visitor)
  +  {
  +  	if(visitor.visitStep(owner, this))
  +  	{
  +  		callPredicateVisitors(visitor);
  +  		if(null != m_nextWalker)
  +  		{
  +  			m_nextWalker.callVisitors(this, visitor);
  +  		}
  +  	}
  +  }
  +  
  +  /**
  +   * @see ExpressionOwner#getExpression()
  +   */
  +  public Expression getExpression()
  +  {
  +    return m_nextWalker;
  +  }
   
  +  /**
  +   * @see ExpressionOwner#setExpression(Expression)
  +   */
  +  public void setExpression(Expression exp)
  +  {
  +  	exp.exprSetParent(this);
  +  	m_nextWalker = (AxesWalker)exp;
  +  }
  +  
  +    /**
  +     * @see Expression#deepEquals(Expression)
  +     */
  +    public boolean deepEquals(Expression expr)
  +    {
  +      if (!super.deepEquals(expr))
  +                return false;
  +
  +      AxesWalker walker = (AxesWalker)expr;
  +      if(this.m_axis != walker.m_axis)
  +      	return false;
  +
  +      return true;
  +    }
   
     /**
      *  The root node of the TreeWalker, as specified when it was created.
  @@ -554,5 +620,5 @@
     protected int m_axis = -1;
   
     /** The DTM inner traversal class, that corresponds to the super axis. */
  -  protected DTMAxisTraverser m_traverser;   
  +  protected DTMAxisTraverser m_traverser; 
   }
  
  
  
  1.10      +3 -26     xml-xalan/java/src/org/apache/xpath/axes/ChildIterator.java
  
  Index: ChildIterator.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/axes/ChildIterator.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- ChildIterator.java	21 Aug 2001 03:06:45 -0000	1.9
  +++ ChildIterator.java	22 Mar 2002 01:04:42 -0000	1.10
  @@ -122,27 +122,8 @@
      */
     public int nextNode()
     {
  -
  -    // If the cache is on, and the node has already been found, then 
  -    // just return from the list.
  -    // If the cache is on, and the node has already been found, then 
  -    // just return from the list.
  -    if ((null != m_cachedNodes)
  -            && (m_next < m_cachedNodes.size()))
  -    {
  -      int next = m_cachedNodes.elementAt(m_next);
  -    
  -      incrementNextPosition();
  -      m_currentContextNode = next;
  -
  -      return next;
  -    }
  -
  -    if (m_foundLast)
  -    {
  -      m_lastFetched = DTM.NULL;
  -      return DTM.NULL;
  -    }
  +  	if(m_foundLast)
  +  		return DTM.NULL;
   
       int next;
   
  @@ -153,11 +134,7 @@
       // m_lastFetched = next;
       if (DTM.NULL != next)
       {
  -      if (null != m_cachedNodes)
  -        m_cachedNodes.addElement(m_lastFetched);
  -
  -      m_next++;
  -
  +      m_pos++;
         return next;
       }
       else
  
  
  
  1.14      +16 -137   xml-xalan/java/src/org/apache/xpath/axes/ChildTestIterator.java
  
  Index: ChildTestIterator.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/axes/ChildTestIterator.java,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- ChildTestIterator.java	21 Aug 2001 03:06:45 -0000	1.13
  +++ ChildTestIterator.java	22 Mar 2002 01:04:42 -0000	1.14
  @@ -74,7 +74,7 @@
    * children patterns that have a node test, and possibly a predicate.
    * @see org.apache.xpath.axes.WalkerFactory#newLocPathIterator
    */
  -public class ChildTestIterator extends LocPathIterator
  +public class ChildTestIterator extends BasicTestIterator
   {
     /** The traverser to use to navigate over the descendants. */
     transient protected DTMAxisTraverser m_traverser;
  @@ -95,37 +95,17 @@
     ChildTestIterator(Compiler compiler, int opPos, int analysis)
             throws javax.xml.transform.TransformerException
     {
  -
  -    super(compiler, opPos, analysis, false);
  -
  -    int firstStepPos = compiler.getFirstChildPos(opPos);
  -    int whatToShow = compiler.getWhatToShow(firstStepPos);
  -
  -    if ((0 == (whatToShow
  -               & (DTMFilter.SHOW_ATTRIBUTE 
  -               | DTMFilter.SHOW_NAMESPACE 
  -               | DTMFilter.SHOW_ELEMENT
  -               | DTMFilter.SHOW_PROCESSING_INSTRUCTION))) 
  -               || (whatToShow == DTMFilter.SHOW_ALL))
  -      initNodeTest(whatToShow);
  -    else
  -    {
  -      initNodeTest(whatToShow, compiler.getStepNS(firstStepPos),
  -                              compiler.getStepLocalName(firstStepPos));
  -    }
  -    initPredicateInfo(compiler, firstStepPos);
  +    super(compiler, opPos, analysis);
     }
     
     /**
      * Create a ChildTestIterator object.
      *
  -   * @param compiler A reference to the Compiler that contains the op map.
  -   * @param opPos The position within the op map, which contains the
  -   * location path expression for this itterator.
  +   * @param traverser Traverser that tells how the KeyIterator is to be handled.
      *
      * @throws javax.xml.transform.TransformerException
      */
  -  ChildTestIterator(DTMAxisTraverser traverser)
  +  public ChildTestIterator(DTMAxisTraverser traverser)
     {
   
       super(null);
  @@ -133,25 +113,6 @@
       m_traverser = traverser;
     }
   
  -  
  -  /**
  -   *  Get a cloned Iterator that is reset to the beginning
  -   *  of the query.
  -   * 
  -   *  @return A cloned NodeIterator set of the start of the query.
  -   * 
  -   *  @throws CloneNotSupportedException
  -   */
  -  public DTMIterator cloneWithReset() throws CloneNotSupportedException
  -  {
  -
  -    ChildTestIterator clone = (ChildTestIterator) super.cloneWithReset();
  -
  -    clone.resetProximityPositions();
  -
  -    return clone;
  -  }
  -  
     /**
      * Get the next node via getNextXXX.  Bottlenecked for derived class override.
      * @return The next node on the axis, or DTM.NULL.
  @@ -175,107 +136,25 @@
       return m_lastFetched;
     }
   
  +  
     /**
  -   *  Returns the next node in the set and advances the position of the
  -   * iterator in the set. After a NodeIterator is created, the first call
  -   * to nextNode() returns the first node in the set.
  -   *
  -   * @return  The next <code>Node</code> in the set being iterated over, or
  -   *   <code>null</code> if there are no more members in that set.
  +   *  Get a cloned Iterator that is reset to the beginning
  +   *  of the query.
  +   * 
  +   *  @return A cloned NodeIterator set of the start of the query.
  +   * 
  +   *  @throws CloneNotSupportedException
      */
  -  public int nextNode()
  +  public DTMIterator cloneWithReset() throws CloneNotSupportedException
     {
   
  -    // If the cache is on, and the node has already been found, then 
  -    // just return from the list.
  -    // If the cache is on, and the node has already been found, then 
  -    // just return from the list.
  -    if ((null != m_cachedNodes)
  -            && (m_next < m_cachedNodes.size()))
  -    {
  -      int next = m_cachedNodes.elementAt(m_next);
  -    
  -      incrementNextPosition();
  -      m_currentContextNode = next;
  -
  -      return next;
  -    }
  -
  -    if (m_foundLast)
  -    {
  -      m_lastFetched = DTM.NULL;
  -      return DTM.NULL;
  -    }
  -      
  -    if(DTM.NULL == m_lastFetched)
  -    {
  -      resetProximityPositions();
  -    }
  -
  -    int next;
  -    
  -    org.apache.xpath.VariableStack vars;
  -    int savedStart;
  -    if (-1 != m_stackFrame)
  -    {
  -      vars = m_execContext.getVarStack();
  -
  -      // These three statements need to be combined into one operation.
  -      savedStart = vars.getStackFrame();
  +    ChildTestIterator clone = (ChildTestIterator) super.cloneWithReset();
  +    clone.m_traverser = m_traverser;
   
  -      vars.setStackFrame(m_stackFrame);
  -    }
  -    else
  -    {
  -      // Yuck.  Just to shut up the compiler!
  -      vars = null;
  -      savedStart = 0;
  -    }
  -    
  -    try
  -    {
  -      do
  -      {
  -        next = getNextNode();
  -  
  -        if (DTM.NULL != next)
  -        {
  -          if(DTMIterator.FILTER_ACCEPT == acceptNode(next))
  -            break;
  -          else
  -            continue;
  -        }
  -        else
  -          break;
  -      }
  -      while (next != DTM.NULL);
  -  
  -      if (DTM.NULL != next)
  -      {
  -        if (null != m_cachedNodes)
  -          m_cachedNodes.addElement(m_lastFetched);
  -  
  -        m_next++;
  -  
  -        return next;
  -      }
  -      else
  -      {
  -        m_foundLast = true;
  -  
  -        return DTM.NULL;
  -      }
  -    }
  -    finally
  -    {
  -      if (-1 != m_stackFrame)
  -      {
  -        // These two statements need to be combined into one operation.
  -        vars.setStackFrame(savedStart);
  -      }
  -    }
  +    return clone;
     }
     
  +
     /**
      * Initialize the context values for this expression
      * after it is cloned.
  
  
  
  1.15      +29 -36    xml-xalan/java/src/org/apache/xpath/axes/DescendantIterator.java
  
  Index: DescendantIterator.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/axes/DescendantIterator.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- DescendantIterator.java	21 Aug 2001 03:06:45 -0000	1.14
  +++ DescendantIterator.java	22 Mar 2002 01:04:42 -0000	1.15
  @@ -57,18 +57,17 @@
   package org.apache.xpath.axes;
   
   import javax.xml.transform.TransformerException;
  -
  -import org.apache.xpath.compiler.Compiler;
  -import org.apache.xpath.patterns.NodeTest;
  -import org.apache.xpath.objects.XObject;
  -import org.apache.xpath.compiler.OpCodes;
  -import org.apache.xpath.XPathContext;
  -
  +import org.apache.xml.dtm.Axis;
   import org.apache.xml.dtm.DTM;
  -import org.apache.xml.dtm.DTMIterator;
  -import org.apache.xml.dtm.DTMFilter;
   import org.apache.xml.dtm.DTMAxisTraverser;
  -import org.apache.xml.dtm.Axis;
  +import org.apache.xml.dtm.DTMFilter;
  +import org.apache.xml.dtm.DTMIterator;
  +import org.apache.xpath.Expression;
  +import org.apache.xpath.VariableStack;
  +import org.apache.xpath.XPathContext;
  +import org.apache.xpath.compiler.Compiler;
  +import org.apache.xpath.compiler.OpCodes;
  +import org.apache.xpath.patterns.NodeTest;
   
   /**
    * <meta name="usage" content="advanced"/>
  @@ -193,6 +192,7 @@
     {
   
       DescendantIterator clone = (DescendantIterator) super.cloneWithReset();
  +    clone.m_traverser = m_traverser;
   
       clone.resetProximityPositions();
   
  @@ -213,27 +213,9 @@
      */
     public int nextNode()
     {
  -    // If the cache is on, and the node has already been found, then 
  -    // just return from the list.
  -    // If the cache is on, and the node has already been found, then 
  -    // just return from the list.
  -    if ((null != m_cachedNodes)
  -            && (m_next < m_cachedNodes.size()))
  -    {
  -      int next = m_cachedNodes.elementAt(m_next);
  -    
  -      incrementNextPosition();
  -      m_currentContextNode = next;
  -
  -      return next;
  -    }
  +   	if(m_foundLast)
  +  		return DTM.NULL;
   
  -    if (m_foundLast)
  -    {
  -      m_lastFetched = DTM.NULL;
  -      return DTM.NULL;
  -    }
  -      
       if(DTM.NULL == m_lastFetched)
       {
         resetProximityPositions();
  @@ -291,11 +273,7 @@
     
         if (DTM.NULL != next)
         {
  -        if (null != m_cachedNodes)
  -          m_cachedNodes.addElement(m_lastFetched);
  -  
  -        m_next++;
  -  
  +      	m_pos++;
           return next;
         }
         else
  @@ -413,7 +391,7 @@
     {
       return m_axis;
     }
  -
  +  
     
     /** The traverser to use to navigate over the descendants. */
     transient protected DTMAxisTraverser m_traverser;
  @@ -423,5 +401,20 @@
     
     /** The extended type ID, not set until setRoot. */
     protected int m_extendedTypeID;
  +  
  +  /**
  +   * @see Expression#deepEquals(Expression)
  +   */
  +  public boolean deepEquals(Expression expr)
  +  {
  +  	if(!super.deepEquals(expr))
  +  		return false;
  +  		
  +  	if(m_axis != ((DescendantIterator)expr).m_axis)
  +  		return false;
  +  		
  +  	return true;
  +  }
  +
     
   }
  
  
  
  1.20      +151 -68   xml-xalan/java/src/org/apache/xpath/axes/FilterExprWalker.java
  
  Index: FilterExprWalker.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/axes/FilterExprWalker.java,v
  retrieving revision 1.19
  retrieving revision 1.20
  diff -u -r1.19 -r1.20
  --- FilterExprWalker.java	7 Aug 2001 19:16:43 -0000	1.19
  +++ FilterExprWalker.java	22 Mar 2002 01:04:42 -0000	1.20
  @@ -56,23 +56,22 @@
    */
   package org.apache.xpath.axes;
   
  -import org.apache.xpath.axes.LocPathIterator;
  -import org.apache.xpath.XPath;
  -import org.apache.xpath.Expression;
  -import org.apache.xpath.XPathContext;
  -import org.apache.xpath.VariableStack;
  -import org.apache.xpath.objects.XObject;
  -import org.apache.xml.utils.PrefixResolver;
  -import org.apache.xpath.compiler.Compiler;
  -import org.apache.xpath.compiler.OpCodes;
  -import org.apache.xpath.patterns.NodeTestFilter;
  -
   import java.util.Vector;
   
  +import javax.xml.transform.TransformerException;
  +import org.apache.xalan.templates.FuncKey;
  +import org.apache.xml.dtm.Axis;
   import org.apache.xml.dtm.DTM;
   import org.apache.xml.dtm.DTMIterator;
  -import org.apache.xml.dtm.DTMFilter;
  -import org.apache.xml.dtm.Axis;
  +import org.apache.xml.utils.PrefixResolver;
  +import org.apache.xpath.Expression;
  +import org.apache.xpath.ExpressionOwner;
  +import org.apache.xpath.VariableStack;
  +import org.apache.xpath.XPathContext;
  +import org.apache.xpath.XPathVisitor;
  +import org.apache.xpath.compiler.Compiler;
  +import org.apache.xpath.compiler.OpCodes;
  +import org.apache.xpath.objects.XNodeSet;
   
   /**
    * Walker for the OP_VARIABLE, or OP_EXTFUNCTION, or OP_FUNCTION, or OP_GROUP,
  @@ -87,7 +86,7 @@
      *
      * @param locPathIterator non-null reference to the parent iterator.
      */
  -  FilterExprWalker(WalkingIterator locPathIterator)
  +  public FilterExprWalker(WalkingIterator locPathIterator)
     {
       super(locPathIterator, Axis.FILTEREDLIST);
     }
  @@ -110,15 +109,49 @@
       // Smooth over an anomily in the opcode map...
       switch (stepType)
       {
  -    case OpCodes.OP_VARIABLE :
  -    case OpCodes.OP_EXTFUNCTION :
       case OpCodes.OP_FUNCTION :
  +    case OpCodes.OP_EXTFUNCTION :
  +    	m_mustHardReset = true;
       case OpCodes.OP_GROUP :
  +    case OpCodes.OP_VARIABLE :
         m_expr = compiler.compile(opPos);
  +      m_expr.exprSetParent(this);
  +      if((OpCodes.OP_FUNCTION == stepType) && (m_expr instanceof org.apache.xalan.templates.FuncKey))
  +      {
  +      	// hack/temp workaround
  +      	m_canDetachNodeset = false;
  +      }
         break;
       default :
         m_expr = compiler.compile(opPos + 2);
  +      m_expr.exprSetParent(this);
       }
  +//    if(m_expr instanceof WalkingIterator)
  +//    {
  +//      WalkingIterator wi = (WalkingIterator)m_expr;
  +//      if(wi.getFirstWalker() instanceof FilterExprWalker)
  +//      {
  +//      	FilterExprWalker fw = (FilterExprWalker)wi.getFirstWalker();
  +//      	if(null == fw.getNextWalker())
  +//      	{
  +//      		m_expr = fw.m_expr;
  +//      		m_expr.exprSetParent(this);
  +//      	}
  +//      }
  +//      		
  +//    }
  +  }
  +  
  +  /**
  +   * Detaches the walker from the set which it iterated over, releasing
  +   * any computational resources and placing the iterator in the INVALID
  +   * state.
  +   */
  +  public void detach()
  +  {  
  +  	super.detach();
  +  	m_exprObj.detach();
  +  	m_exprObj = null;
     }
   
     /**
  @@ -130,51 +163,12 @@
     public void setRoot(int root)
     {
   
  -    // System.out.println("root: "+root);
  -    XPathContext xctxt = m_lpi.getXPathContext();
  -    PrefixResolver savedResolver = xctxt.getNamespaceContext();
  -
  -    try
  -    {
  -      xctxt.pushCurrentNode(root);
  -      xctxt.setNamespaceContext(m_lpi.getPrefixResolver());
  -      
  -      // The setRoot operation can take place with a reset operation, 
  -      // and so we may not be in the context of LocPathIterator#nextNode, 
  -      // so we have to set up the variable context, execute the expression, 
  -      // and then restore the variable context.
  +    super.setRoot(root);
   
  -      if(m_lpi.getIsTopLevel())
  -      {
  -        // System.out.println("calling m_expr.execute(m_lpi.getXPathContext())");
  -        VariableStack vars = m_lpi.m_execContext.getVarStack();
  -        
  -        // These three statements need to be combined into one operation.
  -        int savedStart = vars.getStackFrame();
  -        vars.setStackFrame(m_lpi.m_stackFrame);
  -        
  -        m_nodeSet = m_expr.asIterator(xctxt, root);
  -        
  -        // These two statements need to be combined into one operation.
  -        vars.setStackFrame(savedStart);
  -      }
  -      else
  -        m_nodeSet = m_expr.asIterator(xctxt, root);
  -            
  -    }
  -    catch (javax.xml.transform.TransformerException se)
  -    {
  +  	m_exprObj = FilterExprIteratorSimple.executeFilterExpr(root, 
  +  	                  m_lpi.getXPathContext(), m_lpi.getPrefixResolver(), 
  +  	                  m_lpi.getIsTopLevel(), m_lpi.m_stackFrame, m_expr);
   
  -      // TODO: Fix...
  -      throw new org.apache.xml.utils.WrappedRuntimeException(se);
  -    }
  -    finally
  -    {
  -      xctxt.popCurrentNode();
  -      xctxt.setNamespaceContext(savedResolver);
  -    }
  -
  -    super.setRoot(root);
     }
   
     /**
  @@ -190,12 +184,12 @@
       FilterExprWalker clone = (FilterExprWalker) super.clone();
   
       // clone.m_expr = (Expression)((Expression)m_expr).clone();
  -    if (null != m_nodeSet)
  -      clone.m_nodeSet = (DTMIterator) m_nodeSet.clone();
  +    if (null != m_exprObj)
  +      clone.m_exprObj = (XNodeSet) m_exprObj.clone();
   
       return clone;
     }
  -
  +  
     /**
      * This method needs to override AxesWalker.acceptNode because FilterExprWalkers
      * don't need to, and shouldn't, do a node test.
  @@ -236,8 +230,11 @@
     public int getNextNode()
     {
   
  -    if (null != m_nodeSet)
  -       return m_nodeSet.nextNode();
  +    if (null != m_exprObj)
  +    {
  +       int next = m_exprObj.nextNode();
  +       return next;
  +    }
       else
         return DTM.NULL;
     }
  @@ -252,7 +249,7 @@
      */
     public int getLastPos(XPathContext xctxt)
     {
  -    return m_nodeSet.getLength();
  +    return m_exprObj.getLength();
     }
     
     /** The contained expression. Should be non-null.
  @@ -260,7 +257,10 @@
     private Expression m_expr;
   
     /** The result of executing m_expr.  Needs to be deep cloned on clone op.  */
  -  transient private DTMIterator m_nodeSet;
  +  transient private XNodeSet m_exprObj;
  +  
  +  private boolean m_mustHardReset = false;
  +  private boolean m_canDetachNodeset = true;
   
     /**
      * This function is used to fixup variables from QNames to stack frame 
  @@ -279,6 +279,37 @@
     }
     
     /**
  +   * Get the inner contained expression of this filter.
  +   */
  +  public Expression getInnerExpression()
  +  {
  +  	return m_expr;
  +  }
  +  
  +  /**
  +   * Set the inner contained expression of this filter.
  +   */
  +  public void setInnerExpression(Expression expr)
  +  {
  +  	expr.exprSetParent(this);
  +  	m_expr = expr;
  +  }
  +
  +  
  +  /** 
  +   * Get the analysis bits for this walker, as defined in the WalkerFactory.
  +   * @return One of WalkerFactory#BIT_DESCENDANT, etc.
  +   */
  +  public int getAnalysisBits()
  +  {
  +      if (null != m_expr && m_expr instanceof PathComponent)
  +      {
  +        return ((PathComponent) m_expr).getAnalysisBits();
  +      }
  +      return WalkerFactory.BIT_FILTER;
  +  }
  +  
  +  /**
      * Returns true if all the nodes in the iteration well be returned in document 
      * order.
      * Warning: This can only be called after setRoot has been called!
  @@ -287,7 +318,7 @@
      */
     public boolean isDocOrdered()
     {
  -    return m_nodeSet.isDocOrdered();
  +    return m_exprObj.isDocOrdered();
     }
     
     /**
  @@ -298,9 +329,61 @@
      */
     public int getAxis()
     {
  -    return m_nodeSet.getAxis();
  +    return m_exprObj.getAxis();
     }
  +  
  +  class filterExprOwner implements ExpressionOwner
  +  {
  +      /**
  +     * @see ExpressionOwner#getExpression()
  +     */
  +    public Expression getExpression()
  +    {
  +      return m_expr;
  +    }
  +
  +    /**
  +     * @see ExpressionOwner#setExpression(Expression)
  +     */
  +    public void setExpression(Expression exp)
  +    {
  +    	exp.exprSetParent(FilterExprWalker.this);
  +    	m_expr = exp;
  +    }
  +  }
  +  
  +	/**
  +	 * This will traverse the heararchy, calling the visitor for 
  +	 * each member.  If the called visitor method returns 
  +	 * false, the subtree should not be called.
  +	 * 
  +	 * @param owner The owner of the visitor, where that path may be 
  +	 *              rewritten if needed.
  +	 * @param visitor The visitor whose appropriate method will be called.
  +	 */
  +	public void callPredicateVisitors(XPathVisitor visitor)
  +	{
  +	  m_expr.callVisitors(new filterExprOwner(), visitor);
  +	  
  +	  super.callPredicateVisitors(visitor);
  +	} 
  +
  +
  +    /**
  +     * @see Expression#deepEquals(Expression)
  +     */
  +    public boolean deepEquals(Expression expr)
  +    {
  +      if (!super.deepEquals(expr))
  +                return false;
   
  +      FilterExprWalker walker = (FilterExprWalker)expr;
  +      if(!m_expr.deepEquals(walker.m_expr))
  +      	return false;
  +
  +      return true;
  +    }
   
  +	
   
   }
  
  
  
  1.4       +27 -2     xml-xalan/java/src/org/apache/xpath/axes/IteratorPool.java
  
  Index: IteratorPool.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/axes/IteratorPool.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- IteratorPool.java	8 Feb 2002 23:33:50 -0000	1.3
  +++ IteratorPool.java	22 Mar 2002 01:04:42 -0000	1.4
  @@ -35,9 +35,34 @@
      *
      * @return An instance of the given object
      */
  -  public synchronized DTMIterator getInstance()
  +  public synchronized DTMIterator getInstanceOrThrow()
  +    throws CloneNotSupportedException
     {
  +    // Check if the pool is empty.
  +    if (m_freeStack.isEmpty())
  +    {
  +
  +      // Create a new object if so.
  +      return (DTMIterator)m_orig.clone();
  +    }
  +    else
  +    {
  +      // Remove object from end of free pool.
  +      DTMIterator result = (DTMIterator)m_freeStack.lastElement();
   
  +      m_freeStack.setSize(m_freeStack.size() - 1);
  +
  +      return result;
  +    }
  +  }
  +  
  +  /**
  +   * Get an instance of the given object in this pool 
  +   *
  +   * @return An instance of the given object
  +   */
  +  public synchronized DTMIterator getInstance()
  +  {
       // Check if the pool is empty.
       if (m_freeStack.isEmpty())
       {
  @@ -73,4 +98,4 @@
     {
       m_freeStack.addElement(obj);
     }
  -}
  +}
  \ No newline at end of file
  
  
  
  1.34      +203 -242  xml-xalan/java/src/org/apache/xpath/axes/LocPathIterator.java
  
  Index: LocPathIterator.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/axes/LocPathIterator.java,v
  retrieving revision 1.33
  retrieving revision 1.34
  diff -u -r1.33 -r1.34
  --- LocPathIterator.java	6 Nov 2001 19:25:53 -0000	1.33
  +++ LocPathIterator.java	22 Mar 2002 01:04:42 -0000	1.34
  @@ -57,31 +57,24 @@
   package org.apache.xpath.axes;
   
   // Java library imports
  -import java.util.Vector;
  -import java.util.Stack;
  +import java.io.IOException;
  +import java.io.ObjectInputStream;
  +import java.io.Serializable;
   
  +import javax.xml.transform.TransformerException;
   import org.apache.xml.dtm.DTM;
  -import org.apache.xml.dtm.DTMIterator;
   import org.apache.xml.dtm.DTMFilter;
  +import org.apache.xml.dtm.DTMIterator;
   import org.apache.xml.dtm.DTMManager;
  -
  -// Xalan imports
  -import org.apache.xpath.res.XPATHErrorResources;
  -import org.apache.xpath.XPath;
  -import org.apache.xpath.compiler.OpMap;
  -import org.apache.xpath.compiler.Compiler;
  -import org.apache.xpath.compiler.OpCodes;
  -import org.apache.xpath.compiler.PsuedoNames;
  -import org.apache.xpath.NodeSetDTM;
  -import org.apache.xpath.Expression;
  -import org.apache.xpath.XPathContext;
  -import org.apache.xpath.objects.XObject;
  -import org.apache.xml.utils.IntStack;
   import org.apache.xml.utils.PrefixResolver;
  -import org.apache.xml.utils.ObjectPool;
  +import org.apache.xpath.ExpressionOwner;
  +import org.apache.xpath.XPathContext;
  +import org.apache.xpath.XPathVisitor;
  +import org.apache.xpath.compiler.Compiler;
   import org.apache.xpath.objects.XNodeSet;
  -import org.apache.xpath.axes.AxesWalker;
  -import org.apache.xpath.VariableStack;
  +import org.apache.xpath.objects.XObject;
  +import org.xml.sax.ContentHandler;
  +import org.xml.sax.SAXException;
   
   /**
    * <meta name="usage" content="advanced"/>
  @@ -96,8 +89,19 @@
    * in which case the UnionPathIterator will cache the nodes.</p>
    */
   public abstract class LocPathIterator extends PredicatedNodeTest
  -        implements Cloneable, DTMIterator, java.io.Serializable
  +        implements Cloneable, DTMIterator, java.io.Serializable, PathComponent
   {
  +	
  +  /**
  +   * Create a LocPathIterator object.
  +   *
  +   * @param nscontext The namespace context for this iterator,
  +   * should be OK if null.
  +   */
  +  protected LocPathIterator()
  +  {
  +  }
  +
   
     /**
      * Create a LocPathIterator object.
  @@ -109,8 +113,7 @@
     {
   
       setLocPathIterator(this);
  -
  -    this.m_prefixResolver = nscontext;
  +    m_prefixResolver = nscontext;
     }
   
     /**
  @@ -153,6 +156,17 @@
       setLocPathIterator(this);
     }
     
  +  /** 
  +   * Get the analysis bits for this walker, as defined in the WalkerFactory.
  +   * @return One of WalkerFactory#BIT_DESCENDANT, etc.
  +   */
  +  public int getAnalysisBits()
  +  {
  +  	int axis = getAxis();
  +  	int bit = WalkerFactory.getAnalysisBitFromAxes(axis);
  +  	return bit;
  +  }
  +  
     /**
      * Read the object from a serialization stream.
      *
  @@ -219,7 +233,7 @@
     {
       return m_execContext.getDTMManager();
     }
  -
  +  
     /**
      * Execute this iterator, meaning create a clone that can
      * store state, and initialize it for fast execution from
  @@ -236,12 +250,45 @@
             throws javax.xml.transform.TransformerException
     {
   
  +    XNodeSet iter = new XNodeSet((LocPathIterator)m_clones.getInstance());
  +
  +    iter.setRoot(xctxt.getCurrentNode(), xctxt);
  +
  +    return iter;
  +  }
  +    
  +  /**
  +   * Execute an expression in the XPath runtime context, and return the
  +   * result of the expression.
  +   *
  +   *
  +   * @param xctxt The XPath runtime context.
  +   * @param handler The target content handler.
  +   *
  +   * @return The result of the expression in the form of a <code>XObject</code>.
  +   *
  +   * @throws javax.xml.transform.TransformerException if a runtime exception
  +   *         occurs.
  +   * @throws org.xml.sax.SAXException
  +   */
  +  public void executeCharsToContentHandler(
  +          XPathContext xctxt, org.xml.sax.ContentHandler handler)
  +            throws javax.xml.transform.TransformerException,
  +                   org.xml.sax.SAXException
  +  {
       LocPathIterator clone = (LocPathIterator)m_clones.getInstance();
   
       int current = xctxt.getCurrentNode();
       clone.setRoot(current, xctxt);
  -
  -    return new XNodeSet(clone);
  +    
  +    int node = clone.nextNode();
  +    DTM dtm = clone.getDTM(node);
  +    clone.detach();
  +	
  +    if(node != DTM.NULL)
  +    {
  +      dtm.dispatchCharactersEvents(node, handler, false);
  +    }
     }
     
     /**
  @@ -263,9 +310,11 @@
             XPathContext xctxt, int contextNode)
               throws javax.xml.transform.TransformerException
     {
  -    LocPathIterator clone = (LocPathIterator)m_clones.getInstance();
  -    clone.setRoot(contextNode, xctxt);
  -    return clone;
  +    XNodeSet iter = new XNodeSet((LocPathIterator)m_clones.getInstance());
  +
  +    iter.setRoot(contextNode, xctxt);
  +
  +    return iter;
     }
   
     
  @@ -291,7 +340,7 @@
       throws javax.xml.transform.TransformerException
     {
       DTMIterator iter = (DTMIterator)m_clones.getInstance();
  -
  +    
       int current = xctxt.getCurrentNode();
       
       iter.setRoot(current, xctxt);
  @@ -355,22 +404,26 @@
     {
   
       m_context = context;
  +    
       XPathContext xctxt = (XPathContext)environment;
       m_execContext = xctxt;
       m_cdtm = xctxt.getDTM(context);
  -    m_currentContextNode = context;
  -    m_prefixResolver = xctxt.getNamespaceContext();
  +    
  +    m_currentContextNode = context; // only if top level?
  +    
  +    // Yech, shouldn't have to do this.  -sb
  +    if(null == m_prefixResolver)
  +    	m_prefixResolver = xctxt.getNamespaceContext();
           
  -//    m_lastFetched = DTM.NULL;
  -//    m_currentContextNode = DTM.NULL;
  -//    m_foundLast = false;
  -//    m_last = 0;
  -//    m_next = 0;
  +    m_lastFetched = DTM.NULL;
  +    m_foundLast = false;
  +    m_pos = 0;
  +    m_length = -1;
   
       if (m_isTopLevel)
         this.m_stackFrame = xctxt.getVarStack().getStackFrame();
         
  -    reset();
  +    // reset();
     }
   
     /**
  @@ -381,7 +434,7 @@
      */
     protected void setNextPosition(int next)
     {
  -    m_next = next;
  +    assertion(false, "setNextPosition not supported in this iterator!");
     }
   
     /**
  @@ -395,16 +448,9 @@
      */
     public final int getCurrentPos()
     {
  -    return m_next;
  +    return m_pos;
     }
   
  -  /**
  -   * Add one to the current node index.
  -   */
  -  void incrementNextPosition()
  -  {
  -    m_next++;
  -  }
   
     /**
      * If setShouldCacheNodes(true) is called, then nodes will
  @@ -415,15 +461,7 @@
     public void setShouldCacheNodes(boolean b)
     {
   
  -    if (b)
  -    {
  -      if(null == m_cachedNodes)
  -      {
  -        m_cachedNodes = new NodeSetDTM(getDTMManager());
  -      }
  -    }
  -    else
  -      m_cachedNodes = null;
  +    assertion(false, "setShouldCacheNodes not supported by this iterater!");
     }
     
     /**
  @@ -434,18 +472,7 @@
      */
     public boolean isMutable()
     {
  -    return (m_cachedNodes != null);
  -  }
  -
  -
  -  /**
  -   * Get cached nodes.
  -   *
  -   * @return Cached nodes.
  -   */
  -  public NodeSetDTM getCachedNodes()
  -  {
  -    return m_cachedNodes;
  +    return false;
     }
   
     /**
  @@ -456,18 +483,18 @@
      */
     public void setCurrentPos(int i)
     {
  -
  -    // System.out.println("setCurrentPos: "+i);
  -    if (null == m_cachedNodes)
  -      throw new RuntimeException(
  -        "This NodeSetDTM can not do indexing or counting functions!");
  -
  -    setNextPosition(i);
  -    m_cachedNodes.setCurrentPos(i);
  -
  -    // throw new RuntimeException("Who's resetting this thing?");
  +  	assertion(false, "setCurrentPos not supported by this iterator!");
  +  }
  +  
  +  /**
  +   * Increment the current position in the node set.
  +   */
  +  public void incrementCurrentPos()
  +  {
  +  	m_pos++;
     }
   
  +
     /**
      * Get the length of the cached nodes.
      *
  @@ -480,11 +507,8 @@
      */
     public int size()
     {
  -
  -    if (null == m_cachedNodes)
  -      return 0;
  -
  -    return m_cachedNodes.size();
  +	assertion(false, "size() not supported by this iterator!");
  +	return 0;
     }
   
     /**
  @@ -498,10 +522,8 @@
      */
     public int item(int index)
     {
  -
  -    // resetToCachedList();
  -
  -    return m_cachedNodes.item(index);
  +	assertion(false, "item(int index) not supported by this iterator!");
  +	return 0;
     }
     
     /**
  @@ -519,7 +541,7 @@
      */
     public void setItem(int node, int index)
     {
  -    m_cachedNodes.setElementAt(node, index);
  +	assertion(false, "setItem not supported by this iterator!");
     }
   
     /**
  @@ -529,36 +551,49 @@
      * @return The number of nodes in the list, always greater or equal to zero.
      */
     public int getLength()
  -  {
  +  {      
  +  	boolean isPredicateTest = (this == m_execContext.getSubContextList());
  +  	int predCount = getPredicateCount();
  +  	
  +  	if(-1 != m_length && !isPredicateTest)
  +  		return m_length;
  +  	
  +  	if(m_foundLast)
  +  		return m_pos;
  +  		
  +    int pos = (m_predicateIndex >= 0) ? getProximityPosition() : m_pos;
  +              
  +    LocPathIterator clone;
   
  -    // resetToCachedList();
  -    if(m_last > 0)
  -      return m_last;
  -    else if(null == m_cachedNodes || !m_foundLast)
  +    try
       {
  -      m_last = findLastPos(m_execContext);
  +      clone = (LocPathIterator) clone();        
       }
  -    else
  +    catch (CloneNotSupportedException cnse)
       {
  -      m_last = m_cachedNodes.getLength();
  +      return -1;
       }
  -    return m_last;
  -  }
   
  -  /**
  -   * In order to implement NodeList (for extensions), try to reset
  -   * to a cached list for random access.
  -   */
  -  private void resetToCachedList()
  -  {
  -    // %REVIEW% ? This doesn't seem to work so well...
  -    int pos = this.getCurrentPos();
  +    // We want to clip off the last predicate, but only if we are a sub 
  +    // context node list, NOT if we are a context list.  See pos68 test, 
  +    // also test against bug4638.
  +    if(predCount > 0 && isPredicateTest)
  +    {
  +      // Don't call setPredicateCount, because it clones and is slower.
  +      clone.m_predCount = predCount - 1;
  +    }
   
  -    if ((null == m_cachedNodes) || (pos != 0))
  -      this.setShouldCacheNodes(true);
  +    int next;
   
  -    runTo(-1);
  -    this.setCurrentPos(pos);
  +    while (DTM.NULL != (next = clone.nextNode()))
  +    {
  +      pos++;
  +    }
  +    
  +    if(!isPredicateTest)
  +      m_length = pos;
  +    
  +    return pos;
     }
   
     /**
  @@ -570,7 +605,7 @@
      */
     public boolean isFresh()
     {
  -    return (m_next == 0);
  +    return (m_pos == 0);
     }
   
     /**
  @@ -581,12 +616,8 @@
      */
     public int previousNode()
     {
  -
  -    if (null == m_cachedNodes)
  -      throw new RuntimeException(
  -        "This NodeSetDTM can not iterate to a previous node!");
  -
  -    return m_cachedNodes.previousNode();
  +    throw new RuntimeException(
  +      "This NodeSetDTM can not iterate to a previous node!");
     }
   
     /**
  @@ -654,7 +685,7 @@
     }
     
     /** Control over whether it is OK for detach to reset the iterator. */
  -  private boolean m_allowDetach = true;
  +  protected boolean m_allowDetach = true;
     
     /**
      * Specify if it's OK for detach to release the iterator for reuse.
  @@ -678,10 +709,16 @@
     {    
       if(m_allowDetach)
       {
  -      m_cachedNodes = null;
  +      // sb: allow reusing of cached nodes when possible?
  +      // m_cachedNodes = null;
         m_execContext = null;
  -      m_prefixResolver = null;
  +      // m_prefixResolver = null;  sb: Why would this ever want to be null?
         m_cdtm = null;
  +      m_length = -1;
  +      m_pos = 0;
  +      m_lastFetched = DTM.NULL;
  +      m_context = DTM.NULL;
  +      m_currentContextNode = DTM.NULL;
         
         m_clones.freeInstance(this);
       }
  @@ -692,12 +729,7 @@
      */
     public void reset()
     {
  -
  -    // super.reset();
  -    m_foundLast = false;
  -    m_lastFetched = DTM.NULL;
  -    m_next = 0;
  -    m_last = 0;
  +  	assertion(false, "This iterator can not reset!");
     }
   
     /**
  @@ -710,10 +742,17 @@
      */
     public DTMIterator cloneWithReset() throws CloneNotSupportedException
     {
  +    LocPathIterator clone;
  +//    clone = (LocPathIterator) clone();
  +    clone = (LocPathIterator)m_clones.getInstanceOrThrow();
  +    clone.m_execContext = m_execContext;
  +    clone.m_cdtm = m_cdtm;
  +    
  +    clone.m_context = m_context;
  +    clone.m_currentContextNode = m_currentContextNode;
  +    clone.m_stackFrame = m_stackFrame;
   
  -    LocPathIterator clone = (LocPathIterator) clone();
  -
  -    clone.reset();
  +    // clone.reset();
   
       return clone;
     }
  @@ -756,10 +795,7 @@
   
       if (DTM.NULL != nextNode)
       {
  -      if (null != m_cachedNodes)
  -        m_cachedNodes.addElement(nextNode);
  -
  -      this.incrementNextPosition();
  +      m_pos++;
       }
   
       m_lastFetched = nextNode;
  @@ -882,101 +918,14 @@
      */
     public final PrefixResolver getPrefixResolver()
     {
  -    return m_prefixResolver;
  -  }
  -
  -  /**
  -   * Get the index of the last node in the iteration.
  -   *
  -   *
  -   * @return the index of the last node in the iteration.
  -   */
  -  public int getLast()
  -  {
  -    return getLength();
  -  }
  -
  -  /**
  -   * Set the index of the last node in the iteration.
  -   *
  -   *
  -   * @param last the index of the last node in the iteration.
  -   */
  -  public void setLast(int last)
  -  {
  -    m_last = last;
  -  }
  -  
  -   /**
  -   * Get the index of the last node that can be itterated to.
  -   * This probably will need to be overridded by derived classes.
  -   *
  -   * @param xctxt XPath runtime context.
  -   *
  -   * @return the index of the last node that can be itterated to.
  -   */
  -  public int getLastPos(XPathContext xctxt)
  -  {
  -    return getLength();
  -  }
  -    
  -  /**
  -   * Get the index of the last node that can be itterated to.
  -   * This probably will need to be overridded by derived classes.
  -   *
  -   * @param xctxt XPath runtime context.
  -   *
  -   * @return the index of the last node that can be itterated to.
  -   */
  -  public int findLastPos(XPathContext xctxt)
  -  {
  -    int savedPos;
  -    if(null != m_cachedNodes)
  -      savedPos = m_cachedNodes.getCurrentPos();
  -    else 
  -      savedPos = -1;
  -      
  -    int pos = (m_predicateIndex >= 0) ? getProximityPosition() : 
  -              ((null != m_cachedNodes) ? m_cachedNodes.getCurrentPos() : m_next);
  -              
  -    LocPathIterator clone;
  +  	if(null == m_prefixResolver)
  +  	{
  +    	m_prefixResolver = (PrefixResolver)getExpressionOwner();
  +  	}
   
  -    try
  -    {
  -      // %REVIEW% %OPT%
  -      if(0 == pos && m_currentContextNode != DTM.NULL)
  -        clone = (LocPathIterator) cloneWithReset();
  -      else
  -        clone = (LocPathIterator) clone();
  -    }
  -    catch (CloneNotSupportedException cnse)
  -    {
  -      return -1;
  -    }
  -
  -    // We want to clip off the last predicate, but only if we are a sub 
  -    // context node list, NOT if we are a context list.  See pos68 test, 
  -    // also test against bug4638.
  -    int predCount = clone.getPredicateCount();
  -    if(predCount > 0 && this == m_execContext.getSubContextList())
  -    {
  -      // Don't call setPredicateCount, because it clones and is slower.
  -      clone.m_predCount = predCount - 1;
  -    }
  -
  -    int next;
  -
  -    while (DTM.NULL != (next = clone.nextNode()))
  -    {
  -      pos++;
  -    }
  -    
  -    if(-1 != savedPos)
  -      m_cachedNodes.setCurrentPos(savedPos);
  -
  -    return pos;
  +    return m_prefixResolver;
     }
  -  
  +        
   //  /**
   //   * Get the analysis pattern built by the WalkerFactory.
   //   *
  @@ -996,6 +945,19 @@
   //  {
   //    m_analysis = a;
   //  }
  +
  +  /**
  +   * @see XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
  +   */
  +  public void callVisitors(ExpressionOwner owner, XPathVisitor visitor)
  +  {
  +  	 	if(visitor.visitLocationPath(owner, this))
  +  	 	{
  +  	 		visitor.visitStep(owner, this);
  +  	 		callPredicateVisitors(visitor);
  +  	 	}
  +  }  
  +
     
     //============= State Data =============
     
  @@ -1025,19 +987,10 @@
      */
     private boolean m_isTopLevel = false;
   
  -  /** The index of the last node in the iteration. */
  -  transient protected int m_last = 0;
  -  
     /** The last node that was fetched, usually by nextNode. */
     transient public int m_lastFetched = DTM.NULL;
   
     /**
  -   * If this iterator needs to cache nodes that are fetched, they
  -   * are stored here.
  -   */
  -  transient NodeSetDTM m_cachedNodes;
  -
  -  /**
      * The context node for this iterator, which doesn't change through
      * the course of the iteration.
      */
  @@ -1050,26 +1003,26 @@
      * expression, rather than the context for the subexpression.
      */
     transient protected int m_currentContextNode = DTM.NULL;
  +  
  +  /**
  +   * The current position of the context node.
  +   */
  +  transient protected int m_pos = 0;
  +  
  +  transient protected int m_length = -1;
   
     /**
      * Fast access to the current prefix resolver.  It isn't really
      * clear that this is needed.
      * @serial
      */
  -  protected PrefixResolver m_prefixResolver;
  +  private PrefixResolver m_prefixResolver;
   
     /**
      * The XPathContext reference, needed for execution of many
      * operations.
      */
     transient protected XPathContext m_execContext;
  -
  -  /**
  -   * The index of the next node to be fetched.  Useful if this
  -   * is a cached iterator, and is being used as random access
  -   * NodeList.
  -   */
  -  transient protected int m_next;
     
     /**
      * Returns true if all the nodes in the iteration well be returned in document 
  @@ -1101,4 +1054,12 @@
   //   * @serial
   //   */
   //  protected int m_analysis = 0x00000000;
  +  /**
  +   * @see PredicatedNodeTest#getLastPos(XPathContext)
  +   */
  +  public int getLastPos(XPathContext xctxt)
  +  {
  +    return getLength();
  +  }
  +
   }
  
  
  
  1.4       +5 -26     xml-xalan/java/src/org/apache/xpath/axes/MatchPatternIterator.java
  
  Index: MatchPatternIterator.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/axes/MatchPatternIterator.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- MatchPatternIterator.java	21 Aug 2001 03:06:45 -0000	1.3
  +++ MatchPatternIterator.java	22 Mar 2002 01:04:42 -0000	1.4
  @@ -192,6 +192,7 @@
       
     }
     
  +  
     /**
      * Initialize the context values for this expression
      * after it is cloned.
  @@ -225,29 +226,10 @@
      *   <code>null</code> if there are no more members in that set.
      */
     public int nextNode()
  -  {
  -
  -    // If the cache is on, and the node has already been found, then 
  -    // just return from the list.
  -    // If the cache is on, and the node has already been found, then 
  -    // just return from the list.
  -    if ((null != m_cachedNodes)
  -            && (m_next < m_cachedNodes.size()))
  -    {
  -      int next = m_cachedNodes.elementAt(m_next);
  -    
  -      incrementNextPosition();
  -      m_currentContextNode = next;
  +  {      
  +  	if(m_foundLast)
  +  		return DTM.NULL;
   
  -      return next;
  -    }
  -
  -    if (m_foundLast)
  -    {
  -      m_lastFetched = DTM.NULL;
  -      return DTM.NULL;
  -    }
  -      
       int next;
       
       org.apache.xpath.VariableStack vars;
  @@ -296,10 +278,7 @@
             System.out.println("next: "+next);
             System.out.println("name: "+m_cdtm.getNodeName(next));
           }
  -        if (null != m_cachedNodes)
  -          m_cachedNodes.addElement(m_lastFetched);
  -  
  -        m_next++;
  +        incrementCurrentPos();
     
           return next;
         }
  
  
  
  1.8       +39 -65    xml-xalan/java/src/org/apache/xpath/axes/OneStepIterator.java
  
  Index: OneStepIterator.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/axes/OneStepIterator.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- OneStepIterator.java	6 Nov 2001 19:25:53 -0000	1.7
  +++ OneStepIterator.java	22 Mar 2002 01:04:43 -0000	1.8
  @@ -1,17 +1,13 @@
   package org.apache.xpath.axes;
   
   import javax.xml.transform.TransformerException;
  -
  -import org.apache.xpath.XPathContext;
  -import org.apache.xpath.compiler.Compiler;
  -import org.apache.xpath.patterns.NodeTest;
  -import org.apache.xpath.objects.XObject;
  -
   import org.apache.xml.dtm.DTM;
  -import org.apache.xml.dtm.DTMIterator;
  -import org.apache.xml.dtm.DTMFilter;
  -import org.apache.xml.dtm.Axis;
   import org.apache.xml.dtm.DTMAxisIterator;
  +import org.apache.xml.dtm.DTMFilter;
  +import org.apache.xml.dtm.DTMIterator;
  +import org.apache.xpath.Expression;
  +import org.apache.xpath.XPathContext;
  +import org.apache.xpath.compiler.Compiler;
   
   /**
    * <meta name="usage" content="advanced"/>
  @@ -46,6 +42,7 @@
       
     }
     
  +  
     /**
      * Create a OneStepIterator object.
      *
  @@ -107,6 +104,24 @@
       }
       return clone;
     }
  +  
  +  /**
  +   *  Get a cloned Iterator that is reset to the beginning
  +   *  of the query.
  +   * 
  +   *  @return A cloned NodeIterator set of the start of the query.
  +   * 
  +   *  @throws CloneNotSupportedException
  +   */
  +  public DTMIterator cloneWithReset() throws CloneNotSupportedException
  +  {
  +
  +    OneStepIterator clone = (OneStepIterator) super.cloneWithReset();
  +    clone.m_iterator = m_iterator;
  +
  +    return clone;
  +  }
  +
   
   
     /**
  @@ -192,61 +207,6 @@
       else if (i < m_proximityPositions.length)
         m_proximityPositions[i]--;
     }
  -
  -  /**
  -   * Get the number of nodes in this node list.  The function is probably ill
  -   * named?
  -   *
  -   *
  -   * @param xctxt The XPath runtime context.
  -   *
  -   * @return the number of nodes in this node list.
  -   */
  -  public int findLastPos(XPathContext xctxt)
  -  {
  -    if(!isReverseAxes())
  -      return super.getLastPos(xctxt);
  -
  -    int count = 0;
  -
  -    try
  -    {
  -      OneStepIterator clone = (OneStepIterator) this.clone();
  -
  -      int root = getRoot();
  -      xctxt.pushCurrentNode(root);
  -      clone.setRoot(root, xctxt);
  -
  -      int predCount = clone.getPredicateCount();
  -      if(predCount > 0 && this == m_execContext.getSubContextList())
  -      {
  -        // Don't call setPredicateCount, because it clones and is slower.
  -        clone.m_predCount = predCount - 1;
  -      }
  -
  -      // Count 'em all
  -      // count = 1;
  -      int next;
  -
  -      while (DTM.NULL != (next = clone.nextNode()))
  -      {
  -        count++;
  -      }
  -    }
  -    catch (CloneNotSupportedException cnse)
  -    {
  -
  -      // can't happen
  -    }
  -    finally
  -    {
  -      xctxt.popCurrentNode();
  -    }
  -
  -    // System.out.println("getLastPos - pos: "+count);
  -    // System.out.println("pos (ReverseAxesWalker): "+count);
  -    return count;
  -  }
     
     /**
      * Reset the iterator.
  @@ -269,6 +229,20 @@
     {
       return m_axis;
     }
  +  
  +  /**
  +   * @see Expression#deepEquals(Expression)
  +   */
  +  public boolean deepEquals(Expression expr)
  +  {
  +  	if(!super.deepEquals(expr))
  +  		return false;
  +  		
  +  	if(m_axis != ((OneStepIterator)expr).m_axis)
  +  		return false;
  +  		
  +  	return true;
  +  }
   
  -
  +  
   }
  
  
  
  1.5       +17 -10    xml-xalan/java/src/org/apache/xpath/axes/OneStepIteratorForward.java
  
  Index: OneStepIteratorForward.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/axes/OneStepIteratorForward.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- OneStepIteratorForward.java	7 Aug 2001 19:16:43 -0000	1.4
  +++ OneStepIteratorForward.java	22 Mar 2002 01:04:43 -0000	1.5
  @@ -1,17 +1,10 @@
   package org.apache.xpath.axes;
   
   import javax.xml.transform.TransformerException;
  -
  -import org.apache.xpath.XPathContext;
  -import org.apache.xpath.compiler.Compiler;
  -import org.apache.xpath.patterns.NodeTest;
  -import org.apache.xpath.objects.XObject;
  -
   import org.apache.xml.dtm.DTM;
  -import org.apache.xml.dtm.DTMIterator;
   import org.apache.xml.dtm.DTMFilter;
  -import org.apache.xml.dtm.Axis;
  -import org.apache.xml.dtm.DTMAxisTraverser;
  +import org.apache.xpath.Expression;
  +import org.apache.xpath.compiler.Compiler;
   
   /**
    * <meta name="usage" content="advanced"/>
  @@ -44,7 +37,7 @@
       m_axis = WalkerFactory.getAxisFromStep(compiler, firstStepPos);
       
     }
  -  
  +    
     /**
      * Create a OneStepIterator object that will just traverse the self axes.
      * 
  @@ -138,6 +131,20 @@
     public int getAxis()
     {
       return m_axis;
  +  }
  +
  +  /**
  +   * @see Expression#deepEquals(Expression)
  +   */
  +  public boolean deepEquals(Expression expr)
  +  {
  +  	if(!super.deepEquals(expr))
  +  		return false;
  +  		
  +  	if(m_axis != ((OneStepIteratorForward)expr).m_axis)
  +  		return false;
  +  		
  +  	return true;
     }
   
     
  
  
  
  1.10      +111 -14   xml-xalan/java/src/org/apache/xpath/axes/PredicatedNodeTest.java
  
  Index: PredicatedNodeTest.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/axes/PredicatedNodeTest.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- PredicatedNodeTest.java	6 Nov 2001 19:25:53 -0000	1.9
  +++ PredicatedNodeTest.java	22 Mar 2002 01:04:43 -0000	1.10
  @@ -1,19 +1,20 @@
   package org.apache.xpath.axes;
   
  -import org.apache.xpath.patterns.NodeTest;
  -import org.apache.xpath.compiler.Compiler;
  -import org.apache.xpath.XPathContext;
  -import org.apache.xpath.objects.XObject;
  -import org.apache.xpath.Expression;
  -import org.apache.xpath.axes.SubContextList;
  +import java.io.IOException;
  +import java.io.ObjectInputStream;
  +import java.util.Vector;
   
  -import org.apache.xml.utils.PrefixResolver;
  -
  -//import org.w3c.dom.Node;
  -//import org.w3c.dom.traversal.NodeFilter;
  +import javax.xml.transform.TransformerException;
   import org.apache.xml.dtm.DTM;
   import org.apache.xml.dtm.DTMIterator;
  -import org.apache.xml.dtm.DTMFilter;
  +import org.apache.xml.utils.PrefixResolver;
  +import org.apache.xpath.Expression;
  +import org.apache.xpath.ExpressionOwner;
  +import org.apache.xpath.XPathContext;
  +import org.apache.xpath.XPathVisitor;
  +import org.apache.xpath.compiler.Compiler;
  +import org.apache.xpath.objects.XObject;
  +import org.apache.xpath.patterns.NodeTest;
   
   public abstract class PredicatedNodeTest extends NodeTest implements SubContextList
   {
  @@ -146,7 +147,16 @@
       int pos = compiler.getFirstPredicateOpPos(opPos);
   
       if(pos > 0)
  +    {
         m_predicates = compiler.getCompiledPredicates(pos);
  +      if(null != m_predicates)
  +      {
  +      	for(int i = 0; i < m_predicates.length; i++)
  +      	{
  +      		m_predicates[i].exprSetParent(this);
  +      	}
  +      }
  +    }
     }
   
     /**
  @@ -255,8 +265,11 @@
      */
     protected void countProximityPosition(int i)
     {
  -    if (i < m_proximityPositions.length)
  -      m_proximityPositions[i]++;
  +  	// Note that in the case of a UnionChildIterator, this may be a 
  +  	// static object and so m_proximityPositions may indeed be null!
  +  	int[] pp = m_proximityPositions;
  +    if ((null != pp) && (i < pp.length))
  +      pp[i]++;
     }
   
     /**
  @@ -326,7 +339,8 @@
             }
   
             int proxPos = this.getProximityPosition(m_predicateIndex);
  -          if (proxPos != (int) pred.num())
  +          int predIndex = (int) pred.num();
  +          if (proxPos != predIndex)
             {
               if (DEBUG_PREDICATECOUNTING)
               {
  @@ -482,6 +496,8 @@
     public void setLocPathIterator(LocPathIterator li)
     {
       m_lpi = li;
  +    if(this != li)
  +      li.exprSetParent(this);
     }
     
     /**
  @@ -501,6 +517,59 @@
       return false;
      }
      
  +	/**
  +	 * This will traverse the heararchy, calling the visitor for 
  +	 * each member.  If the called visitor method returns 
  +	 * false, the subtree should not be called.
  +	 * 
  +	 * @param owner The owner of the visitor, where that path may be 
  +	 *              rewritten if needed.
  +	 * @param visitor The visitor whose appropriate method will be called.
  +	 */
  +	public void callPredicateVisitors(XPathVisitor visitor)
  +	{
  +	  if (null != m_predicates)
  +	    {
  +	    int n = m_predicates.length;
  +	    for (int i = 0; i < n; i++)
  +	      {
  +	      ExpressionOwner predOwner = new PredOwner(i);
  +	      if (visitor.visitPredicate(predOwner, m_predicates[i]))
  +	        {
  +	        m_predicates[i].callVisitors(predOwner, visitor);
  +	      }
  +	
  +	    }
  +	  }
  +	} 
  +	
  +    /**
  +     * @see Expression#deepEquals(Expression)
  +     */
  +    public boolean deepEquals(Expression expr)
  +    {
  +      if (!super.deepEquals(expr))
  +            return false;
  +
  +      PredicatedNodeTest pnt = (PredicatedNodeTest) expr;
  +      if (null != m_predicates)
  +      {
  +
  +        int n = m_predicates.length;
  +        if ((null == pnt.m_predicates) || (pnt.m_predicates.length != n))
  +              return false;
  +        for (int i = 0; i < n; i++)
  +        {
  +          if (!m_predicates[i].deepEquals(pnt.m_predicates[i]))
  +          	return false; 
  +        }
  +      }
  +      else if (null != pnt.m_predicates)
  +              return false; 
  +              
  +      return true; 
  +    }
  +    
     /** This is true if nextNode returns null. */
     transient protected boolean m_foundLast = false;
       
  @@ -527,5 +596,33 @@
   
     /** If true, diagnostic messages about predicate execution will be posted.  */
     static final boolean DEBUG_PREDICATECOUNTING = false;
  +  
  +  class PredOwner implements ExpressionOwner
  +  {
  +  	int m_index;
  +  	
  +  	PredOwner(int index)
  +  	{
  +  		m_index = index;
  +  	}
  +  	
  +    /**
  +     * @see ExpressionOwner#getExpression()
  +     */
  +    public Expression getExpression()
  +    {
  +      return m_predicates[m_index];
  +    }
  +
   
  +    /**
  +     * @see ExpressionOwner#setExpression(Expression)
  +     */
  +    public void setExpression(Expression exp)
  +    {
  +    	exp.exprSetParent(PredicatedNodeTest.this);
  +    	m_predicates[m_index] = exp;
  +    }
  +  }
  +    
   }
  
  
  
  1.10      +7 -5      xml-xalan/java/src/org/apache/xpath/axes/ReverseAxesWalker.java
  
  Index: ReverseAxesWalker.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/axes/ReverseAxesWalker.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- ReverseAxesWalker.java	7 Aug 2001 19:16:43 -0000	1.9
  +++ ReverseAxesWalker.java	22 Mar 2002 01:04:43 -0000	1.10
  @@ -162,7 +162,9 @@
       if(predicateIndex < 0)
         return -1;
         
  -    if (m_proximityPositions[predicateIndex] <= 0)
  +    int count = m_proximityPositions[predicateIndex];
  +      
  +    if (count <= 0)
       {
         AxesWalker savedWalker = wi().getLastUsedWalker();
   
  @@ -179,7 +181,7 @@
           wi().setLastUsedWalker(clone);
   
           // Count 'em all
  -        int count = 1;
  +        count++;
           int next;
   
           while (DTM.NULL != (next = clone.nextNode()))
  @@ -187,7 +189,7 @@
             count++;
           }
   
  -        m_proximityPositions[predicateIndex] += count;
  +        m_proximityPositions[predicateIndex] = count;
         }
         catch (CloneNotSupportedException cnse)
         {
  @@ -199,8 +201,8 @@
           wi().setLastUsedWalker(savedWalker);
         }
       }
  -
  -    return m_proximityPositions[predicateIndex];
  +    
  +    return count;
     }
   
     /**
  
  
  
  1.6       +1 -26     xml-xalan/java/src/org/apache/xpath/axes/SelfIteratorNoPredicate.java
  
  Index: SelfIteratorNoPredicate.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/axes/SelfIteratorNoPredicate.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- SelfIteratorNoPredicate.java	21 Aug 2001 03:06:45 -0000	1.5
  +++ SelfIteratorNoPredicate.java	22 Mar 2002 01:04:43 -0000	1.6
  @@ -63,28 +63,6 @@
      */
     public int nextNode()
     {
  -
  -    // If the cache is on, and the node has already been found, then 
  -    // just return from the list.
  -    // If the cache is on, and the node has already been found, then 
  -    // just return from the list.
  -    if ((null != m_cachedNodes)
  -            && (m_next < m_cachedNodes.size()))
  -    {
  -      int next = m_cachedNodes.elementAt(m_next);
  -    
  -      incrementNextPosition();
  -      m_currentContextNode = next;
  -
  -      return next;
  -    }
  -
  -    if (m_foundLast)
  -    {
  -      m_lastFetched = DTM.NULL;
  -      return DTM.NULL;
  -    }
  -
       int next;
       DTM dtm = m_cdtm;
   
  @@ -95,10 +73,7 @@
       // m_lastFetched = next;
       if (DTM.NULL != next)
       {
  -      if (null != m_cachedNodes)
  -        m_cachedNodes.addElement(m_lastFetched);
  -
  -      m_next++;
  +      m_pos++;
   
         return next;
       }
  
  
  
  1.26      +268 -673  xml-xalan/java/src/org/apache/xpath/axes/UnionPathIterator.java
  
  Index: UnionPathIterator.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/axes/UnionPathIterator.java,v
  retrieving revision 1.25
  retrieving revision 1.26
  diff -u -r1.25 -r1.26
  --- UnionPathIterator.java	17 Sep 2001 21:55:42 -0000	1.25
  +++ UnionPathIterator.java	22 Mar 2002 01:04:43 -0000	1.26
  @@ -56,28 +56,20 @@
    */
   package org.apache.xpath.axes;
   
  -import org.apache.xpath.compiler.OpCodes;
  +import java.io.IOException;
  +import java.io.ObjectInputStream;
  +import java.io.Serializable;
  +import java.util.Vector;
   
  -// DOM Imports
  -//import org.w3c.dom.traversal.NodeIterator;
  -//import org.w3c.dom.Node;
  -//import org.w3c.dom.DOMException;
  -//import org.w3c.dom.traversal.NodeFilter;
  +import javax.xml.transform.TransformerException;
  +import org.apache.xml.dtm.Axis;
   import org.apache.xml.dtm.DTM;
   import org.apache.xml.dtm.DTMIterator;
  -import org.apache.xml.dtm.DTMFilter;
  -import org.apache.xml.dtm.DTMManager;
  -import org.apache.xml.dtm.DTMIterator;
  -
  -// Xalan Imports
  -import org.apache.xpath.NodeSetDTM;
   import org.apache.xpath.Expression;
  -import org.apache.xpath.XPath;
  -import org.apache.xpath.XPathContext;
  -import org.apache.xpath.objects.XNodeSet;
  -import org.apache.xpath.objects.XObject;
  +import org.apache.xpath.ExpressionOwner;
  +import org.apache.xpath.XPathVisitor;
   import org.apache.xpath.compiler.Compiler;
  -import org.apache.xml.utils.ObjectPool;
  +import org.apache.xpath.compiler.OpCodes;
   
   /**
    * <meta name="usage" content="advanced"/>
  @@ -87,8 +79,8 @@
    * As each node is iterated via nextNode(), the node is also stored
    * in the NodeVector, so that previousNode() can easily be done.
    */
  -public class UnionPathIterator extends Expression
  -        implements Cloneable, DTMIterator, java.io.Serializable
  +public class UnionPathIterator extends LocPathIterator
  +        implements Cloneable, DTMIterator, java.io.Serializable, PathComponent
   {
   
     /**
  @@ -102,6 +94,7 @@
       // m_mutable = false;
       // m_cacheNodes = false;
       m_iterators = null;
  +    m_exprs = null;
     }
   
     /**
  @@ -113,26 +106,22 @@
      */
     public void setRoot(int context, Object environment)
     {
  -    this.m_execContext = (XPathContext)environment;
  -    this.m_currentContextNode = context;
  -    this.m_context = context;
  -    m_lastFetched = DTM.NULL;
  -    m_next = 0;
  -    m_last = 0;
  -    m_foundLast = false;
  +    super.setRoot(context, environment);
   
       try
       {
  -      if (null != m_iterators)
  +      if (null != m_exprs)
         {
  -        int n = m_iterators.length;
  +        int n = m_exprs.length;
  +        DTMIterator newIters[] = new DTMIterator[n];
     
           for (int i = 0; i < n; i++)
           {
  -          m_iterators[i] = ((LocPathIterator)m_iterators[i]).asIterator(m_execContext, context);
  -          m_iterators[i].setRoot(context, environment);
  -          m_iterators[i].nextNode();
  +          DTMIterator iter = m_exprs[i].asIterator(m_execContext, context);
  +          newIters[i] = iter;
  +          iter.nextNode();
           }
  +        m_iterators = newIters;
         }
       }
       catch(Exception e)
  @@ -141,261 +130,58 @@
       }
     }
     
  -  /** Control over whether it is OK for detach to reset the iterator. */
  -  private boolean m_allowDetach = true;
  -  
  -  /**
  -   * Specify if it's OK for detach to release the iterator for reuse.
  -   * 
  -   * @param allowRelease true if it is OK for detach to release this iterator 
  -   * for pooling.
  -   */
  -  public void allowDetachToRelease(boolean allowRelease)
  -  {
  -    m_allowDetach = allowRelease;
  -  }
  -
  -  /**
  -   *  Detaches the iterator from the set which it iterated over, releasing
  -   * any computational resources and placing the iterator in the INVALID
  -   * state. After<code>detach</code> has been invoked, calls to
  -   * <code>nextNode</code> or<code>previousNode</code> will raise the
  -   * exception INVALID_STATE_ERR.
  -   */
  -  public void detach()
  -  {
  -
  -    if(m_allowDetach)
  -    {
  -      m_cachedNodes = null;
  -      m_execContext = null;
  -      // m_prefixResolver = null;
  -      // m_cdtm = null;
  -      
  -      if (null != m_iterators)
  -      {
  -        int n = m_iterators.length;
  -  
  -        for (int i = 0; i < n; i++)
  -        {
  -          m_iterators[i].detach();
  -        }
  -      }
  -
  -  
  -  //    int n = m_iterators.length;
  -  //
  -  //    for (int i = 0; i < n; i++)
  -  //    {
  -  //      m_iterators[i].detach();
  -  //    }
  -  
  -      m_clones.freeInstance(this);
  -    }
  -  }
  -
  -  /** Pool of UnionPathIterators.  (The need for this has to be re-evaluated.  -sb) */
  -  transient protected IteratorPool m_clones = new IteratorPool(this);
  -
  -  /**
  -   * Execute this iterator, meaning create a clone that can  
  -   * store state, and initialize it for fast execution from 
  -   * the current runtime state.  When this is called, no actual 
  -   * query from the current context node is performed.
  -   *
  -   * @param xctxt The XPath execution context.
  -   *
  -   * @return An XNodeSet reference that holds this iterator.
  -   *
  -   * @throws javax.xml.transform.TransformerException
  -   */
  -  public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
  -  {
  -
  -    UnionPathIterator clone =
  -      (UnionPathIterator) m_clones.getInstance();
  -
  -    int current = xctxt.getCurrentNode();
  -    clone.setRoot(current, xctxt);
  -
  -    return new XNodeSet(clone);
  -  }
  -
  -  /** If this iterator needs to cache nodes that are fetched, they
  -   * are stored here.   */
  -  transient NodeSetDTM m_cachedNodes = null;
  -
  -  /** The index of the next node to be fetched.  Useful if this 
  -   * is a cached iterator, and is being used as random access 
  -   * NodeList.   */
  -  transient protected int m_next = 0;
  -
  -  /**
  -   * If setShouldCacheNodes(true) is called, then nodes will
  -   * be cached.  They are not cached by default.
  -   *
  -   * @param b True if this iterator should cache nodes.
  -   */
  -  public void setShouldCacheNodes(boolean b)
  -  {
  -
  -    if (b)
  -      m_cachedNodes = new NodeSetDTM(getDTMManager());
  -    else
  -      m_cachedNodes = null;
  -  }
  -  
  -  /**
  -   * Tells if this iterator can have nodes added to it or set via 
  -   * the <code>setItem(int node, int index)</code> method.
  -   * 
  -   * @return True if the nodelist can be mutated.
  -   */
  -  public boolean isMutable()
  -  {
  -    return (m_cachedNodes != null);
  -  }
  -
  -  /**
  -   * Set the current position in the node set.
  -   * @param i Must be a valid index.
  -   */
  -  public void setCurrentPos(int i)
  -  {
  -
  -    if (null == m_cachedNodes)
  -      throw new RuntimeException(
  -        "This NodeSetDTM can not do indexing or counting functions!");
  -
  -    m_next = i;
  -
  -    m_cachedNodes.setCurrentPos(i);
  -  }
  -
  -  /**
  -   * Get the length of the list.
  -   *
  -   * @return The length of this list, or zero is this is not a cached list.
  -   */
  -  public int size()
  -  {
  -
  -    if (null == m_cachedNodes)
  -      return 0;
  -
  -    return m_cachedNodes.size();
  -  }
  -
  -  /**
  -   * Tells if this NodeSetDTM is "fresh", in other words, if
  -   * the first nextNode() that is called will return the
  -   * first node in the set.
  -   *
  -   * @return True if the iteration has not yet begun.
  -   */
  -  public boolean isFresh()
  -  {
  -    return (m_next == 0);
  -  }
  -
  -  /**
  -   *  Returns the previous node in the set and moves the position of the
  -   * iterator backwards in the set.
  -   * @return  The previous <code>Node</code> in the set being iterated over,
  -   *   or<code>null</code> if there are no more members in that set.
  -   */
  -  public int previousNode()
  -  {
  -
  -    if (null == m_cachedNodes)
  -      throw new RuntimeException(
  -        "This NodeSetDTM can not iterate to a previous node!");
  -
  -    return m_cachedNodes.previousNode();
  -  }
  -
  -  /**
  -   *  This attribute determines which node types are presented via the
  -   * iterator. The available set of constants is defined in the
  -   * <code>DTMFilter</code> interface.
  -   *
  -   * @return A bit set that tells what node types to show (DTMFilter.SHOW_ALL at 
  -   * the iterator level).
  -   */
  -  public int getWhatToShow()
  -  {
  -
  -    // TODO: ??
  -    return DTMFilter.SHOW_ALL & ~DTMFilter.SHOW_ENTITY_REFERENCE;
  -  }
  -
  -  /**
  -   *  The filter used to screen nodes.
  -   *
  -   * @return null.
  -   */
  -  public DTMFilter getFilter()
  -  {
  -    return null;
  -  }
  -
  -  /**
  -   *  The root node of the Iterator, as specified when it was created.
  -   *
  -   * @return The context node of this iterator.
  -   */
  -  public int getRoot()
  -  {
  -    return m_context;
  -  }
  -
  -  /**
  -   *  The value of this flag determines whether the children of entity
  -   * reference nodes are visible to the iterator. If false, they will be
  -   * skipped over.
  -   * <br> To produce a view of the document that has entity references
  -   * expanded and does not expose the entity reference node itself, use the
  -   * whatToShow flags to hide the entity reference node and set
  -   * expandEntityReferences to true when creating the iterator. To produce
  -   * a view of the document that has entity reference nodes but no entity
  -   * expansion, use the whatToShow flags to show the entity reference node
  -   * and set expandEntityReferences to false.
  -   *
  -   * @return true.
  -   */
  -  public boolean getExpandEntityReferences()
  -  {
  -    return true;
  -  }
  -
     /**
      * Add an iterator to the union list.
      *
      * @param iter non-null reference to a location path iterator.
      */
  -  public void addIterator(LocPathIterator iter)
  +  public void addIterator(DTMIterator expr)
     {
   
       // Increase array size by only 1 at a time.  Fix this
       // if it looks to be a problem.
       if (null == m_iterators)
       {
  -      m_iterators = new LocPathIterator[1];
  -      m_iterators[0] = iter;
  +      m_iterators = new DTMIterator[1];
  +      m_iterators[0] = expr;
       }
       else
       {
  -      DTMIterator[] iters = m_iterators;
  +      DTMIterator[] exprs = m_iterators;
         int len = m_iterators.length;
   
  -      m_iterators = new LocPathIterator[len + 1];
  +      m_iterators = new DTMIterator[len + 1];
   
  -      System.arraycopy(iters, 0, m_iterators, 0, len);
  +      System.arraycopy(exprs, 0, m_iterators, 0, len);
   
  -      m_iterators[len] = iter;
  +      m_iterators[len] = expr;
  +    }
  +    expr.nextNode();
  +    if(expr instanceof Expression)
  +    	((Expression)expr).exprSetParent(this);
  +  }
  +  
  +  /**
  +   *  Detaches the iterator from the set which it iterated over, releasing
  +   * any computational resources and placing the iterator in the INVALID
  +   * state. After<code>detach</code> has been invoked, calls to
  +   * <code>nextNode</code> or<code>previousNode</code> will raise the
  +   * exception INVALID_STATE_ERR.
  +   */
  +  public void detach()
  +  {    
  +    if(null != m_iterators)
  +    {
  +    	int n = m_iterators.length;
  +    	for(int i = 0; i < n; i++)
  +    	{
  +    		m_iterators[i].detach();
  +    	}
  +    	m_iterators = null;
       }
     }
   
  +
     /**
      * Create a UnionPathIterator object, including creation 
      * of location path iterators from the opcode list, and call back 
  @@ -420,6 +206,88 @@
     }
     
     /**
  +   * This will return an iterator capable of handling the union of paths given.
  +   * 
  +   * @param compiler The Compiler which is creating 
  +   * this expression.
  +   * @param opPos The position of this iterator in the 
  +   * opcode list from the compiler.
  +   * 
  +   * @return Object that is derived from LocPathIterator.
  +   *
  +   * @throws javax.xml.transform.TransformerException
  +   */
  +  public static LocPathIterator createUnionIterator(Compiler compiler, int opPos)
  +          throws javax.xml.transform.TransformerException
  +  {
  +  	// For the moment, I'm going to first create a full UnionPathIterator, and 
  +  	// then see if I can reduce it to a UnionChildIterator.  It would obviously 
  +  	// be more effecient to just test for the conditions for a UnionChildIterator, 
  +  	// and then create that directly.
  +  	UnionPathIterator upi = new UnionPathIterator(compiler, opPos);
  +  	int nPaths = upi.m_exprs.length;
  +  	boolean isAllChildIterators = true;
  +  	for(int i = 0; i < nPaths; i++)
  +  	{
  +  		LocPathIterator lpi = upi.m_exprs[i];
  +  		
  +  		if(lpi.getAxis() != Axis.CHILD)
  +  		{
  +  			isAllChildIterators = false;
  +  			break;
  +  		}
  +  		else
  +  		{
  +  			// check for positional predicates or position function, which won't work.
  +  			if(HasPositionalPredChecker.check(lpi))
  +  			{
  +  				isAllChildIterators = false;
  +  				break;
  +  			}
  +  		}
  +  	}
  +  	if(isAllChildIterators)
  +  	{
  +  		UnionChildIterator uci = new UnionChildIterator();
  +  		
  +	  	for(int i = 0; i < nPaths; i++)
  +	  	{
  +	  		PredicatedNodeTest lpi = upi.m_exprs[i];
  +	  		// I could strip the lpi down to a pure PredicatedNodeTest, but 
  +	  		// I don't think it's worth it.  Note that the test can be used 
  +	  		// as a static object... so it doesn't have to be cloned.
  +	  		uci.addNodeTest(lpi);
  +	  	}
  +	  	return uci;
  +  		
  +  	}
  +  	else
  +  		return upi;
  +  }
  +  
  +  /** 
  +   * Get the analysis bits for this walker, as defined in the WalkerFactory.
  +   * @return One of WalkerFactory#BIT_DESCENDANT, etc.
  +   */
  +  public int getAnalysisBits()
  +  {
  +    int bits = 0;
  +    
  +    if (m_exprs != null)
  +    {
  +      int n = m_exprs.length;
  +
  +      for (int i = 0; i < n; i++)
  +      {
  +      	int bit = m_exprs[i].getAnalysisBits();
  +        bits |= bit;
  +      }
  +    }
  +
  +    return bits;
  +  }
  +  
  +  /**
      * Read the object from a serialization stream.
      *
      * @param stream Input stream to read from
  @@ -442,24 +310,6 @@
     }
   
     /**
  -   * Get a cloned Iterator that is reset to the beginning 
  -   * of the query.
  -   *
  -   * @return A cloned DTMIterator set of the start of the query.
  -   *
  -   * @throws CloneNotSupportedException
  -   */
  -  public DTMIterator cloneWithReset() throws CloneNotSupportedException
  -  {
  -
  -    UnionPathIterator clone = (UnionPathIterator) clone();
  -    
  -    clone.reset();
  -
  -    return clone;
  -  }
  -
  -  /**
      * Get a cloned LocPathIterator that holds the same 
      * position as this iterator.
      *
  @@ -471,69 +321,39 @@
     {
   
       UnionPathIterator clone = (UnionPathIterator) super.clone();
  -    if (m_iterators != null)
  -    {
  -      int n = m_iterators.length;
  -
  -      clone.m_iterators = new LocPathIterator[n];
  -
  -      for (int i = 0; i < n; i++)
  -      {
  -        clone.m_iterators[i] = (LocPathIterator)m_iterators[i].clone();
  -      }
  -    }
  +//    if (m_iterators != null)
  +//    {
  +//      int n = m_iterators.length;
  +//
  +//      clone.m_iterators = new LocPathIterator[n];
  +//
  +//      for (int i = 0; i < n; i++)
  +//      {
  +//        clone.m_iterators[i] = (LocPathIterator)m_iterators[i].clone();
  +//      }
  +//    }
   
       return clone;
     }
     
  +  
     /**
  -   * <meta name="usage" content="experimental"/>
  -   * Given an select expression and a context, evaluate the XPath
  -   * and return the resulting iterator.
  -   * 
  -   * @param xctxt The execution context.
  -   * @param contextNode The node that "." expresses.
  -   * @param namespaceContext The context in which namespaces in the
  -   * XPath are supposed to be expanded.
  -   * 
  -   * @throws TransformerException thrown if the active ProblemListener decides
  -   * the error condition is severe enough to halt processing.
  +   * Create a new location path iterator.
  +   *
  +   * @param compiler The Compiler which is creating 
  +   * this expression.
  +   * @param opPos The position of this iterator in the 
  +   *
  +   * @return New location path iterator.
      *
      * @throws javax.xml.transform.TransformerException
      */
  -  public DTMIterator asIterator(
  -          XPathContext xctxt, int contextNode)
  -            throws javax.xml.transform.TransformerException
  -  {
  -    UnionPathIterator clone = (UnionPathIterator)m_clones.getInstance();
  -    
  -    clone.setRoot(contextNode, xctxt);
  -    
  -    return clone;
  -  }
  -
  -  /**
  -   * Reset the iterator.
  -   */
  -  public void reset()
  +  protected LocPathIterator createDTMIterator(
  +          Compiler compiler, int opPos) throws javax.xml.transform.TransformerException
     {
  -
  -    // super.reset();
  -    m_foundLast = false;
  -    m_next = 0;
  -    m_last = 0;
  -    m_lastFetched = DTM.NULL;
  -
  -    if (m_iterators != null)
  -    {
  -      int n = m_iterators.length;
  -
  -      for (int i = 0; i < n; i++)
  -      {
  -        m_iterators[i].reset();
  -        m_iterators[i].nextNode();
  -      }
  -    }
  +    LocPathIterator lpi = (LocPathIterator)WalkerFactory.newDTMIterator(compiler, opPos, 
  +                                      (compiler.getLocationPathDepth() <= 0));
  +    return lpi;
     }
   
     /**
  @@ -558,7 +378,8 @@
       {
         loadLocationPaths(compiler, compiler.getNextOpPos(opPos), count + 1);
   
  -      m_iterators[count] = createDTMIterator(compiler, opPos);
  +      m_exprs[count] = createDTMIterator(compiler, opPos);
  +      m_exprs[count].exprSetParent(this);
       }
       else
       {
  @@ -575,6 +396,7 @@
   
           WalkingIterator iter =
             new WalkingIterator(compiler.getNamespaceContext());
  +        iter.exprSetParent(this);
             
           if(compiler.getLocationPathDepth() <= 0)
             iter.setIsTopLevel(true);
  @@ -583,37 +405,15 @@
   
           iter.m_firstWalker.init(compiler, opPos, steptype);
   
  -        m_iterators[count] = iter;
  +        m_exprs[count] = iter;
           break;
         default :
  -        m_iterators = new LocPathIterator[count];
  +        m_exprs = new LocPathIterator[count];
         }
       }
     }
   
     /**
  -   * Create a new location path iterator.
  -   *
  -   * @param compiler The Compiler which is creating 
  -   * this expression.
  -   * @param opPos The position of this iterator in the 
  -   *
  -   * @return New location path iterator.
  -   *
  -   * @throws javax.xml.transform.TransformerException
  -   */
  -  protected DTMIterator createDTMIterator(
  -          Compiler compiler, int opPos) throws javax.xml.transform.TransformerException
  -  {
  -    DTMIterator lpi = WalkerFactory.newDTMIterator(compiler, opPos, 
  -                                      (compiler.getLocationPathDepth() <= 0));
  -    return lpi;
  -  }
  -
  -  /** The last node that was fetched, usually by nextNode. */
  -  transient int m_lastFetched = DTM.NULL;
  -
  -  /**
      *  Returns the next node in the set and advances the position of the
      * iterator in the set. After a DTMIterator is created, the first call
      * to nextNode() returns the first node in the set.
  @@ -622,32 +422,8 @@
      */
     public int nextNode()
     {
  -
  -//    // If the cache is on, and the node has already been found, then 
  -//    // just return from the list.
  -//    if ((null != m_cachedNodes)
  -//            && (m_cachedNodes.getCurrentPos() < m_cachedNodes.size()))
  -//    {
  -//      return m_cachedNodes.nextNode();
  -//    }
  -    // If the cache is on, and the node has already been found, then 
  -    // just return from the list.
  -    if ((null != m_cachedNodes)
  -            && (m_next < m_cachedNodes.size()))
  -    {
  -      int next = m_cachedNodes.elementAt(m_next);
  -    
  -      m_next++;
  -      m_currentContextNode = next;
  -
  -      return next;
  -    }
  -
  -    if (m_foundLast)
  -    {
  -      m_lastFetched = DTM.NULL;
  -      return DTM.NULL;
  -    }
  +  	if(m_foundLast)
  +  		return DTM.NULL;
   
       // Loop through the iterators getting the current fetched 
       // node, and get the earliest occuring in document order
  @@ -694,10 +470,7 @@
         {
           m_iterators[iteratorUsed].nextNode();
   
  -        if (null != m_cachedNodes)
  -          m_cachedNodes.addElement(earliestNode);
  -
  -        m_next++;
  +        incrementCurrentPos();
         }
         else
           m_foundLast = true;
  @@ -707,205 +480,7 @@
   
       return earliestNode;
     }
  -
  -  /**
  -   * If an index is requested, NodeSetDTM will call this method
  -   * to run the iterator to the index.  By default this sets
  -   * m_next to the index.  If the index argument is -1, this
  -   * signals that the iterator should be run to the end.
  -   *
  -   * @param index The index to run to, or -1 if the iterator 
  -   * should run to the end.
  -   */
  -  public void runTo(int index)
  -  {
  -
  -    if (m_foundLast || ((index >= 0) && (index <= getCurrentPos())))
  -      return;
  -
  -    int n;
  -
  -    if (-1 == index)
  -    {
  -      while (DTM.NULL != (n = nextNode()));
  -    }
  -    else
  -    {
  -      while (DTM.NULL != (n = nextNode()))
  -      {
  -        if (getCurrentPos() >= index)
  -          break;
  -      }
  -    }
  -  }
  -
  -  /**
  -   * Get the current position, which is one less than
  -   * the next nextNode() call will retrieve.  i.e. if
  -   * you call getCurrentPos() and the return is 0, the next
  -   * fetch will take place at index 1.
  -   *
  -   * @return A value greater than or equal to zero that indicates the next 
  -   * node position to fetch.
  -   */
  -  public int getCurrentPos()
  -  {
  -    return m_next;
  -  }
  -  
  -  /**
  -   *  The number of nodes in the list. The range of valid child node indices
  -   * is 0 to <code>length-1</code> inclusive.
  -   *
  -   * @return The number of nodes in the list, always greater or equal to zero.
  -   */
  -  public int getLength()
  -  {
  -
  -    // resetToCachedList();
  -    if(m_last > 0)
  -      return m_last;
  -    else if(null == m_cachedNodes || !m_foundLast)
  -    {
  -      m_last = getLastPos(m_execContext);
  -    }
  -    else
  -    {
  -      m_last = m_cachedNodes.getLength();
  -    }
  -    return m_last;
  -  }
  -  
  -  /**
  -   * Get the index of the last node that can be itterated to.
  -   * This probably will need to be overridded by derived classes.
  -   *
  -   * @param xctxt XPath runtime context.
  -   *
  -   * @return the index of the last node that can be itterated to.
  -   */
  -  public int getLastPos(XPathContext xctxt)
  -  {
  -    int pos = m_next;
  -    UnionPathIterator clone;
  -
  -    int savedPos;
  -    if(null != m_cachedNodes)
  -      savedPos = m_cachedNodes.getCurrentPos();
  -    else 
  -      savedPos = -1;
  -
  -    try
  -    {
  -      // %REVIEW% %OPT%
  -      if(0 == pos && m_currentContextNode != DTM.NULL)
  -        clone = (UnionPathIterator) cloneWithReset();
  -      else
  -        clone = (UnionPathIterator) clone();
  -    }
  -    catch (CloneNotSupportedException cnse)
  -    {
  -      return -1;
  -    }
  -
  -    int next;
  -    pos = clone.getCurrentPos();
  -
  -    while (DTM.NULL != (next = clone.nextNode()))
  -    {
  -      pos++;
  -    }
  -    
  -    if(-1 != savedPos)
  -      m_cachedNodes.setCurrentPos(savedPos);
  -    
  -    return pos;
  -  }
  -
  -  /**
  -   *  Returns the <code>index</code> th item in the collection. If
  -   * <code>index</code> is greater than or equal to the number of nodes in
  -   * the list, this returns <code>null</code> .
  -   * @param index  Index into the collection.
  -   * @return  The node at the <code>index</code> th position in the
  -   *   <code>NodeList</code> , or <code>null</code> if that is not a valid
  -   *   index.
  -   */
  -  public int item(int index)
  -  {
  -    // resetToCachedList(); %TBD% ??
  -
  -    return m_cachedNodes.item(index);
  -  }
  -  
  -  /**
  -   * Sets the node at the specified index of this vector to be the
  -   * specified node. The previous component at that position is discarded.
  -   *
  -   * <p>The index must be a value greater than or equal to 0 and less
  -   * than the current size of the vector.  
  -   * The iterator must be in cached mode.</p>
  -   * 
  -   * <p>Meant to be used for sorted iterators.</p>
  -   *
  -   * @param node Node to set
  -   * @param index Index of where to set the node
  -   */
  -  public void setItem(int node, int index)
  -  {
  -    m_cachedNodes.setElementAt(node, index);
  -  }
  -  
  -  /**
  -   * Set the current context node for this iterator.
  -   *
  -   * @param n Must be a non-null reference to the node context.
  -   */
  -  public final void setRoot(int n)
  -  {
  -    m_context = n;
  -  }
  -  
  -  /**
  -   * Set the environment in which this iterator operates, which should provide:
  -   * a node (the context node... same value as "root" defined below) 
  -   * a pair of non-zero positive integers (the context position and the context size) 
  -   * a set of variable bindings 
  -   * a function library 
  -   * the set of namespace declarations in scope for the expression.
  -   * 
  -   * <p>At this time the exact implementation of this environment is application 
  -   * dependent.  Probably a proper interface will be created fairly soon.</p>
  -   * 
  -   * @param environment The environment object.
  -   */
  -  public void setEnvironment(Object environment)
  -  {
  -    // no-op for now.
  -  }
  -  
  -  /**
  -   * Get an instance of the DTMManager.  Since a node 
  -   * iterator may be passed without a DTMManager, this allows the 
  -   * caller to easily get the DTMManager using just the iterator.
  -   *
  -   * @return a non-null DTMManager reference.
  -   */
  -  public DTMManager getDTMManager()
  -  {
  -    return m_execContext.getDTMManager();
  -  }
  -  
  -  /**
  -   * Return the last fetched node.
  -   *
  -   * @return The last fetched node, or null if the last fetch was null.
  -   */
  -  public int getCurrentNode()
  -  {
  -    return m_lastFetched;
  -  }
  -  
  +            
     /**
      * This function is used to fixup variables from QNames to stack frame 
      * indexes at stylesheet build time.
  @@ -918,63 +493,22 @@
      */
     public void fixupVariables(java.util.Vector vars, int globalsSize)
     {
  -    for (int i = 0; i < m_iterators.length; i++) 
  +    for (int i = 0; i < m_exprs.length; i++) 
       {
  -      DTMIterator iter = m_iterators[i];
  -      if(iter instanceof Expression)
  -      {
  -        ((Expression)iter).fixupVariables(vars, globalsSize);
  -      }
  +      m_exprs[i].fixupVariables(vars, globalsSize);
       }
       
     }
  -
  -  /**
  -   * Tells if we've found the last node yet.
  -   */
  -  transient protected boolean m_foundLast = false;
  -
  -  /**
  -   * The execution context for the expression.
  -   */
  -  transient protected XPathContext m_execContext;
  -
  -  /**
  -   * The node context for the expression.
  -   */
  -  transient protected int m_context = DTM.NULL;
  -
  -  /**
  -   * The node context from where the Location Path is being
  -   * executed from (i.e. for current() support).
  -   */
  -  transient protected int m_currentContextNode = DTM.NULL;
     
     /**
  -   * Get an instance of a DTM that "owns" a node handle.  Since a node 
  -   * iterator may be passed without a DTMManager, this allows the 
  -   * caller to easily get the DTM using just the iterator.
  -   *
  -   * @param nodeHandle the nodeHandle.
  -   *
  -   * @return a non-null DTM reference.
  -   */
  -  public DTM getDTM(int nodeHandle)
  -  {
  -    return m_execContext.getDTM(nodeHandle);
  -  }
  -  
  -  /**
  -   * The node context from where the expression is being
  -   * executed from (i.e. for current() support).
  -   *
  -   * @return The top-level node context of the entire expression.
  +   * The location path iterators, one for each
  +   * <a href="http://www.w3.org/TR/xpath#NT-LocationPath">location
  +   * path</a> contained in the union expression.
  +   * @serial
      */
  -  public int getCurrentContextNode()
  -  {
  -    return m_currentContextNode;
  -  }
  +  protected LocPathIterator[] m_exprs;
   
  +    
     /**
      * The location path iterators, one for each
      * <a href="http://www.w3.org/TR/xpath#NT-LocationPath">location
  @@ -982,39 +516,7 @@
      * @serial
      */
     protected DTMIterator[] m_iterators;
  -  
  -  /**
  -   * The last index in the list.
  -   */
  -  transient private int m_last = 0;
  -  
  -  /**
  -   * Get the index of the last node in the itteration.
  -   */
  -  public int getLast()
  -  {
  -    return m_last;
  -  }
  -  
  -  /**
  -   * Set the index of the last node in the itteration.
  -   */
  -  public void setLast(int last)
  -  {
  -    m_last = last;
  -  }
  -  
  -  /**
  -   * Returns true if all the nodes in the iteration well be returned in document 
  -   * order.
  -   * 
  -   * @return true as a default.
  -   */
  -  public boolean isDocOrdered()
  -  {
  -    return true;
  -  }
  -  
  +      
     /**
      * Returns the axis being iterated, if it is known.
      * 
  @@ -1026,5 +528,98 @@
       // Could be smarter.
       return -1;
     }
  +  
  +  class iterOwner implements ExpressionOwner
  +  {
  +  	int m_index;
  +  	
  +  	iterOwner(int index)
  +  	{
  +  		m_index = index;
  +  	}
  +  	
  +    /**
  +     * @see ExpressionOwner#getExpression()
  +     */
  +    public Expression getExpression()
  +    {
  +      return m_exprs[m_index];
  +    }
  +
  +    /**
  +     * @see ExpressionOwner#setExpression(Expression)
  +     */
  +    public void setExpression(Expression exp)
  +    {
  +    	
  +    	if(!(exp instanceof LocPathIterator))
  +    	{
  +    		// Yuck.  Need FilterExprIter.  Or make it so m_exprs can be just 
  +    		// plain expressions?
  +    		WalkingIterator wi = new WalkingIterator(getPrefixResolver());
  +    		FilterExprWalker few = new FilterExprWalker(wi);
  +    		wi.setFirstWalker(few);
  +    		few.setInnerExpression(exp);
  +    		wi.exprSetParent(UnionPathIterator.this);
  +    		few.exprSetParent(wi);
  +    		exp.exprSetParent(few);
  +    		exp = wi;
  +    	}
  +    	else
  +    		exp.exprSetParent(UnionPathIterator.this);
  +    	m_exprs[m_index] = (LocPathIterator)exp;
  +    }
  +
  +  }
  +
  +  /**
  +   * @see XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
  +   */
  +  public void callVisitors(ExpressionOwner owner, XPathVisitor visitor)
  +  {
  +  	 	if(visitor.visitUnionPath(owner, this))
  +  	 	{
  +  	 		if(null != m_exprs)
  +  	 		{
  +  	 			int n = m_exprs.length;
  +  	 			for(int i = 0; i < n; i++)
  +  	 			{
  +  	 				m_exprs[i].callVisitors(new iterOwner(i), visitor);
  +  	 			}
  +  	 		}
  +  	 	}
  +  }
  +  
  +    /**
  +     * @see Expression#deepEquals(Expression)
  +     */
  +    public boolean deepEquals(Expression expr)
  +    {
  +      if (!super.deepEquals(expr))
  +            return false;
  +
  +      UnionPathIterator upi = (UnionPathIterator) expr;
  +
  +      if (null != m_exprs)
  +      {
  +        int n = m_exprs.length;
  +        
  +        if((null == upi.m_exprs) || (upi.m_exprs.length != n))
  +        	return false;
  +        
  +        for (int i = 0; i < n; i++)
  +        {
  +          if(!m_exprs[i].deepEquals(upi.m_exprs[i]))
  +          	return false;
  +        }
  +      }
  +      else if (null != upi.m_exprs)
  +      {
  +          return false;
  +      }
  +
  +      return true;
  +    }
  +
   
   }
  
  
  
  1.22      +99 -12    xml-xalan/java/src/org/apache/xpath/axes/WalkerFactory.java
  
  Index: WalkerFactory.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/axes/WalkerFactory.java,v
  retrieving revision 1.21
  retrieving revision 1.22
  diff -u -r1.21 -r1.22
  --- WalkerFactory.java	10 Aug 2001 19:26:52 -0000	1.21
  +++ WalkerFactory.java	22 Mar 2002 01:04:43 -0000	1.22
  @@ -150,6 +150,7 @@
         walker = createDefaultWalker(compiler, stepOpCodePos, lpi, analysis);
   
         walker.init(compiler, stepOpCodePos, stepType);
  +      walker.exprSetParent(lpi);
   
         // walker.setAnalysis(analysis);
         if (null == firstWalker)
  @@ -386,7 +387,59 @@
   
       throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NULL_ERROR_HANDLER, new Object[]{Integer.toString(stepType)})); //"Programmer's assertion: unknown opcode: "
                                  //+ stepType);
  -  }
  +   }
  +    
  +    /**
  +     * Get a corresponding BIT_XXX from an axis.
  +     * @param axis One of Axis.ANCESTOR, etc.
  +     * @return One of BIT_ANCESTOR, etc.
  +     */
  +    static public int getAnalysisBitFromAxes(int axis)
  +    {
  +      switch (axis) // Generate new traverser
  +        {
  +        case Axis.ANCESTOR :
  +          return BIT_ANCESTOR;
  +        case Axis.ANCESTORORSELF :
  +          return BIT_ANCESTOR_OR_SELF;
  +        case Axis.ATTRIBUTE :
  +          return BIT_ATTRIBUTE;
  +        case Axis.CHILD :
  +          return BIT_CHILD;
  +        case Axis.DESCENDANT :
  +          return BIT_DESCENDANT;
  +        case Axis.DESCENDANTORSELF :
  +          return BIT_DESCENDANT_OR_SELF;
  +        case Axis.FOLLOWING :
  +          return BIT_FOLLOWING;
  +        case Axis.FOLLOWINGSIBLING :
  +          return BIT_FOLLOWING_SIBLING;
  +        case Axis.NAMESPACE :
  +        case Axis.NAMESPACEDECLS :
  +          return BIT_NAMESPACE;
  +        case Axis.PARENT :
  +          return BIT_PARENT;
  +        case Axis.PRECEDING :
  +          return BIT_PRECEDING;
  +        case Axis.PRECEDINGSIBLING :
  +          return BIT_PRECEDING_SIBLING;
  +        case Axis.SELF :
  +          return BIT_SELF;
  +        case Axis.ALLFROMNODE :
  +          return BIT_DESCENDANT_OR_SELF;
  +          // case Axis.PRECEDINGANDANCESTOR :
  +        case Axis.DESCENDANTSFROMROOT :
  +        case Axis.ALL :
  +        case Axis.DESCENDANTSORSELFFROMROOT :
  +          return BIT_ANY_DESCENDANT_FROM_ROOT;
  +        case Axis.ROOT :
  +          return BIT_ROOT;
  +        case Axis.FILTEREDLIST :
  +          return BIT_FILTER;
  +        default :
  +          return BIT_FILTER;
  +      }
  +    }
     
     static boolean functionProximateOrContainsProximate(Compiler compiler, 
                                                         int opPos)
  @@ -1399,12 +1452,18 @@
       return isSet(analysis, BIT_DESCENDANT | BIT_DESCENDANT_OR_SELF | BIT_CHILD);
     }
     
  -  public static boolean walksSubtreeOnly(int analysis)
  +  public static boolean walksSubtreeOnlyMaybeAbsolute(int analysis)
     {
       return walksSubtree(analysis)
              && !walksExtraNodes(analysis) 
              && !walksUp(analysis) 
              && !walksSideways(analysis) 
  +           ;
  +  }
  +  
  +  public static boolean walksSubtreeOnly(int analysis)
  +  {
  +    return walksSubtreeOnlyMaybeAbsolute(analysis) 
              && !isAbsolute(analysis) 
              ;
     }
  @@ -1426,15 +1485,22 @@
   
     public static boolean walksInDocOrder(int analysis)
     {
  -    return (walksSubtree(analysis)
  -           || walksExtraNodes(analysis)
  -           || isSet(analysis, BIT_SELF | BIT_FOLLOWING_SIBLING | BIT_FOLLOWING)) 
  -           && !walksUp(analysis) 
  -           && !isSet(analysis, BIT_PRECEDING | BIT_PRECEDING_SIBLING) 
  +    return (walksSubtreeOnlyMaybeAbsolute(analysis)
  +           || walksExtraNodesOnly(analysis)
  +           || walksFollowingOnlyMaybeAbsolute(analysis)) 
              && !isSet(analysis, BIT_FILTER) 
              ;
     }
     
  +  public static boolean walksFollowingOnlyMaybeAbsolute(int analysis)
  +  {
  +    return isSet(analysis, BIT_SELF | BIT_FOLLOWING_SIBLING | BIT_FOLLOWING)
  +           && !walksSubtree(analysis) 
  +           && !walksUp(analysis) 
  +           && !walksSideways(analysis) 
  +           ;
  +  }
  +  
     public static boolean walksUp(int analysis)
     {
       return isSet(analysis, BIT_PARENT | BIT_ANCESTOR | BIT_ANCESTOR_OR_SELF);
  @@ -1475,7 +1541,7 @@
              && !walksDescendants(analysis) 
              && !walksUp(analysis) 
              && !walksSideways(analysis) 
  -           && !isAbsolute(analysis) 
  +           && (!isAbsolute(analysis) || isSet(analysis, BIT_ROOT))
              ;
     }
     
  @@ -1485,7 +1551,7 @@
              && !walksDescendants(analysis) 
              && !walksUp(analysis) 
              && !walksSideways(analysis) 
  -           && !isAbsolute(analysis) 
  +           && (!isAbsolute(analysis) || isSet(analysis, BIT_ROOT))
              ;
     }
     
  @@ -1495,7 +1561,7 @@
              && walksDescendants(analysis) 
              && !walksUp(analysis) 
              && !walksSideways(analysis) 
  -           && !isAbsolute(analysis) 
  +           && (!isAbsolute(analysis) || isSet(analysis, BIT_ROOT))
              ;
     }
     
  @@ -1570,14 +1636,35 @@
      * Tell if the pattern can be 'walked' with the iteration steps in natural 
      * document order, without duplicates.
      *
  +   * @param analysis The general analysis of the pattern.
  +   *
  +   * @return true if the walk can be done in natural order.
  +   *
  +   * @throws javax.xml.transform.TransformerException
  +   */
  +  static public boolean isNaturalDocOrder(int analysis)
  +  {
  +    if(canCrissCross(analysis) || isSet(analysis, BIT_NAMESPACE) ||
  +       walksFilteredList(analysis))
  +      return false;
  +      
  +    if(walksInDocOrder(analysis))
  +      return true;
  +      
  +    return false;
  +  }
  +  
  +  /**
  +   * Tell if the pattern can be 'walked' with the iteration steps in natural 
  +   * document order, without duplicates.
  +   *
      * @param compiler non-null reference to compiler object that has processed
      *                 the XPath operations into an opcode map.
      * @param stepOpCodePos The opcode position for the step.
      * @param stepIndex The top-level step index withing the iterator.
      * @param analysis The general analysis of the pattern.
      *
  -   * @return 32 bits as an integer that give information about the location
  -   * path as a whole.
  +   * @return true if the walk can be done in natural order.
      *
      * @throws javax.xml.transform.TransformerException
      */
  
  
  
  1.5       +134 -62   xml-xalan/java/src/org/apache/xpath/axes/WalkingIterator.java
  
  Index: WalkingIterator.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/axes/WalkingIterator.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- WalkingIterator.java	17 Jun 2001 21:39:59 -0000	1.4
  +++ WalkingIterator.java	22 Mar 2002 01:04:43 -0000	1.5
  @@ -1,33 +1,21 @@
   package org.apache.xpath.axes;
   
  +import java.util.Vector;
  +
  +import javax.xml.transform.TransformerException;
   import org.apache.xml.dtm.DTM;
  -import org.apache.xml.dtm.DTMIterator;
  -import org.apache.xml.dtm.DTMFilter;
  -import org.apache.xml.dtm.DTMManager;
  -
  -// Xalan imports
  -import org.apache.xpath.res.XPATHErrorResources;
  -import org.apache.xpath.XPath;
  -import org.apache.xpath.compiler.OpMap;
  -import org.apache.xpath.compiler.Compiler;
  -import org.apache.xpath.compiler.OpCodes;
  -import org.apache.xpath.compiler.PsuedoNames;
  -import org.apache.xpath.NodeSetDTM;
  -import org.apache.xpath.Expression;
  -import org.apache.xpath.XPathContext;
  -import org.apache.xpath.objects.XObject;
  -import org.apache.xml.utils.IntStack;
   import org.apache.xml.utils.PrefixResolver;
  -import org.apache.xml.utils.ObjectPool;
  -import org.apache.xpath.objects.XNodeSet;
  -import org.apache.xpath.axes.AxesWalker;
  +import org.apache.xpath.Expression;
  +import org.apache.xpath.ExpressionOwner;
   import org.apache.xpath.VariableStack;
  +import org.apache.xpath.XPathVisitor;
  +import org.apache.xpath.compiler.Compiler;
   
   /**
    * Location path iterator that uses Walkers.
    */
   
  -public class WalkingIterator extends LocPathIterator
  +public class WalkingIterator extends LocPathIterator implements ExpressionOwner
   {
     /**
      * Create a WalkingIterator iterator, including creation
  @@ -65,12 +53,33 @@
      * @param nscontext The namespace context for this iterator,
      * should be OK if null.
      */
  -  protected WalkingIterator(PrefixResolver nscontext)
  +  public WalkingIterator(PrefixResolver nscontext)
     {
   
       super(nscontext);
     }
  +  
  +  
  +  /** 
  +   * Get the analysis bits for this walker, as defined in the WalkerFactory.
  +   * @return One of WalkerFactory#BIT_DESCENDANT, etc.
  +   */
  +  public int getAnalysisBits()
  +  {
  +    int bits = 0;
  +    if (null != m_firstWalker)
  +    {    	
  +      AxesWalker walker = m_firstWalker;
   
  +      while (null != walker)
  +      {
  +        int bit = walker.getAnalysisBits();
  +        bits |= bit;
  +        walker = walker.getNextWalker();
  +      }       
  +    }
  +    return bits;
  +  }
     
     /**
      * Get a cloned WalkingIterator that holds the same
  @@ -113,6 +122,25 @@
     }
     
     /**
  +   * Initialize the context values for this expression
  +   * after it is cloned.
  +   *
  +   * @param execContext The XPath runtime context for this
  +   * transformation.
  +   */
  +  public void setRoot(int context, Object environment)
  +  {
  +
  +    super.setRoot(context, environment);
  +    
  +    if(null != m_firstWalker)
  +    {
  +      m_firstWalker.setRoot(context);
  +      m_lastUsedWalker = m_firstWalker;
  +    }
  +  }
  +  
  +  /**
      *  Returns the next node in the set and advances the position of the
      * iterator in the set. After a NodeIterator is created, the first call
      * to nextNode() returns the first node in the set.
  @@ -121,26 +149,8 @@
      */
     public int nextNode()
     {
  -
  -    // If the cache is on, and the node has already been found, then 
  -    // just return from the list.
  -    if (null != m_cachedNodes)
  -    {
  -      if(m_next < m_cachedNodes.size())
  -      {
  -        int next = m_lastFetched = m_currentContextNode 
  -                                       = m_cachedNodes.elementAt(m_next);
  -      
  -        incrementNextPosition();
  -  
  -        return next;
  -      }
  -      else if(m_foundLast)
  -      {
  -        m_lastFetched = DTM.NULL;
  -        return DTM.NULL;
  -      }
  -    }
  +  	if(m_foundLast)
  +  		return DTM.NULL;
   
       // If the variable stack position is not -1, we'll have to 
       // set our position in the variable stack, so our variable access 
  @@ -152,14 +162,6 @@
       // from the execute method.
       if (-1 == m_stackFrame)
       {
  -      if (DTM.NULL == m_firstWalker.getRoot())
  -      {
  -        this.setNextPosition(0);
  -        m_firstWalker.setRoot(m_context);
  -
  -        m_lastUsedWalker = m_firstWalker;
  -      }
  -
         return returnNextNode(m_firstWalker.nextNode());
       }
       else
  @@ -171,14 +173,6 @@
   
         vars.setStackFrame(m_stackFrame);
   
  -      if (DTM.NULL == m_firstWalker.getRoot())
  -      {
  -        this.setNextPosition(0);
  -        m_firstWalker.setRoot(m_context);
  -
  -        m_lastUsedWalker = m_firstWalker;
  -      }
  -
         int n = returnNextNode(m_firstWalker.nextNode());
   
         // These two statements need to be combined into one operation.
  @@ -187,6 +181,7 @@
         return n;
       }
     }
  +
     
     /**
      * <meta name="usage" content="advanced"/>
  @@ -199,6 +194,18 @@
     {
       return m_firstWalker;
     }
  +  
  +  /**
  +   * <meta name="usage" content="advanced"/>
  +   * Set the head of the walker list.
  +   * 
  +   * @param walker Should be a valid AxesWalker.
  +   */
  +  public final void setFirstWalker(AxesWalker walker)
  +  {
  +    m_firstWalker = walker;
  +  }
  +
   
     /**
      * <meta name="usage" content="advanced"/>
  @@ -230,11 +237,21 @@
      * exception INVALID_STATE_ERR.
      */
     public void detach()
  -  {    
  -    m_lastUsedWalker = null;
  -    
  -    // Always call the superclass detach last!
  -    super.detach();
  +  {   
  +    if(m_allowDetach)
  +    {
  +	  	AxesWalker walker = m_firstWalker; 
  +	    while (null != walker)
  +	    {
  +	      walker.detach();
  +	      walker = walker.getNextWalker();
  +	    }
  +	
  +	    m_lastUsedWalker = null;
  +	    
  +	    // Always call the superclass detach last!
  +	    super.detach();
  +    }
     }
     
     /**
  @@ -259,6 +276,20 @@
         walker = walker.getNextWalker();
       }
     }
  +  
  +  /**
  +   * @see XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
  +   */
  +  public void callVisitors(ExpressionOwner owner, XPathVisitor visitor)
  +  {
  +  	 	if(visitor.visitLocationPath(owner, this))
  +  	 	{
  +  	 		if(null != m_firstWalker)
  +  	 		{
  +  	 			m_firstWalker.callVisitors(this, visitor);
  +  	 		}
  +  	 	}
  +  }
   
     
     /** The last used step walker in the walker list.
  @@ -269,4 +300,45 @@
      *  @serial */
     protected AxesWalker m_firstWalker;
   
  +  /**
  +   * @see ExpressionOwner#getExpression()
  +   */
  +  public Expression getExpression()
  +  {
  +    return m_firstWalker;
  +  }
  +
  +  /**
  +   * @see ExpressionOwner#setExpression(Expression)
  +   */
  +  public void setExpression(Expression exp)
  +  {
  +  	exp.exprSetParent(this);
  +  	m_firstWalker = (AxesWalker)exp;
  +  }
  +  
  +    /**
  +     * @see Expression#deepEquals(Expression)
  +     */
  +    public boolean deepEquals(Expression expr)
  +    {
  +      if (!super.deepEquals(expr))
  +                return false;
  +
  +      AxesWalker walker1 = m_firstWalker;
  +      AxesWalker walker2 = ((WalkingIterator)expr).m_firstWalker;
  +      while ((null != walker1) && (null != walker2))
  +      {
  +        if(!walker1.deepEquals(walker2))
  +        	return false;
  +        walker1 = walker1.getNextWalker();
  +        walker2 = walker2.getNextWalker();
  +      }
  +      
  +      if((null != walker1) || (null != walker2))
  +      	return false;
  +
  +      return true;
  +    }
  +
   }
  
  
  
  1.7       +101 -145  xml-xalan/java/src/org/apache/xpath/axes/WalkingIteratorSorted.java
  
  Index: WalkingIteratorSorted.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/axes/WalkingIteratorSorted.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- WalkingIteratorSorted.java	8 Aug 2001 03:55:51 -0000	1.6
  +++ WalkingIteratorSorted.java	22 Mar 2002 01:04:43 -0000	1.7
  @@ -65,13 +65,17 @@
   
   /**
    * <meta name="usage" content="internal"/>
  - * NEEDSDOC Class WalkingIteratorSorted <needs-comment/>
  + * This class iterates over set of nodes that needs to be sorted.
    */
   public class WalkingIteratorSorted extends WalkingIterator
   {
   
  -  /** NEEDSDOC Field m_inNaturalOrder          */
  -  protected boolean m_inNaturalOrder = false;
  +//  /** True if the nodes will be found in document order */
  +//  protected boolean m_inNaturalOrder = false;
  +  
  +  /** True if the nodes will be found in document order, and this can 
  +   * be determined statically. */
  +  protected boolean m_inNaturalOrderStatic = false;
   
     /**
      * Create a WalkingIteratorSorted object.
  @@ -85,36 +89,46 @@
     }
   
     /**
  -   * Create a WalkingIteratorSorted iteratorWalkingIteratorSortedWalkingIteratorSorted.
  +   * Create a WalkingIterator iterator, including creation
  +   * of step walkers from the opcode list, and call back
  +   * into the Compiler to create predicate expressions.
      *
      * @param compiler The Compiler which is creating
      * this expression.
      * @param opPos The position of this iterator in the
      * opcode list from the compiler.
  -   * NEEDSDOC @param analysis
      * @param shouldLoadWalkers True if walkers should be
      * loaded, or false if this is a derived iterator and
      * it doesn't wish to load child walkers.
      *
      * @throws javax.xml.transform.TransformerException
      */
  -  public WalkingIteratorSorted(
  +  WalkingIteratorSorted(
             Compiler compiler, int opPos, int analysis, boolean shouldLoadWalkers)
               throws javax.xml.transform.TransformerException
     {
  -
       super(compiler, opPos, analysis, shouldLoadWalkers);
  -
  -    //this.setShouldCacheNodes(true);
  +  }
  +  
  +  /**
  +   * Returns true if all the nodes in the iteration well be returned in document 
  +   * order.
  +   * 
  +   * @return true as a default.
  +   */
  +  public boolean isDocOrdered()
  +  {
  +    return m_inNaturalOrderStatic;
     }
   
  +    
     /**
  -   * NEEDSDOC Method canBeWalkedInNaturalDocOrder 
  +   * Tell if the nodeset can be walked in doc order, via static analysis. 
      *
      *
  -   * NEEDSDOC (canBeWalkedInNaturalDocOrder) @return
  +   * @return true if the nodeset can be walked in doc order, without sorting.
      */
  -  boolean canBeWalkedInNaturalDocOrder()
  +  boolean canBeWalkedInNaturalDocOrderStatic()
     {
   
       if (null != m_firstWalker)
  @@ -126,12 +140,15 @@
         for(int i = 0; null != walker; i++)
         {
           int axis = walker.getAxis();
  -        boolean isSimpleDownAxis = ((axis == Axis.CHILD)
  -           || (axis == Axis.SELF)
  -           || (axis == Axis.ROOT));
  +        
           if(walker.isDocOrdered())
           {
  -          if(isSimpleDownAxis)
  +          boolean isSimpleDownAxis = ((axis == Axis.CHILD)
  +                                   || (axis == Axis.SELF)
  +                                   || (axis == Axis.ROOT));
  +          // Catching the filtered list here is only OK because
  +          // FilterExprWalker#isDocOrdered() did the right thing.
  +          if(isSimpleDownAxis || (axis == -1))
               walker = walker.getNextWalker();
             else
             {
  @@ -154,143 +171,82 @@
       return false;
     }
   
  +
  +//  /**
  +//   * NEEDSDOC Method canBeWalkedInNaturalDocOrder 
  +//   *
  +//   *
  +//   * NEEDSDOC (canBeWalkedInNaturalDocOrder) @return
  +//   */
  +//  boolean canBeWalkedInNaturalDocOrder()
  +//  {
  +//
  +//    if (null != m_firstWalker)
  +//    {
  +//      AxesWalker walker = m_firstWalker;
  +//      int prevAxis = -1;
  +//      boolean prevIsSimpleDownAxis = true;
  +//
  +//      for(int i = 0; null != walker; i++)
  +//      {
  +//        int axis = walker.getAxis();
  +//        
  +//        if(walker.isDocOrdered())
  +//        {
  +//          boolean isSimpleDownAxis = ((axis == Axis.CHILD)
  +//                                   || (axis == Axis.SELF)
  +//                                   || (axis == Axis.ROOT));
  +//          // Catching the filtered list here is only OK because
  +//          // FilterExprWalker#isDocOrdered() did the right thing.
  +//          if(isSimpleDownAxis || (axis == -1))
  +//            walker = walker.getNextWalker();
  +//          else
  +//          {
  +//            boolean isLastWalker = (null == walker.getNextWalker());
  +//            if(isLastWalker)
  +//            {
  +//              if(walker.isDocOrdered() && (axis == Axis.DESCENDANT || 
  +//                 axis == Axis.DESCENDANTORSELF || axis == Axis.DESCENDANTSFROMROOT
  +//                 || axis == Axis.DESCENDANTSORSELFFROMROOT) || (axis == Axis.ATTRIBUTE))
  +//                return true;
  +//            }
  +//            return false;
  +//          }
  +//        }
  +//        else
  +//          return false;
  +//      }
  +//      return true;
  +//    }
  +//    return false;
  +//  }
  +  
     /**
  -   * Initialize the context values for this expression
  -   * after it is cloned.
  -   *
  -   * @param execContext The XPath runtime context for this
  -   * transformation.
  -   *
  -   * NEEDSDOC @param context
  -   * NEEDSDOC @param environment
  +   * This function is used to perform some extra analysis of the iterator.
  +   * 
  +   * @param vars List of QNames that correspond to variables.  This list 
  +   * should be searched backwards for the first qualified name that 
  +   * corresponds to the variable reference qname.  The position of the 
  +   * QName in the vector from the start of the vector will be its position 
  +   * in the stack frame (but variables above the globalsTop value will need 
  +   * to be offset to the current stack frame).
      */
  -  public void setRoot(int context, Object environment)
  +  public void fixupVariables(java.util.Vector vars, int globalsSize)
     {
  +    super.fixupVariables(vars, globalsSize);
   
  -    super.setRoot(context, environment);
  -
  -    m_inNaturalOrder = canBeWalkedInNaturalDocOrder();
  -
  -    if (!m_inNaturalOrder)
  +    int analysis = getAnalysisBits();
  +    if(WalkerFactory.isNaturalDocOrder(analysis))
       {
  -      this.setShouldCacheNodes(true);
  -
  -      // This should really be done in the super's setRoot, but if I do that 
  -      // it becomes unhappy in the minitest... possibly something to do with 
  -      // the keyref iterator.  -sb
  -      m_cachedNodes.setLast(0);
  -      m_cachedNodes.reset();
  -      m_cachedNodes.RemoveAllNoClear();
  -      setNextPosition(0);
  -      m_firstWalker.setRoot(context);
  -
  -      m_lastUsedWalker = m_firstWalker;
  -
  -      int nextNode = DTM.NULL;
  -      AxesWalker walker = getLastUsedWalker();
  -      XPathContext execContext = (XPathContext) environment;
  -
  -      execContext.pushCurrentNodeAndExpression(context, context);
  -
  -      try
  -      {
  -        do
  -        {
  -          while (true)
  -          {
  -            if (null == walker)
  -              break;
  -
  -            nextNode = walker.getNextNode();
  -
  -            if (DTM.NULL == nextNode)
  -            {
  -              walker = walker.m_prevWalker;
  -            }
  -            else
  -            {
  -              if (walker.acceptNode(nextNode) != DTMIterator.FILTER_ACCEPT)
  -              {
  -                continue;
  -              }
  -
  -              if (null == walker.m_nextWalker)
  -              {
  -                setLastUsedWalker(walker);
  -
  -                // return walker.returnNextNode(nextNode);
  -                break;
  -              }
  -              else
  -              {
  -                AxesWalker prev = walker;
  -
  -                walker = walker.m_nextWalker;
  -
  -                walker.setRoot(nextNode);
  -
  -                walker.m_prevWalker = prev;
  -
  -                continue;
  -              }
  -            }  // if(null != nextNode)
  -          }  // while(null != walker)
  -
  -          if (DTM.NULL != nextNode)
  -          {
  -            incrementNextPosition();
  -
  -            // m_currentContextNode = nextNode;
  -            m_cachedNodes.addNodeInDocOrder(nextNode, execContext);
  -
  -            walker = getLastUsedWalker();
  -          }
  -        }
  -        while (DTM.NULL != nextNode);
  -      }
  -      finally
  -      {
  -        execContext.popCurrentNodeAndExpression();
  -      }
  -
  -      // m_prevReturned = nextNode;
  -      setNextPosition(0);
  -
  -      m_last = m_cachedNodes.size();
  -      m_lastFetched = DTM.NULL;
  -      m_currentContextNode = DTM.NULL;
  -      m_foundLast = true;
  +    	m_inNaturalOrderStatic = true;
       }
  -  }
  -
  -  //  public int nextNode()
  -  //  {
  -  //    return super.nextNode();
  -  //  }
  -
  -  /**
  -   * Reset the iterator.
  -   */
  -  public void reset()
  -  {
  -
  -    if (m_inNaturalOrder)
  -      super.reset();
       else
       {
  -
  -      // super.reset();
  -      // m_foundLast = false;
  -      m_lastFetched = DTM.NULL;
  -      m_next = 0;
  -
  -      // m_last = 0;
  -      if (null != m_firstWalker)
  -      {
  -        m_lastUsedWalker = m_firstWalker;
  -
  -        m_firstWalker.setRoot(m_context);
  -      }
  +    	m_inNaturalOrderStatic = false;
  +    	// System.out.println("Setting natural doc order to false: "+
  +    	//    WalkerFactory.getAnalysisString(analysis));
       }
  +    
     }
  +
   }
  
  
  
  1.2       +203 -0    xml-xalan/java/src/org/apache/xpath/axes/BasicTestIterator.java
  
  
  
  
  1.2       +203 -0    xml-xalan/java/src/org/apache/xpath/axes/FilterExprIterator.java
  
  
  
  
  1.2       +305 -0    xml-xalan/java/src/org/apache/xpath/axes/FilterExprIteratorSimple.java
  
  
  
  
  1.2       +104 -0    xml-xalan/java/src/org/apache/xpath/axes/HasPositionalPredChecker.java
  
  
  
  
  1.2       +674 -0    xml-xalan/java/src/org/apache/xpath/axes/NodeSequence.java
  
  
  
  
  1.2       +72 -0     xml-xalan/java/src/org/apache/xpath/axes/PathComponent.java
  
  
  
  
  1.2       +165 -0    xml-xalan/java/src/org/apache/xpath/axes/UnionChildIterator.java
  
  
  
  
  1.27      +7 -14     xml-xalan/java/src/org/apache/xpath/compiler/Compiler.java
  
  Index: Compiler.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/compiler/Compiler.java,v
  retrieving revision 1.26
  retrieving revision 1.27
  diff -u -r1.26 -r1.27
  --- Compiler.java	27 Jul 2001 17:42:40 -0000	1.26
  +++ Compiler.java	22 Mar 2002 01:04:44 -0000	1.27
  @@ -112,20 +112,13 @@
      * @param errorHandler Error listener where messages will be sent, or null 
      *                     if messages should be sent to System err.
      * @param locator The location object where the expression lives, which 
  -   *                may be null.
  +   *                may be null, but which, if not null, must be valid over 
  +   *                the long haul, in other words, it will not be cloned.
      */
     public Compiler(ErrorListener errorHandler, SourceLocator locator)
     {
       m_errorHandler = errorHandler;
  -    if(null != locator)
  -    {
  -      SAXSourceLocator ssl = new SAXSourceLocator();
  -      ssl.setColumnNumber(locator.getColumnNumber());
  -      ssl.setLineNumber(locator.getLineNumber());
  -      ssl.setPublicId(locator.getPublicId());
  -      ssl.setSystemId(locator.getSystemId());
  -      m_locator = ssl;
  -    }
  +    m_locator = locator;
     }
   
     /**
  @@ -229,8 +222,8 @@
         error(XPATHErrorResources.ER_UNKNOWN_OPCODE,
               new Object[]{ Integer.toString(m_opMap[opPos]) });  //"ERROR! Unknown op code: "+m_opMap[opPos]);
       }
  -    if(null != expr)
  -      expr.setSourceLocator(m_locator);
  +//    if(null != expr)
  +//      expr.setSourceLocator(m_locator);
   
       return expr;
     }
  @@ -631,7 +624,7 @@
      * 
      * @param opPos The current position in the m_opMap array.
      *
  -   * @return reference to {@link org.apache.xpath.axes.UnionPathIterator} instance.
  +   * @return reference to {@link org.apache.xpath.axes.LocPathIterator} instance.
      *
      * @throws TransformerException if a error occurs creating the Expression.
      */
  @@ -640,7 +633,7 @@
       locPathDepth++;
       try
       {
  -      return new UnionPathIterator(this, opPos);
  +      return UnionPathIterator.createUnionIterator(this, opPos);
       }
       finally
       {
  
  
  
  1.5       +1 -0      xml-xalan/java/src/org/apache/xpath/functions/FuncBoolean.java
  
  Index: FuncBoolean.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/functions/FuncBoolean.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- FuncBoolean.java	12 Jun 2001 19:16:32 -0000	1.4
  +++ FuncBoolean.java	22 Mar 2002 01:04:44 -0000	1.5
  @@ -84,4 +84,5 @@
     {
       return m_arg0.execute(xctxt).bool() ? XBoolean.S_TRUE : XBoolean.S_FALSE;
     }
  +  
   }
  
  
  
  1.6       +13 -10    xml-xalan/java/src/org/apache/xpath/functions/FuncCount.java
  
  Index: FuncCount.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/functions/FuncCount.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- FuncCount.java	12 Jun 2001 19:16:32 -0000	1.5
  +++ FuncCount.java	22 Mar 2002 01:04:44 -0000	1.6
  @@ -89,17 +89,20 @@
     public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
     {
   
  -    DTMIterator nl = m_arg0.asIterator(xctxt, xctxt.getCurrentNode());
  +//    DTMIterator nl = m_arg0.asIterator(xctxt, xctxt.getCurrentNode());
   
  -    // We should probably make a function on the iterator for this, 
  -    // as a given implementation could optimize.
  -    int i = 0;
  -
  -    while (DTM.NULL != nl.nextNode())
  -    {
  -      i++;
  -    }
  -    nl.detach();
  +//    // We should probably make a function on the iterator for this, 
  +//    // as a given implementation could optimize.
  +//    int i = 0;
  +//
  +//    while (DTM.NULL != nl.nextNode())
  +//    {
  +//      i++;
  +//    }
  +//    nl.detach();
  +	DTMIterator nl = m_arg0.asIterator(xctxt, xctxt.getCurrentNode());
  +	int i = nl.getLength();	
  +	nl.detach();
   
       return new XNumber((double) i);
     }
  
  
  
  1.14      +3 -1      xml-xalan/java/src/org/apache/xpath/functions/FuncExtFunction.java
  
  Index: FuncExtFunction.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/functions/FuncExtFunction.java,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- FuncExtFunction.java	3 Aug 2001 02:43:17 -0000	1.13
  +++ FuncExtFunction.java	22 Mar 2002 01:04:44 -0000	1.14
  @@ -173,8 +173,10 @@
       for (int i = 0; i < nArgs; i++)
       {
         Expression arg = (Expression) m_argVec.elementAt(i);
  +      
  +      XObject xobj = arg.execute(xctxt);
   
  -      argVec.addElement(arg.execute(xctxt));
  +      argVec.addElement(xobj);
       }
   
       ExtensionsTable etable = xctxt.getExtensionsTable();
  
  
  
  1.6       +34 -4     xml-xalan/java/src/org/apache/xpath/functions/Function.java
  
  Index: Function.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/functions/Function.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- Function.java	12 Jun 2001 19:16:39 -0000	1.5
  +++ Function.java	22 Mar 2002 01:04:44 -0000	1.6
  @@ -58,12 +58,12 @@
   
   //import org.w3c.dom.Node;
   
  -import java.util.Vector;
  -
  +import javax.xml.transform.TransformerException;
  +import org.apache.xpath.Expression;
  +import org.apache.xpath.ExpressionOwner;
   import org.apache.xpath.XPathContext;
  -import org.apache.xpath.XPath;
  +import org.apache.xpath.XPathVisitor;
   import org.apache.xpath.objects.XObject;
  -import org.apache.xpath.Expression;
   
   /**
    * <meta name="usage" content="advanced"/>
  @@ -127,5 +127,35 @@
       return null;
     }
     
  +  /**
  +   * Call the visitors for the function arguments.
  +   */
  +  public void callArgVisitors(XPathVisitor visitor)
  +  {
  +  }
  +
  +  
  +  /**
  +   * @see XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
  +   */
  +  public void callVisitors(ExpressionOwner owner, XPathVisitor visitor)
  +  {
  +  	if(visitor.visitFunction(owner, this))
  +  	{
  +  		callArgVisitors(visitor);
  +  	}
  +  }
  +  
  +  /**
  +   * @see Expression#deepEquals(Expression)
  +   */
  +  public boolean deepEquals(Expression expr)
  +  {
  +  	if(!isSameClass(expr))
  +  		return false;
  +  		
  +  	return true;
  +  }
  +
   
   }
  
  
  
  1.7       +61 -0     xml-xalan/java/src/org/apache/xpath/functions/Function2Args.java
  
  Index: Function2Args.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/functions/Function2Args.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- Function2Args.java	12 Jun 2001 19:16:39 -0000	1.6
  +++ Function2Args.java	22 Mar 2002 01:04:44 -0000	1.7
  @@ -56,7 +56,11 @@
    */
   package org.apache.xpath.functions;
   
  +import java.util.Vector;
  +
   import org.apache.xpath.Expression;
  +import org.apache.xpath.ExpressionOwner;
  +import org.apache.xpath.XPathVisitor;
   
   /**
    * <meta name="usage" content="advanced"/>
  @@ -115,7 +119,10 @@
       if (argNum == 0)
         super.setArg(arg, argNum);
       else if (1 == argNum)
  +    {
         m_arg1 = arg;
  +      arg.exprSetParent(this);
  +    }
       else
         throw new WrongNumberArgsException("2");
     }
  @@ -145,5 +152,59 @@
       return super.canTraverseOutsideSubtree() 
       ? true : m_arg1.canTraverseOutsideSubtree();
      }
  +   
  +  class Arg1Owner implements ExpressionOwner
  +  {
  +    /**
  +     * @see ExpressionOwner#getExpression()
  +     */
  +    public Expression getExpression()
  +    {
  +      return m_arg1;
  +    }
  +
  +
  +    /**
  +     * @see ExpressionOwner#setExpression(Expression)
  +     */
  +    public void setExpression(Expression exp)
  +    {
  +    	exp.exprSetParent(Function2Args.this);
  +    	m_arg1 = exp;
  +    }
  +  }
  +
  +   
  +  /**
  +   * @see XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
  +   */
  +  public void callArgVisitors(XPathVisitor visitor)
  +  {
  +  	super.callArgVisitors(visitor);
  +  	if(null != m_arg1)
  +  		m_arg1.callVisitors(new Arg1Owner(), visitor);
  +  }
  +
  +  /**
  +   * @see Expression#deepEquals(Expression)
  +   */
  +  public boolean deepEquals(Expression expr)
  +  {
  +  	if(!super.deepEquals(expr))
  +  		return false;
  +  		
  +  	if(null != m_arg1)
  +  	{
  +  		if(null == ((Function2Args)expr).m_arg1)
  +  			return false;
  +  			
  +  		if(!m_arg1.deepEquals(((Function2Args)expr).m_arg1))
  +  			return false;
  +  	}
  +  	else if(null != ((Function2Args)expr).m_arg1)
  +  		return false;
  +  		
  +  	return true;
  +  }
   
   }
  
  
  
  1.8       +62 -0     xml-xalan/java/src/org/apache/xpath/functions/Function3Args.java
  
  Index: Function3Args.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/functions/Function3Args.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- Function3Args.java	12 Jun 2001 19:16:39 -0000	1.7
  +++ Function3Args.java	22 Mar 2002 01:04:44 -0000	1.8
  @@ -56,7 +56,11 @@
    */
   package org.apache.xpath.functions;
   
  +import java.util.Vector;
  +
   import org.apache.xpath.Expression;
  +import org.apache.xpath.ExpressionOwner;
  +import org.apache.xpath.XPathVisitor;
   
   /**
    * <meta name="usage" content="advanced"/>
  @@ -113,7 +117,10 @@
       if (argNum < 2)
         super.setArg(arg, argNum);
       else if (2 == argNum)
  +    {
         m_arg2 = arg;
  +      arg.exprSetParent(this);
  +    }
       else
         throw new WrongNumberArgsException("3");
     }
  @@ -143,5 +150,60 @@
       return super.canTraverseOutsideSubtree() 
       ? true : m_arg2.canTraverseOutsideSubtree();
      }
  +   
  +  class Arg2Owner implements ExpressionOwner
  +  {
  +    /**
  +     * @see ExpressionOwner#getExpression()
  +     */
  +    public Expression getExpression()
  +    {
  +      return m_arg2;
  +    }
  +
  +
  +    /**
  +     * @see ExpressionOwner#setExpression(Expression)
  +     */
  +    public void setExpression(Expression exp)
  +    {
  +    	exp.exprSetParent(Function3Args.this);
  +    	m_arg2 = exp;
  +    }
  +  }
  +
  +   
  +  /**
  +   * @see XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
  +   */
  +  public void callArgVisitors(XPathVisitor visitor)
  +  {
  +  	super.callArgVisitors(visitor);
  +  	if(null != m_arg2)
  +  		m_arg2.callVisitors(new Arg2Owner(), visitor);
  +  }
  +
  +  /**
  +   * @see Expression#deepEquals(Expression)
  +   */
  +  public boolean deepEquals(Expression expr)
  +  {
  +  	if(!super.deepEquals(expr))
  +  		return false;
  +  		
  +  	if(null != m_arg2)
  +  	{
  +  		if(null == ((Function3Args)expr).m_arg2)
  +  			return false;
  +
  +  		if(!m_arg2.deepEquals(((Function3Args)expr).m_arg2))
  +  			return false;
  +  	}
  +  	else if (null != ((Function3Args)expr).m_arg2)
  +  		return false;
  +  		
  +  	return true;
  +  }
  +
   
   }
  
  
  
  1.8       +81 -0     xml-xalan/java/src/org/apache/xpath/functions/FunctionMultiArgs.java
  
  Index: FunctionMultiArgs.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/functions/FunctionMultiArgs.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- FunctionMultiArgs.java	12 Jun 2001 19:16:40 -0000	1.7
  +++ FunctionMultiArgs.java	22 Mar 2002 01:04:44 -0000	1.8
  @@ -56,7 +56,12 @@
    */
   package org.apache.xpath.functions;
   
  +import java.util.Vector;
  +
   import org.apache.xpath.Expression;
  +import org.apache.xpath.ExpressionOwner;
  +import org.apache.xpath.XPathVisitor;
  +import org.apache.xpath.functions.Function3Args.Arg2Owner;
   
   /**
    * <meta name="usage" content="advanced"/>
  @@ -104,6 +109,7 @@
           args[m_args.length] = arg;
           m_args = args;
         }
  +      arg.exprSetParent(this);
       }
     }
     
  @@ -163,4 +169,79 @@
         return false;
       }
     }
  +  
  +  class ArgMultiOwner implements ExpressionOwner
  +  {
  +  	int m_argIndex;
  +  	
  +  	ArgMultiOwner(int index)
  +  	{
  +  		m_argIndex = index;
  +  	}
  +  	
  +    /**
  +     * @see ExpressionOwner#getExpression()
  +     */
  +    public Expression getExpression()
  +    {
  +      return m_args[m_argIndex];
  +    }
  +
  +
  +    /**
  +     * @see ExpressionOwner#setExpression(Expression)
  +     */
  +    public void setExpression(Expression exp)
  +    {
  +    	exp.exprSetParent(FunctionMultiArgs.this);
  +    	m_args[m_argIndex] = exp;
  +    }
  +  }
  +
  +   
  +    /**
  +     * @see XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
  +     */
  +    public void callArgVisitors(XPathVisitor visitor)
  +    {
  +      super.callArgVisitors(visitor);
  +      if (null != m_args)
  +      {
  +        int n = m_args.length;
  +        for (int i = 0; i < n; i++)
  +        {
  +          m_args[i].callVisitors(new ArgMultiOwner(i), visitor);
  +        }
  +      }
  +    }
  +    
  +    /**
  +     * @see Expression#deepEquals(Expression)
  +     */
  +    public boolean deepEquals(Expression expr)
  +    {
  +      if (!super.deepEquals(expr))
  +            return false;
  +
  +      FunctionMultiArgs fma = (FunctionMultiArgs) expr;
  +      if (null != m_args)
  +      {
  +        int n = m_args.length;
  +        if ((null == fma) || (fma.m_args.length != n))
  +              return false;
  +
  +        for (int i = 0; i < n; i++)
  +        {
  +          if (!m_args[i].deepEquals(fma.m_args[i]))
  +                return false;
  +        }
  +
  +      }
  +      else if (null != fma.m_args)
  +      {
  +          return false;
  +      }
  +
  +      return true;
  +    }
   }
  
  
  
  1.7       +58 -1     xml-xalan/java/src/org/apache/xpath/functions/FunctionOneArg.java
  
  Index: FunctionOneArg.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/functions/FunctionOneArg.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- FunctionOneArg.java	12 Jun 2001 19:16:40 -0000	1.6
  +++ FunctionOneArg.java	22 Mar 2002 01:04:44 -0000	1.7
  @@ -56,13 +56,17 @@
    */
   package org.apache.xpath.functions;
   
  +import java.util.Vector;
  +
   import org.apache.xpath.Expression;
  +import org.apache.xpath.ExpressionOwner;
  +import org.apache.xpath.XPathVisitor;
   
   /**
    * <meta name="usage" content="advanced"/>
    * Base class for functions that accept one argument.
    */
  -public class FunctionOneArg extends Function
  +public class FunctionOneArg extends Function implements ExpressionOwner
   {
   
     /** The first argument passed to the function (at index 0).
  @@ -94,7 +98,10 @@
     {
   
       if (0 == argNum)
  +    {
         m_arg0 = arg;
  +      arg.exprSetParent(this);
  +    }
       else
         throw new WrongNumberArgsException("1");
     }
  @@ -139,5 +146,55 @@
       if(null != m_arg0)
         m_arg0.fixupVariables(vars, globalsSize);
     }
  +  
  +  /**
  +   * @see XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
  +   */
  +  public void callArgVisitors(XPathVisitor visitor)
  +  {
  +  	if(null != m_arg0)
  +  		m_arg0.callVisitors(this, visitor);
  +  }
  +
  +
  +  /**
  +   * @see ExpressionOwner#getExpression()
  +   */
  +  public Expression getExpression()
  +  {
  +    return m_arg0;
  +  }
  +
  +  /**
  +   * @see ExpressionOwner#setExpression(Expression)
  +   */
  +  public void setExpression(Expression exp)
  +  {
  +  	exp.exprSetParent(this);
  +  	m_arg0 = exp;
  +  }
  +  
  +  /**
  +   * @see Expression#deepEquals(Expression)
  +   */
  +  public boolean deepEquals(Expression expr)
  +  {
  +  	if(!super.deepEquals(expr))
  +  		return false;
  +  		
  +  	if(null != m_arg0)
  +  	{
  +  		if(null == ((FunctionOneArg)expr).m_arg0)
  +  			return false;
  +  			
  +  		if(!m_arg0.deepEquals(((FunctionOneArg)expr).m_arg0))
  +  			return false;
  +  	}
  +  	else if(null != ((FunctionOneArg)expr).m_arg0)
  +  		return false;
  +
  +  	return true;
  +  }
   
  +
   }
  
  
  
  1.11      +0 -2      xml-xalan/java/src/org/apache/xpath/objects/XBoolean.java
  
  Index: XBoolean.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/objects/XBoolean.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- XBoolean.java	4 Feb 2002 15:00:51 -0000	1.10
  +++ XBoolean.java	22 Mar 2002 01:04:44 -0000	1.11
  @@ -93,7 +93,6 @@
       super();
   
       m_val = b;
  -    m_precedence = XObject.ORDER_BOOLEAN;
     }
     
     /**
  @@ -108,7 +107,6 @@
   
       m_val = b.booleanValue();
       m_obj = b;
  -    m_precedence = XObject.ORDER_BOOLEAN;
     }
   
   
  
  
  
  1.21      +105 -79   xml-xalan/java/src/org/apache/xpath/objects/XNodeSet.java
  
  Index: XNodeSet.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/objects/XNodeSet.java,v
  retrieving revision 1.20
  retrieving revision 1.21
  diff -u -r1.20 -r1.21
  --- XNodeSet.java	4 Feb 2002 15:00:51 -0000	1.20
  +++ XNodeSet.java	22 Mar 2002 01:04:44 -0000	1.21
  @@ -70,6 +70,7 @@
   import org.apache.xpath.XPathContext;
   import org.apache.xpath.NodeSetDTM;
   import org.apache.xpath.axes.ContextNodeList;
  +import org.apache.xpath.axes.NodeSequence;
   import org.apache.xml.utils.StringVector;
   import org.apache.xml.utils.XMLString;
   
  @@ -78,21 +79,13 @@
    * This class represents an XPath nodeset object, and is capable of
    * converting the nodeset to other types, such as a string.
    */
  -public class XNodeSet extends XObject
  -{
  -  protected DTMManager m_dtmMgr;
  -  
  -  public DTMManager getDTMMgr()
  -  {
  -    return m_dtmMgr;
  -  }
  -  
  +public class XNodeSet extends NodeSequence
  +{  
     /**
      * Default constructor for derived objects.
      */
     protected XNodeSet()
     {
  -    m_precedence = XObject.ORDER_NODESET;
     }
   
     /**
  @@ -102,20 +95,44 @@
      */
     public XNodeSet(DTMIterator val)
     {
  -    super(val);
  -    m_dtmMgr = val.getDTMManager();
  -    m_precedence = XObject.ORDER_NODESET;
  +  	super();
  +  	if(val instanceof XNodeSet)
  +  	{
  +	    setIter(((XNodeSet)val).m_iter);
  +	    m_dtmMgr = ((XNodeSet)val).m_dtmMgr;
  +	    m_last = ((XNodeSet)val).m_last;
  +	    if(!((XNodeSet)val).hasCache())
  +	    	((XNodeSet)val).setShouldCacheNodes(true);
  +	    m_obj = ((XNodeSet)val).m_obj;
  +  	}
  +  	else
  +    	setIter(val);
  +  }
  +  
  +  /**
  +   * Construct a XNodeSet object.
  +   *
  +   * @param val Value of the XNodeSet object
  +   */
  +  public XNodeSet(XNodeSet val)
  +  {
  +  	super();
  +    setIter(val.m_iter);
  +    m_dtmMgr = val.m_dtmMgr;
  +    m_last = val.m_last;
  +    if(!val.hasCache())
  +    	val.setShouldCacheNodes(true);
  +    m_obj = val.m_obj;
     }
   
  +
     /**
      * Construct an empty XNodeSet object.  This is used to create a mutable 
      * nodeset to which random nodes may be added.
      */
  -  public XNodeSet(DTMManager dtmMgr)
  +  public XNodeSet(DTMManager dtmMgr) 
     {
  -    super(new NodeSetDTM(dtmMgr));
  -    m_dtmMgr = dtmMgr;
  -    m_precedence = XObject.ORDER_NODESET;
  +    super(dtmMgr);
     }
   
     /**
  @@ -132,8 +149,10 @@
       if (DTM.NULL != n)
       {
         ((NodeSetDTM) m_obj).addNode(n);
  +      m_last = 1;
       }
  -    m_precedence = XObject.ORDER_NODESET;
  +    else
  +    	m_last = 0;
     }
   
     /**
  @@ -179,9 +198,7 @@
     public double num()
     {
   
  -    DTMIterator nl = iter();
  -    int node = nl.nextNode();
  -
  +    int node = item(0);
       return (node != DTM.NULL) ? getNumberFromNode(node) : Double.NaN;
     }
     
  @@ -194,8 +211,7 @@
      */
     public double numWithSideEffects()
     {
  -    DTMIterator nl = iterRaw();
  -    int node = nl.nextNode();
  +    int node = nextNode();
   
       return (node != DTM.NULL) ? getNumberFromNode(node) : Double.NaN;
     }
  @@ -208,7 +224,7 @@
      */
     public boolean bool()
     {
  -    return (iter().nextNode() != DTM.NULL);
  +    return (item(0) != DTM.NULL);
     }
     
     /**
  @@ -219,7 +235,7 @@
      */
     public boolean boolWithSideEffects()
     {
  -    return (iterRaw().nextNode() != DTM.NULL);
  +    return (nextNode() != DTM.NULL);
     }
   
     
  @@ -258,13 +274,13 @@
     public void dispatchCharactersEvents(org.xml.sax.ContentHandler ch)
             throws org.xml.sax.SAXException
     {
  -    DTMIterator nl = iter();
  -    int node = nl.nextNode();
  -
  +    int node = item(0);
  +	
       if(node != DTM.NULL)
       {
         m_dtmMgr.getDTM(node).dispatchCharactersEvents(node, ch, false);
       }
  +    
     }
     
     /**
  @@ -274,9 +290,7 @@
      */
     public XMLString xstr()
     {
  -    DTMIterator nl = iter();
  -    int node = nl.nextNode();
  -
  +    int node = item(0);
       return (node != DTM.NULL) ? getStringFromNode(node) : XString.EMPTYSTRING;
     }
     
  @@ -291,35 +305,6 @@
       xstring.appendToFsb(fsb);
     }
     
  -  /**
  -   * Specify if it's OK for detach to release the iterator for reuse.
  -   * 
  -   * @param allowRelease true if it is OK for detach to release this iterator 
  -   * for pooling.
  -   */
  -  public void allowDetachToRelease(boolean allowRelease)
  -  {
  -    if(null != m_obj)
  -      ((DTMIterator) m_obj).allowDetachToRelease(allowRelease);
  -  }
  -
  -  /**
  -   * Detaches the <code>DTMIterator</code> from the set which it iterated
  -   * over, releasing any computational resources and placing the iterator
  -   * in the INVALID state. After <code>detach</code> has been invoked,
  -   * calls to <code>nextNode</code> or <code>previousNode</code> will
  -   * raise a runtime exception.
  -   */
  -  public void detach()
  -  {
  -    if(null != m_obj)
  -    {
  -      Object obj = m_obj;
  -      m_obj = null;
  -      ((DTMIterator) obj).detach();
  -    }
  -  }
  -
   
     /**
      * Cast result object to a string.
  @@ -329,11 +314,22 @@
      */
     public String str()
     {
  -
  -    DTMIterator nl = iter();
  -    int node = nl.nextNode();
  -
  -    return (node != DTM.NULL) ? getStringFromNode(node).toString() : "";
  +    int node = item(0);
  +    return (node != DTM.NULL) ? getStringFromNode(node).toString() : "";   
  +  }
  +  
  +  /**
  +   * Return a java object that's closest to the representation
  +   * that should be handed to an extension.
  +   *
  +   * @return The object that this class wraps
  +   */
  +  public Object object()
  +  {
  +    if(null == m_obj)
  +    	return this;
  +    else
  +    	return m_obj;
     }
   
     // %REVIEW%
  @@ -365,9 +361,9 @@
   //  }
   
     /**
  -   * Cast result object to a nodelist. Always issues an error.
  +   * Cast result object to a nodelist.
      *
  -   * @return null
  +   * @return a NodeIterator.
      *
      * @throws javax.xml.transform.TransformerException
      */
  @@ -377,9 +373,9 @@
     }
     
     /**
  -   * Cast result object to a nodelist. Always issues an error.
  +   * Cast result object to a nodelist.
      *
  -   * @return null
  +   * @return a NodeList.
      *
      * @throws javax.xml.transform.TransformerException
      */
  @@ -405,9 +401,11 @@
      */
     public DTMIterator iterRaw()
     {
  -
  -    // System.out.println("In XNodeSet.iter()");
  -    return (DTMIterator) m_obj;
  +    return this;
  +  }
  +  
  +  public void release(DTMIterator iter)
  +  {
     }
     
     /**
  @@ -419,7 +417,30 @@
     {
       try
       {
  -      return ((DTMIterator) m_obj).cloneWithReset();
  +    	if(hasCache())
  +      		return cloneWithReset();
  +      	else
  +      		return this; // don't bother to clone... won't do any good!
  +    }
  +    catch (CloneNotSupportedException cnse)
  +    {
  +      throw new RuntimeException(cnse.getMessage());
  +    }
  +  }
  +  
  +  /**
  +   * Get a fresh copy of the object.  For use with variables.
  +   *
  +   * @return A fresh nodelist.
  +   */
  +  public XObject getFresh()
  +  {
  +    try
  +    {
  +    	if(hasCache())
  +      		return (XObject)cloneWithReset();
  +      	else
  +      		return this; // don't bother to clone... won't do any good!
       }
       catch (CloneNotSupportedException cnse)
       {
  @@ -434,7 +455,6 @@
      */
     public NodeSetDTM mutableNodeset()
     {
  -
       NodeSetDTM mnl;
   
       if(m_obj instanceof NodeSetDTM)
  @@ -445,6 +465,7 @@
       {
         mnl = new NodeSetDTM(iter());
         m_obj = mnl;
  +      setCurrentPos(0);
       }
   
       return mnl;
  @@ -501,8 +522,8 @@
         // is true if and only if some node in $x has the string-value 
         // foo; the latter is true if and only if all nodes in $x have 
         // the string-value foo.
  -      DTMIterator list1 = iter();
  -      DTMIterator list2 = ((XNodeSet) obj2).iter();
  +      DTMIterator list1 = iterRaw();
  +      DTMIterator list2 = ((XNodeSet) obj2).iterRaw();
         int node1;
         java.util.Vector node2Strings = null;
   
  @@ -546,6 +567,8 @@
             }
           }
         }
  +      list1.reset();
  +      list2.reset();
       }
       else if (XObject.CLASS_BOOLEAN == type)
       {
  @@ -571,7 +594,7 @@
         // comparison on the number to be compared and on the result of 
         // converting the string-value of that node to a number using 
         // the number function is true. 
  -      DTMIterator list1 = iter();
  +      DTMIterator list1 = iterRaw();
         double num2 = obj2.num();
         int node;
   
  @@ -586,11 +609,12 @@
             break;
           }
         }
  +      list1.reset();
       }
       else if (XObject.CLASS_RTREEFRAG == type)
       {
         XMLString s2 = obj2.xstr();
  -      DTMIterator list1 = iter();
  +      DTMIterator list1 = iterRaw();
         int node;
   
         while (DTM.NULL != (node = list1.nextNode()))
  @@ -604,6 +628,7 @@
             break;
           }
         }
  +      list1.reset();
       }
       else if (XObject.CLASS_STRING == type)
       {
  @@ -615,7 +640,7 @@
         // the comparison on the string-value of the node and the other 
         // string is true. 
         XMLString s2 = obj2.xstr();
  -      DTMIterator list1 = iter();
  +      DTMIterator list1 = iterRaw();
         int node;
   
         while (DTM.NULL != (node = list1.nextNode()))
  @@ -628,6 +653,7 @@
             break;
           }
         }
  +      list1.reset();
       }
       else
       {
  
  
  
  1.2       +12 -0     xml-xalan/java/src/org/apache/xpath/objects/XNodeSetForDOM.java
  
  Index: XNodeSetForDOM.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/objects/XNodeSetForDOM.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- XNodeSetForDOM.java	3 Aug 2001 02:43:17 -0000	1.1
  +++ XNodeSetForDOM.java	22 Mar 2002 01:04:44 -0000	1.2
  @@ -25,6 +25,18 @@
       ((NodeSetDTM) m_obj).addNode(dtmHandle);
     }
     
  +  /**
  +   * Construct a XNodeSet object.
  +   *
  +   * @param val Value of the XNodeSet object
  +   */
  +  public XNodeSetForDOM(XNodeSet val)
  +  {
  +  	super(val);
  +  	if(val instanceof XNodeSetForDOM)
  +    	m_origObj = ((XNodeSetForDOM)val).m_origObj;
  +  }
  +  
     public XNodeSetForDOM(NodeList nodeList, XPathContext xctxt)
     {
       m_dtmMgr = xctxt.getDTMManager();
  
  
  
  1.13      +19 -8     xml-xalan/java/src/org/apache/xpath/objects/XNumber.java
  
  Index: XNumber.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/objects/XNumber.java,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- XNumber.java	4 Feb 2002 15:00:51 -0000	1.12
  +++ XNumber.java	22 Mar 2002 01:04:44 -0000	1.13
  @@ -56,9 +56,10 @@
    */
   package org.apache.xpath.objects;
   
  -import org.w3c.dom.*;
  -import java.math.BigDecimal;
  +import javax.xml.transform.TransformerException;
  +import org.apache.xpath.ExpressionOwner;
   import org.apache.xpath.XPathContext;
  +import org.apache.xpath.XPathVisitor;
   
   /**
    * <meta name="usage" content="general"/>
  @@ -82,7 +83,6 @@
       super();
   
       m_val = d;
  -    m_precedence = XObject.ORDER_NUMBER;
     }
     
     /**
  @@ -97,7 +97,6 @@
   
       m_val = num.doubleValue();
       m_obj = num;
  -    m_precedence = XObject.ORDER_NUMBER;
     }
   
     /**
  @@ -424,12 +423,15 @@
       // In order to handle the 'all' semantics of 
       // nodeset comparisons, we always call the 
       // nodeset function.
  -    if (obj2.getType() == XObject.CLASS_NODESET)
  -      return obj2.equals(this);
  -
  +    int t = obj2.getType();
       try
       {
  -      return m_val == obj2.num();
  +	    if (t == XObject.CLASS_NODESET)
  +	      return obj2.equals(this);
  +	    else if(t == XObject.CLASS_BOOLEAN)
  +	      return obj2.bool() == bool();
  +		else
  +	       return m_val == obj2.num();
       }
       catch(javax.xml.transform.TransformerException te)
       {
  @@ -449,5 +451,14 @@
     {
       return true;
     }
  +  
  +  /**
  +   * @see XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
  +   */
  +  public void callVisitors(ExpressionOwner owner, XPathVisitor visitor)
  +  {
  +  	visitor.visitNumberLiteral(owner, this);
  +  }
  +
   
   }
  
  
  
  1.19      +50 -29    xml-xalan/java/src/org/apache/xpath/objects/XObject.java
  
  Index: XObject.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/objects/XObject.java,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- XObject.java	4 Feb 2002 15:00:51 -0000	1.18
  +++ XObject.java	22 Mar 2002 01:04:44 -0000	1.19
  @@ -66,9 +66,11 @@
   import java.io.Serializable;
   
   import org.apache.xpath.res.XPATHErrorResources;
  +import org.apache.xpath.ExpressionOwner;
   import org.apache.xpath.XPathContext;
   import org.apache.xpath.NodeSetDTM;
   import org.apache.xpath.XPathException;
  +import org.apache.xpath.XPathVisitor;
   import org.apache.xalan.res.XSLMessages;
   import org.apache.xpath.Expression;
   import org.apache.xml.utils.XMLString;
  @@ -88,27 +90,11 @@
      *  @serial  
      */
     protected Object m_obj;  // This may be NULL!!!
  -  
  -  /* Constants for precedence order of object types */
  -  protected static final short ORDER_RTF = 1;
  -  protected static final short ORDER_NODESET = 2;
  -  protected static final short ORDER_BOOLEAN = 3;
  -  protected static final short ORDER_NUMBER = 4;
  -  protected static final short ORDER_STRING = 5;
  -  protected static final short ORDER_OBJECT = -1;
  -  
  -  /**
  -   * The precedence order of this object, according to XSLT rules
  -   */ 
  -  protected short m_precedence;
   
     /**
      * Create an XObject.
      */
  -  public XObject()
  -  {
  -    m_precedence = ORDER_OBJECT;  
  -  }
  +  public XObject(){}
   
     /**
      * Create an XObject.
  @@ -119,7 +105,6 @@
     public XObject(Object obj)
     {
       m_obj = obj;
  -    m_precedence = ORDER_OBJECT;
     }
   
     /**
  @@ -139,6 +124,10 @@
   
     /**
      * Specify if it's OK for detach to release the iterator for reuse.
  +   * This function should be called with a value of false for objects that are 
  +   * stored in variables.
  +   * Calling this with a value of false on a XNodeSet will cause the nodeset 
  +   * to be cached.
      *
      * @param allowRelease true if it is OK for detach to release this iterator
      * for pooling.
  @@ -169,6 +158,13 @@
         m_obj = null;
       }
     }
  +  
  +  /**
  +   * Reset for fresh reuse.
  +   */
  +  public void reset()
  +  {
  +  }
   
     /**
      * Directly call the
  @@ -249,16 +245,6 @@
     {
       return CLASS_UNKNOWN;
     }
  -  
  -  /**
  -   * Get this objects precedence order.
  -   *
  -   * @return precedence order 
  -   */
  -  public short getOrder()
  -  {
  -    return m_precedence;
  -  }
   
     /**
      * Given a request type, return the equivalent string.
  @@ -414,7 +400,6 @@
     }
     
     
  -  
     /**
      * For functions to override.
      *
  @@ -463,6 +448,17 @@
     }
     
     /**
  +   * Get a fresh copy of the object.  For use with variables.
  +   *
  +   * @return This object, unless overridden by subclass.
  +   */
  +  public XObject getFresh()
  +  {
  +    return this;
  +  }
  +
  +  
  +  /**
      * Cast result object to a nodelist. Always issues an error.
      *
      * @return null
  @@ -766,4 +762,29 @@
     {
       fsb.append(str());
     }
  +  
  +  /**
  +   * @see XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
  +   */
  +  public void callVisitors(ExpressionOwner owner, XPathVisitor visitor)
  +  {
  +  	assertion(false, "callVisitors should not be called for this object!!!");
  +  }
  +
  /**
  +   * @see Expression#deepEquals(Expression)
  +   */
  +  public boolean deepEquals(Expression expr)
  +  {
  +  	if(!isSameClass(expr))
  +  		return false;
  +  		
  +  	// If equals at the expression level calls deepEquals, I think we're 
  +  	// still safe from infinite recursion since this object overrides 
  +  	// equals.  I hope.
  +  	if(!this.equals((XObject)expr))
  +  		return false;
  +  		
  +  	return true;
  +  }
  +
   }
  
  
  
  1.20      +1 -2      xml-xalan/java/src/org/apache/xpath/objects/XRTreeFrag.java
  
  Index: XRTreeFrag.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/objects/XRTreeFrag.java,v
  retrieving revision 1.19
  retrieving revision 1.20
  diff -u -r1.19 -r1.20
  --- XRTreeFrag.java	27 Feb 2002 22:22:46 -0000	1.19
  +++ XRTreeFrag.java	22 Mar 2002 01:04:44 -0000	1.20
  @@ -78,7 +78,7 @@
     DTM m_dtm;
     int m_dtmRoot;
     XPathContext m_xctxt;
  -  boolean m_allowRelease = true;
  +  boolean m_allowRelease = false;
   
   //  /**
   //   * Create an XRTreeFrag Object.
  @@ -106,7 +106,6 @@
       m_dtmRoot = root;
       m_xctxt = xctxt;
       m_dtm = xctxt.getDTM(root);
  -    m_precedence = XObject.ORDER_RTF;
     }
     
     /**
  
  
  
  1.5       +22 -1     xml-xalan/java/src/org/apache/xpath/objects/XRTreeFragSelectWrapper.java
  
  Index: XRTreeFragSelectWrapper.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/objects/XRTreeFragSelectWrapper.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- XRTreeFragSelectWrapper.java	28 Jul 2001 00:26:00 -0000	1.4
  +++ XRTreeFragSelectWrapper.java	22 Mar 2002 01:04:44 -0000	1.5
  @@ -53,8 +53,9 @@
     {
       try
       {
  +      m_selected = ((Expression)m_obj).execute(xctxt);
  +      m_selected.allowDetachToRelease(m_allowRelease);
         XRTreeFragSelectWrapper xrtf = (XRTreeFragSelectWrapper)this.clone();
  -      xrtf.m_selected = ((Expression)m_obj).execute(xctxt);
         return xrtf;
       }
       catch(CloneNotSupportedException cnse)
  @@ -62,6 +63,26 @@
         throw new javax.xml.transform.TransformerException(cnse);
       }
       
  +  }
  +  
  +  /**
  +   * Detaches the <code>DTMIterator</code> from the set which it iterated
  +   * over, releasing any computational resources and placing the iterator
  +   * in the INVALID state. After <code>detach</code> has been invoked,
  +   * calls to <code>nextNode</code> or <code>previousNode</code> will
  +   * raise a runtime exception.
  +   * 
  +   * In general, detach should only be called once on the object.
  +   */
  +  public void detach()
  +  {
  +    if(m_allowRelease)
  +    {
  +      m_selected.detach();
  +      m_selected = null;
  +    }
  +    
  +    super.detach();
     }
     
     /**
  
  
  
  1.10      +43 -15    xml-xalan/java/src/org/apache/xpath/objects/XString.java
  
  Index: XString.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/objects/XString.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- XString.java	4 Feb 2002 15:00:51 -0000	1.9
  +++ XString.java	22 Mar 2002 01:04:44 -0000	1.10
  @@ -57,16 +57,18 @@
   package org.apache.xpath.objects;
   
   //import org.w3c.dom.*;
  +import java.util.Locale;
  +
   import org.apache.xml.dtm.DTM;
  -import org.apache.xml.dtm.DTMIterator;
  -import org.apache.xml.dtm.DTMFilter;
  -import org.apache.xpath.XPathContext;
  +import org.apache.xml.utils.XMLCharacterRecognizer;
   import org.apache.xml.utils.XMLString;
   import org.apache.xml.utils.XMLStringFactory;
  -import org.apache.xml.utils.XMLCharacterRecognizer;
  -import org.apache.xml.utils.FastStringBuffer;
  -
  -import java.util.Locale;
  +import org.apache.xpath.ExpressionOwner;
  +import org.apache.xpath.XPathContext;
  +import org.apache.xpath.XPathVisitor;
  +import org.xml.sax.ContentHandler;
  +import org.xml.sax.SAXException;
  +import org.xml.sax.ext.LexicalHandler;
   
   /**
    * <meta name="usage" content="general"/>
  @@ -87,7 +89,6 @@
     protected XString(Object val)
     {
       super(val);
  -    m_precedence = XObject.ORDER_STRING;
     }
   
     /**
  @@ -98,7 +99,6 @@
     public XString(String val)
     {
       super(val);
  -    m_precedence = XObject.ORDER_STRING;
     }
   
     /**
  @@ -399,10 +399,29 @@
       // In order to handle the 'all' semantics of 
       // nodeset comparisons, we always call the 
       // nodeset function.
  -    if (obj2.getType() == XObject.CLASS_NODESET)
  -      return obj2.equals(this);
  +    int t = obj2.getType();
  +    try
  +    {
  +	    if (XObject.CLASS_NODESET == t)
  +	      return obj2.equals(this);
  +	    // If at least one object to be compared is a boolean, then each object 
  +	    // to be compared is converted to a boolean as if by applying the 
  +	    // boolean function. 
  +	    else if(XObject.CLASS_BOOLEAN == t)
  +	    	return obj2.bool() == bool();
  +	    // Otherwise, if at least one object to be compared is a number, then each object 
  +	    // to be compared is converted to a number as if by applying the number function. 
  +	    else if(XObject.CLASS_NUMBER == t)
  +	    	return obj2.num() == num();
  +    }
  +    catch(javax.xml.transform.TransformerException te)
  +    {
  +    	throw new org.apache.xml.utils.WrappedRuntimeException(te);
  +    }
   
  -    return str().equals(obj2.str());
  +    // Otherwise, both objects to be compared are converted to strings as 
  +    // if by applying the string function. 
  +    return xstr().equals(obj2.xstr());
     }
   
     /**
  @@ -411,10 +430,8 @@
      * <code>null</code> and is a <code>String</code> object that represents
      * the same sequence of characters as this object.
      *
  -   * @param   anObject   the object to compare this <code>String</code>
  +   * @param obj2   the object to compare this <code>String</code>
      *                     against.
  -   *
  -   * NEEDSDOC @param obj2
      * @return  <code>true</code> if the <code>String </code>are equal;
      *          <code>false</code> otherwise.
      * @see     java.lang.String#compareTo(java.lang.String)
  @@ -455,6 +472,8 @@
         // nodeset function.
       else if (obj2 instanceof XNodeSet)
         return obj2.equals(this);
  +    else if(obj2 instanceof XNumber)
  +    	return obj2.equals(this);
       else
         return str().equals(obj2.toString());
     }
  @@ -1180,4 +1199,13 @@
   
       return edit ? xsf.newstr(new String(buf, start, d - start)) : this;
     }
  +  
  +  /**
  +   * @see XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
  +   */
  +  public void callVisitors(ExpressionOwner owner, XPathVisitor visitor)
  +  {
  +  	visitor.visitStringLiteral(owner, this);
  +  }
  +
   }
  
  
  
  1.15      +11 -47    xml-xalan/java/src/org/apache/xpath/objects/XStringForFSB.java
  
  Index: XStringForFSB.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/objects/XStringForFSB.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- XStringForFSB.java	5 Feb 2002 18:52:36 -0000	1.14
  +++ XStringForFSB.java	22 Mar 2002 01:04:44 -0000	1.15
  @@ -68,7 +68,6 @@
    */
   public class XStringForFSB extends XString
   {
  -  static long MAX_NO_OVERFLOW_RISK=(Long.MAX_VALUE-'9')/10;
   
     /** The start position in the fsb. */
     int m_start;
  @@ -372,6 +371,8 @@
       {
         return true;
       }
  +    if(obj2.getType() == XObject.CLASS_NUMBER)
  +    	return obj2.equals(this);
   
       String str = obj2.str();
       int n = m_length;
  @@ -458,6 +459,9 @@
   
       if (null == obj2)
         return false;
  +      
  +    if(obj2 instanceof XNumber)
  +    	return obj2.equals(this);
   
         // In order to handle the 'all' semantics of 
         // nodeset comparisons, we always call the 
  @@ -979,8 +983,6 @@
      * the performance of this operation. Does XString.toDouble constitute
      * any measurable percentage of our typical runtime? I suspect not!
      *
  -   * %REVIEW%
  -   *
      * @return A double value representation of the string, or return Double.NaN 
      * if the string can not be converted.  */
     public double toDouble()
  @@ -998,7 +1000,6 @@
       int[] digitsFound={0,0}; // intpart,fracpart
       int digitType=0;    // Index to which kind of digit we're accumulating
       double doubleResult;
  -    int overflow=0;
       
       // Scan past leading whitespace characters
       while(start< end &&
  @@ -1044,21 +1045,8 @@
         case '7':
         case '8':
         case '9':
  -	// We have a potential overflow issue that we need
  -	// to guard against. See Bugzilla 5346.
  -	//
  -	// %REVIEW% MUST BE RECONSIDERED. I _think_ the truncation of
  -	// the 64-bit long before it overflows is well within the acceptable
  -	// error range of the double's 53-bit mantissa...
  -	if(longResult>MAX_NO_OVERFLOW_RISK)
  -	{
  -	  if(digitType==0) ++overflow;
  -	}
  -	else
  -	{
  -	  longResult=longResult*10 + (c - '0');
  -	  ++digitsFound[digitType]; // Remember scaling
  -	}
  +        longResult = longResult * 10 + (c - '0'); // Accumulate as int
  +        ++digitsFound[digitType]; // Remember scaling
   	break;
   
         default:
  @@ -1076,34 +1064,10 @@
       // the same thing.
                   
       long scale=1;               // AFAIK, java doesn't have an easier 10^n operation
  -    
  -    doubleResult=(double)longResult;
  -    if(digitsFound[1]==0)		// Integer overflow scaling
  -    {
  -	    for(int i=overflow;i>0;--i) 
  - 		     scale*=10;
  -	 	doubleResult*=scale;
  -    }
  -    else 						// Fractional-part scaling
  -    {
  -    	// Complication: In values <0, the fractional part may want to be divided
  -    	// by a power of 10 too large to fit in a long! In that case, resort to 
  -    	// successive divisions. 
  -    	//
  -    	// %REVIEW% This can't be an optimal solution. Need a better algorithm.
  - 	    int i=digitsFound[1];
  - 	    while(i>0)
  - 	    {
  - 	    	int j=(i<18) ? i : 18;
  - 	    	i-=j;
  - 	    	
  -		    for(scale=1;j>0;--j) 
  -		    	scale*=10;
  - 	     
  -		    doubleResult/=scale;
  - 	    }
  -    }
  -
  +    for(int i=digitsFound[1];i>0;--i) 
  +      scale*=10;
  +                
  +    doubleResult=((double)longResult)/scale;
                   
       if(isNegative)
         doubleResult *= -1;
  
  
  
  1.6       +3 -1      xml-xalan/java/src/org/apache/xpath/operations/Bool.java
  
  Index: Bool.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/operations/Bool.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- Bool.java	12 Jun 2001 19:16:55 -0000	1.5
  +++ Bool.java	22 Mar 2002 01:04:45 -0000	1.6
  @@ -56,6 +56,8 @@
    */
   package org.apache.xpath.operations;
   
  +import org.apache.xpath.Expression;
  +import org.apache.xpath.XPathVisitor;
   import org.apache.xpath.objects.XObject;
   import org.apache.xpath.objects.XBoolean;
   import org.apache.xpath.XPathContext;
  @@ -99,5 +101,5 @@
     {
       return m_right.bool(xctxt);
     }
  -
  +
   }
  
  
  
  1.6       +28 -5     xml-xalan/java/src/org/apache/xpath/operations/Equals.java
  
  Index: Equals.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/operations/Equals.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- Equals.java	4 Feb 2002 15:00:51 -0000	1.5
  +++ Equals.java	22 Mar 2002 01:04:45 -0000	1.6
  @@ -56,8 +56,10 @@
    */
   package org.apache.xpath.operations;
   
  -import org.apache.xpath.objects.XObject;
  +import javax.xml.transform.TransformerException;
  +import org.apache.xpath.XPathContext;
   import org.apache.xpath.objects.XBoolean;
  +import org.apache.xpath.objects.XObject;
   
   /**
    * The '=' operation expression executer.
  @@ -79,9 +81,30 @@
     public XObject operate(XObject left, XObject right)
             throws javax.xml.transform.TransformerException
     {
  -    if (right.getOrder() > left.getOrder())
  -      return left.equals(right) ? XBoolean.S_TRUE : XBoolean.S_FALSE;
  -    else
  -      return right.equals(left) ? XBoolean.S_TRUE : XBoolean.S_FALSE;
  +    return left.equals(right) ? XBoolean.S_TRUE : XBoolean.S_FALSE;
  +  }
  +  
  +  /**
  +   * Execute a binary operation by calling execute on each of the operands,
  +   * and then calling the operate method on the derived class.
  +   *
  +   *
  +   * @param xctxt The runtime execution context.
  +   *
  +   * @return The XObject result of the operation.
  +   *
  +   * @throws javax.xml.transform.TransformerException
  +   */
  +  public boolean bool(XPathContext xctxt)
  +          throws javax.xml.transform.TransformerException
  +  {
  +    XObject left = m_left.execute(xctxt, true);
  +    XObject right = m_right.execute(xctxt, true);
  +
  +    boolean result = left.equals(right) ? true : false;
  +	left.detach();
  +	right.detach();
  +    return result;
     }
  +
   }
  
  
  
  1.9       +79 -7     xml-xalan/java/src/org/apache/xpath/operations/Operation.java
  
  Index: Operation.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/operations/Operation.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- Operation.java	6 Nov 2001 17:38:21 -0000	1.8
  +++ Operation.java	22 Mar 2002 01:04:45 -0000	1.9
  @@ -56,17 +56,19 @@
    */
   package org.apache.xpath.operations;
   
  +import java.util.Vector;
  +
  +import javax.xml.transform.TransformerException;
   import org.apache.xpath.Expression;
  -import org.apache.xpath.XPath;
  +import org.apache.xpath.ExpressionOwner;
   import org.apache.xpath.XPathContext;
  +import org.apache.xpath.XPathVisitor;
   import org.apache.xpath.objects.XObject;
   
  -import org.w3c.dom.Node;
  -
   /**
    * The baseclass for a binary operation.
    */
  -public class Operation extends Expression
  +public class Operation extends Expression implements ExpressionOwner
   {
   
     /** The left operand expression.
  @@ -123,6 +125,8 @@
     {
       m_left = l;
       m_right = r;
  +    l.exprSetParent(this);
  +    r.exprSetParent(this);
     }
   
     /**
  @@ -140,10 +144,13 @@
             throws javax.xml.transform.TransformerException
     {
   
  -    XObject left = m_left.execute(xctxt);
  -    XObject right = m_right.execute(xctxt);
  +    XObject left = m_left.execute(xctxt, true);
  +    XObject right = m_right.execute(xctxt, true);
   
  -    return operate(left, right);
  +    XObject result = operate(left, right);
  +    left.detach();
  +    right.detach();
  +    return result;
     }
   
     /**
  @@ -174,5 +181,70 @@
     public Expression getRightOperand(){
       return m_right;
     }
  +  
  +  class LeftExprOwner implements ExpressionOwner
  +  {
  +    /**
  +     * @see ExpressionOwner#getExpression()
  +     */
  +    public Expression getExpression()
  +    {
  +      return m_left;
  +    }
  +
  +    /**
  +     * @see ExpressionOwner#setExpression(Expression)
  +     */
  +    public void setExpression(Expression exp)
  +    {
  +    	exp.exprSetParent(Operation.this);
  +    	m_left = exp;
  +    }
  +  }
  +
  +  /**
  +   * @see XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
  +   */
  +  public void callVisitors(ExpressionOwner owner, XPathVisitor visitor)
  +  {
  +  	if(visitor.visitBinaryOperation(owner, this))
  +  	{
  +  		m_left.callVisitors(new LeftExprOwner(), visitor);
  +  		m_right.callVisitors(this, visitor);
  +  	}
  +  }
  +
  +  /**
  +   * @see ExpressionOwner#getExpression()
  +   */
  +  public Expression getExpression()
  +  {
  +    return m_right;
  +  }
  +
  +  /**
  +   * @see ExpressionOwner#setExpression(Expression)
  +   */
  +  public void setExpression(Expression exp)
  +  {
  +  	exp.exprSetParent(this);
  +  	m_right = exp;
  +  }
   
  +  /**
  +   * @see Expression#deepEquals(Expression)
  +   */
  +  public boolean deepEquals(Expression expr)
  +  {
  +  	if(!isSameClass(expr))
  +  		return false;
  +  		
  +  	if(!m_left.deepEquals(((Operation)expr).m_left))
  +  		return false;
  +  		
  +  	if(!m_right.deepEquals(((Operation)expr).m_right))
  +  		return false;
  +  		
  +  	return true;
  +  }
   }
  
  
  
  1.9       +51 -4     xml-xalan/java/src/org/apache/xpath/operations/UnaryOperation.java
  
  Index: UnaryOperation.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/operations/UnaryOperation.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- UnaryOperation.java	6 Nov 2001 17:38:21 -0000	1.8
  +++ UnaryOperation.java	22 Mar 2002 01:04:45 -0000	1.9
  @@ -56,17 +56,19 @@
    */
   package org.apache.xpath.operations;
   
  +import java.util.Vector;
  +
  +import javax.xml.transform.TransformerException;
   import org.apache.xpath.Expression;
  -import org.apache.xpath.XPath;
   import org.apache.xpath.XPathContext;
  +import org.apache.xpath.XPathVisitor;
  +import org.apache.xpath.ExpressionOwner;
   import org.apache.xpath.objects.XObject;
   
  -import org.w3c.dom.Node;
  -
   /**
    * The unary operation base class.
    */
  -public abstract class UnaryOperation extends Expression
  +public abstract class UnaryOperation extends Expression implements ExpressionOwner
   {
   
     /** The operand for the operation.
  @@ -113,6 +115,7 @@
     public void setRight(Expression r)
     {
       m_right = r;
  +    r.exprSetParent(this);
     }
   
     /**
  @@ -150,5 +153,49 @@
     public Expression getOperand(){
       return m_right;
     }
  +  
  +  /**
  +   * @see XPathVisitable#callVisitors(XPathVisitor)
  +   */
  +  public void callVisitors(ExpressionOwner owner, XPathVisitor visitor)
  +  {
  +  	if(visitor.visitUnaryOperation(owner, this))
  +  	{
  +  		m_right.callVisitors(this, visitor);
  +  	}
  +  }
  +
  +
  +  /**
  +   * @see ExpressionOwner#getExpression()
  +   */
  +  public Expression getExpression()
  +  {
  +    return m_right;
  +  }
  +
  +  /**
  +   * @see ExpressionOwner#setExpression(Expression)
  +   */
  +  public void setExpression(Expression exp)
  +  {
  +  	exp.exprSetParent(this);
  +  	m_right = exp;
  +  }
  +  
  +  /**
  +   * @see Expression#deepEquals(Expression)
  +   */
  +  public boolean deepEquals(Expression expr)
  +  {
  +  	if(!isSameClass(expr))
  +  		return false;
  +  		
  +  	if(!m_right.deepEquals(((UnaryOperation)expr).m_right))
  +  		return false;
  +  		
  +  	return true;
  +  }
   
  +
   }
  
  
  
  1.17      +220 -52   xml-xalan/java/src/org/apache/xpath/operations/Variable.java
  
  Index: Variable.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/operations/Variable.java,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- Variable.java	26 Aug 2001 05:07:04 -0000	1.16
  +++ Variable.java	22 Mar 2002 01:04:45 -0000	1.17
  @@ -56,24 +56,34 @@
    */
   package org.apache.xpath.operations;
   
  -import javax.xml.transform.TransformerException;
  +import java.util.Vector;
   
  +import javax.xml.transform.TransformerException;
  +import org.apache.xalan.res.XSLMessages;
  +import org.apache.xalan.templates.ElemTemplateElement;
  +import org.apache.xalan.templates.ElemVariable;
  +import org.apache.xalan.templates.Stylesheet;
  +import org.apache.xml.utils.PrefixResolver;
   import org.apache.xml.utils.QName;
   import org.apache.xpath.Expression;
  +import org.apache.xpath.ExpressionNode;
  +import org.apache.xpath.ExpressionOwner;
   import org.apache.xpath.XPath;
   import org.apache.xpath.XPathContext;
  -import org.apache.xpath.objects.XObject;
  +import org.apache.xpath.XPathVisitor;
  +import org.apache.xpath.axes.PathComponent;
  +import org.apache.xpath.axes.WalkerFactory;
   import org.apache.xpath.objects.XNodeSet;
  -
  -import org.w3c.dom.Node;
  -
  +import org.apache.xpath.objects.XObject;
   import org.apache.xpath.res.XPATHErrorResources;
  -import org.apache.xalan.res.XSLMessages;
  +import org.xml.sax.ContentHandler;
  +import org.xml.sax.SAXException;
  +
   
   /**
    * The variable reference expression executer.
    */
  -public class Variable extends Expression
  +public class Variable extends Expression implements PathComponent
   {
     /** Tell if fixupVariables was called.
      *  @serial   */
  @@ -90,6 +100,51 @@
      */
     protected int m_index;
     
  +  /**
  +   * Set the index for the variable into the stack.  For advanced use only. You 
  +   * must know what you are doing to use this.
  +   * 
  +   * @param index a global or local index.
  +   */
  +  public void setIndex(int index)
  +  {
  +  	m_index = index;
  +  }
  +  
  +  /**
  +   * Set the index for the variable into the stack.  For advanced use only.
  +   * 
  +   * @return index a global or local index.
  +   */
  +  public int getIndex()
  +  {
  +  	return m_index;
  +  }
  +  
  +  /**
  +   * Set whether or not this is a global reference.  For advanced use only.
  +   * 
  +   * @param isGlobal true if this should be a global variable reference.
  +   */
  +  public void setIsGlobal(boolean isGlobal)
  +  {
  +  	m_isGlobal = isGlobal;
  +  }
  +  
  +  /**
  +   * Set the index for the variable into the stack.  For advanced use only.
  +   * 
  +   * @return true if this should be a global variable reference.
  +   */
  +  public boolean getGlobal()
  +  {
  +  	return m_isGlobal;
  +  }
  +
  +  
  +  
  +
  +  
     protected boolean m_isGlobal = false;
     
     /**
  @@ -106,6 +161,7 @@
     {
       m_fixUpWasCalled = true;
       int sz = vars.size();
  +
       for (int i = vars.size()-1; i >= 0; i--) 
       {
         QName qn = (QName)vars.elementAt(i);
  @@ -126,10 +182,11 @@
           return;
         }
       }
  +    
       java.lang.String msg = XSLMessages.createXPATHMessage(XPATHErrorResources.ER_COULD_NOT_FIND_VAR, 
                                                new Object[]{m_qname.toString()});
                                                
  -    TransformerException te = new TransformerException(msg, m_slocator);
  +    TransformerException te = new TransformerException(msg, this);
                                                
       throw new org.apache.xml.utils.WrappedRuntimeException(te);
       
  @@ -145,6 +202,35 @@
     {
       m_qname = qname;
     }
  +  
  +  /**
  +   * Get the qualified name of the variable.
  +   *
  +   * @return A non-null reference to a qualified name.
  +   */
  +  public QName getQName()
  +  {
  +    return m_qname;
  +  }
  +  
  +  /**
  +   * Execute an expression in the XPath runtime context, and return the
  +   * result of the expression.
  +   *
  +   *
  +   * @param xctxt The XPath runtime context.
  +   *
  +   * @return The result of the expression in the form of a <code>XObject</code>.
  +   *
  +   * @throws javax.xml.transform.TransformerException if a runtime exception
  +   *         occurs.
  +   */
  +  public XObject execute(XPathContext xctxt)
  +    throws javax.xml.transform.TransformerException
  +  {
  +  	return execute(xctxt, false);
  +  }
  +
   
     /**
      * Dereference the variable, and return the reference value.  Note that lazy 
  @@ -158,8 +244,9 @@
      *
      * @throws javax.xml.transform.TransformerException
      */
  -  public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
  +  public XObject execute(XPathContext xctxt, boolean destructiveOK) throws javax.xml.transform.TransformerException
     {
  +  	org.apache.xml.utils.PrefixResolver xprefixResolver = xctxt.getNamespaceContext();
   
       // Is the variable fetched always the same?
       // XObject result = xctxt.getVariable(m_qname);
  @@ -167,9 +254,9 @@
       {    
         XObject result;
         if(m_isGlobal)
  -        result = xctxt.getVarStack().getGlobalVariable(xctxt, m_index);
  +        result = xctxt.getVarStack().getGlobalVariable(xctxt, m_index, destructiveOK);
         else
  -        result = xctxt.getVarStack().getLocalVariable(xctxt, m_index);
  +        result = xctxt.getVarStack().getLocalVariable(xctxt, m_index, destructiveOK);
     
         if (null == result)
         {
  @@ -191,60 +278,74 @@
         // pending some bright light going off in my head.  Some sort of callback?
         synchronized(this)
         {
  -        org.apache.xml.utils.PrefixResolver prefixResolver = xctxt.getNamespaceContext();
  +      	org.apache.xalan.templates.ElemVariable vvar= getElemVariable();
  +      	if(null != vvar)
  +      	{
  +          m_index = vvar.getIndex();
  +          m_isGlobal = vvar.getIsTopLevel();
  +          m_fixUpWasCalled = true;
  +          return execute(xctxt);
  +      	}
  +      }
  +      throw new javax.xml.transform.TransformerException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_VAR_NOT_RESOLVABLE, new Object[]{m_qname.toString()})); //"Variable not resolvable: "+m_qname);
  +    }
  +  }
  +  
  +  /**
  +   * Get the XSLT ElemVariable that this sub-expression references.  In order for 
  +   * this to work, the SourceLocator must be the owning ElemTemplateElement.
  +   * @return The dereference to the ElemVariable, or null if not found.
  +   */
  +  public org.apache.xalan.templates.ElemVariable getElemVariable()
  +  {
  +  	
  +    // Get the current ElemTemplateElement, and then walk backwards in 
  +    // document order, searching 
  +    // for an xsl:param element or xsl:variable element that matches our 
  +    // qname.  If we reach the top level, use the StylesheetRoot's composed
  +    // list of top level variables and parameters.
  +    
  +    org.apache.xpath.ExpressionNode owner = getExpressionOwner();
   
  -        // Get the current ElemTemplateElement, which must be pushed in as the 
  -        // prefix resolver, and then walk backwards in document order, searching 
  -        // for an xsl:param element or xsl:variable element that matches our 
  -        // qname.  If we reach the top level, use the StylesheetRoot's composed
  -        // list of top level variables and parameters.
  +    if (null != owner && owner instanceof org.apache.xalan.templates.ElemTemplateElement)
  +    {
   
  -        if (prefixResolver instanceof org.apache.xalan.templates.ElemTemplateElement)
  -        {
  +      org.apache.xalan.templates.ElemVariable vvar;
   
  -          org.apache.xalan.templates.ElemVariable vvar;
  +      org.apache.xalan.templates.ElemTemplateElement prev = 
  +        (org.apache.xalan.templates.ElemTemplateElement) owner;
   
  -          org.apache.xalan.templates.ElemTemplateElement prev = 
  -            (org.apache.xalan.templates.ElemTemplateElement) prefixResolver;
  +      if (!(prev instanceof org.apache.xalan.templates.Stylesheet))
  +      {            
  +        while ( !(prev.getParentNode() instanceof org.apache.xalan.templates.Stylesheet) )
  +        {
  +          org.apache.xalan.templates.ElemTemplateElement savedprev = prev;
   
  -          if (!(prev instanceof org.apache.xalan.templates.Stylesheet))
  -          {            
  -            while ( !(prev.getParentNode() instanceof org.apache.xalan.templates.Stylesheet) )
  +          while (null != (prev = prev.getPreviousSiblingElem()))
  +          {
  +            if(prev instanceof org.apache.xalan.templates.ElemVariable)
               {
  -              org.apache.xalan.templates.ElemTemplateElement savedprev = prev;
  -
  -              while (null != (prev = prev.getPreviousSiblingElem()))
  +              vvar = (org.apache.xalan.templates.ElemVariable) prev;
  +            
  +              if (vvar.getName().equals(m_qname))
                 {
  -                if(prev instanceof org.apache.xalan.templates.ElemVariable)
  -                {
  -                  vvar = (org.apache.xalan.templates.ElemVariable) prev;
  -                
  -                  if (vvar.getName().equals(m_qname))
  -                  {
  -                    m_index = vvar.getIndex();
  -                    m_isGlobal = false;
  -                    m_fixUpWasCalled = true;
  -                    return execute(xctxt);
  -                  }
  -                }
  +                return vvar;
                 }
  -              prev = savedprev.getParentElem();
               }
             }
  -
  -          vvar = prev.getStylesheetRoot().getVariableOrParamComposed(m_qname);
  -          if (null != vvar)
  -          {
  -            m_index = vvar.getIndex();
  -            m_isGlobal = true;
  -            m_fixUpWasCalled = true;
  -            return execute(xctxt);
  -          }
  -
  +          prev = savedprev.getParentElem();
           }
         }
  -      throw new javax.xml.transform.TransformerException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_VAR_NOT_RESOLVABLE, new Object[]{m_qname.toString()})); //"Variable not resolvable: "+m_qname);
  +
  +      vvar = prev.getStylesheetRoot().getVariableOrParamComposed(m_qname);
  +      if (null != vvar)
  +      {
  +        return vvar;;
  +      }
  +
       }
  +    return null;
  +
     }
     
     /**
  @@ -259,5 +360,72 @@
     {
       return true;
     }
  +  
  +  /** 
  +   * Get the analysis bits for this walker, as defined in the WalkerFactory.
  +   * @return One of WalkerFactory#BIT_DESCENDANT, etc.
  +   */
  +  public int getAnalysisBits()
  +  {
  +  	org.apache.xalan.templates.ElemVariable vvar = getElemVariable();
  +  	if(null != vvar)
  +  	{
  +  		XPath xpath = vvar.getSelect();
  +  		if(null != xpath)
  +  		{
  +	  		Expression expr = xpath.getExpression();
  +	  		if(null != expr && expr instanceof PathComponent)
  +	  		{
  +	  			return ((PathComponent)expr).getAnalysisBits();
  +	  		}
  +  		}
  +  	}
  +    return WalkerFactory.BIT_FILTER;
  +  }
  +
  +
  +  /**
  +   * @see XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
  +   */
  +  public void callVisitors(ExpressionOwner owner, XPathVisitor visitor)
  +  {
  +  	visitor.visitVariableRef(owner, this);
  +  }
  +
  /**
  +   * @see Expression#deepEquals(Expression)
  +   */
  +  public boolean deepEquals(Expression expr)
  +  {
  +  	if(!isSameClass(expr))
  +  		return false;
  +  		
  +  	if(!m_qname.equals(((Variable)expr).m_qname))
  +  		return false;
  +  		
  +  	// We have to make sure that the qname really references 
  +  	// the same variable element.
  +    if(getElemVariable() != ((Variable)expr).getElemVariable())
  +    	return false;
  +  		
  +  	return true;
  +  }
  +  
  +  static final java.lang.String PSUEDOVARNAMESPACE = "http://xml.apache.org/xalan/psuedovar";
  +  
  +  /**
  +   * Tell if this is a psuedo variable reference, declared by Xalan instead 
  +   * of by the user.
  +   */
  +  public boolean isPsuedoVarRef()
  +  {
  +  	java.lang.String ns = m_qname.getNamespaceURI();
  +  	if((null != ns) && ns.equals(PSUEDOVARNAMESPACE))
  +  	{
  +  		if(m_qname.getLocalName().startsWith("#"))
  +  			return true;
  +  	}
  +  	return false;
  +  }
  +  
   
   }
  
  
  
  1.2       +56 -0     xml-xalan/java/src/org/apache/xpath/operations/VariableSafeAbsRef.java
  
  
  
  
  1.9       +39 -4     xml-xalan/java/src/org/apache/xpath/patterns/FunctionPattern.java
  
  Index: FunctionPattern.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/patterns/FunctionPattern.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- FunctionPattern.java	12 Jun 2001 19:17:01 -0000	1.8
  +++ FunctionPattern.java	22 Mar 2002 01:04:45 -0000	1.9
  @@ -56,14 +56,18 @@
    */
   package org.apache.xpath.patterns;
   
  -import org.apache.xpath.XPath;
  +import java.util.Vector;
  +
  +import javax.xml.transform.TransformerException;
  +import org.apache.xml.dtm.DTM;
  +import org.apache.xml.dtm.DTMIterator;
   import org.apache.xpath.Expression;
  +import org.apache.xpath.ExpressionOwner;
   import org.apache.xpath.XPathContext;
  +import org.apache.xpath.XPathVisitor;
   import org.apache.xpath.objects.XNumber;
   import org.apache.xpath.objects.XObject;
  -import org.apache.xml.dtm.DTM;
  -import org.apache.xml.dtm.DTMIterator;
  -import org.apache.xml.dtm.Axis;
  +import org.apache.xpath.patterns.StepPattern.PredOwner;
   
   /**
    * <meta name="usage" content="advanced"/>
  @@ -252,4 +256,35 @@
   
       return score;
     }
  +  
  +  class FunctionOwner implements ExpressionOwner
  +  {
  +    /**
  +     * @see ExpressionOwner#getExpression()
  +     */
  +    public Expression getExpression()
  +    {
  +      return m_functionExpr;
  +    }
  +
  +
  +    /**
  +     * @see ExpressionOwner#setExpression(Expression)
  +     */
  +    public void setExpression(Expression exp)
  +    {
  +    	exp.exprSetParent(FunctionPattern.this);
  +    	m_functionExpr = exp;
  +    }
  +  }
  +  
  +  /**
  +   * Call the visitor for the function.
  +   */
  +  protected void callSubtreeVisitors(XPathVisitor visitor)
  +  {
  +    m_functionExpr.callVisitors(new FunctionOwner(), visitor);
  +    super.callSubtreeVisitors(visitor);
  +  }
  +
   }
  
  
  
  1.22      +56 -7     xml-xalan/java/src/org/apache/xpath/patterns/NodeTest.java
  
  Index: NodeTest.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/patterns/NodeTest.java,v
  retrieving revision 1.21
  retrieving revision 1.22
  diff -u -r1.21 -r1.22
  --- NodeTest.java	12 Jun 2001 19:17:02 -0000	1.21
  +++ NodeTest.java	22 Mar 2002 01:04:45 -0000	1.22
  @@ -56,17 +56,19 @@
    */
   package org.apache.xpath.patterns;
   
  -import org.apache.xpath.compiler.OpCodes;
  -import org.apache.xpath.XPath;
  +import java.util.Vector;
  +
  +import javax.xml.transform.TransformerException;
  +import org.apache.xml.dtm.DTM;
  +import org.apache.xml.dtm.DTMFilter;
  +import org.apache.xml.dtm.ref.ExpandedNameTable;
   import org.apache.xpath.Expression;
  +import org.apache.xpath.ExpressionOwner;
  +import org.apache.xpath.XPath;
   import org.apache.xpath.XPathContext;
  +import org.apache.xpath.XPathVisitor;
   import org.apache.xpath.objects.XNumber;
   import org.apache.xpath.objects.XObject;
  -import org.apache.xpath.WhitespaceStrippingElementMatcher;
  -import org.apache.xml.utils.PrefixResolver;
  -import org.apache.xml.dtm.DTMFilter;
  -import org.apache.xml.dtm.DTM;
  -import org.apache.xml.dtm.ref.ExpandedNameTable;
   
   /**
    * <meta name="usage" content="advanced"/>
  @@ -248,6 +250,45 @@
     {
       initNodeTest(whatToShow);
     }
  +  
  +  /**
  +   * @see Expression#deepEquals(Expression)
  +   */
  +  public boolean deepEquals(Expression expr)
  +  {
  +  	if(!isSameClass(expr))
  +  		return false;
  +  		
  +  	NodeTest nt = (NodeTest)expr;
  +
  +  	if(null != nt.m_name)
  +  	{
  +  		if(null == m_name)
  +  			return false;
  +  		else if(!nt.m_name.equals(m_name))
  +  			return false;
  +  	}
  +  	else if(null != m_name)
  +  		return false;
  +
  +  	if(null != nt.m_namespace)
  +  	{
  +  		if(null == m_namespace)
  +  			return false;
  +  		else if(!nt.m_namespace.equals(m_namespace))
  +  			return false;
  +  	}
  +  	else if(null != m_namespace)
  +  		return false;
  +  		  		
  +  	if(m_whatToShow != nt.m_whatToShow)
  +  		return false;
  +  		
  +  	if(m_isTotallyWild != nt.m_isTotallyWild)
  +  		return false;
  +
  +	return true;
  +  }
   
     /**
      * Null argument constructor.
  @@ -679,4 +720,12 @@
       // no-op
     }
   
  +  /**
  +   * @see XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
  +   */
  +  public void callVisitors(ExpressionOwner owner, XPathVisitor visitor)
  +  {
  +  	assertion(false, "callVisitors should not be called for this object!!!");  	
  +  }
  +
   }
  
  
  
  1.24      +136 -7    xml-xalan/java/src/org/apache/xpath/patterns/StepPattern.java
  
  Index: StepPattern.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/patterns/StepPattern.java,v
  retrieving revision 1.23
  retrieving revision 1.24
  diff -u -r1.23 -r1.24
  --- StepPattern.java	1 Aug 2001 04:20:35 -0000	1.23
  +++ StepPattern.java	22 Mar 2002 01:04:45 -0000	1.24
  @@ -56,22 +56,26 @@
    */
   package org.apache.xpath.patterns;
   
  +import java.util.Vector;
  +
  +import javax.xml.transform.TransformerException;
  +import org.apache.xml.dtm.Axis;
  +import org.apache.xml.dtm.DTM;
  +import org.apache.xml.dtm.DTMAxisTraverser;
  +import org.apache.xml.dtm.DTMFilter;
   import org.apache.xpath.Expression;
  -import org.apache.xpath.objects.XObject;
  +import org.apache.xpath.ExpressionOwner;
   import org.apache.xpath.XPathContext;
  -import org.apache.xml.utils.PrefixResolver;
  +import org.apache.xpath.XPathVisitor;
   import org.apache.xpath.axes.SubContextList;
   import org.apache.xpath.compiler.PsuedoNames;
  -import org.apache.xml.dtm.DTM;
  -import org.apache.xml.dtm.DTMFilter;
  -import org.apache.xml.dtm.DTMAxisTraverser;
  -import org.apache.xml.dtm.Axis;
  +import org.apache.xpath.objects.XObject;
   
   /**
    * <meta name="usage" content="advanced"/>
    * This class represents a single pattern match step.
    */
  -public class StepPattern extends NodeTest implements SubContextList
  +public class StepPattern extends NodeTest implements SubContextList, ExpressionOwner
   {
   
     /** The axis for this test. */
  @@ -219,6 +223,7 @@
     {
   
       m_relativePathPattern = expr;
  +    expr.exprSetParent(this);
   
       calcScore();
     }
  @@ -317,6 +322,13 @@
     {
   
       m_predicates = predicates;
  +    if(null != predicates)
  +    {
  +    	for(int i = 0; i < predicates.length; i++)
  +    	{
  +    		predicates[i].exprSetParent(this);
  +    	}
  +    }
   
       calcScore();
     }
  @@ -958,5 +970,122 @@
     {
       return m_axis;
     }
  +  
  +  class PredOwner implements ExpressionOwner
  +  {
  +  	int m_index;
  +  	
  +  	PredOwner(int index)
  +  	{
  +  		m_index = index;
  +  	}
  +  	
  +    /**
  +     * @see ExpressionOwner#getExpression()
  +     */
  +    public Expression getExpression()
  +    {
  +      return m_predicates[m_index];
  +    }
  +
  +
  +    /**
  +     * @see ExpressionOwner#setExpression(Expression)
  +     */
  +    public void setExpression(Expression exp)
  +    {
  +    	exp.exprSetParent(StepPattern.this);
  +    	m_predicates[m_index] = exp;
  +    }
  +  }
  +  
  +  /**
  +   * @see XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
  +   */
  +  public void callVisitors(ExpressionOwner owner, XPathVisitor visitor)
  +  {
  +  	 	if(visitor.visitMatchPattern(owner, this))
  +  	 	{
  +  	 		callSubtreeVisitors(visitor);
  +  	 	}
  +  }
  +
  +  /**
  +   * Call the visitors on the subtree.  Factored out from callVisitors 
  +   * so it may be called by derived classes.
  +   */
  +  protected void callSubtreeVisitors(XPathVisitor visitor)
  +  {
  +    if (null != m_predicates)
  +    {
  +      int n = m_predicates.length;
  +      for (int i = 0; i < n; i++)
  +      {
  +        ExpressionOwner predOwner = new PredOwner(i);
  +        if (visitor.visitPredicate(predOwner, m_predicates[i]))
  +        {
  +          m_predicates[i].callVisitors(predOwner, visitor);
  +        }
  +      }
  +    }
  +    if (null != m_relativePathPattern)
  +    {
  +      m_relativePathPattern.callVisitors(this, visitor);
  +    }
  +  }
  +
  +
  +  /**
  +   * @see ExpressionOwner#getExpression()
  +   */
  +  public Expression getExpression()
  +  {
  +    return m_relativePathPattern;
  +  }
  +
  +  /**
  +   * @see ExpressionOwner#setExpression(Expression)
  +   */
  +  public void setExpression(Expression exp)
  +  {
  +    exp.exprSetParent(this);
  +  	m_relativePathPattern = (StepPattern)exp;
  +  }
  +  
  +  /**
  +   * @see Expression#deepEquals(Expression)
  +   */
  +  public boolean deepEquals(Expression expr)
  +  {
  +  	if(!super.deepEquals(expr))
  +  		return false;
  +  		
  +  	StepPattern sp = (StepPattern)expr;
  +  	
  +    if (null != m_predicates)
  +    {
  +        int n = m_predicates.length;
  +        if ((null == sp.m_predicates) || (sp.m_predicates.length != n))
  +              return false;
  +        for (int i = 0; i < n; i++)
  +        {
  +          if (!m_predicates[i].deepEquals(sp.m_predicates[i]))
  +          	return false; 
  +        }
  +    }
  +    else if (null != sp.m_predicates)
  +    	return false;
  +  		
  +  	if(null != m_relativePathPattern)
  +  	{
  +  		if(!m_relativePathPattern.deepEquals(sp.m_relativePathPattern))
  +  			return false;
  +  	}
  +  	else if(sp.m_relativePathPattern != null)
  +  		return false;
  +  		
  +  	return true;
  +  }
   
  +
   }
  
  
  
  1.9       +88 -0     xml-xalan/java/src/org/apache/xpath/patterns/UnionPattern.java
  
  Index: UnionPattern.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/patterns/UnionPattern.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- UnionPattern.java	12 Jun 2001 19:17:02 -0000	1.8
  +++ UnionPattern.java	22 Mar 2002 01:04:45 -0000	1.9
  @@ -56,8 +56,13 @@
    */
   package org.apache.xpath.patterns;
   
  +import java.util.Vector;
  +
  +import javax.xml.transform.TransformerException;
   import org.apache.xpath.Expression;
  +import org.apache.xpath.ExpressionOwner;
   import org.apache.xpath.XPathContext;
  +import org.apache.xpath.XPathVisitor;
   import org.apache.xpath.objects.XObject;
   
   /**
  @@ -113,6 +118,14 @@
     public void setPatterns(StepPattern[] patterns)
     {
       m_patterns = patterns;
  +    if(null != patterns)
  +    {
  +    	for(int i = 0; i < patterns.length; i++)
  +    	{
  +    		patterns[i].exprSetParent(this);
  +    	}
  +    }
  +    
     }
   
     /**
  @@ -165,4 +178,79 @@
   
       return bestScore;
     }
  +  
  +  class UnionPathPartOwner implements ExpressionOwner
  +  {
  +  	int m_index;
  +  	
  +  	UnionPathPartOwner(int index)
  +  	{
  +  		m_index = index;
  +  	}
  +  	
  +    /**
  +     * @see ExpressionOwner#getExpression()
  +     */
  +    public Expression getExpression()
  +    {
  +      return m_patterns[m_index];
  +    }
  +
  +
  +    /**
  +     * @see ExpressionOwner#setExpression(Expression)
  +     */
  +    public void setExpression(Expression exp)
  +    {
  +    	exp.exprSetParent(UnionPattern.this);
  +    	m_patterns[m_index] = (StepPattern)exp;
  +    }
  +  }
  +  
  +  /**
  +   * @see XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
  +   */
  +  public void callVisitors(ExpressionOwner owner, XPathVisitor visitor)
  +  {
  +  	visitor.visitUnionPattern(owner, this);
  +  	if(null != m_patterns)
  +  	{
  +  		int n = m_patterns.length;
  +  		for(int i = 0; i < n; i++)
  +  		{
  +  			m_patterns[i].callVisitors(new UnionPathPartOwner(i), visitor);
  +  		}
  +  	}
  +  }
  +  
  +  /**
  +   * @see Expression#deepEquals(Expression)
  +   */
  +  public boolean deepEquals(Expression expr)
  +  {
  +  	if(!isSameClass(expr))
  +  		return false;
  +  		
  +  	UnionPattern up = (UnionPattern)expr;
  +  		
  +  	if(null != m_patterns)
  +  	{
  +  		int n = m_patterns.length;
  +  		if((null == up.m_patterns) || (up.m_patterns.length != n))
  +  			return false;
  +  			
  +  		for(int i = 0; i < n; i++)
  +  		{
  +  			if(!m_patterns[i].deepEquals(up.m_patterns[i]))
  +  				return false;
  +  		}
  +  	}
  +  	else if(up.m_patterns != null)
  +  		return false;
  +  		
  +  	return true;
  +  	
  +  }
  +
  +
   }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: xalan-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: xalan-cvs-help@xml.apache.org