
org.jbpm.simulation.SimulationRunner Maven / Gradle / Ivy
/*
* 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.simulation;
import java.util.List;
import org.drools.core.command.NewKieSessionCommand;
import org.drools.core.command.SetVariableCommandFromLastReturn;
import org.drools.core.command.impl.GenericCommand;
import org.drools.core.command.runtime.DisposeCommand;
import org.drools.simulation.fluent.session.KieSessionSimulationFluent;
import org.drools.simulation.fluent.session.impl.DefaultStatefulKnowledgeSessionSimFluent;
import org.drools.simulation.fluent.simulation.SimulationFluent;
import org.drools.simulation.fluent.simulation.impl.DefaultSimulationFluent;
import org.jbpm.process.core.validation.ProcessValidatorRegistry;
import org.jbpm.simulation.converter.SimulationFilterPathFormatConverter;
import org.jbpm.simulation.impl.BPMN2SimulationDataProvider;
import org.jbpm.simulation.impl.SimulateProcessPathCommand;
import org.jbpm.simulation.impl.SimulationPath;
import org.jbpm.simulation.impl.SimulationProcessValidator;
import org.jbpm.simulation.impl.WorkingMemorySimulationRepository;
import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.KieModule;
import org.kie.api.builder.Message;
import org.kie.api.builder.ReleaseId;
import org.kie.api.builder.model.KieBaseModel;
import org.kie.api.builder.model.KieModuleModel;
import org.kie.api.builder.model.KieSessionModel;
import org.kie.api.conf.EqualityBehaviorOption;
import org.kie.api.conf.EventProcessingOption;
import org.kie.api.io.Resource;
import org.kie.api.io.ResourceType;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.conf.ClockTypeOption;
import org.kie.internal.command.Context;
import org.kie.internal.io.ResourceFactory;
import org.kie.internal.runtime.StatefulKnowledgeSession;
public class SimulationRunner {
static {
ProcessValidatorRegistry.getInstance().registerAdditonalValidator(new SimulationProcessValidator());
}
public static SimulationRepository runSimulation(String processId, String bpmn2Container, int numberOfAllInstances, long interval, String... rules) {
return runSimulation(processId, bpmn2Container, numberOfAllInstances, interval, false, rules);
}
public static SimulationRepository runSimulation(String processId, String bpmn2Container, int numberOfAllInstances, long interval, boolean runRules, String... rules) {
Resource[] resources = new Resource[rules.length];
for (int i = 0; i < rules.length; i++) {
resources[i] = ResourceFactory.newClassPathResource(rules[i]);
}
return runSimulation(processId, bpmn2Container, numberOfAllInstances, interval, runRules, resources);
}
public static SimulationRepository runSimulation(String processId, String bpmn2Container, int numberOfAllInstances, long interval, boolean runRules, Resource... rules) {
SimulationContext context = SimulationContextFactory.newContext(new BPMN2SimulationDataProvider(bpmn2Container), new WorkingMemorySimulationRepository(runRules, rules));
SimulationDataProvider provider = context.getDataProvider();
PathFinder finder = PathFinderFactory.getInstance(bpmn2Container);
List paths = finder.findPaths(new SimulationFilterPathFormatConverter(provider));
// TODO when introduced configurable start time that should be used instead of currentTimeMillis
context.getRepository().setSimulationInfo(new SimulationInfo(System.currentTimeMillis(), processId, numberOfAllInstances, interval));
final ReleaseId releaseId = createKJarWithMultipleResources(processId,
new String[]{bpmn2Container}, new ResourceType[]{ResourceType.BPMN2});
SimulationFluent f = new DefaultSimulationFluent(){
final KieServices kieServices = KieServices.Factory.get();
final KieContainer kieContainer = kieServices.newKieContainer( releaseId );
@Override
public KieSessionSimulationFluent newKieSession(final ReleaseId releaseId, final String id) {
assureActiveStep();
activeKieSessionId = id == null ? DEFAULT_ID : id;
addCommand( new NewKieSessionCommand(null, null) {
@Override
public KieSession execute(Context context) {
return id != null ? kieContainer.newKieSession( id ) : kieContainer.newKieSession();
}
});
addCommand( new SetVariableCommandFromLastReturn( StatefulKnowledgeSession.class.getName() ) );
return new DefaultStatefulKnowledgeSessionSimFluent( this );
}
};
// @formatter:off
int counter = 0;
int remainingInstances = numberOfAllInstances;
for (SimulationPath path : paths) {
// only paths that can be started are considered
if (!path.isStartable()) {
continue;
}
double probability = path.getProbability();
f.newPath("path" + counter);
int instancesOfPath = 1;
// count how many instances/steps should current path have
if (numberOfAllInstances > 1) {
instancesOfPath = (int) Math.round((numberOfAllInstances * probability));
// ensure that we won't exceed total number of instance due to rounding
if (instancesOfPath > remainingInstances) {
instancesOfPath = remainingInstances;
}
remainingInstances -= instancesOfPath;
for (int i = 0; i < instancesOfPath; i++) {
f.newStep( interval * i )
.newKieSession( releaseId, null)
.end()
.addCommand(new SimulateProcessPathCommand(processId, context, path))
.addCommand( new SetVariableCommandFromLastReturn( StatefulKnowledgeSession.class.getName() ))
.addCommand(new DisposeCommand());
}
} else {
f.newStep(interval)
.newKieSession(releaseId, null)
.end()
.addCommand(new SimulateProcessPathCommand(processId, context, path))
.addCommand( new SetVariableCommandFromLastReturn( StatefulKnowledgeSession.class.getName() ))
.addCommand(new DisposeCommand());
break;
}
counter++;
// currently standalone paths within single definition are not supported
// if (probability == 1) {
// // in case given path has probability of 100% there is a need to reset the remaining instances
// // as this is standalone process path
// remainingInstances = numberOfAllInstances;
// }
}
f.runSimulation();
// @formatter:on
context.getRepository().getSimulationInfo().setEndTime(context.getMaxEndTime());
return context.getRepository();
}
protected static ReleaseId createKJarWithMultipleResources(String id, String[] resources, ResourceType[] types) {
KieServices ks = KieServices.Factory.get();
KieModuleModel kproj = ks.newKieModuleModel();
KieFileSystem kfs = ks.newKieFileSystem();
kfs.writePomXML(getPom("org.jbpm.sim", id, "1.0"));
for (int i = 0; i < resources.length; i++) {
String res = resources[i];
String type = types[i].getDefaultExtension();
kfs.write("src/main/resources/" + id.replaceAll("\\.", "/")
+ "/org/test/res" + i + ".bpsim." + type, res);
}
KieBaseModel kBase1 = kproj.newKieBaseModel(id)
.setEqualsBehavior(EqualityBehaviorOption.EQUALITY)
.setEventProcessingMode(EventProcessingOption.STREAM)
.setDefault(true);
KieSessionModel ksession1 = kBase1
.newKieSessionModel(id + ".KSession1")
.setType(KieSessionModel.KieSessionType.STATEFUL)
.setClockType(ClockTypeOption.get("pseudo"))
.setDefault(true);
kfs.writeKModuleXML(kproj.toXML());
KieBuilder kieBuilder = ks.newKieBuilder(kfs).buildAll();
if(!kieBuilder.getResults().getMessages().isEmpty()) {
for (Message msg : kieBuilder.getResults().getMessages()) {
System.out.println("[ERROR]" + msg.getText());
}
throw new RuntimeException("Error building knowledge base, see previous errors");
}
KieModule kieModule = kieBuilder.getKieModule();
return kieModule.getReleaseId();
}
protected static String getPom(String groupId, String artifactId, String version) {
String pom =
"\n" +
"\n" +
" 4.0.0 \n" +
"\n" +
" " + groupId + " \n" +
" " + artifactId + " \n" +
" " + version + " \n" +
"\n";
pom += " ";
return pom;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy