KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > activemq > filter > ComparisonExpression


1 /**
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one or more
4  * contributor license agreements. See the NOTICE file distributed with
5  * this work for additional information regarding copyright ownership.
6  * The ASF licenses this file to You under the Apache License, Version 2.0
7  * (the "License"); you may not use this file except in compliance with
8  * the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */

18 package org.apache.activemq.filter;
19
20 import java.util.HashSet JavaDoc;
21 import java.util.List JavaDoc;
22 import java.util.regex.Pattern JavaDoc;
23
24 import javax.jms.JMSException JavaDoc;
25
26 /**
27  * A filter performing a comparison of two objects
28  *
29  * @version $Revision: 1.2 $
30  */

31 public abstract class ComparisonExpression extends BinaryExpression implements BooleanExpression {
32
33     public static BooleanExpression createBetween(Expression value, Expression left, Expression right) {
34         return LogicExpression.createAND(createGreaterThanEqual(value, left), createLessThanEqual(value, right));
35     }
36
37     public static BooleanExpression createNotBetween(Expression value, Expression left, Expression right) {
38         return LogicExpression.createOR(createLessThan(value, left), createGreaterThan(value, right));
39     }
40
41     static final private HashSet JavaDoc REGEXP_CONTROL_CHARS = new HashSet JavaDoc();
42
43     static {
44         REGEXP_CONTROL_CHARS.add(new Character JavaDoc('.'));
45         REGEXP_CONTROL_CHARS.add(new Character JavaDoc('\\'));
46         REGEXP_CONTROL_CHARS.add(new Character JavaDoc('['));
47         REGEXP_CONTROL_CHARS.add(new Character JavaDoc(']'));
48         REGEXP_CONTROL_CHARS.add(new Character JavaDoc('^'));
49         REGEXP_CONTROL_CHARS.add(new Character JavaDoc('$'));
50         REGEXP_CONTROL_CHARS.add(new Character JavaDoc('?'));
51         REGEXP_CONTROL_CHARS.add(new Character JavaDoc('*'));
52         REGEXP_CONTROL_CHARS.add(new Character JavaDoc('+'));
53         REGEXP_CONTROL_CHARS.add(new Character JavaDoc('{'));
54         REGEXP_CONTROL_CHARS.add(new Character JavaDoc('}'));
55         REGEXP_CONTROL_CHARS.add(new Character JavaDoc('|'));
56         REGEXP_CONTROL_CHARS.add(new Character JavaDoc('('));
57         REGEXP_CONTROL_CHARS.add(new Character JavaDoc(')'));
58         REGEXP_CONTROL_CHARS.add(new Character JavaDoc(':'));
59         REGEXP_CONTROL_CHARS.add(new Character JavaDoc('&'));
60         REGEXP_CONTROL_CHARS.add(new Character JavaDoc('<'));
61         REGEXP_CONTROL_CHARS.add(new Character JavaDoc('>'));
62         REGEXP_CONTROL_CHARS.add(new Character JavaDoc('='));
63         REGEXP_CONTROL_CHARS.add(new Character JavaDoc('!'));
64     }
65
66     static class LikeExpression extends UnaryExpression implements BooleanExpression {
67
68         Pattern JavaDoc likePattern;
69
70         /**
71          * @param left
72          */

73         public LikeExpression(Expression right, String JavaDoc like, int escape) {
74             super(right);
75
76             StringBuffer JavaDoc regexp = new StringBuffer JavaDoc(like.length() * 2);
77             regexp.append("\\A"); // The beginning of the input
78
for (int i = 0; i < like.length(); i++) {
79                 char c = like.charAt(i);
80                 if (escape == (0xFFFF & c)) {
81                     i++;
82                     if (i >= like.length()) {
83                         // nothing left to escape...
84
break;
85                     }
86
87                     char t = like.charAt(i);
88                     regexp.append("\\x");
89                     regexp.append(Integer.toHexString(0xFFFF & t));
90                 }
91                 else if (c == '%') {
92                     regexp.append(".*?"); // Do a non-greedy match
93
}
94                 else if (c == '_') {
95                     regexp.append("."); // match one
96
}
97                 else if (REGEXP_CONTROL_CHARS.contains(new Character JavaDoc(c))) {
98                     regexp.append("\\x");
99                     regexp.append(Integer.toHexString(0xFFFF & c));
100                 }
101                 else {
102                     regexp.append(c);
103                 }
104             }
105             regexp.append("\\z"); // The end of the input
106

107             likePattern = Pattern.compile(regexp.toString(), Pattern.DOTALL);
108         }
109
110         /**
111          * @see org.apache.activemq.filter.UnaryExpression#getExpressionSymbol()
112          */

113         public String JavaDoc getExpressionSymbol() {
114             return "LIKE";
115         }
116
117         /**
118          * @see org.apache.activemq.filter.Expression#evaluate(MessageEvaluationContext)
119          */

120         public Object JavaDoc evaluate(MessageEvaluationContext message) throws JMSException JavaDoc {
121
122             Object JavaDoc rv = this.getRight().evaluate(message);
123
124             if (rv == null) {
125                 return null;
126             }
127
128             if (!(rv instanceof String JavaDoc)) {
129                 return Boolean.FALSE;
130                 //throw new RuntimeException("LIKE can only operate on String identifiers. LIKE attemped on: '" + rv.getClass());
131
}
132
133             return likePattern.matcher((String JavaDoc) rv).matches() ? Boolean.TRUE : Boolean.FALSE;
134         }
135         
136         public boolean matches(MessageEvaluationContext message) throws JMSException JavaDoc {
137             Object JavaDoc object = evaluate(message);
138             return object!=null && object==Boolean.TRUE;
139         }
140     }
141
142     public static BooleanExpression createLike(Expression left, String JavaDoc right, String JavaDoc escape) {
143         if (escape != null && escape.length() != 1) {
144             throw new RuntimeException JavaDoc("The ESCAPE string litteral is invalid. It can only be one character. Litteral used: " + escape);
145         }
146         int c = -1;
147         if (escape != null) {
148             c = 0xFFFF & escape.charAt(0);
149         }
150
151         return new LikeExpression(left, right, c);
152     }
153
154     public static BooleanExpression createNotLike(Expression left, String JavaDoc right, String JavaDoc escape) {
155         return UnaryExpression.createNOT(createLike(left, right, escape));
156     }
157
158     public static BooleanExpression createInFilter(Expression left, List JavaDoc elements) {
159         
160         if( !(left instanceof PropertyExpression) )
161             throw new RuntimeException JavaDoc("Expected a property for In expression, got: "+left);
162         return UnaryExpression.createInExpression((PropertyExpression)left, elements, false);
163         
164     }
165
166     public static BooleanExpression createNotInFilter(Expression left, List JavaDoc elements) {
167         
168         if( !(left instanceof PropertyExpression) )
169             throw new RuntimeException JavaDoc("Expected a property for In expression, got: "+left);
170         return UnaryExpression.createInExpression((PropertyExpression)left, elements, true);
171
172     }
173
174     public static BooleanExpression createIsNull(Expression left) {
175         return doCreateEqual(left, ConstantExpression.NULL);
176     }
177
178     public static BooleanExpression createIsNotNull(Expression left) {
179         return UnaryExpression.createNOT(doCreateEqual(left, ConstantExpression.NULL));
180     }
181
182     public static BooleanExpression createNotEqual(Expression left, Expression right) {
183         return UnaryExpression.createNOT(createEqual(left, right));
184     }
185
186     public static BooleanExpression createEqual(Expression left, Expression right) {
187         checkEqualOperand(left);
188         checkEqualOperand(right);
189         checkEqualOperandCompatability(left, right);
190         return doCreateEqual(left, right);
191     }
192     
193     private static BooleanExpression doCreateEqual(Expression left, Expression right) {
194         return new ComparisonExpression(left, right) {
195
196             public Object JavaDoc evaluate(MessageEvaluationContext message) throws JMSException JavaDoc {
197                 Object JavaDoc lv = left.evaluate(message);
198                 Object JavaDoc rv = right.evaluate(message);
199                 
200                 // Iff one of the values is null
201
if (lv == null ^ rv == null) {
202                     return Boolean.FALSE;
203                 }
204                 if (lv == rv || lv.equals(rv)) {
205                     return Boolean.TRUE;
206                 }
207                 if( lv instanceof Comparable JavaDoc && rv instanceof Comparable JavaDoc ) {
208                     return compare((Comparable JavaDoc)lv, (Comparable JavaDoc)rv);
209                 }
210                 return Boolean.FALSE;
211             }
212
213             protected boolean asBoolean(int answer) {
214                 return answer == 0;
215             }
216
217             public String JavaDoc getExpressionSymbol() {
218                 return "=";
219             }
220         };
221     }
222
223     public static BooleanExpression createGreaterThan(final Expression left, final Expression right) {
224         checkLessThanOperand(left);
225         checkLessThanOperand(right);
226         return new ComparisonExpression(left, right) {
227             protected boolean asBoolean(int answer) {
228                 return answer > 0;
229             }
230
231             public String JavaDoc getExpressionSymbol() {
232                 return ">";
233             }
234         };
235     }
236
237     public static BooleanExpression createGreaterThanEqual(final Expression left, final Expression right) {
238         checkLessThanOperand(left);
239         checkLessThanOperand(right);
240         return new ComparisonExpression(left, right) {
241             protected boolean asBoolean(int answer) {
242                 return answer >= 0;
243             }
244
245             public String JavaDoc getExpressionSymbol() {
246                 return ">=";
247             }
248         };
249     }
250
251     public static BooleanExpression createLessThan(final Expression left, final Expression right) {
252         checkLessThanOperand(left);
253         checkLessThanOperand(right);
254         return new ComparisonExpression(left, right) {
255
256             protected boolean asBoolean(int answer) {
257                 return answer < 0;
258             }
259
260             public String JavaDoc getExpressionSymbol() {
261                 return "<";
262             }
263
264         };
265     }
266
267     public static BooleanExpression createLessThanEqual(final Expression left, final Expression right) {
268         checkLessThanOperand(left);
269         checkLessThanOperand(right);
270         return new ComparisonExpression(left, right) {
271
272             protected boolean asBoolean(int answer) {
273                 return answer <= 0;
274             }
275
276             public String JavaDoc getExpressionSymbol() {
277                 return "<=";
278             }
279         };
280     }
281
282     /**
283      * Only Numeric expressions can be used in >, >=, < or <= expressions.s
284      *
285      * @param expr
286      */

287     public static void checkLessThanOperand(Expression expr ) {
288         if( expr instanceof ConstantExpression ) {
289             Object JavaDoc value = ((ConstantExpression)expr).getValue();
290             if( value instanceof Number JavaDoc )
291                 return;
292             
293             // Else it's boolean or a String..
294
throw new RuntimeException JavaDoc("Value '"+expr+"' cannot be compared.");
295         }
296         if( expr instanceof BooleanExpression ) {
297             throw new RuntimeException JavaDoc("Value '"+expr+"' cannot be compared.");
298         }
299     }
300
301     /**
302      * Validates that the expression can be used in == or <> expression.
303      * Cannot not be NULL TRUE or FALSE litterals.
304      *
305      * @param expr
306      */

307     public static void checkEqualOperand(Expression expr ) {
308         if( expr instanceof ConstantExpression ) {
309             Object JavaDoc value = ((ConstantExpression)expr).getValue();
310             if( value == null )
311                 throw new RuntimeException JavaDoc("'"+expr+"' cannot be compared.");
312         }
313     }
314
315     /**
316      *
317      * @param left
318      * @param right
319      */

320     private static void checkEqualOperandCompatability(Expression left, Expression right) {
321         if( left instanceof ConstantExpression && right instanceof ConstantExpression ) {
322             if( left instanceof BooleanExpression && !(right instanceof BooleanExpression) )
323                 throw new RuntimeException JavaDoc("'"+left+"' cannot be compared with '"+right+"'");
324         }
325     }
326
327     
328     
329     /**
330      * @param left
331      * @param right
332      */

333     public ComparisonExpression(Expression left, Expression right) {
334         super(left, right);
335     }
336
337     public Object JavaDoc evaluate(MessageEvaluationContext message) throws JMSException JavaDoc {
338         Comparable JavaDoc lv = (Comparable JavaDoc) left.evaluate(message);
339         if (lv == null) {
340             return null;
341         }
342         Comparable JavaDoc rv = (Comparable JavaDoc) right.evaluate(message);
343         if (rv == null) {
344             return null;
345         }
346         return compare(lv, rv);
347     }
348
349     protected Boolean JavaDoc compare(Comparable JavaDoc lv, Comparable JavaDoc rv) {
350         Class JavaDoc lc = lv.getClass();
351         Class JavaDoc rc = rv.getClass();
352         // If the the objects are not of the same type,
353
// try to convert up to allow the comparison.
354
if (lc != rc) {
355             if (lc == Byte JavaDoc.class) {
356                 if (rc == Short JavaDoc.class) {
357                     lv = new Short JavaDoc(((Number JavaDoc) lv).shortValue());
358                 }
359                 else if (rc == Integer JavaDoc.class) {
360                     lv = new Integer JavaDoc(((Number JavaDoc) lv).intValue());
361                 }
362                 else if (rc == Long JavaDoc.class) {
363                     lv = new Long JavaDoc(((Number JavaDoc) lv).longValue());
364                 }
365                 else if (rc == Float JavaDoc.class) {
366                     lv = new Float JavaDoc(((Number JavaDoc) lv).floatValue());
367                 }
368                 else if (rc == Double JavaDoc.class) {
369                     lv = new Double JavaDoc(((Number JavaDoc) lv).doubleValue());
370                 }
371                 else {
372                     return Boolean.FALSE;
373                 }
374              } else if (lc == Short JavaDoc.class) {
375                 if (rc == Integer JavaDoc.class) {
376                     lv = new Integer JavaDoc(((Number JavaDoc) lv).intValue());
377                 }
378                 else if (rc == Long JavaDoc.class) {
379                     lv = new Long JavaDoc(((Number JavaDoc) lv).longValue());
380                 }
381                 else if (rc == Float JavaDoc.class) {
382                     lv = new Float JavaDoc(((Number JavaDoc) lv).floatValue());
383                 }
384                 else if (rc == Double JavaDoc.class) {
385                     lv = new Double JavaDoc(((Number JavaDoc) lv).doubleValue());
386                 }
387                 else {
388                     return Boolean.FALSE;
389                 }
390             } else if (lc == Integer JavaDoc.class) {
391                 if (rc == Long JavaDoc.class) {
392                     lv = new Long JavaDoc(((Number JavaDoc) lv).longValue());
393                 }
394                 else if (rc == Float JavaDoc.class) {
395                     lv = new Float JavaDoc(((Number JavaDoc) lv).floatValue());
396                 }
397                 else if (rc == Double JavaDoc.class) {
398                     lv = new Double JavaDoc(((Number JavaDoc) lv).doubleValue());
399                 }
400                 else {
401                     return Boolean.FALSE;
402                 }
403             }
404             else if (lc == Long JavaDoc.class) {
405                 if (rc == Integer JavaDoc.class) {
406                     rv = new Long JavaDoc(((Number JavaDoc) rv).longValue());
407                 }
408                 else if (rc == Float JavaDoc.class) {
409                     lv = new Float JavaDoc(((Number JavaDoc) lv).floatValue());
410                 }
411                 else if (rc == Double JavaDoc.class) {
412                     lv = new Double JavaDoc(((Number JavaDoc) lv).doubleValue());
413                 }
414                 else {
415                     return Boolean.FALSE;
416                 }
417             }
418             else if (lc == Float JavaDoc.class) {
419                 if (rc == Integer JavaDoc.class) {
420                     rv = new Float JavaDoc(((Number JavaDoc) rv).floatValue());
421                 }
422                 else if (rc == Long JavaDoc.class) {
423                     rv = new Float JavaDoc(((Number JavaDoc) rv).floatValue());
424                 }
425                 else if (rc == Double JavaDoc.class) {
426                     lv = new Double JavaDoc(((Number JavaDoc) lv).doubleValue());
427                 }
428                 else {
429                     return Boolean.FALSE;
430                 }
431             }
432             else if (lc == Double JavaDoc.class) {
433                 if (rc == Integer JavaDoc.class) {
434                     rv = new Double JavaDoc(((Number JavaDoc) rv).doubleValue());
435                 }
436                 else if (rc == Long JavaDoc.class) {
437                     rv = new Double JavaDoc(((Number JavaDoc) rv).doubleValue());
438                 }
439                 else if (rc == Float JavaDoc.class) {
440                     rv = new Float JavaDoc(((Number JavaDoc) rv).doubleValue());
441                 }
442                 else {
443                     return Boolean.FALSE;
444                 }
445             }
446             else
447                 return Boolean.FALSE;
448         }
449         return asBoolean(lv.compareTo(rv)) ? Boolean.TRUE : Boolean.FALSE;
450     }
451
452     protected abstract boolean asBoolean(int answer);
453     
454     public boolean matches(MessageEvaluationContext message) throws JMSException JavaDoc {
455         Object JavaDoc object = evaluate(message);
456         return object!=null && object==Boolean.TRUE;
457     }
458
459 }
460
Popular Tags