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