use of de.hpi.bpt.scylla.model.process.node.GatewayType in project scylla by bptlab.
the class ProcessModelParser method parseProcess.
private ProcessModel parseProcess(Element process, Namespace bpmnNamespace, boolean hasParentModel, CommonProcessElements commonProcessElements) throws ScyllaValidationException {
if (!hasParentModel && process.getChildren("startEvent", bpmnNamespace).size() == 0) {
throw new ScyllaValidationException("No start event in the top process.");
}
String processId = process.getAttributeValue("id");
String processName = process.getAttributeValue("name");
Graph<Integer> graph = new Graph<Integer>();
Map<Integer, String> identifiers = new HashMap<Integer, String>();
Map<String, Integer> identifiersToNodeIds = new HashMap<String, Integer>();
Map<Integer, String> displayNames = new HashMap<Integer, String>();
// node id must be key of any of the following
Map<Integer, ProcessModel> subProcesses = new HashMap<Integer, ProcessModel>();
Map<Integer, String> calledElementsOfCallActivities = new HashMap<Integer, String>();
Map<Integer, TaskType> tasks = new HashMap<Integer, TaskType>();
Map<Integer, GatewayType> gateways = new HashMap<Integer, GatewayType>();
Map<Integer, EventType> eventTypes = new HashMap<Integer, EventType>();
// optional
Map<Integer, Map<String, String>> nodeAttributes = new HashMap<Integer, Map<String, String>>();
Map<Integer, String> conditionExpressions = new HashMap<Integer, String>();
Map<Integer, Set<String>> resourceReferences = new HashMap<Integer, Set<String>>();
Map<Integer, Map<EventDefinitionType, Map<String, String>>> eventDefinitions = new HashMap<Integer, Map<EventDefinitionType, Map<String, String>>>();
Map<Integer, Boolean> cancelActivities = new HashMap<Integer, Boolean>();
Map<Integer, List<Integer>> referencesToBoundaryEvents = new HashMap<Integer, List<Integer>>();
Map<Integer, BatchActivity> batchActivities = new HashMap<Integer, BatchActivity>();
// TODO support more than standard data objects (i.e. support input, output)
Graph<Integer> dataObjectsGraph = new Graph<Integer>();
Map<Integer, String> dataObjectReferences = new HashMap<Integer, String>();
Map<Integer, DataObjectType> dataObjectTypes = new HashMap<Integer, DataObjectType>();
// TODO parse loop / multi instance elements
Map<Integer, Element> boundaryEvents = new HashMap<Integer, Element>();
Map<Integer, Element> sequenceFlows = new HashMap<Integer, Element>();
// not only tasks anymore, also events
Map<Integer, List<Element>> tasksWithDataInputAssociations = new HashMap<Integer, List<Element>>();
// not only tasks anymore, also events
Map<Integer, List<Element>> tasksWithDataOutputAssociations = new HashMap<Integer, List<Element>>();
int nodeId = 1;
for (Element el : process.getChildren()) {
String elementName = el.getName();
if (isKnownElement(elementName)) {
String identifier = el.getAttributeValue("id");
identifiers.put(nodeId, identifier);
identifiersToNodeIds.put(identifier, nodeId);
String displayName = el.getAttributeValue("name");
if (displayName != null && !displayName.isEmpty()) {
displayNames.put(nodeId, displayName);
}
if (elementName.equals("sequenceFlow")) {
// just store them for now, use later to build graph
sequenceFlows.put(nodeId, el);
// store expressions after gateway conditions
Element conditionExpression = el.getChild("conditionExpression", bpmnNamespace);
if (conditionExpression != null) {
conditionExpressions.put(nodeId, conditionExpression.getText());
}
} else if (elementName.equals("subProcess")) {
batchActivities = parseExtensions(el, bpmnNamespace, nodeId, batchActivities);
ProcessModel subProcessModel = parseProcess(el, bpmnNamespace, true, commonProcessElements);
subProcesses.put(nodeId, subProcessModel);
} else if (elementName.equals("callActivity")) {
String calledElement = el.getAttributeValue("calledElement");
if (calledElement != null) {
calledElementsOfCallActivities.put(nodeId, calledElement);
}
} else if (elementName.equals("task") || elementName.endsWith("Task")) {
batchActivities = parseExtensions(el, bpmnNamespace, nodeId, batchActivities);
tasks.put(nodeId, TaskType.getEnum(el.getName()));
if (elementName.equals("userTask") || elementName.equals("manualTask")) {
String[] resourceElementNames = new String[] { "resourceRole", "performer", "humanPerformer", "potentialOwner" };
for (String ren : resourceElementNames) {
Element elem = el.getChild(ren, bpmnNamespace);
if (elem != null) {
String resourceRefOrAssignmentExpression = null;
Element resourceRefElement = elem.getChild("resourceRef", bpmnNamespace);
if (resourceRefElement != null) {
resourceRefOrAssignmentExpression = resourceRefElement.getText();
}
Element resourceAssignmentExpressionElement = elem.getChild("resourceAssignmentExpression", bpmnNamespace);
if (resourceAssignmentExpressionElement != null) {
resourceRefOrAssignmentExpression = resourceAssignmentExpressionElement.getText();
}
if (resourceRefOrAssignmentExpression != null) {
if (!resourceReferences.containsKey(nodeId)) {
resourceReferences.put(nodeId, new TreeSet<String>());
}
resourceReferences.get(nodeId).add(resourceRefOrAssignmentExpression);
break;
}
}
}
}
List<Element> dataInElements = el.getChildren("dataInputAssociation", bpmnNamespace);
if (!dataInElements.isEmpty()) {
tasksWithDataInputAssociations.put(nodeId, dataInElements);
}
List<Element> dataOutElements = el.getChildren("dataOutputAssociation", bpmnNamespace);
if (!dataOutElements.isEmpty()) {
tasksWithDataOutputAssociations.put(nodeId, dataOutElements);
}
} else if (elementName.endsWith("Gateway") || elementName.equals("gateway")) {
gateways.put(nodeId, GatewayType.getEnum(el.getName()));
Map<String, String> gatewayAttributes = new HashMap<String, String>();
String defaultFlow = el.getAttributeValue("default");
if (defaultFlow != null) {
gatewayAttributes.put("default", defaultFlow);
}
String gatewayDirection = el.getAttributeValue("gatewayDirection");
if (gatewayDirection != null) {
gatewayAttributes.put("gatewayDirection", gatewayDirection);
}
nodeAttributes.put(nodeId, gatewayAttributes);
} else if (elementName.endsWith("Event") || elementName.equals("event")) {
eventTypes.put(nodeId, EventType.getEnum(el.getName()));
Map<EventDefinitionType, Map<String, String>> eventDefinitionsOfElement = new HashMap<EventDefinitionType, Map<String, String>>();
for (EventDefinitionType edt : EventDefinitionType.values()) {
Element edElem = el.getChild(edt.toString(), bpmnNamespace);
if (edElem != null) {
Map<String, String> eventAttributes = new HashMap<String, String>();
if (edt == EventDefinitionType.CANCEL) {
// TODO transaction subprocesses only
} else if (edt == EventDefinitionType.COMPENSATION) {
String activityRef = edElem.getAttributeValue("activityRef");
if (activityRef != null) {
eventAttributes.put("activityRef", activityRef);
}
String waitForCompletion = edElem.getAttributeValue("waitForCompletion");
if (waitForCompletion != null) {
eventAttributes.put("waitForCompletion", waitForCompletion);
}
} else if (edt == EventDefinitionType.CONDITIONAL) {
Element conditionElement = edElem.getChild("condition", bpmnNamespace);
if (conditionElement != null) {
eventAttributes.put("condition", conditionElement.getText());
}
} else if (edt == EventDefinitionType.ERROR) {
String errorRef = edElem.getAttributeValue("errorRef");
if (errorRef != null) {
if (!commonProcessElements.getErrors().containsKey(errorRef)) {
throw new ScyllaValidationException("Referenced object of error event " + identifier + " is unknown: " + errorRef);
}
eventAttributes.put("errorRef", errorRef);
} else {
throw new ScyllaValidationException("Error event " + identifier + " has no reference to an error.");
}
} else if (edt == EventDefinitionType.ESCALATION) {
String escalationRef = edElem.getAttributeValue("escalationRef");
if (escalationRef != null) {
if (!commonProcessElements.getEscalations().containsKey(escalationRef)) {
throw new ScyllaValidationException("Referenced object of escalation event " + identifier + " is unknown: " + escalationRef);
}
eventAttributes.put("escalationRef", escalationRef);
} else {
throw new ScyllaValidationException("Escalation event " + identifier + " has no reference to an escalation.");
}
} else if (edt == EventDefinitionType.LINK) {
String name = edElem.getAttributeValue("name");
if (name != null) {
eventAttributes.put("name", name);
}
List<Element> sourceElements = edElem.getChildren("source", bpmnNamespace);
int i = 0;
for (Element sourceElement : sourceElements) {
eventAttributes.put("source" + ++i, sourceElement.getText());
}
Element targetElement = edElem.getChild("target", bpmnNamespace);
if (targetElement != null) {
eventAttributes.put("target", targetElement.getText());
}
} else if (edt == EventDefinitionType.MESSAGE) {
String messageRef = edElem.getAttributeValue("messageRef");
if (messageRef != null) {
if (!commonProcessElements.getMessages().containsKey(messageRef)) {
throw new ScyllaValidationException("Referenced object of message event " + identifier + " is unknown: " + messageRef);
}
eventAttributes.put("messageRef", messageRef);
}
Element operationElement = edElem.getChild("operationRef", bpmnNamespace);
if (operationElement != null) {
eventAttributes.put("operationRef", operationElement.getText());
}
} else if (edt == EventDefinitionType.SIGNAL) {
String signalRef = edElem.getAttributeValue("signalRef");
if (signalRef != null) {
eventAttributes.put("signalRef", signalRef);
}
} else if (edt == EventDefinitionType.TIMER) {
Element timeDateElement = edElem.getChild("timeDate", bpmnNamespace);
// this is the reponsibility of the plug-ins
if (timeDateElement != null) {
eventAttributes.put("timeDate", timeDateElement.getText());
}
Element timeCycleElement = edElem.getChild("timeCycle", bpmnNamespace);
if (timeCycleElement != null) {
eventAttributes.put("timeCycle", timeCycleElement.getText());
}
Element timeDurationElement = edElem.getChild("timeDuration", bpmnNamespace);
if (timeDurationElement != null) {
eventAttributes.put("timeDuration", timeDurationElement.getText());
}
// time attributes are mutually exclusive
if (eventAttributes.size() > 1) {
throw new ScyllaValidationException("Timer event " + identifier + " is invalid. Time definitions are mutually exclusive.");
}
}
eventDefinitionsOfElement.put(edt, eventAttributes);
}
eventDefinitions.put(nodeId, eventDefinitionsOfElement);
if (elementName.equals("boundaryEvent")) {
// just store them for now, use later to create references to boundary events
boundaryEvents.put(nodeId, el);
}
}
List<Element> dataInElements = el.getChildren("dataInputAssociation", bpmnNamespace);
if (!dataInElements.isEmpty()) {
tasksWithDataInputAssociations.put(nodeId, dataInElements);
}
List<Element> dataOutElements = el.getChildren("dataOutputAssociation", bpmnNamespace);
if (!dataOutElements.isEmpty()) {
tasksWithDataOutputAssociations.put(nodeId, dataOutElements);
}
} else if (elementName.equals("dataObjectReference")) {
String dataObjectRef = el.getAttributeValue("dataObjectRef");
dataObjectReferences.put(nodeId, dataObjectRef);
} else if (elementName.equals("ioSpecification")) {
Element input = el.getChild("dataInput", bpmnNamespace);
if (input != null) {
// remove the ioSpecification element
identifiersToNodeIds.remove(identifier);
// override the values with the inner input element
identifier = input.getAttributeValue("id");
identifiers.put(nodeId, identifier);
identifiersToNodeIds.put(identifier, nodeId);
displayName = input.getAttributeValue("name");
if (displayName != null && !displayName.isEmpty()) {
displayNames.put(nodeId, displayName);
}
dataObjectTypes.put(nodeId, DataObjectType.INPUT);
}
} else if (elementName.equals("dataObject")) {
dataObjectTypes.put(nodeId, DataObjectType.DEFAULT);
} else {
DebugLogger.log("Element " + el.getName() + " of process model is expected to be known, but not supported.");
}
nodeId++;
} else {
DebugLogger.log("Element " + el.getName() + " of process model not supported.");
}
}
// create resource references
for (Element laneSet : process.getChildren("laneSet", bpmnNamespace)) {
for (Element lane : laneSet.getChildren("lane", bpmnNamespace)) {
String resourceName = lane.getAttributeValue("name");
for (Element flowNodeRef : lane.getChildren("flowNodeRef", bpmnNamespace)) {
String elementId = flowNodeRef.getText();
Integer nId = identifiersToNodeIds.get(elementId);
if (!resourceReferences.containsKey(nId)) {
resourceReferences.put(nId, new TreeSet<String>());
}
resourceReferences.get(nId).add(resourceName);
}
}
}
for (Integer nId : boundaryEvents.keySet()) {
Element boundaryEvent = boundaryEvents.get(nId);
// interrupting or not?
// initially true, because at least "Camunda Modeler" does not set the cancelActivity value if it is an interrupting activity
boolean cancelActivity;
if (boundaryEvent.getAttributeValue("cancelActivity") != null) {
cancelActivity = Boolean.valueOf(boundaryEvent.getAttributeValue("cancelActivity"));
} else {
cancelActivity = true;
}
cancelActivities.put(nId, cancelActivity);
// attached to?
String attachedTo = boundaryEvent.getAttributeValue("attachedToRef");
int nodeIdOfAttachedTo = identifiersToNodeIds.get(attachedTo);
if (!referencesToBoundaryEvents.containsKey(nodeIdOfAttachedTo)) {
referencesToBoundaryEvents.put(nodeIdOfAttachedTo, new ArrayList<Integer>());
}
referencesToBoundaryEvents.get(nodeIdOfAttachedTo).add(nId);
}
// System.out.println("-----------NORMALFLOW-------------");
for (Integer nId : sequenceFlows.keySet()) {
Element sequenceFlow = sequenceFlows.get(nId);
String sourceRef = sequenceFlow.getAttributeValue("sourceRef");
String targetRef = sequenceFlow.getAttributeValue("targetRef");
int sourceId = identifiersToNodeIds.get(sourceRef);
int targetId = identifiersToNodeIds.get(targetRef);
graph.addEdge(sourceId, nId);
// System.out.println(identifiers.get(sourceId)+" -> "+identifiers.get(nId)+" -> "+identifiers.get(targetId));
graph.addEdge(nId, targetId);
}
// System.out.println("-----------DATAFLOWOUT-------------");
for (Integer nId : tasksWithDataInputAssociations.keySet()) {
List<Element> dataInputAssociations = tasksWithDataInputAssociations.get(nId);
for (Element elem : dataInputAssociations) {
String sourceRef = elem.getChild("sourceRef", bpmnNamespace).getText();
if (identifiersToNodeIds.containsKey(sourceRef)) {
int dataObjectNodeId = identifiersToNodeIds.get(sourceRef);
// System.out.println(identifiers.get(dataObjectNodeId)+" -> "+identifiers.get(nId));
dataObjectsGraph.addEdge(dataObjectNodeId, nId);
/*Map<Integer, Node<Integer>> nodes = dataObjectsGraph.getNodes();
Node<Integer> currentNode = nodes.get(nId);
currentNode.setId(identifiers.get(nId));
currentNode = nodes.get(dataObjectNodeId);
currentNode.setId(identifiers.get(dataObjectNodeId));*/
}
// String targetRef = elem.getChild("targetRef", bpmnNamespace).getText();
}
}
// System.out.println("-----------DATAFLOWIN-------------");
for (Integer nId : tasksWithDataOutputAssociations.keySet()) {
List<Element> dataOutputAssociations = tasksWithDataOutputAssociations.get(nId);
for (Element elem : dataOutputAssociations) {
// String sourceRef = elem.getChild("sourceRef", bpmnNamespace).getText();
String targetRef = elem.getChild("targetRef", bpmnNamespace).getText();
if (identifiersToNodeIds.containsKey(targetRef)) {
int dataObjectNodeId = identifiersToNodeIds.get(targetRef);
// System.out.println(identifiers.get(nId)+" -> "+identifiers.get(dataObjectNodeId));
dataObjectsGraph.addEdge(nId, dataObjectNodeId);
/*Map<Integer, Node<Integer>> nodes = dataObjectsGraph.getNodes();
Node<Integer> currentNode = nodes.get(nId);
currentNode.setId(identifiers.get(nId));
currentNode = nodes.get(dataObjectNodeId);
currentNode.setId(identifiers.get(dataObjectNodeId));*/
}
}
}
ProcessModel processModel = new ProcessModel(processId, process, graph, identifiers, identifiersToNodeIds, displayNames, subProcesses, calledElementsOfCallActivities, tasks, gateways, eventTypes);
processModel.setName(processName);
processModel.setNodeAttributes(nodeAttributes);
processModel.setConditionExpressions(conditionExpressions);
processModel.setResourceReferences(resourceReferences);
processModel.setEventDefinitions(eventDefinitions);
processModel.setCancelActivities(cancelActivities);
processModel.setReferencesToBoundaryEvents(referencesToBoundaryEvents);
processModel.setDataObjectsGraph(dataObjectsGraph);
processModel.setDataObjectTypes(dataObjectTypes);
processModel.setDataObjectReferences(dataObjectReferences);
processModel.setBatchActivities(batchActivities);
batchActivities.forEach((key, value) -> value.setProcessModel(processModel));
for (Integer subProcessId : subProcesses.keySet()) {
ProcessModel subProcessModel = subProcesses.get(subProcessId);
subProcessModel.setNodeIdInParent(subProcessId);
subProcessModel.setParent(processModel);
}
// System.out.println(dataObjectsGraph);
return processModel;
}
use of de.hpi.bpt.scylla.model.process.node.GatewayType in project scylla by bptlab.
the class ExclusiveGatewayEventPlugin method eventRoutine.
@SuppressWarnings("unchecked")
@Override
public void eventRoutine(GatewayEvent desmojEvent, ProcessInstance processInstance) throws ScyllaRuntimeException {
SimulationModel model = (SimulationModel) desmojEvent.getModel();
ProcessModel processModel = processInstance.getProcessModel();
int nodeId = desmojEvent.getNodeId();
boolean showInTrace = desmojEvent.traceIsOn();
GatewayType type = processModel.getGateways().get(nodeId);
ProcessSimulationComponents desmojObjects = desmojEvent.getDesmojObjects();
try {
Set<Integer> idsOfNextNodes = processModel.getIdsOfNextNodes(nodeId);
if (idsOfNextNodes.size() > 1) {
// split
if (type == GatewayType.DEFAULT || type == GatewayType.EXCLUSIVE) {
Map<Integer, Object> branchingDistributions = desmojObjects.getExtensionDistributions().get(getName());
DiscreteDistEmpirical<Integer> distribution = (DiscreteDistEmpirical<Integer>) branchingDistributions.get(nodeId);
// decide on next node
if (distribution != null) {
// if a distribution is given take this
Integer nextFlowId = distribution.sample().intValue();
if (!processModel.getIdentifiers().keySet().contains(nextFlowId)) {
throw new ScyllaValidationException("Flow with id " + nextFlowId + " does not exist.");
}
scheduleNextEvent(desmojEvent, processInstance, processModel, nextFlowId);
} else {
// otherwise try to get information out of the describing branches and branch on the basis of this
Map<Class<?>, ArrayList<PluginWrapper>> a = PluginLoader.getDefaultPluginLoader().getExtensions();
Collection<ArrayList<PluginWrapper>> plugins = a.values();
Boolean dataObjectPluginOn = false;
for (ArrayList<PluginWrapper> plugin : plugins) {
for (PluginWrapper p : plugin) {
if (p.toString().equals("DataObjectSCParserPlugin")) {
dataObjectPluginOn = true;
}
}
}
if (dataObjectPluginOn) {
Object[] outgoingRefs = processModel.getGraph().getTargetObjects(nodeId).toArray();
Integer DefaultPath = null;
Boolean foundAWay = false;
for (Object or : outgoingRefs) {
// go through all outgoing references
if (or.equals(getKeyByValue(processModel.getIdentifiers(), processModel.getNodeAttributes().get(desmojEvent.getNodeId()).get("default")))) {
// if it's the default path jump it
DefaultPath = (Integer) or;
continue;
}
String[] conditions = processModel.getDisplayNames().get(or).split("&&");
Integer nextFlowId = (Integer) or;
List<Boolean> test = new ArrayList<>();
for (String condition : conditions) {
condition = condition.trim();
String field = null;
String value = null;
String comparison = null;
if (condition.contains("==")) {
field = condition.split("==")[0];
value = condition.split("==")[1];
// value = processModel.getDisplayNames().get(or).substring(2, processModel.getDisplayNames().get(or).length());
comparison = "equal";
} else if (condition.contains(">=")) {
field = condition.split(">=")[0];
value = condition.split(">=")[1];
comparison = "greaterOrEqual";
} else if (condition.contains("<=")) {
field = condition.split("<=")[0];
value = condition.split("<=")[1];
comparison = "lessOrEqual";
} else if (condition.contains("!=")) {
field = condition.split("!=")[0];
value = condition.split("!=")[1];
comparison = "notEqual";
} else if (condition.contains("=")) {
field = condition.split("=")[0];
value = condition.split("=")[1];
comparison = "equal";
} else if (condition.contains("<")) {
field = condition.split("<")[0];
value = condition.split("<")[1];
comparison = "less";
} else if (condition.contains(">")) {
field = condition.split(">")[0];
value = condition.split(">")[1];
comparison = "greater";
} else {
throw new ScyllaValidationException("Condition " + condition + " does not have a comparison-operator");
}
value = value.trim();
field = field.trim();
Object fieldValue = DataObjectField.getDataObjectValue(processInstance.getId(), field);
if (!isParsableAsLong(value) || !isParsableAsLong((String.valueOf(fieldValue)))) {
// try a long comparison
Integer comparisonResult = (String.valueOf(fieldValue)).trim().compareTo(String.valueOf(value));
if (comparison.equals("equal") && comparisonResult == 0) {
break;
} else if (comparison.equals("notEqual") && comparisonResult != 0) {
break;
} else {
test.add(false);
}
} else {
// otherwise do a string compare
Long LongValue = Long.valueOf(value);
Long dOValue = Long.valueOf((String.valueOf(fieldValue)));
Integer comparisonResult = (dOValue.compareTo(LongValue));
if (comparison.equals("equal") && comparisonResult == 0) {
} else if (comparison.equals("less") && comparisonResult < 0) {
} else if (comparison.equals("greater") && comparisonResult > 0) {
} else if (comparison.equals("greaterOrEqual") && comparisonResult >= 0) {
} else if (comparison.equals("lessOrEqual") && comparisonResult <= 0) {
} else {
test.add(false);
}
}
}
if (test.size() == 0) {
scheduleNextEvent(desmojEvent, processInstance, processModel, nextFlowId);
foundAWay = true;
}
}
if (!foundAWay && DefaultPath != null) {
scheduleNextEvent(desmojEvent, processInstance, processModel, DefaultPath);
} else if (!foundAWay && DefaultPath == null) {
// everything will be killed, logical error
throw new ScyllaValidationException("No Default Path for " + desmojEvent.getDisplayName() + " given and outgoing branches not complete. No branch matches, abort.");
}
} else {
Object[] outgoingRefs = processModel.getGraph().getTargetObjects(nodeId).toArray();
Integer DefaultPath = null;
for (Object or : outgoingRefs) {
// try to find default path
if (or.equals(getKeyByValue(processModel.getIdentifiers(), processModel.getNodeAttributes().get(desmojEvent.getNodeId()).get("default")))) {
DefaultPath = (Integer) or;
break;
}
}
if (DefaultPath != null) {
scheduleNextEvent(desmojEvent, processInstance, processModel, DefaultPath);
} else {
throw new ScyllaValidationException("No Distribution for " + desmojEvent.getDisplayName() + " given, no DefaultPath given and DataObject PlugIn not activated.");
}
}
}
}
}
} catch (NodeNotFoundException | ScyllaValidationException e) {
System.err.println(e.getMessage());
e.printStackTrace();
SimulationUtils.abort(model, processInstance, nodeId, showInTrace);
return;
}
}
use of de.hpi.bpt.scylla.model.process.node.GatewayType in project scylla by bptlab.
the class GatewayEvent method eventRoutine.
@Override
public void eventRoutine(ProcessInstance processInstance) throws SuspendExecution {
SimulationModel model = (SimulationModel) getModel();
ProcessModel processModel = processInstance.getProcessModel();
try {
Set<Integer> idsOfPreviousNodes = processModel.getIdsOfPreviousNodes(nodeId);
Set<Integer> idsOfNextNodes = processModel.getIdsOfNextNodes(nodeId);
String message = null;
GatewayType type = processModel.getGateways().get(nodeId);
String convergeDivergeName = "Join and Split";
if (idsOfPreviousNodes.size() == 1) {
convergeDivergeName = "Split";
} else if (idsOfNextNodes.size() == 1) {
convergeDivergeName = "Join";
}
if (type == GatewayType.DEFAULT) {
message = "Default " + convergeDivergeName + " Gateway: " + displayName;
}
if (type == GatewayType.EXCLUSIVE) {
message = "Exclusive " + convergeDivergeName + " Gateway: " + displayName;
} else if (type == GatewayType.EVENT_BASED) {
message = "Eventbased " + convergeDivergeName + " Gateway: " + displayName;
} else if (type == GatewayType.INCLUSIVE) {
message = "Inclusive " + convergeDivergeName + " Gateway: " + displayName;
} else if (type == GatewayType.PARALLEL) {
message = "Parallel " + convergeDivergeName + " Gateway: " + displayName;
} else if (type == GatewayType.COMPLEX) {
message = "Complex " + convergeDivergeName + " Gateway: " + displayName;
} else {
// TODO write to log because element not supported
SimulationUtils.abort(model, processInstance, nodeId, traceIsOn());
return;
}
sendTraceNote(message);
// i.e. for splits: default behavior is the one of a parallel gateway
for (Integer nextNodeId : idsOfNextNodes) {
List<ScyllaEvent> events = SimulationUtils.createEventsForNextNode(this, pSimComponents, processInstance, nextNodeId);
// next DesmoJ event occurs immediately after start event
TimeSpan timeSpan = new TimeSpan(0);
for (ScyllaEvent event : events) {
int index = getNewEventIndex();
nextEventMap.put(index, event);
timeSpanToNextEventMap.put(index, timeSpan);
}
}
GatewayEventPluggable.runPlugins(this, processInstance);
scheduleNextEvents();
} catch (NodeNotFoundException | ScyllaValidationException | ScyllaRuntimeException e) {
System.err.println(e.getMessage());
e.printStackTrace();
SimulationUtils.abort(model, processInstance, nodeId, traceIsOn());
return;
}
}
use of de.hpi.bpt.scylla.model.process.node.GatewayType in project scylla by bptlab.
the class SimulationUtils method createEventsForNextNode.
/**
* Gets type of next node and prepare respective event.
*
* @param model
* the simulation model
* @param processModel
* the process model
* @param processInstanceId
* the identifier of the process instance
* @param nextNodeId
* the identifier of the next node
* @return the DesmoJ representing the next node plus DesmoJ events from plug-ins
* @throws ScyllaRuntimeException
* @throws NodeNotFoundException
* @throws ScyllaValidationException
*/
public static List<ScyllaEvent> createEventsForNextNode(ScyllaEvent currentEvent, ProcessSimulationComponents desmojObjects, ProcessInstance processInstance, int nextNodeId) throws ScyllaRuntimeException, NodeNotFoundException, ScyllaValidationException {
SimulationModel model = (SimulationModel) processInstance.getModel();
TimeInstant currentSimulationTime = model.presentTime();
ProcessModel processModel = processInstance.getProcessModel();
String source = currentEvent.getSource();
List<ScyllaEvent> events = new ArrayList<ScyllaEvent>();
if (processModel.getTasks().containsKey(nextNodeId) || processModel.getSubProcesses().containsKey(nextNodeId)) {
// TaskType tType = processModel.getTasks().get(nextNodeId);
ScyllaEvent event = new TaskEnableEvent(model, source, currentSimulationTime, desmojObjects, processInstance, nextNodeId);
events.add(event);
} else if (processModel.getGateways().containsKey(nextNodeId)) {
GatewayType gType = processModel.getGateways().get(nextNodeId);
Set<Integer> idsOfNodesBeforeGateway = processModel.getIdsOfPreviousNodes(nextNodeId);
if (gType == GatewayType.PARALLEL && idsOfNodesBeforeGateway.size() > 1) {
Map<Integer, Set<Integer>> referenceToEventsOnHold = processInstance.getNodesAndTriggers();
if (!referenceToEventsOnHold.containsKey(nextNodeId)) {
referenceToEventsOnHold.put(nextNodeId, new HashSet<Integer>());
}
Set<Integer> nodesTriggeredFrom = referenceToEventsOnHold.get(nextNodeId);
int currentNodeId = currentEvent.getNodeId();
nodesTriggeredFrom.add(currentNodeId);
if (idsOfNodesBeforeGateway.equals(nodesTriggeredFrom)) {
ScyllaEvent event = new GatewayEvent(model, source, currentSimulationTime, desmojObjects, processInstance, nextNodeId);
events.add(event);
// clear list of fired incoming flows
referenceToEventsOnHold.remove(nextNodeId);
}
} else {
ScyllaEvent event = new GatewayEvent(model, source, currentSimulationTime, desmojObjects, processInstance, nextNodeId);
events.add(event);
}
} else if (processModel.getEventTypes().containsKey(nextNodeId)) {
EventType eType = processModel.getEventTypes().get(nextNodeId);
if (eType == EventType.START) {
throw new ScyllaRuntimeException("Start event " + nextNodeId + " must be at the beginning of the process.");
} else if (eType == EventType.END) {
ScyllaEvent event = new BPMNEndEvent(model, source, currentSimulationTime, desmojObjects, processInstance, nextNodeId);
events.add(event);
} else {
ScyllaEvent event = new BPMNIntermediateEvent(model, source, currentSimulationTime, desmojObjects, processInstance, nextNodeId);
events.add(event);
}
} else {
throw new ScyllaRuntimeException("Next node " + nextNodeId + " not found or not supported.");
}
List<ScyllaEvent> eventsFromPlugins = EventCreationPluggable.runPlugins(currentEvent, desmojObjects, processInstance, nextNodeId);
events.addAll(eventsFromPlugins);
return events;
}
use of de.hpi.bpt.scylla.model.process.node.GatewayType in project scylla by bptlab.
the class EventbasedGatewayEventPlugin method eventRoutine.
/**
* Handles a gateway event, if it is an event based gateway
* Changes scheduling behavior by already scheduling the next events of the given gateway event (if event based)
*/
@Override
public void eventRoutine(GatewayEvent desmojEvent, ProcessInstance processInstance) throws ScyllaRuntimeException {
SimulationModel model = (SimulationModel) desmojEvent.getModel();
ProcessModel processModel = processInstance.getProcessModel();
int nodeId = desmojEvent.getNodeId();
GatewayType type = processModel.getGateways().get(nodeId);
try {
Set<Integer> idsOfNextNodes = processModel.getIdsOfNextNodes(nodeId);
if (type == GatewayType.EVENT_BASED && idsOfNextNodes.size() > 1) {
// Schedule all following events
List<ScyllaEvent> nextEvents = new ArrayList<ScyllaEvent>(desmojEvent.getNextEventMap().values());
desmojEvent.scheduleNextEvents();
// and look which is scheduled first.
ScyllaEvent first = nextEvents.get(0);
for (ScyllaEvent e : nextEvents) {
if (TimeInstant.isBefore(e.scheduledNext(), first.scheduledNext())) {
first = e;
}
}
// Cancel all other events except the one that is scheduled first.
nextEvents.remove(first);
for (ScyllaEvent e : nextEvents) {
e.cancel();
}
}
} catch (NodeNotFoundException | ScyllaValidationException | SuspendExecution e) {
e.printStackTrace();
// Critical error (following nodes not found or validation error), abort the instance.
SimulationUtils.abort(model, processInstance, nodeId, desmojEvent.traceIsOn());
}
}
Aggregations