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.WorkingMemory;
023: import org.drools.common.InternalFactHandle;
024: import org.drools.common.InternalWorkingMemory;
025: import org.drools.reteoo.ReteTuple;
026: import org.drools.spi.Evaluator;
027: import org.drools.spi.Extractor;
028: import org.drools.spi.FieldExtractor;
029: import org.drools.spi.Restriction;
030: import org.drools.spi.ReturnValueExpression;
031: import org.drools.spi.Tuple;
032:
033: public class ReturnValueRestriction implements Restriction {
034:
035: private static final long serialVersionUID = 400L;
036:
037: private ReturnValueExpression expression;
038:
039: private final Declaration[] requiredDeclarations;
040:
041: private final String[] requiredGlobals;
042:
043: private final Declaration[] previousDeclarations;
044:
045: private final Declaration[] localDeclarations;
046:
047: private final Evaluator evaluator;
048:
049: private static final Declaration[] noRequiredDeclarations = new Declaration[] {};
050:
051: private static final String[] noRequiredGlobals = new String[] {};
052:
053: private final ReturnValueContextEntry contextEntry;
054:
055: public ReturnValueRestriction(final FieldExtractor fieldExtractor,
056: final Declaration[] previousDeclarations,
057: final Declaration[] localDeclarations,
058: final String[] requiredGlobals, final Evaluator evaluator) {
059: this (fieldExtractor, null, previousDeclarations,
060: localDeclarations, requiredGlobals, evaluator);
061: }
062:
063: public ReturnValueRestriction(final FieldExtractor fieldExtractor,
064: final ReturnValueExpression returnValueExpression,
065: final Declaration[] previousDeclarations,
066: final Declaration[] localDeclarations,
067: final String[] requiredGlobals, final Evaluator evaluator) {
068: this .expression = returnValueExpression;
069:
070: if (previousDeclarations != null) {
071: this .previousDeclarations = previousDeclarations;
072: } else {
073: this .previousDeclarations = ReturnValueRestriction.noRequiredDeclarations;
074: }
075:
076: if (localDeclarations != null) {
077: this .localDeclarations = localDeclarations;
078: } else {
079: this .localDeclarations = ReturnValueRestriction.noRequiredDeclarations;
080: }
081:
082: if (requiredGlobals != null) {
083: this .requiredGlobals = requiredGlobals;
084: } else {
085: this .requiredGlobals = ReturnValueRestriction.noRequiredGlobals;
086: }
087:
088: this .evaluator = evaluator;
089: this .contextEntry = new ReturnValueContextEntry(fieldExtractor,
090: previousDeclarations, localDeclarations);
091:
092: this .requiredDeclarations = new Declaration[previousDeclarations.length
093: + localDeclarations.length];
094: System.arraycopy(this .previousDeclarations, 0,
095: this .requiredDeclarations, 0,
096: this .previousDeclarations.length);
097: System.arraycopy(this .localDeclarations, 0,
098: this .requiredDeclarations,
099: this .previousDeclarations.length,
100: this .localDeclarations.length);
101: }
102:
103: public Declaration[] getRequiredDeclarations() {
104: return this .requiredDeclarations;
105: }
106:
107: public Declaration[] getPreviousDeclarations() {
108: return this .previousDeclarations;
109: }
110:
111: public Declaration[] getLocalDeclarations() {
112: return this .localDeclarations;
113: }
114:
115: public void setReturnValueExpression(
116: final ReturnValueExpression expression) {
117: this .expression = expression;
118: }
119:
120: public ReturnValueExpression getExpression() {
121: return this .expression;
122: }
123:
124: public Evaluator getEvaluator() {
125: return this .evaluator;
126: }
127:
128: public boolean isAllowed(final Extractor extractor,
129: final Object object, final Tuple tuple,
130: final WorkingMemory workingMemory) {
131: try {
132: return this .evaluator.evaluate(null, extractor, object,
133: this .expression.evaluate(object, tuple,
134: this .previousDeclarations,
135: this .localDeclarations, workingMemory));
136: } catch (final Exception e) {
137: throw new RuntimeDroolsException(e);
138: }
139: }
140:
141: public boolean isAllowed(final Extractor extractor,
142: final Object object,
143: final InternalWorkingMemory workingMemoiry) {
144: throw new UnsupportedOperationException(
145: "does not support method call isAllowed(Object object, InternalWorkingMemory workingMemoiry)");
146: }
147:
148: public boolean isAllowedCachedLeft(final ContextEntry context,
149: final Object object) {
150: throw new UnsupportedOperationException(
151: "does not support method call isAllowed(Object object, InternalWorkingMemory workingMemoiry)");
152: }
153:
154: public boolean isAllowedCachedRight(final ReteTuple tuple,
155: final ContextEntry context) {
156: throw new UnsupportedOperationException(
157: "does not support method call isAllowed(Object object, InternalWorkingMemory workingMemoiry)");
158: }
159:
160: public int hashCode() {
161: final int PRIME = 31;
162: int result = 1;
163: result = PRIME * result + this .evaluator.hashCode();
164: result = PRIME
165: * result
166: + ((this .expression != null) ? this .expression
167: .hashCode() : 0);
168: result = PRIME
169: * result
170: + ReturnValueRestriction
171: .hashCode(this .localDeclarations);
172: result = PRIME
173: * result
174: + ReturnValueRestriction
175: .hashCode(this .previousDeclarations);
176: result = PRIME * result
177: + ReturnValueRestriction.hashCode(this .requiredGlobals);
178: return result;
179: }
180:
181: public boolean equals(final Object object) {
182: if (object == this ) {
183: return true;
184: }
185:
186: if (object == null
187: || object.getClass() != ReturnValueRestriction.class) {
188: return false;
189: }
190:
191: final ReturnValueRestriction other = (ReturnValueRestriction) object;
192:
193: if (this .localDeclarations.length != other.localDeclarations.length) {
194: return false;
195: }
196:
197: if (this .previousDeclarations.length != other.previousDeclarations.length) {
198: return false;
199: }
200:
201: if (this .requiredGlobals.length != other.requiredGlobals.length) {
202: return false;
203: }
204:
205: if (!Arrays.equals(this .localDeclarations,
206: other.localDeclarations)) {
207: return false;
208: }
209:
210: if (!Arrays.equals(this .previousDeclarations,
211: other.previousDeclarations)) {
212: return false;
213: }
214:
215: if (!Arrays.equals(this .requiredGlobals, other.requiredGlobals)) {
216: return false;
217: }
218:
219: return this .evaluator.equals(other.evaluator)
220: && this .expression.equals(other.expression);
221: }
222:
223: private static int hashCode(final Object[] array) {
224: final int PRIME = 31;
225: if (array == null) {
226: return 0;
227: }
228: int result = 1;
229: for (int index = 0; index < array.length; index++) {
230: result = PRIME
231: * result
232: + (array[index] == null ? 0 : array[index]
233: .hashCode());
234: }
235: return result;
236: }
237:
238: public ContextEntry getContextEntry() {
239: return this .contextEntry;
240: }
241:
242: public static class ReturnValueContextEntry implements ContextEntry {
243:
244: private static final long serialVersionUID = 400L;
245:
246: public FieldExtractor fieldExtractor;
247: public Object object;
248: public ReteTuple leftTuple;
249: public InternalWorkingMemory workingMemory;
250: public Declaration[] previousDeclarations;
251: public Declaration[] localDeclarations;
252:
253: private ContextEntry entry;
254:
255: public ReturnValueContextEntry(
256: final FieldExtractor fieldExtractor,
257: final Declaration[] previousDeclarations,
258: final Declaration[] localDeclarations) {
259: this .fieldExtractor = fieldExtractor;
260: this .previousDeclarations = previousDeclarations;
261: this .localDeclarations = localDeclarations;
262: }
263:
264: public ContextEntry getNext() {
265: return this .entry;
266: }
267:
268: public void setNext(final ContextEntry entry) {
269: this .entry = entry;
270: }
271:
272: public void updateFromFactHandle(
273: final InternalWorkingMemory workingMemory,
274: final InternalFactHandle handle) {
275: this .workingMemory = workingMemory;
276: this .object = handle.getObject();
277: }
278:
279: public void updateFromTuple(
280: final InternalWorkingMemory workingMemory,
281: final ReteTuple tuple) {
282: this .workingMemory = workingMemory;
283: this .leftTuple = tuple;
284: }
285:
286: /* (non-Javadoc)
287: * @see org.drools.rule.ReturnValueContextEntry#getFieldExtractor()
288: */
289: public FieldExtractor getFieldExtractor() {
290: return this .fieldExtractor;
291: }
292:
293: /* (non-Javadoc)
294: * @see org.drools.rule.ReturnValueContextEntry#getTuple()
295: */
296: public ReteTuple getTuple() {
297: return this .leftTuple;
298: }
299:
300: /* (non-Javadoc)
301: * @see org.drools.rule.ReturnValueContextEntry#getObject()
302: */
303: public Object getObject() {
304: return this .object;
305: }
306:
307: /* (non-Javadoc)
308: * @see org.drools.rule.ReturnValueContextEntry#getRequiredDeclarations()
309: */
310: public Declaration[] getPreviousDeclarations() {
311: return this .previousDeclarations;
312: }
313:
314: public Declaration[] getLocalDeclarations() {
315: return this .localDeclarations;
316: }
317:
318: /* (non-Javadoc)
319: * @see org.drools.rule.ReturnValueContextEntry#getWorkingMemory()
320: */
321: public InternalWorkingMemory getWorkingMemory() {
322: return this.workingMemory;
323: }
324: }
325:
326: }
|