1 /*
   2  * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 /*
   5  * Licensed to the Apache Software Foundation (ASF) under one or more
   6  * contributor license agreements.  See the NOTICE file distributed with
   7  * this work for additional information regarding copyright ownership.
   8  * The ASF licenses this file to You under the Apache License, Version 2.0
   9  * (the "License"); you may not use this file except in compliance with
  10  * the License.  You may obtain a copy of the License at
  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 
  21 package com.sun.org.apache.xpath.internal.patterns;
  22 
  23 import com.sun.org.apache.xml.internal.dtm.Axis;
  24 import com.sun.org.apache.xml.internal.dtm.DTM;
  25 import com.sun.org.apache.xml.internal.dtm.DTMAxisTraverser;
  26 import com.sun.org.apache.xml.internal.dtm.DTMFilter;
  27 import com.sun.org.apache.xpath.internal.XPathContext;
  28 import com.sun.org.apache.xpath.internal.axes.WalkerFactory;
  29 import com.sun.org.apache.xpath.internal.objects.XObject;
  30 /**
  31  * Special context node pattern matcher.
  32  *
  33  * @LastModified: Oct 2017
  34  */
  35 public class ContextMatchStepPattern extends StepPattern
  36 {
  37     static final long serialVersionUID = -1888092779313211942L;
  38 
  39   /**
  40    * Construct a ContextMatchStepPattern.
  41    *
  42    */
  43   public ContextMatchStepPattern(int axis, int paxis)
  44   {
  45     super(DTMFilter.SHOW_ALL, axis, paxis);
  46   }
  47 
  48   /**
  49    * Execute this pattern step, including predicates.
  50    *
  51    *
  52    * @param xctxt XPath runtime context.
  53    *
  54    * @return {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_NODETEST},
  55    *         {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_NONE},
  56    *         {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_NSWILD},
  57    *         {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_QNAME}, or
  58    *         {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_OTHER}.
  59    *
  60    * @throws javax.xml.transform.TransformerException
  61    */
  62   public XObject execute(XPathContext xctxt)
  63           throws javax.xml.transform.TransformerException
  64   {
  65 
  66     if (xctxt.getIteratorRoot() == xctxt.getCurrentNode())
  67       return getStaticScore();
  68     else
  69       return NodeTest.SCORE_NONE;
  70   }
  71 
  72   /**
  73    * Execute the match pattern step relative to another step.
  74    *
  75    *
  76    * @param xctxt The XPath runtime context.
  77    * NEEDSDOC @param prevStep
  78    *
  79    * @return {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_NODETEST},
  80    *         {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_NONE},
  81    *         {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_NSWILD},
  82    *         {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_QNAME}, or
  83    *         {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_OTHER}.
  84    *
  85    * @throws javax.xml.transform.TransformerException
  86    */
  87   public XObject executeRelativePathPattern(
  88           XPathContext xctxt, StepPattern prevStep)
  89             throws javax.xml.transform.TransformerException
  90   {
  91 
  92     XObject score = NodeTest.SCORE_NONE;
  93     int context = xctxt.getCurrentNode();
  94     DTM dtm = xctxt.getDTM(context);
  95 
  96     if (null != dtm)
  97     {
  98       int predContext = xctxt.getCurrentNode();
  99       DTMAxisTraverser traverser;
 100 
 101       int axis = m_axis;
 102 
 103       boolean needToTraverseAttrs = WalkerFactory.isDownwardAxisOfMany(axis);
 104       boolean iterRootIsAttr = (dtm.getNodeType(xctxt.getIteratorRoot())
 105                                  == DTM.ATTRIBUTE_NODE);
 106 
 107       if((Axis.PRECEDING == axis) && iterRootIsAttr)
 108       {
 109         axis = Axis.PRECEDINGANDANCESTOR;
 110       }
 111 
 112       traverser = dtm.getAxisTraverser(axis);
 113 
 114       for (int relative = traverser.first(context); DTM.NULL != relative;
 115               relative = traverser.next(context, relative))
 116       {
 117         try
 118         {
 119           xctxt.pushCurrentNode(relative);
 120 
 121           score = execute(xctxt);
 122 
 123           if (score != NodeTest.SCORE_NONE)
 124           {
 125               //score = executePredicates( xctxt, prevStep, SCORE_OTHER,
 126               //       predContext, relative);
 127               if (executePredicates(xctxt, dtm, context))
 128                   return score;
 129 
 130               score = NodeTest.SCORE_NONE;
 131           }
 132 
 133           if(needToTraverseAttrs && iterRootIsAttr
 134              && (DTM.ELEMENT_NODE == dtm.getNodeType(relative)))
 135           {
 136             int xaxis = Axis.ATTRIBUTE;
 137             for (int i = 0; i < 2; i++)
 138             {
 139               DTMAxisTraverser atraverser = dtm.getAxisTraverser(xaxis);
 140 
 141               for (int arelative = atraverser.first(relative);
 142                       DTM.NULL != arelative;
 143                       arelative = atraverser.next(relative, arelative))
 144               {
 145                 try
 146                 {
 147                   xctxt.pushCurrentNode(arelative);
 148 
 149                   score = execute(xctxt);
 150 
 151                   if (score != NodeTest.SCORE_NONE)
 152                   {
 153                       //score = executePredicates( xctxt, prevStep, SCORE_OTHER,
 154                       //       predContext, arelative);
 155 
 156                     if (score != NodeTest.SCORE_NONE)
 157                       return score;
 158                   }
 159                 }
 160                 finally
 161                 {
 162                   xctxt.popCurrentNode();
 163                 }
 164               }
 165               xaxis = Axis.NAMESPACE;
 166             }
 167           }
 168 
 169         }
 170         finally
 171         {
 172           xctxt.popCurrentNode();
 173         }
 174       }
 175 
 176     }
 177 
 178     return score;
 179   }
 180 
 181 }