All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bonitasoft.engine.execution.AdvancedStartProcessValidator Maven / Gradle / Ivy

There is a newer version: 10.2.0
Show 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 java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import org.bonitasoft.engine.bpm.contract.validation.ContractValidator;
import org.bonitasoft.engine.bpm.contract.validation.ContractValidatorFactory;
import org.bonitasoft.engine.commons.exceptions.SBonitaException;
import org.bonitasoft.engine.core.process.definition.ProcessDefinitionService;
import org.bonitasoft.engine.core.process.definition.model.SContractDefinition;
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.SProcessDefinition;
import org.bonitasoft.engine.core.process.definition.model.SUserTaskDefinition;
import org.bonitasoft.engine.core.process.instance.api.exceptions.SContractViolationException;
import org.bonitasoft.engine.expression.ExpressionService;

/**
 * @author Elias Ricken de Medeiros
 */
public class AdvancedStartProcessValidator {

    private final ProcessDefinitionService processDefinitionService;
    private final long processDefinitionId;

    private ExpressionService expressionService;

    public AdvancedStartProcessValidator(ProcessDefinitionService processDefinitionService, long processDefinitionId,
            ExpressionService expressionService) {
        this.processDefinitionService = processDefinitionService;
        this.processDefinitionId = processDefinitionId;
        this.expressionService = expressionService;
    }

    public List validate(List flowNodeNames, Map processContractInputs)
            throws SBonitaException {
        List problems = new ArrayList<>();
        if (flowNodeNames.isEmpty()) {
            problems.add("The list of activity names to start cannot be empty!");
        }
        List foundFlowNodes = new ArrayList<>(flowNodeNames.size());
        SProcessDefinition processDefinition = processDefinitionService.getProcessDefinition(processDefinitionId);
        problems.addAll(checkFlowNodesAreSupported(flowNodeNames, foundFlowNodes, processDefinition));
        problems.addAll(checkForNotFoundFlowNodes(flowNodeNames, foundFlowNodes, processDefinition));
        if (!problems.isEmpty()) {
            //check contract only if flow nodes are ok
            return problems;
        }
        problems.addAll(checkProcessContract(processContractInputs, processDefinition));
        return problems;
    }

    private List checkProcessContract(Map processContractInputs,
            SProcessDefinition processDefinition) {
        return validateContract(processContractInputs, processDefinition.getContract(), processDefinition.getName());
    }

    private List validateContract(Map inputs, SContractDefinition contract,
            String element) {
        if (contract == null) {
            return Collections.emptyList();
        }
        final ContractValidator validator = new ContractValidatorFactory().createContractValidator(expressionService);
        try {
            validator.validate(processDefinitionId, contract, inputs);
        } catch (SContractViolationException e) {
            return e.getExplanations().isEmpty() ? Collections.singletonList(e.getSimpleMessage() + " on " + element)
                    : appendElement(e, element);
        }
        return Collections.emptyList();
    }

    private List appendElement(SContractViolationException e, String element) {
        ArrayList strings = new ArrayList<>();
        for (String explanation : e.getExplanations()) {
            strings.add(explanation + " on " + element);
        }
        return strings;
    }

    private List checkFlowNodesContracts(List flowNodeNames,
            Map> activitiesContractInputs,
            SProcessDefinition processDefinition) {
        List problems = new ArrayList<>();
        for (String flowNodeName : flowNodeNames) {
            SFlowNodeDefinition flowNode = processDefinition.getProcessContainer().getFlowNode(flowNodeName);
            if (flowNode instanceof SUserTaskDefinition && ((SUserTaskDefinition) flowNode).getContract() != null) {
                problems.addAll(validateContract(
                        activitiesContractInputs == null ? Collections. emptyMap()
                                : activitiesContractInputs.get(flowNodeName),
                        ((SUserTaskDefinition) flowNode).getContract(), flowNodeName));
            }
        }
        return problems;
    }

    private List checkFlowNodesAreSupported(List flowNodeNames, List foundFlowNodes,
            SProcessDefinition processDefinition) {
        List problems = new ArrayList<>();
        for (SFlowNodeDefinition flowNode : processDefinition.getProcessContainer().getFlowNodes()) {
            boolean invalidType = SFlowNodeType.BOUNDARY_EVENT.equals(flowNode.getType())
                    || SFlowNodeType.SUB_PROCESS.equals(flowNode.getType())
                    || SFlowNodeType.GATEWAY.equals(flowNode.getType());
            if (flowNodeNames.contains(flowNode.getName())) {
                foundFlowNodes.add(flowNode.getName());
                if (invalidType) {
                    problems.add(buildInvalidTypeErrorMessage(processDefinition, flowNode));
                }
            }
        }
        return problems;
    }

    private List checkForNotFoundFlowNodes(List flowNodeNames, List foundFlowNodes,
            SProcessDefinition processDefinition) {
        List problems = new ArrayList<>();
        for (String flowNodeName : flowNodeNames) {
            if (!foundFlowNodes.contains(flowNodeName)) {
                problems.add(buildFlowNodeNotFoundErroMessage(processDefinition, flowNodeName));
            }
        }
        return problems;
    }

    private String buildInvalidTypeErrorMessage(SProcessDefinition processDefinition, SFlowNodeDefinition flowNode) {
        return "'" +
                flowNode.getName() +
                "' is not a valid start point for the process " +
                buildProcessContext(processDefinition) +
                " You cannot start a process from a gateway, a boundary event or an event sub-process";
    }

    private String buildFlowNodeNotFoundErroMessage(SProcessDefinition processDefinition, String flowNodeName) {
        return "No flownode named '" +
                flowNodeName +
                "' was found in the process" +
                buildProcessContext(processDefinition);
    }

    private String buildProcessContext(SProcessDefinition processDefinition) {
        return ".";
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy