/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the  "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * $Id: AxesWalker.java 513117 2007-03-01 03:28:52Z minchau $
 */
package org.apache.xpath.axes;

import java.util.Vector;

import org.apache.xalan.res.XSLMessages;
import org.apache.xml.dtm.DTM;
import org.apache.xml.dtm.DTMAxisTraverser;
import org.apache.xml.dtm.DTMIterator;
import org.apache.xpath.Expression;
import org.apache.xpath.ExpressionOwner;
import org.apache.xpath.XPathContext;
import org.apache.xpath.XPathVisitor;
import org.apache.xpath.compiler.Compiler;
import org.apache.xpath.res.XPATHErrorResources;

/**
 * Serves as common interface for axes Walkers, and stores common
 * state variables.
 */
public class AxesWalker extends PredicatedNodeTest
        implements Cloneable, PathComponent, ExpressionOwner
{
    static final long serialVersionUID = -2966031951306601247L;
  
  /**
   * Construct an AxesWalker using a LocPathIterator.
   *
   * @param locPathIterator non-null reference to the parent iterator.
   */
  public AxesWalker(LocPathIterator locPathIterator, int axis)
  {
    super( locPathIterator );
    m_axis = axis;
  }
  
  public final WalkingIterator wi()
  {
    return (WalkingIterator)m_lpi;
  }

  /**
   * Initialize an AxesWalker during the parse of the XPath expression.
   *
   * @param compiler The Compiler object that has information about this 
   *                 walker in the op map.
   * @param opPos The op code position of this location step.
   * @param stepType  The type of location step.
   *
   * @throws javax.xml.transform.TransformerException
   */
  public void init(Compiler compiler, int opPos, int stepType)
          throws javax.xml.transform.TransformerException
  {

    initPredicateInfo(compiler, opPos);

    // int testType = compiler.getOp(nodeTestOpPos);
  }

  /**
   * Get a cloned AxesWalker.
   *
   * @return A new AxesWalker that can be used without mutating this one.
   *
   * @throws CloneNotSupportedException
   */
  public Object clone() throws CloneNotSupportedException
  {
    // Do not access the location path itterator during this operation!
    
    AxesWalker clone = (AxesWalker) super.clone();

    //clone.setCurrentNode(clone.m_root);

    // clone.m_isFresh = true;

    return clone;
  }
  
  /**
   * Do a deep clone of this walker, including next and previous walkers.
   * If the this AxesWalker is on the clone list, don't clone but 
   * return the already cloned version.
   * 
   * @param cloneOwner non-null reference to the cloned location path 
   *                   iterator to which this clone will be added.
   * @param cloneList non-null vector of sources in odd elements, and the 
   *                  corresponding clones in even vectors.
   * 
   * @return non-null clone, which may be a new clone, or may be a clone 
   *         contained on the cloneList.
   */
  AxesWalker cloneDeep(WalkingIterator cloneOwner, Vector cloneList)
     throws CloneNotSupportedException
  {
    AxesWalker clone = findClone(this, cloneList);
    if(null != clone)
      return clone;
    clone = (AxesWalker)this.clone();
    clone.setLocPathIterator(cloneOwner);
    if(null != cloneList)
    {
      cloneList.addElement(this);
      cloneList.addElement(clone);
    }
    
    if(wi().m_lastUsedWalker == this)
      cloneOwner.m_lastUsedWalker = clone;
      
    if(null != m_nextWalker)
      clone.m_nextWalker = m_nextWalker.cloneDeep(cloneOwner, cloneList);
      
    // If you don't check for the cloneList here, you'll go into an 
    // recursive infinate loop.  
    if(null != cloneList)
    {
      if(null != m_prevWalker)
        clone.m_prevWalker = m_prevWalker.cloneDeep(cloneOwner, cloneList);
    }
    else
    {
      if(null != m_nextWalker)
        clone.m_nextWalker.m_prevWalker = clone;
    }
    return clone;
  }
  
  /**
   * Find a clone that corresponds to the key argument.
   * 
   * @param key The original AxesWalker for which there may be a clone.
   * @param cloneList vector of sources in odd elements, and the 
   *                  corresponding clones in even vectors, may be null.
   * 
   * @return A clone that corresponds to the key, or null if key not found.
   */
  static AxesWalker findClone(AxesWalker key, Vector cloneList)
  {
    if(null != cloneList)
    {
      // First, look for clone on list.
      int n = cloneList.size();
      for (int i = 0; i < n; i+=2) 
      {
        if(key == cloneList.elementAt(i))
          return (AxesWalker)cloneList.elementAt(i+1);
      }
    }
    return null;    
  }
  
  /**
   * Detaches the walker from the set which it iterated over, releasing
   * any computational resources and placing the iterator in the INVALID
   * state.
   */
  public void detach()
  { 
  	m_currentNode = DTM.NULL;
  	m_dtm = null;
  	m_traverser = null;
  	m_isFresh = true;
  	m_root = DTM.NULL;
  }
  
  //=============== TreeWalker Implementation ===============

  /**
   * The root node of the TreeWalker, as specified in setRoot(int root).
   * Note that this may actually be below the current node.
   *
   * @return The context node of the step.
   */
  public int getRoot()
  {
    return m_root;
  }
  
  /** 
   * Get the analysis bits for this walker, as defined in the WalkerFactory.
   * @return One of WalkerFactory#BIT_DESCENDANT, etc.
   */
  public int getAnalysisBits()
  {
  	int axis = getAxis();
  	int bit = WalkerFactory.getAnalysisBitFromAxes(axis);
  	return bit;
  }

  /**
   * Set the root node of the TreeWalker.
   * (Not part of the DOM2 TreeWalker interface).
   *
   * @param root The context node of this step.
   */
  public void setRoot(int root)
  {
    // %OPT% Get this directly from the lpi.
    XPathContext xctxt = wi().getXPathContext();
    m_dtm = xctxt.getDTM(root);
    m_traverser = m_dtm.getAxisTraverser(m_axis);
    m_isFresh = true;
    m_foundLast = false;
    m_root = root;
    m_currentNode = root;

    if (DTM.NULL == root)
    {
      throw new RuntimeException(
        XSLMessages.createXPATHMessage(XPATHErrorResources.ER_SETTING_WALKER_ROOT_TO_NULL, null)); //"\n !!!! Error! Setting the root of a walker to null!!!");
    }

    resetProximityPositions();
  }

  /**
   * The node at which the TreeWalker is currently positioned.
   * <br> The value must not be null. Alterations to the DOM tree may cause
   * the current node to no longer be accepted by the TreeWalker's
   * associated filter. currentNode may also be explicitly set to any node,
   * whether or not it is within the subtree specified by the root node or
   * would be accepted by the filter and whatToShow flags. Further
   * traversal occurs relative to currentNode even if it is not part of the
   * current view by applying the filters in the requested direction (not
   * changing currentNode where no traversal is possible).
   *
   * @return The node at which the TreeWalker is currently positioned, only null 
   * if setRoot has not yet been called.
   */
  public final int getCurrentNode()
  {
    return m_currentNode;
  }

  /**
   * Set the next walker in the location step chain.
   *
   *
   * @param walker Reference to AxesWalker derivative, or may be null.
   */
  public void setNextWalker(AxesWalker walker)
  {
    m_nextWalker = walker;
  }

  /**
   * Get the next walker in the location step chain.
   *
   *
   * @return Reference to AxesWalker derivative, or null.
   */
  public AxesWalker getNextWalker()
  {
    return m_nextWalker;
  }

  /**
   * Set or clear the previous walker reference in the location step chain.
   *
   *
   * @param walker Reference to previous walker reference in the location 
   *               step chain, or null.
   */
  public void setPrevWalker(AxesWalker walker)
  {
    m_prevWalker = walker;
  }

  /**
   * Get the previous walker reference in the location step chain.
   *
   *
   * @return Reference to previous walker reference in the location 
   *               step chain, or null.
   */
  public AxesWalker getPrevWalker()
  {
    return m_prevWalker;
  }

  /**
   * This is simply a way to bottle-neck the return of the next node, for 
   * diagnostic purposes.
   *
   * @param n Node to return, or null.
   *
   * @return The argument.
   */
  private int returnNextNode(int n)
  {

    return n;
  }

  /**
   * Get the next node in document order on the axes.
   *
   * @return the next node in document order on the axes, or null.
   */
  protected int getNextNode()
  {
    if (m_foundLast)
      return DTM.NULL;

    if (m_isFresh)
    {
      m_currentNode = m_traverser.first(m_root);
      m_isFresh = false;
    }
    // I shouldn't have to do this the check for current node, I think.
    // numbering\numbering24.xsl fails if I don't do this.  I think 
    // it occurs as the walkers are backing up. -sb
    else if(DTM.NULL != m_currentNode) 
    {
      m_currentNode = m_traverser.next(m_root, m_currentNode);
    }

    if (DTM.NULL == m_currentNode)
      this.m_foundLast = true;

    return m_currentNode;
  }

  /**
   *  Moves the <code>TreeWalker</code> to the next visible node in document
   * order relative to the current node, and returns the new node. If the
   * current node has no next node,  or if the search for nextNode attempts
   * to step upward from the TreeWalker's root node, returns
   * <code>null</code> , and retains the current node.
   * @return  The new node, or <code>null</code> if the current node has no
   *   next node  in the TreeWalker's logical view.
   */
  public int nextNode()
  {
    int nextNode = DTM.NULL;
    AxesWalker walker = wi().getLastUsedWalker();

    while (true)
    {
      if (null == walker)
        break;

      nextNode = walker.getNextNode();

      if (DTM.NULL == nextNode)
      {

        walker = walker.m_prevWalker;
      }
      else
      {
        if (walker.acceptNode(nextNode) != DTMIterator.FILTER_ACCEPT)
        {
          continue;
        }

        if (null == walker.m_nextWalker)
        {
          wi().setLastUsedWalker(walker);

          // return walker.returnNextNode(nextNode);
          break;
        }
        else
        {
          AxesWalker prev = walker;

          walker = walker.m_nextWalker;

          walker.setRoot(nextNode);

          walker.m_prevWalker = prev;

          continue;
        }
      }  // if(null != nextNode)
    }  // while(null != walker)

    return nextNode;
  }

  //============= End TreeWalker Implementation =============

  /**
   * Get the index of the last node that can be itterated to.
   *
   *
   * @param xctxt XPath runtime context.
   *
   * @return the index of the last node that can be itterated to.
   */
  public int getLastPos(XPathContext xctxt)
  {

    int pos = getProximityPosition();
    
    AxesWalker walker;

    try
    {
      walker = (AxesWalker) clone();
    }
    catch (CloneNotSupportedException cnse)
    {
      return -1;
    }

    walker.setPredicateCount(m_predicateIndex);
    walker.setNextWalker(null);
    walker.setPrevWalker(null);

    WalkingIterator lpi = wi();
    AxesWalker savedWalker = lpi.getLastUsedWalker();

    try
    {
      lpi.setLastUsedWalker(walker);

      int next;

      while (DTM.NULL != (next = walker.nextNode()))
      {
        pos++;
      }

      // TODO: Should probably save this in the iterator.
    }
    finally
    {
      lpi.setLastUsedWalker(savedWalker);
    }

    // System.out.println("pos: "+pos);
    return pos;
  }
  
  //============= State Data =============
  
  /**
   * The DTM for the root.  This can not be used, or must be changed, 
   * for the filter walker, or any walker that can have nodes 
   * from multiple documents.
   * Never, ever, access this value without going through getDTM(int node).
   */
  private DTM m_dtm;
  
  /**
   * Set the DTM for this walker.
   * 
   * @param dtm Non-null reference to a DTM.
   */
  public void setDefaultDTM(DTM dtm)
  {
    m_dtm = dtm;
  }
  
  /**
   * Get the DTM for this walker.
   * 
   * @return Non-null reference to a DTM.
   */
  public DTM getDTM(int node)
  {
    //
    return wi().getXPathContext().getDTM(node);
  }
  
  /**
   * Returns true if all the nodes in the iteration well be returned in document 
   * order.
   * Warning: This can only be called after setRoot has been called!
   * 
   * @return true as a default.
   */
  public boolean isDocOrdered()
  {
    return true;
  }
  
  /**
   * Returns the axis being iterated, if it is known.
   * 
   * @return Axis.CHILD, etc., or -1 if the axis is not known or is of multiple 
   * types.
   */
  public int getAxis()
  {
    return m_axis;
  }
  
  /**
   * This will traverse the heararchy, calling the visitor for 
   * each member.  If the called visitor method returns 
   * false, the subtree should not be called.
   * 
   * @param owner The owner of the visitor, where that path may be 
   *              rewritten if needed.
   * @param visitor The visitor whose appropriate method will be called.
   */
  public void callVisitors(ExpressionOwner owner, XPathVisitor visitor)
  {
  	if(visitor.visitStep(owner, this))
  	{
  		callPredicateVisitors(visitor);
  		if(null != m_nextWalker)
  		{
  			m_nextWalker.callVisitors(this, visitor);
  		}
  	}
  }
  
  /**
   * @see ExpressionOwner#getExpression()
   */
  public Expression getExpression()
  {
    return m_nextWalker;
  }

  /**
   * @see ExpressionOwner#setExpression(Expression)
   */
  public void setExpression(Expression exp)
  {
  	exp.exprSetParent(this);
  	m_nextWalker = (AxesWalker)exp;
  }
  
    /**
     * @see Expression#deepEquals(Expression)
     */
    public boolean deepEquals(Expression expr)
    {
      if (!super.deepEquals(expr))
                return false;

      AxesWalker walker = (AxesWalker)expr;
      if(this.m_axis != walker.m_axis)
      	return false;

      return true;
    }

  /**
   *  The root node of the TreeWalker, as specified when it was created.
   */
  transient int m_root = DTM.NULL;

  /**
   *  The node at which the TreeWalker is currently positioned.
   */
  private transient int m_currentNode = DTM.NULL;
  
  /** True if an itteration has not begun.  */
  transient boolean m_isFresh;

  /** The next walker in the location step chain.
   *  @serial  */
  protected AxesWalker m_nextWalker;
  
  /** The previous walker in the location step chain, or null.
   *  @serial   */
  AxesWalker m_prevWalker;
  
  /** The traversal axis from where the nodes will be filtered. */
  protected int m_axis = -1;

  /** The DTM inner traversal class, that corresponds to the super axis. */
  protected DTMAxisTraverser m_traverser; 
}
