/**
   * Generate http request entity from Spring Integration message.
   *
   * @param requestMessage
   * @param method
   * @return
   */
  private HttpEntity<?> generateRequest(Message<?> requestMessage, HttpMethod method) {
    HttpHeaders httpHeaders = new HttpHeaders();
    headerMapper.fromHeaders(requestMessage.getHeaders(), httpHeaders);

    Map<String, ?> messageHeaders = requestMessage.getHeaders();
    for (Entry<String, ?> header : messageHeaders.entrySet()) {
      if (!header.getKey().startsWith(CitrusMessageHeaders.PREFIX)
          && !MessageUtils.isSpringInternalHeader(header.getKey())
          && !httpHeaders.containsKey(header.getKey())) {
        httpHeaders.add(header.getKey(), header.getValue().toString());
      }
    }

    Object payload = requestMessage.getPayload();
    if (httpHeaders.getContentType() == null) {
      httpHeaders.setContentType(
          MediaType.parseMediaType(
              contentType.contains("charset") ? contentType : contentType + ";charset=" + charset));
    }

    if (HttpMethod.POST.equals(method) || HttpMethod.PUT.equals(method)) {
      return new HttpEntity<Object>(payload, httpHeaders);
    }

    return new HttpEntity<Object>(httpHeaders);
  }
  /**
   * Message headers consist of standard HTTP message headers and custom headers. This method
   * assumes that all header entries that were not initially mapped by header mapper implementations
   * are custom headers.
   *
   * @param httpHeaders all message headers in their pre nature.
   * @param mappedHeaders the previously mapped header entries (all standard headers).
   * @return
   */
  private Map<String, String> getCustomHeaders(
      HttpHeaders httpHeaders, Map<String, ?> mappedHeaders) {
    Map<String, String> customHeaders = new HashMap<String, String>();

    for (Entry<String, List<String>> header : httpHeaders.entrySet()) {
      if (!mappedHeaders.containsKey(header.getKey())) {
        customHeaders.put(
            header.getKey(), StringUtils.collectionToCommaDelimitedString(header.getValue()));
      }
    }

    return customHeaders;
  }
  /**
   * Handles requests with message handler implementation. Previously sets Http request method as
   * header parameter.
   *
   * @param method
   * @param requestEntity
   * @return
   */
  private ResponseEntity<String> handleRequestInternal(
      HttpMethod method, HttpEntity<String> requestEntity) {
    Map<String, ?> httpRequestHeaders = headerMapper.toHeaders(requestEntity.getHeaders());
    Map<String, String> customHeaders = new HashMap<String, String>();
    for (Entry<String, List<String>> header : requestEntity.getHeaders().entrySet()) {
      if (!httpRequestHeaders.containsKey(header.getKey())) {
        customHeaders.put(
            header.getKey(), StringUtils.collectionToCommaDelimitedString(header.getValue()));
      }
    }

    HttpServletRequest request =
        ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    UrlPathHelper pathHelper = new UrlPathHelper();

    customHeaders.put(CitrusHttpMessageHeaders.HTTP_REQUEST_URI, pathHelper.getRequestUri(request));
    customHeaders.put(
        CitrusHttpMessageHeaders.HTTP_CONTEXT_PATH, pathHelper.getContextPath(request));

    String queryParams = pathHelper.getOriginatingQueryString(request);
    customHeaders.put(
        CitrusHttpMessageHeaders.HTTP_QUERY_PARAMS, queryParams != null ? queryParams : "");

    customHeaders.put(CitrusHttpMessageHeaders.HTTP_REQUEST_METHOD, method.toString());

    Message<?> response =
        messageHandler.handleMessage(
            MessageBuilder.withPayload(requestEntity.getBody())
                .copyHeaders(convertHeaderTypes(httpRequestHeaders))
                .copyHeaders(customHeaders)
                .build());

    return generateResponse(response);
  }
  /**
   * Checks for collection typed header values and convert them to comma delimited String. We need
   * this for further header processing e.g when forwarding headers to JMS queues.
   *
   * @param headers the http request headers.
   */
  private Map<String, Object> convertHeaderTypes(Map<String, ?> headers) {
    Map<String, Object> convertedHeaders = new HashMap<String, Object>();

    for (Entry<String, ?> header : headers.entrySet()) {
      if (header.getValue() instanceof Collection<?>) {
        Collection<?> value = (Collection<?>) header.getValue();
        convertedHeaders.put(header.getKey(), StringUtils.collectionToCommaDelimitedString(value));
      } else if (header.getValue() instanceof MediaType) {
        convertedHeaders.put(header.getKey(), header.getValue().toString());
      } else {
        convertedHeaders.put(header.getKey(), header.getValue());
      }
    }

    return convertedHeaders;
  }
  /**
   * Generates the Http response message from given Spring Integration message.
   *
   * @param responseMessage message received from the message handler
   * @return an HTTP entity as response
   */
  private ResponseEntity<String> generateResponse(Message<?> responseMessage) {
    if (responseMessage == null) {
      return new ResponseEntity<String>(HttpStatus.OK);
    }

    HttpHeaders httpHeaders = new HttpHeaders();
    headerMapper.fromHeaders(responseMessage.getHeaders(), httpHeaders);

    Map<String, ?> messageHeaders = responseMessage.getHeaders();
    for (Entry<String, ?> header : messageHeaders.entrySet()) {
      if (!header.getKey().startsWith(CitrusMessageHeaders.PREFIX)
          && !MessageUtils.isSpringInternalHeader(header.getKey())
          && !httpHeaders.containsKey(header.getKey())) {
        httpHeaders.add(header.getKey(), header.getValue().toString());
      }
    }

    if (httpHeaders.getContentType() == null) {
      httpHeaders.setContentType(
          MediaType.parseMediaType(
              contentType.contains("charset") ? contentType : contentType + ";charset=" + charset));
    }

    HttpStatus status = HttpStatus.OK;
    if (responseMessage.getHeaders().containsKey(CitrusHttpMessageHeaders.HTTP_STATUS_CODE)) {
      status =
          HttpStatus.valueOf(
              Integer.valueOf(
                  responseMessage
                      .getHeaders()
                      .get(CitrusHttpMessageHeaders.HTTP_STATUS_CODE)
                      .toString()));
    }

    responseCache =
        new ResponseEntity<String>(responseMessage.getPayload().toString(), httpHeaders, status);

    return responseCache;
  }