private Object getParam(
      final Class<?> pClass,
      final String pName,
      final ParamType pType,
      final String pXpath,
      final HttpMessage pMessage)
      throws XmlException {
    Object result = null;
    switch (pType) {
      case GET:
        result = getParamGet(pName, pMessage);
        break;
      case POST:
        result = getParamPost(pName, pMessage);
        break;
      case QUERY:
        result = getParamGet(pName, pMessage);
        if (result == null) {
          result = getParamPost(pName, pMessage);
        }
        break;
      case VAR:
        result = mPathParams.get(pName);
        break;
      case XPATH:
        result = getParamXPath(pClass, pXpath, pMessage.getBody());
        break;
      case BODY:
        result = getBody(pClass, pMessage);
        break;
      case ATTACHMENT:
        result = getAttachment(pClass, pName, pMessage);
        break;
      case PRINCIPAL:
        {
          final Principal principal = pMessage.getUserPrincipal();
          if (pClass.isAssignableFrom(String.class)) {
            result = principal.getName();
          } else {
            result = principal;
          }
          break;
        }
    }
    // XXX generizice this and share the same approach to unmarshalling in ALL code
    // TODO support collection/list parameters
    if ((result != null) && (!pClass.isInstance(result))) {
      if ((Types.isPrimitive(pClass) || (Types.isPrimitiveWrapper(pClass)))
          && (result instanceof String)) {
        try {
          result = Types.parsePrimitive(pClass, ((String) result));
        } catch (NumberFormatException e) {
          throw new HttpResponseException(
              HttpServletResponse.SC_BAD_REQUEST, "The argument given is invalid", e);
        }
      } else if (Enum.class.isAssignableFrom(pClass)) {
        @SuppressWarnings({"rawtypes"})
        final Class clazz = pClass;
        @SuppressWarnings("unchecked")
        final Enum<?> tmpResult = Enum.valueOf(clazz, result.toString());
        result = tmpResult;
      } else if (result instanceof Node) {
        XmlDeserializer factory = pClass.getAnnotation(XmlDeserializer.class);
        if (factory != null) {
          try {
            result =
                factory
                    .value()
                    .newInstance()
                    .deserialize(XmlStreaming.newReader(new DOMSource((Node) result)));
          } catch (IllegalAccessException | InstantiationException e) {
            throw new XmlException(e);
          }
        } else {
          result = JAXB.unmarshal(new DOMSource((Node) result), pClass);
        }
      } else {
        final String s = result.toString();
        // Only wrap when we don't start with <
        final char[] requestBody =
            (s.startsWith("<") ? s : "<wrapper>" + s + "</wrapper>").toCharArray();
        if (requestBody.length > 0) {
          result = JAXB.unmarshal(new CharArrayReader(requestBody), pClass);
        } else {
          result = null;
        }
      }
    }

    return result;
  }