001: package org.drools.common;
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.io.Serializable;
020: import java.util.ArrayList;
021: import java.util.List;
022:
023: import org.drools.RuleBaseConfiguration;
024: import org.drools.base.evaluators.Operator;
025: import org.drools.reteoo.BetaMemory;
026: import org.drools.reteoo.FactHandleMemory;
027: import org.drools.reteoo.ReteTuple;
028: import org.drools.reteoo.TupleMemory;
029: import org.drools.rule.ContextEntry;
030: import org.drools.rule.VariableConstraint;
031: import org.drools.spi.BetaNodeFieldConstraint;
032: import org.drools.util.FactHashTable;
033: import org.drools.util.FactHandleIndexHashTable;
034: import org.drools.util.FactList;
035: import org.drools.util.LinkedList;
036: import org.drools.util.LinkedListEntry;
037: import org.drools.util.TupleHashTable;
038: import org.drools.util.TupleIndexHashTable;
039: import org.drools.util.AbstractHashTable.FieldIndex;
040:
041: public class QuadroupleBetaConstraints implements Serializable,
042: BetaConstraints {
043:
044: /**
045: *
046: */
047: private static final long serialVersionUID = 400L;
048:
049: private final BetaNodeFieldConstraint constraint0;
050: private final BetaNodeFieldConstraint constraint1;
051: private final BetaNodeFieldConstraint constraint2;
052: private final BetaNodeFieldConstraint constraint3;
053:
054: private final ContextEntry context0;
055: private final ContextEntry context1;
056: private final ContextEntry context2;
057: private final ContextEntry context3;
058:
059: private boolean indexed0;
060: private boolean indexed1;
061: private boolean indexed2;
062: private boolean indexed3;
063:
064: public QuadroupleBetaConstraints(
065: final BetaNodeFieldConstraint[] constraints,
066: final RuleBaseConfiguration conf) {
067: this (constraints, conf, false);
068: }
069:
070: public QuadroupleBetaConstraints(
071: final BetaNodeFieldConstraint[] constraints,
072: final RuleBaseConfiguration conf,
073: final boolean disableIndexing) {
074: if (disableIndexing
075: || (!conf.isIndexLeftBetaMemory() && !conf
076: .isIndexRightBetaMemory())) {
077: this .indexed0 = false;
078: this .indexed1 = false;
079: this .indexed2 = false;
080: this .indexed3 = false;
081: } else {
082: final int depth = conf.getCompositeKeyDepth();
083:
084: // Determine if this constraints are indexable
085: final boolean i0 = isIndexable(constraints[0]);
086: final boolean i1 = isIndexable(constraints[1]);
087: final boolean i2 = isIndexable(constraints[2]);
088: final boolean i3 = isIndexable(constraints[3]);
089:
090: if (depth >= 1 && i0) {
091: this .indexed0 = true;
092: }
093:
094: if (i1) {
095: if (depth >= 1 && !this .indexed0) {
096: this .indexed0 = true;
097: swap(constraints, 1, 0);
098: } else if (depth >= 2) {
099: this .indexed1 = true;
100: }
101: }
102:
103: if (i2) {
104: if (depth >= 1 && !this .indexed0) {
105: this .indexed0 = true;
106: swap(constraints, 2, 0);
107: } else if (depth >= 2 && this .indexed0
108: && !this .indexed1) {
109: this .indexed1 = true;
110: swap(constraints, 2, 1);
111: } else if (depth >= 3) {
112: this .indexed2 = true;
113: }
114: }
115:
116: if (i3) {
117: if (depth >= 1 && !this .indexed0) {
118: this .indexed0 = true;
119: swap(constraints, 3, 0);
120: } else if (depth >= 2 && this .indexed0
121: && !this .indexed1) {
122: this .indexed1 = true;
123: swap(constraints, 3, 1);
124: } else if (depth >= 3 && this .indexed0 && this .indexed1
125: && !this .indexed2) {
126: this .indexed2 = true;
127: swap(constraints, 3, 2);
128: } else if (depth >= 4) {
129: this .indexed3 = true;
130: }
131: }
132: }
133:
134: this .constraint0 = constraints[0];
135: this .context0 = this .constraint0.getContextEntry();
136:
137: this .constraint1 = constraints[1];
138: this .context1 = this .constraint1.getContextEntry();
139:
140: this .constraint2 = constraints[2];
141: this .context2 = this .constraint2.getContextEntry();
142:
143: this .constraint3 = constraints[3];
144: this .context3 = this .constraint3.getContextEntry();
145: }
146:
147: private void swap(final BetaNodeFieldConstraint[] constraints,
148: final int p1, final int p2) {
149: final BetaNodeFieldConstraint temp = constraints[p2];
150: constraints[p2] = constraints[p1];
151: constraints[p1] = temp;
152: }
153:
154: private boolean isIndexable(final BetaNodeFieldConstraint constraint) {
155: if (constraint instanceof VariableConstraint) {
156: final VariableConstraint variableConstraint = (VariableConstraint) constraint;
157: return (variableConstraint.getEvaluator().getOperator() == Operator.EQUAL);
158: } else {
159: return false;
160: }
161: }
162:
163: /* (non-Javadoc)
164: * @see org.drools.common.BetaNodeConstraints#updateFromTuple(org.drools.reteoo.ReteTuple)
165: */
166: public void updateFromTuple(
167: final InternalWorkingMemory workingMemory,
168: final ReteTuple tuple) {
169: this .context0.updateFromTuple(workingMemory, tuple);
170: this .context1.updateFromTuple(workingMemory, tuple);
171: this .context2.updateFromTuple(workingMemory, tuple);
172: this .context3.updateFromTuple(workingMemory, tuple);
173: }
174:
175: /* (non-Javadoc)
176: * @see org.drools.common.BetaNodeConstraints#updateFromFactHandle(org.drools.common.InternalFactHandle)
177: */
178: public void updateFromFactHandle(
179: final InternalWorkingMemory workingMemory,
180: final InternalFactHandle handle) {
181: this .context0.updateFromFactHandle(workingMemory, handle);
182: this .context1.updateFromFactHandle(workingMemory, handle);
183: this .context2.updateFromFactHandle(workingMemory, handle);
184: this .context3.updateFromFactHandle(workingMemory, handle);
185: }
186:
187: /* (non-Javadoc)
188: * @see org.drools.common.BetaNodeConstraints#isAllowedCachedLeft(java.lang.Object)
189: */
190: public boolean isAllowedCachedLeft(final Object object) {
191: // return ( this.indexed0 || this.constraint0.isAllowedCachedLeft( context0,
192: // object ) ) && this.constraint1.isAllowedCachedLeft( context1,
193: // object ) && this.constraint2.isAllowedCachedLeft( context2,
194: // object );
195:
196: return (this .indexed0 || this .constraint0.isAllowedCachedLeft(
197: this .context0, object))
198: && (this .indexed1 || this .constraint1
199: .isAllowedCachedLeft(this .context1, object))
200: && (this .indexed2 || this .constraint2
201: .isAllowedCachedLeft(this .context2, object))
202: && (this .indexed3 || this .constraint3
203: .isAllowedCachedLeft(this .context3, object));
204: }
205:
206: /* (non-Javadoc)
207: * @see org.drools.common.BetaNodeConstraints#isAllowedCachedRight(org.drools.reteoo.ReteTuple)
208: */
209: public boolean isAllowedCachedRight(final ReteTuple tuple) {
210: return this .constraint0.isAllowedCachedRight(tuple,
211: this .context0)
212: && this .constraint1.isAllowedCachedRight(tuple,
213: this .context1)
214: && this .constraint2.isAllowedCachedRight(tuple,
215: this .context2)
216: && (this .indexed3 || this .constraint3
217: .isAllowedCachedRight(tuple, this .context3));
218: }
219:
220: public boolean isIndexed() {
221: return this .indexed0;
222: }
223:
224: public int getIndexCount() {
225: int count = 0;
226: if (this .indexed0) {
227: count++;
228: }
229: if (this .indexed1) {
230: count++;
231: }
232: if (this .indexed2) {
233: count++;
234: }
235: if (this .indexed3) {
236: count++;
237: }
238: return count;
239: }
240:
241: public boolean isEmpty() {
242: return false;
243: }
244:
245: public BetaMemory createBetaMemory(RuleBaseConfiguration conf) {
246:
247: BetaMemory memory;
248:
249: final List list = new ArrayList(2);
250: if (this .indexed0) {
251: final VariableConstraint variableConstraint = (VariableConstraint) this .constraint0;
252: final FieldIndex index = new FieldIndex(variableConstraint
253: .getFieldExtractor(), variableConstraint
254: .getRequiredDeclarations()[0], variableConstraint
255: .getEvaluator());
256: list.add(index);
257:
258: }
259:
260: if (this .indexed1) {
261: final VariableConstraint variableConstraint = (VariableConstraint) this .constraint1;
262: final FieldIndex index = new FieldIndex(variableConstraint
263: .getFieldExtractor(), variableConstraint
264: .getRequiredDeclarations()[0], variableConstraint
265: .getEvaluator());
266: list.add(index);
267: }
268:
269: if (this .indexed2) {
270: final VariableConstraint variableConstraint = (VariableConstraint) this .constraint2;
271: final FieldIndex index = new FieldIndex(variableConstraint
272: .getFieldExtractor(), variableConstraint
273: .getRequiredDeclarations()[0], variableConstraint
274: .getEvaluator());
275: list.add(index);
276: }
277:
278: if (this .indexed3) {
279: final VariableConstraint variableConstraint = (VariableConstraint) this .constraint3;
280: final FieldIndex index = new FieldIndex(variableConstraint
281: .getFieldExtractor(), variableConstraint
282: .getRequiredDeclarations()[0], variableConstraint
283: .getEvaluator());
284: list.add(index);
285: }
286:
287: if (!list.isEmpty()) {
288: final FieldIndex[] indexes = (FieldIndex[]) list
289: .toArray(new FieldIndex[list.size()]);
290: TupleMemory tupleMemory;
291: if (conf.isIndexLeftBetaMemory()) {
292: tupleMemory = new TupleIndexHashTable(indexes);
293: } else {
294: tupleMemory = new TupleHashTable();
295: }
296:
297: FactHandleMemory factHandleMemory;
298: if (conf.isIndexRightBetaMemory()) {
299: factHandleMemory = new FactHandleIndexHashTable(indexes);
300: } else {
301: factHandleMemory = conf.isSequential() ? (FactHandleMemory) new FactList()
302: : (FactHandleMemory) new FactHashTable();
303: }
304: memory = new BetaMemory(conf.isSequential() ? null
305: : tupleMemory, factHandleMemory);
306: } else {
307: memory = new BetaMemory(
308: conf.isSequential() ? null : new TupleHashTable(),
309: conf.isSequential() ? (FactHandleMemory) new FactList()
310: : (FactHandleMemory) new FactHashTable());
311: }
312:
313: return memory;
314: }
315:
316: public int hashCode() {
317: return this .constraint0.hashCode()
318: ^ this .constraint1.hashCode()
319: ^ this .constraint2.hashCode()
320: ^ this .constraint3.hashCode();
321: }
322:
323: /* (non-Javadoc)
324: * @see org.drools.common.BetaNodeConstraints#getConstraints()
325: */
326: public LinkedList getConstraints() {
327: final LinkedList list = new LinkedList();
328: list.add(new LinkedListEntry(this .constraint0));
329: list.add(new LinkedListEntry(this .constraint1));
330: list.add(new LinkedListEntry(this .constraint2));
331: list.add(new LinkedListEntry(this .constraint3));
332: return list;
333: }
334:
335: /**
336: * Determine if another object is equal to this.
337: *
338: * @param object
339: * The object to test.
340: *
341: * @return <code>true</code> if <code>object</code> is equal to this,
342: * otherwise <code>false</code>.
343: */
344: public boolean equals(final Object object) {
345: if (this == object) {
346: return true;
347: }
348:
349: if (object == null
350: || !(object instanceof QuadroupleBetaConstraints)) {
351: return false;
352: }
353:
354: final QuadroupleBetaConstraints other = (QuadroupleBetaConstraints) object;
355:
356: if (this .constraint0 != other.constraint0
357: && !this .constraint0.equals(other.constraint0)) {
358: return false;
359: }
360:
361: if (this .constraint1 != other.constraint1
362: && !this .constraint1.equals(other.constraint1)) {
363: return false;
364: }
365:
366: if (this .constraint2 != other.constraint2
367: && !this .constraint2.equals(other.constraint2)) {
368: return false;
369: }
370:
371: if (this .constraint3 != other.constraint3
372: && !this .constraint3.equals(other.constraint3)) {
373: return false;
374: }
375:
376: return true;
377: }
378:
379: }
|