protected void addGlobalVariables(
      Execution execution,
      int variableType,
      Map<String, RestVariable> variableMap,
      UriInfo uriInfo) {
    RuntimeService runtimeService = BPMNOSGIService.getRumtimeService();
    Map<String, Object> rawVariables = runtimeService.getVariables(execution.getId());
    List<RestVariable> globalVariables =
        new RestResponseFactory()
            .createRestVariables(
                rawVariables,
                execution.getId(),
                variableType,
                RestVariable.RestVariableScope.GLOBAL,
                uriInfo.getBaseUri().toString());

    // Overlay global variables over local ones. In case they are present the values are not
    // overridden,
    // since local variables get precedence over global ones at all times.
    for (RestVariable var : globalVariables) {
      if (!variableMap.containsKey(var.getName())) {
        variableMap.put(var.getName(), var);
      }
    }
  }
  protected Map<String, Object> getVariablesToSet(ExecutionActionRequest actionRequest) {
    Map<String, Object> variablesToSet = new HashMap<String, Object>();
    for (RestVariable var : actionRequest.getVariables()) {
      if (var.getName() == null) {
        throw new ActivitiIllegalArgumentException("Variable name is required");
      }

      Object actualVariableValue = new RestResponseFactory().getVariableValue(var);

      variablesToSet.put(var.getName(), actualVariableValue);
    }
    return variablesToSet;
  }
  protected RestVariable setSimpleVariable(
      RestVariable restVariable, Execution execution, boolean isNew, UriInfo uriInfo) {
    if (restVariable.getName() == null) {
      throw new ActivitiIllegalArgumentException("Variable name is required");
    }

    // Figure out scope, revert to local is omitted
    RestVariable.RestVariableScope scope = restVariable.getVariableScope();
    if (scope == null) {
      scope = RestVariable.RestVariableScope.LOCAL;
    }

    Object actualVariableValue = new RestResponseFactory().getVariableValue(restVariable);
    setVariable(execution, restVariable.getName(), actualVariableValue, scope, isNew);

    return constructRestVariable(
        restVariable.getName(), restVariable.getValue(), scope, execution.getId(), false, uriInfo);
  }
  protected void addLocalVariables(
      Execution execution,
      int variableType,
      Map<String, RestVariable> variableMap,
      UriInfo uriInfo) {
    RuntimeService runtimeService = BPMNOSGIService.getRumtimeService();
    Map<String, Object> rawLocalvariables = runtimeService.getVariablesLocal(execution.getId());
    List<RestVariable> localVariables =
        new RestResponseFactory()
            .createRestVariables(
                rawLocalvariables,
                execution.getId(),
                variableType,
                RestVariable.RestVariableScope.LOCAL,
                uriInfo.getBaseUri().toString());

    for (RestVariable var : localVariables) {
      variableMap.put(var.getName(), var);
    }
  }
  protected Response createExecutionVariable(
      Execution execution,
      boolean override,
      int variableType,
      HttpServletRequest httpServletRequest,
      UriInfo uriInfo) {

    Object result = null;
    Response.ResponseBuilder responseBuilder = Response.ok();

    List<RestVariable> inputVariables = new ArrayList<>();
    List<RestVariable> resultVariables = new ArrayList<>();

    if (Utils.isApplicationJsonRequest(httpServletRequest)) {
      try {
        ObjectMapper objectMapper = new ObjectMapper();
        @SuppressWarnings("unchecked")
        List<Object> variableObjects =
            (List<Object>) objectMapper.readValue(httpServletRequest.getInputStream(), List.class);
        for (Object restObject : variableObjects) {
          RestVariable restVariable = objectMapper.convertValue(restObject, RestVariable.class);
          inputVariables.add(restVariable);
        }
      } catch (Exception e) {
        throw new ActivitiIllegalArgumentException(
            "Failed to serialize to a RestVariable instance", e);
      }
    } else if (Utils.isApplicationXmlRequest(httpServletRequest)) {
      JAXBContext jaxbContext = null;
      try {
        jaxbContext = JAXBContext.newInstance(RestVariableCollection.class);
        Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
        RestVariableCollection restVariableCollection =
            (RestVariableCollection)
                jaxbUnmarshaller.unmarshal(httpServletRequest.getInputStream());
        if (restVariableCollection == null) {
          throw new ActivitiIllegalArgumentException(
              "xml request body could not be transformed to a "
                  + "RestVariable Collection instance.");
        }
        List<RestVariable> restVariableList = restVariableCollection.getRestVariables();

        if (restVariableList.size() == 0) {
          throw new ActivitiIllegalArgumentException(
              "xml request body could not identify any rest " + "variables to be updated");
        }
        for (RestVariable restVariable : restVariableList) {
          inputVariables.add(restVariable);
        }

      } catch (JAXBException | IOException e) {
        throw new ActivitiIllegalArgumentException(
            "xml request body could not be transformed to a " + "RestVariable instance.", e);
      }
    }

    if (inputVariables.size() == 0) {
      throw new ActivitiIllegalArgumentException(
          "Request didn't contain a list of variables to create.");
    }

    RestVariable.RestVariableScope sharedScope = null;
    RestVariable.RestVariableScope varScope = null;
    Map<String, Object> variablesToSet = new HashMap<String, Object>();

    for (RestVariable var : inputVariables) {
      // Validate if scopes match
      varScope = var.getVariableScope();
      if (var.getName() == null) {
        throw new ActivitiIllegalArgumentException("Variable name is required");
      }

      if (varScope == null) {
        varScope = RestVariable.RestVariableScope.LOCAL;
      }
      if (sharedScope == null) {
        sharedScope = varScope;
      }
      if (varScope != sharedScope) {
        throw new ActivitiIllegalArgumentException(
            "Only allowed to update multiple variables in the same scope.");
      }

      if (!override && hasVariableOnScope(execution, var.getName(), varScope)) {
        throw new BPMNConflictException(
            "Variable '"
                + var.getName()
                + "' is already present on execution '"
                + execution.getId()
                + "'.");
      }

      Object actualVariableValue = new RestResponseFactory().getVariableValue(var);
      variablesToSet.put(var.getName(), actualVariableValue);
      resultVariables.add(
          new RestResponseFactory()
              .createRestVariable(
                  var.getName(),
                  actualVariableValue,
                  varScope,
                  execution.getId(),
                  variableType,
                  false,
                  uriInfo.getBaseUri().toString()));
    }

    if (!variablesToSet.isEmpty()) {
      RuntimeService runtimeService = BPMNOSGIService.getRumtimeService();
      if (sharedScope == RestVariable.RestVariableScope.LOCAL) {
        runtimeService.setVariablesLocal(execution.getId(), variablesToSet);
      } else {
        if (execution.getParentId() != null) {
          // Explicitly set on parent, setting non-local variables on execution itself will override
          // local-variables if exists
          runtimeService.setVariables(execution.getParentId(), variablesToSet);
        } else {
          // Standalone task, no global variables possible
          throw new ActivitiIllegalArgumentException(
              "Cannot set global variables on execution '"
                  + execution.getId()
                  + "', task is not part of process.");
        }
      }
    }

    RestVariableCollection restVariableCollection = new RestVariableCollection();
    restVariableCollection.setRestVariables(resultVariables);
    responseBuilder.entity(restVariableCollection);
    return responseBuilder.status(Response.Status.CREATED).build();
  }