001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements. See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership. The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the  "License");
007     * you may not use this file except in compliance with the License.
008     * You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    /*
019     * $Id: ContextMatchStepPattern.java 468655 2006-10-28 07:12:06Z minchau $
020     */
021    package org.apache.xpath.patterns;
022    
023    import org.apache.xml.dtm.Axis;
024    import org.apache.xml.dtm.DTM;
025    import org.apache.xml.dtm.DTMAxisTraverser;
026    import org.apache.xml.dtm.DTMFilter;
027    import org.apache.xpath.XPathContext;
028    import org.apache.xpath.axes.WalkerFactory;
029    import org.apache.xpath.objects.XObject;
030    /**
031     * Special context node pattern matcher.
032     */
033    public class ContextMatchStepPattern extends StepPattern
034    {
035        static final long serialVersionUID = -1888092779313211942L;
036    
037      /**
038       * Construct a ContextMatchStepPattern.
039       *
040       */
041      public ContextMatchStepPattern(int axis, int paxis)
042      {
043        super(DTMFilter.SHOW_ALL, axis, paxis);
044      }
045    
046      /**
047       * Execute this pattern step, including predicates.
048       *
049       *
050       * @param xctxt XPath runtime context.
051       *
052       * @return {@link org.apache.xpath.patterns.NodeTest#SCORE_NODETEST},
053       *         {@link org.apache.xpath.patterns.NodeTest#SCORE_NONE},
054       *         {@link org.apache.xpath.patterns.NodeTest#SCORE_NSWILD},
055       *         {@link org.apache.xpath.patterns.NodeTest#SCORE_QNAME}, or
056       *         {@link org.apache.xpath.patterns.NodeTest#SCORE_OTHER}.
057       *
058       * @throws javax.xml.transform.TransformerException
059       */
060      public XObject execute(XPathContext xctxt)
061              throws javax.xml.transform.TransformerException
062      {
063    
064        if (xctxt.getIteratorRoot() == xctxt.getCurrentNode())
065          return getStaticScore();
066        else
067          return this.SCORE_NONE;
068      }
069      
070      /**
071       * Execute the match pattern step relative to another step.
072       *
073       *
074       * @param xctxt The XPath runtime context.
075       * NEEDSDOC @param prevStep
076       *
077       * @return {@link org.apache.xpath.patterns.NodeTest#SCORE_NODETEST},
078       *         {@link org.apache.xpath.patterns.NodeTest#SCORE_NONE},
079       *         {@link org.apache.xpath.patterns.NodeTest#SCORE_NSWILD},
080       *         {@link org.apache.xpath.patterns.NodeTest#SCORE_QNAME}, or
081       *         {@link org.apache.xpath.patterns.NodeTest#SCORE_OTHER}.
082       *
083       * @throws javax.xml.transform.TransformerException
084       */
085      public XObject executeRelativePathPattern(
086              XPathContext xctxt, StepPattern prevStep)
087                throws javax.xml.transform.TransformerException
088      {
089    
090        XObject score = NodeTest.SCORE_NONE;
091        int context = xctxt.getCurrentNode();
092        DTM dtm = xctxt.getDTM(context);
093    
094        if (null != dtm)
095        {
096          int predContext = xctxt.getCurrentNode();
097          DTMAxisTraverser traverser;
098          
099          int axis = m_axis;
100          
101          boolean needToTraverseAttrs = WalkerFactory.isDownwardAxisOfMany(axis);
102          boolean iterRootIsAttr = (dtm.getNodeType(xctxt.getIteratorRoot()) 
103                                     == DTM.ATTRIBUTE_NODE);
104    
105          if((Axis.PRECEDING == axis) && iterRootIsAttr)
106          {
107            axis = Axis.PRECEDINGANDANCESTOR;
108          }
109          
110          traverser = dtm.getAxisTraverser(axis);
111    
112          for (int relative = traverser.first(context); DTM.NULL != relative;
113                  relative = traverser.next(context, relative))
114          {
115            try
116            {
117              xctxt.pushCurrentNode(relative);
118    
119              score = execute(xctxt);
120    
121              if (score != NodeTest.SCORE_NONE)
122              {
123                  //score = executePredicates( xctxt, prevStep, SCORE_OTHER, 
124                  //       predContext, relative);
125                  if (executePredicates(xctxt, dtm, context))
126                      return score;
127                  
128                  score = NodeTest.SCORE_NONE;
129              }
130              
131              if(needToTraverseAttrs && iterRootIsAttr
132                 && (DTM.ELEMENT_NODE == dtm.getNodeType(relative)))
133              {
134                int xaxis = Axis.ATTRIBUTE;
135                for (int i = 0; i < 2; i++) 
136                {            
137                  DTMAxisTraverser atraverser = dtm.getAxisTraverser(xaxis);
138            
139                  for (int arelative = atraverser.first(relative); 
140                          DTM.NULL != arelative;
141                          arelative = atraverser.next(relative, arelative))
142                  {
143                    try
144                    {
145                      xctxt.pushCurrentNode(arelative);
146            
147                      score = execute(xctxt);
148            
149                      if (score != NodeTest.SCORE_NONE)
150                      {
151                          //score = executePredicates( xctxt, prevStep, SCORE_OTHER, 
152                          //       predContext, arelative);
153            
154                        if (score != NodeTest.SCORE_NONE)
155                          return score;
156                      }
157                    }
158                    finally
159                    {
160                      xctxt.popCurrentNode();
161                    }
162                  }
163                  xaxis = Axis.NAMESPACE;
164                }
165              }
166    
167            }
168            finally
169            {
170              xctxt.popCurrentNode();
171            }
172          }
173    
174        }
175    
176        return score;
177      }
178    
179    }