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 org.drools.ruleflow.instance.RuleFlowNodeInstance;
020: import org.drools.ruleflow.instance.impl.RuleFlowSequenceNodeInstanceImpl;
021: import org.drools.spi.Activation;
022: import org.drools.util.Iterator;
023: import org.drools.util.LinkedList;
024: import org.drools.util.LinkedList.LinkedListIterator;
025:
026: /**
027: * Implementation of a <code>RuleFlowGroup</code> that collects activations
028: * of rules of this ruleflow-group.
029: * If this group is activated, all its activations are added to the agenda.
030: * As long as this group is active, its activations are added to the agenda.
031: * Deactivating the group removes all its activations from the agenda and
032: * collects them until it is activated again.
033: * By default, <code>RuleFlowGroups</code> are automatically deactivated when there are no more
034: * activations in the <code>RuleFlowGroup</code>. However, this can be configured.
035: *
036: * @author <a href="mailto:mark.proctor@jboss.com">Mark Proctor</a>
037: * @author <a href="mailto:kris_verlaenen@hotmail.com">Kris Verlaenen</a>
038: *
039: */
040: public class RuleFlowGroupImpl extends RuleFlowSequenceNodeInstanceImpl
041: implements InternalRuleFlowGroup {
042:
043: private static final long serialVersionUID = 400L;
044:
045: private InternalWorkingMemory workingMemory;
046: private final String name;
047: private boolean active = false;
048: private final LinkedList list;
049: private boolean autoDeactivate = true;
050:
051: /**
052: * Construct a <code>RuleFlowGroupImpl</code> with the given name.
053: *
054: * @param name
055: * The RuleFlowGroup name.
056: */
057: public RuleFlowGroupImpl(final String name) {
058: this .name = name;
059: this .list = new LinkedList();
060: }
061:
062: public String getName() {
063: return this .name;
064: }
065:
066: public void setWorkingMemory(InternalWorkingMemory workingMemory) {
067: this .workingMemory = workingMemory;
068: }
069:
070: public InternalWorkingMemory getWorkingMemory() {
071: return this .workingMemory;
072: }
073:
074: public void setActive(final boolean active) {
075: if (this .active == active) {
076: return;
077: }
078: this .active = active;
079: if (active) {
080: if (this .list.isEmpty()) {
081: if (this .autoDeactivate) {
082: // if the list of activations is empty and
083: // auto-deactivate is on, deactivate this group
084: WorkingMemoryAction action = new DeactivateCallback(
085: this );
086: this .workingMemory.queueWorkingMemoryAction(action);
087: }
088: } else {
089: triggerActivations();
090: }
091: ((EventSupport) this .workingMemory)
092: .getRuleFlowEventSupport()
093: .fireRuleFlowGroupActivated(this ,
094: this .workingMemory);
095: } else {
096: final Iterator it = this .list.iterator();
097: for (RuleFlowGroupNode node = (RuleFlowGroupNode) it.next(); node != null; node = (RuleFlowGroupNode) it
098: .next()) {
099: final Activation activation = node.getActivation();
100: activation.remove();
101: if (activation.getActivationGroupNode() != null) {
102: activation.getActivationGroupNode()
103: .getActivationGroup().removeActivation(
104: activation);
105: }
106: }
107: ((EventSupport) this .workingMemory)
108: .getRuleFlowEventSupport()
109: .fireRuleFlowGroupDeactivated(this ,
110: this .workingMemory);
111: }
112: }
113:
114: public boolean isActive() {
115: return this .active;
116: }
117:
118: public boolean isAutoDeactivate() {
119: return this .autoDeactivate;
120: }
121:
122: public void setAutoDeactivate(final boolean autoDeactivate) {
123: this .autoDeactivate = autoDeactivate;
124: if (autoDeactivate && this .active && this .list.isEmpty()) {
125: this .active = false;
126: }
127: }
128:
129: private void triggerActivations() {
130: // iterate all activations adding them to their AgendaGroups
131: final Iterator it = this .list.iterator();
132: for (RuleFlowGroupNode node = (RuleFlowGroupNode) it.next(); node != null; node = (RuleFlowGroupNode) it
133: .next()) {
134: final Activation activation = node.getActivation();
135: ((BinaryHeapQueueAgendaGroup) activation.getAgendaGroup())
136: .add(activation);
137: }
138: }
139:
140: public void clear() {
141: this .list.clear();
142: }
143:
144: public int size() {
145: return this .list.size();
146: }
147:
148: public void addActivation(final Activation activation) {
149: final RuleFlowGroupNode node = new RuleFlowGroupNode(
150: activation, this );
151: activation.setRuleFlowGroupNode(node);
152: this .list.add(node);
153:
154: if (this .active) {
155: ((InternalAgendaGroup) activation.getAgendaGroup())
156: .add(activation);
157: }
158: }
159:
160: public void removeActivation(final Activation activation) {
161: final RuleFlowGroupNode node = activation
162: .getRuleFlowGroupNode();
163: this .list.remove(node);
164: activation.setActivationGroupNode(null);
165: if (this .active && this .autoDeactivate) {
166: if (this .list.isEmpty()) {
167: // deactivate callback
168: WorkingMemoryAction action = new DeactivateCallback(
169: this );
170: this .workingMemory.queueWorkingMemoryAction(action);
171: }
172: }
173: }
174:
175: public boolean isEmpty() {
176: return this .list.isEmpty();
177: }
178:
179: public java.util.Iterator iterator() {
180: return this .list.javaUtilIterator();
181: }
182:
183: public String toString() {
184: return "RuleFlowGroup '" + this .name + "'";
185: }
186:
187: public boolean equal(final Object object) {
188: if ((object == null) || !(object instanceof RuleFlowGroupImpl)) {
189: return false;
190: }
191:
192: if (((RuleFlowGroupImpl) object).name.equals(this .name)) {
193: return true;
194: }
195:
196: return false;
197: }
198:
199: public int hashCode() {
200: return this .name.hashCode();
201: }
202:
203: public void trigger(final RuleFlowNodeInstance parent) {
204: setActive(true);
205: }
206:
207: public static class DeactivateCallback implements
208: WorkingMemoryAction {
209: private final InternalRuleFlowGroup ruleFlowGroup;
210:
211: public DeactivateCallback(InternalRuleFlowGroup ruleFlowGroup) {
212: this .ruleFlowGroup = ruleFlowGroup;
213: }
214:
215: public void execute(InternalWorkingMemory workingMemory) {
216: // check whether ruleflow group is still empty first
217: if (this .ruleFlowGroup.isEmpty()) {
218: // deactivate ruleflow group
219: this .ruleFlowGroup.setActive(false);
220: // only trigger next node if this RuleFlowGroup was
221: // triggered from inside a process instance
222: if (this.ruleFlowGroup.getProcessInstance() != null) {
223: this.ruleFlowGroup.triggerCompleted();
224: }
225: }
226: }
227: }
228: }
|