protected ResultType handleClientException(
      GenericClient theClient, Exception e, ModelMap theModel) {
    ResultType returnsResource;
    returnsResource = ResultType.NONE;
    ourLog.warn("Failed to invoke server", e);

    if (theClient.getLastResponse() == null) {
      theModel.put("errorMsg", "Error: " + e.getMessage());
    }

    return returnsResource;
  }
  protected void processAndAddLastClientInvocation(
      GenericClient theClient,
      ResultType theResultType,
      ModelMap theModelMap,
      long theLatency,
      String outcomeDescription,
      CaptureInterceptor theInterceptor,
      HomeRequest theRequest) {
    try {
      HttpRequestBase lastRequest = theInterceptor.getLastRequest();
      HttpResponse lastResponse = theInterceptor.getLastResponse();
      String requestBody = null;
      String requestUrl = lastRequest != null ? lastRequest.getURI().toASCIIString() : null;
      String action = lastRequest != null ? lastRequest.getMethod() : null;
      String resultStatus = lastResponse != null ? lastResponse.getStatusLine().toString() : null;
      String resultBody = StringUtils.defaultString(theInterceptor.getLastResponseBody());

      if (lastRequest instanceof HttpEntityEnclosingRequest) {
        HttpEntity entity = ((HttpEntityEnclosingRequest) lastRequest).getEntity();
        if (entity.isRepeatable()) {
          requestBody = IOUtils.toString(entity.getContent());
        }
      }

      ContentType ct = lastResponse != null ? ContentType.get(lastResponse.getEntity()) : null;
      String mimeType = ct != null ? ct.getMimeType() : null;
      EncodingEnum ctEnum = EncodingEnum.forContentType(mimeType);
      String narrativeString = "";

      StringBuilder resultDescription = new StringBuilder();
      Bundle bundle = null;
      IBaseResource riBundle = null;

      FhirContext context = getContext(theRequest);
      if (ctEnum == null) {
        resultDescription.append("Non-FHIR response");
      } else {
        switch (ctEnum) {
          case JSON:
            if (theResultType == ResultType.RESOURCE) {
              narrativeString = parseNarrative(theRequest, ctEnum, resultBody);
              resultDescription.append("JSON resource");
            } else if (theResultType == ResultType.BUNDLE) {
              resultDescription.append("JSON bundle");
              if (context.getVersion().getVersion().isRi()) {
                riBundle = context.newJsonParser().parseResource(resultBody);
              } else {
                bundle = context.newJsonParser().parseBundle(resultBody);
              }
            }
            break;
          case XML:
          default:
            if (theResultType == ResultType.RESOURCE) {
              narrativeString = parseNarrative(theRequest, ctEnum, resultBody);
              resultDescription.append("XML resource");
            } else if (theResultType == ResultType.BUNDLE) {
              resultDescription.append("XML bundle");
              if (context.getVersion().getVersion().isRi()) {
                riBundle = context.newXmlParser().parseResource(resultBody);
              } else {
                bundle = context.newXmlParser().parseBundle(resultBody);
              }
            }
            break;
        }
      }

      resultDescription.append(" (").append(resultBody.length() + " bytes)");

      Header[] requestHeaders =
          lastRequest != null ? applyHeaderFilters(lastRequest.getAllHeaders()) : new Header[0];
      Header[] responseHeaders =
          lastResponse != null ? applyHeaderFilters(lastResponse.getAllHeaders()) : new Header[0];

      theModelMap.put("outcomeDescription", outcomeDescription);
      theModelMap.put("resultDescription", resultDescription.toString());
      theModelMap.put("action", action);
      theModelMap.put("bundle", bundle);
      theModelMap.put("riBundle", riBundle);
      theModelMap.put("resultStatus", resultStatus);

      theModelMap.put("requestUrl", requestUrl);
      theModelMap.put("requestUrlText", formatUrl(theClient.getUrlBase(), requestUrl));

      String requestBodyText = format(requestBody, ctEnum);
      theModelMap.put("requestBody", requestBodyText);

      String resultBodyText = format(resultBody, ctEnum);
      theModelMap.put("resultBody", resultBodyText);

      theModelMap.put("resultBodyIsLong", resultBodyText.length() > 1000);
      theModelMap.put("requestHeaders", requestHeaders);
      theModelMap.put("responseHeaders", responseHeaders);
      theModelMap.put("narrative", narrativeString);
      theModelMap.put("latencyMs", theLatency);

    } catch (Exception e) {
      ourLog.error("Failure during processing", e);
      theModelMap.put("errorMsg", "Error during processing: " + e.getMessage());
    }
  }
  private IBaseResource loadAndAddConfDstu21(
      HttpServletRequest theServletRequest, final HomeRequest theRequest, final ModelMap theModel) {
    CaptureInterceptor interceptor = new CaptureInterceptor();
    GenericClient client =
        theRequest.newClient(theServletRequest, getContext(theRequest), myConfig, interceptor);

    org.hl7.fhir.dstu21.model.Conformance conformance;
    try {
      conformance =
          client.fetchConformance().ofType(org.hl7.fhir.dstu21.model.Conformance.class).execute();
    } catch (Exception e) {
      ourLog.warn("Failed to load conformance statement", e);
      theModel.put("errorMsg", "Failed to load conformance statement, error was: " + e.toString());
      conformance = new org.hl7.fhir.dstu21.model.Conformance();
    }

    theModel.put(
        "jsonEncodedConf",
        getContext(theRequest).newJsonParser().encodeResourceToString(conformance));

    Map<String, Number> resourceCounts = new HashMap<String, Number>();
    long total = 0;
    for (ConformanceRestComponent nextRest : conformance.getRest()) {
      for (ConformanceRestResourceComponent nextResource : nextRest.getResource()) {
        List<Extension> exts = nextResource.getExtensionsByUrl(RESOURCE_COUNT_EXT_URL);
        if (exts != null && exts.size() > 0) {
          Number nextCount = ((DecimalType) (exts.get(0).getValue())).getValueAsNumber();
          resourceCounts.put(nextResource.getTypeElement().getValue(), nextCount);
          total += nextCount.longValue();
        }
      }
    }
    theModel.put("resourceCounts", resourceCounts);

    if (total > 0) {
      for (ConformanceRestComponent nextRest : conformance.getRest()) {
        Collections.sort(
            nextRest.getResource(),
            new Comparator<ConformanceRestResourceComponent>() {
              @Override
              public int compare(
                  ConformanceRestResourceComponent theO1, ConformanceRestResourceComponent theO2) {
                DecimalType count1 = new DecimalType();
                List<Extension> count1exts = theO1.getExtensionsByUrl(RESOURCE_COUNT_EXT_URL);
                if (count1exts != null && count1exts.size() > 0) {
                  count1 = (DecimalType) count1exts.get(0).getValue();
                }
                DecimalType count2 = new DecimalType();
                List<Extension> count2exts = theO2.getExtensionsByUrl(RESOURCE_COUNT_EXT_URL);
                if (count2exts != null && count2exts.size() > 0) {
                  count2 = (DecimalType) count2exts.get(0).getValue();
                }
                int retVal = count2.compareTo(count1);
                if (retVal == 0) {
                  retVal =
                      theO1
                          .getTypeElement()
                          .getValue()
                          .compareTo(theO2.getTypeElement().getValue());
                }
                return retVal;
              }
            });
      }
    }

    theModel.put("conf", conformance);
    theModel.put("requiredParamExtension", ExtensionConstants.PARAM_IS_REQUIRED);

    return conformance;
  }
  @SuppressWarnings("unchecked")
  void validateServerBase(String theServerBase, HttpClient theHttpClient, BaseClient theClient) {

    GenericClient client = new GenericClient(myContext, theHttpClient, theServerBase, this);
    for (IClientInterceptor interceptor : theClient.getInterceptors()) {
      client.registerInterceptor(interceptor);
    }
    client.setDontValidateConformance(true);

    IBaseResource conformance;
    try {
      @SuppressWarnings("rawtypes")
      Class implementingClass =
          myContext.getResourceDefinition("Conformance").getImplementingClass();
      conformance = (IBaseResource) client.fetchConformance().ofType(implementingClass).execute();
    } catch (FhirClientConnectionException e) {
      throw new FhirClientConnectionException(
          myContext
              .getLocalizer()
              .getMessage(
                  RestfulClientFactory.class,
                  "failedToRetrieveConformance",
                  theServerBase + Constants.URL_TOKEN_METADATA),
          e);
    }

    FhirTerser t = myContext.newTerser();
    String serverFhirVersionString = null;
    Object value = t.getSingleValueOrNull(conformance, "fhirVersion");
    if (value instanceof IPrimitiveType) {
      serverFhirVersionString = ((IPrimitiveType<?>) value).getValueAsString();
    }
    FhirVersionEnum serverFhirVersionEnum = null;
    if (StringUtils.isBlank(serverFhirVersionString)) {
      // we'll be lenient and accept this
    } else {
      if (serverFhirVersionString.startsWith("0.80")
          || serverFhirVersionString.startsWith("0.0.8")) {
        serverFhirVersionEnum = FhirVersionEnum.DSTU1;
      } else if (serverFhirVersionString.startsWith("0.4")) {
        serverFhirVersionEnum = FhirVersionEnum.DSTU2;
      } else if (serverFhirVersionString.startsWith("0.5")) {
        serverFhirVersionEnum = FhirVersionEnum.DSTU2;
      } else {
        // we'll be lenient and accept this
        ourLog.debug(
            "Server conformance statement indicates unknown FHIR version: {}",
            serverFhirVersionString);
      }
    }

    if (serverFhirVersionEnum != null) {
      FhirVersionEnum contextFhirVersion = myContext.getVersion().getVersion();
      if (!contextFhirVersion.isEquivalentTo(serverFhirVersionEnum)) {
        throw new FhirClientInappropriateForServerException(
            myContext
                .getLocalizer()
                .getMessage(
                    RestfulClientFactory.class,
                    "wrongVersionInConformance",
                    theServerBase + Constants.URL_TOKEN_METADATA,
                    serverFhirVersionString,
                    serverFhirVersionEnum,
                    contextFhirVersion));
      }
    }

    myValidatedServerBaseUrls.add(normalizeBaseUrlForMap(theServerBase));
  }