001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the "License"); 007 * you may not use this file except in compliance with the License. 008 * You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 /* 019 * $Id: FuncPosition.java 468655 2006-10-28 07:12:06Z minchau $ 020 */ 021 package org.apache.xpath.functions; 022 023 import org.apache.xml.dtm.DTM; 024 import org.apache.xml.dtm.DTMIterator; 025 import org.apache.xpath.XPathContext; 026 import org.apache.xpath.axes.SubContextList; 027 import org.apache.xpath.compiler.Compiler; 028 import org.apache.xpath.objects.XNumber; 029 import org.apache.xpath.objects.XObject; 030 031 /** 032 * Execute the Position() function. 033 * @xsl.usage advanced 034 */ 035 public class FuncPosition extends Function 036 { 037 static final long serialVersionUID = -9092846348197271582L; 038 private boolean m_isTopLevel; 039 040 /** 041 * Figure out if we're executing a toplevel expression. 042 * If so, we can't be inside of a predicate. 043 */ 044 public void postCompileStep(Compiler compiler) 045 { 046 m_isTopLevel = compiler.getLocationPathDepth() == -1; 047 } 048 049 /** 050 * Get the position in the current context node list. 051 * 052 * @param xctxt Runtime XPath context. 053 * 054 * @return The current position of the itteration in the context node list, 055 * or -1 if there is no active context node list. 056 */ 057 public int getPositionInContextNodeList(XPathContext xctxt) 058 { 059 060 // System.out.println("FuncPosition- entry"); 061 // If we're in a predicate, then this will return non-null. 062 SubContextList iter = m_isTopLevel ? null : xctxt.getSubContextList(); 063 064 if (null != iter) 065 { 066 int prox = iter.getProximityPosition(xctxt); 067 068 // System.out.println("FuncPosition- prox: "+prox); 069 return prox; 070 } 071 072 DTMIterator cnl = xctxt.getContextNodeList(); 073 074 if (null != cnl) 075 { 076 int n = cnl.getCurrentNode(); 077 if(n == DTM.NULL) 078 { 079 if(cnl.getCurrentPos() == 0) 080 return 0; 081 082 // Then I think we're in a sort. See sort21.xsl. So the iterator has 083 // already been spent, and is not on the node we're processing. 084 // It's highly possible that this is an issue for other context-list 085 // functions. Shouldn't be a problem for last(), and it shouldn't be 086 // a problem for current(). 087 try 088 { 089 cnl = cnl.cloneWithReset(); 090 } 091 catch(CloneNotSupportedException cnse) 092 { 093 throw new org.apache.xml.utils.WrappedRuntimeException(cnse); 094 } 095 int currentNode = xctxt.getContextNode(); 096 // System.out.println("currentNode: "+currentNode); 097 while(DTM.NULL != (n = cnl.nextNode())) 098 { 099 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 }