org.bonitasoft.engine.execution.ProcessExecutorImpl 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;
import static org.bonitasoft.engine.classloader.ClassLoaderIdentifier.identifier;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import lombok.extern.slf4j.Slf4j;
import org.bonitasoft.engine.SArchivingException;
import org.bonitasoft.engine.bdm.Entity;
import org.bonitasoft.engine.bpm.connector.ConnectorDefinition;
import org.bonitasoft.engine.bpm.connector.ConnectorDefinitionWithInputValues;
import org.bonitasoft.engine.bpm.connector.ConnectorEvent;
import org.bonitasoft.engine.bpm.contract.validation.ContractValidator;
import org.bonitasoft.engine.bpm.contract.validation.ContractValidatorFactory;
import org.bonitasoft.engine.bpm.document.DocumentValue;
import org.bonitasoft.engine.bpm.model.impl.BPMInstancesCreator;
import org.bonitasoft.engine.bpm.process.ActivationState;
import org.bonitasoft.engine.bpm.process.ProcessInstanceState;
import org.bonitasoft.engine.builder.BuilderFactory;
import org.bonitasoft.engine.business.data.BusinessDataRepository;
import org.bonitasoft.engine.business.data.proxy.ServerProxyfier;
import org.bonitasoft.engine.classloader.ClassLoaderService;
import org.bonitasoft.engine.classloader.SClassLoaderException;
import org.bonitasoft.engine.commons.exceptions.SBonitaException;
import org.bonitasoft.engine.commons.exceptions.SObjectCreationException;
import org.bonitasoft.engine.commons.exceptions.SObjectModificationException;
import org.bonitasoft.engine.core.connector.ConnectorInstanceService;
import org.bonitasoft.engine.core.connector.ConnectorResult;
import org.bonitasoft.engine.core.connector.ConnectorService;
import org.bonitasoft.engine.core.connector.exception.SConnectorException;
import org.bonitasoft.engine.core.connector.exception.SConnectorInstanceReadException;
import org.bonitasoft.engine.core.contract.data.ContractDataService;
import org.bonitasoft.engine.core.contract.data.SContractDataCreationException;
import org.bonitasoft.engine.core.document.api.DocumentService;
import org.bonitasoft.engine.core.document.api.impl.DocumentHelper;
import org.bonitasoft.engine.core.expression.control.api.ExpressionResolverService;
import org.bonitasoft.engine.core.expression.control.model.SExpressionContext;
import org.bonitasoft.engine.core.operation.OperationService;
import org.bonitasoft.engine.core.operation.exception.SOperationExecutionException;
import org.bonitasoft.engine.core.operation.model.SOperation;
import org.bonitasoft.engine.core.process.definition.ProcessDefinitionService;
import org.bonitasoft.engine.core.process.definition.exception.SProcessDefinitionException;
import org.bonitasoft.engine.core.process.definition.exception.SProcessDefinitionNotFoundException;
import org.bonitasoft.engine.core.process.definition.model.SBusinessDataDefinition;
import org.bonitasoft.engine.core.process.definition.model.SConnectorDefinition;
import org.bonitasoft.engine.core.process.definition.model.SContractDefinition;
import org.bonitasoft.engine.core.process.definition.model.SDocumentDefinition;
import org.bonitasoft.engine.core.process.definition.model.SDocumentListDefinition;
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.SFlowNodeType;
import org.bonitasoft.engine.core.process.definition.model.SGatewayDefinition;
import org.bonitasoft.engine.core.process.definition.model.SGatewayType;
import org.bonitasoft.engine.core.process.definition.model.SProcessDefinition;
import org.bonitasoft.engine.core.process.definition.model.SProcessDefinitionDeployInfo;
import org.bonitasoft.engine.core.process.definition.model.STransitionDefinition;
import org.bonitasoft.engine.core.process.definition.model.event.SEndEventDefinition;
import org.bonitasoft.engine.core.process.instance.api.ActivityInstanceService;
import org.bonitasoft.engine.core.process.instance.api.GatewayInstanceService;
import org.bonitasoft.engine.core.process.instance.api.ProcessInstanceService;
import org.bonitasoft.engine.core.process.instance.api.RefBusinessDataService;
import org.bonitasoft.engine.core.process.instance.api.exceptions.SActivityInstanceNotFoundException;
import org.bonitasoft.engine.core.process.instance.api.exceptions.SActivityReadException;
import org.bonitasoft.engine.core.process.instance.api.exceptions.SContractViolationException;
import org.bonitasoft.engine.core.process.instance.api.exceptions.SFlowNodeExecutionException;
import org.bonitasoft.engine.core.process.instance.api.exceptions.SProcessInstanceCreationException;
import org.bonitasoft.engine.core.process.instance.api.exceptions.SProcessInstanceModificationException;
import org.bonitasoft.engine.core.process.instance.api.states.FlowNodeState;
import org.bonitasoft.engine.core.process.instance.model.SActivityInstance;
import org.bonitasoft.engine.core.process.instance.model.SConnectorInstance;
import org.bonitasoft.engine.core.process.instance.model.SFlowElementsContainerType;
import org.bonitasoft.engine.core.process.instance.model.SFlowNodeInstance;
import org.bonitasoft.engine.core.process.instance.model.SGatewayInstance;
import org.bonitasoft.engine.core.process.instance.model.SProcessInstance;
import org.bonitasoft.engine.core.process.instance.model.SStateCategory;
import org.bonitasoft.engine.core.process.instance.model.builder.business.data.SRefBusinessDataInstanceBuilderFactory;
import org.bonitasoft.engine.core.process.instance.model.business.data.SRefBusinessDataInstance;
import org.bonitasoft.engine.core.process.instance.model.event.SThrowEventInstance;
import org.bonitasoft.engine.data.instance.api.DataInstanceContainer;
import org.bonitasoft.engine.dependency.model.ScopeType;
import org.bonitasoft.engine.events.EventService;
import org.bonitasoft.engine.events.model.HandlerRegistrationException;
import org.bonitasoft.engine.events.model.SEvent;
import org.bonitasoft.engine.exception.BonitaRuntimeException;
import org.bonitasoft.engine.execution.archive.BPMArchiverService;
import org.bonitasoft.engine.execution.event.EventsHandler;
import org.bonitasoft.engine.execution.flowmerger.FlowNodeTransitionsWrapper;
import org.bonitasoft.engine.execution.handler.SProcessInstanceHandler;
import org.bonitasoft.engine.execution.work.BPMWorkFactory;
import org.bonitasoft.engine.expression.Expression;
import org.bonitasoft.engine.expression.ExpressionService;
import org.bonitasoft.engine.expression.exception.SExpressionDependencyMissingException;
import org.bonitasoft.engine.expression.exception.SExpressionEvaluationException;
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.operation.Operation;
import org.bonitasoft.engine.persistence.SBonitaReadException;
import org.bonitasoft.engine.recorder.model.EntityUpdateDescriptor;
import org.bonitasoft.engine.resources.BARResourceType;
import org.bonitasoft.engine.resources.ProcessResourcesService;
import org.bonitasoft.engine.service.ModelConvertor;
import org.bonitasoft.engine.work.SWorkRegisterException;
import org.bonitasoft.engine.work.WorkService;
/**
* @author Baptiste Mesta
* @author Matthieu Chaffotte
* @author Yanyan Liu
* @author Elias Ricken de Medeiros
* @author Hongwen Zang
* @author Celine Souchet
*/
@Slf4j
public class ProcessExecutorImpl implements ProcessExecutor {
protected final ActivityInstanceService activityInstanceService;
protected final ProcessInstanceService processInstanceService;
protected final ClassLoaderService classLoaderService;
protected final ExpressionResolverService expressionResolverService;
protected final ExpressionService expressionService;
protected final ConnectorService connectorService;
protected final BPMInstancesCreator bpmInstancesCreator;
protected final EventsHandler eventsHandler;
private final FlowNodeExecutor flowNodeExecutor;
private final WorkService workService;
private final ProcessDefinitionService processDefinitionService;
private final GatewayInstanceService gatewayInstanceService;
private final OperationService operationService;
private final ProcessResourcesService processResourcesService;
private final ConnectorInstanceService connectorInstanceService;
private final TransitionEvaluator transitionEvaluator;
private final ContractDataService contractDataService;
private final BusinessDataRepository businessDataRepository;
private final RefBusinessDataService refBusinessDataService;
private final DocumentHelper documentHelper;
private final BPMWorkFactory workFactory;
private final BPMArchiverService bpmArchiverService;
private final ProcessStarterVerifier processStarterVerifier;
public ProcessExecutorImpl(final ActivityInstanceService activityInstanceService,
final ProcessInstanceService processInstanceService, final FlowNodeExecutor flowNodeExecutor,
final WorkService workService,
final ProcessDefinitionService processDefinitionService,
final GatewayInstanceService gatewayInstanceService,
final ProcessResourcesService processResourcesService, final ConnectorService connectorService,
final ConnectorInstanceService connectorInstanceService, final ClassLoaderService classLoaderService,
final OperationService operationService,
final ExpressionResolverService expressionResolverService, final ExpressionService expressionService,
final EventService eventService,
final Map> handlers, final DocumentService documentService,
final ContainerRegistry containerRegistry, final BPMInstancesCreator bpmInstancesCreator,
final EventsHandler eventsHandler,
final BusinessDataRepository businessDataRepository,
final RefBusinessDataService refBusinessDataService, final TransitionEvaluator transitionEvaluator,
final ContractDataService contractDataService, BPMWorkFactory workFactory,
BPMArchiverService bpmArchiverService, final ProcessStarterVerifier processStarterVerifier) {
super();
this.activityInstanceService = activityInstanceService;
this.processInstanceService = processInstanceService;
this.processResourcesService = processResourcesService;
this.connectorInstanceService = connectorInstanceService;
this.flowNodeExecutor = flowNodeExecutor;
this.workService = workService;
this.processDefinitionService = processDefinitionService;
this.gatewayInstanceService = gatewayInstanceService;
this.connectorService = connectorService;
this.classLoaderService = classLoaderService;
this.operationService = operationService;
this.expressionResolverService = expressionResolverService;
this.expressionService = expressionService;
this.bpmInstancesCreator = bpmInstancesCreator;
this.eventsHandler = eventsHandler;
this.transitionEvaluator = transitionEvaluator;
this.businessDataRepository = businessDataRepository;
this.refBusinessDataService = refBusinessDataService;
this.contractDataService = contractDataService;
this.workFactory = workFactory;
this.bpmArchiverService = bpmArchiverService;
this.processStarterVerifier = processStarterVerifier;
documentHelper = new DocumentHelper(documentService, processDefinitionService, processInstanceService);
//FIXME There is responsibility issue the circular dependencies must be fixed next time.
eventsHandler.setProcessExecutor(this);
for (final Entry> handler : handlers.entrySet()) {
try {
eventService.addHandler(handler.getKey(), handler.getValue());
} catch (final HandlerRegistrationException e) {
log.warn(e.getMessage());
log.debug("", e);
}
}
containerRegistry.addContainerExecutor(this);
}
@Override
public FlowNodeState executeFlowNode(SFlowNodeInstance flowNodeInstance, Long executerId, Long executerSubstituteId)
throws SFlowNodeExecutionException {
return flowNodeExecutor.stepForward(flowNodeInstance, executerId, executerSubstituteId);
}
private SConnectorInstance getNextConnectorInstance(final SProcessInstance processInstance,
final ConnectorEvent event)
throws SConnectorInstanceReadException {
final List connectorInstances = connectorInstanceService.getConnectorInstances(
processInstance.getId(),
SConnectorInstance.PROCESS_TYPE, event, 0, 1, ConnectorService.TO_BE_EXECUTED);
return connectorInstances.size() == 1 ? connectorInstances.get(0) : null;
}
@Override
public boolean registerConnectorsToExecute(final SProcessDefinition processDefinition,
final SProcessInstance sProcessInstance, final ConnectorEvent activationEvent,
final FlowNodeSelector selectorForConnectorOnEnter) throws SBonitaException {
final SFlowElementContainerDefinition processContainer = processDefinition.getProcessContainer();
final long processDefinitionId = processDefinition.getId();
final List connectors = processContainer.getConnectors(activationEvent);
if (connectors.size() > 0) {
SConnectorInstance nextConnectorInstance;
nextConnectorInstance = getNextConnectorInstance(sProcessInstance, activationEvent);
if (nextConnectorInstance != null) {
// TODO: extract this search algorithm in a dedicated method:
for (final SConnectorDefinition sConnectorDefinition : connectors) {
if (sConnectorDefinition.getName().equals(nextConnectorInstance.getName())) {
workService.registerWork(workFactory.createExecuteConnectorOfProcessDescriptor(
processDefinitionId, sProcessInstance.getId(),
sProcessInstance.getRootProcessInstanceId(), nextConnectorInstance.getId(),
sConnectorDefinition.getName(), activationEvent,
selectorForConnectorOnEnter));
return true;
}
}
}
}
return false;
}
private List initializeFirstExecutableElements(final SProcessInstance sProcessInstance,
final FlowNodeSelector selector) {
try {
final List flownNodeDefinitions = selector.getFilteredElements();
long rootProcessInstanceId = sProcessInstance.getRootProcessInstanceId();
if (rootProcessInstanceId <= 0) {
rootProcessInstanceId = sProcessInstance.getId();
}
return bpmInstancesCreator.createFlowNodeInstances(selector.getProcessDefinition().getId(),
rootProcessInstanceId, sProcessInstance.getId(),
flownNodeDefinitions, rootProcessInstanceId, sProcessInstance.getId(), SStateCategory.NORMAL);
} catch (final SBonitaException e) {
setExceptionContext(selector.getProcessDefinition(), sProcessInstance, e);
log.error("", e);
throw new BonitaRuntimeException(e);
}
}
private SProcessInstance createProcessInstance(final SProcessDefinition sDefinition, final long starterId,
final long starterSubstituteId,
final long callerId, final SFlowNodeType callerType, final long rootProcessInstanceId)
throws SProcessInstanceCreationException {
SProcessInstance sProcessInstance = SProcessInstance.builder().name(sDefinition.getName())
.processDefinitionId(sDefinition.getId()).description(sDefinition.getDescription())
.startedBy(starterId).startedBySubstitute(starterSubstituteId).callerId(callerId).callerType(callerType)
.rootProcessInstanceId(rootProcessInstanceId).build();
processInstanceService.createProcessInstance(sProcessInstance);
return sProcessInstance;
}
protected SProcessInstance createProcessInstance(final SProcessDefinition processDefinition, final long starterId,
final long starterSubstituteId,
final long callerId) throws SProcessInstanceCreationException {
SActivityInstance callerInstance;
try {
callerInstance = getCaller(callerId);
} catch (final SBonitaException e) {
throw new SProcessInstanceCreationException("Unable to get caller.", e);
}
if (callerInstance != null) {
return createProcessInstance(processDefinition, starterId, starterSubstituteId, callerId,
callerInstance.getType(),
callerInstance.getRootContainerId());
}
return createProcessInstance(processDefinition, starterId, starterSubstituteId, callerId, null, -1);
}
private SActivityInstance getCaller(final long callerId)
throws SActivityReadException, SActivityInstanceNotFoundException {
if (callerId > 0) {
return activityInstanceService.getActivityInstance(callerId);
}
return null;
}
/*
* this method is called when a flow node having a transition that goes to a gateway is finished
* it get the active gateway pointed by this transition, update the tokens of this gateway and execute it if merged
*/
private void executeGateway(final SProcessDefinition sProcessDefinition,
final STransitionDefinition sTransitionDefinition,
final SFlowNodeInstance flowNodeThatTriggeredTheTransition) throws SBonitaException {
final long parentProcessInstanceId = flowNodeThatTriggeredTheTransition.getParentProcessInstanceId();
final long rootProcessInstanceId = flowNodeThatTriggeredTheTransition.getRootProcessInstanceId();
final SFlowNodeDefinition sFlowNodeDefinition = processDefinitionService.getNextFlowNode(sProcessDefinition,
String.valueOf(sTransitionDefinition.getId()));
try {
List gatewaysToExecute = new ArrayList<>(1);
final SProcessInstance parentProcessInstance = processInstanceService
.getProcessInstance(parentProcessInstanceId);
final SStateCategory stateCategory = parentProcessInstance.getStateCategory();
final SGatewayInstance gatewayInstance = getActiveGatewayOrCreateIt(sProcessDefinition, sFlowNodeDefinition,
stateCategory,
parentProcessInstanceId,
rootProcessInstanceId);
gatewayInstanceService.hitTransition(gatewayInstance,
sFlowNodeDefinition.getTransitionIndex(sTransitionDefinition.getId()));
if (gatewayInstanceService.checkMergingCondition(sProcessDefinition, gatewayInstance)) {
gatewaysToExecute.add(gatewayInstance);
gatewaysToExecute.addAll(gatewayInstanceService
.setFinishAndCreateNewGatewayForRemainingToken(sProcessDefinition, gatewayInstance));
}
for (final SGatewayInstance gatewayToExecute : gatewaysToExecute) {
registerExecuteFlowNodeWork(gatewayToExecute);
}
} catch (final SBonitaException e) {
setExceptionContext(sProcessDefinition, flowNodeThatTriggeredTheTransition, e);
log.error("", e);
throw e;
}
}
/*
* try to gate active gateway.
* if the gateway is already hit by this transition or by the same token, we create a new gateway
*/
SGatewayInstance getActiveGatewayOrCreateIt(final SProcessDefinition sProcessDefinition,
final SFlowNodeDefinition flowNodeDefinition,
final SStateCategory stateCategory, final long parentProcessInstanceId, final long rootProcessInstanceId)
throws SBonitaException {
SGatewayInstance gatewayInstance = gatewayInstanceService
.getActiveGatewayInstanceOfTheProcess(parentProcessInstanceId, flowNodeDefinition.getName());
if (gatewayInstance == null) {
// no gateway found we create one
gatewayInstance = createGateway(sProcessDefinition.getId(), flowNodeDefinition, stateCategory,
parentProcessInstanceId, rootProcessInstanceId);
}
return gatewayInstance;
}
private SGatewayInstance createGateway(final Long processDefinitionId, final SFlowNodeDefinition flowNodeDefinition,
final SStateCategory stateCategory,
final long parentProcessInstanceId, final long rootProcessInstanceId) throws SBonitaException {
return (SGatewayInstance) bpmInstancesCreator
.createFlowNodeInstance(processDefinitionId, rootProcessInstanceId, parentProcessInstanceId,
SFlowElementsContainerType.PROCESS,
flowNodeDefinition, rootProcessInstanceId, parentProcessInstanceId, false, 0, stateCategory,
-1);
}
protected void executeOperations(final List operations, final Map context,
SExpressionContext expressionContext,
final SExpressionContext expressionContextToEvaluateOperations,
final SProcessInstance sProcessInstance) throws SBonitaException {
if (operations != null && !operations.isEmpty()) {
SExpressionContext currentExpressionContext = expressionContextToEvaluateOperations != null
? expressionContextToEvaluateOperations
: expressionContext;
currentExpressionContext.setInputValues(context);
if (currentExpressionContext.getContainerId() == null) {
currentExpressionContext.setContainerId(sProcessInstance.getId());
currentExpressionContext.setContainerType(DataInstanceContainer.PROCESS_INSTANCE.name());
}
operationService.execute(new ArrayList<>(operations), sProcessInstance.getId(),
DataInstanceContainer.PROCESS_INSTANCE.name(),
currentExpressionContext);
}
}
protected boolean initialize(final long userId, final SProcessDefinition sProcessDefinition,
final SProcessInstance sProcessInstance,
SExpressionContext expressionContextToEvaluateOperations, List operations,
final Map context,
final SFlowElementContainerDefinition processContainer,
final List connectors,
final FlowNodeSelector selectorForConnectorOnEnter, final Map processInputs)
throws SBonitaException {
SExpressionContext expressionContext = createExpressionsContextForProcessInstance(sProcessDefinition,
sProcessInstance);
operations = operations != null ? new ArrayList<>(operations) : Collections.emptyList();
storeProcessInstantiationInputs(sProcessInstance.getId(), processInputs);
// Create SDataInstances
bpmInstancesCreator.createDataInstances(sProcessInstance, processContainer, sProcessDefinition,
expressionContext, operations, context,
expressionContextToEvaluateOperations);
initializeBusinessData(processContainer, sProcessInstance, expressionContext);
initializeStringIndexes(sProcessInstance, sProcessDefinition, processContainer);
createDocuments(sProcessDefinition, processContainer, sProcessInstance, userId, expressionContext, context);
createDocumentLists(processContainer, sProcessInstance, userId, expressionContext, context);
if (connectors != null) {
//these are set only when start process through the command ExecuteActionsAndStartInstanceExt
executeConnectors(sProcessDefinition, sProcessInstance, connectors);
}
// operations given to the startProcess method of the API or by command, not operations of the process definition
executeOperations(operations, context, expressionContext, expressionContextToEvaluateOperations,
sProcessInstance);
// Create connectors
bpmInstancesCreator.createConnectorInstances(sProcessInstance, processContainer.getConnectors(),
SConnectorInstance.PROCESS_TYPE);
return registerConnectorsToExecute(sProcessDefinition, sProcessInstance, ConnectorEvent.ON_ENTER,
selectorForConnectorOnEnter);
}
private SExpressionContext createExpressionsContextForProcessInstance(SProcessDefinition sProcessDefinition,
SProcessInstance sProcessInstance) {
SExpressionContext expressionContext = new SExpressionContext();
expressionContext.setProcessDefinitionId(sProcessDefinition.getId());
expressionContext.setContainerId(sProcessInstance.getId());
expressionContext.setContainerType(DataInstanceContainer.PROCESS_INSTANCE.name());
return expressionContext;
}
private void storeProcessInstantiationInputs(final long processInstanceId,
final Map processInputs)
throws SContractDataCreationException {
contractDataService.addProcessData(processInstanceId, processInputs);
}
protected void initializeBusinessData(SFlowElementContainerDefinition processContainer, SProcessInstance sInstance,
SExpressionContext expressionContext)
throws SBonitaException {
final List businessDataDefinitions = processContainer.getBusinessDataDefinitions();
for (final SBusinessDataDefinition bdd : businessDataDefinitions) {
final SExpression expression = bdd.getDefaultValueExpression();
if (bdd.isMultiple()) {
final List dataIds = initializeMultipleBusinessDataIds(expressionContext, expression);
final SRefBusinessDataInstanceBuilderFactory instanceFactory = BuilderFactory
.get(SRefBusinessDataInstanceBuilderFactory.class);
final SRefBusinessDataInstance instance = instanceFactory
.createNewInstance(bdd.getName(), sInstance.getId(), dataIds, bdd.getClassName())
.done();
refBusinessDataService.addRefBusinessDataInstance(instance);
} else {
final Long primaryKey = initializeSingleBusinessData(expressionContext, expression);
final SRefBusinessDataInstanceBuilderFactory instanceFactory = BuilderFactory
.get(SRefBusinessDataInstanceBuilderFactory.class);
final SRefBusinessDataInstance instance = instanceFactory
.createNewInstance(bdd.getName(), sInstance.getId(), primaryKey,
bdd.getClassName())
.done();
refBusinessDataService.addRefBusinessDataInstance(instance);
}
}
}
private Long initializeSingleBusinessData(final SExpressionContext expressionContext, final SExpression expression)
throws SBonitaException {
Long primaryKey = null;
if (expression != null) {
final Entity businessData = (Entity) expressionResolverService.evaluate(expression, expressionContext);
primaryKey = saveBusinessData(businessData);
}
return primaryKey;
}
private List initializeMultipleBusinessDataIds(final SExpressionContext expressionContext,
final SExpression expression) throws SBonitaException {
final List dataIds = new ArrayList<>();
if (expression != null) {
final List businessData = (List) expressionResolverService.evaluate(expression,
expressionContext);
if (businessData != null) {
for (final Entity entity : businessData) {
dataIds.add(saveBusinessData(entity));
}
}
}
return dataIds;
}
private Long saveBusinessData(final Entity entity) throws SObjectCreationException {
try {
final Entity mergedBusinessData = businessDataRepository.merge(ServerProxyfier.unProxifyIfNeeded(entity));
if (mergedBusinessData == null) {
return null;
}
return mergedBusinessData.getPersistenceId();
} catch (IllegalArgumentException e) {
throw new SObjectCreationException("Unable to save the business data", e);
}
}
private void createDocuments(final SProcessDefinition sDefinition, SFlowElementContainerDefinition processContainer,
final SProcessInstance sProcessInstance, final long authorId,
final SExpressionContext expressionContext, final Map context)
throws SObjectCreationException, SBonitaReadException, SObjectModificationException,
SExpressionTypeUnknownException, SExpressionDependencyMissingException, SExpressionEvaluationException,
SInvalidExpressionException, SOperationExecutionException {
final List documentDefinitions = processContainer.getDocumentDefinitions();
final Map evaluatedDocumentValues = evaluateInitialExpressionsOfDocument(
sProcessInstance, expressionContext, context,
documentDefinitions);
if (!documentDefinitions.isEmpty()) {
for (final SDocumentDefinition document : documentDefinitions) {
final DocumentValue documentValue = getInitialDocumentValue(sDefinition, evaluatedDocumentValues,
document);
if (documentValue != null) {
documentHelper.createOrUpdateDocument(documentValue,
document.getName(), sProcessInstance.getId(), authorId, document.getDescription());
}
}
}
}
protected DocumentValue getInitialDocumentValue(final SProcessDefinition sDefinition,
final Map evaluatedDocumentValues,
final SDocumentDefinition document) throws SBonitaReadException {
DocumentValue documentValue = null;
if (document.getInitialValue() != null) {
documentValue = evaluatedDocumentValues.get(document.getInitialValue());
} else if (document.getFile() != null) {
final byte[] content = getProcessDocumentContent(sDefinition, document);
documentValue = new DocumentValue(content, document.getMimeType(), document.getFileName());
} else if (document.getUrl() != null) {
documentValue = new DocumentValue(document.getUrl());
documentValue.setFileName(document.getFileName());
documentValue.setMimeType(document.getMimeType());
}
return documentValue;
}
byte[] getProcessDocumentContent(final SProcessDefinition sDefinition, final SDocumentDefinition document)
throws SBonitaReadException {
final String file = document.getFile();// should always exists...validation on BusinessArchive
return processResourcesService.get(sDefinition.getId(), BARResourceType.DOCUMENT, file).getContent();
}
private Map evaluateInitialExpressionsOfDocument(final SProcessInstance processInstance,
final SExpressionContext expressionContext,
final Map context, final List documentDefinitions)
throws SExpressionTypeUnknownException,
SExpressionEvaluationException, SExpressionDependencyMissingException, SInvalidExpressionException,
SOperationExecutionException {
final List initialValuesExpressions = new ArrayList<>(documentDefinitions.size());
final Map evaluatedDocumentValue = new HashMap<>();
for (final SDocumentDefinition documentDefinition : documentDefinitions) {
if (documentDefinition.getInitialValue() != null) {
initialValuesExpressions.add(documentDefinition.getInitialValue());
}
}
final List