001: package org.drools.ruleflow.instance.impl;
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.util.ArrayList;
020: import java.util.Collection;
021: import java.util.Collections;
022: import java.util.Iterator;
023: import java.util.List;
024:
025: import org.drools.Agenda;
026: import org.drools.WorkingMemory;
027: import org.drools.common.EventSupport;
028: import org.drools.common.InternalWorkingMemory;
029: import org.drools.event.ActivationCancelledEvent;
030: import org.drools.event.ActivationCreatedEvent;
031: import org.drools.event.AfterActivationFiredEvent;
032: import org.drools.event.AgendaEventListener;
033: import org.drools.event.AgendaGroupPoppedEvent;
034: import org.drools.event.AgendaGroupPushedEvent;
035: import org.drools.event.BeforeActivationFiredEvent;
036: import org.drools.event.RuleFlowCompletedEvent;
037: import org.drools.event.RuleFlowEventListener;
038: import org.drools.event.RuleFlowGroupActivatedEvent;
039: import org.drools.event.RuleFlowGroupDeactivatedEvent;
040: import org.drools.event.RuleFlowStartedEvent;
041: import org.drools.ruleflow.common.instance.impl.ProcessInstanceImpl;
042: import org.drools.ruleflow.core.ActionNode;
043: import org.drools.ruleflow.core.EndNode;
044: import org.drools.ruleflow.core.Join;
045: import org.drools.ruleflow.core.MilestoneNode;
046: import org.drools.ruleflow.core.Node;
047: import org.drools.ruleflow.core.RuleFlowProcess;
048: import org.drools.ruleflow.core.RuleSetNode;
049: import org.drools.ruleflow.core.Split;
050: import org.drools.ruleflow.core.StartNode;
051: import org.drools.ruleflow.core.SubFlowNode;
052: import org.drools.ruleflow.instance.RuleFlowNodeInstance;
053: import org.drools.ruleflow.instance.RuleFlowProcessInstance;
054:
055: /**
056: * Default implementation of a RuleFlow process instance.
057: *
058: * @author <a href="mailto:kris_verlaenen@hotmail.com">Kris Verlaenen</a>
059: */
060: public class RuleFlowProcessInstanceImpl extends ProcessInstanceImpl
061: implements RuleFlowProcessInstance, AgendaEventListener,
062: RuleFlowEventListener {
063:
064: private static final long serialVersionUID = 400L;
065:
066: private InternalWorkingMemory workingMemory;
067: private final List nodeInstances = new ArrayList();
068:
069: public RuleFlowProcess getRuleFlowProcess() {
070: return (RuleFlowProcess) getProcess();
071: }
072:
073: public void addNodeInstance(final RuleFlowNodeInstance nodeInstance) {
074: this .nodeInstances.add(nodeInstance);
075: nodeInstance.setProcessInstance(this );
076: }
077:
078: public void removeNodeInstance(
079: final RuleFlowNodeInstance nodeInstance) {
080: this .nodeInstances.remove(nodeInstance);
081: }
082:
083: public Collection getNodeInstances() {
084: return Collections.unmodifiableCollection(new ArrayList(
085: this .nodeInstances));
086: }
087:
088: public RuleFlowNodeInstance getFirstNodeInstance(final long nodeId) {
089: for (final Iterator iterator = this .nodeInstances.iterator(); iterator
090: .hasNext();) {
091: final RuleFlowNodeInstance nodeInstance = (RuleFlowNodeInstance) iterator
092: .next();
093: if (nodeInstance.getNodeId() == nodeId) {
094: return nodeInstance;
095: }
096: }
097: return null;
098: }
099:
100: public Agenda getAgenda() {
101: if (this .workingMemory == null) {
102: return null;
103: }
104: return this .workingMemory.getAgenda();
105: }
106:
107: public void setWorkingMemory(
108: final InternalWorkingMemory workingMemory) {
109: if (this .workingMemory != null) {
110: throw new IllegalArgumentException(
111: "A working memory can only be set once.");
112: }
113: this .workingMemory = workingMemory;
114: workingMemory.addEventListener((AgendaEventListener) this );
115: workingMemory.addEventListener((RuleFlowEventListener) this );
116: }
117:
118: public WorkingMemory getWorkingMemory() {
119: return this .workingMemory;
120: }
121:
122: public RuleFlowNodeInstance getNodeInstance(final Node node) {
123: if (node instanceof RuleSetNode) {
124: final RuleFlowNodeInstance result = (RuleFlowNodeInstance) getAgenda()
125: .getRuleFlowGroup(
126: ((RuleSetNode) node).getRuleFlowGroup());
127: result.setNodeId(node.getId());
128: addNodeInstance(result);
129: return result;
130: } else if (node instanceof Split) {
131: RuleFlowNodeInstance result = getFirstNodeInstance(node
132: .getId());
133: if (result == null) {
134: result = new RuleFlowSplitInstanceImpl();
135: result.setNodeId(node.getId());
136: addNodeInstance(result);
137: }
138: return result;
139: } else if (node instanceof Join) {
140: RuleFlowNodeInstance result = getFirstNodeInstance(node
141: .getId());
142: if (result == null) {
143: result = new RuleFlowJoinInstanceImpl();
144: result.setNodeId(node.getId());
145: addNodeInstance(result);
146: }
147: return result;
148: } else if (node instanceof StartNode) {
149: final RuleFlowNodeInstance result = new StartNodeInstanceImpl();
150: result.setNodeId(node.getId());
151: addNodeInstance(result);
152: return result;
153: } else if (node instanceof EndNode) {
154: final RuleFlowNodeInstance result = new EndNodeInstanceImpl();
155: result.setNodeId(node.getId());
156: addNodeInstance(result);
157: return result;
158: } else if (node instanceof MilestoneNode) {
159: final RuleFlowNodeInstance result = new MilestoneNodeInstanceImpl();
160: result.setNodeId(node.getId());
161: addNodeInstance(result);
162: return result;
163: } else if (node instanceof SubFlowNode) {
164: final RuleFlowNodeInstance result = new SubFlowNodeInstanceImpl();
165: result.setNodeId(node.getId());
166: addNodeInstance(result);
167: return result;
168: } else if (node instanceof ActionNode) {
169: final RuleFlowNodeInstance result = new ActionNodeInstanceImpl();
170: result.setNodeId(node.getId());
171: addNodeInstance(result);
172: return result;
173: }
174: throw new IllegalArgumentException("Illegal node type: "
175: + node.getClass());
176: }
177:
178: public void start() {
179: if (getState() != ProcessInstanceImpl.STATE_PENDING) {
180: throw new IllegalArgumentException(
181: "A process instance can only be started once");
182: }
183: setState(ProcessInstanceImpl.STATE_ACTIVE);
184: getNodeInstance(getRuleFlowProcess().getStart()).trigger(null);
185: }
186:
187: public void setState(final int state) {
188: super .setState(state);
189: if (state == ProcessInstanceImpl.STATE_COMPLETED) {
190: // deactivate all node instances of this process instance
191: while (!nodeInstances.isEmpty()) {
192: RuleFlowNodeInstance nodeInstance = (RuleFlowNodeInstance) nodeInstances
193: .get(0);
194: nodeInstance.cancel();
195: }
196: workingMemory
197: .removeEventListener((AgendaEventListener) this );
198: workingMemory
199: .removeEventListener((RuleFlowEventListener) this );
200: ((EventSupport) this .workingMemory)
201: .getRuleFlowEventSupport()
202: .fireRuleFlowProcessCompleted(this ,
203: this .workingMemory);
204: }
205: }
206:
207: public String toString() {
208: final StringBuffer sb = new StringBuffer(
209: "RuleFlowProcessInstance");
210: sb.append(getId());
211: sb.append(" [processId=");
212: sb.append(getProcess().getId());
213: sb.append(",state=");
214: sb.append(getState());
215: sb.append("]");
216: return sb.toString();
217: }
218:
219: public void activationCreated(ActivationCreatedEvent event,
220: WorkingMemory workingMemory) {
221: // TODO group all milestone related code in milestone instance impl?
222: // check whether this activation is from the DROOLS_SYSTEM agenda group
223: String ruleFlowGroup = event.getActivation().getRule()
224: .getRuleFlowGroup();
225: if ("DROOLS_SYSTEM".equals(ruleFlowGroup)) {
226: // new activations of the rule associate with a milestone node
227: // trigger node instances of that milestone node
228: String ruleName = event.getActivation().getRule().getName();
229: for (Iterator iterator = getNodeInstances().iterator(); iterator
230: .hasNext();) {
231: RuleFlowNodeInstance nodeInstance = (RuleFlowNodeInstance) iterator
232: .next();
233: if (nodeInstance instanceof MilestoneNodeInstanceImpl) {
234: String milestoneName = "RuleFlow-"
235: + getProcess().getId() + "-"
236: + nodeInstance.getNodeId();
237: if (milestoneName.equals(ruleName)) {
238: ((MilestoneNodeInstanceImpl) nodeInstance)
239: .triggerCompleted();
240: }
241: }
242:
243: }
244: }
245: }
246:
247: public void activationCancelled(ActivationCancelledEvent event,
248: WorkingMemory workingMemory) {
249: // Do nothing
250: }
251:
252: public void afterActivationFired(AfterActivationFiredEvent event,
253: WorkingMemory workingMemory) {
254: // Do nothing
255: }
256:
257: public void agendaGroupPopped(AgendaGroupPoppedEvent event,
258: WorkingMemory workingMemory) {
259: // Do nothing
260: }
261:
262: public void agendaGroupPushed(AgendaGroupPushedEvent event,
263: WorkingMemory workingMemory) {
264: // Do nothing
265: }
266:
267: public void beforeActivationFired(BeforeActivationFiredEvent event,
268: WorkingMemory workingMemory) {
269: // Do nothing
270: }
271:
272: public void ruleFlowGroupActivated(
273: RuleFlowGroupActivatedEvent event,
274: WorkingMemory workingMemory) {
275: // Do nothing
276: }
277:
278: public void ruleFlowGroupDeactivated(
279: RuleFlowGroupDeactivatedEvent event,
280: WorkingMemory workingMemory) {
281: // Do nothing
282: }
283:
284: public void ruleFlowStarted(RuleFlowStartedEvent event,
285: WorkingMemory workingMemory) {
286: // Do nothing
287: }
288:
289: public void ruleFlowCompleted(RuleFlowCompletedEvent event,
290: WorkingMemory workingMemory) {
291: // TODO group all subflow related code in subflow instance impl?
292: for (Iterator iterator = getNodeInstances().iterator(); iterator
293: .hasNext();) {
294: RuleFlowNodeInstance nodeInstance = (RuleFlowNodeInstance) iterator
295: .next();
296: if (nodeInstance instanceof SubFlowNodeInstanceImpl) {
297: SubFlowNodeInstanceImpl subFlowInstance = (SubFlowNodeInstanceImpl) nodeInstance;
298: if (event.getRuleFlowProcessInstance().getId() == subFlowInstance
299: .getProcessInstanceId()) {
300: subFlowInstance.triggerCompleted();
301: }
302: }
303:
304: }
305: }
306: }
|