@Override
  public ValueSet expandByIdentifier(String theUri, String theFilter) {
    if (isBlank(theUri)) {
      throw new InvalidRequestException("URI must not be blank or missing");
    }
    ValueSet source;

    org.hl7.fhir.instance.model.ValueSet defaultValueSet =
        myDefaultProfileValidationSupport.fetchResource(
            myRiCtx, org.hl7.fhir.instance.model.ValueSet.class, theUri);
    if (defaultValueSet != null) {
      source =
          getContext()
              .newJsonParser()
              .parseResource(
                  ValueSet.class, myRiCtx.newJsonParser().encodeResourceToString(defaultValueSet));
    } else {
      IBundleProvider ids = search(ValueSet.SP_URL, new UriParam(theUri));
      if (ids.size() == 0) {
        throw new InvalidRequestException("Unknown ValueSet URI: " + theUri);
      }
      source = (ValueSet) ids.getResources(0, 1).get(0);
    }

    return expand(source, theFilter);
  }
  @SuppressWarnings("unchecked")
  @Override
  public Object invokeServer(
      IRestfulServer theServer, RequestDetails theRequest, Object[] theMethodParams)
      throws InvalidRequestException, InternalErrorException {

    /*
     * The design of HAPI's transaction method for DSTU1 support assumed that a transaction was just an update on a
     * bunch of resources (because that's what it was), but in DSTU2 transaction has become much more broad, so we
     * no longer hold the user's hand much here.
     */
    if (myTransactionParamStyle == ParamStyle.RESOURCE_BUNDLE) {
      // This is the DSTU2 style
      Object response = invokeServerMethod(theServer, theRequest, theMethodParams);
      return response;
    }

    // Grab the IDs of all of the resources in the transaction
    List<IResource> resources;
    if (theMethodParams[myTransactionParamIndex] instanceof Bundle) {
      resources = ((Bundle) theMethodParams[myTransactionParamIndex]).toListOfResources();
    } else {
      resources = (List<IResource>) theMethodParams[myTransactionParamIndex];
    }

    IdentityHashMap<IResource, IdDt> oldIds = new IdentityHashMap<IResource, IdDt>();
    for (IResource next : resources) {
      oldIds.put(next, next.getId());
    }

    // Call the server implementation method
    Object response = invokeServerMethod(theServer, theRequest, theMethodParams);
    IBundleProvider retVal = toResourceList(response);

    /*
     * int offset = 0; if (retVal.size() != resources.size()) { if (retVal.size() > 0 && retVal.getResources(0,
     * 1).get(0) instanceof OperationOutcome) { offset = 1; } else { throw new
     * InternalErrorException("Transaction bundle contained " + resources.size() +
     * " entries, but server method response contained " + retVal.size() + " entries (must be the same)"); } }
     */

    List<IBaseResource> retResources = retVal.getResources(0, retVal.size());
    for (int i = 0; i < retResources.size(); i++) {
      IdDt oldId = oldIds.get(retResources.get(i));
      IBaseResource newRes = retResources.get(i);
      if (newRes.getIdElement() == null || newRes.getIdElement().isEmpty()) {
        if (!(newRes instanceof BaseOperationOutcome)) {
          throw new InternalErrorException(
              "Transaction method returned resource at index "
                  + i
                  + " with no id specified - IResource#setId(IdDt)");
        }
      }

      if (oldId != null && !oldId.isEmpty()) {
        if (!oldId.equals(newRes.getIdElement()) && newRes instanceof IResource) {
          ((IResource) newRes)
              .getResourceMetadata()
              .put(ResourceMetadataKeyEnum.PREVIOUS_ID, oldId);
        }
      }
    }

    return retVal;
  }
  @Override
  public void invokeServer(RestfulServer theServer, Request theRequest)
      throws BaseServerResponseException, IOException {

    // Pretty print
    boolean prettyPrint = RestfulServerUtils.prettyPrintResponse(theServer, theRequest);

    // Narrative mode
    NarrativeModeEnum narrativeMode = RestfulServerUtils.determineNarrativeMode(theRequest);

    // Determine response encoding
    EncodingEnum responseEncoding =
        RestfulServerUtils.determineResponseEncodingNoDefault(theRequest.getServletRequest());

    // Is this request coming from a browser
    String uaHeader = theRequest.getServletRequest().getHeader("user-agent");
    boolean requestIsBrowser = false;
    if (uaHeader != null && uaHeader.contains("Mozilla")) {
      requestIsBrowser = true;
    }

    Object requestObject = parseRequestObject(theRequest);

    // Method params
    Object[] params = new Object[getParameters().size()];
    for (int i = 0; i < getParameters().size(); i++) {
      IParameter param = getParameters().get(i);
      if (param != null) {
        params[i] = param.translateQueryParametersIntoServerArgument(theRequest, requestObject);
      }
    }

    Object resultObj = invokeServer(theRequest, params);

    Integer count = RestfulServerUtils.extractCountParameter(theRequest.getServletRequest());
    boolean respondGzip = theRequest.isRespondGzip();
    HttpServletResponse response = theRequest.getServletResponse();
    switch (getReturnType()) {
      case BUNDLE:
        {
          if (getMethodReturnType() == MethodReturnTypeEnum.BUNDLE_RESOURCE) {
            IResource resource;
            if (resultObj instanceof IBundleProvider) {
              IBundleProvider result = (IBundleProvider) resultObj;
              resource = result.getResources(0, 1).get(0);
            } else {
              resource = (IResource) resultObj;
            }

            /*
             * We assume that the bundle we got back from the handling method may not have everything populated
             * (e.g. self links, bundle type, etc) so we do that here.
             */
            IVersionSpecificBundleFactory bundleFactory =
                theServer.getFhirContext().newBundleFactory();
            bundleFactory.initializeWithBundleResource(resource);
            bundleFactory.addRootPropertiesToBundle(
                null,
                theRequest.getFhirServerBase(),
                theRequest.getCompleteUrl(),
                count,
                getResponseBundleType());

            for (int i = theServer.getInterceptors().size() - 1; i >= 0; i--) {
              IServerInterceptor next = theServer.getInterceptors().get(i);
              boolean continueProcessing =
                  next.outgoingResponse(
                      theRequest,
                      resource,
                      theRequest.getServletRequest(),
                      theRequest.getServletResponse());
              if (!continueProcessing) {
                ourLog.debug("Interceptor {} returned false, not continuing processing");
                return;
              }
            }
            RestfulServerUtils.streamResponseAsResource(
                theServer,
                response,
                resource,
                responseEncoding,
                prettyPrint,
                requestIsBrowser,
                narrativeMode,
                Constants.STATUS_HTTP_200_OK,
                respondGzip,
                theRequest.getFhirServerBase(),
                isAddContentLocationHeader());
            break;
          } else {
            Set<Include> includes = getRequestIncludesFromParams(params);

            IBundleProvider result = (IBundleProvider) resultObj;
            if (count == null) {
              count = result.preferredPageSize();
            }

            IVersionSpecificBundleFactory bundleFactory =
                theServer.getFhirContext().newBundleFactory();
            bundleFactory.initializeBundleFromBundleProvider(
                theServer,
                result,
                responseEncoding,
                theRequest.getFhirServerBase(),
                theRequest.getCompleteUrl(),
                prettyPrint,
                0,
                count,
                null,
                getResponseBundleType(),
                includes);
            Bundle bundle = bundleFactory.getDstu1Bundle();
            if (bundle != null) {
              for (int i = theServer.getInterceptors().size() - 1; i >= 0; i--) {
                IServerInterceptor next = theServer.getInterceptors().get(i);
                boolean continueProcessing =
                    next.outgoingResponse(
                        theRequest,
                        bundle,
                        theRequest.getServletRequest(),
                        theRequest.getServletResponse());
                if (!continueProcessing) {
                  ourLog.debug("Interceptor {} returned false, not continuing processing");
                  return;
                }
              }
              RestfulServerUtils.streamResponseAsBundle(
                  theServer,
                  response,
                  bundle,
                  responseEncoding,
                  theRequest.getFhirServerBase(),
                  prettyPrint,
                  narrativeMode,
                  respondGzip,
                  requestIsBrowser);
            } else {
              IBaseResource resBundle = bundleFactory.getResourceBundle();
              for (int i = theServer.getInterceptors().size() - 1; i >= 0; i--) {
                IServerInterceptor next = theServer.getInterceptors().get(i);
                boolean continueProcessing =
                    next.outgoingResponse(
                        theRequest,
                        resBundle,
                        theRequest.getServletRequest(),
                        theRequest.getServletResponse());
                if (!continueProcessing) {
                  ourLog.debug("Interceptor {} returned false, not continuing processing");
                  return;
                }
              }
              RestfulServerUtils.streamResponseAsResource(
                  theServer,
                  response,
                  (IResource) resBundle,
                  responseEncoding,
                  prettyPrint,
                  requestIsBrowser,
                  narrativeMode,
                  Constants.STATUS_HTTP_200_OK,
                  theRequest.isRespondGzip(),
                  theRequest.getFhirServerBase(),
                  isAddContentLocationHeader());
            }

            break;
          }
        }
      case RESOURCE:
        {
          IBundleProvider result = (IBundleProvider) resultObj;
          if (result.size() == 0) {
            throw new ResourceNotFoundException(theRequest.getId());
          } else if (result.size() > 1) {
            throw new InternalErrorException("Method returned multiple resources");
          }

          IResource resource = result.getResources(0, 1).get(0);

          for (int i = theServer.getInterceptors().size() - 1; i >= 0; i--) {
            IServerInterceptor next = theServer.getInterceptors().get(i);
            boolean continueProcessing =
                next.outgoingResponse(
                    theRequest,
                    resource,
                    theRequest.getServletRequest(),
                    theRequest.getServletResponse());
            if (!continueProcessing) {
              return;
            }
          }

          RestfulServerUtils.streamResponseAsResource(
              theServer,
              response,
              resource,
              responseEncoding,
              prettyPrint,
              requestIsBrowser,
              narrativeMode,
              Constants.STATUS_HTTP_200_OK,
              respondGzip,
              theRequest.getFhirServerBase(),
              isAddContentLocationHeader());
          break;
        }
    }
  }