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

org.activiti.engine.impl.bpmn.deployer.BpmnDeployer Maven / Gradle / Ivy

/* Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.activiti.engine.impl.bpmn.deployer;

import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.activiti.bpmn.constants.BpmnXMLConstants;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.ExtensionElement;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.SubProcess;
import org.activiti.bpmn.model.UserTask;
import org.activiti.bpmn.model.ValuedDataObject;
import org.activiti.engine.DynamicBpmnConstants;
import org.activiti.engine.DynamicBpmnService;
import org.activiti.engine.delegate.event.ActivitiEventType;
import org.activiti.engine.delegate.event.impl.ActivitiEventBuilder;
import org.activiti.engine.impl.cfg.IdGenerator;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.impl.persistence.deploy.Deployer;
import org.activiti.engine.impl.persistence.entity.DeploymentEntity;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntityManager;
import org.activiti.engine.impl.persistence.entity.ResourceEntity;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class BpmnDeployer implements Deployer {

    private static final Logger log = LoggerFactory.getLogger(BpmnDeployer.class);

    protected IdGenerator idGenerator;
    protected ParsedDeploymentBuilderFactory parsedDeploymentBuilderFactory;
    protected BpmnDeploymentHelper bpmnDeploymentHelper;
    protected CachingAndArtifactsManager cachingAndArtifactsManager;

    @Override
    public void deploy(DeploymentEntity deployment,
                       Map deploymentSettings) {
        log.debug("Processing deployment {}",
                  deployment.getName());

        // The ParsedDeployment represents the deployment, the process definitions, and the BPMN
        // resource, parse, and model associated with each process definition.
        ParsedDeployment parsedDeployment = parsedDeploymentBuilderFactory
                .getBuilderForDeploymentAndSettings(deployment,
                                                    deploymentSettings)
                .build();

        bpmnDeploymentHelper.verifyProcessDefinitionsDoNotShareKeys(parsedDeployment.getAllProcessDefinitions());

        bpmnDeploymentHelper.copyDeploymentValuesToProcessDefinitions(
                parsedDeployment.getDeployment(),
                parsedDeployment.getAllProcessDefinitions());
        bpmnDeploymentHelper.setResourceNamesOnProcessDefinitions(parsedDeployment);

//    createAndPersistNewDiagramsIfNeeded(parsedDeployment);
        setProcessDefinitionDiagramNames(parsedDeployment);

        if (deployment.isNew()) {
            Map mapOfNewProcessDefinitionToPreviousVersion =
                    getPreviousVersionsOfProcessDefinitions(parsedDeployment);
            setProcessDefinitionVersionsAndIds(parsedDeployment,
                                               mapOfNewProcessDefinitionToPreviousVersion);
            persistProcessDefinitionsAndAuthorizations(parsedDeployment);
            updateTimersAndEvents(parsedDeployment,
                                  mapOfNewProcessDefinitionToPreviousVersion);
            dispatchProcessDefinitionEntityInitializedEvent(parsedDeployment);
        } else {
            makeProcessDefinitionsConsistentWithPersistedVersions(parsedDeployment);
        }

        cachingAndArtifactsManager.updateCachingAndArtifacts(parsedDeployment);

        for (ProcessDefinitionEntity processDefinition : parsedDeployment.getAllProcessDefinitions()) {
            BpmnModel bpmnModel = parsedDeployment.getBpmnModelForProcessDefinition(processDefinition);
            createLocalizationValues(processDefinition.getId(),
                                     bpmnModel.getProcessById(processDefinition.getKey()));
        }
    }
//
//  /**
//   * Creates new diagrams for process definitions if the deployment is new, the process definition in
//   * question supports it, and the engine is configured to make new diagrams.
//   *
//   * When this method creates a new diagram, it also persists it via the ResourceEntityManager
//   * and adds it to the resources of the deployment.
//   */
//  protected void createAndPersistNewDiagramsIfNeeded(ParsedDeployment parsedDeployment) {
//
//    final ProcessEngineConfigurationImpl processEngineConfiguration = Context.getProcessEngineConfiguration();
//    final DeploymentEntity deploymentEntity = parsedDeployment.getDeployment();
//
//    final ResourceEntityManager resourceEntityManager = processEngineConfiguration.getResourceEntityManager();
//
//    for (ProcessDefinitionEntity processDefinition : parsedDeployment.getAllProcessDefinitions()) {
//      if (processDefinitionDiagramHelper.shouldCreateDiagram(processDefinition, deploymentEntity)) {
//        ResourceEntity resource = processDefinitionDiagramHelper.createDiagramForProcessDefinition(
//            processDefinition, parsedDeployment.getBpmnParseForProcessDefinition(processDefinition));
//        if (resource != null) {
//          resourceEntityManager.insert(resource, false);
//          deploymentEntity.addResource(resource);  // now we'll find it if we look for the diagram name later.
//        }
//      }
//    }
//  }

    /**
     * Updates all the process definition entities to have the correct diagram resource name.  Must
     * be called after createAndPersistNewDiagramsAsNeeded to ensure that any newly-created diagrams
     * already have their resources attached to the deployment.
     */
    protected void setProcessDefinitionDiagramNames(ParsedDeployment parsedDeployment) {
        Map resources = parsedDeployment.getDeployment().getResources();

        for (ProcessDefinitionEntity processDefinition : parsedDeployment.getAllProcessDefinitions()) {
            String diagramResourceName = ResourceNameUtil.getProcessDiagramResourceNameFromDeployment(processDefinition,
                                                                                                      resources);
            processDefinition.setDiagramResourceName(diagramResourceName);
        }
    }

    /**
     * Constructs a map from new ProcessDefinitionEntities to the previous version by key and tenant.
     * If no previous version exists, no map entry is created.
     */
    protected Map getPreviousVersionsOfProcessDefinitions(
            ParsedDeployment parsedDeployment) {

        Map result = new LinkedHashMap();

        for (ProcessDefinitionEntity newDefinition : parsedDeployment.getAllProcessDefinitions()) {
            ProcessDefinitionEntity existingDefinition = bpmnDeploymentHelper.getMostRecentVersionOfProcessDefinition(newDefinition);

            if (existingDefinition != null) {
                result.put(newDefinition,
                           existingDefinition);
            }
        }

        return result;
    }

    /**
     * Sets the version on each process definition entity, and the identifier.  If the map contains
     * an older version for a process definition, then the version is set to that older entity's
     * version plus one; otherwise it is set to 1.  Also dispatches an ENTITY_CREATED event.
     */
    protected void setProcessDefinitionVersionsAndIds(ParsedDeployment parsedDeployment,
                                                      Map mapNewToOldProcessDefinitions) {
        CommandContext commandContext = Context.getCommandContext();

        for (ProcessDefinitionEntity processDefinition : parsedDeployment.getAllProcessDefinitions()) {
            int version = 1;

            ProcessDefinitionEntity latest = mapNewToOldProcessDefinitions.get(processDefinition);
            if (latest != null) {
                version = latest.getVersion() + 1;
            }

            processDefinition.setVersion(version);
            processDefinition.setId(getIdForNewProcessDefinition(processDefinition));

            if (commandContext.getProcessEngineConfiguration().getEventDispatcher().isEnabled()) {
                commandContext.getProcessEngineConfiguration().getEventDispatcher().dispatchEvent(ActivitiEventBuilder.createEntityEvent(ActivitiEventType.ENTITY_CREATED,
                                                                                                                                         processDefinition));
            }
        }
    }

    /**
     * Saves each process definition.  It is assumed that the deployment is new, the definitions
     * have never been saved before, and that they have all their values properly set up.
     */
    protected void persistProcessDefinitionsAndAuthorizations(ParsedDeployment parsedDeployment) {
        CommandContext commandContext = Context.getCommandContext();
        ProcessDefinitionEntityManager processDefinitionManager = commandContext.getProcessDefinitionEntityManager();

        for (ProcessDefinitionEntity processDefinition : parsedDeployment.getAllProcessDefinitions()) {
            processDefinitionManager.insert(processDefinition,
                                            false);
            bpmnDeploymentHelper.addAuthorizationsForNewProcessDefinition(parsedDeployment.getProcessModelForProcessDefinition(processDefinition),
                                                                          processDefinition);
        }
    }

    protected void updateTimersAndEvents(ParsedDeployment parsedDeployment,
                                         Map mapNewToOldProcessDefinitions) {

        for (ProcessDefinitionEntity processDefinition : parsedDeployment.getAllProcessDefinitions()) {
            bpmnDeploymentHelper.updateTimersAndEvents(processDefinition,
                                                       mapNewToOldProcessDefinitions.get(processDefinition),
                                                       parsedDeployment);
        }
    }

    protected void dispatchProcessDefinitionEntityInitializedEvent(ParsedDeployment parsedDeployment) {
        CommandContext commandContext = Context.getCommandContext();
        for (ProcessDefinitionEntity processDefinitionEntity : parsedDeployment.getAllProcessDefinitions()) {
            if (commandContext.getProcessEngineConfiguration().getEventDispatcher().isEnabled()) {
                commandContext.getProcessEngineConfiguration().getEventDispatcher().dispatchEvent(
                        ActivitiEventBuilder.createEntityEvent(ActivitiEventType.ENTITY_INITIALIZED,
                                                               processDefinitionEntity));
            }
        }
    }

    /**
     * Returns the ID to use for a new process definition; subclasses may override this to provide
     * their own identification scheme.
     * 

* Process definition ids NEED to be unique accross the whole engine! */ protected String getIdForNewProcessDefinition(ProcessDefinitionEntity processDefinition) { String nextId = idGenerator.getNextId(); String result = processDefinition.getKey() + ":" + processDefinition.getVersion() + ":" + nextId; // ACT-505 // ACT-115: maximum id length is 64 characters if (result.length() > 64) { result = nextId; } return result; } /** * Loads the persisted version of each process definition and set values on the in-memory * version to be consistent. */ protected void makeProcessDefinitionsConsistentWithPersistedVersions(ParsedDeployment parsedDeployment) { for (ProcessDefinitionEntity processDefinition : parsedDeployment.getAllProcessDefinitions()) { ProcessDefinitionEntity persistedProcessDefinition = bpmnDeploymentHelper.getPersistedInstanceOfProcessDefinition(processDefinition); if (persistedProcessDefinition != null) { processDefinition.setId(persistedProcessDefinition.getId()); processDefinition.setVersion(persistedProcessDefinition.getVersion()); processDefinition.setSuspensionState(persistedProcessDefinition.getSuspensionState()); } } } protected void createLocalizationValues(String processDefinitionId, Process process) { if (process == null) { return; } CommandContext commandContext = Context.getCommandContext(); DynamicBpmnService dynamicBpmnService = commandContext.getProcessEngineConfiguration().getDynamicBpmnService(); ObjectNode infoNode = dynamicBpmnService.getProcessDefinitionInfo(processDefinitionId); boolean localizationValuesChanged = false; List localizationElements = process.getExtensionElements().get("localization"); if (localizationElements != null) { for (ExtensionElement localizationElement : localizationElements) { if (BpmnXMLConstants.ACTIVITI_EXTENSIONS_PREFIX.equals(localizationElement.getNamespacePrefix())) { String locale = localizationElement.getAttributeValue(null, "locale"); String name = localizationElement.getAttributeValue(null, "name"); String documentation = null; List documentationElements = localizationElement.getChildElements().get("documentation"); if (documentationElements != null) { for (ExtensionElement documentationElement : documentationElements) { documentation = StringUtils.trimToNull(documentationElement.getElementText()); break; } } String processId = process.getId(); if (!isEqualToCurrentLocalizationValue(locale, processId, "name", name, infoNode)) { dynamicBpmnService.changeLocalizationName(locale, processId, name, infoNode); localizationValuesChanged = true; } if (documentation != null && !isEqualToCurrentLocalizationValue(locale, processId, "description", documentation, infoNode)) { dynamicBpmnService.changeLocalizationDescription(locale, processId, documentation, infoNode); localizationValuesChanged = true; } break; } } } boolean isFlowElementLocalizationChanged = localizeFlowElements(process.getFlowElements(), infoNode); boolean isDataObjectLocalizationChanged = localizeDataObjectElements(process.getDataObjects(), infoNode); if (isFlowElementLocalizationChanged || isDataObjectLocalizationChanged) { localizationValuesChanged = true; } if (localizationValuesChanged) { dynamicBpmnService.saveProcessDefinitionInfo(processDefinitionId, infoNode); } } protected boolean localizeFlowElements(Collection flowElements, ObjectNode infoNode) { boolean localizationValuesChanged = false; if (flowElements == null) { return localizationValuesChanged; } CommandContext commandContext = Context.getCommandContext(); DynamicBpmnService dynamicBpmnService = commandContext.getProcessEngineConfiguration().getDynamicBpmnService(); for (FlowElement flowElement : flowElements) { if (flowElement instanceof UserTask || flowElement instanceof SubProcess) { List localizationElements = flowElement.getExtensionElements().get("localization"); if (localizationElements != null) { for (ExtensionElement localizationElement : localizationElements) { if (BpmnXMLConstants.ACTIVITI_EXTENSIONS_PREFIX.equals(localizationElement.getNamespacePrefix())) { String locale = localizationElement.getAttributeValue(null, "locale"); String name = localizationElement.getAttributeValue(null, "name"); String documentation = null; List documentationElements = localizationElement.getChildElements().get("documentation"); if (documentationElements != null) { for (ExtensionElement documentationElement : documentationElements) { documentation = StringUtils.trimToNull(documentationElement.getElementText()); break; } } String flowElementId = flowElement.getId(); if (isEqualToCurrentLocalizationValue(locale, flowElementId, "name", name, infoNode) == false) { dynamicBpmnService.changeLocalizationName(locale, flowElementId, name, infoNode); localizationValuesChanged = true; } if (documentation != null && isEqualToCurrentLocalizationValue(locale, flowElementId, "description", documentation, infoNode) == false) { dynamicBpmnService.changeLocalizationDescription(locale, flowElementId, documentation, infoNode); localizationValuesChanged = true; } break; } } } if (flowElement instanceof SubProcess) { SubProcess subprocess = (SubProcess) flowElement; boolean isFlowElementLocalizationChanged = localizeFlowElements(subprocess.getFlowElements(), infoNode); boolean isDataObjectLocalizationChanged = localizeDataObjectElements(subprocess.getDataObjects(), infoNode); if (isFlowElementLocalizationChanged || isDataObjectLocalizationChanged) { localizationValuesChanged = true; } } } } return localizationValuesChanged; } protected boolean isEqualToCurrentLocalizationValue(String language, String id, String propertyName, String propertyValue, ObjectNode infoNode) { boolean isEqual = false; JsonNode localizationNode = infoNode.path("localization").path(language).path(id).path(propertyName); if (!localizationNode.isMissingNode() && !localizationNode.isNull() && localizationNode.asText().equals(propertyValue)) { isEqual = true; } return isEqual; } protected boolean localizeDataObjectElements(List dataObjects, ObjectNode infoNode) { boolean localizationValuesChanged = false; CommandContext commandContext = Context.getCommandContext(); DynamicBpmnService dynamicBpmnService = commandContext.getProcessEngineConfiguration().getDynamicBpmnService(); for (ValuedDataObject dataObject : dataObjects) { List localizationElements = dataObject.getExtensionElements().get("localization"); if (localizationElements != null) { for (ExtensionElement localizationElement : localizationElements) { if (BpmnXMLConstants.ACTIVITI_EXTENSIONS_PREFIX.equals(localizationElement.getNamespacePrefix())) { String locale = localizationElement.getAttributeValue(null, "locale"); String name = localizationElement.getAttributeValue(null, "name"); String documentation = null; List documentationElements = localizationElement.getChildElements().get("documentation"); if (documentationElements != null) { for (ExtensionElement documentationElement : documentationElements) { documentation = StringUtils.trimToNull(documentationElement.getElementText()); break; } } if (name != null && isEqualToCurrentLocalizationValue(locale, dataObject.getId(), DynamicBpmnConstants.LOCALIZATION_NAME, name, infoNode) == false) { dynamicBpmnService.changeLocalizationName(locale, dataObject.getId(), name, infoNode); localizationValuesChanged = true; } if (documentation != null && isEqualToCurrentLocalizationValue(locale, dataObject.getId(), DynamicBpmnConstants.LOCALIZATION_DESCRIPTION, documentation, infoNode) == false) { dynamicBpmnService.changeLocalizationDescription(locale, dataObject.getId(), documentation, infoNode); localizationValuesChanged = true; } } } } } return localizationValuesChanged; } public IdGenerator getIdGenerator() { return idGenerator; } public void setIdGenerator(IdGenerator idGenerator) { this.idGenerator = idGenerator; } public ParsedDeploymentBuilderFactory getExParsedDeploymentBuilderFactory() { return parsedDeploymentBuilderFactory; } public void setParsedDeploymentBuilderFactory(ParsedDeploymentBuilderFactory parsedDeploymentBuilderFactory) { this.parsedDeploymentBuilderFactory = parsedDeploymentBuilderFactory; } public BpmnDeploymentHelper getBpmnDeploymentHelper() { return bpmnDeploymentHelper; } public void setBpmnDeploymentHelper(BpmnDeploymentHelper bpmnDeploymentHelper) { this.bpmnDeploymentHelper = bpmnDeploymentHelper; } public CachingAndArtifactsManager getCachingAndArtifcatsManager() { return cachingAndArtifactsManager; } public void setCachingAndArtifactsManager(CachingAndArtifactsManager manager) { this.cachingAndArtifactsManager = manager; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy