@Override
  public Object translateQueryParametersIntoServerArgument(
      RequestDetails theRequest, byte[] theRequestContents, BaseMethodBinding<?> theMethodBinding)
      throws InternalErrorException, InvalidRequestException {

    List<QualifiedParamList> paramList = new ArrayList<QualifiedParamList>();
    String name = getName();
    parseParams(theRequest, paramList, name, null);

    List<String> qualified = theRequest.getUnqualifiedToQualifiedNames().get(name);
    if (qualified != null) {
      for (String nextQualified : qualified) {
        parseParams(theRequest, paramList, nextQualified, nextQualified.substring(name.length()));
      }
    }

    if (paramList.isEmpty()) {

      ourLog.debug(
          "No value for parameter '{}' - Qualified names {} and qualifier whitelist {}",
          getName(),
          qualified,
          getQualifierWhitelist());

      if (handlesMissing()) {
        return parse(theRequest.getServer().getFhirContext(), paramList);
      } else {
        return null;
      }
    }

    return parse(theRequest.getServer().getFhirContext(), paramList);
  }
  @Override
  public Verdict applyRule(
      RestOperationTypeEnum theOperation,
      RequestDetails theRequestDetails,
      IBaseResource theInputResource,
      IIdType theInputResourceId,
      IBaseResource theOutputResource,
      IRuleApplier theRuleApplier) {

    if (theInputResourceId != null) {
      return null;
    }

    if (theOperation == myOperationType) {
      switch (myAppliesTo) {
        case ALL_RESOURCES:
          break;
        case TYPES:
          if (theInputResource == null || !myAppliesToTypes.contains(theInputResource.getClass())) {
            return null;
          }
          break;
      }

      if (theRequestDetails.getConditionalUrl(myOperationType) == null) {
        return null;
      }

      return newVerdict();
    }

    return null;
  }
  private void parseParams(
      RequestDetails theRequest,
      List<QualifiedParamList> paramList,
      String theQualifiedParamName,
      String theQualifier) {
    QualifierDetails qualifiers =
        SearchMethodBinding.extractQualifiersFromParameterName(theQualifier);
    if (!qualifiers.passes(getQualifierWhitelist(), getQualifierBlacklist())) {
      return;
    }

    String[] value = theRequest.getParameters().get(theQualifiedParamName);
    if (value != null) {
      for (String nextParam : value) {
        if (nextParam.contains(",") == false) {
          paramList.add(QualifiedParamList.singleton(theQualifier, nextParam));
        } else {
          paramList.add(
              QualifiedParamList.splitQueryStringByCommasIgnoreEscape(theQualifier, nextParam));
        }
      }
    }
  }
  @Override
  public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
    String authHeader = theRequestDetails.getHeader("Authorization");

    // @formatter:off
    if (isBlank(authHeader)) {
      return new RuleBuilder()
          .deny()
          .operation()
          .named(BaseJpaSystemProvider.MARK_ALL_RESOURCES_FOR_REINDEXING)
          .onServer()
          .andThen()
          .deny()
          .operation()
          .named(TerminologyUploaderProviderDstu3.UPLOAD_EXTERNAL_CODE_SYSTEM)
          .onServer()
          .andThen()
          .allowAll()
          .build();
    }
    // @formatter:off

    if (!authHeader.startsWith("Bearer ")) {
      throw new ForbiddenOperationException(
          "Invalid bearer token, must be in the form \"Authorization: Bearer [token]\"");
    }

    String token = authHeader.substring("Bearer ".length()).trim();
    if (!myTokens.contains(token)) {
      ourLog.error("Invalid token '{}' - Valid are: {}", token, myTokens);
      throw new ForbiddenOperationException("Unknown/expired bearer token");
    }

    ourLog.info("User logged in with bearer token: " + token.substring(0, 4) + "...");

    return new RuleBuilder().allowAll().build();
  }
    @Override
    public String lookup(String theKey) {

      /*
       * TODO: this method could be made more efficient through some sort of lookup map
       */

      if ("operationType".equals(theKey)) {
        if (myRequestDetails.getRestOperationType() != null) {
          return myRequestDetails.getRestOperationType().getCode();
        }
        return "";
      } else if ("operationName".equals(theKey)) {
        if (myRequestDetails.getRestOperationType() != null) {
          switch (myRequestDetails.getRestOperationType()) {
            case EXTENDED_OPERATION_INSTANCE:
            case EXTENDED_OPERATION_SERVER:
            case EXTENDED_OPERATION_TYPE:
              return myRequestDetails.getOperation();
            default:
              return "";
          }
        } else {
          return "";
        }
      } else if ("id".equals(theKey)) {
        if (myRequestDetails.getId() != null) {
          return myRequestDetails.getId().getValue();
        }
        return "";
      } else if ("servletPath".equals(theKey)) {
        return StringUtils.defaultString(myRequest.getServletPath());
      } else if ("idOrResourceName".equals(theKey)) {
        if (myRequestDetails.getId() != null) {
          return myRequestDetails.getId().getValue();
        }
        if (myRequestDetails.getResourceName() != null) {
          return myRequestDetails.getResourceName();
        }
        return "";
      } else if (theKey.equals("requestParameters")) {
        StringBuilder b = new StringBuilder();
        for (Entry<String, String[]> next : myRequestDetails.getParameters().entrySet()) {
          for (String nextValue : next.getValue()) {
            if (b.length() == 0) {
              b.append('?');
            } else {
              b.append('&');
            }
            try {
              b.append(URLEncoder.encode(next.getKey(), "UTF-8"));
              b.append('=');
              b.append(URLEncoder.encode(nextValue, "UTF-8"));
            } catch (UnsupportedEncodingException e) {
              throw new ca.uhn.fhir.context.ConfigurationException("UTF-8 not supported", e);
            }
          }
        }
        return b.toString();
      } else if (theKey.startsWith("requestHeader.")) {
        String val = myRequest.getHeader(theKey.substring("requestHeader.".length()));
        return StringUtils.defaultString(val);
      } else if (theKey.startsWith("remoteAddr")) {
        return StringUtils.defaultString(myRequest.getRemoteAddr());
      } else if (theKey.equals("responseEncodingNoDefault")) {
        EncodingEnum encoding =
            RestfulServerUtils.determineResponseEncodingNoDefault(
                myRequestDetails, myRequestDetails.getServer().getDefaultResponseEncoding());
        if (encoding != null) {
          return encoding.name();
        } else {
          return "";
        }
      } else if (theKey.equals("exceptionMessage")) {
        return myException != null ? myException.getMessage() : null;
      } else if (theKey.equals("requestUrl")) {
        return myRequest.getRequestURL().toString();
      } else if (theKey.equals("requestVerb")) {
        return myRequest.getMethod();
      } else if (theKey.equals("requestBodyFhir")) {
        String contentType = myRequest.getContentType();
        if (isNotBlank(contentType)) {
          int colonIndex = contentType.indexOf(';');
          if (colonIndex != -1) {
            contentType = contentType.substring(0, colonIndex);
          }
          contentType = contentType.trim();

          EncodingEnum encoding = EncodingEnum.forContentType(contentType);
          if (encoding != null) {
            byte[] requestContents = myRequestDetails.loadRequestContents();
            return new String(requestContents, Charsets.UTF_8);
          }
        }
        return "";
      }

      return "!VAL!";
    }