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    */
postCompileStep(Compiler compiler)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    */
getPositionInContextNodeList(XPathContext xctxt)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    */
execute(XPathContext xctxt)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    */
fixupVariables(java.util.Vector vars, int globalsSize)130   public void fixupVariables(java.util.Vector vars, int globalsSize)
131   {
132     // no-op
133   }
134 }
135