KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > xpath > internal > VariableStack


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 package com.sun.org.apache.xpath.internal;
18
19 import javax.xml.transform.TransformerException JavaDoc;
20
21 import com.sun.org.apache.xalan.internal.res.XSLMessages;
22 import com.sun.org.apache.xpath.internal.objects.XObject;
23 import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
24
25 /**
26  * Defines a class to keep track of a stack for
27  * template arguments and variables.
28  *
29  * <p>This has been changed from the previous incarnations of this
30  * class to be fairly low level.</p>
31  * @xsl.usage internal
32  */

33 public class VariableStack implements Cloneable JavaDoc
34 {
35   /**
36    * limitation for 1K
37    */

38   public static final int CLEARLIMITATION= 1024;
39
40   /**
41    * Constructor for a variable stack.
42    */

43   public VariableStack()
44   {
45     reset();
46   }
47
48   /**
49    * Returns a clone of this variable stack.
50    *
51    * @return a clone of this variable stack.
52    *
53    * @throws CloneNotSupportedException
54    */

55   public synchronized Object JavaDoc clone() throws CloneNotSupportedException JavaDoc
56   {
57
58     VariableStack vs = (VariableStack) super.clone();
59
60     // I *think* I can get away with a shallow clone here?
61
vs._stackFrames = (XObject[]) _stackFrames.clone();
62     vs._links = (int[]) _links.clone();
63
64     return vs;
65   }
66
67   /**
68    * The stack frame where all variables and params will be kept.
69    * @serial
70    */

71   XObject[] _stackFrames = new XObject[XPathContext.RECURSIONLIMIT * 2];
72
73   /**
74    * The top of the stack frame (<code>_stackFrames</code>).
75    * @serial
76    */

77   int _frameTop;
78
79   /**
80    * The bottom index of the current frame (relative to <code>_stackFrames</code>).
81    * @serial
82    */

83   private int _currentFrameBottom;
84
85   /**
86    * The stack of frame positions. I call 'em links because of distant
87    * <a HREF="http://math.millikin.edu/mprogers/Courses/currentCourses/CS481-ComputerArchitecture/cs481.Motorola68000.html">
88    * Motorola 68000 assembler</a> memories. :-)
89    * @serial
90    */

91   int[] _links = new int[XPathContext.RECURSIONLIMIT];
92
93   /**
94    * The top of the links stack.
95    */

96   int _linksTop;
97
98   /**
99    * Get the element at the given index, regardless of stackframe.
100    *
101    * @param i index from zero.
102    *
103    * @return The item at the given index.
104    */

105   public XObject elementAt(final int i)
106   {
107     return _stackFrames[i];
108   }
109
110   /**
111    * Get size of the stack.
112    *
113    * @return the total size of the execution stack.
114    */

115   public int size()
116   {
117     return _frameTop;
118   }
119
120   /**
121    * Reset the stack to a start position.
122    *
123    * @return the total size of the execution stack.
124    */

125   public void reset()
126   {
127
128     _frameTop = 0;
129     _linksTop = 0;
130
131     // Adding one here to the stack of frame positions will allow us always
132
// to look one under without having to check if we're at zero.
133
// (As long as the caller doesn't screw up link/unlink.)
134
_links[_linksTop++] = 0;
135     _stackFrames = new XObject[_stackFrames.length];
136   }
137
138   /**
139    * Set the current stack frame.
140    *
141    * @param sf The new stack frame position.
142    */

143   public void setStackFrame(int sf)
144   {
145     _currentFrameBottom = sf;
146   }
147
148   /**
149    * Get the position from where the search should start,
150    * which is either the searchStart property, or the top
151    * of the stack if that value is -1.
152    *
153    * @return The current stack frame position.
154    */

155   public int getStackFrame()
156   {
157     return _currentFrameBottom;
158   }
159
160   /**
161    * Allocates memory (called a stackframe) on the stack; used to store
162    * local variables and parameter arguments.
163    *
164    * <p>I use the link/unlink concept because of distant
165    * <a HREF="http://math.millikin.edu/mprogers/Courses/currentCourses/CS481-ComputerArchitecture/cs481.Motorola68000.html">
166    * Motorola 68000 assembler</a> memories.</p>
167    *
168    * @param size The size of the stack frame allocation. This ammount should
169    * normally be the maximum number of variables that you can have allocated
170    * at one time in the new stack frame.
171    *
172    * @return The bottom of the stack frame, from where local variable addressing
173    * should start from.
174    */

175   public int link(final int size)
176   {
177
178     _currentFrameBottom = _frameTop;
179     _frameTop += size;
180
181     if (_frameTop >= _stackFrames.length)
182     {
183       XObject newsf[] = new XObject[_stackFrames.length + XPathContext.RECURSIONLIMIT + size];
184
185       System.arraycopy(_stackFrames, 0, newsf, 0, _stackFrames.length);
186
187       _stackFrames = newsf;
188     }
189
190     if (_linksTop + 1 >= _links.length)
191     {
192       int newlinks[] = new int[_links.length + (CLEARLIMITATION * 2)];
193
194       System.arraycopy(_links, 0, newlinks, 0, _links.length);
195
196       _links = newlinks;
197     }
198
199     _links[_linksTop++] = _currentFrameBottom;
200
201     return _currentFrameBottom;
202   }
203
204   /**
205    * Free up the stack frame that was last allocated with
206    * {@link link(int size)}.
207    */

208   public void unlink()
209   {
210     _frameTop = _links[--_linksTop];
211     _currentFrameBottom = _links[_linksTop - 1];
212   }
213   
214   /**
215    * Free up the stack frame that was last allocated with
216    * {@link link(int size)}.
217    * @param currentFrame The current frame to set to
218    * after the unlink.
219    */

220   public void unlink(int currentFrame)
221   {
222     _frameTop = _links[--_linksTop];
223     _currentFrameBottom = currentFrame;
224   }
225
226   /**
227    * Set a local variable or parameter in the current stack frame.
228    *
229    *
230    * @param index Local variable index relative to the current stack
231    * frame bottom.
232    *
233    * @param val The value of the variable that is being set.
234    */

235   public void setLocalVariable(int index, XObject val)
236   {
237     _stackFrames[index + _currentFrameBottom] = val;
238   }
239
240   /**
241    * Set a local variable or parameter in the specified stack frame.
242    *
243    *
244    * @param index Local variable index relative to the current stack
245    * frame bottom.
246    * NEEDSDOC @param stackFrame
247    *
248    * @param val The value of the variable that is being set.
249    */

250   public void setLocalVariable(int index, XObject val, int stackFrame)
251   {
252     _stackFrames[index + stackFrame] = val;
253   }
254
255   /**
256    * Get a local variable or parameter in the current stack frame.
257    *
258    *
259    * @param xctxt The XPath context, which must be passed in order to
260    * lazy evaluate variables.
261    *
262    * @param index Local variable index relative to the current stack
263    * frame bottom.
264    *
265    * @return The value of the variable.
266    *
267    * @throws TransformerException
268    */

269   public XObject getLocalVariable(XPathContext xctxt, int index)
270           throws TransformerException JavaDoc
271   {
272
273     index += _currentFrameBottom;
274
275     XObject val = _stackFrames[index];
276     
277     if(null == val)
278       throw new TransformerException JavaDoc(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_VARIABLE_ACCESSED_BEFORE_BIND, null),
279                      xctxt.getSAXLocator());
280       // "Variable accessed before it is bound!", xctxt.getSAXLocator());
281

282     // Lazy execution of variables.
283
if (val.getType() == XObject.CLASS_UNRESOLVEDVARIABLE)
284       return (_stackFrames[index] = val.execute(xctxt));
285
286     return val;
287   }
288
289   /**
290    * Get a local variable or parameter in the current stack frame.
291    *
292    *
293    * @param index Local variable index relative to the given
294    * frame bottom.
295    * NEEDSDOC @param frame
296    *
297    * @return The value of the variable.
298    *
299    * @throws TransformerException
300    */

301   public XObject getLocalVariable(int index, int frame)
302           throws TransformerException JavaDoc
303   {
304
305     index += frame;
306
307     XObject val = _stackFrames[index];
308
309     return val;
310   }
311   
312   /**
313    * Get a local variable or parameter in the current stack frame.
314    *
315    *
316    * @param xctxt The XPath context, which must be passed in order to
317    * lazy evaluate variables.
318    *
319    * @param index Local variable index relative to the current stack
320    * frame bottom.
321    *
322    * @return The value of the variable.
323    *
324    * @throws TransformerException
325    */

326   public XObject getLocalVariable(XPathContext xctxt, int index, boolean destructiveOK)
327           throws TransformerException JavaDoc
328   {
329
330     index += _currentFrameBottom;
331
332     XObject val = _stackFrames[index];
333     
334     if(null == val)
335       throw new TransformerException JavaDoc(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_VARIABLE_ACCESSED_BEFORE_BIND, null),
336                      xctxt.getSAXLocator());
337       // "Variable accessed before it is bound!", xctxt.getSAXLocator());
338

339     // Lazy execution of variables.
340
if (val.getType() == XObject.CLASS_UNRESOLVEDVARIABLE)
341       return (_stackFrames[index] = val.execute(xctxt));
342
343     return destructiveOK ? val : val.getFresh();
344   }
345
346   /**
347    * Tell if a local variable has been set or not.
348    *
349    * @param index Local variable index relative to the current stack
350    * frame bottom.
351    *
352    * @return true if the value at the index is not null.
353    *
354    * @throws TransformerException
355    */

356   public boolean isLocalSet(int index) throws TransformerException JavaDoc
357   {
358     return (_stackFrames[index + _currentFrameBottom] != null);
359   }
360
361   /** NEEDSDOC Field m_nulls */
362   private static XObject[] m_nulls = new XObject[CLEARLIMITATION];
363
364   /**
365    * Use this to clear the variables in a section of the stack. This is
366    * used to clear the parameter section of the stack, so that default param
367    * values can tell if they've already been set. It is important to note that
368    * this function has a 1K limitation.
369    *
370    * @param start The start position, relative to the current local stack frame.
371    * @param len The number of slots to be cleared.
372    */

373   public void clearLocalSlots(int start, int len)
374   {
375
376     start += _currentFrameBottom;
377
378     System.arraycopy(m_nulls, 0, _stackFrames, start, len);
379   }
380
381   /**
382    * Set a global variable or parameter in the global stack frame.
383    *
384    *
385    * @param index Local variable index relative to the global stack frame
386    * bottom.
387    *
388    * @param val The value of the variable that is being set.
389    */

390   public void setGlobalVariable(final int index, final XObject val)
391   {
392     _stackFrames[index] = val;
393   }
394
395   /**
396    * Get a global variable or parameter from the global stack frame.
397    *
398    *
399    * @param xctxt The XPath context, which must be passed in order to
400    * lazy evaluate variables.
401    *
402    * @param index Global variable index relative to the global stack
403    * frame bottom.
404    *
405    * @return The value of the variable.
406    *
407    * @throws TransformerException
408    */

409   public XObject getGlobalVariable(XPathContext xctxt, final int index)
410           throws TransformerException JavaDoc
411   {
412
413     XObject val = _stackFrames[index];
414
415     // Lazy execution of variables.
416
if (val.getType() == XObject.CLASS_UNRESOLVEDVARIABLE)
417       return (_stackFrames[index] = val.execute(xctxt));
418
419     return val;
420   }
421   
422   /**
423    * Get a global variable or parameter from the global stack frame.
424    *
425    *
426    * @param xctxt The XPath context, which must be passed in order to
427    * lazy evaluate variables.
428    *
429    * @param index Global variable index relative to the global stack
430    * frame bottom.
431    *
432    * @return The value of the variable.
433    *
434    * @throws TransformerException
435    */

436   public XObject getGlobalVariable(XPathContext xctxt, final int index, boolean destructiveOK)
437           throws TransformerException JavaDoc
438   {
439
440     XObject val = _stackFrames[index];
441
442     // Lazy execution of variables.
443
if (val.getType() == XObject.CLASS_UNRESOLVEDVARIABLE)
444       return (_stackFrames[index] = val.execute(xctxt));
445
446     return destructiveOK ? val : val.getFresh();
447   }
448
449   /**
450    * Get a variable based on it's qualified name.
451    * This is for external use only.
452    *
453    * @param xctxt The XPath context, which must be passed in order to
454    * lazy evaluate variables.
455    *
456    * @param qname The qualified name of the variable.
457    *
458    * @return The evaluated value of the variable.
459    *
460    * @throws javax.xml.transform.TransformerException
461    */

462   public XObject getVariableOrParam(
463           XPathContext xctxt, com.sun.org.apache.xml.internal.utils.QName qname)
464             throws javax.xml.transform.TransformerException JavaDoc
465   {
466
467     // <<<<<<< TIGER SPECIFIC CHANGE >>>>>>>>>
468
// As we are not supporting Xalan interpretive we are taking away the functionality
469
// dependent on XSLT interpretive Transformer. Only way supported is to use XSLTC
470
// and the execution path needed for supporting standard XPath API defined by
471
// JAXP 1.3 . This method is overridden in XPath implementation to support
472
// standard XPath functionality with xpath package of Xalan
473

474     throw new javax.xml.transform.TransformerException JavaDoc(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_VAR_NOT_RESOLVABLE, new Object JavaDoc[]{qname.toString()})); //"Variable not resolvable: " + qname);
475
}
476 } // end VariableStack
477

478
Popular Tags