KickJava   Java API By Example, From Geeks To Geeks.

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


1 package net.sf.saxon.expr;
2 import net.sf.saxon.om.Item;
3 import net.sf.saxon.om.NamePool;
4 import net.sf.saxon.om.SequenceIterator;
5 import net.sf.saxon.trans.XPathException;
6 import net.sf.saxon.type.ItemType;
7 import net.sf.saxon.type.SchemaType;
8 import net.sf.saxon.type.Type;
9 import net.sf.saxon.value.BooleanValue;
10 import net.sf.saxon.value.Cardinality;
11 import net.sf.saxon.value.Value;
12 import net.sf.saxon.value.EmptySequence;
13 import net.sf.saxon.instruct.TailCallReturner;
14 import net.sf.saxon.instruct.TailCall;
15
16 import java.io.PrintStream JavaDoc;
17 import java.util.ArrayList JavaDoc;
18 import java.util.Iterator JavaDoc;
19
20
21 /**
22 * An IfExpression returns the value of either the "then" part or the "else" part,
23 * depending on the value of the condition
24 */

25
26 public class IfExpression extends ComputedExpression implements TailCallReturner {
27
28     private Expression condition;
29     private Expression thenExp;
30     private Expression elseExp;
31
32     /**
33     * Constructor
34     */

35
36     public IfExpression(Expression condition, Expression thenExp, Expression elseExp) {
37         this.condition = condition;
38         this.thenExp = thenExp;
39         this.elseExp = elseExp;
40         adoptChildExpression(condition);
41         adoptChildExpression(thenExp);
42         adoptChildExpression(elseExp);
43     }
44
45     public Expression getCondition() {
46         return condition;
47     }
48
49     public Expression getThenExpression() {
50         return thenExp;
51     }
52
53     public Expression getElseExpression() {
54         return elseExp;
55     }
56
57     public void setCondition(Expression exp) {
58         condition = exp;
59         adoptChildExpression(exp);
60     }
61
62     public void setThenExpression(Expression exp) {
63         thenExp = exp;
64         adoptChildExpression(exp);
65     }
66
67     /**
68     * Simplify an expression
69     */

70
71      public Expression simplify(StaticContext env) throws XPathException {
72
73         condition = condition.simplify(env);
74
75         if (condition instanceof Value) {
76             return (condition.effectiveBooleanValue(null) ? thenExp.simplify(env) : elseExp.simplify(env));
77         }
78         thenExp = thenExp.simplify(env);
79         elseExp = elseExp.simplify(env);
80         return this;
81     }
82
83     /**
84     * Type-check the expression
85     */

86
87     public Expression typeCheck(StaticContext env, ItemType contextItemType) throws XPathException {
88         condition = condition.typeCheck(env, contextItemType);
89         // If the condition after typechecking is reduced to a constant,
90
// cut it down to the appropriate branch. This is especially important
91
// when handling typeswitch, as otherwise the unused branches will
92
// generate a type error.
93
if (condition instanceof BooleanValue) {
94             if (((BooleanValue)condition).getBooleanValue()) {
95                 return thenExp.typeCheck(env, contextItemType);
96             } else {
97                 return elseExp.typeCheck(env, contextItemType);
98             }
99         } else {
100             thenExp = thenExp.typeCheck(env, contextItemType);
101             elseExp = elseExp.typeCheck(env, contextItemType);
102             adoptChildExpression(condition);
103             adoptChildExpression(thenExp);
104             adoptChildExpression(elseExp);
105             return this;
106         }
107     }
108
109     public Expression optimize(Optimizer opt, StaticContext env, ItemType contextItemType) throws XPathException {
110         condition = condition.optimize(opt, env, contextItemType);
111         thenExp = thenExp.optimize(opt, env, contextItemType);
112         elseExp = elseExp.optimize(opt, env, contextItemType);
113         return this;
114     }
115
116
117     /**
118     * Promote this expression if possible
119     */

120
121     public Expression promote(PromotionOffer offer) throws XPathException {
122         Expression exp = offer.accept(this);
123         if (exp != null) {
124             return exp;
125         } else {
126             // Promote subexpressions in the condition, but not in the "then" and "else"
127
// branches, because these are guaranteed not to be evaluated if the condition
128
// is false (bzw true).
129
condition = doPromotion(condition, offer);
130
131             // allow some types of promotion to trickle down to the subexpressions
132
if (offer.action == PromotionOffer.UNORDERED ||
133                     offer.action == PromotionOffer.INLINE_VARIABLE_REFERENCES ||
134                     offer.action == PromotionOffer.REPLACE_CURRENT) {
135                 thenExp = doPromotion(thenExp, offer);
136                 elseExp = doPromotion(elseExp, offer);
137             }
138             return this;
139         }
140     }
141
142     /**
143     * Get the immediate subexpressions of this expression
144     */

145
146     public Iterator iterateSubExpressions() {
147         ArrayList JavaDoc a = new ArrayList JavaDoc(3);
148         a.add(condition);
149         a.add(thenExp);
150         a.add(elseExp);
151         return a.iterator();
152     }
153
154     /**
155     * Mark tail calls on used-defined functions. For most expressions, this does nothing.
156     */

157
158     public boolean markTailFunctionCalls() {
159         boolean a = ExpressionTool.markTailFunctionCalls(thenExp);
160         boolean b = ExpressionTool.markTailFunctionCalls(elseExp);
161         return a || b;
162     }
163
164     /**
165      * Check that any elements and attributes constructed or returned by this expression are acceptable
166      * in the content model of a given complex type. It's always OK to say yes, since the check will be
167      * repeated at run-time. The process of checking element and attribute constructors against the content
168      * model of a complex type also registers the type of content expected of those constructors, so the
169      * static validation can continue recursively.
170      */

171
172     public void checkPermittedContents(SchemaType parentType, StaticContext env, boolean whole) throws XPathException {
173         thenExp.checkPermittedContents(parentType, env, whole);
174         elseExp.checkPermittedContents(parentType, env, whole);
175     }
176
177     /**
178     * Evaluate the conditional expression in a given context
179     * @param context the evaluation context
180     */

181
182     public Item evaluateItem(XPathContext context) throws XPathException {
183         if (condition.effectiveBooleanValue(context)) {
184             return thenExp.evaluateItem(context);
185         } else {
186             return elseExp.evaluateItem(context);
187         }
188     }
189
190     /**
191     * Iterate the path-expression in a given context
192     * @param context the evaluation context
193     */

194
195     public SequenceIterator iterate(XPathContext context) throws XPathException {
196         if (condition.effectiveBooleanValue(context)) {
197             return thenExp.iterate(context);
198         } else {
199             return elseExp.iterate(context);
200         }
201     }
202
203     /**
204      * Process this expression as an instruction, writing results to the current
205      * receiver
206      */

207
208     public void process(XPathContext context) throws XPathException {
209         if (condition.effectiveBooleanValue(context)) {
210             thenExp.process(context);
211         } else {
212             elseExp.process(context);
213         }
214     }
215
216     /**
217      * ProcessLeavingTail: called to do the real work of this instruction. This method
218      * must be implemented in each subclass. The results of the instruction are written
219      * to the current Receiver, which can be obtained via the Controller.
220      *
221      * @param context The dynamic context of the transformation, giving access to the current node,
222      * the current variables, etc.
223      * @return null if the instruction has completed execution; or a TailCall indicating
224      * a function call or template call that is delegated to the caller, to be made after the stack has
225      * been unwound so as to save stack space.
226      */

227
228     public TailCall processLeavingTail(XPathContext context) throws XPathException {
229         if (condition.effectiveBooleanValue(context)) {
230             if (thenExp instanceof TailCallReturner) {
231                 return ((TailCallReturner)thenExp).processLeavingTail(context);
232             } else {
233                 thenExp.process(context);
234                 return null;
235             }
236         } else {
237             if (elseExp instanceof TailCallReturner) {
238                 return ((TailCallReturner)elseExp).processLeavingTail(context);
239             } else {
240                 elseExp.process(context);
241                 return null;
242             }
243         }
244     }
245
246
247     /**
248     * Get data type of items in sequence returned by expression
249     */

250
251     public ItemType getItemType() {
252         return Type.getCommonSuperType(thenExp.getItemType(), elseExp.getItemType());
253     }
254
255     /**
256     * Determine the static cardinality of the result
257     */

258
259     public int computeCardinality() {
260         return Cardinality.union(thenExp.getCardinality(), elseExp.getCardinality());
261     }
262
263     /**
264     * Get the static properties of this expression (other than its type). The result is
265     * bit-signficant. These properties are used for optimizations. In general, if
266     * property bit is set, it is true, but if it is unset, the value is unknown.
267     */

268
269     public int computeSpecialProperties() {
270         // if one branch is empty, return the properties of the other branch
271
if (thenExp instanceof EmptySequence) {
272             return elseExp.getSpecialProperties();
273         }
274         if (elseExp instanceof EmptySequence) {
275             return thenExp.getSpecialProperties();
276         }
277         // otherwise return the properties that are shared by both subexpressions
278
return thenExp.getSpecialProperties() & elseExp.getSpecialProperties();
279     }
280
281     /**
282     * Diagnostic print of expression structure
283     */

284
285     public void display(int level, NamePool pool, PrintStream JavaDoc out) {
286         out.println(ExpressionTool.indent(level) + "if (");
287         condition.display(level+1, pool, out);
288         out.println(ExpressionTool.indent(level) + "then");
289         thenExp.display(level+1, pool, out);
290         out.println(ExpressionTool.indent(level) + "else");
291         elseExp.display(level+1, pool, out);
292     }
293
294 }
295
296
297
298 //
299
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
300
// you may not use this file except in compliance with the License. You may obtain a copy of the
301
// License at http://www.mozilla.org/MPL/
302
//
303
// Software distributed under the License is distributed on an "AS IS" basis,
304
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
305
// See the License for the specific language governing rights and limitations under the License.
306
//
307
// The Original Code is: all this file.
308
//
309
// The Initial Developer of the Original Code is Michael H. Kay.
310
//
311
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
312
//
313
// Contributor(s): none.
314
//
315
Popular Tags