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: Counter.java 468645 2006-10-28 06:57:24Z minchau $
020 */
021 package org.apache.xalan.transformer;
022
023 import javax.xml.transform.TransformerException;
024
025 import org.apache.xalan.templates.ElemNumber;
026 import org.apache.xml.dtm.DTM;
027 import org.apache.xpath.NodeSetDTM;
028 import org.apache.xpath.XPathContext;
029
030 /**
031 * A class that does incremental counting for support of xsl:number.
032 * This class stores a cache of counted nodes (m_countNodes).
033 * It tries to cache the counted nodes in document order...
034 * the node count is based on its position in the cache list
035 * @xsl.usage internal
036 */
037 public class Counter
038 {
039
040 /**
041 * Set the maximum ammount the m_countNodes list can
042 * grow to.
043 */
044 static final int MAXCOUNTNODES = 500;
045
046 /**
047 * The start count from where m_countNodes counts
048 * from. In other words, the count of a given node
049 * in the m_countNodes vector is node position +
050 * m_countNodesStartCount.
051 */
052 int m_countNodesStartCount = 0;
053
054 /**
055 * A vector of all nodes counted so far.
056 */
057 NodeSetDTM m_countNodes;
058
059 /**
060 * The node from where the counting starts. This is needed to
061 * find a counter if the node being counted is not immediatly
062 * found in the m_countNodes vector.
063 */
064 int m_fromNode = DTM.NULL;
065
066 /**
067 * The owning xsl:number element.
068 */
069 ElemNumber m_numberElem;
070
071 /**
072 * Value to store result of last getCount call, for benifit
073 * of returning val from CountersTable.getCounterByCounted,
074 * who calls getCount.
075 */
076 int m_countResult;
077
078 /**
079 * Construct a counter object.
080 *
081 * @param numberElem The owning xsl:number element.
082 * @param countNodes A vector of all nodes counted so far.
083 *
084 * @throws TransformerException
085 */
086 Counter(ElemNumber numberElem, NodeSetDTM countNodes) throws TransformerException
087 {
088 m_countNodes = countNodes;
089 m_numberElem = numberElem;
090 }
091
092 /**
093 * Construct a counter object.
094 *
095 * @param numberElem The owning xsl:number element.
096 *
097 * @throws TransformerException
098 *
099 Counter(ElemNumber numberElem) throws TransformerException
100 {
101 m_numberElem = numberElem;
102 }*/
103
104 /**
105 * Try and find a node that was previously counted. If found,
106 * return a positive integer that corresponds to the count.
107 *
108 * @param support The XPath context to use
109 * @param node The node to be counted.
110 *
111 * @return The count of the node, or -1 if not found.
112 */
113 int getPreviouslyCounted(XPathContext support, int node)
114 {
115
116 int n = m_countNodes.size();
117
118 m_countResult = 0;
119
120 for (int i = n - 1; i >= 0; i--)
121 {
122 int countedNode = m_countNodes.elementAt(i);
123
124 if (node == countedNode)
125 {
126
127 // Since the list is in backwards order, the count is
128 // how many are in the rest of the list.
129 m_countResult = i + 1 + m_countNodesStartCount;
130
131 break;
132 }
133
134 DTM dtm = support.getDTM(countedNode);
135
136 // Try to see if the given node falls after the counted node...
137 // if it does, don't keep searching backwards.
138 if (dtm.isNodeAfter(countedNode, node))
139 break;
140 }
141
142 return m_countResult;
143 }
144
145 /**
146 * Get the last node in the list.
147 *
148 * @return the last node in the list.
149 */
150 int getLast()
151 {
152
153 int size = m_countNodes.size();
154
155 return (size > 0) ? m_countNodes.elementAt(size - 1) : DTM.NULL;
156 }
157 }