OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / libcore / luni / src / main / java / org / apache / xpath / axes / WalkerFactory.java
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: WalkerFactory.java 469314 2006-10-30 23:31:59Z minchau $
20  */
21 package org.apache.xpath.axes;
22
23 import org.apache.xalan.res.XSLMessages;
24 import org.apache.xml.dtm.Axis;
25 import org.apache.xml.dtm.DTMFilter;
26 import org.apache.xml.dtm.DTMIterator;
27 import org.apache.xpath.Expression;
28 import org.apache.xpath.compiler.Compiler;
29 import org.apache.xpath.compiler.FunctionTable;
30 import org.apache.xpath.compiler.OpCodes;
31 import org.apache.xpath.compiler.OpMap;
32 import org.apache.xpath.objects.XNumber;
33 import org.apache.xpath.patterns.ContextMatchStepPattern;
34 import org.apache.xpath.patterns.FunctionPattern;
35 import org.apache.xpath.patterns.NodeTest;
36 import org.apache.xpath.patterns.StepPattern;
37 import org.apache.xpath.res.XPATHErrorResources;
38
39 /**
40  * This class is both a factory for XPath location path expressions,
41  * which are built from the opcode map output, and an analysis engine
42  * for the location path expressions in order to provide optimization hints.
43  */
44 public class WalkerFactory
45 {
46
47   /**
48    * This method is for building an array of possible levels
49    * where the target element(s) could be found for a match.
50    * @param lpi The owning location path iterator.
51    * @param compiler non-null reference to compiler object that has processed
52    *                 the XPath operations into an opcode map.
53    * @param stepOpCodePos The opcode position for the step.
54    *
55    * @return non-null AxesWalker derivative.
56    *
57    * @throws javax.xml.transform.TransformerException
58    * @xsl.usage advanced
59    */
60   static AxesWalker loadOneWalker(
61           WalkingIterator lpi, Compiler compiler, int stepOpCodePos)
62             throws javax.xml.transform.TransformerException
63   {
64
65     AxesWalker firstWalker = null;
66     int stepType = compiler.getOp(stepOpCodePos);
67
68     if (stepType != OpCodes.ENDOP)
69     {
70
71       // m_axesWalkers = new AxesWalker[1];
72       // As we unwind from the recursion, create the iterators.
73       firstWalker = createDefaultWalker(compiler, stepType, lpi, 0);
74
75       firstWalker.init(compiler, stepOpCodePos, stepType);
76     }
77
78     return firstWalker;
79   }
80
81   /**
82    * This method is for building an array of possible levels
83    * where the target element(s) could be found for a match.
84    * @param lpi The owning location path iterator object.
85    * @param compiler non-null reference to compiler object that has processed
86    *                 the XPath operations into an opcode map.
87    * @param stepOpCodePos The opcode position for the step.
88    * @param stepIndex The top-level step index withing the iterator.
89    *
90    * @return non-null AxesWalker derivative.
91    *
92    * @throws javax.xml.transform.TransformerException
93    * @xsl.usage advanced
94    */
95   static AxesWalker loadWalkers(
96           WalkingIterator lpi, Compiler compiler, int stepOpCodePos, int stepIndex)
97             throws javax.xml.transform.TransformerException
98   {
99
100     int stepType;
101     AxesWalker firstWalker = null;
102     AxesWalker walker, prevWalker = null;
103
104     int analysis = analyze(compiler, stepOpCodePos, stepIndex);
105
106     while (OpCodes.ENDOP != (stepType = compiler.getOp(stepOpCodePos)))
107     {
108       walker = createDefaultWalker(compiler, stepOpCodePos, lpi, analysis);
109
110       walker.init(compiler, stepOpCodePos, stepType);
111       walker.exprSetParent(lpi);
112
113       // walker.setAnalysis(analysis);
114       if (null == firstWalker)
115       {
116         firstWalker = walker;
117       }
118       else
119       {
120         prevWalker.setNextWalker(walker);
121         walker.setPrevWalker(prevWalker);
122       }
123
124       prevWalker = walker;
125       stepOpCodePos = compiler.getNextStepPos(stepOpCodePos);
126
127       if (stepOpCodePos < 0)
128         break;
129     }
130
131     return firstWalker;
132   }
133   
134   public static boolean isSet(int analysis, int bits)
135   {
136     return (0 != (analysis & bits));
137   }
138   
139   public static void diagnoseIterator(String name, int analysis, Compiler compiler)
140   {
141     System.out.println(compiler.toString()+", "+name+", "
142                              + Integer.toBinaryString(analysis) + ", "
143                              + getAnalysisString(analysis));
144   }
145
146   /**
147    * Create a new LocPathIterator iterator.  The exact type of iterator
148    * returned is based on an analysis of the XPath operations.
149    *
150    * @param compiler non-null reference to compiler object that has processed
151    *                 the XPath operations into an opcode map.
152    * @param opPos The position of the operation code for this itterator.
153    *
154    * @return non-null reference to a LocPathIterator or derivative.
155    *
156    * @throws javax.xml.transform.TransformerException
157    */
158   public static DTMIterator newDTMIterator(
159           Compiler compiler, int opPos,
160           boolean isTopLevel)
161             throws javax.xml.transform.TransformerException
162   {
163
164     int firstStepPos = OpMap.getFirstChildPos(opPos);
165     int analysis = analyze(compiler, firstStepPos, 0);
166     boolean isOneStep = isOneStep(analysis);
167     DTMIterator iter;
168
169     // Is the iteration a one-step attribute pattern (i.e. select="@foo")?
170     if (isOneStep && walksSelfOnly(analysis) && 
171         isWild(analysis) && !hasPredicate(analysis))
172     {
173       if (DEBUG_ITERATOR_CREATION)
174         diagnoseIterator("SelfIteratorNoPredicate", analysis, compiler);
175
176       // Then use a simple iteration of the attributes, with node test 
177       // and predicate testing.
178       iter = new SelfIteratorNoPredicate(compiler, opPos, analysis);
179     }
180     // Is the iteration exactly one child step?
181     else if (walksChildrenOnly(analysis) && isOneStep)
182     {
183
184       // Does the pattern specify *any* child with no predicate? (i.e. select="child::node()".
185       if (isWild(analysis) && !hasPredicate(analysis))
186       {
187         if (DEBUG_ITERATOR_CREATION)
188           diagnoseIterator("ChildIterator", analysis, compiler);
189
190         // Use simple child iteration without any test.
191         iter = new ChildIterator(compiler, opPos, analysis);
192       }
193       else
194       {
195         if (DEBUG_ITERATOR_CREATION)
196           diagnoseIterator("ChildTestIterator", analysis, compiler);
197
198         // Else use simple node test iteration with predicate test.
199         iter = new ChildTestIterator(compiler, opPos, analysis);
200       }
201     }
202     // Is the iteration a one-step attribute pattern (i.e. select="@foo")?
203     else if (isOneStep && walksAttributes(analysis))
204     {
205       if (DEBUG_ITERATOR_CREATION)
206         diagnoseIterator("AttributeIterator", analysis, compiler);
207
208       // Then use a simple iteration of the attributes, with node test 
209       // and predicate testing.
210       iter = new AttributeIterator(compiler, opPos, analysis);
211     }
212     else if(isOneStep && !walksFilteredList(analysis))
213     {
214       if( !walksNamespaces(analysis) 
215       && (walksInDocOrder(analysis) || isSet(analysis, BIT_PARENT)))
216       {
217         if (false || DEBUG_ITERATOR_CREATION)
218           diagnoseIterator("OneStepIteratorForward", analysis, compiler);
219   
220         // Then use a simple iteration of the attributes, with node test 
221         // and predicate testing.
222         iter = new OneStepIteratorForward(compiler, opPos, analysis);
223       }
224       else
225       {
226         if (false || DEBUG_ITERATOR_CREATION)
227           diagnoseIterator("OneStepIterator", analysis, compiler);
228   
229         // Then use a simple iteration of the attributes, with node test 
230         // and predicate testing.
231         iter = new OneStepIterator(compiler, opPos, analysis);
232       }
233     }
234
235     // Analysis of "//center":
236     // bits: 1001000000001010000000000000011
237     // count: 3
238     // root
239     // child:node()
240     // BIT_DESCENDANT_OR_SELF
241     // It's highly possible that we should have a seperate bit set for 
242     // "//foo" patterns.
243     // For at least the time being, we can't optimize patterns like 
244     // "//table[3]", because this has to be analyzed as 
245     // "/descendant-or-self::node()/table[3]" in order for the indexes 
246     // to work right.
247     else if (isOptimizableForDescendantIterator(compiler, firstStepPos, 0)
248               // && getStepCount(analysis) <= 3 
249               // && walksDescendants(analysis) 
250               // && walksSubtreeOnlyFromRootOrContext(analysis)
251              )
252     {
253       if (DEBUG_ITERATOR_CREATION)
254         diagnoseIterator("DescendantIterator", analysis, compiler);
255
256       iter = new DescendantIterator(compiler, opPos, analysis);
257     }
258     else
259     { 
260       if(isNaturalDocOrder(compiler, firstStepPos, 0, analysis))
261       {
262         if (false || DEBUG_ITERATOR_CREATION)
263         {
264           diagnoseIterator("WalkingIterator", analysis, compiler);
265         }
266   
267         iter = new WalkingIterator(compiler, opPos, analysis, true);
268       }
269       else
270       {
271 //        if (DEBUG_ITERATOR_CREATION)
272 //          diagnoseIterator("MatchPatternIterator", analysis, compiler);
273 //
274 //        return new MatchPatternIterator(compiler, opPos, analysis);
275         if (DEBUG_ITERATOR_CREATION)
276           diagnoseIterator("WalkingIteratorSorted", analysis, compiler);
277
278         iter = new WalkingIteratorSorted(compiler, opPos, analysis, true);
279       }
280     }
281     if(iter instanceof LocPathIterator)
282       ((LocPathIterator)iter).setIsTopLevel(isTopLevel);
283       
284     return iter;
285   }
286   
287   /**
288    * Special purpose function to see if we can optimize the pattern for 
289    * a DescendantIterator.
290    *
291    * @param compiler non-null reference to compiler object that has processed
292    *                 the XPath operations into an opcode map.
293    * @param stepOpCodePos The opcode position for the step.
294    *
295    * @return 32 bits as an integer that give information about the location
296    * path as a whole.
297    *
298    * @throws javax.xml.transform.TransformerException
299    */
300   public static int getAxisFromStep(
301           Compiler compiler, int stepOpCodePos)
302             throws javax.xml.transform.TransformerException
303   {
304
305     int stepType = compiler.getOp(stepOpCodePos);
306
307     switch (stepType)
308     {
309     case OpCodes.FROM_FOLLOWING :
310       return Axis.FOLLOWING;
311     case OpCodes.FROM_FOLLOWING_SIBLINGS :
312       return Axis.FOLLOWINGSIBLING;
313     case OpCodes.FROM_PRECEDING :
314       return Axis.PRECEDING;
315     case OpCodes.FROM_PRECEDING_SIBLINGS :
316       return Axis.PRECEDINGSIBLING;
317     case OpCodes.FROM_PARENT :
318       return Axis.PARENT;
319     case OpCodes.FROM_NAMESPACE :
320       return Axis.NAMESPACE;
321     case OpCodes.FROM_ANCESTORS :
322       return Axis.ANCESTOR;
323     case OpCodes.FROM_ANCESTORS_OR_SELF :
324       return Axis.ANCESTORORSELF;
325     case OpCodes.FROM_ATTRIBUTES :
326       return Axis.ATTRIBUTE;
327     case OpCodes.FROM_ROOT :
328       return Axis.ROOT;
329     case OpCodes.FROM_CHILDREN :
330       return Axis.CHILD;
331     case OpCodes.FROM_DESCENDANTS_OR_SELF :
332       return Axis.DESCENDANTORSELF;
333     case OpCodes.FROM_DESCENDANTS :
334       return Axis.DESCENDANT;
335     case OpCodes.FROM_SELF :
336       return Axis.SELF;
337     case OpCodes.OP_EXTFUNCTION :
338     case OpCodes.OP_FUNCTION :
339     case OpCodes.OP_GROUP :
340     case OpCodes.OP_VARIABLE :
341       return Axis.FILTEREDLIST;
342     }
343
344     throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NULL_ERROR_HANDLER, new Object[]{Integer.toString(stepType)})); //"Programmer's assertion: unknown opcode: "
345                                //+ stepType);
346    }
347     
348     /**
349      * Get a corresponding BIT_XXX from an axis.
350      * @param axis One of Axis.ANCESTOR, etc.
351      * @return One of BIT_ANCESTOR, etc.
352      */
353     static public int getAnalysisBitFromAxes(int axis)
354     {
355       switch (axis) // Generate new traverser
356         {
357         case Axis.ANCESTOR :
358           return BIT_ANCESTOR;
359         case Axis.ANCESTORORSELF :
360           return BIT_ANCESTOR_OR_SELF;
361         case Axis.ATTRIBUTE :
362           return BIT_ATTRIBUTE;
363         case Axis.CHILD :
364           return BIT_CHILD;
365         case Axis.DESCENDANT :
366           return BIT_DESCENDANT;
367         case Axis.DESCENDANTORSELF :
368           return BIT_DESCENDANT_OR_SELF;
369         case Axis.FOLLOWING :
370           return BIT_FOLLOWING;
371         case Axis.FOLLOWINGSIBLING :
372           return BIT_FOLLOWING_SIBLING;
373         case Axis.NAMESPACE :
374         case Axis.NAMESPACEDECLS :
375           return BIT_NAMESPACE;
376         case Axis.PARENT :
377           return BIT_PARENT;
378         case Axis.PRECEDING :
379           return BIT_PRECEDING;
380         case Axis.PRECEDINGSIBLING :
381           return BIT_PRECEDING_SIBLING;
382         case Axis.SELF :
383           return BIT_SELF;
384         case Axis.ALLFROMNODE :
385           return BIT_DESCENDANT_OR_SELF;
386           // case Axis.PRECEDINGANDANCESTOR :
387         case Axis.DESCENDANTSFROMROOT :
388         case Axis.ALL :
389         case Axis.DESCENDANTSORSELFFROMROOT :
390           return BIT_ANY_DESCENDANT_FROM_ROOT;
391         case Axis.ROOT :
392           return BIT_ROOT;
393         case Axis.FILTEREDLIST :
394           return BIT_FILTER;
395         default :
396           return BIT_FILTER;
397       }
398     }
399   
400   static boolean functionProximateOrContainsProximate(Compiler compiler, 
401                                                       int opPos)
402   {
403     int endFunc = opPos + compiler.getOp(opPos + 1) - 1;
404     opPos = OpMap.getFirstChildPos(opPos);
405     int funcID = compiler.getOp(opPos);
406     //  System.out.println("funcID: "+funcID);
407     //  System.out.println("opPos: "+opPos);
408     //  System.out.println("endFunc: "+endFunc);
409     switch(funcID)
410     {
411       case FunctionTable.FUNC_LAST:
412       case FunctionTable.FUNC_POSITION:
413         return true;
414       default:
415         opPos++;
416         int i = 0;
417         for (int p = opPos; p < endFunc; p = compiler.getNextOpPos(p), i++)
418         {
419           int innerExprOpPos = p+2;
420           int argOp = compiler.getOp(innerExprOpPos);
421           boolean prox = isProximateInnerExpr(compiler, innerExprOpPos);
422           if(prox)
423             return true;
424         }
425
426     }
427     return false;
428   }
429   
430   static boolean isProximateInnerExpr(Compiler compiler, int opPos)
431   {
432     int op = compiler.getOp(opPos);
433     int innerExprOpPos = opPos+2;
434     switch(op)
435     {
436       case OpCodes.OP_ARGUMENT:
437         if(isProximateInnerExpr(compiler, innerExprOpPos))
438           return true;
439         break;
440       case OpCodes.OP_VARIABLE:
441       case OpCodes.OP_NUMBERLIT:
442       case OpCodes.OP_LITERAL:
443       case OpCodes.OP_LOCATIONPATH:
444         break; // OK
445       case OpCodes.OP_FUNCTION:
446         boolean isProx = functionProximateOrContainsProximate(compiler, opPos);
447         if(isProx)
448           return true;
449         break;
450       case OpCodes.OP_GT:
451       case OpCodes.OP_GTE:
452       case OpCodes.OP_LT:
453       case OpCodes.OP_LTE:
454       case OpCodes.OP_EQUALS:
455         int leftPos = OpMap.getFirstChildPos(op);
456         int rightPos = compiler.getNextOpPos(leftPos);
457         isProx = isProximateInnerExpr(compiler, leftPos);
458         if(isProx)
459           return true;
460         isProx = isProximateInnerExpr(compiler, rightPos);
461         if(isProx)
462           return true;
463         break;
464       default:
465         return true; // be conservative...
466     }
467     return false;
468   }
469     
470   /**
471    * Tell if the predicates need to have proximity knowledge.
472    */
473   public static boolean mightBeProximate(Compiler compiler, int opPos, int stepType)
474           throws javax.xml.transform.TransformerException
475   {
476
477     boolean mightBeProximate = false;
478     int argLen;
479
480     switch (stepType)
481     {
482     case OpCodes.OP_VARIABLE :
483     case OpCodes.OP_EXTFUNCTION :
484     case OpCodes.OP_FUNCTION :
485     case OpCodes.OP_GROUP :
486       argLen = compiler.getArgLength(opPos);
487       break;
488     default :
489       argLen = compiler.getArgLengthOfStep(opPos);
490     }
491
492     int predPos = compiler.getFirstPredicateOpPos(opPos);
493     int count = 0;
494
495     while (OpCodes.OP_PREDICATE == compiler.getOp(predPos))
496     {
497       count++;
498       
499       int innerExprOpPos = predPos+2;
500       int predOp = compiler.getOp(innerExprOpPos);
501
502       switch(predOp)
503       {
504         case OpCodes.OP_VARIABLE:
505                 return true; // Would need more smarts to tell if this could be a number or not!
506         case OpCodes.OP_LOCATIONPATH:
507           // OK.
508           break;
509         case OpCodes.OP_NUMBER:
510         case OpCodes.OP_NUMBERLIT:
511           return true; // that's all she wrote!
512         case OpCodes.OP_FUNCTION:
513           boolean isProx 
514             = functionProximateOrContainsProximate(compiler, innerExprOpPos);
515           if(isProx)
516             return true;
517           break;
518         case OpCodes.OP_GT:
519         case OpCodes.OP_GTE:
520         case OpCodes.OP_LT:
521         case OpCodes.OP_LTE:
522         case OpCodes.OP_EQUALS:
523           int leftPos = OpMap.getFirstChildPos(innerExprOpPos);
524           int rightPos = compiler.getNextOpPos(leftPos);
525           isProx = isProximateInnerExpr(compiler, leftPos);
526           if(isProx)
527             return true;
528           isProx = isProximateInnerExpr(compiler, rightPos);
529           if(isProx)
530             return true;
531           break;
532         default:
533           return true; // be conservative...
534       }
535
536       predPos = compiler.getNextOpPos(predPos);
537     }
538
539     return mightBeProximate;
540   }
541   
542   /**
543    * Special purpose function to see if we can optimize the pattern for 
544    * a DescendantIterator.
545    *
546    * @param compiler non-null reference to compiler object that has processed
547    *                 the XPath operations into an opcode map.
548    * @param stepOpCodePos The opcode position for the step.
549    * @param stepIndex The top-level step index withing the iterator.
550    *
551    * @return 32 bits as an integer that give information about the location
552    * path as a whole.
553    *
554    * @throws javax.xml.transform.TransformerException
555    */
556   private static boolean isOptimizableForDescendantIterator(
557           Compiler compiler, int stepOpCodePos, int stepIndex)
558             throws javax.xml.transform.TransformerException
559   {
560
561     int stepType;
562     int stepCount = 0;
563     boolean foundDorDS = false;
564     boolean foundSelf = false;
565     boolean foundDS = false;
566     
567     int nodeTestType = OpCodes.NODETYPE_NODE;
568     
569     while (OpCodes.ENDOP != (stepType = compiler.getOp(stepOpCodePos)))
570     {
571       // The DescendantIterator can only do one node test.  If there's more 
572       // than one, use another iterator.
573       if(nodeTestType != OpCodes.NODETYPE_NODE && nodeTestType != OpCodes.NODETYPE_ROOT)
574         return false;
575         
576       stepCount++;
577       if(stepCount > 3)
578         return false;
579         
580       boolean mightBeProximate = mightBeProximate(compiler, stepOpCodePos, stepType);
581       if(mightBeProximate)
582         return false;
583
584       switch (stepType)
585       {
586       case OpCodes.FROM_FOLLOWING :
587       case OpCodes.FROM_FOLLOWING_SIBLINGS :
588       case OpCodes.FROM_PRECEDING :
589       case OpCodes.FROM_PRECEDING_SIBLINGS :
590       case OpCodes.FROM_PARENT :
591       case OpCodes.OP_VARIABLE :
592       case OpCodes.OP_EXTFUNCTION :
593       case OpCodes.OP_FUNCTION :
594       case OpCodes.OP_GROUP :
595       case OpCodes.FROM_NAMESPACE :
596       case OpCodes.FROM_ANCESTORS :
597       case OpCodes.FROM_ANCESTORS_OR_SELF :
598       case OpCodes.FROM_ATTRIBUTES :
599       case OpCodes.MATCH_ATTRIBUTE :
600       case OpCodes.MATCH_ANY_ANCESTOR :
601       case OpCodes.MATCH_IMMEDIATE_ANCESTOR :
602         return false;
603       case OpCodes.FROM_ROOT :
604         if(1 != stepCount)
605           return false;
606         break;
607       case OpCodes.FROM_CHILDREN :
608         if(!foundDS && !(foundDorDS && foundSelf))
609           return false;
610         break;
611       case OpCodes.FROM_DESCENDANTS_OR_SELF :
612         foundDS = true;
613       case OpCodes.FROM_DESCENDANTS :
614         if(3 == stepCount)
615           return false;
616         foundDorDS = true;
617         break;
618       case OpCodes.FROM_SELF :
619         if(1 != stepCount)
620           return false;
621         foundSelf = true;
622         break;
623       default :
624         throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NULL_ERROR_HANDLER, new Object[]{Integer.toString(stepType)})); //"Programmer's assertion: unknown opcode: "
625                                   // + stepType);
626       }
627       
628       nodeTestType = compiler.getStepTestType(stepOpCodePos);
629
630       int nextStepOpCodePos = compiler.getNextStepPos(stepOpCodePos);
631
632       if (nextStepOpCodePos < 0)
633         break;
634         
635       if(OpCodes.ENDOP != compiler.getOp(nextStepOpCodePos))
636       {
637         if(compiler.countPredicates(stepOpCodePos) > 0)
638         {
639           return false;
640         }
641       }
642       
643       stepOpCodePos = nextStepOpCodePos;
644     }
645
646     return true;
647   }
648
649   /**
650    * Analyze the location path and return 32 bits that give information about
651    * the location path as a whole.  See the BIT_XXX constants for meaning about
652    * each of the bits.
653    *
654    * @param compiler non-null reference to compiler object that has processed
655    *                 the XPath operations into an opcode map.
656    * @param stepOpCodePos The opcode position for the step.
657    * @param stepIndex The top-level step index withing the iterator.
658    *
659    * @return 32 bits as an integer that give information about the location
660    * path as a whole.
661    *
662    * @throws javax.xml.transform.TransformerException
663    */
664   private static int analyze(
665           Compiler compiler, int stepOpCodePos, int stepIndex)
666             throws javax.xml.transform.TransformerException
667   {
668
669     int stepType;
670     int stepCount = 0;
671     int analysisResult = 0x00000000;  // 32 bits of analysis
672
673     while (OpCodes.ENDOP != (stepType = compiler.getOp(stepOpCodePos)))
674     {
675       stepCount++;
676
677       // String namespace = compiler.getStepNS(stepOpCodePos);
678       // boolean isNSWild = (null != namespace) 
679       //                   ? namespace.equals(NodeTest.WILD) : false;
680       // String localname = compiler.getStepLocalName(stepOpCodePos);
681       // boolean isWild = (null != localname) ? localname.equals(NodeTest.WILD) : false;
682       boolean predAnalysis = analyzePredicate(compiler, stepOpCodePos,
683                                               stepType);
684
685       if (predAnalysis)
686         analysisResult |= BIT_PREDICATE;
687
688       switch (stepType)
689       {
690       case OpCodes.OP_VARIABLE :
691       case OpCodes.OP_EXTFUNCTION :
692       case OpCodes.OP_FUNCTION :
693       case OpCodes.OP_GROUP :
694         analysisResult |= BIT_FILTER;
695         break;
696       case OpCodes.FROM_ROOT :
697         analysisResult |= BIT_ROOT;
698         break;
699       case OpCodes.FROM_ANCESTORS :
700         analysisResult |= BIT_ANCESTOR;
701         break;
702       case OpCodes.FROM_ANCESTORS_OR_SELF :
703         analysisResult |= BIT_ANCESTOR_OR_SELF;
704         break;
705       case OpCodes.FROM_ATTRIBUTES :
706         analysisResult |= BIT_ATTRIBUTE;
707         break;
708       case OpCodes.FROM_NAMESPACE :
709         analysisResult |= BIT_NAMESPACE;
710         break;
711       case OpCodes.FROM_CHILDREN :
712         analysisResult |= BIT_CHILD;
713         break;
714       case OpCodes.FROM_DESCENDANTS :
715         analysisResult |= BIT_DESCENDANT;
716         break;
717       case OpCodes.FROM_DESCENDANTS_OR_SELF :
718
719         // Use a special bit to to make sure we get the right analysis of "//foo".
720         if (2 == stepCount && BIT_ROOT == analysisResult)
721         {
722           analysisResult |= BIT_ANY_DESCENDANT_FROM_ROOT;
723         }
724
725         analysisResult |= BIT_DESCENDANT_OR_SELF;
726         break;
727       case OpCodes.FROM_FOLLOWING :
728         analysisResult |= BIT_FOLLOWING;
729         break;
730       case OpCodes.FROM_FOLLOWING_SIBLINGS :
731         analysisResult |= BIT_FOLLOWING_SIBLING;
732         break;
733       case OpCodes.FROM_PRECEDING :
734         analysisResult |= BIT_PRECEDING;
735         break;
736       case OpCodes.FROM_PRECEDING_SIBLINGS :
737         analysisResult |= BIT_PRECEDING_SIBLING;
738         break;
739       case OpCodes.FROM_PARENT :
740         analysisResult |= BIT_PARENT;
741         break;
742       case OpCodes.FROM_SELF :
743         analysisResult |= BIT_SELF;
744         break;
745       case OpCodes.MATCH_ATTRIBUTE :
746         analysisResult |= (BIT_MATCH_PATTERN | BIT_ATTRIBUTE);
747         break;
748       case OpCodes.MATCH_ANY_ANCESTOR :
749         analysisResult |= (BIT_MATCH_PATTERN | BIT_ANCESTOR);
750         break;
751       case OpCodes.MATCH_IMMEDIATE_ANCESTOR :
752         analysisResult |= (BIT_MATCH_PATTERN | BIT_PARENT);
753         break;
754       default :
755         throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NULL_ERROR_HANDLER, new Object[]{Integer.toString(stepType)})); //"Programmer's assertion: unknown opcode: "
756                                    //+ stepType);
757       }
758
759       if (OpCodes.NODETYPE_NODE == compiler.getOp(stepOpCodePos + 3))  // child::node()
760       {
761         analysisResult |= BIT_NODETEST_ANY;
762       }
763
764       stepOpCodePos = compiler.getNextStepPos(stepOpCodePos);
765
766       if (stepOpCodePos < 0)
767         break;
768     }
769
770     analysisResult |= (stepCount & BITS_COUNT);
771
772     return analysisResult;
773   }
774   
775   /**
776    * Tell if the given axis goes downword.  Bogus name, if you can think of 
777    * a better one, please do tell.  This really has to do with inverting 
778    * attribute axis.
779    * @param axis One of Axis.XXX.
780    * @return true if the axis is not a child axis and does not go up from 
781    * the axis root.
782    */
783   public static boolean isDownwardAxisOfMany(int axis)
784   {
785     return ((Axis.DESCENDANTORSELF == axis) ||
786           (Axis.DESCENDANT == axis) 
787           || (Axis.FOLLOWING == axis) 
788 //          || (Axis.FOLLOWINGSIBLING == axis) 
789           || (Axis.PRECEDING == axis) 
790 //          || (Axis.PRECEDINGSIBLING == axis)
791           );
792   }
793
794   /**
795    * Read a <a href="http://www.w3.org/TR/xpath#location-paths">LocationPath</a>
796    * as a generalized match pattern.  What this means is that the LocationPath
797    * is read backwards, as a test on a given node, to see if it matches the
798    * criteria of the selection, and ends up at the context node.  Essentially,
799    * this is a backwards query from a given node, to find the context node.
800    * <p>So, the selection "foo/daz[2]" is, in non-abreviated expanded syntax,
801    * "self::node()/following-sibling::foo/child::daz[position()=2]".
802    * Taking this as a match pattern for a probable node, it works out to
803    * "self::daz/parent::foo[child::daz[position()=2 and isPrevStepNode()]
804    * precedingSibling::node()[isContextNodeOfLocationPath()]", adding magic
805    * isPrevStepNode and isContextNodeOfLocationPath operations.  Predicates in
806    * the location path have to be executed by the following step,
807    * because they have to know the context of their execution.
808    *
809    * @param mpi The MatchPatternIterator to which the steps will be attached.
810    * @param compiler The compiler that holds the syntax tree/op map to
811    * construct from.
812    * @param stepOpCodePos The current op code position within the opmap.
813    * @param stepIndex The top-level step index withing the iterator.
814    *
815    * @return A StepPattern object, which may contain relative StepPatterns.
816    *
817    * @throws javax.xml.transform.TransformerException
818    */
819   static StepPattern loadSteps(
820           MatchPatternIterator mpi, Compiler compiler, int stepOpCodePos, 
821                                                        int stepIndex)
822             throws javax.xml.transform.TransformerException
823   {
824     if (DEBUG_PATTERN_CREATION)
825     {
826       System.out.println("================");
827       System.out.println("loadSteps for: "+compiler.getPatternString());
828     }
829     int stepType;
830     StepPattern step = null;
831     StepPattern firstStep = null, prevStep = null;
832     int analysis = analyze(compiler, stepOpCodePos, stepIndex);
833
834     while (OpCodes.ENDOP != (stepType = compiler.getOp(stepOpCodePos)))
835     {
836       step = createDefaultStepPattern(compiler, stepOpCodePos, mpi, analysis,
837                                       firstStep, prevStep);
838
839       if (null == firstStep)
840       {
841         firstStep = step;
842       }
843       else
844       {
845
846         //prevStep.setNextWalker(step);
847         step.setRelativePathPattern(prevStep);
848       }
849
850       prevStep = step;
851       stepOpCodePos = compiler.getNextStepPos(stepOpCodePos);
852
853       if (stepOpCodePos < 0)
854         break;
855     }
856     
857     int axis = Axis.SELF;
858     int paxis = Axis.SELF;
859     StepPattern tail = step;
860     for (StepPattern pat = step; null != pat; 
861          pat = pat.getRelativePathPattern()) 
862     {
863       int nextAxis = pat.getAxis();
864       //int nextPaxis = pat.getPredicateAxis();
865       pat.setAxis(axis);
866       
867       // The predicate axis can't be moved!!!  Test Axes103
868       // pat.setPredicateAxis(paxis);
869       
870       // If we have an attribute or namespace axis that went up, then 
871       // it won't find the attribute in the inverse, since the select-to-match
872       // axes are not invertable (an element is a parent of an attribute, but 
873       // and attribute is not a child of an element).
874       // If we don't do the magic below, then "@*/ancestor-or-self::*" gets
875       // inverted for match to "self::*/descendant-or-self::@*/parent::node()",
876       // which obviously won't work.
877       // So we will rewrite this as:
878       // "self::*/descendant-or-self::*/attribute::*/parent::node()"
879       // Child has to be rewritten a little differently:
880       // select: "@*/parent::*"
881       // inverted match: "self::*/child::@*/parent::node()"
882       // rewrite: "self::*/attribute::*/parent::node()"
883       // Axes that go down in the select, do not have to have special treatment 
884       // in the rewrite. The following inverted match will still not select 
885       // anything.
886       // select: "@*/child::*"
887       // inverted match: "self::*/parent::@*/parent::node()"
888       // Lovely business, this.
889       // -sb
890       int whatToShow = pat.getWhatToShow();
891       if(whatToShow == DTMFilter.SHOW_ATTRIBUTE || 
892          whatToShow == DTMFilter.SHOW_NAMESPACE)
893       {
894         int newAxis = (whatToShow == DTMFilter.SHOW_ATTRIBUTE) ? 
895                        Axis.ATTRIBUTE : Axis.NAMESPACE;
896         if(isDownwardAxisOfMany(axis))
897         {
898           StepPattern attrPat = new StepPattern(whatToShow, 
899                                     pat.getNamespace(),
900                                     pat.getLocalName(),
901                                 //newAxis, pat.getPredicateAxis);
902                                                 newAxis, 0); // don't care about the predicate axis
903           XNumber score = pat.getStaticScore();
904           pat.setNamespace(null);
905           pat.setLocalName(NodeTest.WILD);
906           attrPat.setPredicates(pat.getPredicates());
907           pat.setPredicates(null);
908           pat.setWhatToShow(DTMFilter.SHOW_ELEMENT);
909           StepPattern rel = pat.getRelativePathPattern();
910           pat.setRelativePathPattern(attrPat);
911           attrPat.setRelativePathPattern(rel);
912           attrPat.setStaticScore(score);
913           
914           // This is needed to inverse a following pattern, because of the 
915           // wacky Xalan rules for following from an attribute.  See axes108.
916           // By these rules, following from an attribute is not strictly 
917           // inverseable.
918           if(Axis.PRECEDING == pat.getAxis())
919             pat.setAxis(Axis.PRECEDINGANDANCESTOR);
920             
921           else if(Axis.DESCENDANT == pat.getAxis())
922             pat.setAxis(Axis.DESCENDANTORSELF);
923           
924           pat = attrPat;
925         }
926         else if(Axis.CHILD == pat.getAxis())
927         {
928           // In this case just change the axis.
929           // pat.setWhatToShow(whatToShow);
930           pat.setAxis(Axis.ATTRIBUTE);
931         }
932       }
933       axis = nextAxis;
934       //paxis = nextPaxis;
935       tail = pat;
936     }
937     
938     if(axis < Axis.ALL)
939     {
940       StepPattern selfPattern = new ContextMatchStepPattern(axis, paxis);
941       // We need to keep the new nodetest from affecting the score...
942       XNumber score = tail.getStaticScore();
943       tail.setRelativePathPattern(selfPattern);
944       tail.setStaticScore(score);
945       selfPattern.setStaticScore(score);
946     }        
947
948     if (DEBUG_PATTERN_CREATION)
949     {
950       System.out.println("Done loading steps: "+step.toString());
951             
952       System.out.println("");
953     }
954     return step;  // start from last pattern?? //firstStep;
955   }
956
957   /**
958    * Create a StepPattern that is contained within a LocationPath.
959    *
960    *
961    * @param compiler The compiler that holds the syntax tree/op map to
962    * construct from.
963    * @param stepOpCodePos The current op code position within the opmap.
964    * @param mpi The MatchPatternIterator to which the steps will be attached.
965    * @param analysis 32 bits of analysis, from which the type of AxesWalker
966    *                 may be influenced.
967    * @param tail The step that is the first step analyzed, but the last 
968    *                  step in the relative match linked list, i.e. the tail.
969    *                  May be null.
970    * @param head The step that is the current head of the relative 
971    *                 match step linked list.
972    *                 May be null.
973    *
974    * @return the head of the list.
975    *
976    * @throws javax.xml.transform.TransformerException
977    */
978   private static StepPattern createDefaultStepPattern(
979           Compiler compiler, int opPos, MatchPatternIterator mpi, 
980           int analysis, StepPattern tail, StepPattern head)
981             throws javax.xml.transform.TransformerException
982   {
983
984     int stepType = compiler.getOp(opPos);
985     boolean simpleInit = false;
986     boolean prevIsOneStepDown = true;
987     
988     int whatToShow = compiler.getWhatToShow(opPos);
989     StepPattern ai = null;
990     int axis, predicateAxis;
991     
992     switch (stepType)
993     {
994     case OpCodes.OP_VARIABLE :
995     case OpCodes.OP_EXTFUNCTION :
996     case OpCodes.OP_FUNCTION :
997     case OpCodes.OP_GROUP :
998       prevIsOneStepDown = false;
999
1000       Expression expr;
1001
1002       switch (stepType)
1003       {
1004       case OpCodes.OP_VARIABLE :
1005       case OpCodes.OP_EXTFUNCTION :
1006       case OpCodes.OP_FUNCTION :
1007       case OpCodes.OP_GROUP :
1008         expr = compiler.compile(opPos);
1009         break;
1010       default :
1011         expr = compiler.compile(opPos + 2);
1012       }
1013
1014       axis = Axis.FILTEREDLIST;
1015       predicateAxis = Axis.FILTEREDLIST;
1016       ai = new FunctionPattern(expr, axis, predicateAxis);
1017       simpleInit = true;
1018       break;
1019     case OpCodes.FROM_ROOT :
1020       whatToShow = DTMFilter.SHOW_DOCUMENT
1021                    | DTMFilter.SHOW_DOCUMENT_FRAGMENT;
1022
1023       axis = Axis.ROOT;
1024       predicateAxis = Axis.ROOT;
1025       ai = new StepPattern(DTMFilter.SHOW_DOCUMENT | 
1026                                 DTMFilter.SHOW_DOCUMENT_FRAGMENT,
1027                                 axis, predicateAxis);
1028       break;
1029     case OpCodes.FROM_ATTRIBUTES :
1030       whatToShow = DTMFilter.SHOW_ATTRIBUTE;
1031       axis = Axis.PARENT;
1032       predicateAxis = Axis.ATTRIBUTE;
1033       // ai = new StepPattern(whatToShow, Axis.SELF, Axis.SELF);
1034       break;
1035     case OpCodes.FROM_NAMESPACE :
1036       whatToShow = DTMFilter.SHOW_NAMESPACE;
1037       axis = Axis.PARENT;
1038       predicateAxis = Axis.NAMESPACE;
1039       // ai = new StepPattern(whatToShow, axis, predicateAxis);
1040       break;
1041     case OpCodes.FROM_ANCESTORS :
1042       axis = Axis.DESCENDANT;
1043       predicateAxis = Axis.ANCESTOR;
1044       break;
1045     case OpCodes.FROM_CHILDREN :
1046       axis = Axis.PARENT;
1047       predicateAxis = Axis.CHILD;
1048       break;
1049     case OpCodes.FROM_ANCESTORS_OR_SELF :
1050       axis = Axis.DESCENDANTORSELF;
1051       predicateAxis = Axis.ANCESTORORSELF;
1052       break;
1053     case OpCodes.FROM_SELF :
1054       axis = Axis.SELF;
1055       predicateAxis = Axis.SELF;
1056       break;
1057     case OpCodes.FROM_PARENT :
1058       axis = Axis.CHILD;
1059       predicateAxis = Axis.PARENT;
1060       break;
1061     case OpCodes.FROM_PRECEDING_SIBLINGS :
1062       axis = Axis.FOLLOWINGSIBLING;
1063       predicateAxis = Axis.PRECEDINGSIBLING;
1064       break;
1065     case OpCodes.FROM_PRECEDING :
1066       axis = Axis.FOLLOWING;
1067       predicateAxis = Axis.PRECEDING;
1068       break;
1069     case OpCodes.FROM_FOLLOWING_SIBLINGS :
1070       axis = Axis.PRECEDINGSIBLING;
1071       predicateAxis = Axis.FOLLOWINGSIBLING;
1072       break;
1073     case OpCodes.FROM_FOLLOWING :
1074       axis = Axis.PRECEDING;
1075       predicateAxis = Axis.FOLLOWING;
1076       break;
1077     case OpCodes.FROM_DESCENDANTS_OR_SELF :
1078       axis = Axis.ANCESTORORSELF;
1079       predicateAxis = Axis.DESCENDANTORSELF;
1080       break;
1081     case OpCodes.FROM_DESCENDANTS :
1082       axis = Axis.ANCESTOR;
1083       predicateAxis = Axis.DESCENDANT;
1084       break;
1085     default :
1086       throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NULL_ERROR_HANDLER, new Object[]{Integer.toString(stepType)})); //"Programmer's assertion: unknown opcode: "
1087                                  //+ stepType);
1088     }
1089     if(null == ai)
1090     {
1091       whatToShow = compiler.getWhatToShow(opPos); // %REVIEW%
1092       ai = new StepPattern(whatToShow, compiler.getStepNS(opPos),
1093                                 compiler.getStepLocalName(opPos),
1094                                 axis, predicateAxis);
1095     }
1096    
1097     if (false || DEBUG_PATTERN_CREATION)
1098     {
1099       System.out.print("new step: "+ ai);
1100       System.out.print(", axis: " + Axis.getNames(ai.getAxis()));
1101       System.out.print(", predAxis: " + Axis.getNames(ai.getAxis()));
1102       System.out.print(", what: ");
1103       System.out.print("    ");
1104       ai.debugWhatToShow(ai.getWhatToShow());
1105     }
1106
1107     int argLen = compiler.getFirstPredicateOpPos(opPos);
1108
1109     ai.setPredicates(compiler.getCompiledPredicates(argLen));
1110
1111     return ai;
1112   }
1113
1114   /**
1115    * Analyze a step and give information about it's predicates.  Right now this
1116    * just returns true or false if the step has a predicate.
1117    *
1118    * @param compiler non-null reference to compiler object that has processed
1119    *                 the XPath operations into an opcode map.
1120    * @param opPos The opcode position for the step.
1121    * @param stepType The type of step, one of OP_GROUP, etc.
1122    *
1123    * @return true if step has a predicate.
1124    *
1125    * @throws javax.xml.transform.TransformerException
1126    */
1127   static boolean analyzePredicate(Compiler compiler, int opPos, int stepType)
1128           throws javax.xml.transform.TransformerException
1129   {
1130
1131     int argLen;
1132
1133     switch (stepType)
1134     {
1135     case OpCodes.OP_VARIABLE :
1136     case OpCodes.OP_EXTFUNCTION :
1137     case OpCodes.OP_FUNCTION :
1138     case OpCodes.OP_GROUP :
1139       argLen = compiler.getArgLength(opPos);
1140       break;
1141     default :
1142       argLen = compiler.getArgLengthOfStep(opPos);
1143     }
1144
1145     int pos = compiler.getFirstPredicateOpPos(opPos);
1146     int nPredicates = compiler.countPredicates(pos);
1147
1148     return (nPredicates > 0) ? true : false;
1149   }
1150
1151   /**
1152    * Create the proper Walker from the axes type.
1153    *
1154    * @param compiler non-null reference to compiler object that has processed
1155    *                 the XPath operations into an opcode map.
1156    * @param opPos The opcode position for the step.
1157    * @param lpi The owning location path iterator.
1158    * @param analysis 32 bits of analysis, from which the type of AxesWalker
1159    *                 may be influenced.
1160    *
1161    * @return non-null reference to AxesWalker derivative.
1162    * @throws RuntimeException if the input is bad.
1163    */
1164   private static AxesWalker createDefaultWalker(Compiler compiler, int opPos,
1165           WalkingIterator lpi, int analysis)
1166   {
1167
1168     AxesWalker ai = null;
1169     int stepType = compiler.getOp(opPos);
1170
1171     /*
1172     System.out.println("0: "+compiler.getOp(opPos));
1173     System.out.println("1: "+compiler.getOp(opPos+1));
1174     System.out.println("2: "+compiler.getOp(opPos+2));
1175     System.out.println("3: "+compiler.getOp(opPos+3));
1176     System.out.println("4: "+compiler.getOp(opPos+4));
1177     System.out.println("5: "+compiler.getOp(opPos+5));
1178     */
1179     boolean simpleInit = false;
1180     int totalNumberWalkers = (analysis & BITS_COUNT);
1181     boolean prevIsOneStepDown = true;
1182
1183     switch (stepType)
1184     {
1185     case OpCodes.OP_VARIABLE :
1186     case OpCodes.OP_EXTFUNCTION :
1187     case OpCodes.OP_FUNCTION :
1188     case OpCodes.OP_GROUP :
1189       prevIsOneStepDown = false;
1190
1191       if (DEBUG_WALKER_CREATION)
1192         System.out.println("new walker:  FilterExprWalker: " + analysis
1193                            + ", " + compiler.toString());
1194
1195       ai = new FilterExprWalker(lpi);
1196       simpleInit = true;
1197       break;
1198     case OpCodes.FROM_ROOT :
1199       ai = new AxesWalker(lpi, Axis.ROOT);
1200       break;
1201     case OpCodes.FROM_ANCESTORS :
1202       prevIsOneStepDown = false;
1203       ai = new ReverseAxesWalker(lpi, Axis.ANCESTOR);
1204       break;
1205     case OpCodes.FROM_ANCESTORS_OR_SELF :
1206       prevIsOneStepDown = false;
1207       ai = new ReverseAxesWalker(lpi, Axis.ANCESTORORSELF);
1208       break;
1209     case OpCodes.FROM_ATTRIBUTES :
1210       ai = new AxesWalker(lpi, Axis.ATTRIBUTE);
1211       break;
1212     case OpCodes.FROM_NAMESPACE :
1213       ai = new AxesWalker(lpi, Axis.NAMESPACE);
1214       break;
1215     case OpCodes.FROM_CHILDREN :
1216       ai = new AxesWalker(lpi, Axis.CHILD);
1217       break;
1218     case OpCodes.FROM_DESCENDANTS :
1219       prevIsOneStepDown = false;
1220       ai = new AxesWalker(lpi, Axis.DESCENDANT);
1221       break;
1222     case OpCodes.FROM_DESCENDANTS_OR_SELF :
1223       prevIsOneStepDown = false;
1224       ai = new AxesWalker(lpi, Axis.DESCENDANTORSELF);
1225       break;
1226     case OpCodes.FROM_FOLLOWING :
1227       prevIsOneStepDown = false;
1228       ai = new AxesWalker(lpi, Axis.FOLLOWING);
1229       break;
1230     case OpCodes.FROM_FOLLOWING_SIBLINGS :
1231       prevIsOneStepDown = false;
1232       ai = new AxesWalker(lpi, Axis.FOLLOWINGSIBLING);
1233       break;
1234     case OpCodes.FROM_PRECEDING :
1235       prevIsOneStepDown = false;
1236       ai = new ReverseAxesWalker(lpi, Axis.PRECEDING);
1237       break;
1238     case OpCodes.FROM_PRECEDING_SIBLINGS :
1239       prevIsOneStepDown = false;
1240       ai = new ReverseAxesWalker(lpi, Axis.PRECEDINGSIBLING);
1241       break;
1242     case OpCodes.FROM_PARENT :
1243       prevIsOneStepDown = false;
1244       ai = new ReverseAxesWalker(lpi, Axis.PARENT);
1245       break;
1246     case OpCodes.FROM_SELF :
1247       ai = new AxesWalker(lpi, Axis.SELF);
1248       break;
1249     default :
1250       throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NULL_ERROR_HANDLER, new Object[]{Integer.toString(stepType)})); //"Programmer's assertion: unknown opcode: "
1251                                  //+ stepType);
1252     }
1253
1254     if (simpleInit)
1255     {
1256       ai.initNodeTest(DTMFilter.SHOW_ALL);
1257     }
1258     else
1259     {
1260       int whatToShow = compiler.getWhatToShow(opPos);
1261
1262       /*
1263       System.out.print("construct: ");
1264       NodeTest.debugWhatToShow(whatToShow);
1265       System.out.println("or stuff: "+(whatToShow & (DTMFilter.SHOW_ATTRIBUTE
1266                              | DTMFilter.SHOW_ELEMENT
1267                              | DTMFilter.SHOW_PROCESSING_INSTRUCTION)));
1268       */
1269       if ((0 == (whatToShow
1270                  & (DTMFilter.SHOW_ATTRIBUTE | DTMFilter.SHOW_NAMESPACE | DTMFilter.SHOW_ELEMENT
1271                     | DTMFilter.SHOW_PROCESSING_INSTRUCTION))) || (whatToShow == DTMFilter.SHOW_ALL))
1272         ai.initNodeTest(whatToShow);
1273       else
1274       {
1275         ai.initNodeTest(whatToShow, compiler.getStepNS(opPos),
1276                         compiler.getStepLocalName(opPos));
1277       }
1278     }
1279
1280     return ai;
1281   }
1282   
1283   public static String getAnalysisString(int analysis)
1284   {
1285     StringBuffer buf = new StringBuffer();
1286     buf.append("count: "+getStepCount(analysis)+" ");
1287     if((analysis & BIT_NODETEST_ANY) != 0)
1288     {
1289       buf.append("NTANY|");
1290     }
1291     if((analysis & BIT_PREDICATE) != 0)
1292     {
1293       buf.append("PRED|");
1294     }
1295     if((analysis & BIT_ANCESTOR) != 0)
1296     {
1297       buf.append("ANC|");
1298     }
1299     if((analysis & BIT_ANCESTOR_OR_SELF) != 0)
1300     {
1301       buf.append("ANCOS|");
1302     }
1303     if((analysis & BIT_ATTRIBUTE) != 0)
1304     {
1305       buf.append("ATTR|");
1306     }
1307     if((analysis & BIT_CHILD) != 0)
1308     {
1309       buf.append("CH|");
1310     }
1311     if((analysis & BIT_DESCENDANT) != 0)
1312     {
1313       buf.append("DESC|");
1314     }
1315     if((analysis & BIT_DESCENDANT_OR_SELF) != 0)
1316     {
1317       buf.append("DESCOS|");
1318     }
1319     if((analysis & BIT_FOLLOWING) != 0)
1320     {
1321       buf.append("FOL|");
1322     }
1323     if((analysis & BIT_FOLLOWING_SIBLING) != 0)
1324     {
1325       buf.append("FOLS|");
1326     }
1327     if((analysis & BIT_NAMESPACE) != 0)
1328     {
1329       buf.append("NS|");
1330     }
1331     if((analysis & BIT_PARENT) != 0)
1332     {
1333       buf.append("P|");
1334     }
1335     if((analysis & BIT_PRECEDING) != 0)
1336     {
1337       buf.append("PREC|");
1338     }
1339     if((analysis & BIT_PRECEDING_SIBLING) != 0)
1340     {
1341       buf.append("PRECS|");
1342     }
1343     if((analysis & BIT_SELF) != 0)
1344     {
1345       buf.append(".|");
1346     }
1347     if((analysis & BIT_FILTER) != 0)
1348     {
1349       buf.append("FLT|");
1350     }
1351     if((analysis & BIT_ROOT) != 0)
1352     {
1353       buf.append("R|");
1354     }
1355     return buf.toString();
1356   }
1357
1358   /** Set to true for diagnostics about walker creation */
1359   static final boolean DEBUG_PATTERN_CREATION = false;
1360
1361   /** Set to true for diagnostics about walker creation */
1362   static final boolean DEBUG_WALKER_CREATION = false;
1363
1364   /** Set to true for diagnostics about iterator creation */
1365   static final boolean DEBUG_ITERATOR_CREATION = false;
1366   
1367   public static boolean hasPredicate(int analysis)
1368   {
1369     return (0 != (analysis & BIT_PREDICATE));
1370   }
1371
1372   public static boolean isWild(int analysis)
1373   {
1374     return (0 != (analysis & BIT_NODETEST_ANY));
1375   }
1376
1377   public static boolean walksAncestors(int analysis)
1378   {
1379     return isSet(analysis, BIT_ANCESTOR | BIT_ANCESTOR_OR_SELF);
1380   }
1381   
1382   public static boolean walksAttributes(int analysis)
1383   {
1384     return (0 != (analysis & BIT_ATTRIBUTE));
1385   }
1386
1387   public static boolean walksNamespaces(int analysis)
1388   {
1389     return (0 != (analysis & BIT_NAMESPACE));
1390   }  
1391
1392   public static boolean walksChildren(int analysis)
1393   {
1394     return (0 != (analysis & BIT_CHILD));
1395   }
1396
1397   public static boolean walksDescendants(int analysis)
1398   {
1399     return isSet(analysis, BIT_DESCENDANT | BIT_DESCENDANT_OR_SELF);
1400   }
1401
1402   public static boolean walksSubtree(int analysis)
1403   {
1404     return isSet(analysis, BIT_DESCENDANT | BIT_DESCENDANT_OR_SELF | BIT_CHILD);
1405   }
1406   
1407   public static boolean walksSubtreeOnlyMaybeAbsolute(int analysis)
1408   {
1409     return walksSubtree(analysis)
1410            && !walksExtraNodes(analysis) 
1411            && !walksUp(analysis) 
1412            && !walksSideways(analysis) 
1413            ;
1414   }
1415   
1416   public static boolean walksSubtreeOnly(int analysis)
1417   {
1418     return walksSubtreeOnlyMaybeAbsolute(analysis) 
1419            && !isAbsolute(analysis) 
1420            ;
1421   }
1422
1423   public static boolean walksFilteredList(int analysis)
1424   {
1425     return isSet(analysis, BIT_FILTER);
1426   }
1427   
1428   public static boolean walksSubtreeOnlyFromRootOrContext(int analysis)
1429   {
1430     return walksSubtree(analysis)
1431            && !walksExtraNodes(analysis) 
1432            && !walksUp(analysis) 
1433            && !walksSideways(analysis) 
1434            && !isSet(analysis, BIT_FILTER) 
1435            ;
1436   }
1437
1438   public static boolean walksInDocOrder(int analysis)
1439   {
1440     return (walksSubtreeOnlyMaybeAbsolute(analysis)
1441            || walksExtraNodesOnly(analysis)
1442            || walksFollowingOnlyMaybeAbsolute(analysis)) 
1443            && !isSet(analysis, BIT_FILTER) 
1444            ;
1445   }
1446   
1447   public static boolean walksFollowingOnlyMaybeAbsolute(int analysis)
1448   {
1449     return isSet(analysis, BIT_SELF | BIT_FOLLOWING_SIBLING | BIT_FOLLOWING)
1450            && !walksSubtree(analysis) 
1451            && !walksUp(analysis) 
1452            && !walksSideways(analysis) 
1453            ;
1454   }
1455   
1456   public static boolean walksUp(int analysis)
1457   {
1458     return isSet(analysis, BIT_PARENT | BIT_ANCESTOR | BIT_ANCESTOR_OR_SELF);
1459   }
1460   
1461   public static boolean walksSideways(int analysis)
1462   {
1463     return isSet(analysis, BIT_FOLLOWING | BIT_FOLLOWING_SIBLING | 
1464                            BIT_PRECEDING | BIT_PRECEDING_SIBLING);
1465   }
1466   
1467   public static boolean walksExtraNodes(int analysis)
1468   {
1469     return isSet(analysis, BIT_NAMESPACE | BIT_ATTRIBUTE);
1470   }
1471
1472   public static boolean walksExtraNodesOnly(int analysis)
1473   {
1474     return walksExtraNodes(analysis)
1475            && !isSet(analysis, BIT_SELF) 
1476            && !walksSubtree(analysis) 
1477            && !walksUp(analysis) 
1478            && !walksSideways(analysis) 
1479            && !isAbsolute(analysis) 
1480            ;
1481   }
1482
1483   public static boolean isAbsolute(int analysis)
1484   {
1485     return isSet(analysis, BIT_ROOT | BIT_FILTER);
1486   }
1487   
1488   public static boolean walksChildrenOnly(int analysis)
1489   {
1490     return walksChildren(analysis)
1491            && !isSet(analysis, BIT_SELF)
1492            && !walksExtraNodes(analysis)
1493            && !walksDescendants(analysis) 
1494            && !walksUp(analysis) 
1495            && !walksSideways(analysis) 
1496            && (!isAbsolute(analysis) || isSet(analysis, BIT_ROOT))
1497            ;
1498   }
1499   
1500   public static boolean walksChildrenAndExtraAndSelfOnly(int analysis)
1501   {
1502     return walksChildren(analysis)
1503            && !walksDescendants(analysis) 
1504            && !walksUp(analysis) 
1505            && !walksSideways(analysis) 
1506            && (!isAbsolute(analysis) || isSet(analysis, BIT_ROOT))
1507            ;
1508   }
1509   
1510   public static boolean walksDescendantsAndExtraAndSelfOnly(int analysis)
1511   {
1512     return !walksChildren(analysis)
1513            && walksDescendants(analysis) 
1514            && !walksUp(analysis) 
1515            && !walksSideways(analysis) 
1516            && (!isAbsolute(analysis) || isSet(analysis, BIT_ROOT))
1517            ;
1518   }
1519   
1520   public static boolean walksSelfOnly(int analysis)
1521   {
1522     return isSet(analysis, BIT_SELF) 
1523            && !walksSubtree(analysis) 
1524            && !walksUp(analysis) 
1525            && !walksSideways(analysis) 
1526            && !isAbsolute(analysis) 
1527            ;
1528   }
1529
1530   
1531   public static boolean walksUpOnly(int analysis)
1532   {
1533     return !walksSubtree(analysis) 
1534            && walksUp(analysis) 
1535            && !walksSideways(analysis) 
1536            && !isAbsolute(analysis) 
1537            ;
1538   }
1539   
1540   public static boolean walksDownOnly(int analysis)
1541   {
1542     return walksSubtree(analysis) 
1543            && !walksUp(analysis) 
1544            && !walksSideways(analysis) 
1545            && !isAbsolute(analysis) 
1546            ;
1547   }
1548
1549   public static boolean walksDownExtraOnly(int analysis)
1550   {
1551     return walksSubtree(analysis) &&  walksExtraNodes(analysis)
1552            && !walksUp(analysis) 
1553            && !walksSideways(analysis) 
1554            && !isAbsolute(analysis) 
1555            ;
1556   }
1557   
1558   public static boolean canSkipSubtrees(int analysis)
1559   {
1560     return isSet(analysis, BIT_CHILD) | walksSideways(analysis);
1561   }
1562   
1563   public static boolean canCrissCross(int analysis)
1564   {
1565     // This could be done faster.  Coded for clarity.
1566     if(walksSelfOnly(analysis))
1567       return false;
1568     else if(walksDownOnly(analysis) && !canSkipSubtrees(analysis))
1569       return false;
1570     else if(walksChildrenAndExtraAndSelfOnly(analysis))
1571       return false;
1572     else if(walksDescendantsAndExtraAndSelfOnly(analysis))
1573       return false;
1574     else if(walksUpOnly(analysis))
1575       return false;
1576     else if(walksExtraNodesOnly(analysis))
1577       return false;
1578     else if(walksSubtree(analysis) 
1579            && (walksSideways(analysis) 
1580             || walksUp(analysis) 
1581             || canSkipSubtrees(analysis)))
1582       return true;
1583     else
1584       return false;
1585   }
1586   
1587   /**
1588    * Tell if the pattern can be 'walked' with the iteration steps in natural 
1589    * document order, without duplicates.
1590    *
1591    * @param analysis The general analysis of the pattern.
1592    *
1593    * @return true if the walk can be done in natural order.
1594    *
1595    * @throws javax.xml.transform.TransformerException
1596    */
1597   static public boolean isNaturalDocOrder(int analysis)
1598   {
1599     if(canCrissCross(analysis) || isSet(analysis, BIT_NAMESPACE) ||
1600        walksFilteredList(analysis))
1601       return false;
1602       
1603     if(walksInDocOrder(analysis))
1604       return true;
1605       
1606     return false;
1607   }
1608   
1609   /**
1610    * Tell if the pattern can be 'walked' with the iteration steps in natural 
1611    * document order, without duplicates.
1612    *
1613    * @param compiler non-null reference to compiler object that has processed
1614    *                 the XPath operations into an opcode map.
1615    * @param stepOpCodePos The opcode position for the step.
1616    * @param stepIndex The top-level step index withing the iterator.
1617    * @param analysis The general analysis of the pattern.
1618    *
1619    * @return true if the walk can be done in natural order.
1620    *
1621    * @throws javax.xml.transform.TransformerException
1622    */
1623   private static boolean isNaturalDocOrder(
1624           Compiler compiler, int stepOpCodePos, int stepIndex, int analysis)
1625             throws javax.xml.transform.TransformerException
1626   {
1627     if(canCrissCross(analysis))
1628       return false;
1629       
1630     // Namespaces can present some problems, so just punt if we're looking for 
1631     // these.
1632     if(isSet(analysis, BIT_NAMESPACE))
1633       return false;
1634       
1635     // The following, preceding, following-sibling, and preceding sibling can 
1636     // be found in doc order if we get to this point, but if they occur 
1637     // together, they produce 
1638     // duplicates, so it's better for us to eliminate this case so we don't 
1639     // have to check for duplicates during runtime if we're using a 
1640     // WalkingIterator.
1641     if(isSet(analysis, BIT_FOLLOWING | BIT_FOLLOWING_SIBLING) && 
1642        isSet(analysis, BIT_PRECEDING | BIT_PRECEDING_SIBLING))
1643       return  false;
1644       
1645     // OK, now we have to check for select="@*/axis::*" patterns, which 
1646     // can also cause duplicates to happen.  But select="axis*/@::*" patterns 
1647     // are OK, as are select="@foo/axis::*" patterns.
1648     // Unfortunately, we can't do this just via the analysis bits.
1649     
1650     int stepType;
1651     int stepCount = 0;
1652     boolean foundWildAttribute = false;
1653     
1654     // Steps that can traverse anything other than down a 
1655     // subtree or that can produce duplicates when used in 
1656     // combonation are counted with this variable.
1657     int potentialDuplicateMakingStepCount = 0;
1658     
1659     while (OpCodes.ENDOP != (stepType = compiler.getOp(stepOpCodePos)))
1660     {        
1661       stepCount++;
1662         
1663       switch (stepType)
1664       {
1665       case OpCodes.FROM_ATTRIBUTES :
1666       case OpCodes.MATCH_ATTRIBUTE :
1667         if(foundWildAttribute) // Maybe not needed, but be safe.
1668           return false;
1669         
1670         // This doesn't seem to work as a test for wild card.  Hmph.
1671         // int nodeTestType = compiler.getStepTestType(stepOpCodePos);  
1672         
1673         String localName = compiler.getStepLocalName(stepOpCodePos);
1674         // System.err.println("localName: "+localName);
1675         if(localName.equals("*"))
1676         {
1677           foundWildAttribute = true;
1678         }
1679         break;
1680       case OpCodes.FROM_FOLLOWING :
1681       case OpCodes.FROM_FOLLOWING_SIBLINGS :
1682       case OpCodes.FROM_PRECEDING :
1683       case OpCodes.FROM_PRECEDING_SIBLINGS :
1684       case OpCodes.FROM_PARENT :
1685       case OpCodes.OP_VARIABLE :
1686       case OpCodes.OP_EXTFUNCTION :
1687       case OpCodes.OP_FUNCTION :
1688       case OpCodes.OP_GROUP :
1689       case OpCodes.FROM_NAMESPACE :
1690       case OpCodes.FROM_ANCESTORS :
1691       case OpCodes.FROM_ANCESTORS_OR_SELF :      
1692       case OpCodes.MATCH_ANY_ANCESTOR :
1693       case OpCodes.MATCH_IMMEDIATE_ANCESTOR :
1694       case OpCodes.FROM_DESCENDANTS_OR_SELF :
1695       case OpCodes.FROM_DESCENDANTS :
1696         if(potentialDuplicateMakingStepCount > 0)
1697             return false;
1698         potentialDuplicateMakingStepCount++;
1699       case OpCodes.FROM_ROOT :
1700       case OpCodes.FROM_CHILDREN :
1701       case OpCodes.FROM_SELF :
1702         if(foundWildAttribute)
1703           return false;
1704         break;
1705       default :
1706         throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NULL_ERROR_HANDLER, new Object[]{Integer.toString(stepType)})); //"Programmer's assertion: unknown opcode: "
1707                                   // + stepType);
1708       }
1709
1710       int nextStepOpCodePos = compiler.getNextStepPos(stepOpCodePos);
1711
1712       if (nextStepOpCodePos < 0)
1713         break;
1714               
1715       stepOpCodePos = nextStepOpCodePos;
1716     }
1717
1718     return true;
1719   }
1720   
1721   public static boolean isOneStep(int analysis)
1722   {
1723     return (analysis & BITS_COUNT) == 0x00000001;
1724   }
1725
1726   public static int getStepCount(int analysis)
1727   {
1728     return (analysis & BITS_COUNT);
1729   }
1730
1731   /**
1732    * First 8 bits are the number of top-level location steps.  Hopefully
1733    *  there will never be more that 255 location steps!!!
1734    */
1735   public static final int BITS_COUNT = 0x000000FF;
1736
1737   /** 4 bits are reserved for future use. */
1738   public static final int BITS_RESERVED = 0x00000F00;
1739
1740   /** Bit is on if the expression contains a top-level predicate. */
1741   public static final int BIT_PREDICATE = (0x00001000);
1742
1743   /** Bit is on if any of the walkers contain an ancestor step. */
1744   public static final int BIT_ANCESTOR = (0x00001000 << 1);
1745
1746   /** Bit is on if any of the walkers contain an ancestor-or-self step. */
1747   public static final int BIT_ANCESTOR_OR_SELF = (0x00001000 << 2);
1748
1749   /** Bit is on if any of the walkers contain an attribute step. */
1750   public static final int BIT_ATTRIBUTE = (0x00001000 << 3);
1751
1752   /** Bit is on if any of the walkers contain a child step. */
1753   public static final int BIT_CHILD = (0x00001000 << 4);
1754
1755   /** Bit is on if any of the walkers contain a descendant step. */
1756   public static final int BIT_DESCENDANT = (0x00001000 << 5);
1757
1758   /** Bit is on if any of the walkers contain a descendant-or-self step. */
1759   public static final int BIT_DESCENDANT_OR_SELF = (0x00001000 << 6);
1760
1761   /** Bit is on if any of the walkers contain a following step. */
1762   public static final int BIT_FOLLOWING = (0x00001000 << 7);
1763
1764   /** Bit is on if any of the walkers contain a following-sibiling step. */
1765   public static final int BIT_FOLLOWING_SIBLING = (0x00001000 << 8);
1766
1767   /** Bit is on if any of the walkers contain a namespace step. */
1768   public static final int BIT_NAMESPACE = (0x00001000 << 9);
1769
1770   /** Bit is on if any of the walkers contain a parent step. */
1771   public static final int BIT_PARENT = (0x00001000 << 10);
1772
1773   /** Bit is on if any of the walkers contain a preceding step. */
1774   public static final int BIT_PRECEDING = (0x00001000 << 11);
1775
1776   /** Bit is on if any of the walkers contain a preceding-sibling step. */
1777   public static final int BIT_PRECEDING_SIBLING = (0x00001000 << 12);
1778
1779   /** Bit is on if any of the walkers contain a self step. */
1780   public static final int BIT_SELF = (0x00001000 << 13);
1781
1782   /**
1783    * Bit is on if any of the walkers contain a filter (i.e. id(), extension
1784    *  function, etc.) step.
1785    */
1786   public static final int BIT_FILTER = (0x00001000 << 14);
1787
1788   /** Bit is on if any of the walkers contain a root step. */
1789   public static final int BIT_ROOT = (0x00001000 << 15);
1790
1791   /**
1792    * If any of these bits are on, the expression may likely traverse outside
1793    *  the given subtree.
1794    */
1795   public static final int BITMASK_TRAVERSES_OUTSIDE_SUBTREE = (BIT_NAMESPACE  // ??
1796                                                                 | BIT_PRECEDING_SIBLING
1797                                                                 | BIT_PRECEDING
1798                                                                 | BIT_FOLLOWING_SIBLING
1799                                                                 | BIT_FOLLOWING
1800                                                                 | BIT_PARENT  // except parent of attrs.
1801                                                                 | BIT_ANCESTOR_OR_SELF
1802                                                                 | BIT_ANCESTOR
1803                                                                 | BIT_FILTER
1804                                                                 | BIT_ROOT);
1805
1806   /**
1807    * Bit is on if any of the walkers can go backwards in document
1808    *  order from the context node.
1809    */
1810   public static final int BIT_BACKWARDS_SELF = (0x00001000 << 16);
1811
1812   /** Found "//foo" pattern */
1813   public static final int BIT_ANY_DESCENDANT_FROM_ROOT = (0x00001000 << 17);
1814
1815   /**
1816    * Bit is on if any of the walkers contain an node() test.  This is
1817    *  really only useful if the count is 1.
1818    */
1819   public static final int BIT_NODETEST_ANY = (0x00001000 << 18);
1820
1821   // can't go higher than 18!
1822
1823   /** Bit is on if the expression is a match pattern. */
1824   public static final int BIT_MATCH_PATTERN = (0x00001000 << 19);
1825 }