KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xalan > transformer > CountersTable


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: CountersTable.java,v 1.13 2004/02/16 20:41:30 minchau Exp $
18  */

19 package org.apache.xalan.transformer;
20
21 import java.util.Hashtable JavaDoc;
22 import java.util.Vector JavaDoc;
23
24 import javax.xml.transform.TransformerException JavaDoc;
25
26 import org.apache.xalan.templates.ElemNumber;
27 import org.apache.xml.dtm.DTM;
28 import org.apache.xpath.NodeSetDTM;
29 import org.apache.xpath.XPathContext;
30
31 /**
32  * This is a table of counters, keyed by ElemNumber objects, each
33  * of which has a list of Counter objects. This really isn't a true
34  * table, it is more like a list of lists (there must be a technical
35  * term for that...).
36  * @xsl.usage internal
37  */

38 public class CountersTable extends Hashtable JavaDoc
39 {
40
41   /**
42    * Construct a CountersTable.
43    */

44   public CountersTable(){}
45
46   /**
47    * Get the list of counters that corresponds to
48    * the given ElemNumber object.
49    *
50    * @param numberElem the given xsl:number element.
51    *
52    * @return the list of counters that corresponds to
53    * the given ElemNumber object.
54    */

55   Vector JavaDoc getCounters(ElemNumber numberElem)
56   {
57
58     Vector JavaDoc counters = (Vector JavaDoc) this.get(numberElem);
59
60     return (null == counters) ? putElemNumber(numberElem) : counters;
61   }
62
63   /**
64    * Put a counter into the table and create an empty
65    * vector as it's value.
66    *
67    * @param numberElem the given xsl:number element.
68    *
69    * @return an empty vector to be used to store counts
70    * for this number element.
71    */

72   Vector JavaDoc putElemNumber(ElemNumber numberElem)
73   {
74
75     Vector JavaDoc counters = new Vector JavaDoc();
76
77     this.put(numberElem, counters);
78
79     return counters;
80   }
81
82   /**
83    * Place to collect new counters.
84    */

85   transient private NodeSetDTM m_newFound;
86
87   /**
88    * Add a list of counted nodes that were built in backwards document
89    * order, or a list of counted nodes that are in forwards document
90    * order.
91    *
92    * @param flist Vector of nodes built in forwards document order
93    * @param blist Vector of nodes built in backwards document order
94    */

95   void appendBtoFList(NodeSetDTM flist, NodeSetDTM blist)
96   {
97
98     int n = blist.size();
99
100     for (int i = (n - 1); i >= 0; i--)
101     {
102       flist.addElement(blist.item(i));
103     }
104   }
105
106   // For diagnostics
107

108   /** Number of counters created so far */
109   transient int m_countersMade = 0;
110
111   /**
112    * Count forward until the given node is found, or until
113    * we have looked to the given amount.
114    *
115    * @param support The XPath context to use
116    * @param numberElem The given xsl:number element.
117    * @param node The node to count.
118    *
119    * @return The node count, or 0 if not found.
120    *
121    * @throws TransformerException
122    */

123   public int countNode(XPathContext support, ElemNumber numberElem, int node)
124           throws TransformerException JavaDoc
125   {
126
127     int count = 0;
128     Vector JavaDoc counters = getCounters(numberElem);
129     int nCounters = counters.size();
130
131     // XPath countMatchPattern = numberElem.getCountMatchPattern(support, node);
132
// XPath fromMatchPattern = numberElem.m_fromMatchPattern;
133
int target = numberElem.getTargetNode(support, node);
134
135     if (DTM.NULL != target)
136     {
137       for (int i = 0; i < nCounters; i++)
138       {
139         Counter counter = (Counter) counters.elementAt(i);
140
141         count = counter.getPreviouslyCounted(support, target);
142
143         if (count > 0)
144           return count;
145       }
146
147       // In the loop below, we collect the nodes in backwards doc order, so
148
// we don't have to do inserts, but then we store the nodes in forwards
149
// document order, so we don't have to insert nodes into that list,
150
// so that's what the appendBtoFList stuff is all about. In cases
151
// of forward counting by one, this will mean a single node copy from
152
// the backwards list (m_newFound) to the forwards list (counter.m_countNodes).
153
count = 0;
154       if (m_newFound == null)
155         m_newFound = new NodeSetDTM(support.getDTMManager());
156
157       for (; DTM.NULL != target;
158               target = numberElem.getPreviousNode(support, target))
159       {
160
161         // First time in, we should not have to check for previous counts,
162
// since the original target node was already checked in the
163
// block above.
164
if (0 != count)
165         {
166           for (int i = 0; i < nCounters; i++)
167           {
168             Counter counter = (Counter) counters.elementAt(i);
169             int cacheLen = counter.m_countNodes.size();
170
171             if ((cacheLen > 0)
172                     && (counter.m_countNodes.elementAt(cacheLen
173                                                       - 1) == target))
174             {
175               count += (cacheLen + counter.m_countNodesStartCount);
176
177               if (cacheLen > 0)
178                 appendBtoFList(counter.m_countNodes, m_newFound);
179
180               m_newFound.removeAllElements();
181
182               return count;
183             }
184           }
185         }
186
187         m_newFound.addElement(target);
188
189         count++;
190       }
191
192       // If we got to this point, then we didn't find a counter, so make
193
// one and add it to the list.
194
Counter counter = new Counter(numberElem, new NodeSetDTM(support.getDTMManager()));
195
196       m_countersMade++; // for diagnostics
197

198       appendBtoFList(counter.m_countNodes, m_newFound);
199       m_newFound.removeAllElements();
200       counters.addElement(counter);
201     }
202
203     return count;
204   }
205 }
206
Popular Tags