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.RuntimeDroolsException;
022: import org.drools.common.InternalFactHandle;
023: import org.drools.common.InternalWorkingMemory;
024: import org.drools.reteoo.ReteTuple;
025: import org.drools.spi.AlphaNodeFieldConstraint;
026: import org.drools.spi.BetaNodeFieldConstraint;
027: import org.drools.spi.PredicateExpression;
028:
029: public class PredicateConstraint implements BetaNodeFieldConstraint,
030: AlphaNodeFieldConstraint {
031:
032: /**
033: *
034: */
035: private static final long serialVersionUID = 400L;
036:
037: private PredicateExpression expression;
038:
039: private final Declaration[] requiredDeclarations;
040:
041: private final Declaration[] previousDeclarations;
042:
043: private final Declaration[] localDeclarations;
044:
045: private final String[] requiredGlobals;
046:
047: private static final Declaration[] EMPTY_DECLARATIONS = new Declaration[0];
048: private static final String[] EMPTY_GLOBALS = new String[0];
049:
050: public PredicateConstraint(final PredicateExpression evaluator) {
051: this (evaluator, null, null, null);
052: }
053:
054: public PredicateConstraint(
055: final Declaration[] previousDeclarations,
056: final Declaration[] localDeclarations) {
057: this (null, previousDeclarations, localDeclarations, null);
058: }
059:
060: public PredicateConstraint(final PredicateExpression expression,
061: final Declaration[] previousDeclarations,
062: final Declaration[] localDeclarations,
063: final String[] requiredGlobals) {
064:
065: this .expression = expression;
066:
067: if (previousDeclarations == null) {
068: this .previousDeclarations = PredicateConstraint.EMPTY_DECLARATIONS;
069: } else {
070: this .previousDeclarations = previousDeclarations;
071: }
072:
073: if (localDeclarations == null) {
074: this .localDeclarations = PredicateConstraint.EMPTY_DECLARATIONS;
075: } else {
076: this .localDeclarations = localDeclarations;
077: }
078:
079: if (requiredGlobals == null) {
080: this .requiredGlobals = PredicateConstraint.EMPTY_GLOBALS;
081: } else {
082: this .requiredGlobals = requiredGlobals;
083: }
084:
085: this .requiredDeclarations = new Declaration[this .previousDeclarations.length
086: + this .localDeclarations.length];
087: System.arraycopy(this .previousDeclarations, 0,
088: this .requiredDeclarations, 0,
089: this .previousDeclarations.length);
090: System.arraycopy(this .localDeclarations, 0,
091: this .requiredDeclarations,
092: this .previousDeclarations.length,
093: this .localDeclarations.length);
094: }
095:
096: public Declaration[] getRequiredDeclarations() {
097: return this .requiredDeclarations;
098: }
099:
100: public Declaration[] getPreviousDeclarations() {
101: return this .previousDeclarations;
102: }
103:
104: public Declaration[] getLocalDeclarations() {
105: return this .localDeclarations;
106: }
107:
108: public void setPredicateExpression(
109: final PredicateExpression expression) {
110: this .expression = expression;
111: }
112:
113: public PredicateExpression getPredicateExpression() {
114: return this .expression;
115: }
116:
117: public String toString() {
118: return "[PredicateConstraint previousDeclarations="
119: + this .previousDeclarations + " localDeclarations="
120: + this .localDeclarations + "]";
121: }
122:
123: public int hashCode() {
124: return this .expression.hashCode();
125: }
126:
127: public boolean equals(final Object object) {
128: if (object == this ) {
129: return true;
130: }
131:
132: if (object == null
133: || object.getClass() != PredicateConstraint.class) {
134: return false;
135: }
136:
137: final PredicateConstraint other = (PredicateConstraint) object;
138:
139: if (this .previousDeclarations.length != other.previousDeclarations.length) {
140: return false;
141: }
142:
143: if (this .localDeclarations.length != other.localDeclarations.length) {
144: return false;
145: }
146:
147: if (this .requiredGlobals.length != other.requiredGlobals.length) {
148: return false;
149: }
150:
151: for (int i = 0, length = this .previousDeclarations.length; i < length; i++) {
152: if (this .previousDeclarations[i].getPattern().getOffset() != other.previousDeclarations[i]
153: .getPattern().getOffset()) {
154: return false;
155: }
156:
157: if (!this .previousDeclarations[i].getExtractor().equals(
158: other.previousDeclarations[i].getExtractor())) {
159: return false;
160: }
161: }
162:
163: for (int i = 0, length = this .localDeclarations.length; i < length; i++) {
164: if (this .localDeclarations[i].getPattern().getOffset() != other.localDeclarations[i]
165: .getPattern().getOffset()) {
166: return false;
167: }
168:
169: if (!this .localDeclarations[i].getExtractor().equals(
170: other.localDeclarations[i].getExtractor())) {
171: return false;
172: }
173: }
174:
175: if (!Arrays.equals(this .requiredGlobals, other.requiredGlobals)) {
176: return false;
177: }
178:
179: return this .expression.equals(other.expression);
180: }
181:
182: public ContextEntry getContextEntry() {
183: return new PredicateContextEntry();
184: }
185:
186: public boolean isAllowed(final Object object,
187: final InternalWorkingMemory workingMemory) {
188: try {
189: return this .expression.evaluate(object, null,
190: this .previousDeclarations, this .localDeclarations,
191: workingMemory);
192: } catch (final Exception e) {
193: throw new RuntimeDroolsException(
194: "Exception executing predicate " + this .expression,
195: e);
196: }
197: }
198:
199: public boolean isAllowedCachedLeft(final ContextEntry context,
200: final Object object) {
201: try {
202: final PredicateContextEntry ctx = (PredicateContextEntry) context;
203: return this .expression.evaluate(object, ctx.leftTuple,
204: this .previousDeclarations, this .localDeclarations,
205: ctx.workingMemory);
206: } catch (final Exception e) {
207: throw new RuntimeDroolsException(
208: "Exception executing predicate " + this .expression,
209: e);
210: }
211: }
212:
213: public boolean isAllowedCachedRight(final ReteTuple tuple,
214: final ContextEntry context) {
215: try {
216: final PredicateContextEntry ctx = (PredicateContextEntry) context;
217: return this .expression.evaluate(ctx.rightObject, tuple,
218: this .previousDeclarations, this .localDeclarations,
219: ctx.workingMemory);
220: } catch (final Exception e) {
221: throw new RuntimeDroolsException(
222: "Exception executing predicate " + this .expression,
223: e);
224: }
225: }
226:
227: public static class PredicateContextEntry implements ContextEntry {
228:
229: private static final long serialVersionUID = 400L;
230:
231: public ReteTuple leftTuple;
232: public Object rightObject;
233: public InternalWorkingMemory workingMemory;
234:
235: private ContextEntry entry;
236:
237: public PredicateContextEntry() {
238: }
239:
240: public ContextEntry getNext() {
241: return this .entry;
242: }
243:
244: public void setNext(final ContextEntry entry) {
245: this .entry = entry;
246: }
247:
248: public void updateFromFactHandle(
249: final InternalWorkingMemory workingMemory,
250: final InternalFactHandle handle) {
251: this .workingMemory = workingMemory;
252: this .rightObject = handle.getObject();
253: }
254:
255: public void updateFromTuple(
256: final InternalWorkingMemory workingMemory,
257: final ReteTuple tuple) {
258: this.workingMemory = workingMemory;
259: this.leftTuple = tuple;
260: }
261: }
262:
263: }
|