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