Search in sources :

Example 1 with EventDefinitionType

use of de.hpi.bpt.scylla.model.process.node.EventDefinitionType 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;
}
Also used : ProcessModel(de.hpi.bpt.scylla.model.process.ProcessModel) EventType(de.hpi.bpt.scylla.model.process.node.EventType) Element(org.jdom2.Element) GatewayType(de.hpi.bpt.scylla.model.process.node.GatewayType) ScyllaValidationException(de.hpi.bpt.scylla.exception.ScyllaValidationException) TaskType(de.hpi.bpt.scylla.model.process.node.TaskType) DataObjectType(de.hpi.bpt.scylla.model.process.node.DataObjectType) EventDefinitionType(de.hpi.bpt.scylla.model.process.node.EventDefinitionType) Graph(de.hpi.bpt.scylla.model.process.graph.Graph)

Example 2 with EventDefinitionType

use of de.hpi.bpt.scylla.model.process.node.EventDefinitionType in project scylla by bptlab.

the class BoundaryEventPluginUtils method createTimerBoundaryEvents.

// I did not touch this for now. Hopefully could be deleted in future.
private void createTimerBoundaryEvents(SimulationModel model, BoundaryObject bo, double startOfInterval, double endOfInterval) throws ScyllaRuntimeException {
    double beginTimeOfTask = bo.getBeginTimeOfTask();
    ProcessSimulationComponents desmojObjects = bo.getDesmojObjects();
    ProcessModel processModel = desmojObjects.getProcessModel();
    Map<Integer, EventType> eventTypes = processModel.getEventTypes();
    Map<Integer, Boolean> cancelActivities = processModel.getCancelActivities();
    List<Integer> referenceToBoundaryEvents = bo.getReferenceToBoundaryEvents();
    for (Integer nId : referenceToBoundaryEvents) {
        boolean timerEventIsInterrupting = false;
        EventType eventType = eventTypes.get(nId);
        if (eventType == EventType.BOUNDARY) {
            Map<EventDefinitionType, Map<String, String>> eventDefinitions = processModel.getEventDefinitions().get(nId);
            Map<String, String> definitionAttributes = eventDefinitions.get(EventDefinitionType.TIMER);
            if (definitionAttributes != null) {
                // if boundary event is timer event
                double timeUntilWhenTimerEventsAreCreated = bo.getTimeUntilWhenTimerEventsAreCreated();
                if (definitionAttributes.get("timeDuration") != null) {
                    // ISO 8601 duration
                    String timeDuration = definitionAttributes.get("timeDuration");
                    if (beginTimeOfTask != timeUntilWhenTimerEventsAreCreated) {
                        // timer event has already been created once, skip
                        continue;
                    }
                    Duration javaDuration = Duration.parse(timeDuration);
                    double duration = javaDuration.get(ChronoUnit.SECONDS);
                    if (duration == 0) {
                        continue;
                    }
                    double timeToSchedule = beginTimeOfTask + duration;
                    if (timeToSchedule < endOfInterval) {
                        String displayName = processModel.getDisplayNames().get(nId);
                        if (displayName == null) {
                            displayName = processModel.getIdentifiers().get(nId);
                        }
                        String source = bo.getSource();
                        ProcessInstance processInstance = bo.getProcessInstance();
                        TimeInstant timeInstant = new TimeInstant(startOfInterval, TimeUnit.SECONDS);
                        BPMNIntermediateEvent event = new BPMNIntermediateEvent(model, source, timeInstant, desmojObjects, processInstance, nId);
                        bo.getBoundaryEventsToSchedule().computeIfAbsent(timeToSchedule, k -> new ArrayList<BPMNIntermediateEvent>());
                        bo.getBoundaryEventsToSchedule().get(timeToSchedule).add(event);
                        String message = "Schedule boundary timer event: " + displayName;
                        bo.getMessagesOfBoundaryEventsToSchedule().computeIfAbsent(timeToSchedule, k -> new ArrayList<String>());
                        bo.getMessagesOfBoundaryEventsToSchedule().get(timeToSchedule).add(message);
                    // timeUntilWhenTimerEventsAreCreated = timeToSchedule;
                    }
                    // TODO fix boundary
                    timeUntilWhenTimerEventsAreCreated = timeToSchedule;
                } else if (definitionAttributes.get("timeCycle") != null) {
                    // ISO 8601 repeating time interval:
                    String timeCycle = definitionAttributes.get("timeCycle");
                    // Rn/[ISO 8601 duration] where n
                    // (optional) for number of
                    // recurrences
                    // ["Rn"], "[ISO 8601 duration]"]
                    String[] recurrencesAndDuration = timeCycle.split("/");
                    String recurrencesString = recurrencesAndDuration[0];
                    String timeDurationString = recurrencesAndDuration[1];
                    Integer recurrencesMax = null;
                    if (recurrencesString.length() > 1) {
                        recurrencesMax = Integer.parseInt(recurrencesString.substring(1, recurrencesString.length()));
                        timerEventIsInterrupting = cancelActivities.get(nId);
                        if (timerEventIsInterrupting) {
                            recurrencesMax = 1;
                        }
                    }
                    Duration javaDuration = Duration.parse(timeDurationString);
                    double duration = javaDuration.get(ChronoUnit.SECONDS);
                    if (duration == 0 || recurrencesMax != null && recurrencesMax == 0) {
                        continue;
                    }
                    double timeToSchedule = beginTimeOfTask;
                    int actualNumberOfOccurrences = 0;
                    boolean recurrencesMaxExceeded = false;
                    while (timeToSchedule <= timeUntilWhenTimerEventsAreCreated) {
                        timeToSchedule += duration;
                        actualNumberOfOccurrences++;
                        if (recurrencesMax != null && actualNumberOfOccurrences > recurrencesMax) {
                            recurrencesMaxExceeded = true;
                            break;
                        }
                    }
                    if (recurrencesMaxExceeded) {
                        continue;
                    }
                    while (timeToSchedule <= endOfInterval) {
                        // add as many timer events for scheduling as possible (lots of them if timer event is
                        // non-interrupting,
                        // only one if it is interrupting
                        String displayName = processModel.getDisplayNames().get(nId);
                        if (displayName == null) {
                            displayName = processModel.getIdentifiers().get(nId);
                        }
                        String source = bo.getSource();
                        ProcessInstance processInstance = bo.getProcessInstance();
                        TimeInstant timeInstant = new TimeInstant(startOfInterval, TimeUnit.SECONDS);
                        BPMNIntermediateEvent event = new BPMNIntermediateEvent(model, source, timeInstant, desmojObjects, processInstance, nId);
                        bo.getBoundaryEventsToSchedule().computeIfAbsent(timeToSchedule, k -> new ArrayList<BPMNIntermediateEvent>());
                        bo.getBoundaryEventsToSchedule().get(timeToSchedule).add(event);
                        String message = "Schedule boundary timer event: " + displayName;
                        bo.getMessagesOfBoundaryEventsToSchedule().computeIfAbsent(timeToSchedule, k -> new ArrayList<String>());
                        bo.getMessagesOfBoundaryEventsToSchedule().get(timeToSchedule).add(message);
                        actualNumberOfOccurrences++;
                        if (recurrencesMax != null && actualNumberOfOccurrences == recurrencesMax) {
                            // recurrencesMaxExceeded = true;
                            break;
                        }
                        timeToSchedule += duration;
                    }
                    timeUntilWhenTimerEventsAreCreated = timeToSchedule;
                } else {
                    // TODO support timeDate attributes?
                    String identifier = processModel.getIdentifiers().get(nId);
                    DebugLogger.log("Timer event " + identifier + " has no timer definition, skip.");
                    continue;
                }
                bo.setTimeUntilWhenTimerEventsAreCreated(timeUntilWhenTimerEventsAreCreated);
            }
        }
    }
}
Also used : SimulationUtils(de.hpi.bpt.scylla.simulation.utils.SimulationUtils) Entity(desmoj.core.simulator.Entity) HashMap(java.util.HashMap) DiscreteDistEmpirical(desmoj.core.dist.DiscreteDistEmpirical) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) BPMNIntermediateEvent(de.hpi.bpt.scylla.simulation.event.BPMNIntermediateEvent) EventType(de.hpi.bpt.scylla.model.process.node.EventType) Duration(java.time.Duration) Map(java.util.Map) DebugLogger(de.hpi.bpt.scylla.logger.DebugLogger) EventDefinitionType(de.hpi.bpt.scylla.model.process.node.EventDefinitionType) TimeSpan(desmoj.core.simulator.TimeSpan) ScyllaEvent(de.hpi.bpt.scylla.simulation.event.ScyllaEvent) ProcessModel(de.hpi.bpt.scylla.model.process.ProcessModel) TimeInstant(desmoj.core.simulator.TimeInstant) SimulationModel(de.hpi.bpt.scylla.simulation.SimulationModel) Iterator(java.util.Iterator) ProcessSimulationComponents(de.hpi.bpt.scylla.simulation.ProcessSimulationComponents) Set(java.util.Set) TimeUnit(java.util.concurrent.TimeUnit) List(java.util.List) ScyllaRuntimeException(de.hpi.bpt.scylla.exception.ScyllaRuntimeException) ChronoUnit(java.time.temporal.ChronoUnit) TreeMap(java.util.TreeMap) ProcessInstance(de.hpi.bpt.scylla.simulation.ProcessInstance) ProcessModel(de.hpi.bpt.scylla.model.process.ProcessModel) EventType(de.hpi.bpt.scylla.model.process.node.EventType) EventDefinitionType(de.hpi.bpt.scylla.model.process.node.EventDefinitionType) ArrayList(java.util.ArrayList) Duration(java.time.Duration) BPMNIntermediateEvent(de.hpi.bpt.scylla.simulation.event.BPMNIntermediateEvent) ProcessSimulationComponents(de.hpi.bpt.scylla.simulation.ProcessSimulationComponents) ProcessInstance(de.hpi.bpt.scylla.simulation.ProcessInstance) HashMap(java.util.HashMap) Map(java.util.Map) TreeMap(java.util.TreeMap) TimeInstant(desmoj.core.simulator.TimeInstant)

Example 3 with EventDefinitionType

use of de.hpi.bpt.scylla.model.process.node.EventDefinitionType in project scylla by bptlab.

the class BPMNTimerPluginUtils method getTimeSpanUntilNextEvent.

/**
 * Returns TimeSpan object (duration and timeUnit) representing time until next event. Available for timer events.
 *
 * @param processModel
 * @param nodeId
 * @return
 * @return
 */
static TimeSpan getTimeSpanUntilNextEvent(ProcessModel processModel, int nodeId) {
    TimeSpan timeSpan = null;
    Map<EventDefinitionType, Map<String, String>> definitions = processModel.getEventDefinitions().get(nodeId);
    if (definitions != null) {
        if (definitions.get(EventDefinitionType.TIMER) != null) {
            Map<String, String> eventAttributes = definitions.get(EventDefinitionType.TIMER);
            // String timeDate = eventAttributes.get("timeDate");
            // if (timeDate != null) {
            // SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
            // Date date = formatter.parse(timeDate);
            // }
            // String timeCycle = eventAttributes.get("timeCycle");
            String timeDuration = eventAttributes.get("timeDuration");
            Duration jtDuration = Duration.parse(timeDuration);
            long duration = jtDuration.getSeconds();
            TimeUnit timeUnit = TimeUnit.SECONDS;
            timeSpan = new TimeSpan(duration, timeUnit);
        }
    }
    return timeSpan;
}
Also used : TimeSpan(desmoj.core.simulator.TimeSpan) EventDefinitionType(de.hpi.bpt.scylla.model.process.node.EventDefinitionType) TimeUnit(java.util.concurrent.TimeUnit) Duration(java.time.Duration) Map(java.util.Map)

Example 4 with EventDefinitionType

use of de.hpi.bpt.scylla.model.process.node.EventDefinitionType in project scylla by bptlab.

the class BPMNEscalationBPMNEEPlugin method eventRoutine.

@Override
public void eventRoutine(BPMNEndEvent desmojEvent, ProcessInstance processInstance) throws ScyllaRuntimeException {
    SimulationModel model = (SimulationModel) desmojEvent.getModel();
    ProcessModel processModel = processInstance.getProcessModel();
    int nodeId = desmojEvent.getNodeId();
    Map<EventDefinitionType, Map<String, String>> definitions = processModel.getEventDefinitions().get(nodeId);
    ProcessSimulationComponents desmojObjects = desmojEvent.getDesmojObjects();
    boolean showInTrace = model.traceIsOn();
    try {
        for (EventDefinitionType definition : definitions.keySet()) {
            if (definition == EventDefinitionType.ESCALATION) {
                if (processModel.getParent() != null) {
                    Map<String, String> eventAttributes = processModel.getEventDefinitions().get(nodeId).get(definition);
                    String escalationRef = eventAttributes.get("escalationRef");
                    // Map<String, Map<String, String>> escalations =
                    // model.getCommonProcessElements().getEscalations();
                    // Map<String, String> escalation = escalations.get("escalationRef");
                    ProcessSimulationComponents parentDesmojObjects = desmojObjects.getParent();
                    ProcessModel parentModel = processModel.getParent();
                    int nodeIdInParent = processModel.getNodeIdInParent();
                    Integer nextNodeId = null;
                    // find boundary event of parentModel which has the same escalationRef
                    List<Integer> referencesToBoundaryEvents = parentModel.getReferencesToBoundaryEvents().get(nodeIdInParent);
                    for (int nId : referencesToBoundaryEvents) {
                        Map<EventDefinitionType, Map<String, String>> boundaryEventDefinitions = parentModel.getEventDefinitions().get(nId);
                        Map<String, String> boundaryEscalationEventDefinition = boundaryEventDefinitions.get(EventDefinitionType.ESCALATION);
                        if (boundaryEscalationEventDefinition != null) {
                            if (escalationRef.equals(boundaryEscalationEventDefinition.get("escalationRef"))) {
                                nextNodeId = nId;
                                break;
                            }
                        }
                    }
                    if (nextNodeId == null) {
                        DebugLogger.error("Could not find referenced escalation " + escalationRef + ".");
                        SimulationUtils.abort(model, processInstance, nodeId, showInTrace);
                        return;
                    }
                    ProcessInstance parentProcessInstance = processInstance.getParent();
                    List<ScyllaEvent> events = SimulationUtils.createEventsForNextNode(desmojEvent, parentDesmojObjects, parentProcessInstance, nextNodeId);
                    TimeSpan timeSpan = new TimeSpan(0);
                    /**
                     * first event in the map is the node that comes after the subprocess when normal behavior
                     * applies, so remove it;
                     */
                    int indexOfTaskTerminateEvent = 0;
                    desmojEvent.getNextEventMap().remove(indexOfTaskTerminateEvent);
                    desmojEvent.getTimeSpanToNextEventMap().remove(indexOfTaskTerminateEvent);
                    for (ScyllaEvent event : events) {
                        int index = desmojEvent.getNewEventIndex();
                        desmojEvent.getNextEventMap().put(index, event);
                        desmojEvent.getTimeSpanToNextEventMap().put(index, timeSpan);
                    }
                    processInstance.cancel();
                }
            }
        }
    } catch (NodeNotFoundException | ScyllaValidationException e) {
        DebugLogger.error(e.getMessage());
        e.printStackTrace();
        SimulationUtils.abort(model, processInstance, nodeId, showInTrace);
    }
}
Also used : ProcessModel(de.hpi.bpt.scylla.model.process.ProcessModel) EventDefinitionType(de.hpi.bpt.scylla.model.process.node.EventDefinitionType) ScyllaEvent(de.hpi.bpt.scylla.simulation.event.ScyllaEvent) TimeSpan(desmoj.core.simulator.TimeSpan) ScyllaValidationException(de.hpi.bpt.scylla.exception.ScyllaValidationException) NodeNotFoundException(de.hpi.bpt.scylla.model.process.graph.exception.NodeNotFoundException) ProcessSimulationComponents(de.hpi.bpt.scylla.simulation.ProcessSimulationComponents) ProcessInstance(de.hpi.bpt.scylla.simulation.ProcessInstance) Map(java.util.Map) SimulationModel(de.hpi.bpt.scylla.simulation.SimulationModel)

Example 5 with EventDefinitionType

use of de.hpi.bpt.scylla.model.process.node.EventDefinitionType in project scylla by bptlab.

the class BPMNTimerPIGEPlugin method eventRoutine.

@Override
public void eventRoutine(ProcessInstanceGenerationEvent desmojEvent, ProcessInstance processInstance) throws ScyllaRuntimeException {
    SimulationModel model = (SimulationModel) desmojEvent.getModel();
    String processId = desmojEvent.getProcessId();
    ProcessSimulationComponents desmojObjects = model.getDesmojObjectsMap().get(processId);
    ProcessModel processModel = desmojObjects.getProcessModel();
    Integer startNodeId;
    try {
        startNodeId = processModel.getStartNode();
        if (desmojObjects.getDistributions().get(startNodeId) == null) {
            // no arrival rate defined, check if start event is timer event and use value from there
            Map<EventDefinitionType, Map<String, String>> eventDefinitions = processModel.getEventDefinitions().get(startNodeId);
            Map<String, String> definitionAttributes = eventDefinitions.get(EventDefinitionType.TIMER);
            if (definitionAttributes != null) {
                // if start event is timer event
                // ISO 8601 duration
                String timeDuration = definitionAttributes.get("timeCycle");
                if (timeDuration == null) {
                    String identifier = processModel.getIdentifiers().get(startNodeId);
                    DebugLogger.log("Timer event " + identifier + " has no timer definition, skip.");
                } else // TODO support timeDate and timeDuration attributes?
                {
                    Duration javaDuration = Duration.parse(timeDuration);
                    long duration = javaDuration.get(ChronoUnit.SECONDS);
                    TimeUnit unit = TimeUnit.SECONDS;
                    TimeSpan timeSpan = new TimeSpan(duration, unit);
                    desmojEvent.setTimeSpanToNextProcessInstance(timeSpan);
                }
            }
        }
    } catch (NodeNotFoundException | MultipleStartNodesException | NoStartNodeException e) {
        DebugLogger.error(e.getMessage());
        DebugLogger.log("Error during instantiation of process model " + processModel.getId() + ".");
    }
}
Also used : ProcessModel(de.hpi.bpt.scylla.model.process.ProcessModel) EventDefinitionType(de.hpi.bpt.scylla.model.process.node.EventDefinitionType) Duration(java.time.Duration) MultipleStartNodesException(de.hpi.bpt.scylla.model.process.graph.exception.MultipleStartNodesException) TimeSpan(desmoj.core.simulator.TimeSpan) NodeNotFoundException(de.hpi.bpt.scylla.model.process.graph.exception.NodeNotFoundException) ProcessSimulationComponents(de.hpi.bpt.scylla.simulation.ProcessSimulationComponents) TimeUnit(java.util.concurrent.TimeUnit) Map(java.util.Map) SimulationModel(de.hpi.bpt.scylla.simulation.SimulationModel) NoStartNodeException(de.hpi.bpt.scylla.model.process.graph.exception.NoStartNodeException)

Aggregations

EventDefinitionType (de.hpi.bpt.scylla.model.process.node.EventDefinitionType)9 ProcessModel (de.hpi.bpt.scylla.model.process.ProcessModel)8 Map (java.util.Map)8 SimulationModel (de.hpi.bpt.scylla.simulation.SimulationModel)7 TimeSpan (desmoj.core.simulator.TimeSpan)7 ScyllaValidationException (de.hpi.bpt.scylla.exception.ScyllaValidationException)5 NodeNotFoundException (de.hpi.bpt.scylla.model.process.graph.exception.NodeNotFoundException)5 ScyllaRuntimeException (de.hpi.bpt.scylla.exception.ScyllaRuntimeException)4 ProcessSimulationComponents (de.hpi.bpt.scylla.simulation.ProcessSimulationComponents)4 HashSet (java.util.HashSet)4 EventType (de.hpi.bpt.scylla.model.process.node.EventType)3 ProcessInstance (de.hpi.bpt.scylla.simulation.ProcessInstance)3 ScyllaEvent (de.hpi.bpt.scylla.simulation.event.ScyllaEvent)3 Duration (java.time.Duration)3 TimeUnit (java.util.concurrent.TimeUnit)3 DebugLogger (de.hpi.bpt.scylla.logger.DebugLogger)1 Graph (de.hpi.bpt.scylla.model.process.graph.Graph)1 MultipleStartNodesException (de.hpi.bpt.scylla.model.process.graph.exception.MultipleStartNodesException)1 NoStartNodeException (de.hpi.bpt.scylla.model.process.graph.exception.NoStartNodeException)1 DataObjectType (de.hpi.bpt.scylla.model.process.node.DataObjectType)1