private Optional attemptResolveSpec()

in legacy/java/piranha/src/main/java/com/uber/piranha/testannotations/TestAnnotationResolver.java [110:202]


  private Optional<ResolvedTestAnnotation> attemptResolveSpec(
      TestAnnotationSpecRecord spec, AnnotationTree at, Tree parent, VisitorState state) {
    if (!at.getAnnotationType().toString().contains(spec.getAnnotationName())) {
      // For sanity, attempting to resolve an annotation with a spec without the same name will
      // always return empty.
      return Optional.empty();
    }
    final ImmutableMultimap<String, AnnotationArgument> fields = parseAnnotationArguments(at);
    Set<String> relevantFieldParsingErrors = new HashSet<String>();
    // Process flag id(s)
    ImmutableList.Builder<AnnotationArgument> flagIdsBuilder = ImmutableList.builder();
    String flagIdentifierOrField = spec.getFlagIdentifierOrField();
    if (TestAnnotationSpecRecord.isFieldReference(flagIdentifierOrField)) {
      // Annotation field reference
      if (!fields.containsKey(flagIdentifierOrField)) {
        // Annotation does not match the spec. That's fine, maybe another spec with the same name
        // does, let's wait until we have seen if that isn't the case before reporting an error.
        return Optional.empty();
      }
      for (AnnotationArgument argument : fields.get(flagIdentifierOrField)) {
        if (argument.getValue().equals(UNPARSED_FIELD_VALUE)) {
          // There is an error parsing the value of this field, let's wait to see if the rest of the
          // annotation matches the specification's shape before we report that as an error.
          relevantFieldParsingErrors.add(
              String.format(
                  "Field %s is not of a type which can be parsed to a flag or list of flags.",
                  flagIdentifierOrField));
        }
        flagIdsBuilder.add(argument);
      }
    } else {
      // constant flag name
      flagIdsBuilder.add(new AnnotationArgument(flagIdentifierOrField, null));
    }
    // Process flag treatment value
    boolean treated = false;
    String treatedValueOrField = spec.getTreatedValueOrField();
    if (TestAnnotationSpecRecord.isFieldReference(treatedValueOrField)) {
      if (!fields.containsKey(treatedValueOrField)) {
        // Annotation does not match the spec. That's fine, maybe another spec with the same name
        // does.
        return Optional.empty();
      } else if (fields.get(treatedValueOrField).size() != 1) {
        relevantFieldParsingErrors.add(
            String.format(
                "Field %s is not valid for specifying the treatment condition. Expected single "
                    + "boolean (or string encoding boolean) value.",
                treatedValueOrField));
      }
      AnnotationArgument argument = fields.get(treatedValueOrField).asList().get(0);
      if (TRUE_STR.equalsIgnoreCase(argument.getValue())) {
        treated = true;
      } else if (FALSE_STR.equalsIgnoreCase(argument.getValue())) {
        treated = false;
      } else {
        relevantFieldParsingErrors.add(
            String.format(
                "Field %s is not valid for specifying the treatment condition. Expected a "
                    + "boolean (or string encoding boolean) value.",
                treatedValueOrField));
      }
    } else {
      // Only 'true' or 'false' are possible at this point, due to parsing logic
      Preconditions.checkArgument(
          TRUE_STR.equalsIgnoreCase(treatedValueOrField)
              || FALSE_STR.equalsIgnoreCase(treatedValueOrField));
      treated = TRUE_STR.equalsIgnoreCase(treatedValueOrField);
    }
    // Process treatment group, if any
    ImmutableList.Builder<AnnotationArgument> groupsBuilder = ImmutableList.builder();
    Optional<String> groupValueOrField = spec.getGroupValueOrField();
    if (groupValueOrField.isPresent()) {
      // ToDo: implement
      throw new UnsupportedOperationException(
          "Treatment group information in test annotations not yet supported");
    }
    if (!relevantFieldParsingErrors.isEmpty()) {
      throw new AnnotationResolutionException(
          String.format(
              "Found annotation %s at %s, matching the shape of the test annotation "
                  + "specification `%s` from Piranha's configuration file. However, one or more errors "
                  + "occurred when parsing the annotation's fields:\n\t* %s",
              state.getSourceForNode(at),
              ASTHelpers.getSymbol(parent).flatName().toString(),
              spec,
              relevantFieldParsingErrors
                  .stream()
                  .map(a -> a.toString())
                  .collect(Collectors.joining("\n\t* "))));
    }
    return Optional.of(
        new ResolvedTestAnnotation(flagIdsBuilder.build(), treated, groupsBuilder.build(), at));
  }