
org.jbpm.simulation.impl.BPMN2SimulationDataProvider 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.impl;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import bpsim.*;
import org.eclipse.bpmn2.BoundaryEvent;
import org.eclipse.bpmn2.BusinessRuleTask;
import org.eclipse.bpmn2.CancelEventDefinition;
import org.eclipse.bpmn2.CompensateEventDefinition;
import org.eclipse.bpmn2.ConditionalEventDefinition;
import org.eclipse.bpmn2.Definitions;
import org.eclipse.bpmn2.EndEvent;
import org.eclipse.bpmn2.ErrorEventDefinition;
import org.eclipse.bpmn2.EventDefinition;
import org.eclipse.bpmn2.ExclusiveGateway;
import org.eclipse.bpmn2.ExtensionAttributeValue;
import org.eclipse.bpmn2.FlowElement;
import org.eclipse.bpmn2.FlowElementsContainer;
import org.eclipse.bpmn2.InclusiveGateway;
import org.eclipse.bpmn2.IntermediateCatchEvent;
import org.eclipse.bpmn2.IntermediateThrowEvent;
import org.eclipse.bpmn2.LinkEventDefinition;
import org.eclipse.bpmn2.ManualTask;
import org.eclipse.bpmn2.MessageEventDefinition;
import org.eclipse.bpmn2.ParallelGateway;
import org.eclipse.bpmn2.Process;
import org.eclipse.bpmn2.ReceiveTask;
import org.eclipse.bpmn2.Relationship;
import org.eclipse.bpmn2.RootElement;
import org.eclipse.bpmn2.ScriptTask;
import org.eclipse.bpmn2.SendTask;
import org.eclipse.bpmn2.SequenceFlow;
import org.eclipse.bpmn2.ServiceTask;
import org.eclipse.bpmn2.SignalEventDefinition;
import org.eclipse.bpmn2.StartEvent;
import org.eclipse.bpmn2.TimerEventDefinition;
import org.eclipse.bpmn2.UserTask;
import org.eclipse.emf.ecore.util.FeatureMap;
import org.jbpm.simulation.SimulationDataProvider;
import org.jbpm.simulation.util.BPMN2Utils;
import org.jbpm.simulation.util.SimulationConstants;
import org.kie.api.definition.process.Node;
public class BPMN2SimulationDataProvider implements SimulationDataProvider {
private Definitions def;
public BPMN2SimulationDataProvider(Definitions def) {
this.def = def;
}
public BPMN2SimulationDataProvider(String bpmn2xml) {
this.def = BPMN2Utils.getDefinitions(new ByteArrayInputStream(getBytes(bpmn2xml)));
}
public BPMN2SimulationDataProvider(InputStream bpmn2Stream) {
this.def = BPMN2Utils.getDefinitions(bpmn2Stream);
}
public Map getSimulationDataForNode(Node node) {
String nodeId = (String) node.getMetaData().get("UniqueId");
return getSimulationDataForNode(nodeId);
}
public Map getSimulationDataForNode(
String nodeId) {
boolean reverse = false;
if (nodeId.startsWith("$reverseprops$")) {
reverse = true;
nodeId = nodeId.replaceFirst("\\$reverseprops\\$", "");
}
Map properties = new HashMap();
// default value for probability is 50
double defaultValue = 50.0;
if (reverse) {
defaultValue = 100 - defaultValue;
}
properties.put("probability", defaultValue);
Scenario scenario = getDefaultScenario(def);
if(scenario != null) {
String baseTimeUnitValue = "";
String baseCurrencyUnitValue = "";
if(scenario.getScenarioParameters() != null) {
baseCurrencyUnitValue = scenario.getScenarioParameters().getBaseCurrencyUnit();
baseTimeUnitValue = scenario.getScenarioParameters().getBaseTimeUnit().getName();
}
if(scenario.getElementParameters() != null) {
for(ElementParameters eleType : scenario.getElementParameters()) {
if(eleType.getElementRef().equals(nodeId)) {
if(eleType.getControlParameters() != null && eleType.getControlParameters().getProbability() != null) {
FlowElement element = null;
for (RootElement root : def.getRootElements()) {
if (root instanceof Process) {
element = findElementInContainer((FlowElementsContainer) root, nodeId);
if (element != null && element instanceof SequenceFlow) {
element = ((SequenceFlow)element).getSourceRef();
}
break;
}
}
if (element != null && element instanceof ParallelGateway) {
// probability should be ignored for parallel gateways so use default value
properties.put("probability", 100.0);
} else {
FloatingParameterType valType = (FloatingParameterType) eleType.getControlParameters().getProbability().getParameterValue().get(0);
double value = valType.getValue();
if (reverse) {
value = 100 - value;
}
properties.put("probability", value);
}
}
if(eleType.getTimeParameters() != null) {
if(eleType.getTimeParameters().getProcessingTime() != null) {
Parameter processingTime = eleType.getTimeParameters().getProcessingTime();
ParameterValue paramValue = processingTime.getParameterValue().get(0);
if(paramValue instanceof NormalDistributionType) {
NormalDistributionType ndt = (NormalDistributionType) paramValue;
properties.put("mean", ndt.getMean());
properties.put("standarddeviation", ndt.getStandardDeviation());
properties.put("distributiontype", "normal");
} else if(paramValue instanceof UniformDistributionType) {
UniformDistributionType udt = (UniformDistributionType) paramValue;
properties.put("max", udt.getMax());
properties.put("min", udt.getMin());
properties.put("distributiontype", "uniform");
// random distribution not supported in bpsim 1.0
// } else if(paramValue instanceof RandomDistributionType) {
// RandomDistributionType rdt = (RandomDistributionType) paramValue;
// properties.put("max", rdt.getMax());
// properties.put("min", rdt.getMin());
// properties.put("distributiontype", "random");
} else if(paramValue instanceof PoissonDistributionType) {
PoissonDistributionType pdt = (PoissonDistributionType) paramValue;
properties.put("mean", pdt.getMean());
properties.put("distributiontype", "poisson");
}
properties.put("timeunit", baseTimeUnitValue);
if(eleType.getTimeParameters().getWaitTime() != null) {
FloatingParameterType waittimeType = (FloatingParameterType) eleType.getTimeParameters().getWaitTime().getParameterValue().get(0);
properties.put("waittime", waittimeType.getValue());
}
}
}
if(eleType.getCostParameters() != null) {
CostParameters costParams = eleType.getCostParameters();
if(costParams.getUnitCost() != null) {
FloatingParameterType unitCostVal = (FloatingParameterType) costParams.getUnitCost().getParameterValue().get(0);
properties.put("unitcost", unitCostVal.getValue());
}
properties.put("currency", baseCurrencyUnitValue);
}
if(eleType.getResourceParameters() != null) {
ResourceParameters resourceParams = eleType.getResourceParameters();
if(resourceParams.getQuantity() != null) {
FloatingParameterType quantityVal = (FloatingParameterType) resourceParams.getQuantity().getParameterValue().get(0);
properties.put("quantity", quantityVal.getValue());
}
if(resourceParams.getAvailability() != null) {
FloatingParameterType workingHoursVal = (FloatingParameterType) resourceParams.getAvailability().getParameterValue().get(0);
properties.put("workinghours", workingHoursVal.getValue());
}
}
}
}
}
}
return properties;
}
protected FlowElement findElementInContainer(FlowElementsContainer container, String id) {
List currentContainerElems = container.getFlowElements();
for (FlowElement fElement : currentContainerElems) {
if (fElement.getId().equals(id) ) {
return fElement;
} else if (fElement instanceof FlowElementsContainer) {
FlowElement fe = findElementInContainer((FlowElementsContainer) fElement, id);
if (fe != null) {
return fe;
}
}
}
return null;
}
public double calculatePathProbability(SimulationPath path) {
double probability = 100;
Set processedSourceElems = new LinkedHashSet();
for (String sequenceFlowId : path.getSequenceFlowsIds()) {
String sourceElemId = path.getSeqenceFlowsSources().get(sequenceFlowId);
// need to test if given source (gateway) was already processed as it can be twice or more when loops are
// modeled in the process, for probability counting only single outgoing flow is taken - currently supports
// only XOR and AND gateways
if (processedSourceElems.contains(sourceElemId)) {
continue;
}
double transitionProbability = (Double) getSimulationDataForNode(sequenceFlowId).get(SimulationConstants.PROBABILITY);
if (transitionProbability >= 0) {
probability = probability * (transitionProbability / 100);
processedSourceElems.add(sourceElemId);
}
}
// calculate probability based on boundary events
for (String sequenceFlowId : path.getBoundaryEventIds()) {
double transitionProbability = (Double) getSimulationDataForNode(sequenceFlowId).get(SimulationConstants.PROBABILITY);
if (transitionProbability >= 0) {
probability = probability * (transitionProbability / 100);
}
}
double result = probability / 100;
path.setProbability(result);
return result;
}
public Map getProcessDataForNode(Node node) {
Map nodeProperties = new HashMap();
FlowElement flowElement = null;
List rootElements = def.getRootElements();
for (RootElement root : rootElements) {
if (root instanceof Process) {
flowElement = findElementInContainer((FlowElementsContainer) root, (String) node.getMetaData().get("UniqueId"));
break;
}
}
if (flowElement != null) {
if (flowElement instanceof ScriptTask) {
nodeProperties.put("node.type", "ScriptTask");
} else if (flowElement instanceof BusinessRuleTask) {
nodeProperties.put("node.type", "BusinessRuleTask");
} else if (flowElement instanceof UserTask) {
nodeProperties.put("node.type", "UserTask");
} else if (flowElement instanceof SendTask) {
nodeProperties.put("node.type", "SendTask");
} else if (flowElement instanceof ServiceTask) {
nodeProperties.put("node.type", "ServiceTask");
} else if (flowElement instanceof ReceiveTask) {
nodeProperties.put("node.type", "ReceiveTask");
} else if (flowElement instanceof ManualTask) {
nodeProperties.put("node.type", "ManualTask");
} else if (flowElement instanceof InclusiveGateway) {
nodeProperties.put("node.type", "InclusiveGateway");
} else if (flowElement instanceof ExclusiveGateway) {
nodeProperties.put("node.type", "ExclusiveGateway");
} else if (flowElement instanceof ParallelGateway) {
nodeProperties.put("node.type", "ParallelGateway");
} else if (flowElement instanceof BoundaryEvent) {
BoundaryEvent boundaryEvent = (BoundaryEvent) flowElement;
List defs = boundaryEvent.getEventDefinitions();
String eventDef = "";
if (defs != null && defs.size() > 0) {
eventDef = getEventDefinitionAsString(defs.get(0));
}
nodeProperties.put("node.type", "BoundaryEvent:"+eventDef);
} else if (flowElement instanceof IntermediateCatchEvent) {
IntermediateCatchEvent boundaryEvent = (IntermediateCatchEvent) flowElement;
List defs = boundaryEvent.getEventDefinitions();
String eventDef = "";
if (defs != null && defs.size() > 0) {
eventDef = getEventDefinitionAsString(defs.get(0));
}
nodeProperties.put("node.type", "IntermediateCatchEvent:"+eventDef);
} else if (flowElement instanceof IntermediateThrowEvent) {
IntermediateThrowEvent boundaryEvent = (IntermediateThrowEvent) flowElement;
List defs = boundaryEvent.getEventDefinitions();
String eventDef = "";
if (defs != null && defs.size() > 0) {
eventDef = getEventDefinitionAsString(defs.get(0));
}
nodeProperties.put("node.type", "IntermediateThrowEvent:"+eventDef);
} else if (flowElement instanceof StartEvent) {
StartEvent boundaryEvent = (StartEvent) flowElement;
List defs = boundaryEvent.getEventDefinitions();
String eventDef = "";
if (defs != null && defs.size() > 0) {
eventDef = getEventDefinitionAsString(defs.get(0));
}
nodeProperties.put("node.type", "StartEvent:"+eventDef);
} else if (flowElement instanceof EndEvent) {
EndEvent boundaryEvent = (EndEvent) flowElement;
List defs = boundaryEvent.getEventDefinitions();
String eventDef = "";
if (defs != null && defs.size() > 0) {
eventDef = getEventDefinitionAsString(defs.get(0));
}
nodeProperties.put("node.type", "EndEvent:"+eventDef);
}
} else {
nodeProperties.put("node.type", "unknown");
}
return nodeProperties;
}
private static byte[] getBytes(String string) {
try {
return string.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
throw new IllegalArgumentException(e.getMessage());
}
}
private Scenario getDefaultScenario(Definitions def) {
if(def.getRelationships() != null && def.getRelationships().size() > 0) {
// current support for single relationship
Relationship relationship = def.getRelationships().get(0);
for(ExtensionAttributeValue extattrval : relationship.getExtensionValues()) {
FeatureMap extensionElements = extattrval.getValue();
@SuppressWarnings("unchecked")
List bpsimExtension = (List) extensionElements.get(BpsimPackage.Literals.DOCUMENT_ROOT__BP_SIM_DATA, true);
if(bpsimExtension != null && bpsimExtension.size() > 0) {
BPSimDataType bpmsim = bpsimExtension.get(0);
if(bpmsim.getScenario() != null && bpmsim.getScenario().size() > 0) {
return bpmsim.getScenario().get(0);
}
}
}
}
return null;
}
protected String getEventDefinitionAsString(EventDefinition eventDefinition) {
if (eventDefinition instanceof SignalEventDefinition) {
return "signalEventDefinition";
} else if (eventDefinition instanceof MessageEventDefinition) {
return "messageEventDefinition";
} else if (eventDefinition instanceof LinkEventDefinition) {
return "linkEventDefinition";
} else if (eventDefinition instanceof CompensateEventDefinition) {
return "compensateEventDefinition";
} else if (eventDefinition instanceof ErrorEventDefinition) {
return "errorEventDefinition";
} else if (eventDefinition instanceof TimerEventDefinition) {
return "timerEventDefinition";
} else if (eventDefinition instanceof ConditionalEventDefinition) {
return "conditionalEventDefinition";
} else if (eventDefinition instanceof CancelEventDefinition) {
return "cancelEventDefinition";
}
return "unknown";
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy