org.bonitasoft.engine.execution.event.MessageEventHandlerStrategy Maven / Gradle / Ivy
The newest version!
/**
* Copyright (C) 2019 Bonitasoft S.A.
* Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble
* This library is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation
* version 2.1 of the License.
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301, USA.
**/
package org.bonitasoft.engine.execution.event;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.bonitasoft.engine.bpm.model.impl.BPMInstancesCreator;
import org.bonitasoft.engine.builder.BuilderFactory;
import org.bonitasoft.engine.commons.exceptions.SBonitaException;
import org.bonitasoft.engine.core.expression.control.api.ExpressionResolverService;
import org.bonitasoft.engine.core.expression.control.model.SExpressionContext;
import org.bonitasoft.engine.core.operation.model.SOperation;
import org.bonitasoft.engine.core.process.definition.ProcessDefinitionService;
import org.bonitasoft.engine.core.process.definition.model.SFlowElementContainerDefinition;
import org.bonitasoft.engine.core.process.definition.model.SFlowNodeDefinition;
import org.bonitasoft.engine.core.process.definition.model.SProcessDefinition;
import org.bonitasoft.engine.core.process.definition.model.SReceiveTaskDefinition;
import org.bonitasoft.engine.core.process.definition.model.event.SCatchEventDefinition;
import org.bonitasoft.engine.core.process.definition.model.event.SEventDefinition;
import org.bonitasoft.engine.core.process.definition.model.event.trigger.SCatchMessageEventTriggerDefinition;
import org.bonitasoft.engine.core.process.definition.model.event.trigger.SCorrelationDefinition;
import org.bonitasoft.engine.core.process.definition.model.event.trigger.SEventTriggerDefinition;
import org.bonitasoft.engine.core.process.definition.model.event.trigger.SMessageEventTriggerDefinition;
import org.bonitasoft.engine.core.process.definition.model.event.trigger.SThrowMessageEventTriggerDefinition;
import org.bonitasoft.engine.core.process.instance.api.event.EventInstanceService;
import org.bonitasoft.engine.core.process.instance.api.exceptions.event.trigger.SMessageInstanceCreationException;
import org.bonitasoft.engine.core.process.instance.api.exceptions.event.trigger.SWaitingEventCreationException;
import org.bonitasoft.engine.core.process.instance.model.SProcessInstance;
import org.bonitasoft.engine.core.process.instance.model.SReceiveTaskInstance;
import org.bonitasoft.engine.core.process.instance.model.SSendTaskInstance;
import org.bonitasoft.engine.core.process.instance.model.builder.event.handling.SCorrelationContainerBuilder;
import org.bonitasoft.engine.core.process.instance.model.builder.event.handling.SMessageInstanceBuilder;
import org.bonitasoft.engine.core.process.instance.model.builder.event.handling.SWaitingMessageEventBuilder;
import org.bonitasoft.engine.core.process.instance.model.builder.event.handling.SWaitingMessageEventBuilderFactory;
import org.bonitasoft.engine.core.process.instance.model.event.SCatchEventInstance;
import org.bonitasoft.engine.core.process.instance.model.event.SThrowEventInstance;
import org.bonitasoft.engine.core.process.instance.model.event.handling.SBPMEventType;
import org.bonitasoft.engine.core.process.instance.model.event.handling.SMessageInstance;
import org.bonitasoft.engine.core.process.instance.model.event.handling.SWaitingEvent;
import org.bonitasoft.engine.data.instance.api.DataInstanceContainer;
import org.bonitasoft.engine.data.instance.exception.SDataInstanceException;
import org.bonitasoft.engine.expression.exception.SExpressionDependencyMissingException;
import org.bonitasoft.engine.expression.exception.SExpressionEvaluationException;
import org.bonitasoft.engine.expression.exception.SExpressionException;
import org.bonitasoft.engine.expression.exception.SExpressionTypeUnknownException;
import org.bonitasoft.engine.expression.exception.SInvalidExpressionException;
import org.bonitasoft.engine.expression.model.SExpression;
import org.bonitasoft.engine.message.MessagesHandlingService;
import org.bonitasoft.engine.transaction.STransactionNotFoundException;
/**
* @author Baptiste Mesta
* @author Elias Ricken de Medeiros
* @author Celine Souchet
*/
@Slf4j
public class MessageEventHandlerStrategy extends CoupleEventHandlerStrategy {
private static final String CORRELATION_NO_VALUE = "NONE";
private final ExpressionResolverService expressionResolverService;
private final BPMInstancesCreator bpmInstancesCreator;
private final ProcessDefinitionService processDefinitionService;
private final MessagesHandlingService messagesHandlingService;
public MessageEventHandlerStrategy(final ExpressionResolverService expressionResolverService,
final EventInstanceService eventInstanceService, final BPMInstancesCreator bpmInstancesCreator,
final ProcessDefinitionService processDefinitionService, MessagesHandlingService messagesHandlingService) {
super(eventInstanceService);
this.expressionResolverService = expressionResolverService;
this.bpmInstancesCreator = bpmInstancesCreator;
this.processDefinitionService = processDefinitionService;
this.messagesHandlingService = messagesHandlingService;
}
@Override
public void handleCatchEvent(final SProcessDefinition processDefinition, final SEventDefinition eventDefinition,
final SCatchEventInstance eventInstance,
final SEventTriggerDefinition sEventTriggerDefinition) throws SBonitaException {
final SCatchMessageEventTriggerDefinition messageTrigger = (SCatchMessageEventTriggerDefinition) sEventTriggerDefinition;
final String messageName = messageTrigger.getMessageName();
final String processName = processDefinition.getName();
final SWaitingMessageEventBuilder builder;
SExpressionContext expressionContext;
switch (eventDefinition.getType()) {
case BOUNDARY_EVENT:
builder = BuilderFactory.get(SWaitingMessageEventBuilderFactory.class)
.createNewWaitingMessageBoundaryEventInstance(processDefinition.getId(),
eventInstance.getRootContainerId(), eventInstance.getParentProcessInstanceId(),
eventInstance.getId(), messageName, processName,
eventInstance.getFlowNodeDefinitionId(),
eventInstance.getName());
expressionContext = new SExpressionContext(eventInstance.getParentContainerId(),
getParentContainerType(eventInstance).name(),
processDefinition.getId());
break;
case INTERMEDIATE_CATCH_EVENT:
builder = BuilderFactory.get(SWaitingMessageEventBuilderFactory.class)
.createNewWaitingMessageIntermediateEventInstance(
processDefinition.getId(),
eventInstance.getRootContainerId(), eventInstance.getParentProcessInstanceId(),
eventInstance.getId(), messageName, processName,
eventInstance.getFlowNodeDefinitionId(),
eventInstance.getName());
expressionContext = new SExpressionContext(eventInstance.getParentContainerId(),
getParentContainerType(eventInstance).name(),
processDefinition.getId());
break;
case START_EVENT:
builder = BuilderFactory.get(SWaitingMessageEventBuilderFactory.class)
.createNewWaitingMessageStartEventInstance(processDefinition.getId(),
messageTrigger.getMessageName(), processDefinition.getName(), eventDefinition.getId(),
eventDefinition.getName());
expressionContext = new SExpressionContext();
expressionContext.setProcessDefinitionId(processDefinition.getId());
break;
default:
throw new SWaitingEventCreationException(eventDefinition.getType() + " is not a catch event.");
}
fillCorrelation(builder, messageTrigger.getCorrelations(), expressionContext);
getEventInstanceService().createWaitingEvent(builder.done());
messagesHandlingService.triggerMatchingOfMessages();
}
public void handleCatchEvent(final SProcessDefinition processDefinition,
final SReceiveTaskInstance receiveTaskInstance,
final SEventTriggerDefinition sEventTriggerDefinition) throws SBonitaException {
final SCatchMessageEventTriggerDefinition messageTrigger = (SCatchMessageEventTriggerDefinition) sEventTriggerDefinition;
final String messageName = messageTrigger.getMessageName();
final String processName = processDefinition.getName();
final SWaitingMessageEventBuilder builder;
SExpressionContext expressionContext;
builder = BuilderFactory.get(SWaitingMessageEventBuilderFactory.class)
.createNewWaitingMessageIntermediateEventInstance(processDefinition.getId(),
receiveTaskInstance.getRootContainerId(), receiveTaskInstance.getParentProcessInstanceId(),
receiveTaskInstance.getId(), messageName,
processName, receiveTaskInstance.getFlowNodeDefinitionId(),
receiveTaskInstance.getName());
expressionContext = new SExpressionContext(receiveTaskInstance.getParentContainerId(),
getParentContainerType(receiveTaskInstance).name(),
processDefinition.getId());
fillCorrelation(builder, messageTrigger.getCorrelations(), expressionContext);
getEventInstanceService().createWaitingEvent(builder.done());
messagesHandlingService.triggerMatchingOfMessages();
}
@Override
public void handleThrowEvent(final SProcessDefinition processDefinition, final SEventDefinition eventDefinition,
final SThrowEventInstance eventInstance,
final SEventTriggerDefinition sEventTriggerDefinition) throws SBonitaException {
final Long processDefinitionId = processDefinition.getId();
final SExpressionContext expressionContext = new SExpressionContext(eventInstance.getParentContainerId(),
getParentContainerType(eventInstance).name(),
processDefinitionId);
handleThrowMessage(sEventTriggerDefinition, eventInstance.getName(), processDefinitionId, expressionContext);
}
public void handleThrowEvent(final SProcessDefinition processDefinition, final SSendTaskInstance sendTaskInstance,
final SThrowMessageEventTriggerDefinition messageTrigger) throws SMessageInstanceCreationException,
SDataInstanceException, SExpressionException, STransactionNotFoundException {
final SExpressionContext expressionContext = new SExpressionContext(sendTaskInstance.getId(),
DataInstanceContainer.ACTIVITY_INSTANCE.name(),
processDefinition.getId());
handleThrowMessage(messageTrigger, sendTaskInstance.getName(), processDefinition.getId(), expressionContext);
}
private void handleThrowMessage(final SEventTriggerDefinition sEventTriggerDefinition,
final String eventInstanceName,
final Long processDefinitionId, final SExpressionContext expressionContext)
throws SMessageInstanceCreationException, SDataInstanceException, SExpressionException,
STransactionNotFoundException {
final SThrowMessageEventTriggerDefinition messageTrigger = (SThrowMessageEventTriggerDefinition) sEventTriggerDefinition;
final String messageName = messageTrigger.getMessageName();
final SExpression targetProcess = messageTrigger.getTargetProcess();
final SExpression targetFlowNode = messageTrigger.getTargetFlowNode();
// evaluate expression
final String stringTargetProcess = (String) expressionResolverService.evaluate(targetProcess,
expressionContext);
String stringTargetFlowNode = null;
if (targetFlowNode != null) {
stringTargetFlowNode = (String) expressionResolverService.evaluate(targetFlowNode, expressionContext);
}
final SMessageInstanceBuilder builder = SMessageInstanceBuilder.create(messageName, stringTargetProcess,
stringTargetFlowNode, processDefinitionId, eventInstanceName);
final List correlations = messageTrigger.getCorrelations();
fillCorrelation(builder, correlations, expressionContext);
final SMessageInstance messageInstance = builder.done();
// evaluate and add correlations
getEventInstanceService().createMessageInstance(messageInstance);
messagesHandlingService.triggerMatchingOfMessages();
// create data
if (!messageTrigger.getDataDefinitions().isEmpty()) {
bpmInstancesCreator.createDataInstances(messageTrigger.getDataDefinitions(), messageInstance.getId(),
DataInstanceContainer.MESSAGE_INSTANCE,
expressionContext);
if (log.isDebugEnabled()) {
log.debug("Initialized variables for message instance [name: <{}>, id: <{}>, flow node: <{}>," +
" target flow node: <{}>, target process: <{}>, process definition: <{}>]",
messageInstance.getMessageName(), messageInstance.getId(), messageInstance.getFlowNodeName(),
messageInstance.getTargetFlowNode(), messageInstance.getTargetProcess(),
messageInstance.getProcessDefinitionId());
}
}
}
private void fillCorrelation(final SCorrelationContainerBuilder builder,
final List correlations,
final SExpressionContext expressionContext)
throws SExpressionTypeUnknownException, SExpressionEvaluationException,
SExpressionDependencyMissingException, SInvalidExpressionException {
final int size = Math.min(5, correlations.size());
final List toEval = new ArrayList<>(size * 2);
if (size > 0) {
for (int i = 0; i < size; i++) {
final SCorrelationDefinition sCorrelationDefinition = correlations.get(i);
toEval.add(sCorrelationDefinition.getKey());
toEval.add(sCorrelationDefinition.getValue());
}
final List