001: package org.drools.base.evaluators;
002:
003: /*
004: * Copyright 2005 JBoss Inc
005: *
006: * Licensed under the Apache License, Version 2.0 (the "License");
007: * you may not use this file except in compliance with the License.
008: * You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */
018:
019: import java.text.ParseException;
020: import java.text.SimpleDateFormat;
021: import java.util.Date;
022:
023: import org.drools.base.BaseEvaluator;
024: import org.drools.base.ValueType;
025: import org.drools.common.InternalWorkingMemory;
026: import org.drools.rule.VariableRestriction.ObjectVariableContextEntry;
027: import org.drools.rule.VariableRestriction.VariableContextEntry;
028: import org.drools.spi.Evaluator;
029: import org.drools.spi.Extractor;
030: import org.drools.spi.FieldValue;
031:
032: /**
033: * This will generate evaluators that handle dates.
034: * This will also parse strings into dates, according to
035: * DEFAULT_FORMAT_MASK, unless it is overridden by the drools.dateformat system property.
036: *
037: * When parsing dates from a string, no time is included.
038: *
039: * So you can do expressions like
040: * <code>Person(birthday <= "10-Jul-1974")</code> etc.
041: *
042: * @author Michael Neale
043: */
044: public class DateFactory implements EvaluatorFactory {
045:
046: private static final long serialVersionUID = 400L;
047: private static final String DEFAULT_FORMAT_MASK = "dd-MMM-yyyy";
048: private static final String DATE_FORMAT_MASK = getDateFormatMask();
049:
050: private static EvaluatorFactory INSTANCE = new DateFactory();
051: private static SimpleDateFormat df;
052:
053: private DateFactory() {
054: df = new SimpleDateFormat(DateFactory.DATE_FORMAT_MASK);
055: }
056:
057: public static EvaluatorFactory getInstance() {
058: if (DateFactory.INSTANCE == null) {
059: DateFactory.INSTANCE = new DateFactory();
060: }
061: return DateFactory.INSTANCE;
062: }
063:
064: public Evaluator getEvaluator(final Operator operator) {
065: if (operator == Operator.EQUAL) {
066: return DateEqualEvaluator.INSTANCE;
067: } else if (operator == Operator.NOT_EQUAL) {
068: return DateNotEqualEvaluator.INSTANCE;
069: } else if (operator == Operator.LESS) {
070: return DateLessEvaluator.INSTANCE;
071: } else if (operator == Operator.LESS_OR_EQUAL) {
072: return DateLessOrEqualEvaluator.INSTANCE;
073: } else if (operator == Operator.GREATER) {
074: return DateGreaterEvaluator.INSTANCE;
075: } else if (operator == Operator.GREATER_OR_EQUAL) {
076: return DateGreaterOrEqualEvaluator.INSTANCE;
077: } else if (operator == Operator.MEMBEROF) {
078: return DateMemberOfEvaluator.INSTANCE;
079: } else if (operator == Operator.NOTMEMBEROF) {
080: return DateNotMemberOfEvaluator.INSTANCE;
081: } else {
082: throw new RuntimeException("Operator '" + operator
083: + "' does not exist for DateEvaluator");
084: }
085: }
086:
087: static class DateEqualEvaluator extends BaseEvaluator {
088: /**
089: *
090: */
091: private static final long serialVersionUID = 400L;
092: public final static Evaluator INSTANCE = new DateEqualEvaluator();
093:
094: private DateEqualEvaluator() {
095: super (ValueType.DATE_TYPE, Operator.EQUAL);
096: }
097:
098: public boolean evaluate(InternalWorkingMemory workingMemory,
099: final Extractor extractor, final Object object1,
100: final FieldValue object2) {
101: final Date value1 = (Date) extractor.getValue(
102: workingMemory, object1);
103: final Object value2 = object2.getValue();
104: if (value1 == null) {
105: return value2 == null;
106: }
107: if (value2 == null) {
108: return false;
109: }
110: return value1.compareTo(getRightDate(value2)) == 0;
111: }
112:
113: public boolean evaluateCachedRight(
114: InternalWorkingMemory workingMemory,
115: final VariableContextEntry context, final Object left) {
116: final Date value1 = (Date) context.declaration
117: .getExtractor().getValue(workingMemory, left);
118: final Object value2 = ((ObjectVariableContextEntry) context).right;
119: if (value1 == null) {
120: return value2 == null;
121: }
122: if (value2 == null) {
123: return false;
124: }
125: return value1.compareTo(getRightDate(value2)) == 0;
126: }
127:
128: public boolean evaluateCachedLeft(
129: InternalWorkingMemory workingMemory,
130: final VariableContextEntry context, final Object right) {
131: final Date value1 = (Date) ((ObjectVariableContextEntry) context).left;
132: final Object value2 = context.extractor.getValue(
133: workingMemory, right);
134: if (value1 == null) {
135: return value2 == null;
136: }
137: if (value2 == null) {
138: return false;
139: }
140: return value1.compareTo(getRightDate(value2)) == 0;
141: }
142:
143: public boolean evaluate(InternalWorkingMemory workingMemory,
144: final Extractor extractor1, final Object object1,
145: final Extractor extractor2, final Object object2) {
146: final Date value1 = (Date) extractor1.getValue(
147: workingMemory, object1);
148: final Date value2 = (Date) extractor2.getValue(
149: workingMemory, object2);
150: if (value1 == null) {
151: return value2 == null;
152: }
153: if (value2 == null) {
154: return false;
155: }
156: return value1.compareTo(value2) == 0;
157: }
158:
159: public String toString() {
160: return "Date ==";
161: }
162:
163: }
164:
165: static class DateNotEqualEvaluator extends BaseEvaluator {
166: /**
167: *
168: */
169: private static final long serialVersionUID = 400L;
170: public final static Evaluator INSTANCE = new DateNotEqualEvaluator();
171:
172: private DateNotEqualEvaluator() {
173: super (ValueType.DATE_TYPE, Operator.NOT_EQUAL);
174: }
175:
176: public boolean evaluate(InternalWorkingMemory workingMemory,
177: final Extractor extractor, final Object object1,
178: final FieldValue object2) {
179: final Date value1 = (Date) extractor.getValue(
180: workingMemory, object1);
181: final Object value2 = object2.getValue();
182: if (value1 == null) {
183: return value2 != null;
184: }
185: if (value2 == null) {
186: return true;
187: }
188: return value1.compareTo(getRightDate(value2)) != 0;
189: }
190:
191: public boolean evaluateCachedRight(
192: InternalWorkingMemory workingMemory,
193: final VariableContextEntry context, final Object left) {
194: final Date value1 = (Date) context.declaration
195: .getExtractor().getValue(workingMemory, left);
196: final Object value2 = ((ObjectVariableContextEntry) context).right;
197: if (value1 == null) {
198: return value2 != null;
199: }
200: if (value2 == null) {
201: return true;
202: }
203: return value1.compareTo(getRightDate(value2)) != 0;
204: }
205:
206: public boolean evaluateCachedLeft(
207: InternalWorkingMemory workingMemory,
208: final VariableContextEntry context, final Object right) {
209: final Date value1 = (Date) ((ObjectVariableContextEntry) context).left;
210: final Object value2 = context.extractor.getValue(
211: workingMemory, right);
212: if (value1 == null) {
213: return value2 != null;
214: }
215: if (value2 == null) {
216: return true;
217: }
218: return value1.compareTo(getRightDate(value2)) != 0;
219: }
220:
221: public boolean evaluate(InternalWorkingMemory workingMemory,
222: final Extractor extractor1, final Object object1,
223: final Extractor extractor2, final Object object2) {
224: final Date value1 = (Date) extractor1.getValue(
225: workingMemory, object1);
226: final Date value2 = (Date) extractor2.getValue(
227: workingMemory, object2);
228: if (value1 == null) {
229: return value2 != null;
230: }
231: if (value2 == null) {
232: return true;
233: }
234: return value1.compareTo(value2) != 0;
235: }
236:
237: public String toString() {
238: return "Date !=";
239: }
240: }
241:
242: static class DateLessEvaluator extends BaseEvaluator {
243: /**
244: *
245: */
246: private static final long serialVersionUID = 400L;
247: public final static Evaluator INSTANCE = new DateLessEvaluator();
248:
249: private DateLessEvaluator() {
250: super (ValueType.DATE_TYPE, Operator.LESS);
251: }
252:
253: public boolean evaluate(InternalWorkingMemory workingMemory,
254: final Extractor extractor, final Object object1,
255: final FieldValue object2) {
256: if (extractor.isNullValue(workingMemory, object1)) {
257: return false;
258: }
259: final Date value1 = (Date) extractor.getValue(
260: workingMemory, object1);
261: final Object value2 = object2.getValue();
262: return value1.compareTo(getRightDate(value2)) < 0;
263: }
264:
265: public boolean evaluateCachedRight(
266: InternalWorkingMemory workingMemory,
267: final VariableContextEntry context, final Object left) {
268: if (context.rightNull) {
269: return false;
270: }
271: final Date value1 = (Date) context.declaration
272: .getExtractor().getValue(workingMemory, left);
273: final Object value2 = ((ObjectVariableContextEntry) context).right;
274: return getRightDate(value2).compareTo(value1) < 0;
275: }
276:
277: public boolean evaluateCachedLeft(
278: InternalWorkingMemory workingMemory,
279: final VariableContextEntry context, final Object right) {
280: if (context.extractor.isNullValue(workingMemory, right)) {
281: return false;
282: }
283: final Date value1 = (Date) ((ObjectVariableContextEntry) context).left;
284: final Object value2 = context.extractor.getValue(
285: workingMemory, right);
286: return getRightDate(value2).compareTo(value1) < 0;
287: }
288:
289: public boolean evaluate(InternalWorkingMemory workingMemory,
290: final Extractor extractor1, final Object object1,
291: final Extractor extractor2, final Object object2) {
292: if (extractor1.isNullValue(workingMemory, object1)) {
293: return false;
294: }
295: final Date value1 = (Date) extractor1.getValue(
296: workingMemory, object1);
297: final Date value2 = (Date) extractor2.getValue(
298: workingMemory, object2);
299: return value1.compareTo(value2) < 0;
300: }
301:
302: public String toString() {
303: return "Date <";
304: }
305: }
306:
307: static class DateLessOrEqualEvaluator extends BaseEvaluator {
308: /**
309: *
310: */
311: private static final long serialVersionUID = 400L;
312: public final static Evaluator INSTANCE = new DateLessOrEqualEvaluator();
313:
314: private DateLessOrEqualEvaluator() {
315: super (ValueType.DATE_TYPE, Operator.LESS_OR_EQUAL);
316: }
317:
318: public boolean evaluate(InternalWorkingMemory workingMemory,
319: final Extractor extractor, final Object object1,
320: final FieldValue object2) {
321: if (extractor.isNullValue(workingMemory, object1)) {
322: return false;
323: }
324: final Date value1 = (Date) extractor.getValue(
325: workingMemory, object1);
326: final Object value2 = object2.getValue();
327: return value1.compareTo(getRightDate(value2)) <= 0;
328: }
329:
330: public boolean evaluateCachedRight(
331: InternalWorkingMemory workingMemory,
332: final VariableContextEntry context, final Object left) {
333: if (context.rightNull) {
334: return false;
335: }
336: final Date value1 = (Date) context.declaration
337: .getExtractor().getValue(workingMemory, left);
338: final Object value2 = ((ObjectVariableContextEntry) context).right;
339: return getRightDate(value2).compareTo(value1) <= 0;
340: }
341:
342: public boolean evaluateCachedLeft(
343: InternalWorkingMemory workingMemory,
344: final VariableContextEntry context, final Object right) {
345: if (context.extractor.isNullValue(workingMemory, right)) {
346: return false;
347: }
348: final Date value1 = (Date) ((ObjectVariableContextEntry) context).left;
349: final Object value2 = context.extractor.getValue(
350: workingMemory, right);
351: return getRightDate(value2).compareTo(value1) <= 0;
352: }
353:
354: public boolean evaluate(InternalWorkingMemory workingMemory,
355: final Extractor extractor1, final Object object1,
356: final Extractor extractor2, final Object object2) {
357: if (extractor1.isNullValue(workingMemory, object1)) {
358: return false;
359: }
360: final Date value1 = (Date) extractor1.getValue(
361: workingMemory, object1);
362: final Date value2 = (Date) extractor2.getValue(
363: workingMemory, object2);
364: return value1.compareTo(value2) <= 0;
365: }
366:
367: public String toString() {
368: return "Date <=";
369: }
370: }
371:
372: static class DateGreaterEvaluator extends BaseEvaluator {
373: /**
374: *
375: */
376: private static final long serialVersionUID = 400L;
377: public final static Evaluator INSTANCE = new DateGreaterEvaluator();
378:
379: private DateGreaterEvaluator() {
380: super (ValueType.DATE_TYPE, Operator.GREATER);
381: }
382:
383: public boolean evaluate(InternalWorkingMemory workingMemory,
384: final Extractor extractor, final Object object1,
385: final FieldValue object2) {
386: if (extractor.isNullValue(workingMemory, object1)) {
387: return false;
388: }
389: final Date value1 = (Date) extractor.getValue(
390: workingMemory, object1);
391: final Object value2 = object2.getValue();
392: return value1.compareTo(getRightDate(value2)) > 0;
393: }
394:
395: public boolean evaluateCachedRight(
396: InternalWorkingMemory workingMemory,
397: final VariableContextEntry context, final Object left) {
398: if (context.rightNull) {
399: return false;
400: }
401: final Date value1 = (Date) context.declaration
402: .getExtractor().getValue(workingMemory, left);
403: final Object value2 = ((ObjectVariableContextEntry) context).right;
404: return getRightDate(value2).compareTo(value1) > 0;
405: }
406:
407: public boolean evaluateCachedLeft(
408: InternalWorkingMemory workingMemory,
409: final VariableContextEntry context, final Object right) {
410: if (context.extractor.isNullValue(workingMemory, right)) {
411: return false;
412: }
413: final Date value1 = (Date) ((ObjectVariableContextEntry) context).left;
414: final Object value2 = context.extractor.getValue(
415: workingMemory, right);
416: return getRightDate(value2).compareTo(value1) > 0;
417: }
418:
419: public boolean evaluate(InternalWorkingMemory workingMemory,
420: final Extractor extractor1, final Object object1,
421: final Extractor extractor2, final Object object2) {
422: if (extractor1.isNullValue(workingMemory, object1)) {
423: return false;
424: }
425: final Date value1 = (Date) extractor1.getValue(
426: workingMemory, object1);
427: final Date value2 = (Date) extractor2.getValue(
428: workingMemory, object2);
429: return value1.compareTo(value2) > 0;
430: }
431:
432: public String toString() {
433: return "Date >";
434: }
435: }
436:
437: static class DateGreaterOrEqualEvaluator extends BaseEvaluator {
438: /**
439: *
440: */
441: private static final long serialVersionUID = 400L;
442: private final static Evaluator INSTANCE = new DateGreaterOrEqualEvaluator();
443:
444: private DateGreaterOrEqualEvaluator() {
445: super (ValueType.DATE_TYPE, Operator.GREATER_OR_EQUAL);
446: }
447:
448: public boolean evaluate(InternalWorkingMemory workingMemory,
449: final Extractor extractor, final Object object1,
450: final FieldValue object2) {
451: if (extractor.isNullValue(workingMemory, object1)) {
452: return false;
453: }
454: final Date value1 = (Date) extractor.getValue(
455: workingMemory, object1);
456: final Object value2 = object2.getValue();
457: return value1.compareTo(getRightDate(value2)) >= 0;
458: }
459:
460: public boolean evaluateCachedRight(
461: InternalWorkingMemory workingMemory,
462: final VariableContextEntry context, final Object left) {
463: if (context.rightNull) {
464: return false;
465: }
466: final Date value1 = (Date) context.declaration
467: .getExtractor().getValue(workingMemory, left);
468: final Object value2 = ((ObjectVariableContextEntry) context).right;
469: return getRightDate(value2).compareTo(value1) >= 0;
470: }
471:
472: public boolean evaluateCachedLeft(
473: InternalWorkingMemory workingMemory,
474: final VariableContextEntry context, final Object right) {
475: if (context.extractor.isNullValue(workingMemory, right)) {
476: return false;
477: }
478: final Date value1 = (Date) ((ObjectVariableContextEntry) context).left;
479: final Object value2 = context.extractor.getValue(
480: workingMemory, right);
481: return getRightDate(value2).compareTo(value1) >= 0;
482: }
483:
484: public boolean evaluate(InternalWorkingMemory workingMemory,
485: final Extractor extractor1, final Object object1,
486: final Extractor extractor2, final Object object2) {
487: if (extractor1.isNullValue(workingMemory, object1)) {
488: return false;
489: }
490: final Date value1 = (Date) extractor1.getValue(
491: workingMemory, object1);
492: final Date value2 = (Date) extractor2.getValue(
493: workingMemory, object2);
494: return value1.compareTo(value2) >= 0;
495: }
496:
497: public String toString() {
498: return "Date >=";
499: }
500: }
501:
502: static class DateMemberOfEvaluator extends BaseMemberOfEvaluator {
503:
504: private static final long serialVersionUID = 400L;
505: public final static Evaluator INSTANCE = new DateMemberOfEvaluator();
506:
507: private DateMemberOfEvaluator() {
508: super (ValueType.DATE_TYPE, Operator.MEMBEROF);
509: }
510:
511: public String toString() {
512: return "Date memberOf";
513: }
514: }
515:
516: static class DateNotMemberOfEvaluator extends
517: BaseNotMemberOfEvaluator {
518:
519: private static final long serialVersionUID = 400L;
520: public final static Evaluator INSTANCE = new DateNotMemberOfEvaluator();
521:
522: private DateNotMemberOfEvaluator() {
523: super (ValueType.DATE_TYPE, Operator.NOTMEMBEROF);
524: }
525:
526: public String toString() {
527: return "Date not memberOf";
528: }
529: }
530:
531: /** Use the simple date formatter to read the date from a string */
532: public static Date parseDate(final String input) {
533: try {
534: return df.parse(input);
535: } catch (final ParseException e) {
536: throw new IllegalArgumentException(
537: "Invalid date input format: [" + input
538: + "] it should follow: ["
539: + DateFactory.DATE_FORMAT_MASK + "]");
540: }
541: }
542:
543: /** Converts the right hand side date as appropriate */
544: private static Date getRightDate(final Object object2) {
545: if (object2 == null) {
546: return null;
547: }
548: if (object2 instanceof String) {
549: return parseDate((String) object2);
550: } else if (object2 instanceof Date) {
551: return (Date) object2;
552: } else {
553: throw new IllegalArgumentException("Unable to convert "
554: + object2.getClass() + " to a Date.");
555: }
556: }
557:
558: /** Check for the system property override, if it exists */
559: private static String getDateFormatMask() {
560: String fmt = System.getProperty("drools.dateformat");
561: if (fmt == null) {
562: fmt = DateFactory.DEFAULT_FORMAT_MASK;
563: }
564: return fmt;
565: }
566:
567: }
|