KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > josql > expressions > ArithmeticExpression


1 /*
2  * Copyright 2004-2005 Gary Bentley
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may
5  * not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */

15 package org.josql.expressions;
16
17 import org.josql.Query;
18 import org.josql.QueryExecutionException;
19 import org.josql.QueryParseException;
20
21 import org.josql.internal.Utilities;
22
23 /**
24  * Represents the arithmetic expressions: *, +, /, - and %.
25  * It should be noted that ALL numbers in JoSQL are represented as <b>double</b> values, this
26  * allows for easy arithmetic operations without the fear of losing precision or casting
27  * issues.
28  * <p>
29  * Last Modified By: $Author: barrygently $<br />
30  * Last Modified On: $Date: 2004/12/20 16:22:43 $<br />
31  * Current Revision: $Revision: 1.2 $<br />
32  */

33 public class ArithmeticExpression extends ValueExpression
34 {
35
36     public static final int MULTIPLY = 0;
37     public static final int ADDITION = 1;
38     public static final int SUBTRACT = 2;
39     public static final int DIVIDE = 3;
40     public static final int MODULUS = 4;
41
42     private int type = -1;
43
44     private ValueExpression left = null;
45     private ValueExpression right = null;
46
47     private boolean fixedResult = false;
48
49     /**
50      * Return the expected return type. This just returns the result of calling this
51      * method on the LHS.
52      *
53      * @param q The Query object.
54      * @return The expected return type class.
55      * @throws QueryParseException If something goes wrong in determining the return type.
56      */

57     public Class JavaDoc getExpectedReturnType (Query q)
58                                     throws QueryParseException
59     {
60
61     return this.left.getExpectedReturnType (q);
62
63     }
64
65     /**
66      * Determine whether this arithmetic expression evaluates to true.
67      * Whilst this seems a little bizarre this method is needed to allow
68      * artithmetic expressions to be used in the columns part of the SELECT.
69      * <p>
70      * Thus the following could be performed:
71      * <pre>
72      * SELECT 10 + 20
73      * FROM java.lang.Object
74      * </pre>
75      *
76      * The rules are as follows:
77      * <ul>
78      * <li>If {@link #evaluate(Object,Query)} returns <code>null</code> then <code>false</code>
79      * is returned.</li>
80      * <li>If {@link #evaluate(Object,Query)} returns a number and it is greater than <b>0</b> then
81      * <code>true</code> is returned. If it is <b>0</b> or less than <b>0</b>
82      * then <code>false</code> is returned.
83      * <li>If it is anything else then <code>true</code> is returned.
84      * </ul>
85      *
86      * @param o The object to perform the expression on.
87      * @param q The Query object.
88      * @return As according to the rules above.
89      * @throws QueryExecutionException If something goes wrong during the evaluation of the
90      * expression.
91      */

92     public boolean isTrue (Object JavaDoc o,
93                Query q)
94                        throws QueryExecutionException
95     {
96
97     o = this.evaluate (o,
98                q);
99
100     if (o == null)
101     {
102
103         return false;
104
105     }
106
107     if (o instanceof Number JavaDoc)
108     {
109
110         return ((Number JavaDoc) o).doubleValue () > 0;
111
112     }
113
114     return true;
115
116     }
117
118     /**
119      * Return whether this expression has a fixed result.
120      *
121      * @param q The Query object.
122      * @return {@link Expression#hasFixedResult(Query) LHS.hasFixedResult(Query)}
123      * &&
124      * {@link Expression#hasFixedResult(Query) RHS.hasFixedResult(Query)}
125      */

126     public boolean hasFixedResult (Query q)
127     {
128
129     return this.fixedResult;
130
131     }
132
133     public void init (Query q)
134                   throws QueryParseException
135     {
136
137     this.left.init (q);
138     this.right.init (q);
139
140     this.fixedResult = this.left.hasFixedResult (q) && this.right.hasFixedResult (q);
141
142     }
143
144     /**
145      * Get the RHS value expression.
146      *
147      * @return The RHS.
148      */

149     public ValueExpression getRight ()
150     {
151
152     return this.right;
153
154     }
155
156     /**
157      * Get the LHS value expression.
158      *
159      * @return The LHS.
160      */

161     public ValueExpression getLeft ()
162     {
163
164     return this.left;
165
166     }
167
168     public void setLeft (ValueExpression exp)
169     {
170
171     this.left = exp;
172
173     }
174
175     public void setRight (ValueExpression exp)
176     {
177
178     this.right = exp;
179
180     }
181
182     public int getType ()
183     {
184
185     return this.type;
186
187     }
188
189     public void setType (int t)
190     {
191
192     this.type = t;
193
194     }
195
196     /**
197      * Evaulate this expression. Apart from the special cases the LHS and RHS must evaluate
198      * to an instance of <code>java.lang.Number</code> otherwise a QueryExecutionException is
199      * thrown.
200      * <p>
201      * Special cases:
202      * <ul>
203      * <li>If the type of the expression is + and either LHS or RHS are NOT numbers
204      * then the String concatentation of them both are returned.
205      * This works the same as in Java.</li>
206      * <li>If the type of the expression is / and the RHS is 0 then 0 is returned.</li>
207      * </ul>
208      *
209      * @param o The object to perform the expression on.
210      * @param q The Query object.
211      * @return The result of the expression, see the "special cases" for the exceptions to what would
212      * be the intuitive result.
213      * @throws QueryExecutionException If an error occurs during processing.
214      */

215     public Object JavaDoc evaluate (Object JavaDoc o,
216                 Query q)
217                         throws QueryExecutionException
218     {
219
220     Object JavaDoc l = this.left.getValue (o,
221                        q);
222
223     Object JavaDoc r = this.right.getValue (o,
224                     q);
225
226     // Special case for addition.
227
if ((this.type == ArithmeticExpression.ADDITION)
228         &&
229         (!(l instanceof Number JavaDoc)
230          ||
231          !(r instanceof Number JavaDoc)
232         )
233        )
234     {
235
236         StringBuffer JavaDoc b = new StringBuffer JavaDoc ();
237
238         if (l == null)
239         {
240
241         b.append ("null");
242
243         } else {
244
245         b.append (l);
246
247         }
248
249         if (r == null)
250         {
251
252         b.append ("null");
253
254         } else {
255
256         b.append (r);
257
258         }
259
260         return b.toString ();
261
262     }
263
264     if (l == null)
265     {
266
267         l = new Double JavaDoc (0);
268
269     }
270
271     if (r == null)
272     {
273
274         r = new Double JavaDoc (0);
275
276     }
277
278     double ld = Utilities.getDouble (l);
279     double rd = Utilities.getDouble (r);
280
281     if (this.type == ArithmeticExpression.ADDITION)
282     {
283
284         return new Double JavaDoc (ld + rd);
285
286     }
287
288     if (this.type == ArithmeticExpression.SUBTRACT)
289     {
290
291         return new Double JavaDoc (ld - rd);
292
293     }
294
295     if (this.type == ArithmeticExpression.MULTIPLY)
296     {
297
298         return new Double JavaDoc (ld * rd);
299
300     }
301
302     if (this.type == ArithmeticExpression.MODULUS)
303     {
304
305         return new Double JavaDoc (ld % rd);
306
307     }
308
309     if (this.type == ArithmeticExpression.DIVIDE)
310     {
311
312         if (rd == 0)
313         {
314
315         return new Double JavaDoc (0);
316
317         }
318
319         return new Double JavaDoc (ld / rd);
320
321     }
322
323     return null;
324
325     }
326
327     public String JavaDoc toString ()
328     {
329
330     String JavaDoc pred = "+";
331     
332     if (this.type == ArithmeticExpression.MULTIPLY)
333     {
334
335         pred = "*";
336
337     }
338
339     if (this.type == ArithmeticExpression.SUBTRACT)
340     {
341
342         pred = "-";
343
344     }
345
346     if (this.type == ArithmeticExpression.MODULUS)
347     {
348
349         pred = "%";
350
351     }
352
353     if (this.type == ArithmeticExpression.DIVIDE)
354     {
355
356         pred = "/";
357
358     }
359
360     String JavaDoc exp = this.left.toString () + " " + pred + " " + this.right.toString ();
361
362     if (this.isBracketed ())
363     {
364
365         exp = "(" + exp + ")";
366
367     }
368
369     return exp;
370
371     }
372
373 }
374
Popular Tags