Home | History | Annotate | Download | only in functions
      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one
      3  * or more contributor license agreements. See the NOTICE file
      4  * distributed with this work for additional information
      5  * regarding copyright ownership. The ASF licenses this file
      6  * to you under the Apache License, Version 2.0 (the  "License");
      7  * you may not use this file except in compliance with the License.
      8  * You may obtain a copy of the License at
      9  *
     10  *     http://www.apache.org/licenses/LICENSE-2.0
     11  *
     12  * Unless required by applicable law or agreed to in writing, software
     13  * distributed under the License is distributed on an "AS IS" BASIS,
     14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15  * See the License for the specific language governing permissions and
     16  * limitations under the License.
     17  */
     18 /*
     19  * $Id: FuncPosition.java 468655 2006-10-28 07:12:06Z minchau $
     20  */
     21 package org.apache.xpath.functions;
     22 
     23 import org.apache.xml.dtm.DTM;
     24 import org.apache.xml.dtm.DTMIterator;
     25 import org.apache.xpath.XPathContext;
     26 import org.apache.xpath.axes.SubContextList;
     27 import org.apache.xpath.compiler.Compiler;
     28 import org.apache.xpath.objects.XNumber;
     29 import org.apache.xpath.objects.XObject;
     30 
     31 /**
     32  * Execute the Position() function.
     33  * @xsl.usage advanced
     34  */
     35 public class FuncPosition extends Function
     36 {
     37     static final long serialVersionUID = -9092846348197271582L;
     38   private boolean m_isTopLevel;
     39 
     40   /**
     41    * Figure out if we're executing a toplevel expression.
     42    * If so, we can't be inside of a predicate.
     43    */
     44   public void postCompileStep(Compiler compiler)
     45   {
     46     m_isTopLevel = compiler.getLocationPathDepth() == -1;
     47   }
     48 
     49   /**
     50    * Get the position in the current context node list.
     51    *
     52    * @param xctxt Runtime XPath context.
     53    *
     54    * @return The current position of the itteration in the context node list,
     55    *         or -1 if there is no active context node list.
     56    */
     57   public int getPositionInContextNodeList(XPathContext xctxt)
     58   {
     59 
     60     // System.out.println("FuncPosition- entry");
     61     // If we're in a predicate, then this will return non-null.
     62     SubContextList iter = m_isTopLevel ? null : xctxt.getSubContextList();
     63 
     64     if (null != iter)
     65     {
     66       int prox = iter.getProximityPosition(xctxt);
     67 
     68       // System.out.println("FuncPosition- prox: "+prox);
     69       return prox;
     70     }
     71 
     72     DTMIterator cnl = xctxt.getContextNodeList();
     73 
     74     if (null != cnl)
     75     {
     76       int n = cnl.getCurrentNode();
     77       if(n == DTM.NULL)
     78       {
     79         if(cnl.getCurrentPos() == 0)
     80           return 0;
     81 
     82         // Then I think we're in a sort.  See sort21.xsl. So the iterator has
     83         // already been spent, and is not on the node we're processing.
     84         // It's highly possible that this is an issue for other context-list
     85         // functions.  Shouldn't be a problem for last(), and it shouldn't be
     86         // a problem for current().
     87         try
     88         {
     89           cnl = cnl.cloneWithReset();
     90         }
     91         catch(CloneNotSupportedException cnse)
     92         {
     93           throw new org.apache.xml.utils.WrappedRuntimeException(cnse);
     94         }
     95         int currentNode = xctxt.getContextNode();
     96         // System.out.println("currentNode: "+currentNode);
     97         while(DTM.NULL != (n = cnl.nextNode()))
     98         {
     99           if(n == currentNode)
    100             break;
    101         }
    102       }
    103       // System.out.println("n: "+n);
    104       // System.out.println("FuncPosition- cnl.getCurrentPos(): "+cnl.getCurrentPos());
    105       return cnl.getCurrentPos();
    106     }
    107 
    108     // System.out.println("FuncPosition - out of guesses: -1");
    109     return -1;
    110   }
    111 
    112   /**
    113    * Execute the function.  The function must return
    114    * a valid object.
    115    * @param xctxt The current execution context.
    116    * @return A valid XObject.
    117    *
    118    * @throws javax.xml.transform.TransformerException
    119    */
    120   public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
    121   {
    122     double pos = (double) getPositionInContextNodeList(xctxt);
    123 
    124     return new XNumber(pos);
    125   }
    126 
    127   /**
    128    * No arguments to process, so this does nothing.
    129    */
    130   public void fixupVariables(java.util.Vector vars, int globalsSize)
    131   {
    132     // no-op
    133   }
    134 }
    135