All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.jbock.convert.matching.MatchFinder Maven / Gradle / Ivy

There is a newer version: 5.18
Show newest version
package net.jbock.convert.matching;

import io.jbock.util.Either;
import net.jbock.Option;
import net.jbock.Parameters;
import net.jbock.annotated.AnnotatedMethod;
import net.jbock.annotated.AnnotatedOption;
import net.jbock.common.ValidationFailure;
import net.jbock.convert.matcher.ListMatcher;
import net.jbock.convert.matcher.OptionalMatcher;
import net.jbock.model.Multiplicity;
import net.jbock.validate.ValidateScope;

import javax.inject.Inject;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.PrimitiveType;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Types;
import java.util.List;
import java.util.Optional;

import static io.jbock.util.Either.left;
import static io.jbock.util.Either.right;
import static javax.lang.model.type.TypeKind.BOOLEAN;
import static net.jbock.common.TypeTool.AS_PRIMITIVE;
import static net.jbock.model.Multiplicity.OPTIONAL;

@ValidateScope
public class MatchFinder {

    private final OptionalMatcher optionalMatcher;
    private final ListMatcher listMatcher;
    private final Types types;

    @Inject
    MatchFinder(
            OptionalMatcher optionalMatcher,
            ListMatcher listMatcher,
            Types types) {
        this.optionalMatcher = optionalMatcher;
        this.listMatcher = listMatcher;
        this.types = types;
    }

    public 
    Either> findMatch(
            M sourceMethod) {
        return validateMatch(findMatchInternal(sourceMethod));
    }

    public Either>
    findFlagMatch(
            AnnotatedOption sourceMethod) {
        PrimitiveType bool = types.getPrimitiveType(BOOLEAN);
        Match match = Match.create(bool, OPTIONAL, sourceMethod);
        return validateMatch(match);
    }

    private  Match
    findMatchInternal(
            M sourceMethod) {
        return List.of(optionalMatcher, listMatcher).stream()
                .map(matcher -> matcher.tryMatch(sourceMethod))
                .flatMap(Optional::stream)
                .findFirst()
                .orElseGet(() -> {
                    TypeMirror baseType = AS_PRIMITIVE.visit(sourceMethod.returnType())
                            .map(types::boxedClass)
                            .map(TypeElement::asType)
                            .orElse(sourceMethod.returnType());
                    return Match.create(baseType, Multiplicity.REQUIRED, sourceMethod);
                });
    }

    private static 
    Either> validateMatch(
            Match match) {
        M sourceMethod = match.sourceMethod();
        if (sourceMethod.isParameter()
                && match.multiplicity() == Multiplicity.REPEATABLE) {
            return left(sourceMethod.fail("method '" +
                    sourceMethod.method().getSimpleName() +
                    "' returns a list-based type, so it must be annotated with @" +
                    Option.class.getSimpleName() +
                    " or @" +
                    Parameters.class.getSimpleName()));
        }
        if (sourceMethod.isParameters()
                && match.multiplicity() != Multiplicity.REPEATABLE) {
            return left(sourceMethod.fail("method '" +
                    sourceMethod.method().getSimpleName() +
                    "' is annotated with @" +
                    Parameters.class.getSimpleName() +
                    ", so it must return java.util.List"));
        }
        return right(new ValidMatch<>(match));
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy