[jbpm-commits] JBoss JBPM SVN: r2457 - in projects/spec/trunk/modules: cts and 4 other directories.
do-not-reply at jboss.org
do-not-reply at jboss.org
Wed Oct 1 09:18:18 EDT 2008
Author: thomas.diesler at jboss.com
Date: 2008-10-01 09:18:18 -0400 (Wed, 01 Oct 2008)
New Revision: 2457
Added:
projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ComplexGatewayImpl.java
projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ExclusiveGatewayImpl.java
projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/InclusiveGatewayImpl.java
projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ParallelGatewayImpl.java
Modified:
projects/spec/trunk/modules/api/src/main/java/org/jbpm/api/model/builder/ProcessBuilder.java
projects/spec/trunk/modules/cts/pom.xml
projects/spec/trunk/modules/cts/src/test/java/org/jbpm/test/cts/gateway/exclusive/ExclusiveGatewayMergeTest.java
projects/spec/trunk/modules/cts/src/test/java/org/jbpm/test/cts/gateway/exclusive/ExclusiveGatewaySplitTest.java
projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ExpressionImpl.java
projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/GatewayImpl.java
projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/NodeImpl.java
projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/builder/GatewayBuilderImpl.java
projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/builder/ProcessBuilderImpl.java
projects/spec/trunk/modules/impl/src/main/resources/jbpm-cfg-beans.xml
Log:
Gateway split tests - pass
Modified: projects/spec/trunk/modules/api/src/main/java/org/jbpm/api/model/builder/ProcessBuilder.java
===================================================================
--- projects/spec/trunk/modules/api/src/main/java/org/jbpm/api/model/builder/ProcessBuilder.java 2008-10-01 03:42:57 UTC (rev 2456)
+++ projects/spec/trunk/modules/api/src/main/java/org/jbpm/api/model/builder/ProcessBuilder.java 2008-10-01 13:18:18 UTC (rev 2457)
@@ -24,7 +24,9 @@
//$Id$
import org.jbpm.api.model.Message;
+import org.jbpm.api.model.Node;
import org.jbpm.api.model.Process;
+import org.jbpm.api.model.Property;
import org.jbpm.api.model.Assignment.AssignTime;
import org.jbpm.api.model.Event.EventDetailType;
import org.jbpm.api.model.Expression.ExpressionLanguage;
Modified: projects/spec/trunk/modules/cts/pom.xml
===================================================================
--- projects/spec/trunk/modules/cts/pom.xml 2008-10-01 03:42:57 UTC (rev 2456)
+++ projects/spec/trunk/modules/cts/pom.xml 2008-10-01 13:18:18 UTC (rev 2457)
@@ -71,15 +71,10 @@
<configuration>
<excludes>
<exclude>org/jbpm/test/cts/gateway/exclusive/ExclusiveGatewayMergeTest.java</exclude>
- <exclude>org/jbpm/test/cts/gateway/exclusive/ExclusiveGatewaySplitTest.java</exclude>
<exclude>org/jbpm/test/cts/gateway/inclusive/InclusiveGatewayMergeTest.java</exclude>
- <exclude>org/jbpm/test/cts/gateway/inclusive/InclusiveGatewaySplitTest.java</exclude>
<exclude>org/jbpm/test/cts/gateway/parallel/ParallelGatewayMergeTest.java</exclude>
- <exclude>org/jbpm/test/cts/gateway/parallel/ParallelGatewaySplitTest.java</exclude>
<exclude>org/jbpm/test/cts/node/NodeInputSetTest.java</exclude>
<exclude>org/jbpm/test/cts/node/NodeOutputSetTest.java</exclude>
- <exclude>org/jbpm/test/pattern/control/exclusivechoice/ExclusiveChoiceTest.java</exclude>
- <exclude>org/jbpm/test/pattern/control/multichoice/MultiChoiceTest.java</exclude>
<exclude>org/jbpm/test/pattern/control/parallelsplit/ParallelSplitTest.java</exclude>
<exclude>org/jbpm/test/pattern/control/simplemerge/SimpleMergeTest.java</exclude>
<exclude>org/jbpm/test/pattern/control/synchronization/SynchronizationTest.java</exclude>
Modified: projects/spec/trunk/modules/cts/src/test/java/org/jbpm/test/cts/gateway/exclusive/ExclusiveGatewayMergeTest.java
===================================================================
--- projects/spec/trunk/modules/cts/src/test/java/org/jbpm/test/cts/gateway/exclusive/ExclusiveGatewayMergeTest.java 2008-10-01 03:42:57 UTC (rev 2456)
+++ projects/spec/trunk/modules/cts/src/test/java/org/jbpm/test/cts/gateway/exclusive/ExclusiveGatewayMergeTest.java 2008-10-01 13:18:18 UTC (rev 2457)
@@ -29,7 +29,9 @@
import org.jbpm.api.model.Message;
import org.jbpm.api.model.Process;
import org.jbpm.api.model.Signal;
+import org.jbpm.api.model.Assignment.AssignTime;
import org.jbpm.api.model.Event.EventDetailType;
+import org.jbpm.api.model.Expression.ExpressionLanguage;
import org.jbpm.api.model.Gateway.GatewayType;
import org.jbpm.api.model.Signal.SignalType;
import org.jbpm.api.model.builder.EventBuilder;
@@ -168,12 +170,12 @@
EventBuilder eventBuilder = procBuilder.addProcess(getName()).addStartEvent("StartA", EventDetailType.Signal);
eventBuilder.addSignalRef(SignalType.SYSTEM_START_TRIGGER, "A");
TaskBuilder taskBuilder = procBuilder.addSequenceFlow("TaskA").addTask("TaskA");
- //taskBuilder.addAssignment(AssignTime.Start, ExpressionLanguage.MVEL, "'TaskA'", "taskValue");
+ taskBuilder.addNodeAssignment(AssignTime.Start, ExpressionLanguage.MVEL, "'TaskA'", "taskValue");
taskBuilder.addSequenceFlow("Merge");
eventBuilder = procBuilder.addStartEvent("StartB", EventDetailType.Signal);
eventBuilder.addSignalRef(SignalType.SYSTEM_START_TRIGGER, "B");
taskBuilder = procBuilder.addSequenceFlow("TaskB").addTask("TaskB");
- //taskBuilder.addAssignment(AssignTime.Start, ExpressionLanguage.MVEL, "'TaskB'", "taskValue");
+ taskBuilder.addNodeAssignment(AssignTime.Start, ExpressionLanguage.MVEL, "'TaskB'", "taskValue");
taskBuilder.addSequenceFlow("Merge");
procBuilder.addGateway("Merge", GatewayType.Exclusive).addSequenceFlow("End");
procBuilder.addEndEvent("End", EventDetailType.Message).addMessageRef("EndMessage");
Modified: projects/spec/trunk/modules/cts/src/test/java/org/jbpm/test/cts/gateway/exclusive/ExclusiveGatewaySplitTest.java
===================================================================
--- projects/spec/trunk/modules/cts/src/test/java/org/jbpm/test/cts/gateway/exclusive/ExclusiveGatewaySplitTest.java 2008-10-01 03:42:57 UTC (rev 2456)
+++ projects/spec/trunk/modules/cts/src/test/java/org/jbpm/test/cts/gateway/exclusive/ExclusiveGatewaySplitTest.java 2008-10-01 13:18:18 UTC (rev 2457)
@@ -83,7 +83,7 @@
try
{
proc.waitForEnd();
- fail("No gate defained for foo==10");
+ fail("No gate defined for foo==10");
}
catch (RuntimeException rte)
{
Added: projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ComplexGatewayImpl.java
===================================================================
--- projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ComplexGatewayImpl.java (rev 0)
+++ projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ComplexGatewayImpl.java 2008-10-01 13:18:18 UTC (rev 2457)
@@ -0,0 +1,68 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jbpm.ri.model;
+
+//$Id$
+
+import javax.persistence.Entity;
+
+import org.jbpm.api.NotImplementedException;
+import org.jbpm.api.model.Expression;
+
+/**
+ * A Complex Gateway handles situations that are not easily handled through the other types of Gateways. Complex
+ * Gateways can also be used to combine a set of linked simple Gateways into a single, more compact situation. Modelers
+ * can provide complex expressions that determine the merging and/or splitting behavior of the
+ *
+ * @author thomas.diesler at jboss.com
+ * @since 08-Jul-2008
+ */
+ at Entity(name = "ComplexGateway")
+public class ComplexGatewayImpl extends GatewayImpl
+{
+ private static final long serialVersionUID = 1L;
+
+ public ComplexGatewayImpl(String name)
+ {
+ super(name, GatewayType.Complex);
+ }
+
+ public GatewayType getGatewayType()
+ {
+ return GatewayType.Complex;
+ }
+
+ public Expression getIncommingCondition()
+ {
+ throw new NotImplementedException("JBPM-1636", "ComplexGateway incomming condition");
+ }
+
+ public Expression getOutgoingCondition()
+ {
+ throw new NotImplementedException("JBPM-1637", "ComplexGateway outgoing condition");
+ }
+
+ public String toString()
+ {
+ return "ComplexGateway[" + getName() + "]";
+ }
+}
\ No newline at end of file
Property changes on: projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ComplexGatewayImpl.java
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Added: projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ExclusiveGatewayImpl.java
===================================================================
--- projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ExclusiveGatewayImpl.java (rev 0)
+++ projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ExclusiveGatewayImpl.java 2008-10-01 13:18:18 UTC (rev 2457)
@@ -0,0 +1,213 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jbpm.ri.model;
+
+//$Id$
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.Entity;
+import javax.persistence.Transient;
+
+import org.jbpm.api.model.Expression;
+import org.jbpm.api.model.Node;
+import org.jbpm.api.model.SequenceFlow;
+import org.jbpm.api.model.SequenceFlow.ConditionType;
+import org.jbpm.api.runtime.ExecutionHandler;
+import org.jbpm.api.runtime.FlowHandler;
+import org.jbpm.api.runtime.Token;
+import org.jbpm.api.runtime.TokenExecutor;
+import org.jbpm.ri.runtime.ExpressionEvaluator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * A point in the workflow process where, based on a decision or workflow control data, one of several branches is
+ * chosen.
+ *
+ * @author thomas.diesler at jboss.com
+ * @since 08-Jul-2008
+ */
+ at Entity(name = "ExclusiveGateway")
+public class ExclusiveGatewayImpl extends GatewayImpl
+{
+ private static final long serialVersionUID = 1L;
+
+ // provide logging
+ final static Logger log = LoggerFactory.getLogger(ExclusiveGatewayImpl.class);
+
+ @Transient
+ private Set<SequenceFlow> outstandingFlows;
+
+ public ExclusiveGatewayImpl(String name)
+ {
+ super(name, GatewayType.Exclusive);
+ }
+
+ @Override
+ protected ExecutionHandler getDefaultExecutionHandler()
+ {
+ final Node thisNode = this;
+ final ExecutionHandler superExecHandler = super.getDefaultExecutionHandler();
+
+ return new ExecutionHandler()
+ {
+ private static final long serialVersionUID = 1L;
+
+ public void execute(Token token)
+ {
+ // Call the super default handler
+ superExecHandler.execute(token);
+
+ // Multiple incomingFlows must be synchronized
+ if (outstandingFlows == null)
+ outstandingFlows = new HashSet<SequenceFlow>(inFlows);
+
+ SequenceFlow flow = token.getFlow();
+ outstandingFlows.remove(flow);
+ }
+
+ @Override
+ public Node getNode()
+ {
+ return thisNode;
+ }
+
+ @Override
+ public void setNode(Node node)
+ {
+ }
+ };
+ }
+
+ @Override
+ protected FlowHandler getDefaultFlowHandler()
+ {
+ final Node thisNode = this;
+ return new FlowHandler()
+ {
+ private static final long serialVersionUID = 1L;
+
+ public void execute(TokenExecutor tokenExecutor, Token token)
+ {
+ Node sourceRef = token.getFlow().getSourceRef();
+
+ // Schedule the first token that arrives
+ if (token == receivedTokens.get(0))
+ {
+ log.debug("Propagate token comming from: " + sourceRef);
+ SequenceFlow selectedGate = getSelectedGate(token);
+ tokenExecutor.move(token, selectedGate);
+ }
+ // Ignore all other tokens
+ else
+ {
+ log.debug("Ignore token comming from: " + sourceRef);
+ tokenExecutor.destroy(token);
+ }
+
+ // Reset the gateway
+ if (outstandingFlows.size() == 0)
+ {
+ reset();
+ }
+ }
+
+ @Override
+ public Node getNode()
+ {
+ return thisNode;
+ }
+
+ @Override
+ public void setNode(Node node)
+ {
+ }
+ };
+ }
+
+ @Override
+ protected void reset()
+ {
+ super.reset();
+ outstandingFlows = null;
+ }
+
+ // Get a single selected gate which' condition evaluates to TRUE
+ // Fall back to the default gate if there is one
+ // Choke if there is no selected gate
+ private SequenceFlow getSelectedGate(Token token)
+ {
+ SequenceFlow selectedGate = null;
+ for (SequenceFlow auxGate : getGates())
+ {
+ SequenceFlow seqFlow = auxGate;
+ if (seqFlow.getConditionType() == ConditionType.Expression)
+ {
+ Expression expr = seqFlow.getConditionExpression();
+ ExpressionEvaluator exprEvaluator = new ExpressionEvaluator(expr);
+ if ((Boolean)exprEvaluator.evaluateExpression(token))
+ {
+ selectedGate = auxGate;
+ break;
+ }
+ }
+ }
+
+ // Use to the default gate if there is one
+ if (selectedGate == null)
+ {
+ for (SequenceFlow auxGate : getGates())
+ {
+ SequenceFlow seqFlow = auxGate;
+ if (seqFlow.getConditionType() == ConditionType.Default)
+ {
+ selectedGate = auxGate;
+ break;
+ }
+ }
+ }
+
+ // Fallback to the single outgoing gate that is not conditional
+ if (selectedGate == null && getGates().size() == 1)
+ {
+ SequenceFlow auxGate = getGates().get(0);
+ SequenceFlow seqFlow = auxGate;
+ if (seqFlow.getConditionType() == ConditionType.None)
+ {
+ selectedGate = auxGate;
+ }
+ }
+
+ if (selectedGate == null)
+ throw new IllegalStateException("Cannot select applicable gate in: " + this);
+
+ return selectedGate;
+ }
+
+ public String toString()
+ {
+ return "ExclusiveGateway[" + getName() + "]";
+ }
+}
\ No newline at end of file
Property changes on: projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ExclusiveGatewayImpl.java
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Modified: projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ExpressionImpl.java
===================================================================
--- projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ExpressionImpl.java 2008-10-01 03:42:57 UTC (rev 2456)
+++ projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ExpressionImpl.java 2008-10-01 13:18:18 UTC (rev 2457)
@@ -58,6 +58,10 @@
this.lang = lang;
}
+ // Persistence ctor
+ protected ExpressionImpl()
+ {
+ }
public ExpressionLanguage getExpressionLanguage()
{
Modified: projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/GatewayImpl.java
===================================================================
--- projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/GatewayImpl.java 2008-10-01 03:42:57 UTC (rev 2456)
+++ projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/GatewayImpl.java 2008-10-01 13:18:18 UTC (rev 2457)
@@ -23,16 +23,28 @@
//$Id$
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.management.ObjectName;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.MappedSuperclass;
+import javax.persistence.Transient;
import org.jbpm.api.Constants;
+import org.jbpm.api.client.ProcessEngine;
import org.jbpm.api.model.Gateway;
+import org.jbpm.api.model.Node;
import org.jbpm.api.model.SequenceFlow;
+import org.jbpm.api.model.Signal;
import org.jbpm.api.model.SequenceFlow.ConditionType;
import org.jbpm.api.model.builder.ObjectNameFactory;
+import org.jbpm.api.runtime.ExecutionHandler;
+import org.jbpm.api.runtime.SignalHandler;
+import org.jbpm.api.runtime.Token;
+import org.jbpm.api.service.SignalService;
import org.jbpm.ri.model.builder.MultipleInFlowSupport;
import org.jbpm.ri.model.builder.MultipleOutFlowSupport;
@@ -43,14 +55,27 @@
* @author thomas.diesler at jboss.com
* @since 08-Jul-2008
*/
+ at MappedSuperclass
public abstract class GatewayImpl extends NodeImpl implements Gateway, MultipleOutFlowSupport, MultipleInFlowSupport
{
// provide serial version UID
private static final long serialVersionUID = 1L;
- public GatewayImpl(String name)
+ @Enumerated(EnumType.STRING)
+ protected GatewayType gatewayType;
+
+ // The list of flows from which a token is expected
+ @Transient
+ protected List<SequenceFlow> expectedFlows;
+
+ // The list of received tokens
+ @Transient
+ protected List<Token> receivedTokens;
+
+ public GatewayImpl(String name, GatewayType gatewayType)
{
super(name);
+ this.gatewayType = gatewayType;
}
@Override
@@ -62,6 +87,24 @@
return oname;
}
+ @Override
+ public GatewayType getGatewayType()
+ {
+ return gatewayType;
+ }
+
+ @Override
+ public void addOutFlow(SequenceFlowImpl outFlow)
+ {
+ outFlows.add(outFlow);
+ }
+
+ @Override
+ public void addInFlow(SequenceFlowImpl inFlow)
+ {
+ inFlows.add(inFlow);
+ }
+
public List<SequenceFlow> getGates()
{
return Collections.unmodifiableList(outFlows);
@@ -94,4 +137,92 @@
}
return gate;
}
+
+ protected void reset()
+ {
+ expectedFlows = null;
+ receivedTokens = null;
+ }
+
+ @Override
+ protected ExecutionHandler getDefaultExecutionHandler()
+ {
+ final Node thisNode = this;
+ return new ExecutionHandler()
+ {
+ private static final long serialVersionUID = 1L;
+
+ public void execute(Token token)
+ {
+ // Initialize the gateway
+ if (expectedFlows == null)
+ {
+ expectedFlows = new ArrayList<SequenceFlow>(inFlows);
+ receivedTokens = new ArrayList<Token>();
+ }
+
+ // Check that token from flow is valid
+ SequenceFlow flow = token.getFlow();
+ if (expectedFlows.contains(flow) == false)
+ throw new IllegalStateException("Unexpected token from: " + flow);
+
+ // Call custom execution handler
+ ExecutionHandler exHandler = getExecutionHandler(false);
+ if (exHandler != null)
+ exHandler.execute(token);
+
+ // Remove the flow from the expected list
+ expectedFlows.remove(flow);
+
+ // Store the received token for processing in the FlowHandler
+ receivedTokens.add(token);
+ }
+
+ @Override
+ public Node getNode()
+ {
+ return thisNode;
+ }
+
+ @Override
+ public void setNode(Node node)
+ {
+ }
+ };
+ }
+
+ @Override
+ protected SignalHandler getDefaultSignalHandler()
+ {
+ final Node thisNode = this;
+ return new SignalHandler()
+ {
+ private static final long serialVersionUID = 1L;
+
+ ProcessEngine engine = getProcess().getProcessEngine();
+ SignalService sigService = engine.getService(SignalService.class);
+
+ public void throwEnterSignal(Token token)
+ {
+ Signal signal = new Signal(getKey(), Signal.SignalType.SYSTEM_GATEWAY_ENTER);
+ sigService.throwSignal(signal);
+ }
+
+ public void throwExitSignal(Token token)
+ {
+ Signal signal = new Signal(getKey(), Signal.SignalType.SYSTEM_GATEWAY_EXIT);
+ sigService.throwSignal(signal);
+ }
+
+ @Override
+ public Node getNode()
+ {
+ return thisNode;
+ }
+ @Override
+ public void setNode(Node node)
+ {
+ }
+ };
+ }
}
\ No newline at end of file
Added: projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/InclusiveGatewayImpl.java
===================================================================
--- projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/InclusiveGatewayImpl.java (rev 0)
+++ projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/InclusiveGatewayImpl.java 2008-10-01 13:18:18 UTC (rev 2457)
@@ -0,0 +1,195 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jbpm.ri.model;
+
+//$Id$
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.persistence.Entity;
+
+import org.jbpm.api.model.Expression;
+import org.jbpm.api.model.Expression.ExpressionLanguage;
+import org.jbpm.api.model.Node;
+import org.jbpm.api.model.SequenceFlow;
+import org.jbpm.api.model.SequenceFlow.ConditionType;
+import org.jbpm.api.runtime.ExecutionContext;
+import org.jbpm.api.runtime.FlowHandler;
+import org.jbpm.api.runtime.Token;
+import org.jbpm.api.runtime.TokenExecutor;
+import org.jbpm.api.runtime.Attachments.Key;
+import org.mvel.MVEL;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This Decision represents a branching point where Alternatives are based on conditional expressions contained within
+ * outgoing Sequence Flow. However, in this case, the True evaluation of one condition expression does not exclude the
+ * evaluation of other condition expressions. All Sequence Flow with a True evaluation will be traversed by a Token.
+ *
+ * @author thomas.diesler at jboss.com
+ * @since 08-Jul-2008
+ */
+ at Entity(name = "InclusiveGateway")
+public class InclusiveGatewayImpl extends GatewayImpl
+{
+ private static final long serialVersionUID = 1L;
+
+ // provide logging
+ final static Logger log = LoggerFactory.getLogger(InclusiveGatewayImpl.class);
+
+ public InclusiveGatewayImpl(String name)
+ {
+ super(name, GatewayType.Inclusive);
+ }
+
+ @Override
+ protected FlowHandler getDefaultFlowHandler()
+ {
+ final Node thisNode = this;
+ return new FlowHandler()
+ {
+ private static final long serialVersionUID = 1L;
+
+ public void execute(TokenExecutor tokenExecutor, Token token)
+ {
+ Node sourceRef = token.getFlow().getSourceRef();
+ log.debug("Propagate token comming from: " + sourceRef);
+
+ // Get the applicable gates
+ List<SequenceFlow> applicableGates = getApplicableGates(token);
+ log.debug("applicableGates: " + applicableGates);
+
+ if (applicableGates.size() == 1)
+ {
+ SequenceFlow outFlow = applicableGates.get(0);
+ tokenExecutor.move(token, outFlow);
+ }
+ else
+ {
+ List<Token> outTokens = new ArrayList<Token>();
+ for (SequenceFlow auxGate : applicableGates)
+ {
+ SequenceFlow outFlow = auxGate;
+ Token outToken = token.copyToken();
+ tokenExecutor.create(outToken, outFlow);
+ outTokens.add(outToken);
+ }
+ for (Token outToken : outTokens)
+ {
+ tokenExecutor.start(outToken);
+ }
+ }
+
+ // Destroy the incomming token if there are
+ // more than one applicable gates
+ if (applicableGates.size() > 1)
+ tokenExecutor.destroy(token);
+ }
+
+ @Override
+ public Node getNode()
+ {
+ return thisNode;
+ }
+
+ @Override
+ public void setNode(Node node)
+ {
+ }
+ };
+ }
+
+ // Get applicable gates which' condition evaluates to TRUE
+ // Fall back to the default gate if there is one
+ // Choke if there is no applicable gate
+ private List<SequenceFlow> getApplicableGates(Token token)
+ {
+ List<SequenceFlow> applicableGates = new ArrayList<SequenceFlow>();
+ for (SequenceFlow auxGate : getGates())
+ {
+ SequenceFlow seqFlow = auxGate;
+ if (seqFlow.getConditionType() == ConditionType.Expression)
+ {
+ Expression expr = seqFlow.getConditionExpression();
+ if (expr.getExpressionLanguage() == ExpressionLanguage.MVEL)
+ {
+ String mvel = expr.getExpressionBody();
+ ExecutionContext exContext = token.getExecutionContext();
+ Map<String, Object> vars = new HashMap<String, Object>();
+ for (Key key : exContext.getAttachmentKeys())
+ {
+ String name = key.getNamePart();
+ Object value = exContext.getAttachment(name);
+ vars.put(name, value);
+ }
+ Boolean result = (Boolean)MVEL.eval(mvel, vars);
+ if (result == true)
+ {
+ applicableGates.add(auxGate);
+ }
+ }
+ else
+ {
+ throw new IllegalStateException("Unsupported expression language: " + expr.getExpressionLanguage());
+ }
+ }
+ }
+
+ // Use to the default gate if there is one
+ if (applicableGates.size() == 0)
+ {
+ for (SequenceFlow auxGate : getGates())
+ {
+ SequenceFlow seqFlow = auxGate;
+ if (seqFlow.getConditionType() == ConditionType.Default)
+ {
+ applicableGates.add(auxGate);
+ }
+ }
+ }
+
+ // Fallback to the single outgoing gate that is not conditional
+ if (applicableGates.size() == 0 && getGates().size() == 1)
+ {
+ SequenceFlow auxGate = getGates().get(0);
+ SequenceFlow seqFlow = auxGate;
+ if (seqFlow.getConditionType() == ConditionType.None)
+ {
+ applicableGates.add(auxGate);
+ }
+ }
+
+ if (applicableGates.size() == 0)
+ throw new IllegalStateException("Cannot select applicable gate in: " + this);
+
+ return applicableGates;
+ }
+
+ public String toString()
+ {
+ return "InclusiveGateway[" + getName() + "]";
+ }
+}
\ No newline at end of file
Property changes on: projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/InclusiveGatewayImpl.java
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Modified: projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/NodeImpl.java
===================================================================
--- projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/NodeImpl.java 2008-10-01 03:42:57 UTC (rev 2456)
+++ projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/NodeImpl.java 2008-10-01 13:18:18 UTC (rev 2457)
@@ -392,14 +392,6 @@
throw new InvalidProcessException("Dead end node: " + this);
}
- /**
- * Reset the Node's state
- */
- public void reset()
- {
- // noting to do
- }
-
private void initFlow(Process proc, SequenceFlowImpl flow)
{
if (flow != null)
Added: projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ParallelGatewayImpl.java
===================================================================
--- projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ParallelGatewayImpl.java (rev 0)
+++ projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ParallelGatewayImpl.java 2008-10-01 13:18:18 UTC (rev 2457)
@@ -0,0 +1,207 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jbpm.ri.model;
+
+//$Id$
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.persistence.Entity;
+import javax.persistence.Transient;
+
+import org.jbpm.api.model.Node;
+import org.jbpm.api.model.SequenceFlow;
+import org.jbpm.api.runtime.ExecutionHandler;
+import org.jbpm.api.runtime.FlowHandler;
+import org.jbpm.api.runtime.Token;
+import org.jbpm.api.runtime.TokenExecutor;
+import org.jbpm.ri.runtime.TokenImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * Parallel Gateway is required when two or more Activities need to be executed in parallel.
+ *
+ * @author thomas.diesler at jboss.com
+ * @since 08-Jul-2008
+ */
+ at Entity(name = "ParallelGateway")
+public class ParallelGatewayImpl extends GatewayImpl
+{
+ private static final long serialVersionUID = 1L;
+
+ // provide logging
+ final static Logger log = LoggerFactory.getLogger(ParallelGatewayImpl.class);
+
+ @Transient
+ private Set<SequenceFlow> outstandingFlows;
+
+ @Transient
+ private Set<Token> mergeTokens;
+
+ public ParallelGatewayImpl(String name)
+ {
+ super(name, GatewayType.Parallel);
+ }
+
+ @Override
+ protected ExecutionHandler getDefaultExecutionHandler()
+ {
+ final Node thisNode = this;
+ final ExecutionHandler superExecHandler = super.getDefaultExecutionHandler();
+
+ return new ExecutionHandler()
+ {
+ private static final long serialVersionUID = 1L;
+
+ public void execute(Token token)
+ {
+ // Call the super default handler
+ superExecHandler.execute(token);
+
+ // Multiple incomingFlows must be synchronized
+ if (outstandingFlows == null)
+ {
+ outstandingFlows = new HashSet<SequenceFlow>(inFlows);
+ mergeTokens = new HashSet<Token>();
+ }
+
+ SequenceFlow flow = token.getFlow();
+ outstandingFlows.remove(flow);
+ mergeTokens.add(token);
+ }
+
+ @Override
+ public Node getNode()
+ {
+ return thisNode;
+ }
+
+ @Override
+ public void setNode(Node node)
+ {
+ }
+ };
+ }
+
+ @Override
+ protected FlowHandler getDefaultFlowHandler()
+ {
+ final Node thisNode = this;
+ return new FlowHandler()
+ {
+ private static final long serialVersionUID = 1L;
+
+ public void execute(TokenExecutor tokenExecutor, Token token)
+ {
+ // In any case, the incomming token is not propagated
+ tokenExecutor.suspend(token);
+
+ // If the gateway has a single incomming flow the outgoing token is the incomming token
+ Token outToken = (getInFlows().size() == 1 ? token : null);
+
+ // The outgoing token is the merge of all incomming tokens
+ if (outToken == null)
+ {
+ // If there are no more outstanding flows
+ if (outstandingFlows.size() == 0)
+ {
+ // Merge the tokens together and submit the merged tokens
+ outToken = getMergedTokens();
+ }
+
+ // There are outstanding flows
+ else if (outstandingFlows.size() > 0)
+ {
+ log.debug("Waiting for " + outstandingFlows + " in gateway: " + this);
+ }
+ }
+
+ // Schedule the outgoing token
+ if (outToken != null)
+ {
+ // Start a copy of the outgoing token for every gate
+ List<Token> outTokens = new ArrayList<Token>();
+ for(SequenceFlow auxGate : getGates())
+ {
+ SequenceFlow outFlow = auxGate;
+ outToken = outToken.copyToken();
+ tokenExecutor.create(outToken, outFlow);
+ outTokens.add(outToken);
+ }
+ for (Token auxToken : outTokens)
+ {
+ tokenExecutor.start(auxToken);
+ }
+
+ // Destroy the received tokens
+ for (Token auxToken : receivedTokens)
+ {
+ tokenExecutor.destroy(auxToken);
+ }
+
+ // Reset the gateway
+ reset();
+ }
+ }
+
+ @Override
+ public Node getNode()
+ {
+ return thisNode;
+ }
+
+ @Override
+ public void setNode(Node node)
+ {
+ }
+ };
+ }
+
+ @Override
+ public void reset()
+ {
+ super.reset();
+ outstandingFlows = null;
+ mergeTokens = null;
+ }
+
+ private Token getMergedTokens()
+ {
+ TokenImpl mergedToken = new TokenImpl(null);
+ for (Token auxToken : mergeTokens)
+ {
+ log.debug("mergeToken: " + auxToken);
+ mergedToken.mergeToken(auxToken);
+ }
+ return mergedToken;
+ }
+
+ public String toString()
+ {
+ return "ParallelGateway[" + getName() + "]";
+ }
+}
\ No newline at end of file
Property changes on: projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ParallelGatewayImpl.java
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Modified: projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/builder/GatewayBuilderImpl.java
===================================================================
--- projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/builder/GatewayBuilderImpl.java 2008-10-01 03:42:57 UTC (rev 2456)
+++ projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/builder/GatewayBuilderImpl.java 2008-10-01 13:18:18 UTC (rev 2457)
@@ -23,10 +23,13 @@
//$Id$
-import org.jbpm.api.NotImplementedException;
import org.jbpm.api.model.Gateway;
import org.jbpm.api.model.Expression.ExpressionLanguage;
+import org.jbpm.api.model.SequenceFlow.ConditionType;
import org.jbpm.api.model.builder.GatewayBuilder;
+import org.jbpm.ri.model.ExpressionImpl;
+import org.jbpm.ri.model.GatewayImpl;
+import org.jbpm.ri.model.SequenceFlowImpl;
/**
* The GatewayBuilder can be used to build a {@link Gateway} dynamically.
@@ -43,16 +46,32 @@
public GatewayBuilder addConditionalGate(String targetName, ExpressionLanguage exprLang, String exprBody)
{
- throw new NotImplementedException();
+ GatewayImpl gatewayImpl = getGateway();
+ SequenceFlowImpl outFlow = new SequenceFlowImpl(targetName, ConditionType.Expression, new ExpressionImpl(exprLang, exprBody));
+ gatewayImpl.addOutFlow(outFlow);
+ return this;
}
public GatewayBuilder addDefaultGate(String targetName)
{
- throw new NotImplementedException();
+ GatewayImpl gatewayImpl = getGateway();
+ SequenceFlowImpl outFlow = new SequenceFlowImpl(targetName, ConditionType.Default, null);
+ gatewayImpl.addOutFlow(outFlow);
+ return this;
}
public GatewayBuilder addGate(String targetName)
{
- throw new NotImplementedException();
+ GatewayImpl gatewayImpl = getGateway();
+ SequenceFlowImpl outFlow = new SequenceFlowImpl(targetName);
+ gatewayImpl.addOutFlow(outFlow);
+ return this;
}
+
+ private GatewayImpl getGateway()
+ {
+ if (node instanceof GatewayImpl == false)
+ throw new IllegalStateException("Last added flow object is not an Gateway: " + node);
+ return (GatewayImpl)node;
+ }
}
\ No newline at end of file
Modified: projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/builder/ProcessBuilderImpl.java
===================================================================
--- projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/builder/ProcessBuilderImpl.java 2008-10-01 03:42:57 UTC (rev 2456)
+++ projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/builder/ProcessBuilderImpl.java 2008-10-01 13:18:18 UTC (rev 2457)
@@ -40,10 +40,14 @@
import org.jbpm.api.runtime.FlowHandler;
import org.jbpm.api.runtime.SignalHandler;
import org.jbpm.ri.model.AssignmentImpl;
+import org.jbpm.ri.model.ComplexGatewayImpl;
import org.jbpm.ri.model.EndEventImpl;
import org.jbpm.ri.model.EventImpl;
+import org.jbpm.ri.model.ExclusiveGatewayImpl;
import org.jbpm.ri.model.ExpressionImpl;
+import org.jbpm.ri.model.InclusiveGatewayImpl;
import org.jbpm.ri.model.NodeImpl;
+import org.jbpm.ri.model.ParallelGatewayImpl;
import org.jbpm.ri.model.ProcessImpl;
import org.jbpm.ri.model.PropertyImpl;
import org.jbpm.ri.model.ReceiveTaskImpl;
@@ -194,19 +198,19 @@
{
if (GatewayType.Exclusive == type)
{
- throw new NotImplementedException();
+ node = new ExclusiveGatewayImpl(name);
}
else if (GatewayType.Inclusive == type)
{
- throw new NotImplementedException();
+ node = new InclusiveGatewayImpl(name);
}
else if (GatewayType.Parallel == type)
{
- throw new NotImplementedException();
+ node = new ParallelGatewayImpl(name);
}
else if (GatewayType.Complex == type)
{
- throw new NotImplementedException();
+ node = new ComplexGatewayImpl(name);
}
addNode(node);
return new GatewayBuilderImpl(this);
Modified: projects/spec/trunk/modules/impl/src/main/resources/jbpm-cfg-beans.xml
===================================================================
--- projects/spec/trunk/modules/impl/src/main/resources/jbpm-cfg-beans.xml 2008-10-01 03:42:57 UTC (rev 2456)
+++ projects/spec/trunk/modules/impl/src/main/resources/jbpm-cfg-beans.xml 2008-10-01 13:18:18 UTC (rev 2457)
@@ -24,9 +24,14 @@
<property name="annotatedClasses">
<set elementClass="java.lang.String">
<value>org.jbpm.ri.model.AbstractElementImpl</value>
+ <value>org.jbpm.ri.model.ComplexGatewayImpl</value>
<value>org.jbpm.ri.model.EndEventImpl</value>
+ <value>org.jbpm.ri.model.ExclusiveGatewayImpl</value>
+ <value>org.jbpm.ri.model.GatewayImpl</value>
+ <value>org.jbpm.ri.model.InclusiveGatewayImpl</value>
<value>org.jbpm.ri.model.MessageImpl</value>
<value>org.jbpm.ri.model.NodeImpl</value>
+ <value>org.jbpm.ri.model.ParallelGatewayImpl</value>
<value>org.jbpm.ri.model.ParticipantImpl</value>
<value>org.jbpm.ri.model.ProcessImpl</value>
<value>org.jbpm.ri.model.PropertyImpl</value>
More information about the jbpm-commits
mailing list