UnaryExpression.java
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 messagethrows 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((Numberrvalue);
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 messagethrows 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 = (Objecti.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 messagethrows 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 messagethrows QpidException
174             {
175                 Boolean lvalue = (Booleanright.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 messagethrows 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 ((Booleanrvalue).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 = (BigDecimalleft;
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 }