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