/*
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jbpm.bpmn2.persistence;
import org.drools.core.command.impl.CommandBasedStatefulKnowledgeSession;
import org.drools.core.command.impl.ExecutableCommand;
import org.drools.core.command.impl.RegistryContext;
import org.jbpm.bpmn2.JbpmBpmn2TestCase;
import org.jbpm.compiler.xml.XmlRuleFlowProcessDumper;
import org.jbpm.persistence.session.objects.TestWorkItemHandler;
import org.jbpm.process.instance.impl.ProcessInstanceImpl;
import org.jbpm.ruleflow.core.RuleFlowProcess;
import org.jbpm.ruleflow.core.RuleFlowProcessFactory;
import org.jbpm.workflow.core.impl.ConnectionImpl;
import org.jbpm.workflow.core.impl.NodeImpl;
import org.jbpm.workflow.core.node.HumanTaskNode;
import org.junit.BeforeClass;
import org.junit.Test;
import org.kie.api.KieBase;
import org.kie.api.definition.process.Connection;
import org.kie.api.event.process.ProcessCompletedEvent;
import org.kie.api.event.process.ProcessEventListener;
import org.kie.api.event.process.ProcessNodeLeftEvent;
import org.kie.api.event.process.ProcessNodeTriggeredEvent;
import org.kie.api.event.process.ProcessStartedEvent;
import org.kie.api.event.process.ProcessVariableChangedEvent;
import org.kie.api.io.Resource;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.Context;
import org.kie.internal.io.ResourceFactory;
import org.kie.internal.runtime.StatefulKnowledgeSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This is a sample file to launch a process.
*/
public class DynamicProcessTest extends JbpmBpmn2TestCase {
private static final Logger logger = LoggerFactory.getLogger(DynamicProcessTest.class);
@BeforeClass
public static void setup() throws Exception {
if (PERSISTENCE) {
setUpDataSource();
}
}
@Test
public void testDynamicProcess() throws Exception {
RuleFlowProcessFactory factory = RuleFlowProcessFactory.createProcess("org.jbpm.HelloWorld");
factory
// Header
.name("HelloWorldProcess")
.version("1.0")
.packageName("org.jbpm")
// Nodes
.startNode(1).name("Start").done()
.humanTaskNode(2).name("Task1").actorId("krisv").taskName("MyTask").done()
.endNode(3).name("End").done()
// Connections
.connection(1, 2)
.connection(2, 3);
final RuleFlowProcess process = factory.validate().getProcess();
Resource resource = ResourceFactory
.newByteArrayResource(XmlRuleFlowProcessDumper.INSTANCE.dump(
process).getBytes());
resource.setSourcePath("/tmp/dynamicProcess.bpmn2"); // source path or target path must be set to be added into kbase
KieBase kbase = createKnowledgeBaseFromResources(resource);
StatefulKnowledgeSession ksession = createKnowledgeSession(kbase);
TestWorkItemHandler testHandler = new TestWorkItemHandler();
ksession.getWorkItemManager().registerWorkItemHandler("Human Task", testHandler);
ksession.addEventListener(new ProcessEventListener() {
public void beforeVariableChanged(ProcessVariableChangedEvent arg0) {
}
public void beforeProcessStarted(ProcessStartedEvent arg0) {
logger.info("{}", arg0);
}
public void beforeProcessCompleted(ProcessCompletedEvent arg0) {
logger.info("{}", arg0);
}
public void beforeNodeTriggered(ProcessNodeTriggeredEvent arg0) {
logger.info("{}", arg0);
}
public void beforeNodeLeft(ProcessNodeLeftEvent arg0) {
logger.info("{}", arg0);
}
public void afterVariableChanged(ProcessVariableChangedEvent arg0) {
}
public void afterProcessStarted(ProcessStartedEvent arg0) {
}
public void afterProcessCompleted(ProcessCompletedEvent arg0) {
}
public void afterNodeTriggered(ProcessNodeTriggeredEvent arg0) {
}
public void afterNodeLeft(ProcessNodeLeftEvent arg0) {
}
});
final ProcessInstanceImpl processInstance = (ProcessInstanceImpl)
ksession.startProcess("org.jbpm.HelloWorld");
HumanTaskNode node = new HumanTaskNode();
node.setName("Task2");
node.setId(4);
insertNodeInBetween(process, 2, 3, node);
((CommandBasedStatefulKnowledgeSession) ksession).getRunner().execute(new ExecutableCommand<Void>() {
public Void execute(Context context) {
StatefulKnowledgeSession ksession = (StatefulKnowledgeSession) ((RegistryContext) context).lookup( KieSession.class );
((ProcessInstanceImpl) ksession.getProcessInstance(processInstance.getId())).updateProcess(process);
return null;
}
});
assertProcessInstanceActive(processInstance);
ksession.getWorkItemManager().completeWorkItem(testHandler.getWorkItem().getId(), null);
assertProcessInstanceActive(processInstance);
ksession.getWorkItemManager().completeWorkItem(testHandler.getWorkItem().getId(), null);
assertProcessInstanceFinished(processInstance, ksession);
ksession.dispose();
}
private static void insertNodeInBetween(RuleFlowProcess process, long startNodeId, long endNodeId, NodeImpl node) {
if (process == null) {
throw new IllegalArgumentException("Process may not be null");
}
NodeImpl selectedNode = (NodeImpl) process.getNode(startNodeId);
if (selectedNode == null) {
throw new IllegalArgumentException("Node " + startNodeId + " not found in process " + process.getId());
}
for (Connection connection: selectedNode.getDefaultOutgoingConnections()) {
if (connection.getTo().getId() == endNodeId) {
process.addNode(node);
NodeImpl endNode = (NodeImpl) connection.getTo();
((ConnectionImpl) connection).terminate();
new ConnectionImpl(selectedNode, NodeImpl.CONNECTION_DEFAULT_TYPE, node, NodeImpl.CONNECTION_DEFAULT_TYPE);
new ConnectionImpl(node, NodeImpl.CONNECTION_DEFAULT_TYPE, endNode, NodeImpl.CONNECTION_DEFAULT_TYPE);
return;
}
}
throw new IllegalArgumentException("Connection to node " + endNodeId + " not found in process " + process.getId());
}
}