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 */ 017package org.apache.activemq.filter; 018 019import javax.jms.JMSException; 020 021/** 022 * An expression which performs an operation on two expression values 023 * 024 * 025 */ 026public 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}