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