001: package org.drools.rule;
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.util.Arrays;
020:
021: import org.drools.base.evaluators.Operator;
022: import org.drools.common.InternalFactHandle;
023: import org.drools.common.InternalWorkingMemory;
024: import org.drools.reteoo.ReteTuple;
025: import org.drools.spi.Evaluator;
026: import org.drools.spi.Extractor;
027: import org.drools.spi.FieldExtractor;
028: import org.drools.spi.Restriction;
029:
030: public class VariableRestriction implements Restriction {
031:
032: private static final long serialVersionUID = 400L;
033:
034: private final Declaration declaration;
035:
036: private final Declaration[] requiredDeclarations;
037:
038: private final Evaluator evaluator;
039:
040: private final VariableContextEntry contextEntry;
041:
042: public VariableRestriction(final FieldExtractor fieldExtractor,
043: final Declaration declaration, final Evaluator evaluator) {
044: this .declaration = declaration;
045: this .requiredDeclarations = new Declaration[] { declaration };
046: this .evaluator = evaluator;
047: this .contextEntry = this .createContextEntry(this .evaluator,
048: fieldExtractor);
049: }
050:
051: public Declaration[] getRequiredDeclarations() {
052: return this .requiredDeclarations;
053: }
054:
055: public Evaluator getEvaluator() {
056: return this .evaluator;
057: }
058:
059: public boolean isAllowed(final Extractor extractor,
060: final Object object,
061: final InternalWorkingMemory workingMemory) {
062: return this .evaluator.evaluate(workingMemory,
063: this .contextEntry.extractor, object,
064: this .contextEntry.declaration.getExtractor(), object);
065: }
066:
067: public boolean isAllowedCachedLeft(final ContextEntry context,
068: final Object object) {
069: return this .evaluator.evaluateCachedLeft(
070: ((VariableContextEntry) context).workingMemory,
071: (VariableContextEntry) context, object);
072: }
073:
074: public boolean isAllowedCachedRight(final ReteTuple tuple,
075: final ContextEntry context) {
076: return this .evaluator.evaluateCachedRight(
077: ((VariableContextEntry) context).workingMemory,
078: (VariableContextEntry) context, tuple.get(
079: this .declaration).getObject());
080: }
081:
082: public String toString() {
083: return "[VariableRestriction declaration=" + this .declaration
084: + "]";
085: }
086:
087: /* (non-Javadoc)
088: * @see java.lang.Object#hashCode()
089: */
090: public int hashCode() {
091: final int PRIME = 31;
092: int result = 1;
093: result = PRIME
094: * result
095: + ((this .declaration == null) ? 0 : this .declaration
096: .hashCode());
097: result = PRIME
098: * result
099: + ((this .evaluator == null) ? 0 : this .evaluator
100: .hashCode());
101: result = PRIME * result
102: + this .requiredDeclarations[0].hashCode();
103: return result;
104: }
105:
106: public boolean equals(final Object object) {
107: if (this == object) {
108: return true;
109: }
110:
111: if (object == null || getClass() != object.getClass()) {
112: return false;
113: }
114:
115: final VariableRestriction other = (VariableRestriction) object;
116:
117: return this .declaration.equals(other.declaration)
118: && this .evaluator.equals(other.evaluator)
119: && Arrays.equals(this .requiredDeclarations,
120: other.requiredDeclarations);
121: }
122:
123: private final VariableContextEntry createContextEntry(
124: final Evaluator eval, final FieldExtractor fieldExtractor) {
125: if (Operator.MEMBEROF.equals(eval.getOperator())
126: || Operator.NOTMEMBEROF.equals(eval.getOperator())) {
127: return new ObjectVariableContextEntry(fieldExtractor,
128: this .declaration);
129: } else {
130: if (fieldExtractor.getValueType().isBoolean()) {
131: return new BooleanVariableContextEntry(fieldExtractor,
132: this .declaration);
133: } else if (fieldExtractor.getValueType().isFloatNumber()) {
134: return new DoubleVariableContextEntry(fieldExtractor,
135: this .declaration);
136: } else if (fieldExtractor.getValueType().isIntegerNumber()) {
137: return new LongVariableContextEntry(fieldExtractor,
138: this .declaration);
139: } else if (fieldExtractor.getValueType().isChar()) {
140: return new CharVariableContextEntry(fieldExtractor,
141: this .declaration);
142: } else {
143: return new ObjectVariableContextEntry(fieldExtractor,
144: this .declaration);
145: }
146: }
147: }
148:
149: public ContextEntry getContextEntry() {
150: return this .contextEntry;
151: }
152:
153: public static abstract class VariableContextEntry implements
154: ContextEntry {
155: public FieldExtractor extractor;
156: public Object object;
157: public Declaration declaration;
158: public ReteTuple reteTuple;
159: public ContextEntry entry;
160: public boolean leftNull;
161: public boolean rightNull;
162: public InternalWorkingMemory workingMemory;
163:
164: public VariableContextEntry(final FieldExtractor extractor,
165: final Declaration declaration) {
166: this .extractor = extractor;
167: this .declaration = declaration;
168: }
169:
170: public ContextEntry getNext() {
171: return this .entry;
172: }
173:
174: public void setNext(final ContextEntry entry) {
175: this .entry = entry;
176: }
177:
178: public FieldExtractor getFieldExtractor() {
179: return this .extractor;
180: }
181:
182: public Object getObject() {
183: return this .object;
184: }
185:
186: public ReteTuple getTuple() {
187: return this .reteTuple;
188: }
189:
190: public Declaration getVariableDeclaration() {
191: return this .declaration;
192: }
193:
194: public boolean isLeftNull() {
195: return this .leftNull;
196: }
197:
198: public boolean isRightNull() {
199: return this .rightNull;
200: }
201: }
202:
203: public static class ObjectVariableContextEntry extends
204: VariableContextEntry {
205:
206: private static final long serialVersionUID = 400L;
207: public Object left;
208: public Object right;
209:
210: public ObjectVariableContextEntry(
211: final FieldExtractor extractor,
212: final Declaration declaration) {
213: super (extractor, declaration);
214: }
215:
216: public void updateFromTuple(
217: final InternalWorkingMemory workingMemory,
218: final ReteTuple tuple) {
219: this .reteTuple = tuple;
220: this .workingMemory = workingMemory;
221: this .leftNull = this .declaration.getExtractor()
222: .isNullValue(workingMemory,
223: tuple.get(this .declaration).getObject());
224: this .left = this .declaration.getExtractor().getValue(
225: workingMemory,
226: tuple.get(this .declaration).getObject());
227: }
228:
229: public void updateFromFactHandle(
230: final InternalWorkingMemory workingMemory,
231: final InternalFactHandle handle) {
232: this .object = handle.getObject();
233: this .workingMemory = workingMemory;
234: this .rightNull = this .extractor.isNullValue(workingMemory,
235: handle.getObject());
236: this .right = this .extractor.getValue(workingMemory, handle
237: .getObject());
238: }
239: }
240:
241: public static class LongVariableContextEntry extends
242: VariableContextEntry {
243:
244: private static final long serialVersionUID = 400L;
245:
246: public long left;
247: public long right;
248:
249: public LongVariableContextEntry(final FieldExtractor extractor,
250: final Declaration declaration) {
251: super (extractor, declaration);
252: }
253:
254: public void updateFromTuple(
255: final InternalWorkingMemory workingMemory,
256: final ReteTuple tuple) {
257: this .reteTuple = tuple;
258: this .workingMemory = workingMemory;
259: this .leftNull = this .declaration.getExtractor()
260: .isNullValue(workingMemory,
261: tuple.get(this .declaration).getObject());
262:
263: if (!leftNull) {
264: this .left = this .declaration
265: .getExtractor()
266: .getLongValue(workingMemory,
267: tuple.get(this .declaration).getObject());
268: } else {
269: this .left = 0;
270: }
271: }
272:
273: public void updateFromFactHandle(
274: final InternalWorkingMemory workingMemory,
275: final InternalFactHandle handle) {
276: this .object = handle.getObject();
277: this .workingMemory = workingMemory;
278: this .rightNull = this .extractor.isNullValue(workingMemory,
279: handle.getObject());
280:
281: if (!rightNull) { // avoid a NullPointerException
282: this .right = this .extractor.getLongValue(workingMemory,
283: handle.getObject());
284: } else {
285: this .right = 0;
286: }
287: }
288: }
289:
290: public static class CharVariableContextEntry extends
291: VariableContextEntry {
292:
293: private static final long serialVersionUID = 400L;
294:
295: public char left;
296: public char right;
297:
298: public CharVariableContextEntry(final FieldExtractor extractor,
299: final Declaration declaration) {
300: super (extractor, declaration);
301: }
302:
303: public void updateFromTuple(
304: final InternalWorkingMemory workingMemory,
305: final ReteTuple tuple) {
306: this .reteTuple = tuple;
307: this .workingMemory = workingMemory;
308: this .leftNull = this .declaration.getExtractor()
309: .isNullValue(workingMemory,
310: tuple.get(this .declaration).getObject());
311:
312: if (!leftNull) {
313: this .left = this .declaration
314: .getExtractor()
315: .getCharValue(workingMemory,
316: tuple.get(this .declaration).getObject());
317: } else {
318: this .left = 0;
319: }
320: }
321:
322: public void updateFromFactHandle(
323: final InternalWorkingMemory workingMemory,
324: final InternalFactHandle handle) {
325: this .object = handle.getObject();
326: this .workingMemory = workingMemory;
327: this .rightNull = this .extractor.isNullValue(workingMemory,
328: handle.getObject());
329:
330: if (!rightNull) { // avoid a NullPointerException
331: this .right = this .extractor.getCharValue(workingMemory,
332: handle.getObject());
333: } else {
334: this .right = 0;
335: }
336: }
337: }
338:
339: public static class DoubleVariableContextEntry extends
340: VariableContextEntry {
341:
342: private static final long serialVersionUID = 400L;
343:
344: public double left;
345: public double right;
346:
347: public DoubleVariableContextEntry(
348: final FieldExtractor extractor,
349: final Declaration declaration) {
350: super (extractor, declaration);
351: }
352:
353: public void updateFromTuple(
354: final InternalWorkingMemory workingMemory,
355: final ReteTuple tuple) {
356: this .reteTuple = tuple;
357: this .workingMemory = workingMemory;
358: this .leftNull = this .declaration.getExtractor()
359: .isNullValue(workingMemory,
360: tuple.get(this .declaration).getObject());
361:
362: if (!leftNull) {
363: this .left = this .declaration
364: .getExtractor()
365: .getDoubleValue(workingMemory,
366: tuple.get(this .declaration).getObject());
367: } else {
368: this .left = 0;
369: }
370: }
371:
372: public void updateFromFactHandle(
373: final InternalWorkingMemory workingMemory,
374: final InternalFactHandle handle) {
375: this .object = handle.getObject();
376: this .workingMemory = workingMemory;
377: this .rightNull = this .extractor.isNullValue(workingMemory,
378: handle.getObject());
379:
380: if (!rightNull) { // avoid a NullPointerException
381: this .right = this .extractor.getDoubleValue(
382: workingMemory, handle.getObject());
383: } else {
384: this .right = 0;
385: }
386: }
387: }
388:
389: public static class BooleanVariableContextEntry extends
390: VariableContextEntry {
391:
392: private static final long serialVersionUID = 400L;
393: public boolean left;
394: public boolean right;
395:
396: public BooleanVariableContextEntry(
397: final FieldExtractor extractor,
398: final Declaration declaration) {
399: super (extractor, declaration);
400: }
401:
402: public void updateFromTuple(
403: final InternalWorkingMemory workingMemory,
404: final ReteTuple tuple) {
405: this .reteTuple = tuple;
406: this .workingMemory = workingMemory;
407: this .leftNull = this .declaration.getExtractor()
408: .isNullValue(workingMemory,
409: tuple.get(this .declaration).getObject());
410:
411: if (!leftNull) {
412: this .left = this .declaration
413: .getExtractor()
414: .getBooleanValue(workingMemory,
415: tuple.get(this .declaration).getObject());
416: } else {
417: this .left = false;
418: }
419: }
420:
421: public void updateFromFactHandle(
422: final InternalWorkingMemory workingMemory,
423: final InternalFactHandle handle) {
424: this .object = handle.getObject();
425: this .workingMemory = workingMemory;
426: this .rightNull = this .extractor.isNullValue(workingMemory,
427: handle.getObject());
428:
429: if (!rightNull) { // avoid a NullPointerException
430: this .right = this .extractor.getBooleanValue(
431: workingMemory, handle.getObject());
432: } else {
433: this .right = false;
434: }
435: }
436: }
437: }
|