ArithmeticExpression.java
001 /* Licensed to the Apache Software Foundation (ASF) under one
002  * or more contributor license agreements.  See the NOTICE file
003  * distributed with this work for additional information
004  * regarding copyright ownership.  The ASF licenses this file
005  * to you under the Apache License, Version 2.0 (the
006  * "License"); you may not use this file except in compliance
007  * with 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,
012  * software distributed under the License is distributed on an
013  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
014  * KIND, either express or implied.  See the License for the
015  * specific language governing permissions and limitations
016  * under the License.
017  */
018 package org.apache.qpid.filter;
019 
020 import org.apache.qpid.QpidException;
021 import org.apache.qpid.client.message.AbstractJMSMessage;
022 
023 
024 /**
025  * An expression which performs an operation on two expression values
026  */
027 public abstract class ArithmeticExpression extends BinaryExpression
028 {
029 
030     protected static final int INTEGER = 1;
031     protected static final int LONG = 2;
032     protected static final int DOUBLE = 3;
033 
034 
035     public ArithmeticExpression(Expression left, Expression right)
036     {
037         super(left, right);
038     }
039 
040     public static Expression createPlus(Expression left, Expression right)
041     {
042         return new ArithmeticExpression(left, right)
043             {
044                 protected Object evaluate(Object lvalue, Object rvalue)
045                 {
046                     if (lvalue instanceof String)
047                     {
048                         String text = (Stringlvalue;
049                         return text + rvalue;
050                     }
051                     else if (lvalue instanceof Number)
052                     {
053                         return plus((Numberlvalue, asNumber(rvalue));
054                     }
055 
056                     throw new RuntimeException("Cannot call plus operation on: " + lvalue + " and: " + rvalue);
057                 }
058 
059                 public String getExpressionSymbol()
060                 {
061                     return "+";
062                 }
063             };
064     }
065 
066     public static Expression createMinus(Expression left, Expression right)
067     {
068         return new ArithmeticExpression(left, right)
069             {
070                 protected Object evaluate(Object lvalue, Object rvalue)
071                 {
072                     if (lvalue instanceof Number)
073                     {
074                         return minus((Numberlvalue, asNumber(rvalue));
075                     }
076 
077                     throw new RuntimeException("Cannot call minus operation on: " + lvalue + " and: " + rvalue);
078                 }
079 
080                 public String getExpressionSymbol()
081                 {
082                     return "-";
083                 }
084             };
085     }
086 
087     public static Expression createMultiply(Expression left, Expression right)
088     {
089         return new ArithmeticExpression(left, right)
090             {
091 
092                 protected Object evaluate(Object lvalue, Object rvalue)
093                 {
094                     if (lvalue instanceof Number)
095                     {
096                         return multiply((Numberlvalue, asNumber(rvalue));
097                     }
098 
099                     throw new RuntimeException("Cannot call multiply operation on: " + lvalue + " and: " + rvalue);
100                 }
101 
102                 public String getExpressionSymbol()
103                 {
104                     return "*";
105                 }
106             };
107     }
108 
109     public static Expression createDivide(Expression left, Expression right)
110     {
111         return new ArithmeticExpression(left, right)
112             {
113 
114                 protected Object evaluate(Object lvalue, Object rvalue)
115                 {
116                     if (lvalue instanceof Number)
117                     {
118                         return divide((Numberlvalue, asNumber(rvalue));
119                     }
120 
121                     throw new RuntimeException("Cannot call divide operation on: " + lvalue + " and: " + rvalue);
122                 }
123 
124                 public String getExpressionSymbol()
125                 {
126                     return "/";
127                 }
128             };
129     }
130 
131     public static Expression createMod(Expression left, Expression right)
132     {
133         return new ArithmeticExpression(left, right)
134             {
135 
136                 protected Object evaluate(Object lvalue, Object rvalue)
137                 {
138                     if (lvalue instanceof Number)
139                     {
140                         return mod((Numberlvalue, asNumber(rvalue));
141                     }
142 
143                     throw new RuntimeException("Cannot call mod operation on: " + lvalue + " and: " + rvalue);
144                 }
145 
146                 public String getExpressionSymbol()
147                 {
148                     return "%";
149                 }
150             };
151     }
152 
153     protected Number plus(Number left, Number right)
154     {
155         switch (numberType(left, right))
156         {
157 
158         case ArithmeticExpression.INTEGER:
159             return new Integer(left.intValue() + right.intValue());
160 
161         case ArithmeticExpression.LONG:
162             return new Long(left.longValue() + right.longValue());
163 
164         default:
165             return new Double(left.doubleValue() + right.doubleValue());
166         }
167     }
168 
169     protected Number minus(Number left, Number right)
170     {
171         switch (numberType(left, right))
172         {
173 
174         case ArithmeticExpression.INTEGER:
175             return new Integer(left.intValue() - right.intValue());
176 
177         case ArithmeticExpression.LONG:
178             return new Long(left.longValue() - right.longValue());
179 
180         default:
181             return new Double(left.doubleValue() - right.doubleValue());
182         }
183     }
184 
185     protected Number multiply(Number left, Number right)
186     {
187         switch (numberType(left, right))
188         {
189 
190         case ArithmeticExpression.INTEGER:
191             return new Integer(left.intValue() * right.intValue());
192 
193         case ArithmeticExpression.LONG:
194             return new Long(left.longValue() * right.longValue());
195 
196         default:
197             return new Double(left.doubleValue() * right.doubleValue());
198         }
199     }
200 
201     protected Number divide(Number left, Number right)
202     {
203         return new Double(left.doubleValue() / right.doubleValue());
204     }
205 
206     protected Number mod(Number left, Number right)
207     {
208         return new Double(left.doubleValue() % right.doubleValue());
209     }
210 
211     private int numberType(Number left, Number right)
212     {
213         if (isDouble(left|| isDouble(right))
214         {
215             return ArithmeticExpression.DOUBLE;
216         }
217         else if ((left instanceof Long|| (right instanceof Long))
218         {
219             return ArithmeticExpression.LONG;
220         }
221         else
222         {
223             return ArithmeticExpression.INTEGER;
224         }
225     }
226 
227     private boolean isDouble(Number n)
228     {
229         return (instanceof Float|| (instanceof Double);
230     }
231 
232     protected Number asNumber(Object value)
233     {
234         if (value instanceof Number)
235         {
236             return (Numbervalue;
237         }
238         else
239         {
240             throw new RuntimeException("Cannot convert value: " + value + " into a number");
241         }
242     }
243 
244     public Object evaluate(AbstractJMSMessage messagethrows QpidException
245     {
246         Object lvalue = left.evaluate(message);
247         if (lvalue == null)
248         {
249             return null;
250         }
251 
252         Object rvalue = right.evaluate(message);
253         if (rvalue == null)
254         {
255             return null;
256         }
257 
258         return evaluate(lvalue, rvalue);
259     }
260 
261     /**
262      @param lvalue
263      @param rvalue
264      @return
265      */
266     protected abstract Object evaluate(Object lvalue, Object rvalue);
267 
268 }