private static boolean isNaturalDocOrder()

in src/org/apache/xpath/axes/WalkerFactory.java [1623:1719]


  private static boolean isNaturalDocOrder(
          Compiler compiler, int stepOpCodePos, int stepIndex, int analysis)
            throws javax.xml.transform.TransformerException
  {
    if(canCrissCross(analysis))
      return false;
      
    // Namespaces can present some problems, so just punt if we're looking for 
    // these.
    if(isSet(analysis, BIT_NAMESPACE))
      return false;
      
    // The following, preceding, following-sibling, and preceding sibling can 
    // be found in doc order if we get to this point, but if they occur 
    // together, they produce 
    // duplicates, so it's better for us to eliminate this case so we don't 
    // have to check for duplicates during runtime if we're using a 
    // WalkingIterator.
    if(isSet(analysis, BIT_FOLLOWING | BIT_FOLLOWING_SIBLING) && 
       isSet(analysis, BIT_PRECEDING | BIT_PRECEDING_SIBLING))
      return  false;
      
    // OK, now we have to check for select="@*/axis::*" patterns, which 
    // can also cause duplicates to happen.  But select="axis*/@::*" patterns 
    // are OK, as are select="@foo/axis::*" patterns.
    // Unfortunately, we can't do this just via the analysis bits.
    
    int stepType;
    int stepCount = 0;
    boolean foundWildAttribute = false;
    
    // Steps that can traverse anything other than down a 
    // subtree or that can produce duplicates when used in 
    // combonation are counted with this variable.
    int potentialDuplicateMakingStepCount = 0;
    
    while (OpCodes.ENDOP != (stepType = compiler.getOp(stepOpCodePos)))
    {        
      stepCount++;
        
      switch (stepType)
      {
      case OpCodes.FROM_ATTRIBUTES :
      case OpCodes.MATCH_ATTRIBUTE :
        if(foundWildAttribute) // Maybe not needed, but be safe.
          return false;
        
        // This doesn't seem to work as a test for wild card.  Hmph.
        // int nodeTestType = compiler.getStepTestType(stepOpCodePos);  
        
        String localName = compiler.getStepLocalName(stepOpCodePos);
        // System.err.println("localName: "+localName);
        if(localName.equals("*"))
        {
          foundWildAttribute = true;
        }
        break;
      case OpCodes.FROM_FOLLOWING :
      case OpCodes.FROM_FOLLOWING_SIBLINGS :
      case OpCodes.FROM_PRECEDING :
      case OpCodes.FROM_PRECEDING_SIBLINGS :
      case OpCodes.FROM_PARENT :
      case OpCodes.OP_VARIABLE :
      case OpCodes.OP_EXTFUNCTION :
      case OpCodes.OP_FUNCTION :
      case OpCodes.OP_GROUP :
      case OpCodes.FROM_NAMESPACE :
      case OpCodes.FROM_ANCESTORS :
      case OpCodes.FROM_ANCESTORS_OR_SELF :      
      case OpCodes.MATCH_ANY_ANCESTOR :
      case OpCodes.MATCH_IMMEDIATE_ANCESTOR :
      case OpCodes.FROM_DESCENDANTS_OR_SELF :
      case OpCodes.FROM_DESCENDANTS :
        if(potentialDuplicateMakingStepCount > 0)
            return false;
        potentialDuplicateMakingStepCount++;
      case OpCodes.FROM_ROOT :
      case OpCodes.FROM_CHILDREN :
      case OpCodes.FROM_SELF :
        if(foundWildAttribute)
          return false;
        break;
      default :
        throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NULL_ERROR_HANDLER, new Object[]{Integer.toString(stepType)})); //"Programmer's assertion: unknown opcode: "
                                  // + stepType);
      }

      int nextStepOpCodePos = compiler.getNextStepPos(stepOpCodePos);

      if (nextStepOpCodePos < 0)
        break;
              
      stepOpCodePos = nextStepOpCodePos;
    }

    return true;
  }