snippets/migrate-third-party-to-camunda/src/main/java/com/camunda/demo/migration/MigrationEnabledCallActivityBehavior.java
@Override
  public void execute(ActivityExecution execution) throws Exception {
    String processDefinitionKey = this.processDefinitionKey;
    String binding = this.binding;
    Integer version = this.version;
    if (copy_processDefinitionExpression != null) {
      processDefinitionKey = (String) copy_processDefinitionExpression.getValue(execution);
    }

    ProcessDefinitionEntity processDefinition = null;
    if (binding == null || CalledElementBinding.LATEST.getValue().equals(binding)) {
      processDefinition = Context.getProcessEngineConfiguration().getDeploymentCache().findDeployedLatestProcessDefinitionByKey(processDefinitionKey);
    } else if (binding != null && CalledElementBinding.DEPLOYMENT.getValue().equals(binding)) {
      processDefinition = Context
          .getProcessEngineConfiguration()
          .getDeploymentCache()
          .findDeployedProcessDefinitionByDeploymentAndKey(Context.getExecutionContext().getExecution().getProcessDefinition().getDeploymentId(),
              processDefinitionKey);
    } else if (binding != null && CalledElementBinding.VERSION.getValue().equals(binding) && version != null) {
      processDefinition = Context.getProcessEngineConfiguration().getDeploymentCache()
          .findDeployedProcessDefinitionByKeyAndVersion(processDefinitionKey, version);
    }

    // copy process variables / businessKey
    String businessKey = null;
    Map<String, Object> callActivityVariables = new HashMap<String, Object>();

    for (DataAssociation dataInputAssociation : copy_dataInputAssociations) {
      Object value = null;

      if (dataInputAssociation.getBusinessKeyExpression() != null) {
        businessKey = (String) dataInputAssociation.getBusinessKeyExpression().getValue(execution);
      } else if (dataInputAssociation.getVariables() != null) {
        Map<String, Object> variables = execution.getVariables();
        if (variables != null && !variables.isEmpty()) {
          Set<String> variableKeys = variables.keySet();
          for (String variableKey : variableKeys) {
            callActivityVariables.put(variableKey, variables.get(variableKey));
          }
        }
      } else if (dataInputAssociation.getSourceExpression() != null) {
        value = dataInputAssociation.getSourceExpression().getValue(execution);
      } else {
        value = execution.getVariable(dataInputAssociation.getSource());
      }

      if (value != null) {
        callActivityVariables.put(dataInputAssociation.getTarget(), value);
      }
    }

    
    
    // UNCHANGED TILL HERE!
    
    // now we create the process instance on a different activity steered by the expression:
    String migrationScenario = null;
    try {
      migrationScenario = (String) migrationScenarioExpression.getValue(execution);
    }
    catch (ProcessEngineException ex) {
      // might be the case if the process run in "normal" mode and some variables have not be passed id
    }
    
    if (migrationScenario==null) {
      // normal behavior
      PvmProcessInstance subProcessInstance = execution.createSubProcessInstance(processDefinition, businessKey);
      subProcessInstance.start(callActivityVariables);
    }
    else {
      // now there are two possibilities: 
      // 1. The process contains a matching Message Start Event
      // 2. The process contains a matching intermediate event
      ActivityImpl startActivity = processDefinition.findActivity(migrationScenario);
            
      ExecutionEntity subProcessInstance = (ExecutionEntity) processDefinition.createProcessInstance(businessKey, startActivity);
      
      // add hierarchy for the sub process instance
      subProcessInstance.setSuperExecution((ExecutionEntity)execution);      
      ((ExecutionEntity)execution).setSubProcessInstance(subProcessInstance);
      
      if (subProcessInstance.getExecutions().size()==1) {
        healExecution(subProcessInstance, subProcessInstance.getExecutions().get(0), startActivity);
      }
      else if (subProcessInstance.getExecutions().size()>1) {
        throw new ProcessEngineException("starting a process instance in parallel pathes of execution is not possible at the moment");
      }
      
      // and start normally
      subProcessInstance.start(callActivityVariables);
    }
  }
@Override
  public void execute(ActivityExecution execution) throws Exception {
    String processDefinitionKey = this.processDefinitionKey;
    String binding = this.binding;
    Integer version = this.version;
    if (copy_processDefinitionExpression != null) {
      processDefinitionKey = (String) copy_processDefinitionExpression.getValue(execution);
    }

    ProcessDefinitionEntity processDefinition = null;
    if (binding == null || CalledElementBinding.LATEST.getValue().equals(binding)) {
      processDefinition = Context.getProcessEngineConfiguration().getDeploymentCache().findDeployedLatestProcessDefinitionByKey(processDefinitionKey);
    } else if (binding != null && CalledElementBinding.DEPLOYMENT.getValue().equals(binding)) {
      processDefinition = Context
          .getProcessEngineConfiguration()
          .getDeploymentCache()
          .findDeployedProcessDefinitionByDeploymentAndKey(Context.getExecutionContext().getExecution().getProcessDefinition().getDeploymentId(),
              processDefinitionKey);
    } else if (binding != null && CalledElementBinding.VERSION.getValue().equals(binding) && version != null) {
      processDefinition = Context.getProcessEngineConfiguration().getDeploymentCache()
          .findDeployedProcessDefinitionByKeyAndVersion(processDefinitionKey, version);
    }

    // copy process variables / businessKey
    String businessKey = null;
    Map<String, Object> callActivityVariables = new HashMap<String, Object>();

    for (DataAssociation dataInputAssociation : copy_dataInputAssociations) {
      Object value = null;

      if (dataInputAssociation.getBusinessKeyExpression() != null) {
        businessKey = (String) dataInputAssociation.getBusinessKeyExpression().getValue(execution);
      } else if (dataInputAssociation.getVariables() != null) {
        Map<String, Object> variables = execution.getVariables();
        if (variables != null && !variables.isEmpty()) {
          Set<String> variableKeys = variables.keySet();
          for (String variableKey : variableKeys) {
            callActivityVariables.put(variableKey, variables.get(variableKey));
          }
        }
      } else if (dataInputAssociation.getSourceExpression() != null) {
        value = dataInputAssociation.getSourceExpression().getValue(execution);
      } else {
        value = execution.getVariable(dataInputAssociation.getSource());
      }

      if (value != null) {
        callActivityVariables.put(dataInputAssociation.getTarget(), value);
      }
    }

    
    
    // UNCHANGED TILL HERE!
    
    // now we create the process instance on a different activity steered by the expression:
    String migrationScenario = null;
    try {
      migrationScenario = (String) migrationScenarioExpression.getValue(execution);
    }
    catch (ProcessEngineException ex) {
      // might be the case if the process run in "normal" mode and some variables have not be passed id
    }
    
    if (migrationScenario==null) {
      // normal behavior
      PvmProcessInstance subProcessInstance = execution.createSubProcessInstance(processDefinition, businessKey);
      subProcessInstance.start(callActivityVariables);
    }
    else {
      // now there are two possibilities: 
      // 1. The process contains a matching Message Start Event
      // 2. The process contains a matching intermediate event
      ActivityImpl startActivity = processDefinition.findActivity(migrationScenario);
            
      ExecutionEntity subProcessInstance = (ExecutionEntity) processDefinition.createProcessInstance(businessKey, startActivity);
      
      // add hierarchy for the sub process instance
      subProcessInstance.setSuperExecution((ExecutionEntity)execution);      
      ((ExecutionEntity)execution).setSubProcessInstance(subProcessInstance);
      
      if (subProcessInstance.getExecutions().size()==1) {
        healExecution(subProcessInstance, subProcessInstance.getExecutions().get(0), startActivity);
      }
      else if (subProcessInstance.getExecutions().size()>1) {
        throw new ProcessEngineException("starting a process instance in parallel pathes of execution is not possible at the moment");
      }
      
      // and start normally
      subProcessInstance.start(callActivityVariables);
    }
  }
copied from CallActivityBehavior