KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > mckoi > database > Operator


1 /**
2  * com.mckoi.database.Operator 11 Jul 2000
3  *
4  * Mckoi SQL Database ( http://www.mckoi.com/database )
5  * Copyright (C) 2000, 2001, 2002 Diehl and Associates, Inc.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * Version 2 as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License Version 2 for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * Version 2 along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  *
20  * Change Log:
21  *
22  *
23  */

24
25 package com.mckoi.database;
26
27 import java.util.HashMap JavaDoc;
28 import java.util.ArrayList JavaDoc;
29
30 /**
31  * An operator for an expression.
32  *
33  * @author Tobias Downer
34  */

35
36 public abstract class Operator implements java.io.Serializable JavaDoc {
37
38   static final long serialVersionUID = 516615288995154064L;
39
40   // ---------- Statics ----------
41

42   /**
43    * The ANY and ALL enumerator.
44    */

45   public static final int NONE = 0, ANY = 1, ALL = 2;
46
47   // ---------- Member ----------
48

49   /**
50    * A string that represents this operator.
51    */

52   private String JavaDoc op;
53
54   /**
55    * If this is a set operator such as ANY or ALL then this is set with the
56    * flag type.
57    */

58   private int set_type;
59
60   /**
61    * The precedence of this operator.
62    */

63   private int precedence;
64
65   /**
66    * Constructs the Operator.
67    */

68   protected Operator(String JavaDoc op) {
69     this(op, 0, NONE);
70   }
71
72   protected Operator(String JavaDoc op, int precedence) {
73     this(op, precedence, NONE);
74   }
75
76   protected Operator(String JavaDoc op, int precedence, int set_type) {
77     if (set_type != NONE && set_type != ANY && set_type != ALL) {
78       throw new Error JavaDoc("Invalid set_type.");
79     }
80     this.op = op;
81     this.precedence = precedence;
82     this.set_type = set_type;
83   }
84
85
86   /**
87    * Returns true if this operator is equal to the operator string.
88    */

89   public boolean is(String JavaDoc given_op) {
90     return given_op.equals(op);
91   }
92
93   public abstract TObject eval(TObject ob1, TObject ob2,
94                                GroupResolver group, VariableResolver resolver,
95                                QueryContext context);
96
97   public int precedence() {
98     return precedence;
99   }
100
101   public boolean isCondition() {
102     return (equals(eq_op) ||
103             equals(neq_op) ||
104             equals(g_op) ||
105             equals(l_op) ||
106             equals(geq_op) ||
107             equals(leq_op) ||
108             equals(is_op) ||
109             equals(isn_op));
110   }
111
112   public boolean isMathematical() {
113     return (equals(add_op) ||
114             equals(sub_op) ||
115             equals(mul_op) ||
116             equals(div_op) ||
117             equals(concat_op));
118   }
119
120   public boolean isPattern() {
121     return (equals(like_op) ||
122             equals(nlike_op) ||
123             equals(regex_op));
124   }
125
126
127   public boolean isLogical() {
128     return (equals(and_op) ||
129             equals(or_op));
130   }
131
132   public boolean isNot() {
133     return equals(not_op);
134   }
135
136   public boolean isSubQuery() {
137     return (set_type != NONE ||
138             equals(in_op) ||
139             equals(nin_op));
140   }
141
142   /**
143    * Returns an Operator that is the reverse of this Operator. This is used
144    * for reversing a conditional expression. eg. 9 > id becomes id < 9.
145    */

146   public Operator reverse() {
147     if (equals(eq_op) || equals(neq_op) || equals(is_op) || equals(isn_op)) {
148       return this;
149     }
150     else if (equals(g_op)) {
151       return l_op;
152     }
153     else if (equals(l_op)) {
154       return g_op;
155     }
156     else if (equals(geq_op)) {
157       return leq_op;
158     }
159     else if (equals(leq_op)) {
160       return geq_op;
161     }
162     throw new Error JavaDoc("Can't reverse a non conditional operator.");
163   }
164
165   /**
166    * Returns true if this operator is not inversible.
167    */

168   public boolean isNotInversible() {
169     // The REGEX op, and mathematical operators are not inversible.
170
return equals(regex_op) || isMathematical();
171   }
172
173   /**
174    * Returns the inverse operator of this operator. For example, = becomes <>,
175    * > becomes <=, AND becomes OR.
176    */

177   public Operator inverse() {
178     if (isSubQuery()) {
179       int inv_type;
180       if (isSubQueryForm(ANY)) {
181         inv_type = ALL;
182       }
183       else if (isSubQueryForm(ALL)) {
184         inv_type = ANY;
185       }
186       else {
187         throw new RuntimeException JavaDoc("Can not handle sub-query form.");
188       }
189
190       Operator inv_op = Operator.get(op).inverse();
191
192       return inv_op.getSubQueryForm(inv_type);
193     }
194     else if (equals(eq_op)) {
195       return neq_op;
196     }
197     else if (equals(neq_op)) {
198       return eq_op;
199     }
200     else if (equals(g_op)) {
201       return leq_op;
202     }
203     else if (equals(l_op)) {
204       return geq_op;
205     }
206     else if (equals(geq_op)) {
207       return l_op;
208     }
209     else if (equals(leq_op)) {
210       return g_op;
211     }
212     else if (equals(and_op)) {
213       return or_op;
214     }
215     else if (equals(or_op)) {
216       return and_op;
217     }
218     else if (equals(like_op)) {
219       return nlike_op;
220     }
221     else if (equals(nlike_op)) {
222       return like_op;
223     }
224     else if (equals(is_op)) {
225       return isn_op;
226     }
227     else if (equals(isn_op)) {
228       return is_op;
229     }
230     else {
231       throw new Error JavaDoc("Can't inverse operator '" + op + "'");
232     }
233
234   }
235
236   /**
237    * Given a parameter of either NONE, ANY, ALL or SINGLE, this returns true
238    * if this operator is of the given type.
239    */

240   public boolean isSubQueryForm(int type) {
241     return type == set_type;
242   }
243
244   /**
245    * Returns the sub query representation of this operator.
246    */

247   int getSubQueryFormRepresentation() {
248     return set_type;
249   }
250
251   /**
252    * Returns the ANY or ALL form of this operator.
253    */

254   public Operator getSubQueryForm(int type) {
255     Operator result_op = null;
256     if (type == ANY) {
257       result_op = (Operator) any_map.get(op);
258     }
259     else if (type == ALL) {
260       result_op = (Operator) all_map.get(op);
261     }
262     else if (type == NONE) {
263       result_op = get(op);
264     }
265
266     if (result_op == null) {
267       throw new Error JavaDoc("Couldn't change the form of operator '" + op + "'.");
268     }
269     return result_op;
270   }
271
272   /**
273    * Same as above only it handles the type as a string.
274    */

275   public Operator getSubQueryForm(String JavaDoc type_str) {
276     String JavaDoc s = type_str.toUpperCase();
277     if (s.equals("SINGLE") || s.equals("ANY") || s.equals("SOME")) {
278       return getSubQueryForm(ANY);
279     }
280     else if (s.equals("ALL")) {
281       return getSubQueryForm(ALL);
282     }
283     throw new Error JavaDoc("Do not understand subquery type '" + type_str + "'");
284   }
285
286   /**
287    * The type of object this Operator evaluates to.
288    */

289   public TType returnTType() {
290     if (equals(concat_op)) {
291       return TType.STRING_TYPE;
292     }
293     else if (isMathematical()) {
294       return TType.NUMERIC_TYPE;
295     }
296     else {
297       return TType.BOOLEAN_TYPE;
298     }
299   }
300
301   /**
302    * Returns the string value of this operator.
303    */

304   String JavaDoc stringRepresentation() {
305     return op;
306   }
307   
308   public String JavaDoc toString() {
309     StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
310     buf.append(op);
311     if (set_type == ANY) {
312       buf.append(" ANY");
313     }
314     else if (set_type == ALL) {
315       buf.append(" ALL");
316     }
317     return new String JavaDoc(buf);
318   }
319
320   public boolean equals(Object JavaDoc ob) {
321     if (this == ob) return true;
322     Operator oob = (Operator) ob;
323     return op.equals(oob.op) && set_type == oob.set_type;
324   }
325
326
327
328   /**
329    * Returns an Operator with the given string.
330    */

331   public static Operator get(String JavaDoc op) {
332     if (op.equals("+")) { return add_op; }
333     else if (op.equals("-")) { return sub_op; }
334     else if (op.equals("*")) { return mul_op; }
335     else if (op.equals("/")) { return div_op; }
336     else if (op.equals("||")) { return concat_op; }
337
338     else if (op.equals("=") | op.equals("==")) { return eq_op; }
339     else if (op.equals("<>") | op.equals("!=")) { return neq_op; }
340     else if (op.equals(">")) { return g_op; }
341     else if (op.equals("<")) { return l_op; }
342     else if (op.equals(">=")) { return geq_op; }
343     else if (op.equals("<=")) { return leq_op; }
344
345     else if (op.equals("(")) { return par1_op; }
346     else if (op.equals(")")) { return par2_op; }
347
348     // Operators that are words, convert to lower case...
349
op = op.toLowerCase();
350     if (op.equals("is")) { return is_op; }
351     else if (op.equals("is not")) { return isn_op; }
352     else if (op.equals("like")) { return like_op; }
353     else if (op.equals("not like")) { return nlike_op; }
354     else if (op.equals("regex")) { return regex_op; }
355
356     else if (op.equals("in")) { return in_op; }
357     else if (op.equals("not in")) { return nin_op; }
358
359     else if (op.equals("not")) { return not_op; }
360     else if (op.equals("and")) { return and_op; }
361     else if (op.equals("or")) { return or_op; }
362
363
364     throw new Error JavaDoc("Unrecognised operator type: " + op);
365   }
366
367   // ---------- Convenience methods ----------
368

369   /**
370    * Returns true if the given TObject is a boolean and is true. If the
371    * TObject is not a boolean value or is null or is false, then it returns
372    * false.
373    */

374   private static boolean isTrue(TObject bool) {
375     return (!bool.isNull() &&
376             bool.getTType() instanceof TBooleanType &&
377             bool.getObject().equals(Boolean.TRUE));
378   }
379
380
381   // ---------- The different types of operator's we can have ----------
382

383   private final static AddOperator add_op = new AddOperator();
384   private final static SubtractOperator sub_op = new SubtractOperator();
385   private final static MultiplyOperator mul_op = new MultiplyOperator();
386   private final static DivideOperator div_op = new DivideOperator();
387   private final static ConcatOperator concat_op = new ConcatOperator();
388
389   private final static EqualOperator eq_op = new EqualOperator();
390   private final static NotEqualOperator neq_op = new NotEqualOperator();
391   private final static GreaterOperator g_op = new GreaterOperator();
392   private final static LesserOperator l_op = new LesserOperator();
393   private final static GreaterEqualOperator geq_op =
394                                                    new GreaterEqualOperator();
395   private final static LesserEqualOperator leq_op = new LesserEqualOperator();
396
397   private final static IsOperator is_op = new IsOperator();
398   private final static IsNotOperator isn_op = new IsNotOperator();
399
400   private final static PatternMatchTrueOperator like_op =
401                                      new PatternMatchTrueOperator();
402   private final static PatternMatchFalseOperator nlike_op =
403                                     new PatternMatchFalseOperator();
404   private final static RegexOperator regex_op = new RegexOperator();
405
406   private final static Operator in_op;
407   private final static Operator nin_op;
408
409   private final static Operator not_op = new SimpleOperator("not", 3);
410
411   private final static AndOperator and_op = new AndOperator();
412   private final static OrOperator or_op = new OrOperator();
413
414   private final static ParenOperator par1_op = new ParenOperator("(");
415   private final static ParenOperator par2_op = new ParenOperator(")");
416
417   // Maps from operator to 'any' operator
418
private final static HashMap JavaDoc any_map = new HashMap JavaDoc();
419   // Maps from operator to 'all' operator.
420
private final static HashMap JavaDoc all_map = new HashMap JavaDoc();
421
422   static {
423     // Populate the static ANY and ALL mapping
424
any_map.put("=", new AnyOperator("="));
425     any_map.put("<>", new AnyOperator("<>"));
426     any_map.put(">", new AnyOperator(">"));
427     any_map.put(">=", new AnyOperator(">="));
428     any_map.put("<", new AnyOperator("<"));
429     any_map.put("<=", new AnyOperator("<="));
430
431     all_map.put("=", new AllOperator("="));
432     all_map.put("<>", new AllOperator("<>"));
433     all_map.put(">", new AllOperator(">"));
434     all_map.put(">=", new AllOperator(">="));
435     all_map.put("<", new AllOperator("<"));
436     all_map.put("<=", new AllOperator("<="));
437
438     // The IN and NOT IN operator are '= ANY' and '<> ALL' respectively.
439
in_op = (Operator) any_map.get("=");
440     nin_op = (Operator) all_map.get("<>");
441   }
442
443
444   static class AddOperator extends Operator {
445     static final long serialVersionUID = 6995379384325694391L;
446     public AddOperator() { super("+", 10); }
447     public TObject eval(TObject ob1, TObject ob2,
448                         GroupResolver group, VariableResolver resolver,
449                         QueryContext context) {
450       return ob1.operatorAdd(ob2);
451     }
452   };
453
454   static class SubtractOperator extends Operator {
455     static final long serialVersionUID = 3035882496296296786L;
456     public SubtractOperator() { super("-", 15); }
457     public TObject eval(TObject ob1, TObject ob2,
458                         GroupResolver group, VariableResolver resolver,
459                         QueryContext context) {
460       return ob1.operatorSubtract(ob2);
461     }
462   };
463
464   static class MultiplyOperator extends Operator {
465     static final long serialVersionUID = 8191233936463163847L;
466     public MultiplyOperator() { super("*", 20); }
467     public TObject eval(TObject ob1, TObject ob2,
468                         GroupResolver group, VariableResolver resolver,
469                         QueryContext context) {
470       return ob1.operatorMultiply(ob2);
471     }
472   };
473
474   static class DivideOperator extends Operator {
475     static final long serialVersionUID = -2695205152105036247L;
476     public DivideOperator() { super("/", 20); }
477     public TObject eval(TObject ob1, TObject ob2,
478                         GroupResolver group, VariableResolver resolver,
479                         QueryContext context) {
480       return ob1.operatorDivide(ob2);
481     }
482   };
483
484   static class ConcatOperator extends Operator {
485     public ConcatOperator() { super("||", 10); }
486     public TObject eval(TObject ob1, TObject ob2,
487                         GroupResolver group, VariableResolver resolver,
488                         QueryContext context) {
489       return ob1.operatorConcat(ob2);
490     }
491   };
492
493
494
495   static class EqualOperator extends Operator {
496     static final long serialVersionUID = -5022271093834866261L;
497     public EqualOperator() { super("=", 4); }
498     public TObject eval(TObject ob1, TObject ob2,
499                         GroupResolver group, VariableResolver resolver,
500                         QueryContext context) {
501       return ob1.operatorEquals(ob2);
502     }
503   }
504
505   static class NotEqualOperator extends Operator {
506     static final long serialVersionUID = 5868174826733282297L;
507     public NotEqualOperator() { super("<>", 4); }
508     public TObject eval(TObject ob1, TObject ob2,
509                         GroupResolver group, VariableResolver resolver,
510                         QueryContext context) {
511       return ob1.operatorNotEquals(ob2);
512     }
513   }
514
515   static class GreaterOperator extends Operator {
516     static final long serialVersionUID = -6870425685250387549L;
517     public GreaterOperator() { super(">", 4); }
518     public TObject eval(TObject ob1, TObject ob2,
519                         GroupResolver group, VariableResolver resolver,
520                         QueryContext context) {
521       return ob1.operatorGreater(ob2);
522     }
523   }
524
525   static class LesserOperator extends Operator {
526     static final long serialVersionUID = 2962736161551360032L;
527     public LesserOperator() { super("<", 4); }
528     public TObject eval(TObject ob1, TObject ob2,
529                         GroupResolver group, VariableResolver resolver,
530                         QueryContext context) {
531       return ob1.operatorLess(ob2);
532     }
533   }
534
535   static class GreaterEqualOperator extends Operator {
536     static final long serialVersionUID = 6040843932499067476L;
537     public GreaterEqualOperator() { super(">=", 4); }
538     public TObject eval(TObject ob1, TObject ob2,
539                         GroupResolver group, VariableResolver resolver,
540                         QueryContext context) {
541       return ob1.operatorGreaterEquals(ob2);
542     }
543   }
544
545   static class LesserEqualOperator extends Operator {
546     static final long serialVersionUID = 4298966494510169621L;
547     public LesserEqualOperator() { super("<=", 4); }
548     public TObject eval(TObject ob1, TObject ob2,
549                         GroupResolver group, VariableResolver resolver,
550                         QueryContext context) {
551       return ob1.operatorLessEquals(ob2);
552     }
553   }
554
555   static class IsOperator extends Operator {
556     static final long serialVersionUID = -5537856102106541908L;
557     public IsOperator() { super("is", 4); }
558     public TObject eval(TObject ob1, TObject ob2,
559                         GroupResolver group, VariableResolver resolver,
560                         QueryContext context) {
561       return ob1.operatorIs(ob2);
562     }
563   }
564
565   static class IsNotOperator extends Operator {
566     static final long serialVersionUID = 1224184162192790982L;
567     public IsNotOperator() { super("is not", 4); }
568     public TObject eval(TObject ob1, TObject ob2,
569                         GroupResolver group, VariableResolver resolver,
570                         QueryContext context) {
571       return ob1.operatorIs(ob2).operatorNot();
572     }
573   }
574
575
576
577
578   static class AnyOperator extends Operator {
579     static final long serialVersionUID = 6421321961221271735L;
580     public AnyOperator(String JavaDoc op) {
581       super(op, 8, ANY);
582     }
583     public TObject eval(TObject ob1, TObject ob2,
584                         GroupResolver group, VariableResolver resolver,
585                         QueryContext context) {
586       if (ob2.getTType() instanceof TQueryPlanType) {
587         // The sub-query plan
588
QueryPlanNode plan = (QueryPlanNode) ob2.getObject();
589         // Discover the correlated variables for this plan.
590
ArrayList JavaDoc list = plan.discoverCorrelatedVariables(1, new ArrayList JavaDoc());
591
592         if (list.size() > 0) {
593           // Set the correlated variables from the VariableResolver
594
for (int i = 0; i < list.size(); ++i) {
595             ((CorrelatedVariable) list.get(i)).setFromResolver(resolver);
596           }
597           // Clear the cache in the context
598
context.clearCache();
599         }
600
601         // Evaluate the plan,
602
Table t = plan.evaluate(context);
603
604         // The ANY operation
605
Operator rev_plain_op = getSubQueryForm(NONE).reverse();
606         if (t.columnMatchesValue(0, rev_plain_op, ob1)) {
607           return TObject.BOOLEAN_TRUE;
608         }
609         return TObject.BOOLEAN_FALSE;
610
611       }
612       else if (ob2.getTType() instanceof TArrayType) {
613         Operator plain_op = getSubQueryForm(NONE);
614         Expression[] exp_list = (Expression[]) ob2.getObject();
615         // Assume there are no matches
616
TObject ret_val = TObject.BOOLEAN_FALSE;
617         for (int i = 0; i < exp_list.length; ++i) {
618           TObject exp_item = exp_list[i].evaluate(group, resolver, context);
619           // If null value, return null if there isn't otherwise a match found.
620
if (exp_item.isNull()) {
621             ret_val = TObject.BOOLEAN_NULL;
622           }
623           // If there is a match, the ANY set test is true
624
else if (isTrue(plain_op.eval(ob1, exp_item, null, null, null))) {
625             return TObject.BOOLEAN_TRUE;
626           }
627         }
628         // No matches, so return either false or NULL. If there are no matches
629
// and no nulls, return false. If there are no matches and there are
630
// nulls present, return null.
631
return ret_val;
632       }
633       else {
634         throw new Error JavaDoc("Unknown RHS of ANY.");
635       }
636     }
637   }
638
639   static class AllOperator extends Operator {
640     static final long serialVersionUID = -4605268759294925687L;
641     public AllOperator(String JavaDoc op) {
642       super(op, 8, ALL);
643     }
644     public TObject eval(TObject ob1, TObject ob2,
645                         GroupResolver group, VariableResolver resolver,
646                         QueryContext context) {
647       if (ob2.getTType() instanceof TQueryPlanType) {
648
649         // The sub-query plan
650
QueryPlanNode plan = (QueryPlanNode) ob2.getObject();
651         // Discover the correlated variables for this plan.
652
ArrayList JavaDoc list = plan.discoverCorrelatedVariables(1, new ArrayList JavaDoc());
653
654         if (list.size() > 0) {
655           // Set the correlated variables from the VariableResolver
656
for (int i = 0; i < list.size(); ++i) {
657             ((CorrelatedVariable) list.get(i)).setFromResolver(resolver);
658           }
659           // Clear the cache in the context
660
context.clearCache();
661         }
662
663         // Evaluate the plan,
664
Table t = plan.evaluate(context);
665
666         Operator rev_plain_op = getSubQueryForm(NONE).reverse();
667         if (t.allColumnMatchesValue(0, rev_plain_op, ob1)) {
668           return TObject.BOOLEAN_TRUE;
669         }
670         return TObject.BOOLEAN_FALSE;
671
672       }
673       else if (ob2.getTType() instanceof TArrayType) {
674         Operator plain_op = getSubQueryForm(NONE);
675         Expression[] exp_list = (Expression[]) ob2.getObject();
676         // Assume true unless otherwise found to be false or NULL.
677
TObject ret_val = TObject.BOOLEAN_TRUE;
678         for (int i = 0; i < exp_list.length; ++i) {
679           TObject exp_item = exp_list[i].evaluate(group, resolver, context);
680           // If there is a null item, we return null if not otherwise found to
681
// be false.
682
if (exp_item.isNull()) {
683             ret_val = TObject.BOOLEAN_NULL;
684           }
685           // If it doesn't match return false
686
else if (!isTrue(plain_op.eval(ob1, exp_item, null, null, null))) {
687             return TObject.BOOLEAN_FALSE;
688           }
689         }
690         // Otherwise return true or null. If all match and no NULLs return
691
// true. If all match and there are NULLs then return NULL.
692
return ret_val;
693       }
694       else {
695         throw new Error JavaDoc("Unknown RHS of ALL.");
696       }
697     }
698   }
699
700   static class RegexOperator extends Operator {
701     static final long serialVersionUID = 8062751421429261272L;
702     public RegexOperator() { super("regex", 8); }
703     public TObject eval(TObject ob1, TObject ob2,
704                         GroupResolver group, VariableResolver resolver,
705                         QueryContext context) {
706       if (ob1.isNull()) {
707         return ob1;
708       }
709       if (ob2.isNull()) {
710         return ob2;
711       }
712       String JavaDoc val = ob1.castTo(TType.STRING_TYPE).toStringValue();
713       String JavaDoc pattern = ob2.castTo(TType.STRING_TYPE).toStringValue();
714       return TObject.booleanVal(PatternSearch.regexMatch(
715                                         context.getSystem(), pattern, val));
716     }
717   }
718
719   static class PatternMatchTrueOperator extends Operator {
720     static final long serialVersionUID = 3038856811053114238L;
721     public PatternMatchTrueOperator() { super("like", 8); }
722     public TObject eval(TObject ob1, TObject ob2,
723                         GroupResolver group, VariableResolver resolver,
724                         QueryContext context) {
725       if (ob1.isNull()) {
726         return ob1;
727       }
728       if (ob2.isNull()) {
729         return ob2;
730       }
731       String JavaDoc val = ob1.castTo(TType.STRING_TYPE).toStringValue();
732       String JavaDoc pattern = ob2.castTo(TType.STRING_TYPE).toStringValue();
733       
734       TObject result = TObject.booleanVal(
735                        PatternSearch.fullPatternMatch(pattern, val, '\\'));
736       return result;
737     }
738   }
739
740   static class PatternMatchFalseOperator extends Operator {
741     static final long serialVersionUID = 7271394661743778291L;
742     public PatternMatchFalseOperator() { super("not like", 8); }
743     public TObject eval(TObject ob1, TObject ob2,
744                         GroupResolver group, VariableResolver resolver,
745                         QueryContext context) {
746       if (ob1.isNull()) {
747         return ob1;
748       }
749       if (ob2.isNull()) {
750         return ob2;
751       }
752       String JavaDoc val = ob1.castTo(TType.STRING_TYPE).toStringValue();
753       String JavaDoc pattern = ob2.castTo(TType.STRING_TYPE).toStringValue();
754       return TObject.booleanVal(
755                      !PatternSearch.fullPatternMatch(pattern, val, '\\'));
756     }
757   }
758
759   // and/or have lowest precedence
760
static class AndOperator extends Operator {
761     static final long serialVersionUID = -6044610739300316190L;
762     public AndOperator() { super("and", 2); }
763     public TObject eval(TObject ob1, TObject ob2,
764                         GroupResolver group, VariableResolver resolver,
765                         QueryContext context) {
766
767       Boolean JavaDoc b1 = ob1.toBoolean();
768       Boolean JavaDoc b2 = ob2.toBoolean();
769
770       // If either ob1 or ob2 are null
771
if (b1 == null) {
772         if (b2 != null) {
773           if (b2.equals(Boolean.FALSE)) {
774             return TObject.BOOLEAN_FALSE;
775           }
776         }
777         return TObject.BOOLEAN_NULL;
778       }
779       else if (b2 == null) {
780         if (b1.equals(Boolean.FALSE)) {
781           return TObject.BOOLEAN_FALSE;
782         }
783         return TObject.BOOLEAN_NULL;
784       }
785
786       // If both true.
787
return TObject.booleanVal(b1.equals(Boolean.TRUE) &&
788                                 b2.equals(Boolean.TRUE));
789     }
790   }
791
792   static class OrOperator extends Operator {
793     static final long serialVersionUID = 6505549460035023998L;
794     public OrOperator() { super("or", 1); }
795     public TObject eval(TObject ob1, TObject ob2,
796                         GroupResolver group, VariableResolver resolver,
797                         QueryContext context) {
798
799       Boolean JavaDoc b1 = ob1.toBoolean();
800       Boolean JavaDoc b2 = ob2.toBoolean();
801
802       // If either ob1 or ob2 are null
803
if (b1 == null) {
804         if (b2 != null) {
805           if (b2.equals(Boolean.TRUE)) {
806             return TObject.BOOLEAN_TRUE;
807           }
808         }
809         return TObject.BOOLEAN_NULL;
810       }
811       else if (b2 == null) {
812         if (b1.equals(Boolean.TRUE)) {
813           return TObject.BOOLEAN_TRUE;
814         }
815         return TObject.BOOLEAN_NULL;
816       }
817
818       // If both true.
819
return TObject.booleanVal(b1.equals(Boolean.TRUE) ||
820                                 b2.equals(Boolean.TRUE));
821
822     }
823   }
824
825
826
827
828
829
830   static class ParenOperator extends Operator {
831     static final long serialVersionUID = -5720902399037456435L;
832     public ParenOperator(String JavaDoc paren) { super(paren); }
833     public TObject eval(TObject ob1, TObject ob2,
834                         GroupResolver group, VariableResolver resolver,
835                         QueryContext context) {
836       throw new Error JavaDoc("Parenthese should never be evaluated!");
837     }
838   }
839
840   static class SimpleOperator extends Operator {
841     static final long serialVersionUID = 1136249637094226133L;
842     public SimpleOperator(String JavaDoc str) { super(str); }
843     public SimpleOperator(String JavaDoc str, int prec) { super(str, prec); }
844     public TObject eval(TObject ob1, TObject ob2,
845                         GroupResolver group, VariableResolver resolver,
846                         QueryContext context) {
847       throw new Error JavaDoc("SimpleOperator should never be evaluated!");
848     }
849   }
850
851 }
852
Popular Tags