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 TripleBetaConstraints 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:
053: private final ContextEntry context0;
054: private final ContextEntry context1;
055: private final ContextEntry context2;
056:
057: private boolean indexed0;
058: private boolean indexed1;
059: private boolean indexed2;
060:
061: public TripleBetaConstraints(
062: final BetaNodeFieldConstraint[] constraints,
063: final RuleBaseConfiguration conf) {
064: this (constraints, conf, false);
065: }
066:
067: public TripleBetaConstraints(
068: final BetaNodeFieldConstraint[] constraints,
069: final RuleBaseConfiguration conf,
070: final boolean disableIndexing) {
071: if (disableIndexing
072: || (!conf.isIndexLeftBetaMemory() && !conf
073: .isIndexRightBetaMemory())) {
074: this .indexed0 = false;
075: this .indexed1 = false;
076: this .indexed2 = false;
077: } else {
078: final int depth = conf.getCompositeKeyDepth();
079:
080: // Determine if this constraints are indexable
081: final boolean i0 = isIndexable(constraints[0]);
082: final boolean i1 = isIndexable(constraints[1]);
083: final boolean i2 = isIndexable(constraints[2]);
084:
085: if (depth >= 1 && i0) {
086: this .indexed0 = true;
087: }
088:
089: if (i1) {
090: if (depth >= 1 && !this .indexed0) {
091: this .indexed0 = true;
092: swap(constraints, 1, 0);
093: } else if (depth >= 2) {
094: this .indexed1 = true;
095: }
096: }
097:
098: if (i2) {
099: if (depth >= 1 && !this .indexed0) {
100: this .indexed0 = true;
101: swap(constraints, 2, 0);
102: } else if (depth >= 2 && this .indexed0
103: && !this .indexed1) {
104: this .indexed1 = true;
105: swap(constraints, 2, 1);
106: } else if (depth >= 3) {
107: this .indexed2 = true;
108: }
109: }
110: }
111: this .constraint0 = constraints[0];
112: this .context0 = this .constraint0.getContextEntry();
113:
114: this .constraint1 = constraints[1];
115: this .context1 = this .constraint1.getContextEntry();
116:
117: this .constraint2 = constraints[2];
118: this .context2 = this .constraint2.getContextEntry();
119: }
120:
121: private void swap(final BetaNodeFieldConstraint[] constraints,
122: final int p1, final int p2) {
123: final BetaNodeFieldConstraint temp = constraints[p2];
124: constraints[p2] = constraints[p1];
125: constraints[p1] = temp;
126: }
127:
128: private boolean isIndexable(final BetaNodeFieldConstraint constraint) {
129: if (constraint instanceof VariableConstraint) {
130: final VariableConstraint variableConstraint = (VariableConstraint) constraint;
131: return (variableConstraint.getEvaluator().getOperator() == Operator.EQUAL);
132: } else {
133: return false;
134: }
135: }
136:
137: /* (non-Javadoc)
138: * @see org.drools.common.BetaNodeConstraints#updateFromTuple(org.drools.reteoo.ReteTuple)
139: */
140: public void updateFromTuple(
141: final InternalWorkingMemory workingMemory,
142: final ReteTuple tuple) {
143: this .context0.updateFromTuple(workingMemory, tuple);
144: this .context1.updateFromTuple(workingMemory, tuple);
145: this .context2.updateFromTuple(workingMemory, tuple);
146: }
147:
148: /* (non-Javadoc)
149: * @see org.drools.common.BetaNodeConstraints#updateFromFactHandle(org.drools.common.InternalFactHandle)
150: */
151: public void updateFromFactHandle(
152: final InternalWorkingMemory workingMemory,
153: final InternalFactHandle handle) {
154: this .context0.updateFromFactHandle(workingMemory, handle);
155: this .context1.updateFromFactHandle(workingMemory, handle);
156: this .context2.updateFromFactHandle(workingMemory, handle);
157: }
158:
159: /* (non-Javadoc)
160: * @see org.drools.common.BetaNodeConstraints#isAllowedCachedLeft(java.lang.Object)
161: */
162: public boolean isAllowedCachedLeft(final Object object) {
163: // return ( this.indexed0 || this.constraint0.isAllowedCachedLeft( context0,
164: // object ) ) && this.constraint1.isAllowedCachedLeft( context1,
165: // object ) && this.constraint2.isAllowedCachedLeft( context2,
166: // object );
167:
168: return (this .indexed0 || this .constraint0.isAllowedCachedLeft(
169: this .context0, object))
170: && (this .indexed1 || this .constraint1
171: .isAllowedCachedLeft(this .context1, object))
172: && (this .indexed2 || this .constraint2
173: .isAllowedCachedLeft(this .context2, object));
174: }
175:
176: /* (non-Javadoc)
177: * @see org.drools.common.BetaNodeConstraints#isAllowedCachedRight(org.drools.reteoo.ReteTuple)
178: */
179: public boolean isAllowedCachedRight(final ReteTuple tuple) {
180: return this .constraint0.isAllowedCachedRight(tuple,
181: this .context0)
182: && this .constraint1.isAllowedCachedRight(tuple,
183: this .context1)
184: && this .constraint2.isAllowedCachedRight(tuple,
185: this .context2);
186: }
187:
188: public boolean isIndexed() {
189: return this .indexed0;
190: }
191:
192: public int getIndexCount() {
193: int count = 0;
194: if (this .indexed0) {
195: count++;
196: }
197: if (this .indexed1) {
198: count++;
199: }
200: if (this .indexed2) {
201: count++;
202: }
203: return count;
204: }
205:
206: public boolean isEmpty() {
207: return false;
208: }
209:
210: public BetaMemory createBetaMemory(final RuleBaseConfiguration conf) {
211:
212: BetaMemory memory;
213:
214: final List list = new ArrayList(2);
215: if (this .indexed0) {
216: final VariableConstraint variableConstraint = (VariableConstraint) this .constraint0;
217: final FieldIndex index = new FieldIndex(variableConstraint
218: .getFieldExtractor(), variableConstraint
219: .getRequiredDeclarations()[0], variableConstraint
220: .getEvaluator());
221: list.add(index);
222:
223: }
224:
225: if (this .indexed1) {
226: final VariableConstraint variableConstraint = (VariableConstraint) this .constraint1;
227: final FieldIndex index = new FieldIndex(variableConstraint
228: .getFieldExtractor(), variableConstraint
229: .getRequiredDeclarations()[0], variableConstraint
230: .getEvaluator());
231: list.add(index);
232: }
233:
234: if (this .indexed2) {
235: final VariableConstraint variableConstraint = (VariableConstraint) this .constraint2;
236: final FieldIndex index = new FieldIndex(variableConstraint
237: .getFieldExtractor(), variableConstraint
238: .getRequiredDeclarations()[0], variableConstraint
239: .getEvaluator());
240: list.add(index);
241: }
242:
243: if (!list.isEmpty()) {
244: final FieldIndex[] indexes = (FieldIndex[]) list
245: .toArray(new FieldIndex[list.size()]);
246: TupleMemory tupleMemory;
247: if (conf.isIndexLeftBetaMemory()) {
248: tupleMemory = new TupleIndexHashTable(indexes);
249: } else {
250: tupleMemory = new TupleHashTable();
251: }
252:
253: FactHandleMemory factHandleMemory;
254: if (conf.isIndexRightBetaMemory()) {
255: factHandleMemory = new FactHandleIndexHashTable(indexes);
256: } else {
257: factHandleMemory = conf.isSequential() ? (FactHandleMemory) new FactList()
258: : (FactHandleMemory) new FactHashTable();
259: }
260: memory = new BetaMemory(conf.isSequential() ? null
261: : tupleMemory, factHandleMemory);
262: } else {
263: memory = new BetaMemory(
264: conf.isSequential() ? null : new TupleHashTable(),
265: conf.isSequential() ? (FactHandleMemory) new FactList()
266: : (FactHandleMemory) new FactHashTable());
267: }
268:
269: return memory;
270: }
271:
272: public int hashCode() {
273: return this .constraint0.hashCode()
274: ^ this .constraint1.hashCode()
275: ^ this .constraint2.hashCode();
276: }
277:
278: /* (non-Javadoc)
279: * @see org.drools.common.BetaNodeConstraints#getConstraints()
280: */
281: public LinkedList getConstraints() {
282: final LinkedList list = new LinkedList();
283: list.add(new LinkedListEntry(this .constraint0));
284: list.add(new LinkedListEntry(this .constraint1));
285: list.add(new LinkedListEntry(this .constraint2));
286: return list;
287: }
288:
289: /**
290: * Determine if another object is equal to this.
291: *
292: * @param object
293: * The object to test.
294: *
295: * @return <code>true</code> if <code>object</code> is equal to this,
296: * otherwise <code>false</code>.
297: */
298: public boolean equals(final Object object) {
299: if (this == object) {
300: return true;
301: }
302:
303: if (object == null || getClass() != object.getClass()) {
304: return false;
305: }
306:
307: final TripleBetaConstraints other = (TripleBetaConstraints) object;
308:
309: if (this .constraint0 != other.constraint0
310: && !this .constraint0.equals(other.constraint0)) {
311: return false;
312: }
313:
314: if (this .constraint1 != other.constraint1
315: && !this .constraint1.equals(other.constraint1)) {
316: return false;
317: }
318:
319: if (this .constraint2 != other.constraint2
320: && !this .constraint2.equals(other.constraint2)) {
321: return false;
322: }
323:
324: return true;
325: }
326:
327: }
|