Skip to content

Commit

Permalink
Merge pull request Activiti#2817 from Activiti/dev-miguelruiz-ACTIVIT…
Browse files Browse the repository at this point in the history
…I-3310-variable-mapping-logic

Activiti-3310 Variable Mapping Logic
  • Loading branch information
miguelruizdev authored Jul 19, 2019
2 parents eb8f6e0 + 64e4af2 commit 12e8825
Show file tree
Hide file tree
Showing 42 changed files with 2,437 additions and 68 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/* 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.runtime.api.impl;

import java.util.List;

import org.activiti.bpmn.model.MapExceptionEntry;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.delegate.Expression;
import org.activiti.engine.impl.bpmn.behavior.CallActivityBehavior;
import org.activiti.engine.impl.bpmn.behavior.UserTaskActivityBehavior;
import org.activiti.engine.impl.bpmn.parser.factory.ActivityBehaviorFactory;
import org.activiti.engine.impl.bpmn.parser.factory.DefaultActivityBehaviorFactory;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.spring.process.ProcessVariablesInitiator;

/**
* Default implementation of the {@link ActivityBehaviorFactory}. Used when no custom {@link ActivityBehaviorFactory} is injected on the {@link ProcessEngineConfigurationImpl}.
*/
public class MappingAwareActivityBehaviorFactory extends DefaultActivityBehaviorFactory {

private VariablesMappingProvider variablesMappingProvider;

private ProcessVariablesInitiator processVariablesInitiator;

public MappingAwareActivityBehaviorFactory(VariablesMappingProvider variablesMappingProvider,
ProcessVariablesInitiator processVariablesInitiator) {
super();
this.variablesMappingProvider = variablesMappingProvider;
this.processVariablesInitiator = processVariablesInitiator;
}

@Override
public UserTaskActivityBehavior createUserTaskActivityBehavior(UserTask userTask) {
return new MappingAwareUserTaskBehavior(userTask,
variablesMappingProvider);
}

@Override
protected CallActivityBehavior createCallActivityBehavior(Expression expression, List<MapExceptionEntry> mapExceptions) {
return new MappingAwareCallActivityBehavior(expression,
mapExceptions,
variablesMappingProvider,
processVariablesInitiator);
}

@Override
protected CallActivityBehavior createCallActivityBehavior(String calledElement,
List<MapExceptionEntry> mapExceptions) {
return new MappingAwareCallActivityBehavior(calledElement,
mapExceptions,
variablesMappingProvider,
processVariablesInitiator);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright 2018 Alfresco, Inc. and/or its affiliates.
*
* 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.runtime.api.impl;

import java.util.List;
import java.util.Map;

import org.activiti.bpmn.model.MapExceptionEntry;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.Expression;
import org.activiti.engine.impl.bpmn.behavior.CallActivityBehavior;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.spring.process.ProcessVariablesInitiator;

public class MappingAwareCallActivityBehavior extends CallActivityBehavior {

private VariablesMappingProvider mappingProvider;
private ProcessVariablesInitiator processVariablesInitiator;

public MappingAwareCallActivityBehavior(String processDefinitionKey,
List<MapExceptionEntry> mapExceptions,
VariablesMappingProvider mappingProvider,
ProcessVariablesInitiator processVariablesInitiator) {
super(processDefinitionKey,
mapExceptions);
this.mappingProvider = mappingProvider;
this.processVariablesInitiator = processVariablesInitiator;
}

public MappingAwareCallActivityBehavior(Expression processDefinitionExpression,
List<MapExceptionEntry> mapExceptions,
VariablesMappingProvider mappingProvider,
ProcessVariablesInitiator processVariablesInitiator) {
super(processDefinitionExpression,
mapExceptions);
this.mappingProvider = mappingProvider;
this.processVariablesInitiator = processVariablesInitiator;
}

@Override
protected Map<String, Object> calculateInboundVariables(DelegateExecution execution,
ProcessDefinition processDefinition) {

Map<String, Object> inputVariables = mappingProvider.calculateInputVariables(execution);
return processVariablesInitiator.calculateVariablesFromExtensionFile(processDefinition,
inputVariables);
}

@Override
protected Map<String, Object> calculateOutBoundVariables(DelegateExecution execution,
Map<String, Object> availableVariables) {

return mappingProvider.calculateOutPutVariables(execution,
availableVariables);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright 2018 Alfresco, Inc. and/or its affiliates.
*
* 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.runtime.api.impl;

import java.util.Map;

import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.impl.bpmn.behavior.UserTaskActivityBehavior;

public class MappingAwareUserTaskBehavior extends UserTaskActivityBehavior {

private VariablesMappingProvider mappingProvider;

public MappingAwareUserTaskBehavior(UserTask userTask,
VariablesMappingProvider mappingProvider) {
super(userTask);
this.mappingProvider = mappingProvider;
}


@Override
protected Map<String, Object> calculateInputVariables(DelegateExecution execution) {
return mappingProvider.calculateInputVariables(execution);
}

@Override
protected Map<String, Object> calculateOutBoundVariables(DelegateExecution execution,
Map<String, Object> taskCompleteVariables) {

return mappingProvider.calculateOutPutVariables(execution,
taskCompleteVariables);
}



}
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/*
* Copyright 2019 Alfresco, Inc. and/or its affiliates.
*
* 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.runtime.api.impl;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.spring.process.ProcessExtensionService;
import org.activiti.spring.process.model.Mapping;
import org.activiti.spring.process.model.ProcessExtensionModel;
import org.activiti.spring.process.model.ProcessVariablesMapping;
import org.activiti.spring.process.model.VariableDefinition;

public class VariablesMappingProvider {

private ProcessExtensionService processExtensionService;

public VariablesMappingProvider(ProcessExtensionService processExtensionService) {
this.processExtensionService = processExtensionService;
}

protected Optional<Object> calculateMappedValue(Mapping inputMapping,
DelegateExecution execution,
ProcessExtensionModel extensions) {
if (inputMapping != null) {
if (Mapping.SourceMappingType.VALUE.equals(inputMapping.getType()) || Mapping.SourceMappingType.STATIC_VALUE.equals(inputMapping.getType())) {
return Optional.of(inputMapping.getValue());
}

if (Mapping.SourceMappingType.VARIABLE.equals(inputMapping.getType())) {
String name = inputMapping.getValue().toString();

VariableDefinition processVariableDefinition = extensions.getExtensions().getPropertyByName(name);
if (processVariableDefinition != null) {
return Optional.of(execution.getVariable(processVariableDefinition.getName()));
}
}
}
return Optional.empty();
}

public Map<String, Object> calculateInputVariables(DelegateExecution execution) {

ProcessExtensionModel extensions = processExtensionService.getExtensionsForId(execution.getProcessDefinitionId());

if(extensions.getExtensions().hasEmptyInputsMapping(execution.getCurrentActivityId())){
return Collections.emptyMap();
}

if(extensions.getExtensions().hasNoMapping(execution.getCurrentActivityId())){
return new HashMap<>(execution.getVariables());
}

return calculateInputVariables(execution, extensions);
}

protected Map<String, Object> calculateInputVariables(DelegateExecution execution,
ProcessExtensionModel extensions) {
Map<String, Object> inboundVariables = new HashMap<>();

ProcessVariablesMapping processVariablesMapping = extensions.getExtensions().getMappingForFlowElement(execution.getCurrentActivityId());
Map<String, Mapping> inputMappings = processVariablesMapping.getInputs();

for (Map.Entry<String, Mapping> mapping : inputMappings.entrySet()) {
Optional<Object> mappedValue = calculateMappedValue(mapping.getValue(),
execution,
extensions);
mappedValue.ifPresent(value -> inboundVariables.put(mapping.getKey(),
value));
}

return inboundVariables;
}

protected Optional<Object> calculateOutPutMappedValue(Mapping mapping,
Map<String, Object> currentContextVariables) {
if (mapping != null) {
if (Mapping.SourceMappingType.VALUE.equals(mapping.getType())) {
return Optional.of(mapping.getValue());
} else {
if (Mapping.SourceMappingType.VARIABLE.equals(mapping.getType())) {
String name = mapping.getValue().toString();

return currentContextVariables != null ?
Optional.of(currentContextVariables.get(name)) :
Optional.empty();
}
}
}
return Optional.empty();
}

public Map<String, Object> calculateOutPutVariables(DelegateExecution execution,
Map<String, Object> availableVariables) {

ProcessExtensionModel extensions = processExtensionService.getExtensionsForId(execution.getProcessDefinitionId());

if(extensions.getExtensions().hasEmptyOutputsMapping(execution.getCurrentActivityId())){
return Collections.emptyMap();
}

if(extensions.getExtensions().hasNoMapping(execution.getCurrentActivityId())){
return new HashMap<>(availableVariables);
}

if (!availableVariables.isEmpty()) {
return calculateOutPutVariables(execution, extensions, availableVariables);
}else{
return Collections.emptyMap();
}
}

private Map<String, Object> calculateOutPutVariables(DelegateExecution execution,
ProcessExtensionModel extensions,
Map<String, Object> availableVariables){
Map<String, Object> outboundVariables = new HashMap<>();
ProcessVariablesMapping processVariablesMapping = extensions.getExtensions().getMappingForFlowElement(execution.getCurrentActivityId());
Map<String, Mapping> outputMappings = processVariablesMapping.getOutputs();

for (Map.Entry<String, Mapping> mapping : outputMappings.entrySet()) {

String name = mapping.getKey();

VariableDefinition processVariableDefinition = extensions.getExtensions().getPropertyByName(name);

if (processVariableDefinition != null && calculateOutPutMappedValue(mapping.getValue(),
availableVariables).isPresent()) {
outboundVariables.put(name, calculateOutPutMappedValue(mapping.getValue(),
availableVariables).get());
}
}

return outboundVariables;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.activiti.runtime.api.connector.InboundVariablesProvider;
import org.activiti.runtime.api.connector.IntegrationContextBuilder;
import org.activiti.runtime.api.connector.OutboundVariablesProvider;
import org.activiti.runtime.api.impl.VariablesMappingProvider;
import org.activiti.spring.process.ProcessExtensionService;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.ApplicationContext;
Expand Down Expand Up @@ -63,4 +64,10 @@ public OutboundVariablesProvider outboundVariablesProvider(ConnectorActionDefini
public ConnectorActionDefinitionFinder connectorActionDefinitionFinder(List<ConnectorDefinition> connectorDefinitions) {
return new ConnectorActionDefinitionFinder(connectorDefinitions);
}


@Bean
public VariablesMappingProvider variablesMappingProvider(ProcessExtensionService processExtensionService){
return new VariablesMappingProvider(processExtensionService);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"id":"taskVariableEmptyMapping",
"extensions": {
"properties": {
"process-variable-unmapped-1-id": {
"id": "process-variable-unmapped-1-id",
"name": "process_variable_unmapped_1",
"type": "string",
"required": true,
"value": "unmapped1Value"
},
"process-variable-inputmap-1-id": {
"id": "process-variable-inputmap-1-id",
"name": "process_variable_inputmap_1",
"type": "string",
"required": true,
"value": "inputmap1Value"
},
"process-variable-outputmap-1-id": {
"id": "process-variable-outputmap-1-id",
"name": "process_variable_outputmap_1",
"type": "string",
"required": true,
"value": "outputmap1Value"
}
},
"mappings": {
"simpleTask": {
"inputs": {},
"outputs": {}
}
}
}
}
Loading

0 comments on commit 12e8825

Please sign in to comment.