<commit_before>/* 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.flowable.engine.impl.bpmn.behavior;

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

import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.DataAssociation;
import org.flowable.bpmn.model.DataSpec;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.bpmn.model.IOSpecification;
import org.flowable.bpmn.model.Import;
import org.flowable.bpmn.model.Interface;
import org.flowable.bpmn.model.Message;
import org.flowable.bpmn.model.SendTask;
import org.flowable.bpmn.model.ServiceTask;
import org.flowable.engine.common.api.FlowableException;
import org.flowable.engine.common.api.delegate.Expression;
import org.flowable.engine.common.impl.el.ExpressionManager;
import org.flowable.engine.common.impl.util.ReflectUtil;
import org.flowable.engine.delegate.BpmnError;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.impl.bpmn.data.AbstractDataAssociation;
import org.flowable.engine.impl.bpmn.data.Assignment;
import org.flowable.engine.impl.bpmn.data.ClassStructureDefinition;
import org.flowable.engine.impl.bpmn.data.ItemDefinition;
import org.flowable.engine.impl.bpmn.data.ItemInstance;
import org.flowable.engine.impl.bpmn.data.ItemKind;
import org.flowable.engine.impl.bpmn.data.SimpleDataInputAssociation;
import org.flowable.engine.impl.bpmn.data.StructureDefinition;
import org.flowable.engine.impl.bpmn.data.TransformationDataOutputAssociation;
import org.flowable.engine.impl.bpmn.helper.ErrorPropagation;
import org.flowable.engine.impl.bpmn.parser.XMLImporter;
import org.flowable.engine.impl.bpmn.webservice.BpmnInterface;
import org.flowable.engine.impl.bpmn.webservice.MessageDefinition;
import org.flowable.engine.impl.bpmn.webservice.MessageImplicitDataInputAssociation;
import org.flowable.engine.impl.bpmn.webservice.MessageImplicitDataOutputAssociation;
import org.flowable.engine.impl.bpmn.webservice.MessageInstance;
import org.flowable.engine.impl.bpmn.webservice.Operation;
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.engine.impl.util.ProcessDefinitionUtil;
import org.flowable.engine.impl.webservice.WSOperation;
import org.flowable.engine.impl.webservice.WSService;

/**
 * An activity behavior that allows calling Web services
 * 
 * @author <NAME>
 * @author <NAME>
 * @author <NAME>
 */
public class WebServiceActivityBehavior extends AbstractBpmnActivityBehavior {

    private static final long serialVersionUID = 1L;

    public static final String CURRENT_MESSAGE = "org.flowable.engine.impl.bpmn.CURRENT_MESSAGE";

    protected Map<String, XMLImporter> xmlImporterMap = new HashMap<>();
    protected Map<String, WSOperation> wsOperationMap = new HashMap<>();
    protected Map<String, StructureDefinition> structureDefinitionMap = new HashMap<>();
    protected Map<String, WSService> wsServiceMap = new HashMap<>();
    protected Map<String, Operation> operationMap = new HashMap<>();
    protected Map<String, ItemDefinition> itemDefinitionMap = new HashMap<>();
    protected Map<String, MessageDefinition> messageDefinitionMap = new HashMap<>();

    public WebServiceActivityBehavior(BpmnModel bpmnModel) {
        itemDefinitionMap.put("http://www.w3.org/2001/XMLSchema:string", new ItemDefinition("http://www.w3.org/2001/XMLSchema:string", new ClassStructureDefinition(String.class)));
    }

    @Override
    public void execute(DelegateExecution execution) {
        BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(execution.getProcessDefinitionId());
        FlowElement flowElement = execution.getCurrentFlowElement();

        IOSpecification ioSpecification = null;
        String operationRef = null;
        List<DataAssociation> dataInputAssociations = null;
        List<DataAssociation> dataOutputAssociations = null;

        if (flowElement instanceof SendTask) {
            SendTask sendTask = (SendTask) flowElement;
            ioSpecification = sendTask.getIoSpecification();
            operationRef = sendTask.getOperationRef();
            dataInputAssociations = sendTask.getDataInputAssociations();
            dataOutputAssociations = sendTask.getDataOutputAssociations();

        } else if (flowElement instanceof ServiceTask) {
            ServiceTask serviceTask = (ServiceTask) flowElement;
            ioSpecification = serviceTask.getIoSpecification();
            operationRef = serviceTask.getOperationRef();
            dataInputAssociations = serviceTask.getDataInputAssociations();
            dataOutputAssociations = serviceTask.getDataOutputAssociations();

        } else {
            throw new FlowableException("Unsupported flow element type " + flowElement);
        }

        MessageInstance message = null;

        fillDefinitionMaps(bpmnModel);

        Operation operation = operationMap.get(operationRef);

        try {

            if (ioSpecification != null) {
                initializeIoSpecification(ioSpecification, execution, bpmnModel);
                if (ioSpecification.getDataInputRefs().size() > 0) {
                    String firstDataInputName = ioSpecification.getDataInputRefs().get(0);
                    ItemInstance inputItem = (ItemInstance) execution.getVariable(firstDataInputName);
                    message = new MessageInstance(operation.getInMessage(), inputItem);
                }

            } else {
                message = operation.getInMessage().createInstance();
            }

            execution.setVariable(CURRENT_MESSAGE, message);

            fillMessage(dataInputAssociations, execution);

            ProcessEngineConfigurationImpl processEngineConfig = CommandContextUtil.getProcessEngineConfiguration();
            MessageInstance receivedMessage = operation.sendMessage(message,
                    processEngineConfig.getWsOverridenEndpointAddresses());

            execution.setVariable(CURRENT_MESSAGE, receivedMessage);

            if (ioSpecification != null && ioSpecification.getDataOutputRefs().size() > 0) {
                String firstDataOutputName = ioSpecification.getDataOutputRefs().get(0);
                if (firstDataOutputName != null) {<commit_msg>Rework fix of issue 622 (Optimize service task execution) according to Tijs comments (#627)<commit_after>/* 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.flowable.engine.impl.bpmn.behavior;

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

import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.DataAssociation;
import org.flowable.bpmn.model.DataSpec;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.bpmn.model.IOSpecification;
import org.flowable.bpmn.model.Import;
import org.flowable.bpmn.model.Interface;
import org.flowable.bpmn.model.Message;
import org.flowable.bpmn.model.SendTask;
import org.flowable.bpmn.model.ServiceTask;
import org.flowable.engine.common.api.FlowableException;
import org.flowable.engine.common.api.delegate.Expression;
import org.flowable.engine.common.impl.el.ExpressionManager;
import org.flowable.engine.common.impl.util.ReflectUtil;
import org.flowable.engine.delegate.BpmnError;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.impl.bpmn.data.AbstractDataAssociation;
import org.flowable.engine.impl.bpmn.data.Assignment;
import org.flowable.engine.impl.bpmn.data.ClassStructureDefinition;
import org.flowable.engine.impl.bpmn.data.ItemDefinition;
import org.flowable.engine.impl.bpmn.data.ItemInstance;
import org.flowable.engine.impl.bpmn.data.ItemKind;
import org.flowable.engine.impl.bpmn.data.SimpleDataInputAssociation;
import org.flowable.engine.impl.bpmn.data.StructureDefinition;
import org.flowable.engine.impl.bpmn.data.TransformationDataOutputAssociation;
import org.flowable.engine.impl.bpmn.helper.ErrorPropagation;
import org.flowable.engine.impl.bpmn.parser.XMLImporter;
import org.flowable.engine.impl.bpmn.webservice.BpmnInterface;
import org.flowable.engine.impl.bpmn.webservice.MessageDefinition;
import org.flowable.engine.impl.bpmn.webservice.MessageImplicitDataInputAssociation;
import org.flowable.engine.impl.bpmn.webservice.MessageImplicitDataOutputAssociation;
import org.flowable.engine.impl.bpmn.webservice.MessageInstance;
import org.flowable.engine.impl.bpmn.webservice.Operation;
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.engine.impl.util.ProcessDefinitionUtil;
import org.flowable.engine.impl.webservice.WSOperation;
import org.flowable.engine.impl.webservice.WSService;

/**
 * An activity behavior that allows calling Web services
 * 
 * @author <NAME>
 * @author <NAME>
 * @author <NAME>
 */
public class WebServiceActivityBehavior extends AbstractBpmnActivityBehavior {

    private static final long serialVersionUID = 1L;

    public static final String CURRENT_MESSAGE = "org.flowable.engine.impl.bpmn.CURRENT_MESSAGE";

    protected Map<String, XMLImporter> xmlImporterMap = new HashMap<>();
    protected Map<String, WSOperation> wsOperationMap = new HashMap<>();
    protected Map<String, StructureDefinition> structureDefinitionMap = new HashMap<>();
    protected Map<String, WSService> wsServiceMap = new HashMap<>();
    protected Map<String, Operation> operationMap = new HashMap<>();
    protected Map<String, ItemDefinition> itemDefinitionMap = new HashMap<>();
    protected Map<String, MessageDefinition> messageDefinitionMap = new HashMap<>();

    public WebServiceActivityBehavior(BpmnModel bpmnModel) {
        itemDefinitionMap.put("http://www.w3.org/2001/XMLSchema:string", new ItemDefinition("http://www.w3.org/2001/XMLSchema:string", new ClassStructureDefinition(String.class)));
        fillDefinitionMaps(bpmnModel);
    }

    @Override
    public void execute(DelegateExecution execution) {
        BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(execution.getProcessDefinitionId());
        FlowElement flowElement = execution.getCurrentFlowElement();

        IOSpecification ioSpecification = null;
        String operationRef = null;
        List<DataAssociation> dataInputAssociations = null;
        List<DataAssociation> dataOutputAssociations = null;

        if (flowElement instanceof SendTask) {
            SendTask sendTask = (SendTask) flowElement;
            ioSpecification = sendTask.getIoSpecification();
            operationRef = sendTask.getOperationRef();
            dataInputAssociations = sendTask.getDataInputAssociations();
            dataOutputAssociations = sendTask.getDataOutputAssociations();

        } else if (flowElement instanceof ServiceTask) {
            ServiceTask serviceTask = (ServiceTask) flowElement;
            ioSpecification = serviceTask.getIoSpecification();
            operationRef = serviceTask.getOperationRef();
            dataInputAssociations = serviceTask.getDataInputAssociations();
            dataOutputAssociations = serviceTask.getDataOutputAssociations();

        } else {
            throw new FlowableException("Unsupported flow element type " + flowElement);
        }

        MessageInstance message = null;

        Operation operation = operationMap.get(operationRef);

        try {

            if (ioSpecification != null) {
                initializeIoSpecification(ioSpecification, execution, bpmnModel);
                if (ioSpecification.getDataInputRefs().size() > 0) {
                    String firstDataInputName = ioSpecification.getDataInputRefs().get(0);
                    ItemInstance inputItem = (ItemInstance) execution.getVariable(firstDataInputName);
                    message = new MessageInstance(operation.getInMessage(), inputItem);
                }

            } else {
                message = operation.getInMessage().createInstance();
            }

            execution.setVariable(CURRENT_MESSAGE, message);

            fillMessage(dataInputAssociations, execution);

            ProcessEngineConfigurationImpl processEngineConfig = CommandContextUtil.getProcessEngineConfiguration();
            MessageInstance receivedMessage = operation.sendMessage(message,
                    processEngineConfig.getWsOverridenEndpointAddresses());

            execution.setVariable(CURRENT_MESSAGE, receivedMessage);

            if (ioSpecification != null && ioSpecification.getDataOutputRefs().size() > 0) {
                String firstDataOutputName = ioSpecification.getDataOutputRefs().get(0);
                if (firstDataOutputName != null) {
{'fraction_non_alphanumeric': 0.09320374265612534, 'fraction_numerical': 0.0033364763908029305, 'mean_word_length': 4.059816513761468, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 6, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6005577', 'n_tokens_mistral': 3753, 'n_tokens_neox': 3661, 'n_words': 743}