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 */
018 package org.granite.gravity.selector;
019
020 import java.math.BigDecimal;
021 import java.util.Collection;
022 import java.util.HashSet;
023 import java.util.Iterator;
024 import java.util.List;
025
026 import javax.jms.JMSException;
027
028 /**
029 * An expression which performs an operation on two expression values
030 *
031 * @version $Revision: 1.3 $
032 */
033 public abstract class UnaryExpression implements Expression {
034
035 private static final BigDecimal BD_LONG_MIN_VALUE = BigDecimal.valueOf(Long.MIN_VALUE);
036 protected Expression right;
037
038 public static Expression createNegate(Expression left) {
039 return new UnaryExpression(left) {
040 public Object evaluate(MessageEvaluationContext message) throws JMSException {
041 Object rvalue = right.evaluate(message);
042 if (rvalue == null) {
043 return null;
044 }
045 if (rvalue instanceof Number) {
046 return negate((Number) rvalue);
047 }
048 return null;
049 }
050
051 @Override
052 public String getExpressionSymbol() {
053 return "-";
054 }
055 };
056 }
057
058 public static BooleanExpression createInExpression(PropertyExpression right, List<?> elements, final boolean not) {
059
060 // Use a HashSet if there are many elements.
061 Collection<?> t;
062 if( elements.size()==0 )
063 t=null;
064 else if( elements.size() < 5 )
065 t = elements;
066 else {
067 t = new HashSet<Object>(elements);
068 }
069 final Collection<?> inList = t;
070
071 return new BooleanUnaryExpression(right) {
072 public Object evaluate(MessageEvaluationContext message) throws JMSException {
073
074 Object rvalue = right.evaluate(message);
075 if (rvalue == null) {
076 return null;
077 }
078 if( rvalue.getClass()!=String.class )
079 return null;
080
081 if( (inList!=null && inList.contains(rvalue)) ^ not ) {
082 return Boolean.TRUE;
083 }
084 return Boolean.FALSE;
085
086 }
087
088 @Override
089 public String toString() {
090 StringBuffer answer = new StringBuffer();
091 answer.append(right);
092 answer.append(" ");
093 answer.append(getExpressionSymbol());
094 answer.append(" ( ");
095
096 if (inList != null) {
097 int count=0;
098 for (Iterator<?> i = inList.iterator(); i.hasNext();) {
099 Object o = i.next();
100 if( count!=0 ) {
101 answer.append(", ");
102 }
103 answer.append(o);
104 count++;
105 }
106 }
107
108 answer.append(" )");
109 return answer.toString();
110 }
111
112 @Override
113 public String getExpressionSymbol() {
114 if( not )
115 return "NOT IN";
116 return "IN";
117 }
118 };
119 }
120
121 abstract static class BooleanUnaryExpression extends UnaryExpression implements BooleanExpression {
122 public BooleanUnaryExpression(Expression left) {
123 super(left);
124 }
125
126 public boolean matches(MessageEvaluationContext message) throws JMSException {
127 Object object = evaluate(message);
128 return object!=null && object == Boolean.TRUE;
129 }
130 }
131
132
133 public static BooleanExpression createNOT(BooleanExpression left) {
134 return new BooleanUnaryExpression(left) {
135 public Object evaluate(MessageEvaluationContext message) throws JMSException {
136 Boolean lvalue = (Boolean) right.evaluate(message);
137 if (lvalue == null) {
138 return null;
139 }
140 return lvalue.booleanValue() ? Boolean.FALSE : Boolean.TRUE;
141 }
142
143 @Override
144 public String getExpressionSymbol() {
145 return "NOT";
146 }
147 };
148 }
149
150 public static BooleanExpression createBooleanCast(Expression left) {
151 return new BooleanUnaryExpression(left) {
152 public Object evaluate(MessageEvaluationContext message) throws JMSException {
153 Object rvalue = right.evaluate(message);
154 if (rvalue == null)
155 return null;
156 if (!rvalue.getClass().equals(Boolean.class))
157 return Boolean.FALSE;
158 return ((Boolean)rvalue).booleanValue() ? Boolean.TRUE : Boolean.FALSE;
159 }
160
161 @Override
162 public String toString() {
163 return right.toString();
164 }
165
166 @Override
167 public String getExpressionSymbol() {
168 return "";
169 }
170 };
171 }
172
173 private static Number negate(Number left) {
174 Class<?> clazz = left.getClass();
175 if (clazz == Integer.class) {
176 return new Integer(-left.intValue());
177 }
178 else if (clazz == Long.class) {
179 return new Long(-left.longValue());
180 }
181 else if (clazz == Float.class) {
182 return new Float(-left.floatValue());
183 }
184 else if (clazz == Double.class) {
185 return new Double(-left.doubleValue());
186 }
187 else if (clazz == BigDecimal.class) {
188 // We ussually get a big deciamal when we have Long.MIN_VALUE constant in the
189 // Selector. Long.MIN_VALUE is too big to store in a Long as a positive so we store it
190 // as a Big decimal. But it gets Negated right away.. to here we try to covert it back
191 // to a Long.
192 BigDecimal bd = (BigDecimal)left;
193 bd = bd.negate();
194
195 if( BD_LONG_MIN_VALUE.compareTo(bd)==0 ) {
196 return new Long(Long.MIN_VALUE);
197 }
198 return bd;
199 }
200 else {
201 throw new RuntimeException("Don't know how to negate: "+left);
202 }
203 }
204
205 public UnaryExpression(Expression left) {
206 this.right = left;
207 }
208
209 public Expression getRight() {
210 return right;
211 }
212
213 public void setRight(Expression expression) {
214 right = expression;
215 }
216
217 /**
218 * @see java.lang.Object#toString()
219 */
220 @Override
221 public String toString() {
222 return "(" + getExpressionSymbol() + " " + right.toString() + ")";
223 }
224
225 /**
226 * TODO: more efficient hashCode()
227 *
228 * @see java.lang.Object#hashCode()
229 */
230 @Override
231 public int hashCode() {
232 return toString().hashCode();
233 }
234
235 /**
236 * TODO: more efficient hashCode()
237 *
238 * @see java.lang.Object#equals(java.lang.Object)
239 */
240 @Override
241 public boolean equals(Object o) {
242
243 if (o == null || !this.getClass().equals(o.getClass())) {
244 return false;
245 }
246 return toString().equals(o.toString());
247
248 }
249
250 /**
251 * Returns the symbol that represents this binary expression. For example, addition is
252 * represented by "+"
253 *
254 * @return teh symbol
255 */
256 abstract public String getExpressionSymbol();
257
258 }