1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the  "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 *     http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18/*
19 * $Id: WalkingIteratorSorted.java 468655 2006-10-28 07:12:06Z minchau $
20 */
21package org.apache.xpath.axes;
22
23import org.apache.xml.dtm.Axis;
24import org.apache.xml.utils.PrefixResolver;
25import org.apache.xpath.compiler.Compiler;
26
27/**
28 * This class iterates over set of nodes that needs to be sorted.
29 * @xsl.usage internal
30 */
31public class WalkingIteratorSorted extends WalkingIterator
32{
33    static final long serialVersionUID = -4512512007542368213L;
34
35//  /** True if the nodes will be found in document order */
36//  protected boolean m_inNaturalOrder = false;
37
38  /** True if the nodes will be found in document order, and this can
39   * be determined statically. */
40  protected boolean m_inNaturalOrderStatic = false;
41
42  /**
43   * Create a WalkingIteratorSorted object.
44   *
45   * @param nscontext The namespace context for this iterator,
46   * should be OK if null.
47   */
48  public WalkingIteratorSorted(PrefixResolver nscontext)
49  {
50    super(nscontext);
51  }
52
53  /**
54   * Create a WalkingIterator iterator, including creation
55   * of step walkers from the opcode list, and call back
56   * into the Compiler to create predicate expressions.
57   *
58   * @param compiler The Compiler which is creating
59   * this expression.
60   * @param opPos The position of this iterator in the
61   * opcode list from the compiler.
62   * @param shouldLoadWalkers True if walkers should be
63   * loaded, or false if this is a derived iterator and
64   * it doesn't wish to load child walkers.
65   *
66   * @throws javax.xml.transform.TransformerException
67   */
68  WalkingIteratorSorted(
69          Compiler compiler, int opPos, int analysis, boolean shouldLoadWalkers)
70            throws javax.xml.transform.TransformerException
71  {
72    super(compiler, opPos, analysis, shouldLoadWalkers);
73  }
74
75  /**
76   * Returns true if all the nodes in the iteration well be returned in document
77   * order.
78   *
79   * @return true as a default.
80   */
81  public boolean isDocOrdered()
82  {
83    return m_inNaturalOrderStatic;
84  }
85
86
87  /**
88   * Tell if the nodeset can be walked in doc order, via static analysis.
89   *
90   *
91   * @return true if the nodeset can be walked in doc order, without sorting.
92   */
93  boolean canBeWalkedInNaturalDocOrderStatic()
94  {
95
96    if (null != m_firstWalker)
97    {
98      AxesWalker walker = m_firstWalker;
99      int prevAxis = -1;
100      boolean prevIsSimpleDownAxis = true;
101
102      for(int i = 0; null != walker; i++)
103      {
104        int axis = walker.getAxis();
105
106        if(walker.isDocOrdered())
107        {
108          boolean isSimpleDownAxis = ((axis == Axis.CHILD)
109                                   || (axis == Axis.SELF)
110                                   || (axis == Axis.ROOT));
111          // Catching the filtered list here is only OK because
112          // FilterExprWalker#isDocOrdered() did the right thing.
113          if(isSimpleDownAxis || (axis == -1))
114            walker = walker.getNextWalker();
115          else
116          {
117            boolean isLastWalker = (null == walker.getNextWalker());
118            if(isLastWalker)
119            {
120              if(walker.isDocOrdered() && (axis == Axis.DESCENDANT ||
121                 axis == Axis.DESCENDANTORSELF || axis == Axis.DESCENDANTSFROMROOT
122                 || axis == Axis.DESCENDANTSORSELFFROMROOT) || (axis == Axis.ATTRIBUTE))
123                return true;
124            }
125            return false;
126          }
127        }
128        else
129          return false;
130      }
131      return true;
132    }
133    return false;
134  }
135
136
137//  /**
138//   * NEEDSDOC Method canBeWalkedInNaturalDocOrder
139//   *
140//   *
141//   * NEEDSDOC (canBeWalkedInNaturalDocOrder) @return
142//   */
143//  boolean canBeWalkedInNaturalDocOrder()
144//  {
145//
146//    if (null != m_firstWalker)
147//    {
148//      AxesWalker walker = m_firstWalker;
149//      int prevAxis = -1;
150//      boolean prevIsSimpleDownAxis = true;
151//
152//      for(int i = 0; null != walker; i++)
153//      {
154//        int axis = walker.getAxis();
155//
156//        if(walker.isDocOrdered())
157//        {
158//          boolean isSimpleDownAxis = ((axis == Axis.CHILD)
159//                                   || (axis == Axis.SELF)
160//                                   || (axis == Axis.ROOT));
161//          // Catching the filtered list here is only OK because
162//          // FilterExprWalker#isDocOrdered() did the right thing.
163//          if(isSimpleDownAxis || (axis == -1))
164//            walker = walker.getNextWalker();
165//          else
166//          {
167//            boolean isLastWalker = (null == walker.getNextWalker());
168//            if(isLastWalker)
169//            {
170//              if(walker.isDocOrdered() && (axis == Axis.DESCENDANT ||
171//                 axis == Axis.DESCENDANTORSELF || axis == Axis.DESCENDANTSFROMROOT
172//                 || axis == Axis.DESCENDANTSORSELFFROMROOT) || (axis == Axis.ATTRIBUTE))
173//                return true;
174//            }
175//            return false;
176//          }
177//        }
178//        else
179//          return false;
180//      }
181//      return true;
182//    }
183//    return false;
184//  }
185
186  /**
187   * This function is used to perform some extra analysis of the iterator.
188   *
189   * @param vars List of QNames that correspond to variables.  This list
190   * should be searched backwards for the first qualified name that
191   * corresponds to the variable reference qname.  The position of the
192   * QName in the vector from the start of the vector will be its position
193   * in the stack frame (but variables above the globalsTop value will need
194   * to be offset to the current stack frame).
195   */
196  public void fixupVariables(java.util.Vector vars, int globalsSize)
197  {
198    super.fixupVariables(vars, globalsSize);
199
200    int analysis = getAnalysisBits();
201    if(WalkerFactory.isNaturalDocOrder(analysis))
202    {
203    	m_inNaturalOrderStatic = true;
204    }
205    else
206    {
207    	m_inNaturalOrderStatic = false;
208    	// System.out.println("Setting natural doc order to false: "+
209    	//    WalkerFactory.getAnalysisString(analysis));
210    }
211
212  }
213
214}
215