001    /** 
002     * 
003     * Copyright 2004 Protique Ltd
004     * Copyright 2004 Hiram Chirino
005     * 
006     * Licensed under the Apache License, Version 2.0 (the "License"); 
007     * you may not use this file except in compliance with the License. 
008     * You may obtain a copy of the License at 
009     * 
010     * http://www.apache.org/licenses/LICENSE-2.0
011     * 
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS, 
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
015     * See the License for the specific language governing permissions and 
016     * limitations under the License. 
017     * 
018     **/
019    package org.activemq.filter;
020    
021    import javax.jms.JMSException;
022    import javax.jms.Message;
023    
024    /**
025     * An expression which performs an operation on two expression values
026     * 
027     * @version $Revision: 1.1.1.1 $
028     */
029    public abstract class ArithmeticExpression extends BinaryExpression {
030    
031        protected static final int INTEGER = 1;
032        protected static final int LONG = 2;
033        protected static final int DOUBLE = 3;
034    
035        /**
036         * @param left
037         * @param right
038         */
039        public ArithmeticExpression(Expression left, Expression right) {
040            super(left, right);
041        }
042    
043        public static Expression createPlus(Expression left, Expression right) {
044            return new ArithmeticExpression(left, right) {
045                protected Object evaluate(Object lvalue, Object rvalue) {
046                    if (lvalue instanceof String) {
047                        String text = (String) lvalue;
048                        String answer = text + rvalue;
049                        System.out.println("lvalue: " + lvalue + " rvalue: " + rvalue + " result: " + answer);
050                        return answer;
051                    }
052                    else if (lvalue instanceof Number) {
053                        return plus((Number) lvalue, asNumber(rvalue));
054                    }
055                    throw new RuntimeException("Cannot call plus operation on: " + lvalue + " and: " + rvalue);
056                }
057    
058                public String getExpressionSymbol() {
059                    return "+";
060                }
061            };
062        }
063    
064        public static Expression createMinus(Expression left, Expression right) {
065            return new ArithmeticExpression(left, right) {
066                protected Object evaluate(Object lvalue, Object rvalue) {
067                    if (lvalue instanceof Number) {
068                        return minus((Number) lvalue, asNumber(rvalue));
069                    }
070                    throw new RuntimeException("Cannot call minus operation on: " + lvalue + " and: " + rvalue);
071                }
072    
073                public String getExpressionSymbol() {
074                    return "-";
075                }
076            };
077        }
078    
079        public static Expression createMultiply(Expression left, Expression right) {
080            return new ArithmeticExpression(left, right) {
081    
082                protected Object evaluate(Object lvalue, Object rvalue) {
083                    if (lvalue instanceof Number) {
084                        return multiply((Number) lvalue, asNumber(rvalue));
085                    }
086                    throw new RuntimeException("Cannot call multiply operation on: " + lvalue + " and: " + rvalue);
087                }
088    
089                public String getExpressionSymbol() {
090                    return "*";
091                }
092            };
093        }
094    
095        public static Expression createDivide(Expression left, Expression right) {
096            return new ArithmeticExpression(left, right) {
097    
098                protected Object evaluate(Object lvalue, Object rvalue) {
099                    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    }