001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.activemq.filter;
018
019 import javax.jms.JMSException;
020
021 /**
022 * An expression which performs an operation on two expression values
023 *
024 *
025 */
026 public abstract class ArithmeticExpression extends BinaryExpression {
027
028 protected static final int INTEGER = 1;
029 protected static final int LONG = 2;
030 protected static final int DOUBLE = 3;
031
032 /**
033 * @param left
034 * @param right
035 */
036 public ArithmeticExpression(Expression left, Expression right) {
037 super(left, right);
038 }
039
040 public static Expression createPlus(Expression left, Expression right) {
041 return new ArithmeticExpression(left, right) {
042 protected Object evaluate(Object lvalue, Object rvalue) {
043 if (lvalue instanceof String) {
044 String text = (String)lvalue;
045 String answer = text + rvalue;
046 return answer;
047 } else if (lvalue instanceof Number) {
048 return plus((Number)lvalue, asNumber(rvalue));
049 }
050 throw new RuntimeException("Cannot call plus operation on: " + lvalue + " and: " + rvalue);
051 }
052
053 public String getExpressionSymbol() {
054 return "+";
055 }
056 };
057 }
058
059 public static Expression createMinus(Expression left, Expression right) {
060 return new ArithmeticExpression(left, right) {
061 protected Object evaluate(Object lvalue, Object rvalue) {
062 if (lvalue instanceof Number) {
063 return minus((Number)lvalue, asNumber(rvalue));
064 }
065 throw new RuntimeException("Cannot call minus operation on: " + lvalue + " and: " + rvalue);
066 }
067
068 public String getExpressionSymbol() {
069 return "-";
070 }
071 };
072 }
073
074 public static Expression createMultiply(Expression left, Expression right) {
075 return new ArithmeticExpression(left, right) {
076
077 protected Object evaluate(Object lvalue, Object rvalue) {
078 if (lvalue instanceof Number) {
079 return multiply((Number)lvalue, asNumber(rvalue));
080 }
081 throw new RuntimeException("Cannot call multiply operation on: " + lvalue + " and: " + rvalue);
082 }
083
084 public String getExpressionSymbol() {
085 return "*";
086 }
087 };
088 }
089
090 public static Expression createDivide(Expression left, Expression right) {
091 return new ArithmeticExpression(left, right) {
092
093 protected Object evaluate(Object lvalue, Object rvalue) {
094 if (lvalue instanceof Number) {
095 return divide((Number)lvalue, asNumber(rvalue));
096 }
097 throw new RuntimeException("Cannot call divide operation on: " + lvalue + " and: " + rvalue);
098 }
099
100 public String getExpressionSymbol() {
101 return "/";
102 }
103 };
104 }
105
106 public static Expression createMod(Expression left, Expression right) {
107 return new ArithmeticExpression(left, right) {
108
109 protected Object evaluate(Object lvalue, Object rvalue) {
110 if (lvalue instanceof Number) {
111 return mod((Number)lvalue, asNumber(rvalue));
112 }
113 throw new RuntimeException("Cannot call mod operation on: " + lvalue + " and: " + rvalue);
114 }
115
116 public String getExpressionSymbol() {
117 return "%";
118 }
119 };
120 }
121
122 protected Number plus(Number left, Number right) {
123 switch (numberType(left, right)) {
124 case INTEGER:
125 return new Integer(left.intValue() + right.intValue());
126 case LONG:
127 return new Long(left.longValue() + right.longValue());
128 default:
129 return new Double(left.doubleValue() + right.doubleValue());
130 }
131 }
132
133 protected Number minus(Number left, Number right) {
134 switch (numberType(left, right)) {
135 case INTEGER:
136 return new Integer(left.intValue() - right.intValue());
137 case LONG:
138 return new Long(left.longValue() - right.longValue());
139 default:
140 return new Double(left.doubleValue() - right.doubleValue());
141 }
142 }
143
144 protected Number multiply(Number left, Number right) {
145 switch (numberType(left, right)) {
146 case INTEGER:
147 return new Integer(left.intValue() * right.intValue());
148 case LONG:
149 return new Long(left.longValue() * right.longValue());
150 default:
151 return new Double(left.doubleValue() * right.doubleValue());
152 }
153 }
154
155 protected Number divide(Number left, Number right) {
156 return new Double(left.doubleValue() / right.doubleValue());
157 }
158
159 protected Number mod(Number left, Number right) {
160 return new Double(left.doubleValue() % right.doubleValue());
161 }
162
163 private int numberType(Number left, Number right) {
164 if (isDouble(left) || isDouble(right)) {
165 return DOUBLE;
166 } else if (left instanceof Long || right instanceof Long) {
167 return LONG;
168 } else {
169 return INTEGER;
170 }
171 }
172
173 private boolean isDouble(Number n) {
174 return n instanceof Float || n instanceof Double;
175 }
176
177 protected Number asNumber(Object value) {
178 if (value instanceof Number) {
179 return (Number)value;
180 } else {
181 throw new RuntimeException("Cannot convert value: " + value + " into a number");
182 }
183 }
184
185 public Object evaluate(MessageEvaluationContext message) throws JMSException {
186 Object lvalue = left.evaluate(message);
187 if (lvalue == null) {
188 return null;
189 }
190 Object rvalue = right.evaluate(message);
191 if (rvalue == null) {
192 return null;
193 }
194 return evaluate(lvalue, rvalue);
195 }
196
197 /**
198 * @param lvalue
199 * @param rvalue
200 * @return
201 */
202 protected abstract Object evaluate(Object lvalue, Object rvalue);
203
204 }