[jboss-svn-commits] JBL Code SVN: r20178 - in labs/jbossrules/trunk: drools-process and 24 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Tue May 27 07:13:44 EDT 2008


Author: KrisVerlaenen
Date: 2008-05-27 07:13:44 -0400 (Tue, 27 May 2008)
New Revision: 20178

Added:
   labs/jbossrules/trunk/drools-process/
   labs/jbossrules/trunk/drools-process/drools-jpdl/
   labs/jbossrules/trunk/drools-process/drools-jpdl/.classpath
   labs/jbossrules/trunk/drools-process/drools-jpdl/.project
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/JpdlParser.java
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/JpdlProcessValidator.java
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/JpdlConnection.java
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/JpdlProcess.java
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/Decision.java
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/EndState.java
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/Fork.java
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/Join.java
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/JpdlNode.java
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/MailNode.java
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/ProcessState.java
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/StartState.java
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/State.java
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/TaskNode.java
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/JpdlProcessInstance.java
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/JpdlProcessInstanceFactory.java
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/DecisionInstance.java
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/EndStateInstance.java
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/ForkInstance.java
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/JoinInstance.java
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/JpdlNodeInstance.java
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/MailNodeInstance.java
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/ProcessStateInstance.java
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/StartStateInstance.java
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/StateInstance.java
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/TaskNodeInstance.java
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/xml/
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/xml/JpdlProcessSemanticModule.java
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/xml/StartStateHandler.java
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/resources/
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/resources/META-INF/
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/resources/META-INF/JpdlProcessInstanceFactory.conf
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/resources/META-INF/JpdlProcessNodeInstanceFactory.conf
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/resources/META-INF/drools.rulebase.conf
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/java/
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/java/org/
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/java/org/drools/
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/java/org/drools/ParseSimpleProcessTest.java
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/java/org/drools/SimpleProcessTest.java
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/java/org/drools/SysoutHandler.java
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/java/org/drools/WebsaleProcessTest.java
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/java/org/jbpm/
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/java/org/jbpm/websale/
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/java/org/jbpm/websale/RemindActor.java
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/java/org/jbpm/websale/ShipItem.java
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/java/org/jbpm/websale/UpdateBooks.java
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/simple/
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/simple/gpd.xml
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/simple/processdefinition.xml
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/simple/processimage.jpg
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/simple2/
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/simple2/gpd.xml
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/simple2/processdefinition.xml
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/simple2/processimage.jpg
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/websale/
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/websale/gpd.xml
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/websale/processdefinition.xml
   labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/websale/processimage.jpg
Log:
JBRULES-1623: Support for jPDL 3.2
 - initial commit

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/.classpath
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/.classpath	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/.classpath	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src/main/java"/>
+	<classpathentry kind="src" path="src/main/resources"/>
+	<classpathentry kind="src" path="src/test/java"/>
+	<classpathentry kind="src" path="src/test/resources"/>
+	<classpathentry combineaccessrules="false" exported="true" kind="src" path="/drools-compiler"/>
+	<classpathentry combineaccessrules="false" exported="true" kind="src" path="/drools-core"/>
+	<classpathentry exported="true" kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3"/>
+	<classpathentry exported="true" kind="lib" path="lib/jbpm-jpdl.jar" sourcepath="F:/Mijn documenten/projects/jbpm/jbpm-jpdl-3.2.GA/src/jpdl"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="var" path="M2_REPO/commons-collections/commons-collections/3.2/commons-collections-3.2.jar"/>
+	<classpathentry kind="var" path="M2_REPO/commons-logging/commons-logging/1.0.4/commons-logging-1.0.4.jar"/>
+	<classpathentry kind="var" path="M2_REPO/org/mvel/mvel/2.0-SNAPSHOT/mvel-2.0-SNAPSHOT.jar"/>
+	<classpathentry kind="var" path="M2_REPO/dom4j/dom4j/1.6.1/dom4j-1.6.1.jar"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/.project
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/.project	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/.project	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>drools-jpdl</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/JpdlParser.java
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/JpdlParser.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/JpdlParser.java	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,239 @@
+package org.drools.jpdl;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.drools.jpdl.core.JpdlConnection;
+import org.drools.jpdl.core.JpdlProcess;
+import org.drools.jpdl.core.node.Decision;
+import org.drools.jpdl.core.node.EndState;
+import org.drools.jpdl.core.node.Fork;
+import org.drools.jpdl.core.node.Join;
+import org.drools.jpdl.core.node.JpdlNode;
+import org.drools.jpdl.core.node.MailNode;
+import org.drools.jpdl.core.node.ProcessState;
+import org.drools.jpdl.core.node.StartState;
+import org.drools.jpdl.core.node.State;
+import org.drools.jpdl.core.node.TaskNode;
+import org.drools.process.core.ParameterDefinition;
+import org.drools.process.core.context.swimlane.Swimlane;
+import org.drools.process.core.context.swimlane.SwimlaneContext;
+import org.drools.process.core.datatype.impl.type.StringDataType;
+import org.drools.process.core.impl.ParameterDefinitionImpl;
+import org.drools.process.core.validation.ProcessValidationError;
+import org.drools.workflow.core.Node;
+import org.jbpm.graph.def.Event;
+import org.jbpm.graph.def.ExceptionHandler;
+import org.jbpm.graph.def.ProcessDefinition;
+import org.jbpm.taskmgmt.def.Task;
+
+public class JpdlParser {
+    
+    private static final Set<ParameterDefinition> EMAIL_PARAMETER_DEFINITIONS = new HashSet<ParameterDefinition>();
+    private static final Pattern MAIL_TEMPLATE_PATTERN = Pattern.compile("<template>(.*)</template>", Pattern.DOTALL);
+    private static final Pattern MAIL_ACTORS_PATTERN = Pattern.compile("<actors>(.*)</actors>", Pattern.DOTALL);
+    private static final Pattern MAIL_TO_PATTERN = Pattern.compile("<to>(.*)</to>", Pattern.DOTALL);
+    private static final Pattern MAIL_SUBJECT_PATTERN = Pattern.compile("<subject>(.*)</subject>", Pattern.DOTALL);
+    private static final Pattern MAIL_TEXT_PATTERN = Pattern.compile("<text>(.*)</text>", Pattern.DOTALL);
+    
+    static {
+        EMAIL_PARAMETER_DEFINITIONS.add(new ParameterDefinitionImpl("From", new StringDataType()));
+        EMAIL_PARAMETER_DEFINITIONS.add(new ParameterDefinitionImpl("To", new StringDataType()));
+        EMAIL_PARAMETER_DEFINITIONS.add(new ParameterDefinitionImpl("Subject", new StringDataType()));
+        EMAIL_PARAMETER_DEFINITIONS.add(new ParameterDefinitionImpl("Text", new StringDataType()));
+    }
+    
+    private ProcessValidationError[] errors;
+    
+    public JpdlProcess loadJpdlProcess(String name) {
+        org.jbpm.graph.def.ProcessDefinition processDefinition =
+            org.jbpm.graph.def.ProcessDefinition.parseXmlResource(name);
+        return loadJpdlProcess(processDefinition);
+    }
+    
+    public JpdlProcess loadJpdlProcess(org.jbpm.graph.def.ProcessDefinition processDefinition) {
+        JpdlProcess process = new JpdlProcess();
+        process.setId(processDefinition.getName());
+        process.setName(processDefinition.getName());
+        process.setPackageName("org.drools");
+        SwimlaneContext swimlaneContext = new SwimlaneContext();
+        process.addContext(swimlaneContext);
+        process.setDefaultContext(swimlaneContext);
+        org.jbpm.graph.def.Node startState = processDefinition.getStartState();
+        String startStateName = startState == null ? null : startState.getName();
+        
+        List<org.jbpm.graph.def.Node> nodes = processDefinition.getNodes();
+        int nodeId = 0;
+        Map<org.jbpm.graph.def.Node, Node> mapping = new HashMap<org.jbpm.graph.def.Node, Node>();
+        for (org.jbpm.graph.def.Node jPDLnode: nodes) {
+            JpdlNode node = null;
+            if (jPDLnode instanceof org.jbpm.graph.node.StartState) {
+                node = new StartState();
+            } else if (jPDLnode instanceof org.jbpm.graph.node.EndState) {
+                node = new EndState();
+            } else if (org.jbpm.graph.def.Node.class.equals(jPDLnode.getClass())) {
+                JpdlNode newNode = new JpdlNode();
+                setDefaultNodeProperties(jPDLnode, newNode);
+                node = newNode;
+            } else if (jPDLnode instanceof org.jbpm.graph.node.Fork) {
+                org.jbpm.graph.node.Fork jPDLfork =
+                    (org.jbpm.graph.node.Fork) jPDLnode; 
+                Fork newNode = new Fork();
+                newNode.setScript(jPDLfork.getScript());
+                node = newNode;
+            } else if (jPDLnode instanceof org.jbpm.graph.node.Join) {
+                org.jbpm.graph.node.Join jPDLjoin =
+                    (org.jbpm.graph.node.Join) jPDLnode; 
+                Join newNode = new Join();
+                newNode.setDiscriminator(jPDLjoin.isDiscriminator());
+                newNode.setTokenNames(jPDLjoin.getTokenNames());
+                newNode.setScript(jPDLjoin.getScript());
+                newNode.setNOutOfM(jPDLjoin.getNOutOfM());
+                node = newNode;
+            } else if (jPDLnode instanceof org.jbpm.graph.node.MailNode) {
+                String config = jPDLnode.getAction().getActionDelegation().getConfiguration();
+                
+                MailNode newNode = new MailNode();
+                Matcher matcher = MAIL_TEMPLATE_PATTERN.matcher(config);
+                if (matcher.find()) {
+                    newNode.setTemplate(matcher.group(1));
+                }
+                matcher = MAIL_ACTORS_PATTERN.matcher(config);
+                if (matcher.find()) {
+                    newNode.setActors(matcher.group(1));
+                }
+                matcher = MAIL_TO_PATTERN.matcher(config);
+                if (matcher.find()) {
+                    newNode.setTo(matcher.group(1));
+                }
+                matcher = MAIL_SUBJECT_PATTERN.matcher(config);
+                if (matcher.find()) {
+                    newNode.setSubject(matcher.group(1));
+                }
+                matcher = MAIL_TEXT_PATTERN.matcher(config);
+                if (matcher.find()) {
+                    newNode.setText(matcher.group(1));
+                }
+                node = newNode;
+            } else if (jPDLnode instanceof org.jbpm.graph.node.Decision) {
+            	org.jbpm.graph.node.Decision jPDLdecision =
+                    (org.jbpm.graph.node.Decision) jPDLnode; 
+            	Decision newNode = new Decision();
+            	newNode.setDecisionConditions(jPDLdecision.getDecisionConditions());
+            	// TODO: unable to access decisionDelegation
+            	// TODO: unable to access decisionExpression
+            	node = newNode;
+            } else if (jPDLnode instanceof org.jbpm.graph.node.ProcessState) {
+            	org.jbpm.graph.node.ProcessState jPDLprocessState =
+                    (org.jbpm.graph.node.ProcessState) jPDLnode; 
+            	ProcessState newNode = new ProcessState();
+            	ProcessDefinition subProcessDefinition = 
+            		jPDLprocessState.getSubProcessDefinition();
+            	if (subProcessDefinition != null) {
+            		newNode.setSubProcessName(subProcessDefinition.getName());
+            		// TODO: parse sub process definition as well
+            	}
+            	// TODO: unable to access subProcessName
+            	// TODO: unable to access variableAccesses
+            	node = newNode;
+            } else if (jPDLnode instanceof org.jbpm.graph.node.TaskNode) {
+            	org.jbpm.graph.node.TaskNode jPDLtaskNode =
+                    (org.jbpm.graph.node.TaskNode) jPDLnode; 
+            	TaskNode newNode = new TaskNode();
+            	Set<Task> tasks = jPDLtaskNode.getTasks();
+            	newNode.setTasks(tasks);
+            	newNode.setSignal(jPDLtaskNode.getSignal());
+            	newNode.setCreateTasks(jPDLtaskNode.getCreateTasks());
+            	newNode.setEndTasks(jPDLtaskNode.isEndTasks());
+            	for (Task task: tasks) {
+            	    org.jbpm.taskmgmt.def.Swimlane jPDLswimlane = task.getSwimlane();
+            	    if (jPDLswimlane != null) {
+            	        String swimlaneName = jPDLswimlane.getName();
+            	        if (swimlaneContext.getSwimlane(swimlaneName) == null) {
+            	            Swimlane swimlane = new Swimlane(swimlaneName);
+            	            swimlane.setActorId(jPDLswimlane.getActorIdExpression());
+            	            // TODO support other types of actor expressions as well
+            	            swimlaneContext.addSwimlane(swimlane);
+            	        }
+            	    }
+            	}
+            	node = newNode;
+            } else if (jPDLnode instanceof org.jbpm.graph.node.State) {
+            	node = new State();
+            }
+            if (node == null) {
+                throw new IllegalArgumentException(
+                    "Unknown node type: " + jPDLnode.getClass().getName() + " " + jPDLnode);
+            }
+            setDefaultNodeProperties(jPDLnode, (JpdlNode) node);
+            node.setId(++nodeId);
+            mapping.put(jPDLnode, node);
+            process.addNode(node);
+            if (startStateName != null && startStateName.equals(node.getName())) {
+                process.setStartState(node);
+            }
+        }
+        
+        for (Map.Entry<org.jbpm.graph.def.Node, Node> entry: mapping.entrySet()) {
+            List<org.jbpm.graph.def.Transition> leavingTransitions =
+                (List<org.jbpm.graph.def.Transition>) entry.getKey().getLeavingTransitions();
+            if (leavingTransitions != null) {
+                for (org.jbpm.graph.def.Transition transition: leavingTransitions) {
+                    Node from = mapping.get(transition.getFrom());
+                    Node to = mapping.get(transition.getTo());
+                    String transitionName = transition.getName();
+                    if (transitionName == null) {
+                        transitionName = Node.CONNECTION_DEFAULT_TYPE;
+                    }
+                    // TODO: transition condition, events and exception handlers
+                    JpdlConnection connection =
+                        new JpdlConnection(from, transitionName, to, Node.CONNECTION_DEFAULT_TYPE);
+                    Map<String, Event> events = transition.getEvents();
+                    if (events != null) {
+                        for (Event event: events.values()) {
+                            connection.addEvent(event);
+                        }
+                    }
+                    List<ExceptionHandler> exceptionHandlers = transition.getExceptionHandlers();
+                    if (exceptionHandlers != null) {
+                        for (ExceptionHandler exceptionHandler: exceptionHandlers) {
+                            connection.addExceptionHandler(exceptionHandler);
+                        }
+                    }
+                    connection.setCondition(transition.getCondition());
+                }
+            }
+        }
+        
+        errors = JpdlProcessValidator.getInstance().validateProcess(process);
+        return process;
+    }
+    
+    private void setDefaultNodeProperties(org.jbpm.graph.def.Node jPDLnode, JpdlNode newNode) {
+        newNode.setName(jPDLnode.getName());
+        newNode.setAction(jPDLnode.getAction());
+        Map<String, Event> events = jPDLnode.getEvents();
+        if (events != null) {
+            for (Event event: events.values()) {
+                newNode.addEvent(event);
+                // TODO: extract timer actions and replace by our timer framework
+            }
+        }
+        List<ExceptionHandler> exceptionHandlers = jPDLnode.getExceptionHandlers();
+        if (exceptionHandlers != null) {
+            for (ExceptionHandler exceptionHandler: exceptionHandlers) {
+                newNode.addExceptionHandler(exceptionHandler);
+            }
+        }
+    }
+    
+    public ProcessValidationError[] getErrors() {
+        return this.errors;
+    }
+    
+}

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/JpdlProcessValidator.java
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/JpdlProcessValidator.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/JpdlProcessValidator.java	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,325 @@
+package org.drools.jpdl;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.jpdl.core.JpdlProcess;
+import org.drools.jpdl.core.node.EndState;
+import org.drools.jpdl.core.node.StartState;
+import org.drools.process.core.Process;
+import org.drools.process.core.Work;
+import org.drools.process.core.context.variable.Variable;
+import org.drools.process.core.validation.ProcessValidationError;
+import org.drools.process.core.validation.ProcessValidator;
+import org.drools.process.core.validation.impl.ProcessValidationErrorImpl;
+import org.drools.workflow.core.Connection;
+import org.drools.workflow.core.Node;
+import org.drools.workflow.core.impl.DroolsConsequenceAction;
+import org.drools.workflow.core.node.ActionNode;
+import org.drools.workflow.core.node.CompositeNode;
+import org.drools.workflow.core.node.Join;
+import org.drools.workflow.core.node.MilestoneNode;
+import org.drools.workflow.core.node.RuleSetNode;
+import org.drools.workflow.core.node.Split;
+import org.drools.workflow.core.node.SubProcessNode;
+import org.drools.workflow.core.node.WorkItemNode;
+import org.mvel.ErrorDetail;
+import org.mvel.ParserContext;
+import org.mvel.compiler.ExpressionCompiler;
+
+public class JpdlProcessValidator implements ProcessValidator {
+    
+    private static JpdlProcessValidator instance;
+
+    private JpdlProcessValidator() {
+    }
+
+    public static JpdlProcessValidator getInstance() {
+        if ( instance == null ) {
+            instance = new JpdlProcessValidator();
+        }
+        return instance;
+    }
+
+    public ProcessValidationError[] validateProcess(final JpdlProcess process) {
+        final List<ProcessValidationError> errors = new ArrayList<ProcessValidationError>();
+
+        if (process.getName() == null) {
+            errors.add(new ProcessValidationErrorImpl(process,
+                "Process has no name."));
+        }
+
+        if (process.getId() == null || "".equals(process.getId())) {
+            errors.add(new ProcessValidationErrorImpl(process,
+                "Process has no id."));
+        }
+
+        if ( process.getPackageName() == null || "".equals( process.getPackageName() ) ) {
+            errors.add(new ProcessValidationErrorImpl(process,
+                "Process has no package name."));
+        }
+
+        final Node[] nodes = process.getNodes();
+        validateNodes(nodes, errors, process);
+        Node startNode = process.getStart();
+        if (startNode == null) {
+            errors.add(new ProcessValidationErrorImpl(process,
+                "Process has no start node."));
+        }
+        for (final Iterator<Variable> it = process.getVariableScope().getVariables().iterator(); it.hasNext(); ) {
+            final Variable variable = it.next();
+            if (variable.getType() == null) {
+                errors.add(new ProcessValidationErrorImpl(process,
+                    "Variable '" + variable.getName() + "' has no type."));
+            }
+        }
+
+        checkAllNodesConnectedToStart(process, errors);
+
+        return errors.toArray(new ProcessValidationError[errors.size()]);
+    }
+    
+    private void validateNodes(Node[] nodes, List<ProcessValidationError> errors, JpdlProcess process) {
+        for ( int i = 0; i < nodes.length; i++ ) {
+            final Node node = nodes[i];
+            if (node instanceof StartState) {
+                final StartState startState = (StartState) node;
+                if (startState.getOutgoingConnections().size() != 1) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "Start state '" + node.getName() + "' [" + node.getId() + "] has more than one type of outgoing connections."));
+                }
+                List<Connection> connections = startState.getOutgoingConnections(Node.CONNECTION_DEFAULT_TYPE);  
+                if (connections == null || connections.size() == 0) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "Start state '" + node.getName() + "' [" + node.getId() + "] has no default outgoing connections."));
+                }
+                if (connections.size() != 1) {
+                	errors.add(new ProcessValidationErrorImpl(process,
+                        "Start state '" + node.getName() + "' [" + node.getId() + "] has more than one default outgoing connection."));
+                }
+            } else if (node instanceof EndState) {
+                final EndState endState = (EndState) node;
+                if (endState.getIncomingConnections().size() != 1) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "End state '" + node.getName() + "' [" + node.getId() + "] has more than one type of incoming connections."));
+                }
+                List<Connection> connections = endState.getIncomingConnections(Node.CONNECTION_DEFAULT_TYPE);  
+                if (connections == null || connections.size() == 0) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "End state '" + node.getName() + "' [" + node.getId() + "] has no default incoming connections."));
+                }
+                if (connections.size() != 1) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "End state '" + node.getName() + "' [" + node.getId() + "] has more than one default incoming connection."));
+                }
+            } else if (node instanceof RuleSetNode) {
+                final RuleSetNode ruleSetNode = (RuleSetNode) node;
+                if (ruleSetNode.getFrom() == null) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "RuleSet node '" + node.getName() + "' [" + node.getId() + "] has no incoming connection."));
+                }
+                if (ruleSetNode.getTo() == null) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "RuleSet node '" + node.getName() + "' [" + node.getId() + "] has no outgoing connection."));
+                }
+                final String ruleFlowGroup = ruleSetNode.getRuleFlowGroup();
+                if (ruleFlowGroup == null || "".equals(ruleFlowGroup)) {
+                    errors.add( new ProcessValidationErrorImpl(process,
+                        "RuleSet node '" + node.getName() + "' [" + node.getId() + "] has no ruleflow-group."));
+                }
+            } else if (node instanceof Split) {
+                final Split split = (Split) node;
+                if (split.getType() == Split.TYPE_UNDEFINED) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "Split node '" + node.getName() + "' [" + node.getId() + "] has no type."));
+                }
+                if (split.getFrom() == null) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "Split node '" + node.getName() + "' [" + node.getId() + "] has no incoming connection."));
+                }
+                if (split.getDefaultOutgoingConnections().size() < 2) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "Split node '" + node.getName() + "' [" + node.getId() + "] does not have more than one outgoing connection: " + split.getOutgoingConnections().size() + "."));
+                }
+                if (split.getType() == Split.TYPE_XOR || split.getType() == Split.TYPE_OR ) {
+                    for ( final Iterator<Connection> it = split.getDefaultOutgoingConnections().iterator(); it.hasNext(); ) {
+                        final Connection connection = it.next();
+                        if (split.getConstraint(connection) == null) {
+                            errors.add(new ProcessValidationErrorImpl(process,
+                                "Split node '" + node.getName() + "' [" + node.getId() + "] does not have a constraint for " + connection.toString() + "."));
+                        }
+                    }
+                }
+            } else if ( node instanceof Join ) {
+                final Join join = (Join) node;
+                if (join.getType() == Join.TYPE_UNDEFINED) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "Join node '" + node.getName() + "' [" + node.getId() + "] has no type."));
+                }
+                if (join.getDefaultIncomingConnections().size() < 2) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "Join node '" + node.getName() + "' [" + node.getId() + "] does not have more than one incoming connection: " + join.getIncomingConnections().size() + "."));
+                }
+                if (join.getTo() == null) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "Join node '" + node.getName() + "' [" + node.getId() + "] has no outgoing connection."));
+                }
+            } else if (node instanceof MilestoneNode) {
+                final MilestoneNode milestone = (MilestoneNode) node;
+                if (milestone.getFrom() == null) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "Milestone node '" + node.getName() + "' [" + node.getId() + "] has no incoming connection."));
+                }
+
+                if (milestone.getTo() == null) {
+                    errors.add( new ProcessValidationErrorImpl(process,
+                        "Milestone node '" + node.getName() + "' [" + node.getId() + "] has no outgoing connection."));
+                }
+                if (milestone.getConstraint() == null) {
+                    errors.add( new ProcessValidationErrorImpl(process,
+                        "Milestone node '" + node.getName() + "' [" + node.getId() + "] has no constraint."));
+                }
+            } else if (node instanceof SubProcessNode) {
+                final SubProcessNode subProcess = (SubProcessNode) node;
+                if (subProcess.getFrom() == null) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "SubProcess node '" + node.getName() + "' [" + node.getId() + "] has no incoming connection."));
+                }
+                if (subProcess.getTo() == null) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "SubProcess node '" + node.getName() + "' [" + node.getId() + "] has no outgoing connection."));
+                }
+                if (subProcess.getProcessId() == null) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "SubProcess node '" + node.getName() + "' [" + node.getId() + "] has no process id."));
+                }
+            } else if (node instanceof ActionNode) {
+                final ActionNode actionNode = (ActionNode) node;
+                if (actionNode.getFrom() == null) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "Action node '" + node.getName() + "' [" + node.getId() + "] has no incoming connection."));
+                }
+                if (actionNode.getTo() == null) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "Action node '" + node.getName() + "' [" + node.getId() + "] has no outgoing connection."));
+                }
+                if (actionNode.getAction() == null) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "Action node '" + node.getName() + "' [" + node.getId() + "] has no action."));
+                } else {
+                    if (actionNode.getAction() instanceof DroolsConsequenceAction) {
+                        DroolsConsequenceAction droolsAction = (DroolsConsequenceAction) actionNode.getAction();
+                        String actionString = droolsAction.getConsequence();
+                        if (actionString == null) {
+                            errors.add(new ProcessValidationErrorImpl(process,
+                                "Action node '" + node.getName() + "' [" + node.getId() + "] has empty action."));
+                        } else {
+                            try {
+                                ExpressionCompiler compiler = new ExpressionCompiler(actionString);
+                                compiler.setVerifying(true);
+                                ParserContext parserContext = new ParserContext();
+                                //parserContext.setStrictTypeEnforcement(true);
+                                compiler.compile(parserContext);
+                                List<ErrorDetail> mvelErrors = parserContext.getErrorList();
+                                if (mvelErrors != null) {
+                                    for (Iterator<ErrorDetail> iterator = mvelErrors.iterator(); iterator.hasNext(); ) {
+                                        ErrorDetail error = iterator.next();
+                                        errors.add(new ProcessValidationErrorImpl(process,
+                                            "Action node '" + node.getName() + "' [" + node.getId() + "] has invalid action: " + error.getMessage() + "."));
+                                    }
+                                }
+                            } catch (Throwable t) {
+                                errors.add(new ProcessValidationErrorImpl(process,
+                                    "Action node '" + node.getName() + "' [" + node.getId() + "] has invalid action: " + t.getMessage() + "."));
+                            }
+                        }
+                    }
+                }
+            } else if (node instanceof WorkItemNode) {
+                final WorkItemNode workItemNode = (WorkItemNode) node;
+                if (workItemNode.getFrom() == null) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "WorkItem node '" + node.getName() + "' [" + node.getId() + "] has no incoming connection."));
+                }
+                if (workItemNode.getTo() == null) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "WorkItem node '" + node.getName() + "' [" + node.getId() + "] has no outgoing connection."));
+                }
+                if (workItemNode.getWork() == null) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "WorkItem node '" + node.getName() + "' [" + node.getId() + "] has no work specified."));
+                } else {
+                    Work work = workItemNode.getWork();
+                    if (work.getName() == null) {
+                        errors.add(new ProcessValidationErrorImpl(process,
+                            "WorkItem node '" + node.getName() + "' [" + node.getId() + "] has no work name."));
+                    }
+                }
+            } else if (node instanceof CompositeNode) {
+                final CompositeNode compositeNode = (CompositeNode) node;
+                for (String inType: compositeNode.getLinkedIncomingNodes().keySet()) {
+                    if (compositeNode.getIncomingConnections(inType).size() == 0) {
+                        errors.add(new ProcessValidationErrorImpl(process,
+                            "Composite node '" + node.getName() + "' [" + node.getId() + "] has no incoming connection for type " + inType));
+                    }
+                }
+                for (String outType: compositeNode.getLinkedOutgoingNodes().keySet()) {
+                    if (compositeNode.getOutgoingConnections(outType).size() == 0) {
+                        errors.add(new ProcessValidationErrorImpl(process,
+                            "Composite node '" + node.getName() + "' [" + node.getId() + "] has no outgoing connection for type " + outType));
+                    }
+                }
+                validateNodes(compositeNode.getNodes(), errors, process);
+            } 
+        }
+
+    }
+
+    private void checkAllNodesConnectedToStart(final JpdlProcess process,
+                                               final List<ProcessValidationError> errors) {
+        final Map<Node, Boolean> processNodes = new HashMap<Node, Boolean>();
+        final Node[] nodes = process.getNodes();
+        for (int i = 0; i < nodes.length; i++) {
+            final Node node = nodes[i];
+            processNodes.put(node, Boolean.FALSE);
+        }
+        Node startNode = process.getStart();
+        if (startNode != null) {
+            processNode(startNode, processNodes);
+        }
+        for ( final Iterator<Node> it = processNodes.keySet().iterator(); it.hasNext(); ) {
+            final Node node = it.next();
+            if (Boolean.FALSE.equals(processNodes.get(node))) {
+                errors.add(new ProcessValidationErrorImpl(process,
+                    "Node '" + node.getName() + "' [" + node.getId() + "] has no connection to the start node."));
+            }
+        }
+    }
+
+    private void processNode(final Node node, final Map<Node, Boolean> nodes) {
+        if (!nodes.containsKey(node) ) {
+            throw new IllegalStateException("A process node is connected with a node that does not belong to the process.");
+        }
+        final Boolean prevValue = (Boolean) nodes.put(node, Boolean.TRUE);
+        if (prevValue == Boolean.FALSE) {
+            for (final Iterator<List<Connection>> it = node.getOutgoingConnections().values().iterator(); it.hasNext(); ) {
+                final List<Connection> list = it.next();
+                for (final Iterator<Connection> it2 = list.iterator(); it2.hasNext(); ) {
+                    processNode(it2.next().getTo(), nodes);
+                }
+            }
+        }
+    }
+
+    public ProcessValidationError[] validateProcess(Process process) {
+        if (!(process instanceof JpdlProcess)) {
+            throw new IllegalArgumentException(
+                "This validator can only validate ruleflow processes!");
+        }
+        return validateProcess((JpdlProcess) process);
+    }
+
+}

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/JpdlConnection.java
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/JpdlConnection.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/JpdlConnection.java	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,115 @@
+package org.drools.jpdl.core;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.workflow.core.Node;
+import org.drools.workflow.core.impl.ConnectionImpl;
+import org.jbpm.graph.def.Event;
+import org.jbpm.graph.def.ExceptionHandler;
+
+public class JpdlConnection extends ConnectionImpl {
+
+    private static final long serialVersionUID = 1L;
+
+    protected String condition;
+    private Map<String, Event> events;
+    private List<ExceptionHandler> exceptionHandlers;
+    
+    public JpdlConnection(Node from, String fromType, Node to, String toType) {
+        super(from, fromType, to, toType);
+    }
+
+    public Map<String, Event> getEvents() {
+        return events;
+    }
+
+    public boolean hasEvents() {
+        return (events != null) && (events.size() > 0);
+    }
+
+    public Event getEvent(String eventType) {
+        Event event = null;
+        if (events != null) {
+            event = (Event) events.get(eventType);
+        }
+        return event;
+    }
+
+    public boolean hasEvent(String eventType) {
+        boolean hasEvent = false;
+        if (events != null) {
+            hasEvent = events.containsKey(eventType);
+        }
+        return hasEvent;
+    }
+
+    public Event addEvent(Event event) {
+        if (event == null) {
+            throw new IllegalArgumentException(
+                "can't add a null event to a graph element");
+        }
+        if (event.getEventType() == null) {
+            throw new IllegalArgumentException(
+                "can't add an event without an eventType to a graph element");
+        }
+        if (events == null) {
+            events = new HashMap<String, Event>();
+        }
+        events.put(event.getEventType(), event);
+        return event;
+    }
+
+    public Event removeEvent(Event event) {
+        Event removedEvent = null;
+        if (event == null) {
+            throw new IllegalArgumentException(
+                "can't remove a null event from a graph element");
+        }
+        if (event.getEventType() == null) {
+            throw new IllegalArgumentException(
+                "can't remove an event without an eventType from a graph element");
+        }
+        if (events != null) {
+            removedEvent = (Event) events.remove(event.getEventType());
+        }
+        return removedEvent;
+    }
+    
+    public List getExceptionHandlers() {
+        return exceptionHandlers;
+    }
+      
+    public ExceptionHandler addExceptionHandler(ExceptionHandler exceptionHandler) {
+        if (exceptionHandler == null) {
+            throw new IllegalArgumentException(
+                "can't add a null exceptionHandler to a connection");
+        }
+        if (exceptionHandlers == null) {
+            exceptionHandlers = new ArrayList<ExceptionHandler>();
+        }
+        exceptionHandlers.add(exceptionHandler);
+        return exceptionHandler;
+    }
+
+    public void removeExceptionHandler(ExceptionHandler exceptionHandler) {
+        if (exceptionHandler == null) {
+            throw new IllegalArgumentException(
+                "can't remove a null exceptionHandler from a connection");
+        }
+        if (exceptionHandlers != null) {
+            exceptionHandlers.remove(exceptionHandler);
+        }
+    }
+
+    public String getCondition() {
+        return condition;
+    }
+
+    public void setCondition(String condition) {
+        this.condition = condition;
+    }
+
+}

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/JpdlProcess.java
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/JpdlProcess.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/JpdlProcess.java	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,44 @@
+package org.drools.jpdl.core;
+
+import org.drools.jpdl.core.node.StartState;
+import org.drools.process.core.context.variable.VariableScope;
+import org.drools.workflow.core.Node;
+import org.drools.workflow.core.impl.WorkflowProcessImpl;
+
+public class JpdlProcess extends WorkflowProcessImpl {
+
+    public static final String JPDL_TYPE = "jPDL";
+
+	private static final long serialVersionUID = 1L;
+	
+	private Node startState;
+
+    public JpdlProcess() {
+        setType(JPDL_TYPE);
+        VariableScope variableScope = new VariableScope();
+        addContext(variableScope);
+        setDefaultContext(variableScope);
+    }
+    
+    public void setStartState(Node startState) {
+        this.startState = startState;
+    }
+    
+    public Node getStart() {
+        if (startState != null) {
+            return startState;
+        }
+        Node[] nodes = getNodes();
+        for (int i = 0; i < nodes.length; i++) {
+            if (nodes[i] instanceof StartState) {
+                return (StartState) nodes[i];
+            }
+        }
+        return null;
+    }
+
+    public VariableScope getVariableScope() {
+        return (VariableScope) getDefaultContext(VariableScope.VARIABLE_SCOPE);
+    }
+
+}

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/Decision.java
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/Decision.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/Decision.java	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,40 @@
+package org.drools.jpdl.core.node;
+
+import java.util.List;
+
+import org.jbpm.graph.node.DecisionCondition;
+import org.jbpm.instantiation.Delegation;
+
+public class Decision extends JpdlNode {
+
+	private static final long serialVersionUID = 1L;
+
+	private List<DecisionCondition> decisionConditions;
+	private Delegation decisionDelegation;
+	private String decisionExpression;
+
+	public List<DecisionCondition> getDecisionConditions() {
+		return decisionConditions;
+	}
+
+	public void setDecisionConditions(List<DecisionCondition> decisionConditions) {
+		this.decisionConditions = decisionConditions;
+	}
+
+	public Delegation getDecisionDelegation() {
+		return decisionDelegation;
+	}
+
+	public void setDecisionDelegation(Delegation decisionDelegation) {
+		this.decisionDelegation = decisionDelegation;
+	}
+
+	public String getDecisionExpression() {
+		return decisionExpression;
+	}
+
+	public void setDecisionExpression(String decisionExpression) {
+		this.decisionExpression = decisionExpression;
+	}
+
+}

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/EndState.java
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/EndState.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/EndState.java	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,19 @@
+package org.drools.jpdl.core.node;
+
+import org.drools.workflow.core.Connection;
+
+public class EndState extends JpdlNode {
+
+	private static final long serialVersionUID = 1L;
+
+    public void validateAddOutgoingConnection(final String type, final Connection connection) {
+        throw new UnsupportedOperationException(
+            "An end state does not have an outgoing connection!");
+    }
+
+    public void validateRemoveOutgoingConnection(final String type, final Connection connection) {
+        throw new UnsupportedOperationException(
+            "An end state does not have an outgoing connection!");
+    }
+    
+}

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/Fork.java
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/Fork.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/Fork.java	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,19 @@
+package org.drools.jpdl.core.node;
+
+import org.jbpm.graph.action.Script;
+
+public class Fork extends JpdlNode {
+
+    private static final long serialVersionUID = 1L;
+    
+    private Script script;
+
+    public Script getScript() {
+        return script;
+    }
+
+    public void setScript(Script script) {
+        this.script = script;
+    }
+    
+}

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/Join.java
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/Join.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/Join.java	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,57 @@
+package org.drools.jpdl.core.node;
+
+import java.util.Collection;
+
+import org.jbpm.graph.action.Script;
+
+public class Join extends JpdlNode {
+
+    private static final long serialVersionUID = 1L;
+    
+    private String parentLockMode;
+    private boolean isDiscriminator = false;
+    private Collection<String> tokenNames = null;
+    private Script script = null;
+    private int nOutOfM = -1;
+    
+    public String getParentLockMode() {
+        return parentLockMode;
+    }
+    
+    public void setParentLockMode(String parentLockMode) {
+        this.parentLockMode = parentLockMode;
+    }
+    
+    public boolean isDiscriminator() {
+        return isDiscriminator;
+    }
+    
+    public void setDiscriminator(boolean isDiscriminator) {
+        this.isDiscriminator = isDiscriminator;
+    }
+    
+    public Collection<String> getTokenNames() {
+        return tokenNames;
+    }
+    
+    public void setTokenNames(Collection<String> tokenNames) {
+        this.tokenNames = tokenNames;
+    }
+    
+    public Script getScript() {
+        return script;
+    }
+    
+    public void setScript(Script script) {
+        this.script = script;
+    }
+    
+    public int getNOutOfM() {
+        return nOutOfM;
+    }
+    
+    public void setNOutOfM(int outOfM) {
+        nOutOfM = outOfM;
+    }
+
+}

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/JpdlNode.java
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/JpdlNode.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/JpdlNode.java	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,131 @@
+package org.drools.jpdl.core.node;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.process.core.context.exception.ExceptionScope;
+import org.drools.workflow.core.Connection;
+import org.drools.workflow.core.impl.NodeImpl;
+import org.jbpm.graph.def.Action;
+import org.jbpm.graph.def.Event;
+import org.jbpm.graph.def.ExceptionHandler;
+
+public class JpdlNode extends NodeImpl {
+
+	private static final long serialVersionUID = 1L;
+
+	private Map<String, Event> events;
+	private Action action;
+	
+	public JpdlNode() {
+		setContext(ExceptionScope.EXCEPTION_SCOPE, new ExceptionScope());
+	}
+
+	public Action getAction() {
+		return action;
+	}
+
+	public void setAction(Action action) {
+		this.action = action;
+	}
+	
+	public Connection getOutgoingConnection(String type) {
+		List<Connection> connections = getOutgoingConnections(type);
+		if (connections == null || connections.size() == 0) {
+			return null;
+		}
+		return connections.get(0);
+	}
+
+	public Map<String, Event> getEvents() {
+		return events;
+	}
+
+	public boolean hasEvents() {
+		return (events != null) && (events.size() > 0);
+	}
+
+	public Event getEvent(String eventType) {
+		Event event = null;
+		if (events != null) {
+			event = (Event) events.get(eventType);
+		}
+		return event;
+	}
+
+	public boolean hasEvent(String eventType) {
+		boolean hasEvent = false;
+		if (events != null) {
+			hasEvent = events.containsKey(eventType);
+		}
+		return hasEvent;
+	}
+
+	public Event addEvent(Event event) {
+		if (event == null) {
+			throw new IllegalArgumentException(
+				"can't add a null event to a graph element");
+		}
+		if (event.getEventType() == null) {
+			throw new IllegalArgumentException(
+				"can't add an event without an eventType to a graph element");
+		}
+		if (events == null) {
+			events = new HashMap<String, Event>();
+		}
+		events.put(event.getEventType(), event);
+		return event;
+	}
+
+	public Event removeEvent(Event event) {
+		Event removedEvent = null;
+		if (event == null) {
+			throw new IllegalArgumentException(
+				"can't remove a null event from a graph element");
+		}
+		if (event.getEventType() == null) {
+			throw new IllegalArgumentException(
+				"can't remove an event without an eventType from a graph element");
+		}
+		if (events != null) {
+			removedEvent = (Event) events.remove(event.getEventType());
+		}
+		return removedEvent;
+	}
+	
+	public ExceptionScope getExceptionScope() {
+		return (ExceptionScope) getContext(ExceptionScope.EXCEPTION_SCOPE);
+	}
+
+	public ExceptionHandler addExceptionHandler(ExceptionHandler exceptionHandler) {
+		if (exceptionHandler == null) {
+			throw new IllegalArgumentException(
+				"can't add a null exceptionHandler to a graph element");
+		}
+		getExceptionScope().setExceptionHandler(
+			exceptionHandler.getExceptionClassName(),
+			new JpdlExceptionHandler(exceptionHandler));
+		return exceptionHandler;
+	}
+
+	public void removeExceptionHandler(ExceptionHandler exceptionHandler) {
+		if (exceptionHandler == null) {
+			throw new IllegalArgumentException(
+				"can't remove a null exceptionHandler from an graph element");
+		}
+		getExceptionScope().removeExceptionHandler(
+			exceptionHandler.getExceptionClassName());
+	}
+
+	private class JpdlExceptionHandler implements org.drools.process.core.context.exception.ExceptionHandler {
+		private ExceptionHandler exceptionHandler;
+		private JpdlExceptionHandler(ExceptionHandler exceptionHandler) {
+			this.exceptionHandler = exceptionHandler;
+		}
+		public ExceptionHandler getExceptionHandler() {
+			return exceptionHandler;
+		}
+	}
+
+}

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/MailNode.java
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/MailNode.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/MailNode.java	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,53 @@
+package org.drools.jpdl.core.node;
+
+public class MailNode extends JpdlNode {
+
+    private static final long serialVersionUID = 1L;
+    
+    private String template;
+    private String actors;
+    private String to;
+    private String subject;
+    private String text;
+    
+    public String getTemplate() {
+        return template;
+    }
+    
+    public void setTemplate(String template) {
+        this.template = template;
+    }
+    
+    public String getActors() {
+        return actors;
+    }
+    
+    public void setActors(String actors) {
+        this.actors = actors;
+    }
+    
+    public String getTo() {
+        return to;
+    }
+    
+    public void setTo(String to) {
+        this.to = to;
+    }
+    
+    public String getSubject() {
+        return subject;
+    }
+    
+    public void setSubject(String subject) {
+        this.subject = subject;
+    }
+    
+    public String getText() {
+        return text;
+    }
+    
+    public void setText(String text) {
+        this.text = text;
+    }
+    
+}

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/ProcessState.java
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/ProcessState.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/ProcessState.java	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,30 @@
+package org.drools.jpdl.core.node;
+
+import java.util.Set;
+
+import org.jbpm.context.def.VariableAccess;
+
+public class ProcessState extends JpdlNode {
+
+	private static final long serialVersionUID = 1L;
+	
+	private Set<VariableAccess> variableAccesses;
+	private String subProcessName;
+	
+	public Set<VariableAccess> getVariableAccesses() {
+		return variableAccesses;
+	}
+	
+	public void setVariableAccesses(Set<VariableAccess> variableAccesses) {
+		this.variableAccesses = variableAccesses;
+	}
+	
+	public String getSubProcessName() {
+		return subProcessName;
+	}
+	
+	public void setSubProcessName(String subProcessName) {
+		this.subProcessName = subProcessName;
+	}
+
+}

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/StartState.java
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/StartState.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/StartState.java	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,19 @@
+package org.drools.jpdl.core.node;
+
+import org.drools.workflow.core.Connection;
+
+public class StartState extends JpdlNode {
+
+	private static final long serialVersionUID = 1L;
+
+    public void validateAddIncomingConnection(final String type, final Connection connection) {
+        throw new UnsupportedOperationException(
+            "A start state does not have an incoming connection!");
+    }
+
+    public void validateRemoveIncomingConnection(final String type, final Connection connection) {
+        throw new UnsupportedOperationException(
+            "A start state does not have an incoming connection!");
+    }
+
+}

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/State.java
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/State.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/State.java	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,7 @@
+package org.drools.jpdl.core.node;
+
+public class State extends JpdlNode {
+
+	private static final long serialVersionUID = 1L;
+
+}

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/TaskNode.java
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/TaskNode.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/core/node/TaskNode.java	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,48 @@
+package org.drools.jpdl.core.node;
+
+import java.util.Set;
+
+import org.jbpm.taskmgmt.def.Task;
+
+public class TaskNode extends JpdlNode {
+
+	private static final long serialVersionUID = 1L;
+
+	private Set<Task> tasks;
+	private int signal = org.jbpm.graph.node.TaskNode.SIGNAL_LAST;
+	private boolean createTasks = true;
+	private boolean endTasks = false;
+	
+	public Set<Task> getTasks() {
+		return tasks;
+	}
+	
+	public void setTasks(Set<Task> tasks) {
+		this.tasks = tasks;
+	}
+	
+	public int getSignal() {
+		return signal;
+	}
+	
+	public void setSignal(int signal) {
+		this.signal = signal;
+	}
+	
+	public boolean isCreateTasks() {
+		return createTasks;
+	}
+	
+	public void setCreateTasks(boolean createTasks) {
+		this.createTasks = createTasks;
+	}
+	
+	public boolean isEndTasks() {
+		return endTasks;
+	}
+	
+	public void setEndTasks(boolean endTasks) {
+		this.endTasks = endTasks;
+	}
+	  
+}

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/JpdlProcessInstance.java
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/JpdlProcessInstance.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/JpdlProcessInstance.java	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,18 @@
+package org.drools.jpdl.instance;
+
+import org.drools.jpdl.core.JpdlProcess;
+import org.drools.workflow.instance.impl.WorkflowProcessInstanceImpl;
+
+public class JpdlProcessInstance extends WorkflowProcessInstanceImpl {
+
+	private static final long serialVersionUID = 1L;
+
+	public JpdlProcess getJpdlProcess() {
+		return (JpdlProcess) getProcess();
+	}
+	
+    public void internalStart() {
+        getNodeInstance( getJpdlProcess().getStart() ).trigger( null, null );
+    }
+
+}

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/JpdlProcessInstanceFactory.java
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/JpdlProcessInstanceFactory.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/JpdlProcessInstanceFactory.java	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,26 @@
+package org.drools.jpdl.instance;
+
+import java.io.Externalizable;
+import java.io.ObjectOutput;
+import java.io.IOException;
+import java.io.ObjectInput;
+
+import org.drools.process.instance.ProcessInstance;
+import org.drools.process.instance.ProcessInstanceFactory;
+
+public class JpdlProcessInstanceFactory implements ProcessInstanceFactory, Externalizable {
+
+    private static final long serialVersionUID = 1L;
+
+    public ProcessInstance createProcessInstance() {
+        return new JpdlProcessInstance();
+    }
+
+    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+    }
+
+    public void writeExternal(ObjectOutput out) throws IOException {
+    }
+
+
+}

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/DecisionInstance.java
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/DecisionInstance.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/DecisionInstance.java	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,68 @@
+package org.drools.jpdl.instance.node;
+
+import org.drools.jpdl.core.node.Decision;
+import org.drools.workflow.instance.NodeInstance;
+import org.jbpm.JbpmException;
+import org.jbpm.graph.node.DecisionCondition;
+import org.jbpm.graph.node.DecisionHandler;
+import org.jbpm.instantiation.Delegation;
+import org.jbpm.jpdl.el.impl.JbpmExpressionEvaluator;
+
+public class DecisionInstance extends JpdlNodeInstance {
+
+	private static final long serialVersionUID = 1L;
+
+    public Decision getDecision() {
+        return (Decision) getNode();
+    }
+
+    public void execute(NodeInstance from, String type) {
+    	String transitionName = null;
+    	try {
+    		Delegation decisionDelegation = getDecision().getDecisionDelegation();
+    		if (decisionDelegation != null) {
+    			DecisionHandler decisionHandler = (DecisionHandler) decisionDelegation.instantiate();
+    			transitionName = decisionHandler.decide(new JpdlExecutionContext());
+    		} else if (getDecision().getDecisionExpression() != null) {
+    			String decisionExpression = getDecision().getDecisionExpression();
+    			Object result = JbpmExpressionEvaluator.evaluate(
+					decisionExpression, new JpdlExecutionContext());
+    			if (result == null) {
+    				throw new JbpmException("decision expression '" + 
+						decisionExpression + "' returned null");
+    			}
+    			transitionName = result.toString();
+    		} else if (getDecision().getDecisionConditions() != null) {
+    			for (DecisionCondition decisionCondition: getDecision().getDecisionConditions()) {
+    				Object result = JbpmExpressionEvaluator.evaluate(
+						decisionCondition.getExpression(), new JpdlExecutionContext());
+    				if (Boolean.TRUE.equals(result)) {
+    					transitionName = decisionCondition.getTransitionName();
+    					break;
+    				}
+    			}
+    		} else {
+    			// TODO
+    			/*Iterator iter = leavingTransitions.iterator();
+    			while (iter.hasNext() && (transition==null)) {
+    				Transition candidate = (Transition) iter.next();
+    				String conditionExpression = candidate.getCondition();
+    				if (conditionExpression!=null) {
+    					Object result = JbpmExpressionEvaluator.evaluate(conditionExpression, executionContext);
+    					if (Boolean.TRUE.equals(result)) {
+    						transition = candidate;
+    					}
+    				}
+    			}*/
+    		}
+    		if (transitionName == null) {
+    			leave();
+    		} else {
+    			leave(transitionName);
+    		}
+    	} catch (Exception exception) {
+    		raiseException(exception);
+    	}
+    }
+
+}

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/EndStateInstance.java
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/EndStateInstance.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/EndStateInstance.java	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,14 @@
+package org.drools.jpdl.instance.node;
+
+import org.drools.process.instance.ProcessInstance;
+
+public class EndStateInstance extends JpdlNodeInstance {
+
+    private static final long serialVersionUID = 1L;
+
+    public void leave() {
+        getNodeInstanceContainer().removeNodeInstance(this);
+        getProcessInstance().setState(ProcessInstance.STATE_COMPLETED);
+    }
+    
+}

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/ForkInstance.java
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/ForkInstance.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/ForkInstance.java	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,48 @@
+package org.drools.jpdl.instance.node;
+
+import java.util.Collection;
+import java.util.Map;
+
+import org.drools.jpdl.core.node.Fork;
+import org.drools.workflow.instance.NodeInstance;
+import org.jbpm.JbpmException;
+import org.jbpm.graph.action.Script;
+
+public class ForkInstance extends JpdlNodeInstance {
+
+    private static final long serialVersionUID = 1L;
+    
+    public Fork getFork() {
+        return (Fork) getNode();
+    }
+
+    public void execute(NodeInstance from, String type) {
+        Collection<String> transitionNames = null;
+        Script script = getFork().getScript();
+        if (script == null) {
+            transitionNames = getNode().getOutgoingConnections().keySet();
+        } else {
+            Map<String, Object> outputMap = null;
+            try {
+                outputMap = script.eval(new JpdlExecutionContext());
+            } catch (Exception e) {
+                this.raiseException(e);
+            }
+            if (outputMap.size() == 1) {
+                Object result = outputMap.values().iterator().next();
+                if (result instanceof Collection) {
+                    transitionNames = (Collection<String>) result;
+                }
+            }
+            if (transitionNames == null) {
+                throw new JbpmException(
+                    "script for fork '" + getNode().getName() +
+                    "' should produce one collection (in one writable variable): " +
+                    transitionNames);
+            }
+        }
+        for (String transitionName: transitionNames) {
+            leave(transitionName);
+        }
+    }
+}

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/JoinInstance.java
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/JoinInstance.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/JoinInstance.java	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,104 @@
+package org.drools.jpdl.instance.node;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.jpdl.core.node.Join;
+import org.drools.workflow.core.Connection;
+import org.drools.workflow.core.Node;
+import org.drools.workflow.instance.NodeInstance;
+import org.jbpm.graph.exe.Token;
+
+public class JoinInstance extends JpdlNodeInstance {
+
+    private static final long serialVersionUID = 1L;
+    
+    private Map<Long, Integer> triggers = new HashMap<Long, Integer>();
+    
+    public Join getJoin() {
+        return (Join) getNode();
+    }
+
+    public void execute(NodeInstance from, String type) {
+        if (getJoin().isDiscriminator()) {
+            leave();
+        } else {
+            // register trigger
+            Integer count = (Integer) this.triggers.get(type);
+            if (count == null) {
+                this.triggers.put(from.getNodeId(), 1);
+            } else {
+                this.triggers.put(from.getNodeId(), count.intValue() + 1);
+            }
+            // check whether we should leave node
+            if (getJoin().getTokenNames() != null) {
+                Collection<String> tokenNames = getJoin().getTokenNames();
+                // TODO: implement this
+//                if (checkTriggers(tokenNames)) {
+//                    decreaseTriggers(tokenNames);
+//                    leave();
+//                }
+            } else if (getJoin().getScript() != null) {
+                Object result = null;
+                try {
+                    result = getJoin().getScript().eval((Token) null);
+                } catch (Exception e) {
+                    this.raiseException(e);
+                }
+                if (result instanceof Collection) {
+                    // TODO: implement this
+//                    Collection<String> runtimeTokenNames = (Collection<String>) result;
+//                    if (checkTriggers(runtimeTokenNames)) {
+//                        decreaseTriggers(runtimeTokenNames);
+//                        leave();
+//                    }
+                } else if (result instanceof Boolean) {
+                    if ((Boolean) result) {
+                        leave();
+                    }
+                }
+            } else if (getJoin().getNOutOfM() != -1) {
+                if (triggers.size() >= getJoin().getNOutOfM()) {
+                    resetAllTriggers();
+                    leave();
+                }
+            } else {
+                // TODO this only works if all incoming connection paths were
+                // activated; fix this in cases where not all incoming connection
+                // paths were activated by letting the corresponding split transfer
+                // the exact number of triggered connections to this join
+                if (checkAllTriggers()) {
+                    decreaseAllTriggers();
+                    leave();
+                }
+            }
+        }
+    }
+    
+    private boolean checkAllTriggers() {
+        for (Connection connection: getJoin().getIncomingConnections(Node.CONNECTION_DEFAULT_TYPE)) {
+            if (this.triggers.get(connection.getFrom().getId()) == null) {
+                return false;
+            }
+        }
+        return true;
+    }
+    
+    private void decreaseAllTriggers() {
+        for (Connection connection: getJoin().getIncomingConnections(Node.CONNECTION_DEFAULT_TYPE)) {
+            final Integer count = (Integer) this.triggers.get( connection.getFrom().getId() );
+            if ( count.intValue() == 1 ) {
+                this.triggers.remove( connection.getFrom().getId() );
+            } else {
+                this.triggers.put( connection.getFrom().getId(),
+                                   count.intValue() - 1 );
+            }
+        }
+    }
+
+    private void resetAllTriggers() {
+        triggers.clear();
+    }
+
+}

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/JpdlNodeInstance.java
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/JpdlNodeInstance.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/JpdlNodeInstance.java	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,277 @@
+package org.drools.jpdl.instance.node;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.jpdl.core.JpdlConnection;
+import org.drools.jpdl.core.node.JpdlNode;
+import org.drools.process.core.context.exception.ExceptionScope;
+import org.drools.process.core.context.variable.VariableScope;
+import org.drools.process.core.timer.Timer;
+import org.drools.process.instance.ProcessInstance;
+import org.drools.process.instance.context.exception.ExceptionScopeInstance;
+import org.drools.process.instance.context.variable.VariableScopeInstance;
+import org.drools.process.instance.timer.TimerListener;
+import org.drools.workflow.core.Node;
+import org.drools.workflow.instance.NodeInstance;
+import org.drools.workflow.instance.impl.NodeInstanceImpl;
+import org.jbpm.JbpmException;
+import org.jbpm.calendar.BusinessCalendar;
+import org.jbpm.calendar.Duration;
+import org.jbpm.graph.def.Action;
+import org.jbpm.graph.def.DelegationException;
+import org.jbpm.graph.def.Event;
+import org.jbpm.graph.def.ExceptionHandler;
+import org.jbpm.graph.def.Transition;
+import org.jbpm.graph.exe.ExecutionContext;
+import org.jbpm.graph.exe.Token;
+import org.jbpm.jpdl.el.impl.JbpmExpressionEvaluator;
+import org.jbpm.scheduler.def.CancelTimerAction;
+import org.jbpm.scheduler.def.CreateTimerAction;
+
+public class JpdlNodeInstance extends NodeInstanceImpl implements TimerListener {
+
+	private static final long serialVersionUID = 1L;
+	private static final BusinessCalendar BUSINESS_CALENDAR = new BusinessCalendar();
+	
+    private Map<Long, Action> timerActions = new HashMap<Long, Action>();
+	private Map<String, List<Timer>> timers = new HashMap<String, List<Timer>>();
+	
+	public JpdlNode getJpdlNode() {
+		return (JpdlNode) getNode();
+	}
+	
+	private Action getAction() {
+		return getJpdlNode().getAction();
+	}
+
+	public void internalTrigger(NodeInstance from, String type) {
+		fireEvent(Event.EVENTTYPE_NODE_ENTER);
+		execute(from, type);
+	}
+	
+	public void execute(NodeInstance from, String type) {
+	    Action action = getAction();
+        if (action != null) {
+            try {
+                action.execute(new JpdlExecutionContext());
+            } catch (Exception exception) {
+                raiseException(exception);
+            }
+        } else {
+            leave();
+        }
+    }
+
+	public void leave() {
+		if (getNode().getOutgoingConnections(Node.CONNECTION_DEFAULT_TYPE) != null) {
+			leave(Node.CONNECTION_DEFAULT_TYPE);
+		} else if (getNode().getOutgoingConnections().size() == 1) {
+			String type = getNode().getOutgoingConnections().keySet().iterator().next() ;
+			leave(type);
+		} else {
+			throw new IllegalArgumentException(
+				"Could not find default leave transition: " + this);
+		}
+	}
+
+	public void leave(String type) {
+		JpdlConnection connection = (JpdlConnection)
+		    getJpdlNode().getOutgoingConnection(type);
+		if (connection == null) {
+			throw new JbpmException("transition '" + type
+				+ "' is not a leaving transition of node '" + this + "'");
+		}
+		fireEvent(Event.EVENTTYPE_NODE_LEAVE);
+        getNodeInstanceContainer().removeNodeInstance(this);
+        Event event = connection.getEvent(Event.EVENTTYPE_TRANSITION);
+        if (event != null) {
+            List<Action> actions = event.getActions();
+            if (actions != null) {
+                for (Action action: actions) {
+                    try {
+                        action.execute(new JpdlExecutionContext());
+                    } catch (Exception exception) {
+                        boolean handled = false;
+                        List<ExceptionHandler> exceptionHandlers = connection.getExceptionHandlers();
+                        try {
+                            for (ExceptionHandler exceptionHandler: exceptionHandlers) {
+                                if (exceptionHandler.matches(exception)) {
+                                    exceptionHandler.handleException(new JpdlExecutionContext());
+                                    handled = true;
+                                }
+                            }
+                        } catch (Exception e) {
+                            exception = e;
+                        }
+                        if (!handled) {
+                            if (exception instanceof JbpmException) {
+                                throw (JbpmException) exception;
+                            } else {
+                                throw new DelegationException(exception, null);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        String condition = connection.getCondition();
+        if (condition != null) {
+            Object result = JbpmExpressionEvaluator.evaluate(
+                condition, new JpdlExecutionContext());
+            if (result == null) {
+                throw new JbpmException("connection condition " + condition
+                        + " evaluated to null");
+            } else if (!(result instanceof Boolean)) {
+                throw new JbpmException("connection condition " + condition
+                        + " evaluated to non-boolean: "
+                        + result.getClass().getName());
+            } else if (!((Boolean) result).booleanValue()) {
+                throw new JbpmException("connection condition " + condition
+                        + " evaluated to 'false'");
+            }
+        }
+        getNodeInstanceContainer().getNodeInstance(connection.getTo())
+            .trigger(this, connection.getToType());
+	}
+
+    public void fireEvent(String eventType) {
+        fireEvent(eventType, new JpdlExecutionContext());
+    }
+
+	public void fireEvent(String eventType, ExecutionContext executionContext) {
+		Event event = getJpdlNode().getEvent(eventType);
+		if (event != null) {
+		    executeActions(event.getActions(), executionContext);
+		}
+		// TODO runtime actions?
+	}
+
+    public void executeActions(List<Action> actions, ExecutionContext executionContext) {
+        if (actions != null) {
+            for (Action action: actions) {
+                executeAction(action, executionContext);
+            }
+        }
+    }
+
+	public void executeAction(Action action, ExecutionContext executionContext) {
+	    if (action instanceof CreateTimerAction) {
+	        CreateTimerAction createTimerAction = (CreateTimerAction) action; 
+	        String timerName = createTimerAction.getTimerName();
+	        Timer timer = new Timer();
+	        long delay = BUSINESS_CALENDAR.add(new Date(0),
+                new Duration(createTimerAction.getDueDate())).getTime();
+            timer.setDelay(delay);
+            if (createTimerAction.getRepeat() != null) {
+                long period = BUSINESS_CALENDAR.add(new Date(0),
+                    new Duration(createTimerAction.getRepeat())).getTime();
+                timer.setPeriod(period);
+            }
+	        if (timerActions.isEmpty()) {
+	            registerTimerListener();
+	        }
+	        getProcessInstance().getWorkingMemory().getTimerManager()
+	            .registerTimer(timer, getProcessInstance());
+	        timerActions.put(timer.getId(), createTimerAction.getTimerAction());
+	        List<Timer> timerList = timers.get(timerName);
+	        if (timerList == null) {
+	            timerList = new ArrayList<Timer>();
+	            timers.put(timerName, timerList);
+	        }
+	        timerList.add(timer);
+	    } else if (action instanceof CancelTimerAction) {
+	        String timerName = ((CancelTimerAction) action).getTimerName();
+	        List<Timer> timerList = timers.get(timerName);
+	        if (timerList != null) {
+	            for (Timer timer: timerList) {
+	                timerActions.remove(timer.getId());
+	                getProcessInstance().getWorkingMemory().getTimerManager()
+	                    .cancelTimer(timer);
+	            }
+                timers.remove(timerName);
+                if (timerActions.isEmpty()) {
+                    removeTimerListener();
+                }
+	        }
+	    } else {
+    		try {
+    			action.execute(executionContext);
+    		} catch (Exception exception) {
+    			raiseException(exception);
+    		}
+	    }
+	}
+
+	public void raiseException(Throwable exception) throws DelegationException {
+		Class<?> clazz = exception.getClass();
+		while (clazz != null) {
+			ExceptionScopeInstance exceptionScopeInstance = (ExceptionScopeInstance)
+				resolveContextInstance(ExceptionScope.EXCEPTION_SCOPE, clazz.getName());
+			if (exceptionScopeInstance != null) {
+				exceptionScopeInstance.handleException(clazz.getName(), exception);
+				return;
+			}
+			clazz = clazz.getSuperclass();
+		}
+		if (exception instanceof JbpmException) {
+			throw (JbpmException) exception;
+		} else {
+			throw new DelegationException(exception, null);
+		}
+	}
+	
+    public void registerTimerListener() {
+        getProcessInstance().addTimerListener(this);
+    }
+    
+    public void removeTimerListener() {
+        getProcessInstance().removeTimerListener(this);
+    }
+
+    public void timerTriggered(Timer timer) {
+        timerTriggered(timer, new JpdlExecutionContext());
+    }
+    
+    protected void timerTriggered(Timer timer, ExecutionContext executionContext) {
+        Action action = timerActions.get(timer.getId());
+        if (action != null) {
+            executeAction(action, executionContext);
+        }
+    }
+
+	public class JpdlExecutionContext extends ExecutionContext {
+	    public JpdlExecutionContext() {
+	        super((Token) null);
+	    }
+	    public void leaveNode() {
+	        leave();
+	    }
+	    public void leaveNode(String transitionName) {
+	        leave(transitionName);
+	    }
+	    public void leaveNode(Transition transition) {
+	        leaveNode(transition.getName());
+	    }
+	    public void setVariable(String name, Object value) {
+	        VariableScopeInstance variableScopeInstance = (VariableScopeInstance)
+	            resolveContextInstance(VariableScope.VARIABLE_SCOPE, name);
+	        variableScopeInstance.setVariable(name, value);
+        }
+        public Object getVariable(String name) {
+            VariableScopeInstance variableScopeInstance = (VariableScopeInstance)
+                resolveContextInstance(VariableScope.VARIABLE_SCOPE, name);
+            return variableScopeInstance.getVariable(name);
+        }
+        public ProcessInstance getDroolsProcessInstance() {
+            return JpdlNodeInstance.this.getProcessInstance();
+        }
+        public NodeInstance getDroolsNodeInstance() {
+            return JpdlNodeInstance.this;
+        }
+	}
+
+}

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/MailNodeInstance.java
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/MailNodeInstance.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/MailNodeInstance.java	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,31 @@
+package org.drools.jpdl.instance.node;
+
+import org.drools.jpdl.core.node.MailNode;
+import org.drools.process.instance.WorkItemManager;
+import org.drools.process.instance.impl.WorkItemImpl;
+import org.drools.workflow.instance.NodeInstance;
+
+public class MailNodeInstance extends JpdlNodeInstance {
+
+	private static final long serialVersionUID = 1L;
+	
+	public MailNode getMailNode() {
+		return (MailNode) getNode();
+	}
+
+	public void execute(NodeInstance from, String type) {
+		MailNode mailNode = getMailNode();
+		WorkItemManager workItemManager = getProcessInstance().getWorkingMemory().getWorkItemManager();
+		WorkItemImpl workItem = new WorkItemImpl();
+		workItem.setName("JpdlEmail");
+		workItem.setProcessInstanceId(getProcessInstance().getId());
+		workItem.setParameter("template", mailNode.getTemplate());
+        workItem.setParameter("actors", mailNode.getActors());
+        workItem.setParameter("to", mailNode.getTo());
+        workItem.setParameter("subject", mailNode.getSubject());
+        workItem.setParameter("text", mailNode.getText());
+		workItemManager.internalExecuteWorkItem(workItem);
+		leave();
+	}
+
+}

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/ProcessStateInstance.java
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/ProcessStateInstance.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/ProcessStateInstance.java	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,136 @@
+package org.drools.jpdl.instance.node;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.drools.WorkingMemory;
+import org.drools.event.RuleFlowCompletedEvent;
+import org.drools.event.RuleFlowEventListener;
+import org.drools.event.RuleFlowGroupActivatedEvent;
+import org.drools.event.RuleFlowGroupDeactivatedEvent;
+import org.drools.event.RuleFlowNodeTriggeredEvent;
+import org.drools.event.RuleFlowStartedEvent;
+import org.drools.jpdl.core.node.ProcessState;
+import org.drools.process.core.context.variable.VariableScope;
+import org.drools.process.instance.context.variable.VariableScopeInstance;
+import org.drools.workflow.instance.NodeInstance;
+import org.jbpm.context.def.VariableAccess;
+import org.jbpm.graph.def.Event;
+
+public class ProcessStateInstance extends JpdlNodeInstance implements RuleFlowEventListener {
+
+	private static final long serialVersionUID = 1L;
+	
+	private long processInstanceId;
+
+	public ProcessState getProcessState() {
+		return (ProcessState) getNode();
+	}
+
+	public void execute(NodeInstance from, String type) {
+		Map<String, Object> parameters = null;
+		Set<VariableAccess> variableAccesses = getProcessState().getVariableAccesses();
+		if ((variableAccesses != null) && (!variableAccesses.isEmpty())) {
+			parameters = new HashMap<String, Object>();
+			// TODO: transient variables ?
+			for (VariableAccess variableAccess : variableAccesses) {
+				if (variableAccess.isReadable()) {
+					String variableName = variableAccess.getVariableName();
+					VariableScopeInstance variableScopeInstance = (VariableScopeInstance)
+						resolveContextInstance(VariableScope.VARIABLE_SCOPE, variableName);
+					Object value = variableScopeInstance.getVariable(variableName);
+					if (value != null) {
+						String mappedName = variableAccess.getMappedName();
+						parameters.put(mappedName, value);
+					}
+				}
+			}
+		}
+		addEventListeners();
+		processInstanceId = getProcessInstance().getWorkingMemory()
+			.startProcess(getProcessState().getSubProcessName(), parameters).getId();
+		fireEvent(Event.EVENTTYPE_SUBPROCESS_CREATED);
+	}
+
+    public void addEventListeners() {
+        getProcessInstance().getWorkingMemory().addEventListener(this);
+    }
+
+    public void removeEventListeners() {
+        getProcessInstance().getWorkingMemory().removeEventListener(this);
+    }
+
+    public void afterRuleFlowCompleted(RuleFlowCompletedEvent event,
+            WorkingMemory workingMemory) {
+        if ( event.getProcessInstance().getId() == processInstanceId ) {
+            removeEventListeners();
+    		Set<VariableAccess> variableAccesses = getProcessState().getVariableAccesses();
+    		if ((variableAccesses != null) && (!variableAccesses.isEmpty())) {
+
+    			for (VariableAccess variableAccess: variableAccesses) {
+    				if (variableAccess.isWritable()) {
+    					String mappedName = variableAccess.getMappedName();
+    					VariableScopeInstance variableScopeInstance = (VariableScopeInstance)
+							event.getProcessInstance().getContextInstance(VariableScope.VARIABLE_SCOPE);
+    					Object value = variableScopeInstance.getVariable(mappedName);
+    					if (value != null) {
+        					String variableName = variableAccess.getVariableName();
+        					variableScopeInstance = (VariableScopeInstance)
+								resolveContextInstance(VariableScope.VARIABLE_SCOPE, mappedName);
+        					variableScopeInstance.setVariable(variableName, value);
+    					}
+    				}
+    			}
+    		}
+    		fireEvent(Event.EVENTTYPE_SUBPROCESS_END);
+            leave();
+        }
+    }
+
+    public void afterRuleFlowGroupActivated(RuleFlowGroupActivatedEvent event,
+            WorkingMemory workingMemory) {
+        // Do nothing
+    }
+
+    public void afterRuleFlowGroupDeactivated(
+            RuleFlowGroupDeactivatedEvent event, WorkingMemory workingMemory) {
+        // Do nothing
+    }
+
+    public void afterRuleFlowNodeTriggered(RuleFlowNodeTriggeredEvent event,
+            WorkingMemory workingMemory) {
+        // Do nothing
+    }
+
+    public void afterRuleFlowStarted(RuleFlowStartedEvent event,
+            WorkingMemory workingMemory) {
+        // Do nothing
+    }
+
+    public void beforeRuleFlowCompleted(RuleFlowCompletedEvent event,
+            WorkingMemory workingMemory) {
+        // Do nothing
+    }
+
+    public void beforeRuleFlowGroupActivated(RuleFlowGroupActivatedEvent event,
+            WorkingMemory workingMemory) {
+        // Do nothing
+    }
+
+    public void beforeRuleFlowGroupDeactivated(
+            RuleFlowGroupDeactivatedEvent event, WorkingMemory workingMemory) {
+        // Do nothing
+    }
+
+    public void beforeRuleFlowNodeTriggered(RuleFlowNodeTriggeredEvent event,
+            WorkingMemory workingMemory) {
+        // Do nothing
+    }
+
+    public void beforeRuleFlowStarted(RuleFlowStartedEvent event,
+            WorkingMemory workingMemory) {
+        // Do nothing
+    }
+
+}

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/StartStateInstance.java
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/StartStateInstance.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/StartStateInstance.java	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,7 @@
+package org.drools.jpdl.instance.node;
+
+public class StartStateInstance extends JpdlNodeInstance {
+
+    private static final long serialVersionUID = 1L;
+
+}

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/StateInstance.java
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/StateInstance.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/StateInstance.java	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,13 @@
+package org.drools.jpdl.instance.node;
+
+import org.drools.workflow.instance.NodeInstance;
+
+public class StateInstance extends JpdlNodeInstance {
+
+	private static final long serialVersionUID = 1L;
+	
+	public void execute(NodeInstance from, String type) {
+		// Do nothing
+	}
+
+}
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/TaskNodeInstance.java
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/TaskNodeInstance.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/instance/node/TaskNodeInstance.java	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,319 @@
+package org.drools.jpdl.instance.node;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
+import org.drools.jpdl.core.node.TaskNode;
+import org.drools.process.core.context.swimlane.SwimlaneContext;
+import org.drools.process.core.context.variable.VariableScope;
+import org.drools.process.instance.WorkItem;
+import org.drools.process.instance.WorkItemListener;
+import org.drools.process.instance.WorkItemManager;
+import org.drools.process.instance.context.swimlane.SwimlaneContextInstance;
+import org.drools.process.instance.context.variable.VariableScopeInstance;
+import org.drools.process.instance.impl.WorkItemImpl;
+import org.drools.workflow.instance.NodeInstance;
+import org.jbpm.JbpmException;
+import org.jbpm.calendar.BusinessCalendar;
+import org.jbpm.calendar.Duration;
+import org.jbpm.context.def.VariableAccess;
+import org.jbpm.graph.def.Event;
+import org.jbpm.instantiation.Delegation;
+import org.jbpm.jpdl.el.impl.JbpmExpressionEvaluator;
+import org.jbpm.taskmgmt.def.Task;
+import org.jbpm.taskmgmt.def.TaskController;
+
+public class TaskNodeInstance extends JpdlNodeInstance implements WorkItemListener {
+
+	private static final long serialVersionUID = 1L;
+	
+    private List<WorkItemImpl> workItems = new ArrayList<WorkItemImpl>();
+    
+	public TaskNode getTaskNode() {
+		return (TaskNode) getNode();
+	}
+
+	public void execute(NodeInstance from, String type) {
+		Set<Task> tasks = getTaskNode().getTasks();
+		if ((getTaskNode().isCreateTasks()) && (tasks != null)) {
+			addEventListeners();
+			for (Task task: tasks) {
+				if (evaluateTaskCondition(task.getCondition())) {
+					WorkItemManager workItemManager = getProcessInstance().getWorkingMemory().getWorkItemManager();
+					WorkItemImpl workItem = new WorkItemImpl();
+					workItem.setName("JpdlTask");
+					workItem.setProcessInstanceId(getProcessInstance().getId());
+					workItem.setParameter("name", task.getName());
+					String description = task.getDescription();
+					workItem.setParameter("signalling", task.isSignalling());
+					workItem.setParameter("blocking", task.isBlocking());
+					if ((description != null) && (description.indexOf("#{") != -1)) {
+						Object result = JbpmExpressionEvaluator.evaluate(
+							description, new JpdlExecutionContext());
+						if (result != null) {
+							description = result.toString();
+						}
+					}
+					workItem.setParameter("Description", description);
+					initializeVariables(workItem, task);
+					if (task.getDueDate() != null) {
+					    BusinessCalendar businessCalendar = new BusinessCalendar();
+					    workItem.setParameter("dueDate", 
+				            businessCalendar.add(new Date(), new Duration(task.getDueDate())));
+				    }
+					if (task.getSwimlane() != null) {
+					    String swimlaneName = task.getSwimlane().getName();
+					    SwimlaneContextInstance swimlaneContextInstance = (SwimlaneContextInstance)
+					        resolveContextInstance(SwimlaneContext.SWIMLANE_SCOPE, swimlaneName);
+					    String actorId = swimlaneContextInstance.getActorId(swimlaneName);
+					    if (actorId == null) {
+					        actorId = assignTask(task);
+					    }
+					    workItem.setParameter("ActorId", actorId);
+					}
+					workItems.add(workItem);
+					Event event = task.getEvent(Event.EVENTTYPE_TASK_CREATE);
+			        if (event != null) {
+			            // TODO this doesn't take event handlers of task itself
+			            // into account
+			            executeActions(event.getActions(), new JpdlTaskExecutionContext(task));
+			        }
+					workItemManager.internalExecuteWorkItem(workItem);
+				}
+			}
+		}
+		boolean continueExecution = false;
+		switch (getTaskNode().getSignal()) {
+			case org.jbpm.graph.node.TaskNode.SIGNAL_UNSYNCHRONIZED:
+				continueExecution = true;
+				break;
+			case org.jbpm.graph.node.TaskNode.SIGNAL_FIRST_WAIT:
+			case org.jbpm.graph.node.TaskNode.SIGNAL_LAST_WAIT:
+			case org.jbpm.graph.node.TaskNode.SIGNAL_NEVER:
+				continueExecution = false;
+				break;
+			case org.jbpm.graph.node.TaskNode.SIGNAL_FIRST:
+			case org.jbpm.graph.node.TaskNode.SIGNAL_LAST:
+				continueExecution = !hasSignallingWorkItems();
+		}
+		if (continueExecution) {
+			leave();
+		}
+	}
+
+	private boolean evaluateTaskCondition(String condition) {
+		if (condition == null) {
+			return true;
+		}
+		Object result = JbpmExpressionEvaluator.evaluate(
+			condition, new JpdlExecutionContext());
+		if (Boolean.TRUE.equals(result)) {
+			return true;
+		}
+		return false;
+	}
+	
+	private void initializeVariables(WorkItemImpl workItem, Task task) {
+		TaskController taskController = task.getTaskController();
+		if (taskController != null) {
+			Delegation taskControllerDelegation = taskController.getTaskControllerDelegation();
+		    if (taskControllerDelegation != null) {
+		    	// TODO: delegation (API mismatch!)
+		    } else {
+		    	List<VariableAccess> variableAccesses = taskController.getVariableAccesses();
+		    	if (variableAccesses != null) {
+		    		for (VariableAccess variableAccess: variableAccesses) {
+		    			String mappedName = variableAccess.getMappedName();
+		    			if (variableAccess.isReadable()) {
+		    				String variableName = variableAccess.getVariableName();
+		    				VariableScopeInstance variableScopeInstance = (VariableScopeInstance)
+		    					resolveContextInstance(VariableScope.VARIABLE_SCOPE, variableName);
+		    				Object value = variableScopeInstance.getVariable(variableName);
+		    				workItem.setParameter(mappedName, value);
+		    			}
+			        }
+		    	}
+		    }
+		}
+	}
+	
+	private String assignTask(Task task) {
+	    Event event = task.getEvent(Event.EVENTTYPE_TASK_ASSIGN);
+        if (event != null) {
+            executeActions(event.getActions(), new JpdlTaskExecutionContext(task));
+        }
+	    if (task.getActorIdExpression() != null) {
+            return resolveActor(task.getActorIdExpression());
+	    } else if (task.getSwimlane().getActorIdExpression() != null) {
+	        return resolveActor(task.getSwimlane().getActorIdExpression());
+	    }
+	    // TODO support other assignment types
+	    return null;
+	}
+	
+	private String resolveActor(String expression) {
+	    Object result = JbpmExpressionEvaluator.evaluate(expression, new JpdlExecutionContext());
+        if (result == null) {
+            throw new JbpmException("actor-id expression '" + expression + "' returned null");
+        }
+        if (result instanceof String) {
+            return (String) result;
+        } else {
+            throw new JbpmException(
+                "actor-id expression '" + expression + 
+                "' didn't resolve to a java.lang.String: '" + result + 
+                "' (" + result.getClass().getName() + ")");
+        }
+	}
+	
+	private boolean hasSignallingWorkItems() {
+	    for (WorkItem workItem: workItems) {
+	        if ((Boolean) workItem.getParameter("signalling") == true) {
+	            return true;
+	        }
+	    }
+	    return false; 
+	}
+
+    private boolean hasBlockingWorkItems() {
+        for (WorkItem workItem: workItems) {
+            if ((Boolean) workItem.getParameter("blocking") == true) {
+                return true;
+            }
+        }
+        return false; 
+    }
+
+	private void restoreVariables(WorkItemImpl workItem, Task task) {
+		TaskController taskController = task.getTaskController();
+		if (taskController != null) {
+			Delegation taskControllerDelegation = taskController.getTaskControllerDelegation();
+			if (taskControllerDelegation != null) {
+				// TODO: delegation (API mismatch!)
+		    } else {
+		    	List<VariableAccess> variableAccesses = taskController.getVariableAccesses();
+		    	if (variableAccesses != null) {
+			        String missingTaskVariables = null;
+		    		for (VariableAccess variableAccess: variableAccesses) {
+		    			String mappedName = variableAccess.getMappedName();
+		    			Object value = workItem.getParameter(mappedName);
+		    			if (variableAccess.isRequired() && (value != null)) {
+		    				if (missingTaskVariables == null) {
+		    					missingTaskVariables = mappedName;
+		    				} else {
+		    					missingTaskVariables += ", "+mappedName;
+		    				}
+		    			}
+		    		}
+			        if (missingTaskVariables != null) {
+			        	throw new IllegalArgumentException(
+		        			"missing task variables: " + missingTaskVariables);
+			        }
+
+			        for (VariableAccess variableAccess: variableAccesses) {
+			        	String mappedName = variableAccess.getMappedName();
+			        	String variableName = variableAccess.getVariableName();
+			        	if (variableAccess.isWritable()) {
+			        		Object value = workItem.getParameter(mappedName);
+			        		if (value != null) {
+			        			VariableScopeInstance variableScopeInstance = (VariableScopeInstance)
+		    						resolveContextInstance(VariableScope.VARIABLE_SCOPE, variableName);
+			        			variableScopeInstance.setVariable(variableName, value);
+			        		}
+			        	}
+			        }
+		    	}
+		    }
+		}
+	}
+
+    public void addEventListeners() {
+        getProcessInstance().addWorkItemListener(this);
+    }
+    
+    public void removeEventListeners() {
+        getProcessInstance().removeWorkItemListener(this);
+    }
+
+    public void workItemAborted(WorkItem workItem) {
+        if (workItems.remove(workItem)) {
+            if (!hasBlockingWorkItems()) {
+                removeEventListeners();
+            	leave();
+            }
+        }
+    }
+
+    public void workItemCompleted(WorkItem workItem) {
+    	if (workItems.remove(workItem)) {
+    		String taskName = (String) workItem.getParameter("name");
+    		Set<Task> tasks = getTaskNode().getTasks();
+			for (Task task: tasks) {
+				if (taskName.equals(task.getName())) {
+		    		restoreVariables((WorkItemImpl) workItem, task);
+		    		if (task.getSwimlane() != null) {
+		    		    String swimlaneName = task.getSwimlane().getName();
+		    		    SwimlaneContextInstance swimlaneContextInstance = (SwimlaneContextInstance)
+                            resolveContextInstance(SwimlaneContext.SWIMLANE_SCOPE, swimlaneName);
+		    		    if (swimlaneContextInstance.getActorId(swimlaneName) == null) {
+		    		        String actorId = (String) workItem.getResult("ActorId");
+		    		        if (actorId != null) {
+		    		            swimlaneContextInstance.setActorId(swimlaneName, 
+	    		                    (String) workItem.getResult("ActorId"));
+		    		        }
+		    		    }
+		    		}
+	                Event event = task.getEvent(Event.EVENTTYPE_TASK_END);
+	                if (event != null) {
+	                    executeActions(event.getActions(), new JpdlTaskExecutionContext(task));
+	                }
+		            break;
+				}
+    		}
+            if (!hasBlockingWorkItems()) {
+                removeEventListeners();
+                String result = (String) workItem.getResult("Result");
+                if (result != null) {
+                    leave(result);
+                } else {
+                    leave();
+                }
+            }
+        }
+    }
+    
+    public WorkItem findWorkItem(Task task) {
+        for (WorkItem workItem: workItems) {
+            if (task.getName().equals(workItem.getName())) {
+                return workItem;
+            }
+        }
+        return null;
+    }
+
+	public void leave(String type) {
+		if (hasBlockingWorkItems()) {
+			throw new IllegalStateException("task-node '"
+				+ getNode().getName() + "' still has blocking tasks");
+		}
+		if (getTaskNode().isEndTasks()) {
+			for (WorkItem workItem: workItems) {
+				getProcessInstance().getWorkingMemory().getWorkItemManager()
+					.internalAbortWorkItem(workItem.getId());
+			}
+		}
+		super.leave(type);
+	}
+	
+	public class JpdlTaskExecutionContext extends JpdlExecutionContext {
+	    private Task task;
+	    public JpdlTaskExecutionContext(Task task) {
+	        this.task = task;
+	    }
+	    public Task getTask() {
+	        return task;
+	    }
+	}
+}

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/xml/JpdlProcessSemanticModule.java
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/xml/JpdlProcessSemanticModule.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/xml/JpdlProcessSemanticModule.java	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,82 @@
+package org.drools.jpdl.xml;
+
+import org.drools.xml.DefaultSemanticModule;
+import org.drools.xml.SemanticModule;
+import org.drools.xml.processes.ActionNodeHandler;
+import org.drools.xml.processes.CompositeNodeHandler;
+import org.drools.xml.processes.ConnectionHandler;
+import org.drools.xml.processes.ConstraintHandler;
+import org.drools.xml.processes.EndNodeHandler;
+import org.drools.xml.processes.GlobalHandler;
+import org.drools.xml.processes.ImportHandler;
+import org.drools.xml.processes.InPortHandler;
+import org.drools.xml.processes.JoinNodeHandler;
+import org.drools.xml.processes.MappingHandler;
+import org.drools.xml.processes.MilestoneNodeHandler;
+import org.drools.xml.processes.OutPortHandler;
+import org.drools.xml.processes.ParameterHandler;
+import org.drools.xml.processes.ProcessHandler;
+import org.drools.xml.processes.RuleSetNodeHandler;
+import org.drools.xml.processes.SplitNodeHandler;
+import org.drools.xml.processes.SubProcessNodeHandler;
+import org.drools.xml.processes.TimerNodeHandler;
+import org.drools.xml.processes.TypeHandler;
+import org.drools.xml.processes.ValueHandler;
+import org.drools.xml.processes.VariableHandler;
+import org.drools.xml.processes.WorkHandler;
+import org.drools.xml.processes.WorkItemNodeHandler;
+
+public class JpdlProcessSemanticModule extends DefaultSemanticModule implements SemanticModule {    
+    public JpdlProcessSemanticModule() {
+        super ( "http://drools.org/drools-4.0/process" );
+
+        addHandler( "process",
+                           new ProcessHandler() );
+        addHandler( "start",
+                           new StartStateHandler() );
+        addHandler( "end",
+                           new EndNodeHandler() );
+        addHandler( "action",
+                           new ActionNodeHandler() );
+        addHandler( "ruleSet",
+                           new RuleSetNodeHandler() );
+        addHandler( "subProcess",
+                           new SubProcessNodeHandler() );
+        addHandler( "workItem",
+                           new WorkItemNodeHandler() );
+        addHandler( "split",
+                           new SplitNodeHandler() );
+        addHandler( "join",
+                           new JoinNodeHandler() );
+        addHandler( "milestone",
+                           new MilestoneNodeHandler() );
+        addHandler( "timer",
+                           new TimerNodeHandler() );
+        addHandler( "composite",
+                           new CompositeNodeHandler() );
+        addHandler( "connection",
+                           new ConnectionHandler() );
+        addHandler( "import",
+                           new ImportHandler() );
+        addHandler( "global",
+                           new GlobalHandler() );        
+        addHandler( "variable",
+                           new VariableHandler() );        
+        addHandler( "type",
+                           new TypeHandler() );        
+        addHandler( "value",
+                           new ValueHandler() );        
+        addHandler( "work",
+                           new WorkHandler() );        
+        addHandler( "parameter",
+                           new ParameterHandler() );        
+        addHandler( "mapping",
+                           new MappingHandler() );        
+        addHandler( "constraint",
+                           new ConstraintHandler() );        
+        addHandler( "in-port",
+                           new InPortHandler() );        
+        addHandler( "out-port",
+                           new OutPortHandler() );        
+    }
+}

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/xml/StartStateHandler.java
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/xml/StartStateHandler.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/java/org/drools/jpdl/xml/StartStateHandler.java	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,23 @@
+package org.drools.jpdl.xml;
+
+import org.drools.jpdl.core.node.StartState;
+import org.drools.workflow.core.Node;
+import org.drools.xml.processes.AbstractNodeHandler;
+
+public class StartStateHandler extends AbstractNodeHandler {
+    
+    protected Node createNode() {
+        return new StartState();
+    }
+    
+    public Class generateNodeFor() {
+        return StartState.class;
+    }
+
+	public void writeNode(Node node, StringBuffer xmlDump, boolean includeMeta) {
+		StartState startNode = (StartState) node;
+		writeNode("start", startNode, xmlDump, includeMeta);
+        endNode(xmlDump);
+	}
+
+}

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/resources/META-INF/JpdlProcessInstanceFactory.conf
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/resources/META-INF/JpdlProcessInstanceFactory.conf	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/resources/META-INF/JpdlProcessInstanceFactory.conf	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,7 @@
+// we use MVEL to configure our process, simply populate a map, which will be added to the main registry
+import org.drools.jpdl.core.JpdlProcess;
+import org.drools.jpdl.instance.JpdlProcessInstanceFactory;
+
+[
+    JpdlProcess     : new JpdlProcessInstanceFactory(),
+]

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/resources/META-INF/JpdlProcessNodeInstanceFactory.conf
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/resources/META-INF/JpdlProcessNodeInstanceFactory.conf	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/resources/META-INF/JpdlProcessNodeInstanceFactory.conf	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,36 @@
+// we use MVEL to configure our nodes, simply populate a map, which will be added to the main registry
+import org.drools.jpdl.core.node.Decision;
+import org.drools.jpdl.core.node.EndState;
+import org.drools.jpdl.core.node.Fork;
+import org.drools.jpdl.core.node.Join;
+import org.drools.jpdl.core.node.JpdlNode;
+import org.drools.jpdl.core.node.MailNode;
+import org.drools.jpdl.core.node.ProcessState;
+import org.drools.jpdl.core.node.StartState;
+import org.drools.jpdl.core.node.State;
+import org.drools.jpdl.core.node.TaskNode;
+import org.drools.jpdl.instance.node.DecisionInstance;
+import org.drools.jpdl.instance.node.EndStateInstance;
+import org.drools.jpdl.instance.node.ForkInstance;
+import org.drools.jpdl.instance.node.JoinInstance;
+import org.drools.jpdl.instance.node.JpdlNodeInstance;
+import org.drools.jpdl.instance.node.MailNodeInstance;
+import org.drools.jpdl.instance.node.ProcessStateInstance;
+import org.drools.jpdl.instance.node.StartStateInstance;
+import org.drools.jpdl.instance.node.StateInstance;
+import org.drools.jpdl.instance.node.TaskNodeInstance;
+import org.drools.workflow.instance.impl.factory.CreateNewNodeFactory;
+import org.drools.workflow.instance.impl.factory.ReuseNodeFactory;
+
+[
+    JpdlNode     : new CreateNewNodeFactory( JpdlNodeInstance ),
+    StartState   : new CreateNewNodeFactory( StartStateInstance ),
+    EndState     : new CreateNewNodeFactory( EndStateInstance ),
+    Fork         : new CreateNewNodeFactory( ForkInstance ),
+    Join         : new ReuseNodeFactory( JoinInstance ),
+    MailNode     : new CreateNewNodeFactory( MailNodeInstance ),
+    Decision     : new CreateNewNodeFactory( DecisionInstance ),
+    ProcessState : new CreateNewNodeFactory( ProcessStateInstance ),
+    TaskNode     : new CreateNewNodeFactory( TaskNodeInstance ),
+    State        : new CreateNewNodeFactory( StateInstance ),
+]

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/resources/META-INF/drools.rulebase.conf
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/resources/META-INF/drools.rulebase.conf	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/main/resources/META-INF/drools.rulebase.conf	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,2 @@
+processInstanceFactoryRegistry=JpdlProcessInstanceFactory.conf
+processNodeInstanceFactoryRegistry=JpdlProcessNodeInstanceFactory.conf
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/java/org/drools/ParseSimpleProcessTest.java
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/java/org/drools/ParseSimpleProcessTest.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/java/org/drools/ParseSimpleProcessTest.java	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,70 @@
+package org.drools;
+
+import junit.framework.TestCase;
+
+import org.drools.jpdl.JpdlParser;
+import org.drools.jpdl.core.JpdlProcess;
+import org.drools.process.core.validation.ProcessValidationError;
+import org.drools.process.instance.ProcessInstance;
+import org.drools.process.instance.WorkItem;
+import org.drools.process.instance.WorkItemHandler;
+import org.drools.process.instance.WorkItemManager;
+import org.drools.rule.Package;
+
+public class ParseSimpleProcessTest extends TestCase {
+
+	public void testSimpleProcess() throws Exception {
+	    JpdlParser parser = new JpdlParser();
+	    JpdlProcess process = parser.loadJpdlProcess("simple/processdefinition.xml");
+	    ProcessValidationError[] errors = parser.getErrors();
+	    for (ProcessValidationError error: errors) {
+            System.err.println(error);
+        }
+        assertEquals(0, errors.length);
+        
+        RuleBase ruleBase = RuleBaseFactory.newRuleBase();
+        Package p = new Package("com.sample");
+        p.addRuleFlow(process);
+        ruleBase.addPackage( p );
+        
+        WorkingMemory workingMemory = ruleBase.newStatefulSession();
+        ProcessInstance processInstance = workingMemory.startProcess("simple");
+        assertEquals(ProcessInstance.STATE_COMPLETED, processInstance.getState());
+    }
+
+    public void testSimpleProcess2() throws Exception {
+        JpdlParser parser = new JpdlParser();
+        JpdlProcess process = parser.loadJpdlProcess("simple2/processdefinition.xml");
+        ProcessValidationError[] errors = parser.getErrors();
+        for (ProcessValidationError error: errors) {
+            System.err.println(error);
+        }
+        assertEquals(0, errors.length);
+        
+        RuleBase ruleBase = RuleBaseFactory.newRuleBase();
+        Package p = new Package("com.sample");
+        p.addRuleFlow(process);
+        ruleBase.addPackage( p );
+        
+        WorkingMemory workingMemory = ruleBase.newStatefulSession();
+        TestWorkItemHandler handler = new TestWorkItemHandler();
+        workingMemory.getWorkItemManager().registerWorkItemHandler(
+            "Email", handler);
+        assertTrue(handler.getWorkItemId() == -1);
+        ProcessInstance processInstance = workingMemory.startProcess("simple");
+        assertEquals(ProcessInstance.STATE_COMPLETED, processInstance.getState());
+    }
+
+    private static class TestWorkItemHandler implements WorkItemHandler {
+        private long workItemId = -1;
+        public void executeWorkItem(WorkItem workItem, WorkItemManager manager) {
+            workItemId = workItem.getId();
+        }
+        public void abortWorkItem(WorkItem workItem, WorkItemManager manager) {
+        }
+        public long getWorkItemId() {
+            return workItemId;
+        }
+    }
+    
+}

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/java/org/drools/SimpleProcessTest.java
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/java/org/drools/SimpleProcessTest.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/java/org/drools/SimpleProcessTest.java	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,40 @@
+package org.drools;
+
+import junit.framework.TestCase;
+
+import org.jbpm.graph.def.ProcessDefinition;
+import org.jbpm.graph.exe.ProcessInstance;
+
+public class SimpleProcessTest extends TestCase {
+
+	public void testSimpleProcess() throws Exception {
+
+		// Extract a process definition from the processdefinition.xml file.
+		ProcessDefinition processDefinition = ProcessDefinition.parseXmlResource("simple/processdefinition.xml");
+		assertNotNull("Definition should not be null", processDefinition);
+
+		// Create an instance of the process definition.
+		ProcessInstance instance = new ProcessInstance(processDefinition);
+		assertEquals(
+				"Instance is in start state", 
+				instance.getRootToken().getNode().getName(), 
+				"start");
+		assertNull(
+				"Message variable should not exist yet", 
+				instance.getContextInstance().getVariable("message"));
+
+		instance.signal();
+		assertEquals(
+				"Instance is in node1", 
+				instance.getRootToken().getNode().getName(), 
+				"node1");
+		
+		instance.signal();
+		assertEquals(
+				"Instance is in end state", 
+				instance.getRootToken().getNode().getName(), 
+				"end");
+		assertTrue("Instance has ended", instance.hasEnded());
+	}
+
+}

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/java/org/drools/SysoutHandler.java
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/java/org/drools/SysoutHandler.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/java/org/drools/SysoutHandler.java	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,15 @@
+package org.drools;
+
+import org.jbpm.graph.def.ActionHandler;
+import org.jbpm.graph.exe.ExecutionContext;
+
+public class SysoutHandler implements ActionHandler {
+
+	private static final long serialVersionUID = 1L;
+
+	public void execute(ExecutionContext executionContext) throws Exception {
+		System.out.println("Executing");
+		executionContext.leaveNode();
+	}
+
+}

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/java/org/drools/WebsaleProcessTest.java
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/java/org/drools/WebsaleProcessTest.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/java/org/drools/WebsaleProcessTest.java	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,69 @@
+package org.drools;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.jpdl.JpdlParser;
+import org.drools.jpdl.core.JpdlProcess;
+import org.drools.process.core.context.variable.Variable;
+import org.drools.process.core.context.variable.VariableScope;
+import org.drools.process.core.datatype.impl.type.StringDataType;
+import org.drools.process.core.validation.ProcessValidationError;
+import org.drools.process.instance.impl.demo.UIWorkItemHandler;
+import org.drools.rule.Package;
+
+public class WebsaleProcessTest {
+
+	public static void main(String[] args) throws Exception {
+	    JpdlParser parser = new JpdlParser();
+	    JpdlProcess process = parser.loadJpdlProcess("websale/processdefinition.xml");
+	    VariableScope variableScope = (VariableScope)
+	        process.getDefaultContext(VariableScope.VARIABLE_SCOPE);
+	    // TODO: do we really need to define all process variables ?
+	    List<Variable> variables = new ArrayList<Variable>();
+	    Variable item = new Variable();
+	    item.setName("item");
+	    item.setType(new StringDataType());
+	    variables.add(item);
+	    Variable quantity = new Variable();
+	    quantity.setName("quantity");
+	    quantity.setType(new StringDataType());
+        variables.add(quantity);
+        Variable address = new Variable();
+        address.setName("address");
+        address.setType(new StringDataType());
+        variables.add(address);
+	    variableScope.setVariables(variables);
+	    ProcessValidationError[] errors = parser.getErrors();
+	    for (ProcessValidationError error: errors) {
+            System.err.println(error);
+        }
+        if (errors.length != 0) {
+            throw new IllegalArgumentException("Errors while parsing websale process");
+        }
+        
+        RuleBase ruleBase = RuleBaseFactory.newRuleBase();
+        Package p = new Package("com.sample");
+        p.addRuleFlow(process);
+        ruleBase.addPackage( p );
+        
+        WorkingMemory workingMemory = ruleBase.newStatefulSession();
+        UIWorkItemHandler uiHandler = new UIWorkItemHandler();
+        workingMemory.getWorkItemManager().registerWorkItemHandler(
+            "JpdlTask", uiHandler);
+        uiHandler.setVisible(true);
+        Map<String, Object> parameters = new HashMap<String, Object>();
+        parameters.put("item", "Drools Manual");
+        parameters.put("quantity", "2");
+        parameters.put("item", "Drools Manual");
+        parameters.put("address", 
+            "Red Hat Corporate Headquarters, " +
+            "1801 Varsity Drive, " +
+            "Raleigh, North Carolina 27606" +
+            "USA");
+        workingMemory.startProcess("websale", parameters);
+    }
+
+}

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/java/org/jbpm/websale/RemindActor.java
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/java/org/jbpm/websale/RemindActor.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/java/org/jbpm/websale/RemindActor.java	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,18 @@
+package org.jbpm.websale;
+
+import org.jbpm.graph.def.ActionHandler;
+import org.jbpm.graph.exe.ExecutionContext;
+
+public class RemindActor implements ActionHandler {
+
+    private static final long serialVersionUID = 1L;
+  
+    String swimlaneName;
+
+    public void execute(ExecutionContext executionContext) throws Exception {
+        System.out.println("###############################################");
+        System.out.println("### Task is waiting.");
+        System.out.println("###############################################");
+    }
+
+}

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/java/org/jbpm/websale/ShipItem.java
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/java/org/jbpm/websale/ShipItem.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/java/org/jbpm/websale/ShipItem.java	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,36 @@
+package org.jbpm.websale;
+
+import org.jbpm.graph.def.ActionHandler;
+import org.jbpm.graph.exe.ExecutionContext;
+
+public class ShipItem implements ActionHandler {
+
+    private static final long serialVersionUID = 1L;
+  
+    String swimlaneName;
+    String msg;
+
+    public void execute(ExecutionContext executionContext) throws Exception {
+        // TODO get real name of assigned person?
+        String actorId = "Shipper";
+        String displayMsg = replace(msg, "${"+swimlaneName+"}", actorId);
+        displayMsg = replace(displayMsg, "${item}", (String) executionContext.getVariable("item")); 
+        displayMsg = replace(displayMsg, "${address}", (String) executionContext.getVariable("address"));
+    
+        System.out.println("###############################################");
+        System.out.println("### " + displayMsg);
+        System.out.println("###############################################");
+    
+        executionContext.leaveNode();
+    }
+
+    private static String replace(String msg, String pattern, String replacement) {
+        String replaced = null;
+        int pos = msg.indexOf(pattern);
+        if (pos!=-1) {
+            replaced = msg.substring(0,pos) + replacement
+                 + msg.substring(pos + pattern.length());
+        }
+        return replaced;
+    }
+}

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/java/org/jbpm/websale/UpdateBooks.java
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/java/org/jbpm/websale/UpdateBooks.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/java/org/jbpm/websale/UpdateBooks.java	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,19 @@
+package org.jbpm.websale;
+
+import org.jbpm.graph.def.ActionHandler;
+import org.jbpm.graph.exe.ExecutionContext;
+
+public class UpdateBooks implements ActionHandler {
+  
+    String msg;
+
+    private static final long serialVersionUID = 1L;
+
+    public void execute(ExecutionContext executionContext) throws Exception {
+        System.out.println("###############################################");
+        System.out.println("### updating the accounting books");
+        System.out.println("###############################################");
+        executionContext.leaveNode();
+    }
+
+}

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/simple/gpd.xml
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/simple/gpd.xml	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/simple/gpd.xml	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<root-container height="662" name="simple" width="694">
+  <node height="40" name="start" width="140" x="150" y="25">
+    <edge>
+      <label x="5" y="-10"/>
+    </edge>
+  </node>
+  <node height="40" name="end" width="140" x="150" y="225"/>
+  <node height="36" name="node1" width="132" x="153" y="120">
+    <edge>
+      <label x="5" y="-10"/>
+    </edge>
+  </node>
+</root-container>

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/simple/processdefinition.xml
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/simple/processdefinition.xml	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/simple/processdefinition.xml	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<process-definition 
+  xmlns="urn:jbpm.org:jpdl-3.2"
+  name="simple">
+   <start-state name="start">
+		<transition to="node1"></transition>
+	</start-state>
+   <node name="node1">
+		<action name="Sysout" class="org.drools.SysoutHandler"></action>
+		<transition to="end"></transition>
+	</node>
+
+
+	<end-state name="end"></end-state>
+</process-definition>
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/simple/processimage.jpg
===================================================================
(Binary files differ)


Property changes on: labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/simple/processimage.jpg
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/simple2/gpd.xml
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/simple2/gpd.xml	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/simple2/gpd.xml	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<root-container height="662" name="simple" width="694">
+  <node height="40" name="start" width="140" x="150" y="25">
+    <edge>
+      <label x="5" y="-10"/>
+    </edge>
+  </node>
+  <node height="36" name="node1" width="132" x="42" y="154">
+    <edge>
+      <label x="5" y="-10"/>
+    </edge>
+  </node>
+  <node height="40" name="end" width="140" x="154" y="290"/>
+  <node height="24" name="fork1" width="252" x="95" y="100">
+    <edge>
+      <label x="5" y="-10"/>
+    </edge>
+    <edge>
+      <label x="5" y="-10"/>
+    </edge>
+  </node>
+  <node height="24" name="join1" width="252" x="99" y="223">
+    <edge>
+      <label x="5" y="-10"/>
+    </edge>
+  </node>
+  <node height="36" name="mail-node1" width="132" x="263" y="155">
+    <edge>
+      <label x="5" y="-10"/>
+    </edge>
+  </node>
+</root-container>

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/simple2/processdefinition.xml
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/simple2/processdefinition.xml	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/simple2/processdefinition.xml	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<process-definition 
+  xmlns="urn:jbpm.org:jpdl-3.2"
+  name="simple">
+   <start-state name="start">
+		<transition to="fork1"></transition>
+	</start-state>
+   <node name="node1">
+		<action name="Sysout" class="org.drools.SysoutHandler"></action>
+		<transition to="join1"></transition>
+	</node>
+
+	<fork name="fork1">
+		<transition to="node1"></transition>
+		<transition to="node2" name="to node2"></transition>
+	</fork>
+
+	<join name="join1">
+		<transition to="end"></transition>
+	</join>
+
+	<node name="node2">
+		<action name="Sysout" class="org.drools.SysoutHandler"></action>
+		<transition to="join1"></transition>
+	</node>
+
+
+	<end-state name="end">
+		<event type="node-enter">
+			<action name="Sysout" class="org.drools.SysoutHandler"></action>
+		</event>
+	</end-state>
+</process-definition>
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/simple2/processimage.jpg
===================================================================
(Binary files differ)


Property changes on: labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/simple2/processimage.jpg
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/websale/gpd.xml
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/websale/gpd.xml	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/websale/gpd.xml	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<process-diagram name="websale" width="566" height="541">
+  <node name="Create new web sale order" x="250" y="50" width="200" height="40">
+    <transition>
+      <label x="5" y="-10"/>
+    </transition>
+  </node>
+  <node name="Evaluate web order" x="280" y="125" width="140" height="40">
+    <transition name="ok">
+      <label x="9" y="-10"/>
+    </transition>
+    <transition name="more info needed">
+      <label x="-44" y="-18"/>
+      <bendpoint w1="-114" h1="-35" w2="116" h2="-35"/>
+    </transition>
+  </node>
+  <node name="Fix web order data" x="50" y="125" width="140" height="40">
+    <transition>
+      <label x="5" y="-10"/>
+      <bendpoint w1="109" h1="32" w2="-121" h2="32"/>
+    </transition>
+  </node>
+  <node name="salefork" x="250" y="200" width="200" height="25">
+    <transition name="payment">
+      <label x="12" y="-18"/>
+      <bendpoint w1="145" h1="31" w2="0" h2="-52"/>
+    </transition>
+    <transition name="shipping">
+      <label x="10" y="10"/>
+      <bendpoint w1="-130" h1="34" w2="0" h2="-89"/>
+    </transition>
+  </node>
+  <node name="Wait for money" x="425" y="275" width="140" height="40">
+    <transition>
+      <label x="5" y="-10"/>
+    </transition>
+  </node>
+  <node name="update books" x="425" y="350" width="140" height="40">
+    <transition>
+      <label x="5" y="-10"/>
+      <bendpoint w1="-1" h1="34" w2="144" h2="-33"/>
+    </transition>
+  </node>
+  <node name="ship item" x="150" y="315" width="140" height="40">
+    <transition>
+      <label x="5" y="-10"/>
+      <bendpoint w1="-1" h1="74" w2="-131" h2="-28"/>
+    </transition>
+  </node>
+  <node name="salejoin" x="250" y="425" width="200" height="25">
+    <transition>
+      <label x="5" y="-10"/>
+    </transition>
+  </node>
+  <node name="end" x="280" y="500" width="140" height="40"/>
+</process-diagram>

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/websale/processdefinition.xml
===================================================================
--- labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/websale/processdefinition.xml	                        (rev 0)
+++ labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/websale/processdefinition.xml	2008-05-27 11:13:44 UTC (rev 20178)
@@ -0,0 +1,77 @@
+<?xml version="1.0"?>
+
+<process-definition name="websale"
+                    xmlns="urn:jbpm.org:jpdl-3.2">
+
+  <!-- SWIMLANES (= process roles) -->
+
+  <swimlane name="buyer" />
+  
+  <swimlane name="salesman">
+    <assignment actor-id="ernie" />
+  </swimlane>
+  
+  <swimlane name="accountant">
+    <assignment actor-id="bert" />
+  </swimlane>
+  
+  <swimlane name="shipper">
+    <assignment actor-id="grover" />
+  </swimlane>
+ 
+  <!-- NODES -->
+
+  <start-state name="Create new web sale order">
+    <task swimlane="buyer" />
+    <transition to="Evaluate web order" />
+  </start-state>
+  
+  <task-node name="Evaluate web order">
+    <task swimlane="salesman">
+      <timer duedate="20 seconds" repeat="10 seconds">
+        <action class="org.jbpm.websale.RemindActor">
+          <swimlaneName>salesman</swimlaneName>
+        </action>
+      </timer>
+    </task>
+    <transition name="OK" to="salefork" />
+    <transition name="More info needed" to="Fix web order data" />
+  </task-node>
+
+  <task-node name="Fix web order data">
+    <task swimlane="buyer" />
+    <transition to="Evaluate web order" />
+  </task-node>
+
+  <fork name="salefork">
+    <transition name="payment"  to="Wait for money" />
+    <transition name="shipping" to="ship item" />
+  </fork>  
+  
+  <task-node name="Wait for money">
+    <task swimlane="accountant" />
+    <transition to="update books" />
+  </task-node>
+  
+  <node name="update books">
+    <action class="org.jbpm.websale.UpdateBooks">
+      <msg>accountancy application is now informed of the payment</msg>
+    </action>
+    <transition to="salejoin" />
+  </node>
+  
+  <node name="ship item">
+    <action class="org.jbpm.websale.ShipItem">
+      <swimlaneName>shipper</swimlaneName>
+      <msg>${shipper} now ships ${item} to ${address}</msg>
+    </action>
+    <transition to="salejoin" />
+  </node>
+  
+  <join name="salejoin">
+    <transition to="end" />
+  </join>  
+
+  <end-state name="end" />
+
+</process-definition>

Added: labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/websale/processimage.jpg
===================================================================
(Binary files differ)


Property changes on: labs/jbossrules/trunk/drools-process/drools-jpdl/src/test/resources/websale/processimage.jpg
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream




More information about the jboss-svn-commits mailing list