KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > expr > VariableReference


1 package net.sf.saxon.expr;
2 import net.sf.saxon.om.*;
3 import net.sf.saxon.trans.XPathException;
4 import net.sf.saxon.type.AnyItemType;
5 import net.sf.saxon.type.ItemType;
6 import net.sf.saxon.value.SequenceType;
7 import net.sf.saxon.value.Value;
8 import net.sf.saxon.value.SingletonNode;
9
10 import java.io.PrintStream JavaDoc;
11
12 /**
13 * Variable reference: a reference to a variable. This may be an XSLT-defined variable, a range
14 * variable defined within the XPath expression, or a variable defined in some other static context.
15 */

16
17 public class VariableReference extends ComputedExpression implements BindingReference {
18
19     Binding binding = null; // This will be null until fixup() is called; it will also be null
20
// if the variable reference has been inlined
21
SequenceType staticType = null;
22     Value constantValue = null;
23     transient String JavaDoc displayName = null;
24
25     /**
26     * Constructor
27     * @param declaration the variable declaration to which this variable refers
28     */

29
30     public VariableReference(VariableDeclaration declaration) {
31
32         // Register this variable reference with the variable declaration. When the variable declaration
33
// is compiled, the declaration will call the fixup() method of the variable reference. Note
34
// that the object does not retain a pointer to the variable declaration, which would cause the
35
// stylesheet to be locked in memory.
36

37         // System.err.println("Register reference " + this + " with declaration " + declaration + " name=" + declaration.getVariableName());
38
declaration.registerReference(this);
39         displayName = declaration.getVariableName();
40     }
41
42     /**
43     * Simplify the expression. Does nothing.
44     */

45
46     public Expression simplify(StaticContext env) {
47         return this;
48     }
49
50     /**
51     * Set static type. This is a callback from the variable declaration object. As well
52     * as supplying the static type, it may also supply a compile-time value for the variable.
53     * As well as the type information, other static properties of the value are supplied:
54     * for example, whether the value is an ordered node-set.
55     */

56
57     public void setStaticType(SequenceType type, Value value, int properties) {
58         // System.err.println(this + " Set static type = " + type);
59
staticType = type;
60         constantValue = value;
61             // Although the variable may be a context document node-set at the point it is defined,
62
// the context at the point of use may be different, so this property cannot be transferred.
63
staticProperties = (properties &~StaticProperty.CONTEXT_DOCUMENT_NODESET) |
64                 type.getCardinality() |
65                 getDependencies();
66     }
67
68     /**
69     * Type-check the expression. At this stage details of the static type must be known.
70     * If the variable has a compile-time value, this is substituted for the variable reference
71     */

72
73     public Expression typeCheck(StaticContext env, ItemType contextItemType) throws XPathException {
74         if (constantValue != null) {
75             binding = null;
76             return constantValue;
77         }
78         if (staticType==null) {
79             throw new IllegalStateException JavaDoc("Variable $" + displayName + " has not been fixed up");
80         } else {
81             return this;
82         }
83     }
84
85     /**
86     * Type-check the expression. At this stage details of the static type must be known.
87     * If the variable has a compile-time value, this is substituted for the variable reference
88     */

89
90     public Expression optimize(Optimizer opt, StaticContext env, ItemType contextItemType) throws XPathException {
91         if (constantValue != null) {
92             binding = null;
93             return constantValue;
94         }
95         return this;
96     }
97
98     /**
99     * Fix up this variable reference to a Binding object, which enables the value of the variable
100     * to be located at run-time.
101     */

102
103     public void fixup(Binding binding) {
104         // System.err.println("Binding for " + this + " is " + binding.getVariableName());
105
this.binding = binding;
106         resetStaticProperties();
107     }
108
109     /**
110     * Determine the data type of the expression, if possible
111     * @return the type of the variable, if this can be determined statically;
112     * otherwise Type.ITEM (meaning not known in advance)
113     */

114
115     public ItemType getItemType() {
116         if (staticType==null) {
117             return AnyItemType.getInstance();
118         } else {
119             return staticType.getPrimaryType();
120         }
121     }
122
123     /**
124     * Get the static cardinality
125     */

126
127     public int computeCardinality() {
128         if (staticType==null) {
129             return StaticProperty.ALLOWS_ZERO_OR_MORE;
130         } else {
131             return staticType.getCardinality();
132         }
133     }
134
135     /**
136      * Determine the special properties of this expression
137      * @return {@link StaticProperty#NON_CREATIVE} (unless the variable is assignable using saxon:assign)
138      */

139
140     public int computeSpecialProperties() {
141         int p = super.computeSpecialProperties();
142         if (binding==null || !binding.isAssignable()) {
143             // if the variable reference is assignable, we mustn't move it, or any expression that contains it,
144
// out of a loop. The way to achieve this is to treat it as a "creative" expression, because the
145
// optimizer recognizes such expressions and handles them with care...
146
p |= StaticProperty.NON_CREATIVE;
147         }
148         return p;
149     }
150
151     /**
152     * Test if this expression is the same as another expression.
153     * (Note, we only compare expressions that
154     * have the same static and dynamic context).
155     */

156
157     public boolean equals(Object JavaDoc other) {
158         return (other instanceof VariableReference &&
159                 binding == ((VariableReference)other).binding &&
160                 binding != null);
161     }
162
163     /**
164     * get HashCode for comparing two expressions
165     */

166
167     public int hashCode() {
168         return binding==null ? 73619830 : binding.hashCode();
169     }
170
171
172     public int getIntrinsicDependencies() {
173         if (binding == null || !binding.isGlobal()) {
174             return StaticProperty.DEPENDS_ON_LOCAL_VARIABLES;
175         } else {
176             return 0;
177         }
178     }
179
180     /**
181     * Promote this expression if possible
182     */

183
184     public Expression promote(PromotionOffer offer) throws XPathException {
185         if (offer.action == PromotionOffer.INLINE_VARIABLE_REFERENCES) {
186             Expression exp = offer.accept(this);
187             if (exp != null) {
188                 // Replace the variable reference with the given expression.
189
//binding = null;
190
offer.accepted = true;
191                 return exp;
192             }
193         }
194         return this;
195     }
196
197     /**
198      * An implementation of Expression must provide at least one of the methods evaluateItem(), iterate(), or process().
199      * This method indicates which of these methods is provided. This implementation provides both all three methods
200      * natively.
201      */

202
203     public int getImplementationMethod() {
204         return EVALUATE_METHOD | ITERATE_METHOD | PROCESS_METHOD;
205     }
206
207     /**
208     * Get the value of this variable in a given context.
209     * @param c the XPathContext which contains the relevant variable bindings
210     * @return the value of the variable, if it is defined
211     * @throws XPathException if the variable is undefined
212     */

213
214     public SequenceIterator iterate(XPathContext c) throws XPathException {
215         ValueRepresentation actual = evaluateVariable(c);
216         return Value.getIterator(actual);
217     }
218
219     public Item evaluateItem(XPathContext c) throws XPathException {
220         ValueRepresentation actual = evaluateVariable(c);
221         if (actual instanceof Item) {
222             return (Item)actual;
223         }
224         return Value.asItem(actual, c);
225     }
226
227     public void process(XPathContext c) throws XPathException {
228         ValueRepresentation actual = evaluateVariable(c);
229         if (actual instanceof NodeInfo) {
230             actual = new SingletonNode((NodeInfo)actual);
231         }
232         ((Value)actual).process(c);
233     }
234
235     public ValueRepresentation evaluateVariable(XPathContext c) throws XPathException {
236
237         if (binding==null) {
238             // System.err.println("No binding for " + this);
239
throw new IllegalStateException JavaDoc("Variable $" + displayName + " has not been fixed up");
240         }
241
242         return binding.evaluateVariable(c);
243     }
244
245     /**
246     * Get the object bound to the variable
247     */

248
249     public Binding getBinding() {
250         return binding;
251     }
252
253     /**
254     * Diagnostic print of expression structure
255     */

256
257     public void display(int level, NamePool pool, PrintStream JavaDoc out) {
258         if (displayName != null) {
259             out.println(ExpressionTool.indent(level) + '$' + displayName);
260         } else {
261             out.println(ExpressionTool.indent(level) + "$(unbound variable)");
262         }
263     }
264 }
265
266 //
267
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
268
// you may not use this file except in compliance with the License. You may obtain a copy of the
269
// License at http://www.mozilla.org/MPL/
270
//
271
// Software distributed under the License is distributed on an "AS IS" basis,
272
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
273
// See the License for the specific language governing rights and limitations under the License.
274
//
275
// The Original Code is: all this file.
276
//
277
// The Initial Developer of the Original Code is Michael H. Kay.
278
//
279
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
280
//
281
// Contributor(s):
282
// Portions marked "e.g." are from Edwin Glaser (edwin@pannenleiter.de)
283
//
284
Popular Tags