1 /*** 2 * 3 * Copyright 2004 Protique Ltd 4 * Copyright 2004 Hiram Chirino 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 * 18 **/ 19 package org.codehaus.activemq.filter; 20 21 import javax.jms.JMSException; 22 import javax.jms.Message; 23 24 /*** 25 * An expression which performs an operation on two expression values 26 * 27 * @version $Revision: 1.1 $ 28 */ 29 public abstract class ArithmeticExpression extends BinaryExpression { 30 31 protected static final int INTEGER = 1; 32 protected static final int LONG = 2; 33 protected static final int DOUBLE = 3; 34 35 /*** 36 * @param left 37 * @param right 38 */ 39 public ArithmeticExpression(Expression left, Expression right) { 40 super(left, right); 41 } 42 43 public static Expression createPlus(Expression left, Expression right) { 44 return new ArithmeticExpression(left, right) { 45 protected Object evaluate(Object lvalue, Object rvalue) { 46 if (lvalue instanceof String) { 47 String text = (String) lvalue; 48 String answer = text + rvalue; 49 System.out.println("lvalue: " + lvalue + " rvalue: " + rvalue + " result: " + answer); 50 return answer; 51 } 52 else if (lvalue instanceof Number) { 53 return plus((Number) lvalue, asNumber(rvalue)); 54 } 55 throw new RuntimeException("Cannot call plus operation on: " + lvalue + " and: " + rvalue); 56 } 57 58 public String getExpressionSymbol() { 59 return "+"; 60 } 61 }; 62 } 63 64 public static Expression createMinus(Expression left, Expression right) { 65 return new ArithmeticExpression(left, right) { 66 protected Object evaluate(Object lvalue, Object rvalue) { 67 if (lvalue instanceof Number) { 68 return minus((Number) lvalue, asNumber(rvalue)); 69 } 70 throw new RuntimeException("Cannot call minus operation on: " + lvalue + " and: " + rvalue); 71 } 72 73 public String getExpressionSymbol() { 74 return "-"; 75 } 76 }; 77 } 78 79 public static Expression createMultiply(Expression left, Expression right) { 80 return new ArithmeticExpression(left, right) { 81 82 protected Object evaluate(Object lvalue, Object rvalue) { 83 if (lvalue instanceof Number) { 84 return multiply((Number) lvalue, asNumber(rvalue)); 85 } 86 throw new RuntimeException("Cannot call multiply operation on: " + lvalue + " and: " + rvalue); 87 } 88 89 public String getExpressionSymbol() { 90 return "*"; 91 } 92 }; 93 } 94 95 public static Expression createDivide(Expression left, Expression right) { 96 return new ArithmeticExpression(left, right) { 97 98 protected Object evaluate(Object lvalue, Object rvalue) { 99 if (lvalue instanceof Number) { 100 return divide((Number) lvalue, asNumber(rvalue)); 101 } 102 throw new RuntimeException("Cannot call divide operation on: " + lvalue + " and: " + rvalue); 103 } 104 105 public String getExpressionSymbol() { 106 return "/"; 107 } 108 }; 109 } 110 111 public static Expression createMod(Expression left, Expression right) { 112 return new ArithmeticExpression(left, right) { 113 114 protected Object evaluate(Object lvalue, Object rvalue) { 115 if (lvalue instanceof Number) { 116 return mod((Number) lvalue, asNumber(rvalue)); 117 } 118 throw new RuntimeException("Cannot call mod operation on: " + lvalue + " and: " + rvalue); 119 } 120 121 public String getExpressionSymbol() { 122 return "%"; 123 } 124 }; 125 } 126 127 protected Number plus(Number left, Number right) { 128 switch (numberType(left, right)) { 129 case INTEGER: 130 return new Integer(left.intValue() + right.intValue()); 131 case LONG: 132 return new Long(left.longValue() + right.longValue()); 133 default: 134 return new Double(left.doubleValue() + right.doubleValue()); 135 } 136 } 137 138 protected Number minus(Number left, Number right) { 139 switch (numberType(left, right)) { 140 case INTEGER: 141 return new Integer(left.intValue() - right.intValue()); 142 case LONG: 143 return new Long(left.longValue() - right.longValue()); 144 default: 145 return new Double(left.doubleValue() - right.doubleValue()); 146 } 147 } 148 149 protected Number multiply(Number left, Number right) { 150 switch (numberType(left, right)) { 151 case INTEGER: 152 return new Integer(left.intValue() * right.intValue()); 153 case LONG: 154 return new Long(left.longValue() * right.longValue()); 155 default: 156 return new Double(left.doubleValue() * right.doubleValue()); 157 } 158 } 159 160 protected Number divide(Number left, Number right) { 161 return new Double(left.doubleValue() / right.doubleValue()); 162 } 163 164 protected Number mod(Number left, Number right) { 165 return new Double(left.doubleValue() % right.doubleValue()); 166 } 167 168 private int numberType(Number left, Number right) { 169 if (isDouble(left) || isDouble(right)) { 170 return DOUBLE; 171 } 172 else if (left instanceof Long || right instanceof Long) { 173 return LONG; 174 } 175 else { 176 return INTEGER; 177 } 178 } 179 180 private boolean isDouble(Number n) { 181 return n instanceof Float || n instanceof Double; 182 } 183 184 protected Number asNumber(Object value) { 185 if (value instanceof Number) { 186 return (Number) value; 187 } 188 else { 189 throw new RuntimeException("Cannot convert value: " + value + " into a number"); 190 } 191 } 192 193 public Object evaluate(Message message) throws JMSException { 194 Object lvalue = left.evaluate(message); 195 if (lvalue == null) { 196 return null; 197 } 198 Object rvalue = right.evaluate(message); 199 if (rvalue == null) { 200 return null; 201 } 202 return evaluate(lvalue, rvalue); 203 } 204 205 206 /*** 207 * @param lvalue 208 * @param rvalue 209 * @return 210 */ 211 abstract protected Object evaluate(Object lvalue, Object rvalue); 212 213 }