KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cayenne > exp > ExpressionFactory


1 /*****************************************************************
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with 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,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  ****************************************************************/

19
20 package org.apache.cayenne.exp;
21
22 import java.util.ArrayList JavaDoc;
23 import java.util.Collection JavaDoc;
24 import java.util.Iterator JavaDoc;
25 import java.util.List JavaDoc;
26 import java.util.Map JavaDoc;
27
28 import org.apache.cayenne.exp.parser.ASTAdd;
29 import org.apache.cayenne.exp.parser.ASTAnd;
30 import org.apache.cayenne.exp.parser.ASTBetween;
31 import org.apache.cayenne.exp.parser.ASTDbPath;
32 import org.apache.cayenne.exp.parser.ASTDivide;
33 import org.apache.cayenne.exp.parser.ASTEqual;
34 import org.apache.cayenne.exp.parser.ASTFalse;
35 import org.apache.cayenne.exp.parser.ASTGreater;
36 import org.apache.cayenne.exp.parser.ASTGreaterOrEqual;
37 import org.apache.cayenne.exp.parser.ASTIn;
38 import org.apache.cayenne.exp.parser.ASTLess;
39 import org.apache.cayenne.exp.parser.ASTLessOrEqual;
40 import org.apache.cayenne.exp.parser.ASTLike;
41 import org.apache.cayenne.exp.parser.ASTLikeIgnoreCase;
42 import org.apache.cayenne.exp.parser.ASTList;
43 import org.apache.cayenne.exp.parser.ASTMultiply;
44 import org.apache.cayenne.exp.parser.ASTNegate;
45 import org.apache.cayenne.exp.parser.ASTNot;
46 import org.apache.cayenne.exp.parser.ASTNotBetween;
47 import org.apache.cayenne.exp.parser.ASTNotEqual;
48 import org.apache.cayenne.exp.parser.ASTNotIn;
49 import org.apache.cayenne.exp.parser.ASTNotLike;
50 import org.apache.cayenne.exp.parser.ASTNotLikeIgnoreCase;
51 import org.apache.cayenne.exp.parser.ASTObjPath;
52 import org.apache.cayenne.exp.parser.ASTOr;
53 import org.apache.cayenne.exp.parser.ASTSubtract;
54 import org.apache.cayenne.exp.parser.ASTTrue;
55 import org.apache.cayenne.exp.parser.SimpleNode;
56
57 /**
58  * Helper class to build expressions. Alternatively expressions can be built using
59  * {@link org.apache.cayenne.exp.Expression#fromString(String)} method.
60  *
61  * @author Andrus Adamchik
62  */

63 public class ExpressionFactory {
64
65     private static Class JavaDoc[] typeLookup;
66
67     static {
68         // make sure all types are small integers, then we can use
69
// them as indexes in lookup array
70
int[] allTypes = new int[] {
71                 Expression.AND, Expression.OR, Expression.NOT, Expression.EQUAL_TO,
72                 Expression.NOT_EQUAL_TO, Expression.LESS_THAN, Expression.GREATER_THAN,
73                 Expression.LESS_THAN_EQUAL_TO, Expression.GREATER_THAN_EQUAL_TO,
74                 Expression.BETWEEN, Expression.IN, Expression.LIKE,
75                 Expression.LIKE_IGNORE_CASE, Expression.ADD, Expression.SUBTRACT,
76                 Expression.MULTIPLY, Expression.DIVIDE, Expression.NEGATIVE,
77                 Expression.OBJ_PATH, Expression.DB_PATH, Expression.LIST,
78                 Expression.NOT_BETWEEN, Expression.NOT_IN, Expression.NOT_LIKE,
79                 Expression.NOT_LIKE_IGNORE_CASE, Expression.TRUE, Expression.FALSE
80         };
81
82         int max = 0;
83         int min = 0;
84         int allLen = allTypes.length;
85         for (int i = 0; i < allLen; i++) {
86             if (allTypes[i] > max)
87                 max = allTypes[i];
88             else if (allTypes[i] < min)
89                 min = allTypes[i];
90         }
91
92         // sanity check....
93
if (max > 500)
94             throw new RuntimeException JavaDoc("Types values are too big: " + max);
95         if (min < 0)
96             throw new RuntimeException JavaDoc("Types values are too small: " + min);
97
98         // now we know that if types are used as indexes,
99
// they will fit in array "max + 1" long (though gaps are possible)
100

101         typeLookup = new Class JavaDoc[max + 1];
102
103         typeLookup[Expression.AND] = ASTAnd.class;
104         typeLookup[Expression.OR] = ASTOr.class;
105         typeLookup[Expression.BETWEEN] = ASTBetween.class;
106         typeLookup[Expression.NOT_BETWEEN] = ASTNotBetween.class;
107
108         // binary types
109
typeLookup[Expression.EQUAL_TO] = ASTEqual.class;
110         typeLookup[Expression.NOT_EQUAL_TO] = ASTNotEqual.class;
111         typeLookup[Expression.LESS_THAN] = ASTLess.class;
112         typeLookup[Expression.GREATER_THAN] = ASTGreater.class;
113         typeLookup[Expression.LESS_THAN_EQUAL_TO] = ASTLessOrEqual.class;
114         typeLookup[Expression.GREATER_THAN_EQUAL_TO] = ASTGreaterOrEqual.class;
115         typeLookup[Expression.IN] = ASTIn.class;
116         typeLookup[Expression.NOT_IN] = ASTNotIn.class;
117         typeLookup[Expression.LIKE] = ASTLike.class;
118         typeLookup[Expression.LIKE_IGNORE_CASE] = ASTLikeIgnoreCase.class;
119         typeLookup[Expression.NOT_LIKE] = ASTNotLike.class;
120         typeLookup[Expression.NOT_LIKE_IGNORE_CASE] = ASTNotLikeIgnoreCase.class;
121         typeLookup[Expression.ADD] = ASTAdd.class;
122         typeLookup[Expression.SUBTRACT] = ASTSubtract.class;
123         typeLookup[Expression.MULTIPLY] = ASTMultiply.class;
124         typeLookup[Expression.DIVIDE] = ASTDivide.class;
125
126         typeLookup[Expression.NOT] = ASTNot.class;
127         typeLookup[Expression.NEGATIVE] = ASTNegate.class;
128         typeLookup[Expression.OBJ_PATH] = ASTObjPath.class;
129         typeLookup[Expression.DB_PATH] = ASTDbPath.class;
130         typeLookup[Expression.LIST] = ASTList.class;
131         
132         typeLookup[Expression.TRUE] = ASTTrue.class;
133         typeLookup[Expression.FALSE] = ASTFalse.class;
134     }
135
136     /**
137      * Creates a new expression for the type requested. If type is unknown,
138      * ExpressionException is thrown.
139      */

140     public static Expression expressionOfType(int type) {
141         if (type < 0 || type >= typeLookup.length) {
142             throw new ExpressionException("Bad expression type: " + type);
143         }
144
145         if (typeLookup[type] == null) {
146             throw new ExpressionException("Bad expression type: " + type);
147         }
148
149         // expected this
150
if (SimpleNode.class.isAssignableFrom(typeLookup[type])) {
151             try {
152                 return (Expression) typeLookup[type].newInstance();
153             }
154             catch (Exception JavaDoc ex) {
155                 throw new ExpressionException("Error creating expression", ex);
156             }
157         }
158
159         throw new ExpressionException("Bad expression type: " + type);
160     }
161
162     /**
163      * Applies a few default rules for adding operands to expressions. In particular wraps
164      * all lists into LIST expressions. Applied only in path expressions.
165      */

166     protected static Object JavaDoc wrapPathOperand(Object JavaDoc op) {
167         if (op instanceof Collection JavaDoc) {
168             return new ASTList((Collection JavaDoc) op);
169         }
170         else if (op instanceof Object JavaDoc[]) {
171             return new ASTList((Object JavaDoc[]) op);
172         }
173         else {
174             return op;
175         }
176     }
177
178     /**
179      * Creates an expression that matches any of the key-values pairs in <code>map</code>.
180      * <p>
181      * For each pair <code>pairType</code> operator is used to build a binary
182      * expression. Key is considered to be a DB_PATH expression. Therefore all keys must
183      * be java.lang.String objects, or ClassCastException is thrown. OR is used to join
184      * pair binary expressions.
185      */

186     public static Expression matchAnyDbExp(Map JavaDoc map, int pairType) {
187         List JavaDoc pairs = new ArrayList JavaDoc();
188
189         Iterator JavaDoc it = map.entrySet().iterator();
190         while (it.hasNext()) {
191             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
192             Expression exp = expressionOfType(pairType);
193             exp.setOperand(0, new ASTDbPath(entry.getKey()));
194             exp.setOperand(1, wrapPathOperand(entry.getValue()));
195             pairs.add(exp);
196         }
197
198         return joinExp(Expression.OR, pairs);
199     }
200
201     /**
202      * Creates an expression that matches all key-values pairs in <code>map</code>.
203      * <p>
204      * For each pair <code>pairType</code> operator is used to build a binary
205      * expression. Key is considered to be a DB_PATH expression. Therefore all keys must
206      * be java.lang.String objects, or ClassCastException is thrown. AND is used to join
207      * pair binary expressions.
208      */

209     public static Expression matchAllDbExp(Map JavaDoc map, int pairType) {
210         List JavaDoc pairs = new ArrayList JavaDoc();
211
212         Iterator JavaDoc it = map.entrySet().iterator();
213         while (it.hasNext()) {
214             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
215
216             Expression exp = expressionOfType(pairType);
217             exp.setOperand(0, new ASTDbPath(entry.getKey()));
218             exp.setOperand(1, wrapPathOperand(entry.getValue()));
219             pairs.add(exp);
220         }
221
222         return joinExp(Expression.AND, pairs);
223     }
224
225     /**
226      * Creates an expression that matches any of the key-values pairs in the
227      * <code>map</code>.
228      * <p>
229      * For each pair <code>pairType</code> operator is used to build a binary
230      * expression. Key is considered to be a OBJ_PATH expression. Therefore all keys must
231      * be java.lang.String objects, or ClassCastException is thrown. OR is used to join
232      * pair binary expressions.
233      */

234     public static Expression matchAnyExp(Map JavaDoc map, int pairType) {
235         List JavaDoc pairs = new ArrayList JavaDoc();
236
237         Iterator JavaDoc it = map.entrySet().iterator();
238         while (it.hasNext()) {
239             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
240
241             Expression exp = expressionOfType(pairType);
242             exp.setOperand(0, new ASTObjPath(entry.getKey()));
243             exp.setOperand(1, wrapPathOperand(entry.getValue()));
244             pairs.add(exp);
245         }
246
247         return joinExp(Expression.OR, pairs);
248     }
249
250     /**
251      * Creates an expression that matches all key-values pairs in <code>map</code>.
252      * <p>
253      * For each pair <code>pairType</code> operator is used to build a binary
254      * expression. Key is considered to be a OBJ_PATH expression. Therefore all keys must
255      * be java.lang.String objects, or ClassCastException is thrown. AND is used to join
256      * pair binary expressions.
257      */

258     public static Expression matchAllExp(Map JavaDoc map, int pairType) {
259         List JavaDoc pairs = new ArrayList JavaDoc();
260
261         Iterator JavaDoc it = map.entrySet().iterator();
262         while (it.hasNext()) {
263             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
264
265             Expression exp = expressionOfType(pairType);
266             exp.setOperand(0, new ASTObjPath(entry.getKey()));
267             exp.setOperand(1, wrapPathOperand(entry.getValue()));
268             pairs.add(exp);
269         }
270
271         return joinExp(Expression.AND, pairs);
272     }
273
274     /**
275      * A convenience method to create an DB_PATH "equal to" expression.
276      */

277     public static Expression matchDbExp(String JavaDoc pathSpec, Object JavaDoc value) {
278         return new ASTEqual(new ASTDbPath(pathSpec), value);
279     }
280
281     /**
282      * A convenience method to create an DB_PATH "not equal to" expression.
283      */

284     public static Expression noMatchDbExp(String JavaDoc pathSpec, Object JavaDoc value) {
285         return new ASTNotEqual(new ASTDbPath(pathSpec), value);
286     }
287
288     /**
289      * A convenience method to create an OBJ_PATH "equal to" expression.
290      */

291     public static Expression matchExp(String JavaDoc pathSpec, Object JavaDoc value) {
292         return new ASTEqual(new ASTObjPath(pathSpec), value);
293     }
294
295     /**
296      * A convenience method to create an OBJ_PATH "not equal to" expression.
297      */

298     public static Expression noMatchExp(String JavaDoc pathSpec, Object JavaDoc value) {
299         return new ASTNotEqual(new ASTObjPath(pathSpec), value);
300     }
301
302     /**
303      * A convenience method to create an OBJ_PATH "less than" expression.
304      */

305     public static Expression lessExp(String JavaDoc pathSpec, Object JavaDoc value) {
306         return new ASTLess(new ASTObjPath(pathSpec), value);
307     }
308     
309     /**
310      * A convenience method to create an DB_PATH "less than" expression.
311      *
312      * @since 3.0
313      */

314     public static Expression lessDbExp(String JavaDoc pathSpec, Object JavaDoc value) {
315         return new ASTLess(new ASTDbPath(pathSpec), value);
316     }
317
318     /**
319      * A convenience method to create an OBJ_PATH "less than or equal to" expression.
320      */

321     public static Expression lessOrEqualExp(String JavaDoc pathSpec, Object JavaDoc value) {
322         return new ASTLessOrEqual(new ASTObjPath(pathSpec), value);
323     }
324     
325     /**
326      * A convenience method to create an DB_PATH "less than or equal to" expression.
327      *
328      * @since 3.0
329      */

330     public static Expression lessOrEqualDbExp(String JavaDoc pathSpec, Object JavaDoc value) {
331         return new ASTLessOrEqual(new ASTDbPath(pathSpec), value);
332     }
333
334     /**
335      * A convenience method to create an OBJ_PATH "greater than" expression.
336      */

337     public static Expression greaterExp(String JavaDoc pathSpec, Object JavaDoc value) {
338         return new ASTGreater(new ASTObjPath(pathSpec), value);
339     }
340     
341     /**
342      * A convenience method to create an DB_PATH "greater than" expression.
343      *
344      * @since 3.0
345      */

346     public static Expression greaterDbExp(String JavaDoc pathSpec, Object JavaDoc value) {
347         return new ASTGreater(new ASTDbPath(pathSpec), value);
348     }
349
350     /**
351      * A convenience method to create an OBJ_PATH "greater than or equal to" expression.
352      */

353     public static Expression greaterOrEqualExp(String JavaDoc pathSpec, Object JavaDoc value) {
354         return new ASTGreaterOrEqual(new ASTObjPath(pathSpec), value);
355     }
356     
357     /**
358      * A convenience method to create an DB_PATH "greater than or equal to" expression.
359      *
360      * @since 3.0
361      */

362     public static Expression greaterOrEqualDbExp(String JavaDoc pathSpec, Object JavaDoc value) {
363         return new ASTGreaterOrEqual(new ASTDbPath(pathSpec), value);
364     }
365
366     /**
367      * A convenience shortcut for building IN expression. Return ASTFalse for empty
368      * collection.
369      */

370     public static Expression inExp(String JavaDoc pathSpec, Object JavaDoc[] values) {
371         if (values.length == 0) {
372             return new ASTFalse();
373         }
374         return new ASTIn(new ASTObjPath(pathSpec), new ASTList(values));
375     }
376
377     /**
378      * A convenience shortcut for building IN DB expression. Return ASTFalse for empty
379      * collection.
380      */

381     public static Expression inDbExp(String JavaDoc pathSpec, Object JavaDoc[] values) {
382         if (values.length == 0) {
383             return new ASTFalse();
384         }
385         return new ASTIn(new ASTDbPath(pathSpec), new ASTList(values));
386     }
387
388     /**
389      * A convenience shortcut for building IN expression. Return ASTFalse for empty
390      * collection.
391      */

392     public static Expression inExp(String JavaDoc pathSpec, Collection JavaDoc values) {
393         if (values.isEmpty()) {
394             return new ASTFalse();
395         }
396         return new ASTIn(new ASTObjPath(pathSpec), new ASTList(values));
397     }
398
399     /**
400      * A convenience shortcut for building IN DB expression. Return ASTFalse for empty
401      * collection.
402      */

403     public static Expression inDbExp(String JavaDoc pathSpec, Collection JavaDoc values) {
404         if (values.isEmpty()) {
405             return new ASTFalse();
406         }
407         return new ASTIn(new ASTDbPath(pathSpec), new ASTList(values));
408     }
409
410     /**
411      * A convenience shortcut for building NOT_IN expression. Return ASTTrue for empty
412      * collection.
413      */

414     public static Expression notInExp(String JavaDoc pathSpec, Collection JavaDoc values) {
415         if (values.isEmpty()) {
416             return new ASTTrue();
417         }
418         return new ASTNotIn(new ASTObjPath(pathSpec), new ASTList(values));
419     }
420     
421     /**
422      * A convenience shortcut for building NOT_IN expression. Return ASTTrue for empty
423      * collection.
424      *
425      * @since 3.0
426      */

427     public static Expression notInDbExp(String JavaDoc pathSpec, Collection JavaDoc values) {
428         if (values.isEmpty()) {
429             return new ASTTrue();
430         }
431         return new ASTNotIn(new ASTDbPath(pathSpec), new ASTList(values));
432     }
433
434
435     /**
436      * A convenience shortcut for building NOT_IN expression. Return ASTTrue for empty
437      * collection.
438      *
439      * @since 1.0.6
440      */

441     public static Expression notInExp(String JavaDoc pathSpec, Object JavaDoc[] values) {
442         if (values.length == 0) {
443             return new ASTTrue();
444         }
445         return new ASTNotIn(new ASTObjPath(pathSpec), new ASTList(values));
446     }
447     
448     /**
449      * A convenience shortcut for building NOT_IN expression. Return ASTTrue for empty
450      * collection.
451      *
452      * @since 3.0
453      */

454     public static Expression notInDbExp(String JavaDoc pathSpec, Object JavaDoc[] values) {
455         if (values.length == 0) {
456             return new ASTTrue();
457         }
458         return new ASTNotIn(new ASTDbPath(pathSpec), new ASTList(values));
459     }
460
461     /**
462      * A convenience shortcut for building BETWEEN expressions.
463      */

464     public static Expression betweenExp(String JavaDoc pathSpec, Object JavaDoc value1, Object JavaDoc value2) {
465         return new ASTBetween(new ASTObjPath(pathSpec), value1, value2);
466     }
467     
468     /**
469      * A convenience shortcut for building BETWEEN expressions.
470      *
471      * @since 3.0
472      */

473     public static Expression betweenDbExp(String JavaDoc pathSpec, Object JavaDoc value1, Object JavaDoc value2) {
474         return new ASTBetween(new ASTDbPath(pathSpec), value1, value2);
475     }
476
477     /**
478      * A convenience shortcut for building NOT_BETWEEN expressions.
479      */

480     public static Expression notBetweenExp(String JavaDoc pathSpec, Object JavaDoc value1, Object JavaDoc value2) {
481         return new ASTNotBetween(new ASTObjPath(pathSpec), value1, value2);
482     }
483     
484     /**
485      * A convenience shortcut for building NOT_BETWEEN expressions.
486      *
487      * @since 3.0
488      */

489     public static Expression notBetweenDbExp(String JavaDoc pathSpec, Object JavaDoc value1, Object JavaDoc value2) {
490         return new ASTNotBetween(new ASTDbPath(pathSpec), value1, value2);
491     }
492
493     /**
494      * A convenience shortcut for building LIKE expression.
495      */

496     public static Expression likeExp(String JavaDoc pathSpec, Object JavaDoc value) {
497         return new ASTLike(new ASTObjPath(pathSpec), value);
498     }
499     
500     /**
501      * A convenience shortcut for building LIKE DB_PATH expression.
502      *
503      * @since 3.0
504      */

505     public static Expression likeDbExp(String JavaDoc pathSpec, Object JavaDoc value) {
506         return new ASTLike(new ASTDbPath(pathSpec), value);
507     }
508
509     /**
510      * A convenience shortcut for building NOT_LIKE expression.
511      */

512     public static Expression notLikeExp(String JavaDoc pathSpec, Object JavaDoc value) {
513         return new ASTNotLike(new ASTObjPath(pathSpec), value);
514     }
515     
516     /**
517      * A convenience shortcut for building NOT_LIKE expression.
518      *
519      * @since 3.0
520      */

521     public static Expression notLikeDbExp(String JavaDoc pathSpec, Object JavaDoc value) {
522         return new ASTNotLike(new ASTDbPath(pathSpec), value);
523     }
524
525     /**
526      * A convenience shortcut for building LIKE_IGNORE_CASE expression.
527      */

528     public static Expression likeIgnoreCaseExp(String JavaDoc pathSpec, Object JavaDoc value) {
529         return new ASTLikeIgnoreCase(new ASTObjPath(pathSpec), value);
530     }
531     
532     /**
533      * A convenience shortcut for building LIKE_IGNORE_CASE expression.
534      *
535      * @since 3.0
536      */

537     public static Expression likeIgnoreCaseDbExp(String JavaDoc pathSpec, Object JavaDoc value) {
538         return new ASTLikeIgnoreCase(new ASTDbPath(pathSpec), value);
539     }
540
541     /**
542      * A convenience shortcut for building NOT_LIKE_IGNORE_CASE expression.
543      */

544     public static Expression notLikeIgnoreCaseExp(String JavaDoc pathSpec, Object JavaDoc value) {
545         return new ASTNotLikeIgnoreCase(new ASTObjPath(pathSpec), value);
546     }
547     
548     /**
549      * A convenience shortcut for building NOT_LIKE_IGNORE_CASE expression.
550      *
551      * @since 3.0
552      */

553     public static Expression notLikeIgnoreCaseDbExp(String JavaDoc pathSpec, Object JavaDoc value) {
554         return new ASTNotLikeIgnoreCase(new ASTDbPath(pathSpec), value);
555     }
556
557     /**
558      * A convenience shortcut for boolean true expression.
559      *
560      * @since 3.0
561      */

562     public static Expression expTrue() {
563         return new ASTTrue();
564     }
565
566     /**
567      * A convenience shortcut for boolean false expression.
568      *
569      * @since 3.0
570      */

571     public static Expression expFalse() {
572         return new ASTFalse();
573     }
574
575     /**
576      * Joins all <code>expressions</code> in a single expression. <code>type</code> is
577      * used as an expression type for expressions joining each one of the items on the
578      * list. <code>type</code> must be binary expression type.
579      * <p>
580      * For example, if type is Expression.AND, resulting expression would match all
581      * expressions in the list. If type is Expression.OR, resulting expression would match
582      * any of the expressions.
583      * </p>
584      */

585     public static Expression joinExp(int type, List JavaDoc expressions) {
586         int len = expressions.size();
587         if (len == 0)
588             return null;
589
590         Expression currentExp = (Expression) expressions.get(0);
591         if (len == 1) {
592             return currentExp;
593         }
594
595         Expression exp = expressionOfType(type);
596         for (int i = 0; i < len; i++) {
597             exp.setOperand(i, expressions.get(i));
598         }
599         return exp;
600     }
601 }
602
Popular Tags