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