KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xpath > patterns > StepPattern


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 /*
17  * $Id: StepPattern.java,v 1.28 2004/02/17 04:35:37 minchau Exp $
18  */

19 package org.apache.xpath.patterns;
20
21 import org.apache.xml.dtm.Axis;
22 import org.apache.xml.dtm.DTM;
23 import org.apache.xml.dtm.DTMAxisTraverser;
24 import org.apache.xml.dtm.DTMFilter;
25 import org.apache.xpath.Expression;
26 import org.apache.xpath.ExpressionOwner;
27 import org.apache.xpath.XPathContext;
28 import org.apache.xpath.XPathVisitor;
29 import org.apache.xpath.axes.SubContextList;
30 import org.apache.xpath.compiler.PsuedoNames;
31 import org.apache.xpath.objects.XObject;
32
33 /**
34  * This class represents a single pattern match step.
35  * @xsl.usage advanced
36  */

37 public class StepPattern extends NodeTest implements SubContextList, ExpressionOwner
38 {
39
40   /** The axis for this test. */
41   protected int m_axis;
42
43   /**
44    * Construct a StepPattern that tests for namespaces and node names.
45    *
46    *
47    * @param whatToShow Bit set defined mainly by {@link org.w3c.dom.traversal.NodeFilter}.
48    * @param namespace The namespace to be tested.
49    * @param name The local name to be tested.
50    * @param axis The Axis for this test, one of of Axes.ANCESTORORSELF, etc.
51    * @param axisForPredicate No longer used.
52    */

53   public StepPattern(int whatToShow, String JavaDoc namespace, String JavaDoc name, int axis,
54                      int axisForPredicate)
55   {
56
57     super(whatToShow, namespace, name);
58
59     m_axis = axis;
60   }
61
62   /**
63    * Construct a StepPattern that doesn't test for node names.
64    *
65    *
66    * @param whatToShow Bit set defined mainly by {@link org.w3c.dom.traversal.NodeFilter}.
67    * @param axis The Axis for this test, one of of Axes.ANCESTORORSELF, etc.
68    * @param axisForPredicate No longer used.
69    */

70   public StepPattern(int whatToShow, int axis, int axisForPredicate)
71   {
72
73     super(whatToShow);
74
75     m_axis = axis;
76   }
77
78   /**
79    * The target local name or psuedo name, for hash table lookup optimization.
80    * @serial
81    */

82   String JavaDoc m_targetString; // only calculate on head
83

84   /**
85    * Calculate the local name or psuedo name of the node that this pattern will test,
86    * for hash table lookup optimization.
87    *
88    * @see org.apache.xpath.compiler.PsuedoNames
89    */

90   public void calcTargetString()
91   {
92
93     int whatToShow = getWhatToShow();
94
95     switch (whatToShow)
96     {
97     case DTMFilter.SHOW_COMMENT :
98       m_targetString = PsuedoNames.PSEUDONAME_COMMENT;
99       break;
100     case DTMFilter.SHOW_TEXT :
101     case DTMFilter.SHOW_CDATA_SECTION :
102     case (DTMFilter.SHOW_TEXT | DTMFilter.SHOW_CDATA_SECTION) :
103       m_targetString = PsuedoNames.PSEUDONAME_TEXT;
104       break;
105     case DTMFilter.SHOW_ALL :
106       m_targetString = PsuedoNames.PSEUDONAME_ANY;
107       break;
108     case DTMFilter.SHOW_DOCUMENT :
109     case DTMFilter.SHOW_DOCUMENT | DTMFilter.SHOW_DOCUMENT_FRAGMENT :
110       m_targetString = PsuedoNames.PSEUDONAME_ROOT;
111       break;
112     case DTMFilter.SHOW_ELEMENT :
113       if (this.WILD == m_name)
114         m_targetString = PsuedoNames.PSEUDONAME_ANY;
115       else
116         m_targetString = m_name;
117       break;
118     default :
119       m_targetString = PsuedoNames.PSEUDONAME_ANY;
120       break;
121     }
122   }
123
124   /**
125    * Get the local name or psuedo name of the node that this pattern will test,
126    * for hash table lookup optimization.
127    *
128    *
129    * @return local name or psuedo name of the node.
130    * @see org.apache.xpath.compiler.PsuedoNames
131    */

132   public String JavaDoc getTargetString()
133   {
134     return m_targetString;
135   }
136
137   /**
138    * Reference to nodetest and predicate for
139    * parent or ancestor.
140    * @serial
141    */

142   StepPattern m_relativePathPattern;
143
144   /**
145    * This function is used to fixup variables from QNames to stack frame
146    * indexes at stylesheet build time.
147    * @param vars List of QNames that correspond to variables. This list
148    * should be searched backwards for the first qualified name that
149    * corresponds to the variable reference qname. The position of the
150    * QName in the vector from the start of the vector will be its position
151    * in the stack frame (but variables above the globalsTop value will need
152    * to be offset to the current stack frame).
153    * @param globalsSize The number of variables in the global variable area.
154    */

155   public void fixupVariables(java.util.Vector JavaDoc vars, int globalsSize)
156   {
157
158     super.fixupVariables(vars, globalsSize);
159
160     if (null != m_predicates)
161     {
162       for (int i = 0; i < m_predicates.length; i++)
163       {
164         m_predicates[i].fixupVariables(vars, globalsSize);
165       }
166     }
167
168     if (null != m_relativePathPattern)
169     {
170       m_relativePathPattern.fixupVariables(vars, globalsSize);
171     }
172   }
173
174   /**
175    * Set the reference to nodetest and predicate for
176    * parent or ancestor.
177    *
178    *
179    * @param expr The relative pattern expression.
180    */

181   public void setRelativePathPattern(StepPattern expr)
182   {
183
184     m_relativePathPattern = expr;
185     expr.exprSetParent(this);
186
187     calcScore();
188   }
189
190   /**
191    * Get the reference to nodetest and predicate for
192    * parent or ancestor.
193    *
194    *
195    * @return The relative pattern expression.
196    */

197   public StepPattern getRelativePathPattern()
198   {
199     return m_relativePathPattern;
200   }
201
202   // /**
203
// * Set the list of predicate expressions for this pattern step.
204
// * @param predicates List of expression objects.
205
// */
206
// public void setPredicates(Expression[] predicates)
207
// {
208
// m_predicates = predicates;
209
// }
210

211   /**
212    * Set the list of predicate expressions for this pattern step.
213    * @return List of expression objects.
214    */

215   public Expression[] getPredicates()
216   {
217     return m_predicates;
218   }
219
220   /**
221    * The list of predicate expressions for this pattern step.
222    * @serial
223    */

224   Expression[] m_predicates;
225
226   /**
227    * Tell if this expression or it's subexpressions can traverse outside
228    * the current subtree.
229    *
230    * NOTE: Ancestors tests with predicates are problematic, and will require
231    * special treatment.
232    *
233    * @return true if traversal outside the context node's subtree can occur.
234    */

235   public boolean canTraverseOutsideSubtree()
236   {
237
238     int n = getPredicateCount();
239
240     for (int i = 0; i < n; i++)
241     {
242       if (getPredicate(i).canTraverseOutsideSubtree())
243         return true;
244     }
245
246     return false;
247   }
248
249   /**
250    * Get a predicate expression.
251    *
252    *
253    * @param i The index of the predicate.
254    *
255    * @return A predicate expression.
256    */

257   public Expression getPredicate(int i)
258   {
259     return m_predicates[i];
260   }
261
262   /**
263    * Get the number of predicates for this match pattern step.
264    *
265    *
266    * @return the number of predicates for this match pattern step.
267    */

268   public final int getPredicateCount()
269   {
270     return (null == m_predicates) ? 0 : m_predicates.length;
271   }
272
273   /**
274    * Set the predicates for this match pattern step.
275    *
276    *
277    * @param predicates An array of expressions that define predicates
278    * for this step.
279    */

280   public void setPredicates(Expression[] predicates)
281   {
282
283     m_predicates = predicates;
284     if(null != predicates)
285     {
286         for(int i = 0; i < predicates.length; i++)
287         {
288             predicates[i].exprSetParent(this);
289         }
290     }
291
292     calcScore();
293   }
294
295   /**
296    * Static calc of match score.
297    */

298   public void calcScore()
299   {
300
301     if ((getPredicateCount() > 0) || (null != m_relativePathPattern))
302     {
303       m_score = SCORE_OTHER;
304     }
305     else
306       super.calcScore();
307
308     if (null == m_targetString)
309       calcTargetString();
310   }
311
312   /**
313    * Execute this pattern step, including predicates.
314    *
315    *
316    * @param xctxt XPath runtime context.
317    * @param currentNode The current node context.
318    *
319    * @return {@link org.apache.xpath.patterns.NodeTest#SCORE_NODETEST},
320    * {@link org.apache.xpath.patterns.NodeTest#SCORE_NONE},
321    * {@link org.apache.xpath.patterns.NodeTest#SCORE_NSWILD},
322    * {@link org.apache.xpath.patterns.NodeTest#SCORE_QNAME}, or
323    * {@link org.apache.xpath.patterns.NodeTest#SCORE_OTHER}.
324    *
325    * @throws javax.xml.transform.TransformerException
326    */

327   public XObject execute(XPathContext xctxt, int currentNode)
328           throws javax.xml.transform.TransformerException JavaDoc
329   {
330
331     DTM dtm = xctxt.getDTM(currentNode);
332
333     if (dtm != null)
334     {
335       int expType = dtm.getExpandedTypeID(currentNode);
336
337       return execute(xctxt, currentNode, dtm, expType);
338     }
339
340     return NodeTest.SCORE_NONE;
341   }
342
343   /**
344    * Execute this pattern step, including predicates.
345    *
346    *
347    * @param xctxt XPath runtime context.
348    *
349    * @return {@link org.apache.xpath.patterns.NodeTest#SCORE_NODETEST},
350    * {@link org.apache.xpath.patterns.NodeTest#SCORE_NONE},
351    * {@link org.apache.xpath.patterns.NodeTest#SCORE_NSWILD},
352    * {@link org.apache.xpath.patterns.NodeTest#SCORE_QNAME}, or
353    * {@link org.apache.xpath.patterns.NodeTest#SCORE_OTHER}.
354    *
355    * @throws javax.xml.transform.TransformerException
356    */

357   public XObject execute(XPathContext xctxt)
358           throws javax.xml.transform.TransformerException JavaDoc
359   {
360     return execute(xctxt, xctxt.getCurrentNode());
361   }
362
363   /**
364    * Execute an expression in the XPath runtime context, and return the
365    * result of the expression.
366    *
367    *
368    * @param xctxt The XPath runtime context.
369    * @param currentNode The currentNode.
370    * @param dtm The DTM of the current node.
371    * @param expType The expanded type ID of the current node.
372    *
373    * @return The result of the expression in the form of a <code>XObject</code>.
374    *
375    * @throws javax.xml.transform.TransformerException if a runtime exception
376    * occurs.
377    */

378   public XObject execute(
379           XPathContext xctxt, int currentNode, DTM dtm, int expType)
380             throws javax.xml.transform.TransformerException JavaDoc
381   {
382
383     if (m_whatToShow == NodeTest.SHOW_BYFUNCTION)
384     {
385       if (null != m_relativePathPattern)
386       {
387         return m_relativePathPattern.execute(xctxt);
388       }
389       else
390         return NodeTest.SCORE_NONE;
391     }
392
393     XObject score;
394
395     score = super.execute(xctxt, currentNode, dtm, expType);
396
397     if (score == NodeTest.SCORE_NONE)
398       return NodeTest.SCORE_NONE;
399
400     if (getPredicateCount() != 0)
401     {
402       if (!executePredicates(xctxt, dtm, currentNode))
403         return NodeTest.SCORE_NONE;
404     }
405
406     if (null != m_relativePathPattern)
407       return m_relativePathPattern.executeRelativePathPattern(xctxt, dtm,
408               currentNode);
409
410     return score;
411   }
412
413   /**
414    * New Method to check whether the current node satisfies a position predicate
415    *
416    * @param xctxt The XPath runtime context.
417    * @param predPos Which predicate we're evaluating of foo[1][2][3].
418    * @param dtm The DTM of the current node.
419    * @param context The currentNode.
420    * @param pos The position being requested, i.e. the value returned by
421    * m_predicates[predPos].execute(xctxt).
422    *
423    * @return true of the position of the context matches pos, false otherwise.
424    */

425   private final boolean checkProximityPosition(XPathContext xctxt,
426           int predPos, DTM dtm, int context, int pos)
427   {
428
429     try
430     {
431       DTMAxisTraverser traverser =
432         dtm.getAxisTraverser(Axis.PRECEDINGSIBLING);
433
434       for (int child = traverser.first(context); DTM.NULL != child;
435               child = traverser.next(context, child))
436       {
437         try
438         {
439           xctxt.pushCurrentNode(child);
440
441           if (NodeTest.SCORE_NONE != super.execute(xctxt, child))
442           {
443             boolean pass = true;
444
445             try
446             {
447               xctxt.pushSubContextList(this);
448
449               for (int i = 0; i < predPos; i++)
450               {
451                 xctxt.pushPredicatePos(i);
452                 try
453                 {
454                   XObject pred = m_predicates[i].execute(xctxt);
455                   
456                   try
457                   {
458                     if (XObject.CLASS_NUMBER == pred.getType())
459                     {
460                       throw new Error JavaDoc("Why: Should never have been called");
461                     }
462                     else if (!pred.boolWithSideEffects())
463                     {
464                       pass = false;
465     
466                       break;
467                     }
468                   }
469                   finally
470                   {
471                     pred.detach();
472                   }
473                 }
474                 finally
475                 {
476                   xctxt.popPredicatePos();
477                 }
478               }
479             }
480             finally
481             {
482               xctxt.popSubContextList();
483             }
484
485             if (pass)
486               pos--;
487
488             if (pos < 1)
489               return false;
490           }
491         }
492         finally
493         {
494           xctxt.popCurrentNode();
495         }
496       }
497     }
498     catch (javax.xml.transform.TransformerException JavaDoc se)
499     {
500
501       // TODO: should keep throw sax exception...
502
throw new java.lang.RuntimeException JavaDoc(se.getMessage());
503     }
504
505     return (pos == 1);
506   }
507
508   /**
509    * Get the proximity position index of the current node based on this
510    * node test.
511    *
512    *
513    * @param xctxt XPath runtime context.
514    * @param predPos Which predicate we're evaluating of foo[1][2][3].
515    * @param findLast If true, don't terminate when the context node is found.
516    *
517    * @return the proximity position index of the current node based on the
518    * node test.
519    */

520   private final int getProximityPosition(XPathContext xctxt, int predPos,
521                     boolean findLast)
522   {
523
524     int pos = 0;
525     int context = xctxt.getCurrentNode();
526     DTM dtm = xctxt.getDTM(context);
527     int parent = dtm.getParent(context);
528
529     try
530     {
531       DTMAxisTraverser traverser = dtm.getAxisTraverser(Axis.CHILD);
532
533       for (int child = traverser.first(parent); DTM.NULL != child;
534               child = traverser.next(parent, child))
535       {
536         try
537         {
538           xctxt.pushCurrentNode(child);
539
540           if (NodeTest.SCORE_NONE != super.execute(xctxt, child))
541           {
542             boolean pass = true;
543
544             try
545             {
546               xctxt.pushSubContextList(this);
547
548               for (int i = 0; i < predPos; i++)
549               {
550                 xctxt.pushPredicatePos(i);
551                 try
552                 {
553                   XObject pred = m_predicates[i].execute(xctxt);
554   
555                   try
556                   {
557                     if (XObject.CLASS_NUMBER == pred.getType())
558                     {
559                       if ((pos + 1) != (int) pred.numWithSideEffects())
560                       {
561                         pass = false;
562     
563                         break;
564                       }
565                     }
566                     else if (!pred.boolWithSideEffects())
567                     {
568                       pass = false;
569     
570                       break;
571                     }
572                   }
573                   finally
574                   {
575                     pred.detach();
576                   }
577                 }
578                 finally
579                 {
580                   xctxt.popPredicatePos();
581                 }
582               }
583             }
584             finally
585             {
586               xctxt.popSubContextList();
587             }
588
589             if (pass)
590               pos++;
591
592             if (!findLast && child == context)
593             {
594               return pos;
595             }
596           }
597         }
598         finally
599         {
600           xctxt.popCurrentNode();
601         }
602       }
603     }
604     catch (javax.xml.transform.TransformerException JavaDoc se)
605     {
606
607       // TODO: should keep throw sax exception...
608
throw new java.lang.RuntimeException JavaDoc(se.getMessage());
609     }
610
611     return pos;
612   }
613
614   /**
615    * Get the proximity position index of the current node based on this
616    * node test.
617    *
618    *
619    * @param xctxt XPath runtime context.
620    *
621    * @return the proximity position index of the current node based on the
622    * node test.
623    */

624   public int getProximityPosition(XPathContext xctxt)
625   {
626     return getProximityPosition(xctxt, xctxt.getPredicatePos(), false);
627   }
628   
629   /**
630    * Get the count of the nodes that match the test, which is the proximity
631    * position of the last node that can pass this test in the sub context
632    * selection. In XSLT 1-based indexing, this count is the index of the last
633    * node.
634    *
635    *
636    * @param xctxt XPath runtime context.
637    *
638    * @return the count of the nodes that match the test.
639    */

640   public int getLastPos(XPathContext xctxt)
641   {
642     return getProximityPosition(xctxt, xctxt.getPredicatePos(), true);
643   }
644
645   /**
646    * Execute the match pattern step relative to another step.
647    *
648    *
649    * @param xctxt The XPath runtime context.
650    * @param dtm The DTM of the current node.
651    * @param currentNode The current node context.
652    *
653    * @return {@link org.apache.xpath.patterns.NodeTest#SCORE_NODETEST},
654    * {@link org.apache.xpath.patterns.NodeTest#SCORE_NONE},
655    * {@link org.apache.xpath.patterns.NodeTest#SCORE_NSWILD},
656    * {@link org.apache.xpath.patterns.NodeTest#SCORE_QNAME}, or
657    * {@link org.apache.xpath.patterns.NodeTest#SCORE_OTHER}.
658    *
659    * @throws javax.xml.transform.TransformerException
660    */

661   protected final XObject executeRelativePathPattern(
662           XPathContext xctxt, DTM dtm, int currentNode)
663             throws javax.xml.transform.TransformerException JavaDoc
664   {
665
666     XObject score = NodeTest.SCORE_NONE;
667     int context = currentNode;
668     DTMAxisTraverser traverser;
669
670     traverser = dtm.getAxisTraverser(m_axis);
671
672     for (int relative = traverser.first(context); DTM.NULL != relative;
673             relative = traverser.next(context, relative))
674     {
675       try
676       {
677         xctxt.pushCurrentNode(relative);
678
679         score = execute(xctxt);
680
681         if (score != NodeTest.SCORE_NONE)
682           break;
683       }
684       finally
685       {
686         xctxt.popCurrentNode();
687       }
688     }
689
690     return score;
691   }
692
693   /**
694    * Execute the predicates on this step to determine if the current node
695    * should be filtered or accepted.
696    *
697    * @param xctxt The XPath runtime context.
698    * @param dtm The DTM of the current node.
699    * @param currentNode The current node context.
700    *
701    * @return true if the node should be accepted, false otherwise.
702    *
703    * @throws javax.xml.transform.TransformerException
704    */

705   protected final boolean executePredicates(
706           XPathContext xctxt, DTM dtm, int currentNode)
707             throws javax.xml.transform.TransformerException JavaDoc
708   {
709
710     boolean result = true;
711     boolean positionAlreadySeen = false;
712     int n = getPredicateCount();
713
714     try
715     {
716       xctxt.pushSubContextList(this);
717
718       for (int i = 0; i < n; i++)
719       {
720         xctxt.pushPredicatePos(i);
721
722         try
723         {
724           XObject pred = m_predicates[i].execute(xctxt);
725
726           try
727           {
728             if (XObject.CLASS_NUMBER == pred.getType())
729             {
730               int pos = (int) pred.num();
731   
732               if (positionAlreadySeen)
733               {
734                 result = (pos == 1);
735   
736                 break;
737               }
738               else
739               {
740                 positionAlreadySeen = true;
741   
742                 if (!checkProximityPosition(xctxt, i, dtm, currentNode, pos))
743                 {
744                   result = false;
745   
746                   break;
747                 }
748               }
749             
750             }
751             else if (!pred.boolWithSideEffects())
752             {
753               result = false;
754   
755               break;
756             }
757           }
758           finally
759           {
760             pred.detach();
761           }
762         }
763         finally
764         {
765           xctxt.popPredicatePos();
766         }
767       }
768     }
769     finally
770     {
771       xctxt.popSubContextList();
772     }
773
774     return result;
775   }
776
777   /**
778    * Get the string represenentation of this step for diagnostic purposes.
779    *
780    *
781    * @return A string representation of this step, built by reverse-engineering
782    * the contained info.
783    */

784   public String JavaDoc toString()
785   {
786
787     StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
788
789     for (StepPattern pat = this; pat != null; pat = pat.m_relativePathPattern)
790     {
791       if (pat != this)
792         buf.append("/");
793
794       buf.append(Axis.names[pat.m_axis]);
795       buf.append("::");
796
797       if (0x000005000 == pat.m_whatToShow)
798       {
799         buf.append("doc()");
800       }
801       else if (DTMFilter.SHOW_BYFUNCTION == pat.m_whatToShow)
802       {
803         buf.append("function()");
804       }
805       else if (DTMFilter.SHOW_ALL == pat.m_whatToShow)
806       {
807         buf.append("node()");
808       }
809       else if (DTMFilter.SHOW_TEXT == pat.m_whatToShow)
810       {
811         buf.append("text()");
812       }
813       else if (DTMFilter.SHOW_PROCESSING_INSTRUCTION == pat.m_whatToShow)
814       {
815         buf.append("processing-instruction(");
816
817         if (null != pat.m_name)
818         {
819           buf.append(pat.m_name);
820         }
821
822         buf.append(")");
823       }
824       else if (DTMFilter.SHOW_COMMENT == pat.m_whatToShow)
825       {
826         buf.append("comment()");
827       }
828       else if (null != pat.m_name)
829       {
830         if (DTMFilter.SHOW_ATTRIBUTE == pat.m_whatToShow)
831         {
832           buf.append("@");
833         }
834
835         if (null != pat.m_namespace)
836         {
837           buf.append("{");
838           buf.append(pat.m_namespace);
839           buf.append("}");
840         }
841
842         buf.append(pat.m_name);
843       }
844       else if (DTMFilter.SHOW_ATTRIBUTE == pat.m_whatToShow)
845       {
846         buf.append("@");
847       }
848       else if ((DTMFilter.SHOW_DOCUMENT | DTMFilter.SHOW_DOCUMENT_FRAGMENT)
849                == pat.m_whatToShow)
850       {
851         buf.append("doc-root()");
852       }
853       else
854       {
855         buf.append("?" + Integer.toHexString(pat.m_whatToShow));
856       }
857
858       if (null != pat.m_predicates)
859       {
860         for (int i = 0; i < pat.m_predicates.length; i++)
861         {
862           buf.append("[");
863           buf.append(pat.m_predicates[i]);
864           buf.append("]");
865         }
866       }
867     }
868
869     return buf.toString();
870   }
871
872   /** Set to true to send diagnostics about pattern matches to the consol. */
873   private static final boolean DEBUG_MATCHES = false;
874
875   /**
876    * Get the match score of the given node.
877    *
878    * @param xctxt The XPath runtime context.
879    * @param context The node to be tested.
880    *
881    * @return {@link org.apache.xpath.patterns.NodeTest#SCORE_NODETEST},
882    * {@link org.apache.xpath.patterns.NodeTest#SCORE_NONE},
883    * {@link org.apache.xpath.patterns.NodeTest#SCORE_NSWILD},
884    * {@link org.apache.xpath.patterns.NodeTest#SCORE_QNAME}, or
885    * {@link org.apache.xpath.patterns.NodeTest#SCORE_OTHER}.
886    *
887    * @throws javax.xml.transform.TransformerException
888    */

889   public double getMatchScore(XPathContext xctxt, int context)
890           throws javax.xml.transform.TransformerException JavaDoc
891   {
892
893     xctxt.pushCurrentNode(context);
894     xctxt.pushCurrentExpressionNode(context);
895
896     try
897     {
898       XObject score = execute(xctxt);
899
900       return score.num();
901     }
902     finally
903     {
904       xctxt.popCurrentNode();
905       xctxt.popCurrentExpressionNode();
906     }
907
908     // return XPath.MATCH_SCORE_NONE;
909
}
910
911   /**
912    * Set the axis that this step should follow.
913    *
914    *
915    * @param axis The Axis for this test, one of of Axes.ANCESTORORSELF, etc.
916    */

917   public void setAxis(int axis)
918   {
919     m_axis = axis;
920   }
921
922   /**
923    * Get the axis that this step follows.
924    *
925    *
926    * @return The Axis for this test, one of of Axes.ANCESTORORSELF, etc.
927    */

928   public int getAxis()
929   {
930     return m_axis;
931   }
932   
933   class PredOwner implements ExpressionOwner
934   {
935     int m_index;
936     
937     PredOwner(int index)
938     {
939         m_index = index;
940     }
941     
942     /**
943      * @see ExpressionOwner#getExpression()
944      */

945     public Expression getExpression()
946     {
947       return m_predicates[m_index];
948     }
949
950
951     /**
952      * @see ExpressionOwner#setExpression(Expression)
953      */

954     public void setExpression(Expression exp)
955     {
956         exp.exprSetParent(StepPattern.this);
957         m_predicates[m_index] = exp;
958     }
959   }
960   
961   /**
962    * @see XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
963    */

964   public void callVisitors(ExpressionOwner owner, XPathVisitor visitor)
965   {
966         if(visitor.visitMatchPattern(owner, this))
967         {
968             callSubtreeVisitors(visitor);
969         }
970   }
971
972   /**
973    * Call the visitors on the subtree. Factored out from callVisitors
974    * so it may be called by derived classes.
975    */

976   protected void callSubtreeVisitors(XPathVisitor visitor)
977   {
978     if (null != m_predicates)
979     {
980       int n = m_predicates.length;
981       for (int i = 0; i < n; i++)
982       {
983         ExpressionOwner predOwner = new PredOwner(i);
984         if (visitor.visitPredicate(predOwner, m_predicates[i]))
985         {
986           m_predicates[i].callVisitors(predOwner, visitor);
987         }
988       }
989     }
990     if (null != m_relativePathPattern)
991     {
992       m_relativePathPattern.callVisitors(this, visitor);
993     }
994   }
995
996
997   /**
998    * @see ExpressionOwner#getExpression()
999    */

1000  public Expression getExpression()
1001  {
1002    return m_relativePathPattern;
1003  }
1004
1005  /**
1006   * @see ExpressionOwner#setExpression(Expression)
1007   */

1008  public void setExpression(Expression exp)
1009  {
1010    exp.exprSetParent(this);
1011    m_relativePathPattern = (StepPattern)exp;
1012  }
1013  
1014  /**
1015   * @see Expression#deepEquals(Expression)
1016   */

1017  public boolean deepEquals(Expression expr)
1018  {
1019    if(!super.deepEquals(expr))
1020        return false;
1021        
1022    StepPattern sp = (StepPattern)expr;
1023    
1024    if (null != m_predicates)
1025    {
1026        int n = m_predicates.length;
1027        if ((null == sp.m_predicates) || (sp.m_predicates.length != n))
1028              return false;
1029        for (int i = 0; i < n; i++)
1030        {
1031          if (!m_predicates[i].deepEquals(sp.m_predicates[i]))
1032            return false;
1033        }
1034    }
1035    else if (null != sp.m_predicates)
1036        return false;
1037        
1038    if(null != m_relativePathPattern)
1039    {
1040        if(!m_relativePathPattern.deepEquals(sp.m_relativePathPattern))
1041            return false;
1042    }
1043    else if(sp.m_relativePathPattern != null)
1044        return false;
1045        
1046    return true;
1047  }
1048
1049
1050}
1051
Popular Tags