/** * Copyright 2010 JBoss Inc * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.drools.reteoo.builder; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import java.util.Stack; import org.drools.common.BaseNode; import org.drools.common.InternalRuleBase; import org.drools.common.InternalWorkingMemory; import org.drools.common.RuleBasePartitionId; import org.drools.reteoo.LeftTupleSource; import org.drools.reteoo.ObjectSource; import org.drools.reteoo.ReteooBuilder; import org.drools.rule.Behavior; import org.drools.rule.EntryPoint; import org.drools.rule.Query; import org.drools.rule.Rule; import org.drools.rule.RuleConditionElement; import org.drools.spi.RuleComponent; import org.drools.time.TemporalDependencyMatrix; /** * A build context for Reteoo Builder * * @author etirelli */ public class BuildContext { // tuple source to attach next node to private LeftTupleSource tupleSource; // object source to attach next node to private ObjectSource objectSource; // object type cache to check for cross products private LinkedList objectType; // offset of the pattern private int currentPatternOffset; // rule base to add rules to private InternalRuleBase rulebase; // rule being added at this moment private Rule rule; // the rule component being processed at the moment private Stack<RuleComponent> ruleComponent; // working memories attached to the given rulebase private InternalWorkingMemory[] workingMemories; // id generator private ReteooBuilder.IdGenerator idGenerator; // a build stack to track nested elements private LinkedList<RuleConditionElement> buildstack; // beta constraints from the last pattern attached private List betaconstraints; // alpha constraints from the last pattern attached private List alphaConstraints; // behaviors from the last pattern attached private List<Behavior> behaviors; // the current entry point private EntryPoint currentEntryPoint; private boolean tupleMemoryEnabled; private boolean objectTypeNodeMemoryEnabled; private boolean terminalNodeMemoryEnabled; /** This one is slightly different as alphaMemory can be adaptive, only turning on for new rule attachments */ private boolean alphaNodeMemoryAllowed; private boolean query; /** Stores the list of nodes being added that require partitionIds */ private List<BaseNode> nodes; /** Stores the id of the partition this rule will be added to */ private RuleBasePartitionId partitionId; /** the calculate temporal distance matrix */ private TemporalDependencyMatrix temporal; public BuildContext(final InternalRuleBase rulebase, final ReteooBuilder.IdGenerator idGenerator) { this.rulebase = rulebase; this.idGenerator = idGenerator; this.workingMemories = null; this.objectType = null; this.buildstack = null; this.tupleSource = null; this.objectSource = null; this.currentPatternOffset = 0; this.tupleMemoryEnabled = true; this.objectTypeNodeMemoryEnabled = true; this.currentEntryPoint = EntryPoint.DEFAULT; this.nodes = new LinkedList<BaseNode>(); this.partitionId = null; this.ruleComponent = new Stack<RuleComponent>(); } /** * @return the currentPatternOffset */ public int getCurrentPatternOffset() { return this.currentPatternOffset; } /** * @param currentPatternOffset the currentPatternOffset to set */ public void setCurrentPatternOffset(final int currentPatternIndex) { this.currentPatternOffset = currentPatternIndex; this.syncObjectTypesWithPatternOffset(); } public void syncObjectTypesWithPatternOffset() { if ( this.objectType == null ) { this.objectType = new LinkedList(); } while ( this.objectType.size() > this.currentPatternOffset ) { this.objectType.removeLast(); } } /** * @return the objectSource */ public ObjectSource getObjectSource() { return this.objectSource; } /** * @param objectSource the objectSource to set */ public void setObjectSource(final ObjectSource objectSource) { this.objectSource = objectSource; } /** * @return the objectType */ public LinkedList getObjectType() { if ( this.objectType == null ) { this.objectType = new LinkedList(); } return this.objectType; } /** * @param objectType the objectType to set */ public void setObjectType(final LinkedList objectType) { if ( this.objectType == null ) { this.objectType = new LinkedList(); } this.objectType = objectType; } /** * @return the tupleSource */ public LeftTupleSource getTupleSource() { return this.tupleSource; } /** * @param tupleSource the tupleSource to set */ public void setTupleSource(final LeftTupleSource tupleSource) { this.tupleSource = tupleSource; } public void incrementCurrentPatternOffset() { this.currentPatternOffset++; } public void decrementCurrentPatternOffset() { this.currentPatternOffset--; this.syncObjectTypesWithPatternOffset(); } /** * Returns context rulebase * @return */ public InternalRuleBase getRuleBase() { return this.rulebase; } /** * Return the array of working memories associated with the given * rulebase. * * @return */ public InternalWorkingMemory[] getWorkingMemories() { if ( this.workingMemories == null ) { this.workingMemories = this.rulebase.getWorkingMemories(); } return this.workingMemories; } /** * Returns an Id for the next node * @return */ public int getNextId() { return this.idGenerator.getNextId(); } /** * Method used to undo previous id assignment */ public void releaseId(int id) { this.idGenerator.releaseId( id ); } /** * Adds the rce to the build stack * @param rce */ public void push(final RuleConditionElement rce) { if ( this.buildstack == null ) { this.buildstack = new LinkedList<RuleConditionElement>(); } this.buildstack.addLast( rce ); } /** * Removes the top stack element * @return */ public RuleConditionElement pop() { if ( this.buildstack == null ) { this.buildstack = new LinkedList<RuleConditionElement>(); } return this.buildstack.removeLast(); } /** * Returns the top stack element without removing it * @return */ public RuleConditionElement peek() { if ( this.buildstack == null ) { this.buildstack = new LinkedList<RuleConditionElement>(); } return this.buildstack.getLast(); } /** * Returns a list iterator to iterate over the stacked elements * @return */ public ListIterator<RuleConditionElement> stackIterator() { if ( this.buildstack == null ) { this.buildstack = new LinkedList<RuleConditionElement>(); } return this.buildstack.listIterator( this.buildstack.size() ); } /** * @return the betaconstraints */ public List getBetaconstraints() { return this.betaconstraints; } /** * @param betaconstraints the betaconstraints to set */ public void setBetaconstraints(final List betaconstraints) { this.betaconstraints = betaconstraints; } public int getNextSequence(String groupName) { //List list = new ArrayList(); Integer seq = (Integer) this.rulebase.getAgendaGroupRuleTotals().get( groupName ); if ( seq == null ) { seq = new Integer( 0 ); } Integer newSeq = new Integer( seq.intValue() + 1 ); this.rulebase.getAgendaGroupRuleTotals().put( groupName, newSeq ); return newSeq.intValue(); } /** * @return */ public List getAlphaConstraints() { return alphaConstraints; } public void setAlphaConstraints(List alphaConstraints) { this.alphaConstraints = alphaConstraints; } public boolean isTupleMemoryEnabled() { return this.tupleMemoryEnabled; } public void setTupleMemoryEnabled(boolean hasLeftMemory) { this.tupleMemoryEnabled = hasLeftMemory; } public boolean isObjectTypeNodeMemoryEnabled() { return objectTypeNodeMemoryEnabled; } public void setObjectTypeNodeMemoryEnabled(boolean hasObjectTypeMemory) { this.objectTypeNodeMemoryEnabled = hasObjectTypeMemory; } public boolean isTerminalNodeMemoryEnabled() { return terminalNodeMemoryEnabled; } public void setTerminalNodeMemoryEnabled(boolean hasTerminalNodeMemory) { this.terminalNodeMemoryEnabled = hasTerminalNodeMemory; } public void setAlphaNodeMemoryAllowed(boolean alphaMemoryAllowed) { this.alphaNodeMemoryAllowed = alphaMemoryAllowed; } public boolean isAlphaMemoryAllowed() { return this.alphaNodeMemoryAllowed; } public boolean isQuery() { return query; } /** * @return the currentEntryPoint */ public EntryPoint getCurrentEntryPoint() { return currentEntryPoint; } /** * @param currentEntryPoint the currentEntryPoint to set */ public void setCurrentEntryPoint(EntryPoint currentEntryPoint) { this.currentEntryPoint = currentEntryPoint; } /** * @return the behaviours */ public List<Behavior> getBehaviors() { return behaviors; } /** * @param behaviors the behaviours to set */ public void setBehaviors(List<Behavior> behaviors) { this.behaviors = behaviors; } /** * @return the nodes */ public List<BaseNode> getNodes() { return nodes; } /** * @param nodes the nodes to set */ public void setNodes(List<BaseNode> nodes) { this.nodes = nodes; } /** * @return the partitionId */ public RuleBasePartitionId getPartitionId() { return partitionId; } /** * @param partitionId the partitionId to set */ public void setPartitionId(RuleBasePartitionId partitionId) { this.partitionId = partitionId; } public void setTemporalDistance(TemporalDependencyMatrix temporal) { this.temporal = temporal; } public TemporalDependencyMatrix getTemporalDistance() { return this.temporal; } public LinkedList<RuleConditionElement> getBuildStack() { return this.buildstack; } public Rule getRule() { return rule; } public void setRule(Rule rule) { this.rule = rule; if ( rule instanceof Query) { this.query = true; } } /** * Removes the top element from the rule component stack. * The rule component stack is used to add trackability to * the ReteOO nodes so that they can be linked to the rule * components that originated them. * * @return */ public RuleComponent popRuleComponent() { return this.ruleComponent.pop(); } /** * Peeks at the top element from the rule component stack. * The rule component stack is used to add trackability to * the ReteOO nodes so that they can be linked to the rule * components that originated them. * * @return */ public RuleComponent peekRuleComponent() { return this.ruleComponent.isEmpty() ? null : this.ruleComponent.peek(); } /** * Adds the ruleComponent to the top of the rule component stack. * The rule component stack is used to add trackability to * the ReteOO nodes so that they can be linked to the rule * components that originated them. * * @return */ public void pushRuleComponent( RuleComponent ruleComponent ) { this.ruleComponent.push( ruleComponent ); } }