1 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 ; 37 import java.math.BigDecimal ; 38 import java.math.BigInteger ; 39 40 43 public class BinaryExpr extends Expr { 44 private int _op; 45 private Expr _left; 46 private Expr _right; 47 48 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 (); 78 } 79 } 80 81 84 @Override 85 public boolean isConstant() 86 { 87 return _left.isConstant() && _right.isConstant(); 88 } 89 90 97 @Override 98 public Object getValue(ELContext env) 99 throws ELException 100 { 101 Object aObj = _left.getValue(env); 102 Object bObj = _right.getValue(env); 103 104 if (aObj instanceof BigDecimal || bObj instanceof BigDecimal ) { 105 BigDecimal a = toBigDecimal(aObj, env); 106 BigDecimal 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 (da % db); 123 } 124 default: 125 throw new IllegalStateException (); 126 } 127 } 128 else if (aObj instanceof BigInteger || bObj instanceof BigInteger ) { 129 BigInteger a = toBigInteger(aObj, env); 130 BigInteger 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 da = toBigDecimal(aObj, env); 142 BigDecimal db = toBigDecimal(bObj, env); 143 144 return da.divide(db, BigDecimal.ROUND_HALF_UP); 145 } 146 case MOD: 147 { 148 if (aObj instanceof Float || 149 aObj instanceof Double || 150 bObj instanceof Float || 151 bObj instanceof Double ) { 152 double da = toDouble(aObj, env); 153 double db = toDouble(bObj, env); 154 155 return new Double (da % db); 156 } 157 else 158 return a.remainder(b); 159 } 160 default: 161 throw new IllegalStateException (); 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 (0) : new Double (dValue); 189 } 190 191 if (aObj == null && bObj == null) 192 return new Integer (0); 193 194 if (bObj instanceof Double || bObj instanceof Float ) { 195 double a = toDouble(aObj, env); 196 double b = ((Number ) 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 (0) : new Double (dValue); 219 } 220 else if (aObj instanceof Number ) { 221 long a = ((Number ) aObj).longValue(); 222 long b = toLong(bObj, env); 223 224 switch (_op) { 225 case ADD: return new Long (a + b); 226 case SUB: return new Long (a - b); 227 case MUL: return new Long (a * b); 228 case DIV: 229 double dValue = (double) a / (double) b; 230 231 return Double.isNaN(dValue) ? new Double (0) : new Double (dValue); 232 233 case MOD: return new Long (a % b); 234 } 235 } 236 else if (bObj instanceof Number ) { 237 long a = toLong(aObj, env); 238 long b = ((Number ) bObj).longValue(); 239 240 switch (_op) { 241 case ADD: return new Long (a + b); 242 case SUB: return new Long (a - b); 243 case MUL: return new Long (a * b); 244 case DIV: 245 double dValue = (double) a / (double) b; 246 247 return Double.isNaN(dValue) ? new Double (0) : new Double (dValue); 248 249 case MOD: return new Long (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 (a + b); 259 case SUB: return new Double (a - b); 260 case MUL: return new Double (a * b); 261 case DIV: 262 double dValue = (double) a / (double) b; 263 264 return Double.isNaN(dValue) ? new Double (0) : new Double (dValue); 265 266 case MOD: return new Double (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 (a + b); 275 case SUB: return new Long (a - b); 276 case MUL: return new Long (a * b); 277 case DIV: 278 double dValue = (double) a / (double) b; 279 280 return Double.isNaN(dValue) ? new Double (0) : new Double (dValue); 281 282 case MOD: return new Long (a % b); 283 } 284 } 285 286 return null; 287 } 288 289 296 @Override 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 327 @Override 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 356 @Override 357 public void printCreate(WriteStream os) 358 throws IOException 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 371 public boolean equals(Object 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 386 public String toString() 387 { 388 String 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 |