public FormRequest create(
      RequestDetails requestDetails,
      Process process,
      ProcessInstance processInstance,
      Task task,
      ActionType actionType,
      FormValidation validation)
      throws StatusCodeError {
    Activity activity = activity(process, processInstance, task);

    // Don't allow anyone to issue a create request for a task that's not open
    if (actionType == ActionType.CREATE
        && task != null
        && task.getTaskStatus() != null
        && !task.getTaskStatus().equals(Constants.TaskStatuses.OPEN)) actionType = ActionType.VIEW;

    FormRequest.Builder formRequestBuilder =
        new FormRequest.Builder()
            .processDefinitionKey(process.getProcessDefinitionKey())
            .instance(processInstance)
            .task(task)
            .activity(activity)
            .action(actionType);

    if (requestDetails != null) {
      String contentType =
          requestDetails.getContentType() != null
              ? requestDetails.getContentType().toString()
              : null;

      formRequestBuilder
          .remoteAddr(requestDetails.getRemoteAddr())
          .remoteHost(requestDetails.getRemoteHost())
          .remotePort(requestDetails.getRemotePort())
          .remoteUser(requestDetails.getRemoteUser())
          .actAsUser(requestDetails.getActAsUser())
          .certificateIssuer(requestDetails.getCertificateIssuer())
          .certificateSubject(requestDetails.getCertificateSubject())
          .contentType(contentType)
          .referrer(requestDetails.getReferrer())
          .userAgent(requestDetails.getUserAgent());

      List<MediaType> acceptableMediaTypes = requestDetails.getAcceptableMediaTypes();
      if (acceptableMediaTypes != null) {
        for (MediaType acceptableMediaType : acceptableMediaTypes) {
          formRequestBuilder.acceptableMediaType(acceptableMediaType.toString());
        }
      }
    }

    if (validation != null) {
      formRequestBuilder.messages(validation.getResults());
    }

    return requestRepository.save(formRequestBuilder.build());
  }
  public FormRequest handle(RequestDetails request, String requestId) throws StatusCodeError {
    FormRequest formRequest = requestRepository.findOne(requestId);

    if (formRequest == null) {
      return null;
    }

    if (request != null) {
      if (request.getRemoteUser() != null
          && formRequest.getRemoteUser() != null
          && !request.getRemoteUser().equals(formRequest.getRemoteUser())) {
        LOG.error(
            "Wrong user viewing or submitting form: "
                + request.getRemoteUser()
                + " not "
                + formRequest.getRemoteUser());
        throw new ForbiddenError(Constants.ExceptionCodes.user_does_not_match);
      }

      if (request.getRemoteHost() != null
          && formRequest.getRemoteHost() != null
          && !request.getRemoteHost().equals(formRequest.getRemoteHost()))
        LOG.warn(
            "This should not happen -- submission remote host ("
                + request.getRemoteHost()
                + ") does not match request ("
                + formRequest.getRemoteHost()
                + ")");

      if (request.getRemoteAddr() != null
          && formRequest.getRemoteAddr() != null
          && !request.getRemoteAddr().equals(formRequest.getRemoteAddr()))
        LOG.warn(
            "This should not happen -- submission remote address ("
                + request.getRemoteAddr()
                + ") does not match request ("
                + formRequest.getRemoteAddr()
                + ")");

      if (formRequest.getCertificateIssuer() != null
          && formRequest.getCertificateSubject() != null) {
        String certificateIssuer = request.getCertificateIssuer();
        String certificateSubject = request.getCertificateSubject();

        if (StringUtils.isEmpty(certificateIssuer)
            || StringUtils.isEmpty(certificateSubject)
            || !certificateIssuer.equals(formRequest.getCertificateIssuer())
            || !certificateSubject.equals(formRequest.getCertificateSubject())) {
          LOG.error(
              "Wrong certificate submitting form: "
                  + certificateIssuer
                  + ":"
                  + certificateSubject
                  + " not "
                  + formRequest.getCertificateIssuer()
                  + ":"
                  + formRequest.getCertificateSubject());
          throw new ForbiddenError(Constants.ExceptionCodes.certificate_does_not_match);
        }
      }

      if (formRequest.getRequestDate() != null) {
        Hours hours =
            Hours.hoursBetween(new DateTime(formRequest.getRequestDate()), new DateTime());
        int h = hours.getHours();
        if (h > 1) {
          throw new ForbiddenError(Constants.ExceptionCodes.request_expired);
        }
      }
    }

    ProcessInstance instance = formRequest.getInstance();

    if (instance == null
        && StringUtils.isNotEmpty(formRequest.getProcessDefinitionKey())
        && StringUtils.isNotEmpty(formRequest.getProcessInstanceId()))
      instance =
          processInstanceService.read(
              formRequest.getProcessDefinitionKey(), formRequest.getProcessInstanceId(), false);

    FormRequest.Builder builder =
        new FormRequest.Builder(formRequest)
            .instance(instance)
            .task(taskService.read(instance, formRequest.getTaskId()));

    return builder.build();
  }