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.axes;
  23 
  24 import com.sun.org.apache.xml.internal.dtm.Axis;
  25 import com.sun.org.apache.xml.internal.utils.PrefixResolver;
  26 import com.sun.org.apache.xml.internal.utils.QName;
  27 import com.sun.org.apache.xpath.internal.compiler.Compiler;
  28 import java.util.List;
  29 
  30 /**
  31  * This class iterates over set of nodes that needs to be sorted.
  32  * @xsl.usage internal
  33  */
  34 public class WalkingIteratorSorted extends WalkingIterator
  35 {
  36     static final long serialVersionUID = -4512512007542368213L;
  37 
  38 //  /** True if the nodes will be found in document order */
  39 //  protected boolean m_inNaturalOrder = false;
  40 
  41   /** True if the nodes will be found in document order, and this can
  42    * be determined statically. */
  43   protected boolean m_inNaturalOrderStatic = false;
  44 
  45   /**
  46    * Create a WalkingIteratorSorted object.
  47    *
  48    * @param nscontext The namespace context for this iterator,
  49    * should be OK if null.
  50    */
  51   public WalkingIteratorSorted(PrefixResolver nscontext)
  52   {
  53     super(nscontext);
  54   }
  55 
  56   /**
  57    * Create a WalkingIterator iterator, including creation
  58    * of step walkers from the opcode list, and call back
  59    * into the Compiler to create predicate expressions.
  60    *
  61    * @param compiler The Compiler which is creating
  62    * this expression.
  63    * @param opPos The position of this iterator in the
  64    * opcode list from the compiler.
  65    * @param shouldLoadWalkers True if walkers should be
  66    * loaded, or false if this is a derived iterator and
  67    * it doesn't wish to load child walkers.
  68    *
  69    * @throws javax.xml.transform.TransformerException
  70    */
  71   WalkingIteratorSorted(
  72           Compiler compiler, int opPos, int analysis, boolean shouldLoadWalkers)
  73             throws javax.xml.transform.TransformerException
  74   {
  75     super(compiler, opPos, analysis, shouldLoadWalkers);
  76   }
  77 
  78   /**
  79    * Returns true if all the nodes in the iteration well be returned in document
  80    * order.
  81    *
  82    * @return true as a default.
  83    */
  84   public boolean isDocOrdered()
  85   {
  86     return m_inNaturalOrderStatic;
  87   }
  88 
  89 
  90   /**
  91    * Tell if the nodeset can be walked in doc order, via static analysis.
  92    *
  93    *
  94    * @return true if the nodeset can be walked in doc order, without sorting.
  95    */
  96   boolean canBeWalkedInNaturalDocOrderStatic()
  97   {
  98 
  99     if (null != m_firstWalker)
 100     {
 101       AxesWalker walker = m_firstWalker;
 102       int prevAxis = -1;
 103       boolean prevIsSimpleDownAxis = true;
 104 
 105       for(int i = 0; null != walker; i++)
 106       {
 107         int axis = walker.getAxis();
 108 
 109         if(walker.isDocOrdered())
 110         {
 111           boolean isSimpleDownAxis = ((axis == Axis.CHILD)
 112                                    || (axis == Axis.SELF)
 113                                    || (axis == Axis.ROOT));
 114           // Catching the filtered list here is only OK because
 115           // FilterExprWalker#isDocOrdered() did the right thing.
 116           if(isSimpleDownAxis || (axis == -1))
 117             walker = walker.getNextWalker();
 118           else
 119           {
 120             boolean isLastWalker = (null == walker.getNextWalker());
 121             if(isLastWalker)
 122             {
 123               if(walker.isDocOrdered() && (axis == Axis.DESCENDANT ||
 124                  axis == Axis.DESCENDANTORSELF || axis == Axis.DESCENDANTSFROMROOT
 125                  || axis == Axis.DESCENDANTSORSELFFROMROOT) || (axis == Axis.ATTRIBUTE))
 126                 return true;
 127             }
 128             return false;
 129           }
 130         }
 131         else
 132           return false;
 133       }
 134       return true;
 135     }
 136     return false;
 137   }
 138 
 139 
 140 //  /**
 141 //   * NEEDSDOC Method canBeWalkedInNaturalDocOrder
 142 //   *
 143 //   *
 144 //   * NEEDSDOC (canBeWalkedInNaturalDocOrder) @return
 145 //   */
 146 //  boolean canBeWalkedInNaturalDocOrder()
 147 //  {
 148 //
 149 //    if (null != m_firstWalker)
 150 //    {
 151 //      AxesWalker walker = m_firstWalker;
 152 //      int prevAxis = -1;
 153 //      boolean prevIsSimpleDownAxis = true;
 154 //
 155 //      for(int i = 0; null != walker; i++)
 156 //      {
 157 //        int axis = walker.getAxis();
 158 //
 159 //        if(walker.isDocOrdered())
 160 //        {
 161 //          boolean isSimpleDownAxis = ((axis == Axis.CHILD)
 162 //                                   || (axis == Axis.SELF)
 163 //                                   || (axis == Axis.ROOT));
 164 //          // Catching the filtered list here is only OK because
 165 //          // FilterExprWalker#isDocOrdered() did the right thing.
 166 //          if(isSimpleDownAxis || (axis == -1))
 167 //            walker = walker.getNextWalker();
 168 //          else
 169 //          {
 170 //            boolean isLastWalker = (null == walker.getNextWalker());
 171 //            if(isLastWalker)
 172 //            {
 173 //              if(walker.isDocOrdered() && (axis == Axis.DESCENDANT ||
 174 //                 axis == Axis.DESCENDANTORSELF || axis == Axis.DESCENDANTSFROMROOT
 175 //                 || axis == Axis.DESCENDANTSORSELFFROMROOT) || (axis == Axis.ATTRIBUTE))
 176 //                return true;
 177 //            }
 178 //            return false;
 179 //          }
 180 //        }
 181 //        else
 182 //          return false;
 183 //      }
 184 //      return true;
 185 //    }
 186 //    return false;
 187 //  }
 188 
 189   /**
 190    * This function is used to perform some extra analysis of the iterator.
 191    *
 192    * @param vars List of QNames that correspond to variables.  This list
 193    * should be searched backwards for the first qualified name that
 194    * corresponds to the variable reference qname.  The position of the
 195    * QName in the vector from the start of the vector will be its position
 196    * in the stack frame (but variables above the globalsTop value will need
 197    * to be offset to the current stack frame).
 198    */
 199   public void fixupVariables(List<QName> vars, int globalsSize)
 200   {
 201     super.fixupVariables(vars, globalsSize);
 202 
 203     int analysis = getAnalysisBits();
 204     if(WalkerFactory.isNaturalDocOrder(analysis))
 205     {
 206         m_inNaturalOrderStatic = true;
 207     }
 208     else
 209     {
 210         m_inNaturalOrderStatic = false;
 211         // System.out.println("Setting natural doc order to false: "+
 212         //    WalkerFactory.getAnalysisString(analysis));
 213     }
 214 
 215   }
 216 
 217 }