org.jbpm.sim.def.JbpmSimulationScenario Maven / Gradle / Ivy
package org.jbpm.sim.def;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.jbpm.JbpmContext;
import org.jbpm.graph.def.ProcessDefinition;
import org.jbpm.graph.exe.ProcessInstance;
import org.jbpm.sim.datasource.ProcessDataFilter;
import org.jbpm.sim.datasource.ProcessDataSource;
import org.jbpm.sim.event.StatisticsResetEvent;
import org.jbpm.sim.exception.ExperimentConfigurationException;
import org.jbpm.sim.jpdl.SimulationDefinition;
import org.jbpm.sim.kpi.BusinessFigure;
import org.jbpm.sim.report.InMemoryOutput;
import org.jbpm.sim.report.ScenarioReport;
import desmoj.core.report.Reporter;
import desmoj.core.simulator.Experiment;
import desmoj.core.simulator.SimTime;
/**
* The scenario is one special simulation run, which relates to one
* DESMO-J experiment (don't get confused, in the jbpm simulation an experiment
* consists of one or more simulation scenarios!).
*
* So can contain special configuration, for example for resource pools
* or distributions. This can reflect different business scenarios, staffing
* strategies or so on.
*
* All configurations will overwrite possible simulation configurations
* made in the process definition.
*
* An example XML for the scenario configuration:
*
*
*
*
*
*
*
*
*
*
* @author [email protected]
*/
public class JbpmSimulationScenario {
/**
* name of scenario
*/
private String name;
/**
* if set to false, the scenario is not executed in a simulation experiment
*/
private boolean execute = true;
/**
* list of processed configured to be available
* in this scenario
*/
private List processDefinitions = new ArrayList();
private List businessFigures = new ArrayList();
private JbpmSimulationModel model = null;
private ScenarioReport scenarioReport;
public JbpmSimulationScenario() {
this(null);
}
public JbpmSimulationScenario(String name) {
if (name==null)
this.name="DefaultScenario";
else
this.name = name;
}
public void changeName(String name) {
this.name = name;
}
public void addProcessDefinition(ProcessDefinition processDefinition) {
processDefinitions.add(processDefinition);
}
public void addDistribution(DistributionDefinition distDef) {
for (Iterator iterator = processDefinitions.iterator(); iterator.hasNext();) {
ProcessDefinition pd = (ProcessDefinition) iterator.next();
SimulationDefinition def = (SimulationDefinition) pd.getDefinition(SimulationDefinition.class);
def.overwriteDistribution(distDef);
}
}
public void addResourcePool(String poolName, Integer poolSize, Double costPerTimeUnit) {
for (Iterator iterator = processDefinitions.iterator(); iterator.hasNext();) {
ProcessDefinition pd = (ProcessDefinition) iterator.next();
SimulationDefinition def = (SimulationDefinition) pd.getDefinition(SimulationDefinition.class);
def.overwriteResourcePool(poolName, poolSize, costPerTimeUnit);
}
}
/**
* copied from desmoj.core.simulator.TimeConverter
, because there it is
* not public, but we need to have the date as string (unfortunately)
*/
static final String DATE_PATTERN = "dd.MM.yyyy HH:mm:ss:SSS";
public void runSimulation(JbpmSimulationExperiment jbpmExperiment, boolean writeHtmlReport, boolean rememberEndedProcessInstances) {
runSimulation(jbpmExperiment, writeHtmlReport, rememberEndedProcessInstances, 0);
}
public void runSimulation(JbpmSimulationExperiment jbpmExperiment, boolean writeHtmlReport, boolean rememberEndedProcessInstances, long seed) {
String reportOutputType = null;
if (writeHtmlReport)
reportOutputType = Experiment.DEFAULT_REPORT_OUTPUT_TYPE;
Experiment desmojExperiment = new Experiment(
jbpmExperiment.getName() + "." + getName(),
jbpmExperiment.getOutputPathName(),
// TODO: shouldn't be converted forth and back, use the REAL date
new SimpleDateFormat(DATE_PATTERN).format(jbpmExperiment.getRealStartDate()),
jbpmExperiment.getTimeUnit(),
reportOutputType,
null, //no trace instead of Experiment.DEFAULT_TRACE_OUTPUT_TYPE,
// specify an error file, otherwise we get a NullPointerException when an error is logged:
Experiment.DEFAULT_ERROR_OUTPUT_TYPE,
null); //no debug instead of Experiment.DEFAULT_DEBUG_OUTPUT_TYPE);
if (seed!=0) {
desmojExperiment.setSeedGenerator(seed);
}
// add our own reporter, to get the results later in memory
InMemoryOutput report = new InMemoryOutput();
desmojExperiment.addReceiver(report, Reporter.class);
// construct the simulation model & connect it to the experiment
DefaultJbpmSimulationModel model = new DefaultJbpmSimulationModel(
(ProcessDefinition[])processDefinitions.toArray(new ProcessDefinition[0]));
model.setRememberEndedProcessInstances(rememberEndedProcessInstances);
model.connectToExperiment(desmojExperiment);
// add statistic reset event if configured
if (jbpmExperiment.getResetTime()>0) {
StatisticsResetEvent evt = new StatisticsResetEvent(model);
evt.schedule(new SimTime(jbpmExperiment.getResetTime()));
}
// add business figure configurations
for (Iterator iterator = businessFigures.iterator(); iterator.hasNext();) {
BusinessFigure figure = (BusinessFigure) iterator.next();
// add a copy, because the object contains results afterwords
// which should not occur in the original configuration
model.addBusinessFigure(figure.copy());
}
// now set the time this simulation should stop at
desmojExperiment.stop(new SimTime(jbpmExperiment.getSimulationRunTime()));
desmojExperiment.setShowProgressBar(false);
desmojExperiment.start();
// save report
desmojExperiment.report();
scenarioReport = report.getReport();
// stop all threads still alive and close all output files
desmojExperiment.finish();
if (rememberEndedProcessInstances)
this.model = model;
else
this.model = null;
}
/**
* persists the process definitions created for this scenario
* and the process instances and all dependent stuff
*/
public void persist(JbpmContext ctx) {
for (Iterator iterator = processDefinitions.iterator(); iterator.hasNext();) {
ProcessDefinition pd = (ProcessDefinition) iterator.next();
ctx.deployProcessDefinition(pd);
}
for (Iterator iterator = model.getEndedProcessInstances().iterator(); iterator.hasNext();) {
ProcessInstance pi = (ProcessInstance) iterator.next();
ctx.save(pi);
}
}
public String getName() {
return name;
}
public ScenarioReport getScenarioReport() {
return scenarioReport;
}
public boolean isExecute() {
return execute;
}
public void setExecute(boolean execute) {
this.execute = execute;
}
public void addBusinessFigure(BusinessFigure figure) {
businessFigures.add(figure);
}
public void addDataSource(String name, String className) {
ProcessDataSource src = null;
try {
src = (ProcessDataSource) Class.forName(className).newInstance();
}
catch (Throwable ex) {
throw new ExperimentConfigurationException("Couldn't initialize data source '" + name + "' of type '" + className + "'", ex);
}
addDataSource(name, src);
}
public void addDataSource(String name, ProcessDataSource src) {
for (Iterator iterator = processDefinitions.iterator(); iterator.hasNext();) {
ProcessDefinition pd = (ProcessDefinition) iterator.next();
SimulationDefinition def = (SimulationDefinition) pd.getDefinition(SimulationDefinition.class);
def.addDataSource(name, src);
}
}
public void addDataFilter(String name, String className) {
ProcessDataFilter filter = null;
try {
filter = (ProcessDataFilter) Class.forName(className).newInstance();
}
catch (Throwable ex) {
throw new ExperimentConfigurationException("Couldn't initialize data filter '" + name + "' of type '" + className + "'", ex);
}
addDataFilter(name, filter);
}
public void addDataFilter(String name, ProcessDataFilter filter) {
for (Iterator iterator = processDefinitions.iterator(); iterator.hasNext();) {
ProcessDefinition pd = (ProcessDefinition) iterator.next();
SimulationDefinition def = (SimulationDefinition) pd.getDefinition(SimulationDefinition.class);
def.addDataFilter(name, filter);
}
}
/**
* @return list of process definitions. Basically helpful for unit tests
*/
public List getProcessDefinitions() {
return processDefinitions;
}
/**
* @return list of ended process instances. Basically helpful for unit tests
*/
public List getEndedProcessInstances() {
return model.getEndedProcessInstances();
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy