KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > icl > saxon > Bindery


1 package com.icl.saxon;
2 import com.icl.saxon.expr.*;
3
4
5 /**
6 * The Bindery class holds information about variables and their values.
7 *
8 * Variables are identified by a Binding object. Values can be any object, though values of XSL
9 * variables will always be of class Value.
10 */

11
12 public final class Bindery {
13
14     private Object JavaDoc[] globals; // global variables and parameters
15
private boolean[] busy;
16     private Object JavaDoc[][] stack = new Object JavaDoc[20][]; // stack for local variables and parameters
17
private Object JavaDoc[] currentStackFrame;
18     private ParameterSet globalParameters; // supplied global parameters
19
private int top = -1;
20     private int allocated = 0;
21     private int globalSpace = 0;
22     private int localSpace = 0;
23
24     /**
25     * Define how many slots are needed for global variables
26     */

27
28     public void allocateGlobals(int n) {
29         globalSpace = n;
30         globals = new Object JavaDoc[n];
31         busy = new boolean[n];
32         for (int i=0; i<n; i++) {
33             globals[i] = null;
34             busy[i] = false;
35         }
36     }
37
38     /**
39     * Define global parameters
40     * @param params The ParameterSet passed in by the user, eg. from the command line
41     */

42
43     public void defineGlobalParameters(ParameterSet params) {
44         globalParameters = params;
45     }
46
47     /**
48     * Use global parameter. This is called when a global xsl:param element is processed.
49     * If a parameter of the relevant name was supplied, it is bound to the xsl:param element.
50     * Otherwise the method returns false, so the xsl:param default will be evaluated
51     * @param fingerprint The fingerprint of the parameter
52     * @param binding The XSLParam element to bind its value to
53     * @return true if a parameter of this name was supplied, false if not
54     */

55
56     public boolean useGlobalParameter(int fingerprint, Binding binding) {
57         if (globalParameters==null) return false;
58         Value val = globalParameters.get(fingerprint);
59         if (val==null) return false;
60         globals[binding.getSlotNumber()] = val;
61         return true;
62     }
63
64     /**
65     * Define global variable
66     * @param name the name of the variable
67     * @param value the value of the variable
68     * @throws SAXException if the variable is already declared
69     */

70
71     public void defineGlobalVariable(Binding binding, Value value) {
72         globals[binding.getSlotNumber()] = value;
73     }
74
75     /**
76     * Set/Unset a flag to indicate that a particular global variable is currently being
77     * evaluated.
78     * @throws XPathException If an attempt is made to set the flag when it is already set, this means
79     * the definition of the variable is circular.
80     */

81
82     public void setExecuting(Binding binding, boolean executing)
83     throws XPathException {
84         int slot = binding.getSlotNumber();
85         if (executing) {
86             if (busy[slot]) {
87                 throw new XPathException(
88                             "Circular definition of variable " +
89                                          binding.getVariableName());
90             }
91             // It would be better to detect circular references statically
92
// at compile time. However, this is not always possible, because they
93
// can arise via execution of templates or stylesheet functions.
94
busy[slot]=true;
95         } else {
96             busy[slot]=false;
97         }
98     }
99
100     /**
101     * Test if global variable has already been evaluated
102     */

103
104     public boolean isEvaluated(Binding binding) {
105         return globals[binding.getSlotNumber()]!=null;
106     }
107
108     /**
109     * Define how many slots are needed for local variables. We work on the basis of
110     * "one size fits all": all stackframes are allocated as large as the largest one needed
111     */

112
113     public void allocateLocals(int n) {
114         if (n>localSpace) {
115             localSpace = n;
116         }
117     }
118
119     /**
120     * Start a new stack frame for local variables
121     */

122
123     public void openStackFrame(ParameterSet localParameters) {
124         if (++top >= allocated) {
125             if (allocated==stack.length) {
126                 Object JavaDoc[][] stack2 = new Object JavaDoc[allocated*2][];
127                 System.arraycopy(stack, 0, stack2, 0, allocated);
128                 stack = stack2;
129             }
130             currentStackFrame = new Object JavaDoc[localSpace+1];
131             stack[top]=currentStackFrame;
132             allocated++;
133         } else {
134             currentStackFrame = stack[top];
135         }
136         
137         currentStackFrame[0]=localParameters;
138         for (int i=1; i<currentStackFrame.length; i++) {
139             currentStackFrame[i] = null;
140         }
141     }
142
143     /**
144     * Close the current stack frame for local variables
145     */

146
147     public void closeStackFrame() {
148         top--;
149         currentStackFrame = (top<0 ? null : stack[top]);
150     }
151
152     /**
153     * Use local parameter. This is called when a local xsl:param element is processed.
154     * If a parameter of the relevant name was supplied, it is bound to the xsl:param element.
155     * Otherwise the method returns false, so the xsl:param default will be evaluated
156     * @param fingerprint The fingerprint of the parameter name
157     * @param binding The XSLParam element to bind its value to
158     * @return true if a parameter of this name was supplied, false if not
159     */

160
161     public boolean useLocalParameter(int fingerprint, Binding binding) {
162         ParameterSet params = (ParameterSet)currentStackFrame[0];
163         if (params==null) return false;
164         Value val = params.get(fingerprint);
165         currentStackFrame[binding.getSlotNumber()+1] = val;
166         return val!=null;
167     }
168
169     /**
170     * Get local parameter. This method is available to user-written node handlers invoked
171     * via the saxon:handler interface, it allows them to retrieve the values of parameters
172     * set up within a calling XSL template.
173     * @name The name of the parameter (an absolute/expanded name, i.e. URI plus local part)
174     * @return The value of the parameter, or null if not supplied
175     */

176
177     public Value getLocalParameter(int fingerprint) {
178         ParameterSet params = (ParameterSet)currentStackFrame[0];
179         if (params==null) return null;
180         return (Value)params.get(fingerprint);
181     }
182
183     /**
184     * Define local variable
185     * @param name the name of the variable
186     * @param value the value of the variable
187     */

188
189     public void defineLocalVariable(Binding binding, Value value) {
190         if (currentStackFrame==null) {
191             throw new IllegalArgumentException JavaDoc("Can't define local variable: stack is empty");
192         }
193         currentStackFrame[binding.getSlotNumber()+1] = value;
194     }
195
196     /**
197     * Get the value of a variable
198     * @param binding the Binding that establishes the unique instance of the variable
199     * @return the Value of the variable if defined, null otherwise.
200     */

201
202     public Value getValue(Binding binding) {
203         if (binding.isGlobal()) {
204             return (Value)globals[binding.getSlotNumber()];
205         } else {
206             if (currentStackFrame != null) {
207                 return (Value)currentStackFrame[binding.getSlotNumber()+1];
208             } else {
209                 return null;
210             }
211         }
212     }
213
214     /**
215     * Get the value of a variable in the given frame
216     * @param binding the Binding that establishes the unique instance of the variable
217     * @param frameId the id of the frame, see getFrameId
218     * @return the Value of the variable if defined, null otherwise.
219     */

220
221     public Value getValue( Binding binding, int frameId ) { // e.g.
222
if (binding.isGlobal()) {
223             return (Value)globals[binding.getSlotNumber()];
224         } else {
225             Object JavaDoc[] theStackFrame = stack[frameId];
226             if (theStackFrame != null) {
227                 return (Value)theStackFrame[binding.getSlotNumber()+1];
228             } else {
229                 return null;
230             }
231         }
232     }
233
234     /**
235     * Get the id of the current frame.
236     * @return an id, that may be given to getValue(Binding,int)
237     */

238
239     public int getFrameId() { // e.g.
240
return top;
241     }
242
243     /**
244     * Assign a new value to a variable
245     * @param name the name of the local or global variable or parameter (without a $ sign)
246     * @return the Value of the variable
247     * @throws SAXException if the variable has not been declared
248     */

249
250     public void assignVariable( Binding binding, Value value ) {
251         if (binding.isGlobal()) {
252             defineGlobalVariable(binding, value);
253         } else {
254             defineLocalVariable(binding, value);
255         }
256     }
257         
258 }
259
260 //
261
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
262
// you may not use this file except in compliance with the License. You may obtain a copy of the
263
// License at http://www.mozilla.org/MPL/
264
//
265
// Software distributed under the License is distributed on an "AS IS" basis,
266
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
267
// See the License for the specific language governing rights and limitations under the License.
268
//
269
// The Original Code is: all this file.
270
//
271
// The Initial Developer of the Original Code is
272
// Michael Kay of International Computers Limited (mhkay@iclway.co.uk).
273
//
274
// Contributor(s):
275
// Portions marked "e.g." are from Edwin Glaser (edwin@pannenleiter.de)
276
//
277
//
278
Popular Tags