001: /*
002: * Copyright 2006 JBoss Inc
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.drools.reteoo.builder;
018:
019: import java.util.Iterator;
020: import java.util.LinkedList;
021: import java.util.List;
022:
023: import org.drools.base.ClassObjectType;
024: import org.drools.common.InstanceNotEqualsConstraint;
025: import org.drools.common.InternalWorkingMemory;
026: import org.drools.reteoo.AlphaNode;
027: import org.drools.reteoo.ObjectSource;
028: import org.drools.reteoo.ObjectTypeNode;
029: import org.drools.reteoo.Rete;
030: import org.drools.reteoo.ReteooBuilder;
031: import org.drools.reteoo.ReteooRuleBase;
032: import org.drools.rule.Declaration;
033: import org.drools.rule.InvalidPatternException;
034: import org.drools.rule.Pattern;
035: import org.drools.rule.PatternSource;
036: import org.drools.rule.RuleConditionElement;
037: import org.drools.spi.AlphaNodeFieldConstraint;
038: import org.drools.spi.Constraint;
039: import org.drools.spi.ObjectType;
040:
041: /**
042: * A builder for patterns
043: *
044: * @author etirelli
045: */
046: public class PatternBuilder implements ReteooComponentBuilder {
047:
048: /**
049: * @inheritDoc
050: */
051: public void build(final BuildContext context,
052: final BuildUtils utils, final RuleConditionElement rce) {
053:
054: final Pattern pattern = (Pattern) rce;
055:
056: this .attachPattern(context, utils, pattern);
057:
058: }
059:
060: private void attachPattern(final BuildContext context,
061: final BuildUtils utils, final Pattern pattern)
062: throws InvalidPatternException {
063:
064: // Set pattern offset to the appropriate value
065: pattern.setOffset(context.getCurrentPatternOffset());
066:
067: context.incrementCurrentPatternOffset();
068:
069: final List alphaConstraints = new LinkedList();
070: final List betaConstraints = new LinkedList();
071:
072: this .createConstraints(context, utils, pattern,
073: alphaConstraints, betaConstraints);
074:
075: // Create BetaConstraints object
076: context.setBetaconstraints(betaConstraints);
077:
078: if (pattern.getSource() == null) {
079: // pattern is selected from working memory, so
080: // Attach alpha nodes
081: attachAlphaNodes(context, utils, pattern, alphaConstraints);
082:
083: } else {
084: context.setAlphaConstraints(alphaConstraints);
085:
086: PatternSource source = pattern.getSource();
087:
088: ReteooComponentBuilder builder = utils
089: .getBuilderFor(source);
090:
091: builder.build(context, utils, source);
092: }
093: }
094:
095: private void createConstraints(BuildContext context,
096: BuildUtils utils, Pattern pattern, List alphaConstraints,
097: List betaConstraints) {
098:
099: final List constraints = pattern.getConstraints();
100:
101: // check if cross products for identity patterns should be disabled
102: checkRemoveIdentities(context, pattern, betaConstraints);
103:
104: for (final Iterator it = constraints.iterator(); it.hasNext();) {
105: final Object object = it.next();
106: // Check if its a declaration
107: if (object instanceof Declaration) {
108: // nothing to be done
109: continue;
110: }
111:
112: final Constraint constraint = (Constraint) object;
113: final Declaration[] declarations = constraint
114: .getRequiredDeclarations();
115:
116: boolean isAlphaConstraint = true;
117: for (int i = 0; isAlphaConstraint
118: && i < declarations.length; i++) {
119: if (!declarations[i].isGlobal()
120: && declarations[i].getPattern() != pattern) {
121: isAlphaConstraint = false;
122: }
123: }
124:
125: if (isAlphaConstraint) {
126: alphaConstraints.add(constraint);
127: } else {
128: utils.checkUnboundDeclarations(context, constraint
129: .getRequiredDeclarations());
130: betaConstraints.add(constraint);
131: }
132: }
133: }
134:
135: public static ObjectTypeNode attachObjectTypeNode(Rete rete,
136: ObjectType objectType) {
137: ReteooRuleBase ruleBase = (ReteooRuleBase) rete.getRuleBase();
138: ReteooBuilder builder = ruleBase.getReteooBuilder();
139:
140: ObjectTypeNode otn = new ObjectTypeNode(builder
141: .getIdGenerator().getNextId(), objectType, rete,
142: ruleBase.getConfiguration()
143: .getAlphaNodeHashingThreshold());
144:
145: InternalWorkingMemory[] wms = ruleBase.getWorkingMemories();
146: otn.attach(wms);
147:
148: return otn;
149: }
150:
151: public void attachAlphaNodes(final BuildContext context,
152: final BuildUtils utils, final Pattern pattern,
153: List alphaConstraints) throws InvalidPatternException {
154:
155: context.setObjectSource((ObjectSource) utils.attachNode(
156: context, new ObjectTypeNode(context.getNextId(),
157: pattern.getObjectType(), context.getRuleBase()
158: .getRete(), context.getRuleBase()
159: .getConfiguration()
160: .getAlphaNodeHashingThreshold())));
161:
162: for (final Iterator it = alphaConstraints.iterator(); it
163: .hasNext();) {
164: final AlphaNodeFieldConstraint constraint = (AlphaNodeFieldConstraint) it
165: .next();
166:
167: context.setObjectSource((ObjectSource) utils.attachNode(
168: context, new AlphaNode(context.getNextId(),
169: (AlphaNodeFieldConstraint) constraint,
170: context.getObjectSource(), context
171: .getRuleBase().getConfiguration()
172: .isAlphaMemory(), context
173: .getRuleBase().getConfiguration()
174: .getAlphaNodeHashingThreshold())));
175: }
176:
177: }
178:
179: /**
180: * @param context
181: * @param pattern
182: * @param betaConstraints
183: */
184: private void checkRemoveIdentities(final BuildContext context,
185: final Pattern pattern, final List betaConstraints) {
186: if (context.getRuleBase().getConfiguration()
187: .isRemoveIdentities()
188: && pattern.getObjectType().getClass() == ClassObjectType.class) {
189: List patterns = null;
190: // Check if this object type exists before
191: // If it does we need stop instance equals cross product
192: final Class this Class = ((ClassObjectType) pattern
193: .getObjectType()).getClassType();
194: for (final Iterator it = context.getObjectType().iterator(); it
195: .hasNext();) {
196: final Pattern previousPattern = (Pattern) it.next();
197: final Class previousClass = ((ClassObjectType) previousPattern
198: .getObjectType()).getClassType();
199: if (this Class.isAssignableFrom(previousClass)) {
200: betaConstraints
201: .add(new InstanceNotEqualsConstraint(
202: previousPattern));
203: }
204: }
205:
206: // Must be added after the checking, otherwise it matches against itself
207: context.getObjectType().add(pattern);
208: }
209: }
210:
211: /**
212: * @inheritDoc
213: */
214: public boolean requiresLeftActivation(final BuildUtils utils,
215: final RuleConditionElement rce) {
216: return ((Pattern) rce).getSource() != null;
217: }
218: }
|