jeudi 31 janvier 2019

Helper method that returns a thing, or causes a return in the calling scope / context

I can't figure out how to factor out this code.

  private CompletionStage<Response<String>> foo(RequestContext rc) {

    final Optional<String> campaignIdOpt = rc.request().parameter("campaignId").filter(s -> !s.isEmpty());
    final Optional<String> creativeIdOpt = rc.request().parameter("creativeId").filter(s -> !s.isEmpty());

    Optional<Uuid> campaignIdOptOfUuid = Optional.empty();
    if (campaignIdOptOfUuid.isPresent()) {
      try {
        campaignIdOptOfUuid = Optional.of(UuidUtils.fromString(campaignIdOpt.get()));
      } catch (IllegalArgumentException e) {
        LOG.error(String.format("Invalid campaignId: %s", campaignIdOpt.get()), e);
        return CompletableFuture.completedFuture(
            Response.forStatus(Status.BAD_REQUEST.withReasonPhrase("Invalid campaignId provided.")));
      }
    }

    Optional<Uuid> creativeIdOptOfUuid = Optional.empty();
    if (creativeIdOptOfUuid.isPresent()) {
      try {
        creativeIdOptOfUuid = Optional.of(UuidUtils.fromString(creativeIdOpt.get()));
      } catch (IllegalArgumentException e) {
        LOG.error(String.format("Invalid creativeId: %s", creativeIdOpt.get()), e);
        return CompletableFuture.completedFuture(
            Response.forStatus(Status.BAD_REQUEST.withReasonPhrase("Invalid creativeId provided.")));
      }
    }

    // Simplified, do something with Uuids.
    return bar(campaignIdOptOfUuid, creativeIdOptOfUuid);
  }

Basically, we very frequently need to parse Google protobuf Uuids from a query string to pass on to another service that will find (or not find). We need to pass along an empty optional if a parameter was not set or an empty string, as both cases mean, "Don't filter by this parameter." Finally, if the string doesn't parse at all, then we want to immediately return an error 400 (Bad Request), rather than pass along a non-sense param to the service.

So, codewise, I want a utility method that

  1. takes an Optional<String>, and
  2. returns an Optional<Uuid> if present, Optional.empty() otherwise, and
  3. if an exception is thrown, return an error from the original context.

But obviously, I can't "double-return." What pattern do I use to achieve this though? I tried to create an encapsulator for both an Optional<Uuid> and a CompletionStage<Response<String>> but it was awkward. Is there some idiomatic way of doing this?

Aucun commentaire:

Enregistrer un commentaire