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

net.jbock.convert.MappingFinder Maven / Gradle / Ivy

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

import io.jbock.javapoet.CodeBlock;
import io.jbock.simple.Inject;
import io.jbock.util.Either;
import net.jbock.annotated.Item;
import net.jbock.common.Util;
import net.jbock.common.ValidationFailure;
import net.jbock.convert.map.AutoOrEnumMapper;
import net.jbock.convert.map.ConverterValidator;
import net.jbock.convert.match.Match;
import net.jbock.convert.match.MatchFinder;
import net.jbock.processor.SourceElement;
import net.jbock.util.StringConverter;

import javax.lang.model.element.TypeElement;
import java.util.Optional;

import static io.jbock.util.Either.right;
import static javax.lang.model.element.Modifier.ABSTRACT;

public final class MappingFinder {

    private final AutoOrEnumMapper autoOrEnumMapper;
    private final ConverterValidator converterValidator;
    private final SourceElement sourceElement;
    private final Util util;
    private final MatchFinder matchFinder;

    @Inject
    public MappingFinder(
            AutoOrEnumMapper autoOrEnumMapper,
            ConverterValidator converterValidator,
            SourceElement sourceElement,
            Util util,
            MatchFinder matchFinder) {
        this.autoOrEnumMapper = autoOrEnumMapper;
        this.converterValidator = converterValidator;
        this.sourceElement = sourceElement;
        this.util = util;
        this.matchFinder = matchFinder;
    }

    public 
    Either> findMapping(M item) {
        return matchFinder.findMatch(item)
                .flatMap(this::findMappingWithMatch);
    }

    public 
    Either> findNullaryMapping(M item) {
        return matchFinder.createNullaryMatch(item)
                .map(match -> Mapping.create(
                        CodeBlock.of("$T.identity())", StringConverter.class), match, true));
    }

    private 
    Either> findMappingWithMatch(Match match) {
        return match.item().converter()
                .map(converter -> checkConverterIsInnerClass(match.item(), converter)
                        .or(() -> util.commonTypeChecks(converter))
                        .or(() -> checkNotAbstract(match.item(), converter))
                        .or(() -> checkNoTypeVars(match.item(), converter))
                        .map(failure -> failure.prepend("invalid converter class: "))
                        .>map(Either::left)
                        .orElseGet(() -> right(converter))
                        .flatMap(c -> converterValidator.findMapping(match, c)))
                .orElseGet(() -> autoOrEnumMapper.findMapping(match));
    }

    /* Left-Optional
     */
    private 
    Optional checkConverterIsInnerClass(
            M item,
            TypeElement converter) {
        boolean nested = util.getEnclosingElements(converter).contains(sourceElement.element());
        if (!nested) {
            return Optional.of(item.fail("converter of '" +
                    item.methodName() +
                    "' must be an inner class of the command class '" +
                    sourceElement.element().getSimpleName() + "'"));
        }
        return Optional.empty();
    }

    /* Left-Optional
     */
    private 
    Optional checkNotAbstract(
            M item,
            TypeElement converter) {
        if (converter.getModifiers().contains(ABSTRACT)) {
            return Optional.of(item.fail("the converter class '" +
                    converter.getSimpleName() +
                    "' may not be abstract"));
        }
        return Optional.empty();
    }

    /* Left-Optional
     */
    private 
    Optional checkNoTypeVars(
            M item,
            TypeElement converter) {
        if (!converter.getTypeParameters().isEmpty()) {
            return Optional.of(item.fail("type parameters are not allowed in the declaration of" +
                    " converter class '" +
                    converter.getSimpleName() +
                    "'"));
        }
        return Optional.empty();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy