14c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson/* 24c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * Licensed to the Apache Software Foundation (ASF) under one 34c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * or more contributor license agreements. See the NOTICE file 44c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * distributed with this work for additional information 54c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * regarding copyright ownership. The ASF licenses this file 64c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * to you under the Apache License, Version 2.0 (the "License"); 74c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * you may not use this file except in compliance with the License. 84c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * You may obtain a copy of the License at 94c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * 104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * 124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * Unless required by applicable law or agreed to in writing, software 134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * See the License for the specific language governing permissions and 164c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * limitations under the License. 174c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */ 184c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson/* 194c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * $Id: FuncPosition.java 468655 2006-10-28 07:12:06Z minchau $ 204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */ 214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonpackage org.apache.xpath.functions; 224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xml.dtm.DTM; 244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xml.dtm.DTMIterator; 254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xpath.XPathContext; 264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xpath.axes.SubContextList; 274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xpath.compiler.Compiler; 284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xpath.objects.XNumber; 294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xpath.objects.XObject; 304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson/** 324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * Execute the Position() function. 334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @xsl.usage advanced 344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */ 354c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonpublic class FuncPosition extends Function 364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson{ 374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson static final long serialVersionUID = -9092846348197271582L; 384c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson private boolean m_isTopLevel; 394c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 404c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson /** 414c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * Figure out if we're executing a toplevel expression. 424c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * If so, we can't be inside of a predicate. 434c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */ 444c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson public void postCompileStep(Compiler compiler) 454c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson { 464c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson m_isTopLevel = compiler.getLocationPathDepth() == -1; 474c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson } 484c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 494c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson /** 504c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * Get the position in the current context node list. 514c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * 524c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @param xctxt Runtime XPath context. 534c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * 544c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @return The current position of the itteration in the context node list, 554c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * or -1 if there is no active context node list. 564c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */ 574c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson public int getPositionInContextNodeList(XPathContext xctxt) 584c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson { 594c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 604c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // System.out.println("FuncPosition- entry"); 614c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // If we're in a predicate, then this will return non-null. 624c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson SubContextList iter = m_isTopLevel ? null : xctxt.getSubContextList(); 634c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 644c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson if (null != iter) 654c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson { 664c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson int prox = iter.getProximityPosition(xctxt); 674c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 684c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // System.out.println("FuncPosition- prox: "+prox); 694c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson return prox; 704c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson } 714c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 724c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson DTMIterator cnl = xctxt.getContextNodeList(); 734c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 744c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson if (null != cnl) 754c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson { 764c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson int n = cnl.getCurrentNode(); 774c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson if(n == DTM.NULL) 784c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson { 794c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson if(cnl.getCurrentPos() == 0) 804c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson return 0; 814c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 824c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // Then I think we're in a sort. See sort21.xsl. So the iterator has 834c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // already been spent, and is not on the node we're processing. 844c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // It's highly possible that this is an issue for other context-list 854c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // functions. Shouldn't be a problem for last(), and it shouldn't be 864c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // a problem for current(). 874c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson try 884c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson { 894c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson cnl = cnl.cloneWithReset(); 904c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson } 914c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson catch(CloneNotSupportedException cnse) 924c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson { 934c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson throw new org.apache.xml.utils.WrappedRuntimeException(cnse); 944c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson } 954c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson int currentNode = xctxt.getContextNode(); 964c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // System.out.println("currentNode: "+currentNode); 974c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson while(DTM.NULL != (n = cnl.nextNode())) 984c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson { 994c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson if(n == currentNode) 1004c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson break; 1014c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson } 1024c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson } 1034c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // System.out.println("n: "+n); 1044c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // System.out.println("FuncPosition- cnl.getCurrentPos(): "+cnl.getCurrentPos()); 1054c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson return cnl.getCurrentPos(); 1064c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson } 1074c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 1084c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // System.out.println("FuncPosition - out of guesses: -1"); 1094c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson return -1; 1104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson } 1114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 1124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson /** 1134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * Execute the function. The function must return 1144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * a valid object. 1154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @param xctxt The current execution context. 1164c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @return A valid XObject. 1174c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * 1184c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @throws javax.xml.transform.TransformerException 1194c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */ 1204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException 1214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson { 1224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson double pos = (double) getPositionInContextNodeList(xctxt); 1234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 1244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson return new XNumber(pos); 1254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson } 1264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 1274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson /** 1284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * No arguments to process, so this does nothing. 1294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */ 1304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson public void fixupVariables(java.util.Vector vars, int globalsSize) 1314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson { 1324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson // no-op 1334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson } 1344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson} 135