KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > el > BinaryExpr


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.el;
31
32 import com.caucho.vfs.WriteStream;
33
34 import javax.el.ELContext;
35 import javax.el.ELException;
36 import java.io.IOException JavaDoc;
37 import java.math.BigDecimal JavaDoc;
38 import java.math.BigInteger JavaDoc;
39
40 /**
41  * Represents a binary numeric operation
42  */

43 public class BinaryExpr extends Expr {
44   private int _op;
45   private Expr _left;
46   private Expr _right;
47
48   /**
49    * Creates the binary expression.
50    *
51    * @param op the binary operation's lexical code
52    * @param left the left subexpression
53    * @param right the right subexpression
54    */

55   private BinaryExpr(int op, Expr left, Expr right)
56   {
57     this._op = op;
58     this._left = left;
59     this._right = right;
60   }
61
62   public static Expr create(int op, Expr left, Expr right)
63   {
64     switch (op) {
65     case ADD:
66       return new AddExpr(left, right);
67     case SUB:
68       return new SubExpr(left, right);
69     case MUL:
70       return new MulExpr(left, right);
71     case DIV:
72       return new DivExpr(left, right);
73     case MOD:
74       return new ModExpr(left, right);
75
76     default:
77       throw new UnsupportedOperationException JavaDoc();
78     }
79   }
80
81   /**
82    * Returns true if this is a constant expression.
83    */

84   @Override JavaDoc
85   public boolean isConstant()
86   {
87     return _left.isConstant() && _right.isConstant();
88   }
89   
90   /**
91    * Evaluate the expression as an object.
92    *
93    * @param env the variable environment
94    *
95    * @return the result as an object
96    */

97   @Override JavaDoc
98   public Object JavaDoc getValue(ELContext env)
99     throws ELException
100   {
101     Object JavaDoc aObj = _left.getValue(env);
102     Object JavaDoc bObj = _right.getValue(env);
103
104     if (aObj instanceof BigDecimal JavaDoc || bObj instanceof BigDecimal JavaDoc) {
105       BigDecimal JavaDoc a = toBigDecimal(aObj, env);
106       BigDecimal JavaDoc b = toBigDecimal(bObj, env);
107       
108       switch (_op) {
109       case ADD:
110         return a.add(b);
111       case SUB:
112         return a.subtract(b);
113       case MUL:
114         return a.multiply(b);
115       case DIV:
116         return a.divide(b, BigDecimal.ROUND_HALF_UP);
117       case MOD:
118     {
119       double da = toDouble(aObj, env);
120       double db = toDouble(bObj, env);
121       
122       return new Double JavaDoc(da % db);
123     }
124       default:
125     throw new IllegalStateException JavaDoc();
126       }
127     }
128     else if (aObj instanceof BigInteger JavaDoc || bObj instanceof BigInteger JavaDoc) {
129       BigInteger JavaDoc a = toBigInteger(aObj, env);
130       BigInteger JavaDoc b = toBigInteger(bObj, env);
131       
132       switch (_op) {
133       case ADD:
134         return a.add(b);
135       case SUB:
136         return a.subtract(b);
137       case MUL:
138         return a.multiply(b);
139       case DIV:
140     {
141       BigDecimal JavaDoc da = toBigDecimal(aObj, env);
142       BigDecimal JavaDoc db = toBigDecimal(bObj, env);
143       
144       return da.divide(db, BigDecimal.ROUND_HALF_UP);
145     }
146       case MOD:
147     {
148       if (aObj instanceof Float JavaDoc ||
149           aObj instanceof Double JavaDoc ||
150           bObj instanceof Float JavaDoc ||
151           bObj instanceof Double JavaDoc) {
152         double da = toDouble(aObj, env);
153         double db = toDouble(bObj, env);
154
155         return new Double JavaDoc(da % db);
156       }
157       else
158         return a.remainder(b);
159     }
160       default:
161     throw new IllegalStateException JavaDoc();
162       }
163     }
164       
165     else if (isDouble(aObj) || isDouble(bObj)) {
166       double a = toDouble(aObj, env);
167       double b = toDouble(bObj, env);
168       double dValue = 0;
169
170       switch (_op) {
171       case ADD:
172         dValue = a + b;
173         break;
174       case SUB:
175         dValue = a - b;
176         break;
177       case MUL:
178         dValue = a * b;
179         break;
180       case DIV:
181         dValue = a / b;
182         break;
183       case MOD:
184         dValue = a % b;
185         break;
186       }
187       
188       return Double.isNaN(dValue) ? new Double JavaDoc(0) : new Double JavaDoc(dValue);
189     }
190     
191     if (aObj == null && bObj == null)
192       return new Integer JavaDoc(0);
193
194     if (bObj instanceof Double JavaDoc || bObj instanceof Float JavaDoc) {
195       double a = toDouble(aObj, env);
196       double b = ((Number JavaDoc) bObj).doubleValue();
197       double dValue = 0;
198
199       switch (_op) {
200       case ADD:
201         dValue = a + b;
202         break;
203       case SUB:
204         dValue = a - b;
205         break;
206       case MUL:
207         dValue = a * b;
208         break;
209       case DIV:
210         dValue = a / b;
211         break;
212         
213       case MOD:
214         dValue = a % b;
215         break;
216       }
217       
218       return Double.isNaN(dValue) ? new Double JavaDoc(0) : new Double JavaDoc(dValue);
219     }
220     else if (aObj instanceof Number JavaDoc) {
221       long a = ((Number JavaDoc) aObj).longValue();
222       long b = toLong(bObj, env);
223
224       switch (_op) {
225       case ADD: return new Long JavaDoc(a + b);
226       case SUB: return new Long JavaDoc(a - b);
227       case MUL: return new Long JavaDoc(a * b);
228       case DIV:
229         double dValue = (double) a / (double) b;
230         
231         return Double.isNaN(dValue) ? new Double JavaDoc(0) : new Double JavaDoc(dValue);
232           
233       case MOD: return new Long JavaDoc(a % b);
234       }
235     }
236     else if (bObj instanceof Number JavaDoc) {
237       long a = toLong(aObj, env);
238       long b = ((Number JavaDoc) bObj).longValue();
239
240       switch (_op) {
241       case ADD: return new Long JavaDoc(a + b);
242       case SUB: return new Long JavaDoc(a - b);
243       case MUL: return new Long JavaDoc(a * b);
244       case DIV:
245         double dValue = (double) a / (double) b;
246         
247         return Double.isNaN(dValue) ? new Double JavaDoc(0) : new Double JavaDoc(dValue);
248           
249       case MOD: return new Long JavaDoc(a % b);
250       }
251     }
252
253     if (isDoubleString(aObj) || isDoubleString(bObj)) {
254       double a = toDouble(aObj, env);
255       double b = toDouble(bObj, env);
256     
257       switch (_op) {
258       case ADD: return new Double JavaDoc(a + b);
259       case SUB: return new Double JavaDoc(a - b);
260       case MUL: return new Double JavaDoc(a * b);
261       case DIV:
262         double dValue = (double) a / (double) b;
263         
264         return Double.isNaN(dValue) ? new Double JavaDoc(0) : new Double JavaDoc(dValue);
265           
266       case MOD: return new Double JavaDoc(a % b);
267       }
268     }
269     else {
270       long a = toLong(aObj, env);
271       long b = toLong(bObj, env);
272
273       switch (_op) {
274       case ADD: return new Long JavaDoc(a + b);
275       case SUB: return new Long JavaDoc(a - b);
276       case MUL: return new Long JavaDoc(a * b);
277       case DIV:
278         double dValue = (double) a / (double) b;
279         
280         return Double.isNaN(dValue) ? new Double JavaDoc(0) : new Double JavaDoc(dValue);
281         
282       case MOD: return new Long JavaDoc(a % b);
283       }
284     }
285
286     return null;
287   }
288
289   /**
290    * Evaluate the expression as a long
291    *
292    * @param env the variable environment
293    *
294    * @return the result as an long
295    */

296   @Override JavaDoc
297   public long evalLong(ELContext env)
298     throws ELException
299   {
300     long a = _left.evalLong(env);
301     long b = _right.evalLong(env);
302
303     switch (_op) {
304     case ADD: return a + b;
305     case SUB: return a - b;
306     case MUL: return a * b;
307     case DIV: return (long) ((double) a / (double) b);
308     case MOD: return a % b;
309     }
310
311     ELException e = new ELException(L.l("error evaluating add {0} and {1}",
312                                         String.valueOf(a),
313                                         String.valueOf(b)));
314
315     error(e, env);
316
317     return 0;
318   }
319   
320   /**
321    * Evaluate the expression as a double
322    *
323    * @param env the variable environment
324    *
325    * @return the result as an double
326    */

327   @Override JavaDoc
328   public double evalDouble(ELContext env)
329     throws ELException
330   {
331     double a = _left.evalDouble(env);
332     double b = _right.evalDouble(env);
333
334     switch (_op) {
335     case ADD: return a + b;
336     case SUB: return a - b;
337     case MUL: return a * b;
338     case DIV: return a / b;
339     case MOD: return a % b;
340     }
341
342     ELException e = new ELException(L.l("error evaluating add {0} and {1}",
343                                         String.valueOf(a),
344                                         String.valueOf(b)));
345
346     error(e, env);
347
348     return 0;
349   }
350
351   /**
352    * Prints the Java code to recreate an LongLiteral.
353    *
354    * @param os the output stream to the *.java file
355    */

356   @Override JavaDoc
357   public void printCreate(WriteStream os)
358     throws IOException JavaDoc
359   {
360     os.print("new com.caucho.el.BinaryExpr(");
361     os.print(_op + ", ");
362     _left.printCreate(os);
363     os.print(", ");
364     _right.printCreate(os);
365     os.print(")");
366   }
367
368   /**
369    * Returns true for equal strings.
370    */

371   public boolean equals(Object JavaDoc o)
372   {
373     if (! (o instanceof BinaryExpr))
374       return false;
375
376     BinaryExpr expr = (BinaryExpr) o;
377
378     return (_op == expr._op &&
379             _left.equals(expr._left) &&
380             _right.equals(expr._right));
381   }
382   
383   /**
384    * Returns a readable representation of the expr.
385    */

386   public String JavaDoc toString()
387   {
388     String JavaDoc op;
389
390     switch (_op) {
391     case ADD:
392       op = " + ";
393       break;
394     case SUB:
395       op = " - ";
396       break;
397     case MUL:
398       op = " * ";
399       break;
400     case DIV:
401       op = " / ";
402       break;
403     case MOD:
404       op = " % ";
405       break;
406     default:
407       op = " unknown(" + _op + ") ";
408       break;
409     }
410         
411     return "(" + _left + op + _right + ")";
412   }
413 }
414
Popular Tags