public void setValues(BoundaryEvent otherEvent) { super.setValues(otherEvent); setAttachedToRefId(otherEvent.getAttachedToRefId()); setAttachedToRef(otherEvent.getAttachedToRef()); setCancelActivity(otherEvent.isCancelActivity()); } }
@Override protected BaseElement convertXMLToElement(XMLStreamReader xtr, BpmnModel model) throws Exception { BoundaryEvent boundaryEvent = new BoundaryEvent(); BpmnXMLUtil.addXMLLocation(boundaryEvent, xtr); if (StringUtils.isNotEmpty(xtr.getAttributeValue(null, ATTRIBUTE_BOUNDARY_CANCELACTIVITY))) { String cancelActivity = xtr.getAttributeValue(null, ATTRIBUTE_BOUNDARY_CANCELACTIVITY); if (ATTRIBUTE_VALUE_FALSE.equalsIgnoreCase(cancelActivity)) { boundaryEvent.setCancelActivity(false); } } boundaryEvent.setAttachedToRefId(xtr.getAttributeValue(null, ATTRIBUTE_BOUNDARY_ATTACHEDTOREF)); parseChildElements(getXMLElementName(), boundaryEvent, model, xtr); // Explicitly set cancel activity to false for error boundary events if (boundaryEvent.getEventDefinitions().size() == 1) { EventDefinition eventDef = boundaryEvent.getEventDefinitions().get(0); if (eventDef instanceof ErrorEventDefinition) { boundaryEvent.setCancelActivity(false); } } return boundaryEvent; }
protected void handleBoundaryEvents() { for (BoundaryEvent boundaryEvent : boundaryEvents) { mxGeometry geometry = new mxGeometry(0.8, 1.0, eventSize, eventSize); geometry.setOffset(new mxPoint(-(eventSize / 2), -(eventSize / 2))); geometry.setRelative(true); mxCell boundaryPort = new mxCell(null, geometry, "shape=ellipse;perimeter=ellipsePerimeter"); boundaryPort.setId("boundary-event-" + boundaryEvent.getId()); boundaryPort.setVertex(true); Object portParent = null; if (boundaryEvent.getAttachedToRefId() != null) { portParent = generatedVertices.get(boundaryEvent.getAttachedToRefId()); } else if (boundaryEvent.getAttachedToRef() != null) { portParent = generatedVertices.get(boundaryEvent.getAttachedToRef().getId()); } else { throw new RuntimeException("Could not generate DI: boundaryEvent '" + boundaryEvent.getId() + "' has no attachedToRef"); } graph.addCell(boundaryPort, portParent); generatedVertices.put(boundaryEvent.getId(), boundaryPort); } }
@Override public BoundaryEvent clone() { BoundaryEvent clone = new BoundaryEvent(); clone.setValues(this); return clone; }
@Override protected void writeAdditionalAttributes(BaseElement element, BpmnModel model, XMLStreamWriter xtw) throws Exception { BoundaryEvent boundaryEvent = (BoundaryEvent) element; if (boundaryEvent.getAttachedToRef() != null) { writeDefaultAttribute(ATTRIBUTE_BOUNDARY_ATTACHEDTOREF, boundaryEvent.getAttachedToRef().getId(), xtw); } if (boundaryEvent.getEventDefinitions().size() == 1) { EventDefinition eventDef = boundaryEvent.getEventDefinitions().get(0); if (!(eventDef instanceof ErrorEventDefinition)) { writeDefaultAttribute(ATTRIBUTE_BOUNDARY_CANCELACTIVITY, String.valueOf(boundaryEvent.isCancelActivity()).toLowerCase(), xtw); } } }
@Override protected void executeParse(BpmnParse bpmnParse, BoundaryEvent boundaryEvent) { ActivityImpl parentActivity = findActivity(bpmnParse, boundaryEvent.getAttachedToRefId()); if (parentActivity == null) { LOGGER.warn("Invalid reference in boundary event. Make sure that the referenced activity is defined in the same scope as the boundary event {}", boundaryEvent.getId()); return; } ActivityImpl nestedActivity = createActivityOnScope(bpmnParse, boundaryEvent, BpmnXMLConstants.ELEMENT_EVENT_BOUNDARY, parentActivity); bpmnParse.setCurrentActivity(nestedActivity); EventDefinition eventDefinition = null; if (!boundaryEvent.getEventDefinitions().isEmpty()) { eventDefinition = boundaryEvent.getEventDefinitions().get(0); } if (eventDefinition instanceof TimerEventDefinition || eventDefinition instanceof org.flowable.bpmn.model.ErrorEventDefinition || eventDefinition instanceof SignalEventDefinition || eventDefinition instanceof CancelEventDefinition || eventDefinition instanceof MessageEventDefinition || eventDefinition instanceof org.flowable.bpmn.model.CompensateEventDefinition) { bpmnParse.getBpmnParserHandlers().parseElement(bpmnParse, eventDefinition); } else { LOGGER.warn("Unsupported boundary event type for boundary event {}", boundaryEvent.getId()); } }
@Override protected void executeParse(BpmnParse bpmnParse, BoundaryEvent boundaryEvent) { if (boundaryEvent.getAttachedToRef() == null) { LOGGER.warn("Invalid reference in boundary event. Make sure that the referenced activity is defined in the same scope as the boundary event {}", boundaryEvent.getId()); return; } EventDefinition eventDefinition = null; if (boundaryEvent.getEventDefinitions().size() > 0) { eventDefinition = boundaryEvent.getEventDefinitions().get(0); } if (eventDefinition instanceof TimerEventDefinition || eventDefinition instanceof ErrorEventDefinition || eventDefinition instanceof SignalEventDefinition || eventDefinition instanceof CancelEventDefinition || eventDefinition instanceof MessageEventDefinition || eventDefinition instanceof CompensateEventDefinition) { bpmnParse.getBpmnParserHandlers().parseElement(bpmnParse, eventDefinition); } else { // Should already be picked up by process validator on deploy, so this is just to be sure LOGGER.warn("Unsupported boundary event type for boundary event {}", boundaryEvent.getId()); } }
if (boundaryEvent.getAttachedToRefId().equals(originalFlowElementId)) { boundaryEvent.setAttachedToRefId(newFlowElementId); if (boundaryEvent.getEventDefinitions() != null && boundaryEvent.getEventDefinitions().size() > 0 && (boundaryEvent.getEventDefinitions().get(0) instanceof CompensateEventDefinition)) { CompensateEventDefinition compensateEventDefinition = (CompensateEventDefinition) boundaryEvent.getEventDefinitions().get(0); if (compensateEventDefinition.getActivityRef().equals(originalFlowElementId)) { compensateEventDefinition.setActivityRef(newFlowElementId);
@Override protected void convertElementToJson(ObjectNode propertiesNode, BaseElement baseElement) { BoundaryEvent boundaryEvent = (BoundaryEvent) baseElement; ArrayNode dockersArrayNode = objectMapper.createArrayNode(); ObjectNode dockNode = objectMapper.createObjectNode(); GraphicInfo graphicInfo = model.getGraphicInfo(boundaryEvent.getId()); GraphicInfo parentGraphicInfo = model.getGraphicInfo(boundaryEvent.getAttachedToRef().getId()); dockNode.put(EDITOR_BOUNDS_X, graphicInfo.getX() - parentGraphicInfo.getX()); dockNode.put(EDITOR_BOUNDS_Y, graphicInfo.getY() - parentGraphicInfo.getY()); dockersArrayNode.add(dockNode); flowElementNode.set("dockers", dockersArrayNode); propertiesNode.put(PROPERTY_CANCEL_ACTIVITY, boundaryEvent.isCancelActivity()); addEventProperties(boundaryEvent, propertiesNode); }
if (boundaryEvent.getEventDefinitions() != null && !boundaryEvent.getEventDefinitions().isEmpty()) { EventDefinition eventDefinition = boundaryEvent.getEventDefinitions().get(0); if (!(eventDefinition instanceof TimerEventDefinition) && !(eventDefinition instanceof ErrorEventDefinition) && !(eventDefinition instanceof SignalEventDefinition) && !(eventDefinition instanceof CancelEventDefinition) && !(eventDefinition instanceof MessageEventDefinition) && !(eventDefinition instanceof CompensateEventDefinition)) { FlowElement attachedToFlowElement = bpmnModel.getFlowElement(boundaryEvent.getAttachedToRefId()); if (!(attachedToFlowElement instanceof Transaction)) { addError(errors, Problems.BOUNDARY_EVENT_CANCEL_ONLY_ON_TRANSACTION, process, boundaryEvent, "boundary event with cancelEventDefinition only supported on transaction subprocesses"); if (!compensateBoundaryEventsCounts.containsKey(boundaryEvent.getAttachedToRefId())) { compensateBoundaryEventsCounts.put(boundaryEvent.getAttachedToRefId(), new Integer(0)); compensateBoundaryEventsCounts.put(boundaryEvent.getAttachedToRefId(), compensateBoundaryEventsCounts.get(boundaryEvent.getAttachedToRefId()) + 1); if (j != i) { BoundaryEvent otherBoundaryEvent = boundaryEvents.get(j); if (otherBoundaryEvent.getAttachedToRefId() != null && otherBoundaryEvent.getAttachedToRefId().equals(boundaryEvent.getAttachedToRefId())) { if (otherBoundaryEvent.getEventDefinitions() != null && !otherBoundaryEvent.getEventDefinitions().isEmpty()) { EventDefinition otherEventDefinition = otherBoundaryEvent.getEventDefinitions().get(0); if (otherEventDefinition instanceof MessageEventDefinition) { MessageEventDefinition currentMessageEventDefinition = (MessageEventDefinition) eventDefinition;
Activity activity = retrieveAttachedRefObject(boundaryEvent.getAttachedToRefId(), parentContainer.getFlowElements()); LOGGER.warn("Boundary event {} is not attached to any activity", boundaryEvent.getId()); } else { boundaryEvent.setAttachedToRef(activity); activity.getBoundaryEvents().add(boundaryEvent);
@Override public void trigger(DelegateExecution execution, String triggerName, Object triggerData) { ExecutionEntity executionEntity = (ExecutionEntity) execution; BoundaryEvent boundaryEvent = (BoundaryEvent) execution.getCurrentFlowElement(); if (boundaryEvent.isCancelActivity()) { EventSubscriptionEntityManager eventSubscriptionEntityManager = CommandContextUtil.getEventSubscriptionEntityManager(); List<EventSubscriptionEntity> eventSubscriptions = executionEntity.getEventSubscriptions(); for (EventSubscriptionEntity eventSubscription : eventSubscriptions) { if (eventSubscription instanceof CompensateEventSubscriptionEntity && eventSubscription.getActivityId().equals(compensateEventDefinition.getActivityRef())) { eventSubscriptionEntityManager.delete(eventSubscription); } } } super.trigger(executionEntity, triggerName, triggerData); } }
protected Collection<BoundaryEvent> findBoundaryEventsForFlowNode(final String processDefinitionId, final FlowElement flowElement) { Process process = getProcessDefinition(processDefinitionId); // This could be cached or could be done at parsing time List<BoundaryEvent> results = new ArrayList<>(1); Collection<BoundaryEvent> boundaryEvents = process.findFlowElementsOfType(BoundaryEvent.class, true); for (BoundaryEvent boundaryEvent : boundaryEvents) { if (boundaryEvent.getAttachedToRefId() != null && boundaryEvent.getAttachedToRefId().equals(flowElement.getId())) { results.add(boundaryEvent); } } return results; }
protected void cleanupExecutions(FlowElement currentFlowElement) { if (execution.getParentId() != null && execution.isScope()) { // If the execution is a scope (and not a process instance), the scope must first be // destroyed before we can continue and follow the sequence flow agenda.planDestroyScopeOperation(execution); } else if (currentFlowElement instanceof Activity) { // If the current activity is an activity, we need to remove any currently active boundary events Activity activity = (Activity) currentFlowElement; if (CollectionUtil.isNotEmpty(activity.getBoundaryEvents())) { // Cancel events are not removed List<String> notToDeleteEvents = new ArrayList<>(); for (BoundaryEvent event : activity.getBoundaryEvents()) { if (CollectionUtil.isNotEmpty(event.getEventDefinitions()) && event.getEventDefinitions().get(0) instanceof CancelEventDefinition) { notToDeleteEvents.add(event.getId()); } } // Delete all child executions Collection<ExecutionEntity> childExecutions = CommandContextUtil.getExecutionEntityManager(commandContext).findChildExecutionsByParentExecutionId(execution.getId()); for (ExecutionEntity childExecution : childExecutions) { if (childExecution.getCurrentFlowElement() == null || !notToDeleteEvents.contains(childExecution.getCurrentFlowElement().getId())) { CommandContextUtil.getExecutionEntityManager(commandContext).deleteExecutionAndRelatedData(childExecution, null, false); } } } } }
@Override protected void executeParse(BpmnParse bpmnParse, TimerEventDefinition timerEventDefinition) { if (bpmnParse.getCurrentFlowElement() instanceof IntermediateCatchEvent) { IntermediateCatchEvent intermediateCatchEvent = (IntermediateCatchEvent) bpmnParse.getCurrentFlowElement(); intermediateCatchEvent.setBehavior(bpmnParse.getActivityBehaviorFactory().createIntermediateCatchTimerEventActivityBehavior(intermediateCatchEvent, timerEventDefinition)); } else if (bpmnParse.getCurrentFlowElement() instanceof BoundaryEvent) { BoundaryEvent boundaryEvent = (BoundaryEvent) bpmnParse.getCurrentFlowElement(); boundaryEvent.setBehavior(bpmnParse.getActivityBehaviorFactory().createBoundaryTimerEventActivityBehavior(boundaryEvent, timerEventDefinition, boundaryEvent.isCancelActivity())); } } }
protected void processFlowElements(Collection<FlowElement> flowElementList, BaseElement parentScope) { for (FlowElement flowElement : flowElementList) { if (flowElement instanceof SequenceFlow) { SequenceFlow sequenceFlow = (SequenceFlow) flowElement; FlowNode sourceNode = getFlowNodeFromScope(sequenceFlow.getSourceRef(), parentScope); if (sourceNode != null) { sourceNode.getOutgoingFlows().add(sequenceFlow); sequenceFlow.setSourceFlowElement(sourceNode); } FlowNode targetNode = getFlowNodeFromScope(sequenceFlow.getTargetRef(), parentScope); if (targetNode != null) { targetNode.getIncomingFlows().add(sequenceFlow); sequenceFlow.setTargetFlowElement(targetNode); } } else if (flowElement instanceof BoundaryEvent) { BoundaryEvent boundaryEvent = (BoundaryEvent) flowElement; FlowElement attachedToElement = getFlowNodeFromScope(boundaryEvent.getAttachedToRefId(), parentScope); if (attachedToElement instanceof Activity) { Activity attachedActivity = (Activity) attachedToElement; boundaryEvent.setAttachedToRef(attachedActivity); attachedActivity.getBoundaryEvents().add(boundaryEvent); } } else if (flowElement instanceof SubProcess) { SubProcess subProcess = (SubProcess) flowElement; processFlowElements(subProcess.getFlowElements(), subProcess); } } }
for (ExecutionEntity childExecution : processInstanceExecutions) { if (childExecution.getCurrentFlowElement() != null && childExecution.getCurrentFlowElement().getId().equals(boundaryEvent.getAttachedToRefId())) { subProcessExecution = childExecution; break; throw new FlowableException("No execution found for sub process of boundary cancel event " + boundaryEvent.getId()); } else { String deleteReason = DeleteReason.BOUNDARY_EVENT_INTERRUPTING + "(" + boundaryEvent.getId() + ")";
@Override protected void writeAdditionalChildElements(BaseElement element, BpmnModel model, XMLStreamWriter xtw) throws Exception { BoundaryEvent boundaryEvent = (BoundaryEvent) element; writeEventDefinitions(boundaryEvent, boundaryEvent.getEventDefinitions(), model, xtw); } }
List<Association> associations = process.findAssociationsWithSourceRefRecursive(boundaryEvent.getId()); for (Association association : associations) { sourceActivity = boundaryEvent.getAttachedToRef(); FlowElement targetElement = process.getFlowElement(association.getTargetRef(), true); if (targetElement instanceof Activity) { throw new FlowableException("Could not find a scope execution for compensation boundary event " + boundaryEvent.getId());
protected void executeBoundaryEvents(Collection<BoundaryEvent> boundaryEvents, ExecutionEntity execution) { // The parent execution becomes a scope, and a child execution is created for each of the boundary events for (BoundaryEvent boundaryEvent : boundaryEvents) { if (CollectionUtil.isEmpty(boundaryEvent.getEventDefinitions()) || (boundaryEvent.getEventDefinitions().get(0) instanceof CompensateEventDefinition)) { continue; } // A Child execution of the current execution is created to represent the boundary event being active ExecutionEntity childExecutionEntity = CommandContextUtil.getExecutionEntityManager().createChildExecution(execution); childExecutionEntity.setParentId(execution.getId()); childExecutionEntity.setCurrentFlowElement(boundaryEvent); childExecutionEntity.setScope(false); ActivityBehavior boundaryEventBehavior = ((ActivityBehavior) boundaryEvent.getBehavior()); LOGGER.debug("Executing boundary event activityBehavior {} with execution {}", boundaryEventBehavior.getClass(), childExecutionEntity.getId()); boundaryEventBehavior.execute(childExecutionEntity); } }