/**
   * extract the list of information from the process variables and make them available locally.
   * Note that if no task instance variables are specified, the full process variables scope will be
   * visible (that means that the user did not specify a special task instance scope).
   */
  public void initializeVariables(TaskInstance taskInstance) {
    ClassLoader surroundingClassLoader = Thread.currentThread().getContextClassLoader();
    try {
      // set context class loader correctly for delegation class
      // (https://jira.jboss.org/jira/browse/JBPM-1448)
      Thread.currentThread()
          .setContextClassLoader(
              JbpmConfiguration.getProcessClassLoader(
                  taskInstance.getTask().getProcessDefinition()));

      if (taskControllerDelegation != null) {
        TaskControllerHandler taskControllerHandler =
            (TaskControllerHandler) taskControllerDelegation.instantiate();
        ProcessInstance processInstance = taskInstance.getTaskMgmtInstance().getProcessInstance();
        ContextInstance contextInstance =
            (processInstance != null ? processInstance.getContextInstance() : null);
        Token token = taskInstance.getToken();

        if (UserCodeInterceptorConfig.userCodeInterceptor != null) {
          UserCodeInterceptorConfig.userCodeInterceptor.executeTaskControllerInitialization(
              taskControllerHandler, taskInstance, contextInstance, token);
        } else {
          taskControllerHandler.initializeTaskVariables(taskInstance, contextInstance, token);
        }

      } else {
        Token token = taskInstance.getToken();
        ProcessInstance processInstance = token.getProcessInstance();
        ContextInstance contextInstance = processInstance.getContextInstance();

        if (variableAccesses != null) {
          Iterator iter = variableAccesses.iterator();
          while (iter.hasNext()) {
            VariableAccess variableAccess = (VariableAccess) iter.next();
            String mappedName = variableAccess.getMappedName();
            if (variableAccess.isReadable()) {
              String variableName = variableAccess.getVariableName();
              Object value = contextInstance.getVariable(variableName, token);
              log.debug(
                  "creating task instance variable '"
                      + mappedName
                      + "' from process variable '"
                      + variableName
                      + "', value '"
                      + value
                      + "'");
              taskInstance.setVariableLocally(mappedName, value);
            } else {
              log.debug(
                  "creating task instance local variable '"
                      + mappedName
                      + "'. initializing with null value.");
              taskInstance.setVariableLocally(mappedName, null);
            }
          }
        }
      }
    } finally {
      Thread.currentThread().setContextClassLoader(surroundingClassLoader);
    }
  }
  /** update the process variables from the the task-instance variables. */
  public void submitParameters(TaskInstance taskInstance) {
    ClassLoader surroundingClassLoader = Thread.currentThread().getContextClassLoader();
    try {
      // set context class loader correctly for delegation class
      // (https://jira.jboss.org/jira/browse/JBPM-1448)
      Thread.currentThread()
          .setContextClassLoader(
              JbpmConfiguration.getProcessClassLoader(
                  taskInstance.getTask().getProcessDefinition()));

      if (taskControllerDelegation != null) {
        TaskControllerHandler taskControllerHandler =
            (TaskControllerHandler) taskControllerDelegation.instantiate();
        ProcessInstance processInstance = taskInstance.getTaskMgmtInstance().getProcessInstance();
        ContextInstance contextInstance =
            (processInstance != null ? processInstance.getContextInstance() : null);
        Token token = taskInstance.getToken();

        if (UserCodeInterceptorConfig.userCodeInterceptor != null) {
          UserCodeInterceptorConfig.userCodeInterceptor.executeTaskControllerSubmission(
              taskControllerHandler, taskInstance, contextInstance, token);
        } else {
          taskControllerHandler.submitTaskVariables(taskInstance, contextInstance, token);
        }

      } else {

        Token token = taskInstance.getToken();
        ProcessInstance processInstance = token.getProcessInstance();
        ContextInstance contextInstance = processInstance.getContextInstance();

        if (variableAccesses != null) {
          String missingTaskVariables = null;
          Iterator iter = variableAccesses.iterator();
          while (iter.hasNext()) {
            VariableAccess variableAccess = (VariableAccess) iter.next();
            String mappedName = variableAccess.getMappedName();
            // first check if the required variableInstances are present
            if ((variableAccess.isRequired()) && (!taskInstance.hasVariableLocally(mappedName))) {
              if (missingTaskVariables == null) {
                missingTaskVariables = mappedName;
              } else {
                missingTaskVariables += ", " + mappedName;
              }
            }
          }

          // if there are missing, required parameters, throw an
          // IllegalArgumentException
          if (missingTaskVariables != null) {
            throw new IllegalArgumentException("missing task variables: " + missingTaskVariables);
          }

          iter = variableAccesses.iterator();
          while (iter.hasNext()) {
            VariableAccess variableAccess = (VariableAccess) iter.next();
            String mappedName = variableAccess.getMappedName();
            String variableName = variableAccess.getVariableName();
            if (variableAccess.isWritable()) {
              Object value = taskInstance.getVariable(mappedName);
              if (value != null) {
                log.debug(
                    "submitting task variable '"
                        + mappedName
                        + "' to process variable '"
                        + variableName
                        + "', value '"
                        + value
                        + "'");
                contextInstance.setVariable(variableName, value, token);
              }
            }
          }
        }
      }
    } finally {
      Thread.currentThread().setContextClassLoader(surroundingClassLoader);
    }
  }