KickJava   Java API By Example, From Geeks To Geeks.

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


1 package net.sf.saxon.expr;
2 import net.sf.saxon.om.NamePool;
3 import net.sf.saxon.trans.DynamicError;
4 import net.sf.saxon.trans.XPathException;
5 import net.sf.saxon.type.ItemType;
6 import net.sf.saxon.value.Cardinality;
7 import net.sf.saxon.value.Value;
8
9 import java.io.PrintStream JavaDoc;
10 import java.util.Iterator JavaDoc;
11
12 /**
13 * Binary Expression: a numeric or boolean expression consisting of the
14 * two operands and an operator
15 */

16
17 public abstract class BinaryExpression extends ComputedExpression {
18
19     protected Expression operand0;
20     protected Expression operand1;
21     protected int operator; // represented by the token number from class Tokenizer
22

23     /**
24     * Create a binary expression identifying the two operands and the operator
25     * @param p0 the left-hand operand
26     * @param op the operator, as a token returned by the Tokenizer (e.g. Token.AND)
27     * @param p1 the right-hand operand
28     */

29
30     public BinaryExpression(Expression p0, int op, Expression p1) {
31         this.operator = op;
32         operand0 = p0;
33         operand1 = p1;
34         adoptChildExpression(p0);
35         adoptChildExpression(p1);
36     }
37
38     /**
39     * Simplify an expression
40     * @return the simplified expression
41     */

42
43      public Expression simplify(StaticContext env) throws XPathException {
44         operand0 = operand0.simplify(env);
45         operand1 = operand1.simplify(env);
46         return this;
47     }
48
49     /**
50     * Type-check the expression. Default implementation for binary operators that accept
51     * any kind of operand
52     */

53
54     public Expression typeCheck(StaticContext env, ItemType contextItemType) throws XPathException {
55         operand0 = operand0.typeCheck(env, contextItemType);
56         operand1 = operand1.typeCheck(env, contextItemType);
57         // if both operands are known, pre-evaluate the expression
58
try {
59             if ((operand0 instanceof Value) && (operand1 instanceof Value)) {
60                 return ExpressionTool.eagerEvaluate(this, null);
61             }
62         } catch (DynamicError err) {
63             // if early evaluation fails, suppress the error: the value might
64
// not be needed at run-time
65
}
66         return this;
67     }
68
69     /**
70      * Perform optimisation of an expression and its subexpressions.
71      * <p/>
72      * <p>This method is called after all references to functions and variables have been resolved
73      * to the declaration of the function or variable, and after all type checking has been done.</p>
74      *
75      * @param opt the optimizer in use. This provides access to supporting functions; it also allows
76      * different optimization strategies to be used in different circumstances.
77      * @param env the static context of the expression
78      * @param contextItemType the static type of "." at the point where this expression is invoked.
79      * The parameter is set to null if it is known statically that the context item will be undefined.
80      * If the type of the context item is not known statically, the argument is set to
81      * {@link net.sf.saxon.type.Type#ITEM_TYPE}
82      * @return the original expression, rewritten if appropriate to optimize execution
83      * @throws net.sf.saxon.trans.StaticError if an error is discovered during this phase
84      * (typically a type error)
85      */

86
87     public Expression optimize(Optimizer opt, StaticContext env, ItemType contextItemType) throws XPathException {
88         operand0 = operand0.optimize(opt, env, contextItemType);
89         operand1 = operand1.optimize(opt, env, contextItemType);
90         // if both operands are known, pre-evaluate the expression
91
try {
92             if ((operand0 instanceof Value) && (operand1 instanceof Value)) {
93                 return ExpressionTool.eagerEvaluate(this, null);
94             }
95         } catch (DynamicError err) {
96             // if early evaluation fails, suppress the error: the value might
97
// not be needed at run-time
98
}
99         return this;
100     }
101
102
103     /**
104     * Promote this expression if possible
105     */

106
107     public Expression promote(PromotionOffer offer) throws XPathException {
108         Expression exp = offer.accept(this);
109         if (exp != null) {
110             return exp;
111         } else {
112             if (offer.action != PromotionOffer.UNORDERED) {
113                 operand0 = doPromotion(operand0, offer);
114                 operand1 = doPromotion(operand1, offer);
115             }
116             return this;
117         }
118     }
119
120     /**
121     * Get the immediate subexpressions of this expression
122     */

123
124     public Iterator JavaDoc iterateSubExpressions() {
125         return new PairIterator(operand0, operand1);
126     }
127
128     /**
129      * Get the operator
130      */

131
132     public int getOperator() {
133         return operator;
134     }
135
136     /**
137      * Get the operands
138      */

139
140     public Expression[] getOperands() {
141         Expression[] ops = {operand0, operand1};
142         return ops;
143     }
144
145     /**
146     * Determine the static cardinality. Default implementation returns [0..1] if either operand
147      * can be empty, or [1..1] otherwise.
148     */

149
150     public int computeCardinality() {
151         if (Cardinality.allowsZero(operand0.getCardinality()) ||
152                 Cardinality.allowsZero(operand1.getCardinality())) {
153             return StaticProperty.ALLOWS_ZERO_OR_ONE;
154         } else {
155             return StaticProperty.EXACTLY_ONE;
156         }
157     }
158
159     /**
160      * Determine the special properties of this expression
161      * @return {@link StaticProperty#NON_CREATIVE}. This is overridden
162      * for some subclasses.
163      */

164
165     public int computeSpecialProperties() {
166         int p = super.computeSpecialProperties();
167         return p | StaticProperty.NON_CREATIVE;
168     }
169
170     protected static boolean isCommutative(int operator) {
171         return (operator == Token.AND ||
172                 operator == Token.OR ||
173                 operator == Token.UNION ||
174                 operator == Token.INTERSECT ||
175                 operator == Token.PLUS ||
176                 operator == Token.MULT ||
177                 operator == Token.EQUALS ||
178                 operator == Token.FEQ ||
179                 operator == Token.NE ||
180                 operator == Token.FNE
181                 );
182     }
183
184     /**
185      * Test if one operator is the inverse of another, so that (A op1 B) is
186      * equivalent to (B op2 A). Commutative operators are the inverse of themselves
187      * and are therefore not listed here.
188      * @param op1 the first operator
189      * @param op2 the second operator
190      * @return true if the operators are the inverse of each other
191      */

192     protected static boolean isInverse(int op1, int op2) {
193         return op1 != op2 && op1 == Token.inverse(op2);
194     }
195
196     /**
197     * Is this expression the same as another expression?
198     */

199
200     public boolean equals(Object JavaDoc other) {
201         if (other instanceof BinaryExpression) {
202             BinaryExpression b = (BinaryExpression)other;
203             if (operator == b.operator) {
204                 if (operand0.equals(b.operand0) &&
205                         operand1.equals(b.operand1)) {
206                     return true;
207                 }
208                 if (isCommutative(operator) &&
209                         operand0.equals(b.operand1) &&
210                         operand1.equals(b.operand0)) {
211                     return true;
212                 }
213             }
214             if (isInverse(operator, b.operator) &&
215                     operand0.equals(b.operand1) &&
216                     operand1.equals(b.operand0)) {
217                 return true;
218             }
219             // TODO: recognize associative operators (A|(B|C)) == ((A|B)|C)
220
}
221         return false;
222     }
223
224     /**
225     * get HashCode for comparing two expressions. Note that this hashcode gives the same
226      * result for (A op B) and for (B op A), whether or not the operator is commutative.
227     */

228
229     public int hashCode() {
230         // Ensure that an operator and its inverse get the same hash code,
231
// so that (A lt B) has the same hash code as (B gt A)
232
int op = Math.min(operator, Token.inverse(operator));
233         return ("BinaryExpression " + op).hashCode()
234                 ^ operand0.hashCode()
235                 ^ operand1.hashCode();
236     }
237
238     /**
239     * Diagnostic print of expression structure
240     */

241
242     public void display(int level, NamePool pool, PrintStream JavaDoc out) {
243         out.println(ExpressionTool.indent(level) + "operator " + displayOperator());
244         operand0.display(level+1, pool, out);
245         operand1.display(level+1, pool, out);
246     }
247
248     protected String JavaDoc displayOperator() {
249         return Token.tokens[operator];
250     }
251
252 }
253
254 //
255
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
256
// you may not use this file except in compliance with the License. You may obtain a copy of the
257
// License at http://www.mozilla.org/MPL/
258
//
259
// Software distributed under the License is distributed on an "AS IS" basis,
260
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
261
// See the License for the specific language governing rights and limitations under the License.
262
//
263
// The Original Code is: all this file.
264
//
265
// The Initial Developer of the Original Code is Michael H. Kay.
266
//
267
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
268
//
269
// Contributor(s): none.
270
//
271
Popular Tags