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

net.jbock.convert.reference.ReferenceTool Maven / Gradle / Ivy

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

import io.jbock.util.Either;
import net.jbock.annotated.AnnotatedMethod;
import net.jbock.common.TypeTool;
import net.jbock.common.ValidationFailure;
import net.jbock.util.StringConverter;
import net.jbock.validate.ValidateScope;

import javax.inject.Inject;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;
import java.util.Optional;
import java.util.function.Supplier;

import static io.jbock.util.Either.left;
import static io.jbock.util.Either.right;
import static net.jbock.common.TypeTool.AS_DECLARED;

@ValidateScope
public class ReferenceTool {

    private final TypeTool tool;

    @Inject
    ReferenceTool(TypeTool tool) {
        this.tool = tool;
    }

    public 
    Either getReferencedType(
            M sourceMethod,
            TypeElement converter) {
        Optional supplier = checkSupplier(converter);
        Optional stringConverter = checkStringConverter(converter);
        if (supplier.isPresent() && stringConverter.isPresent()) {
            return left(sourceMethod.fail(errorConverterType() + " but not both"));
        }
        return supplier.map(declaredType -> handleSupplier(sourceMethod, declaredType))
                .or(() -> stringConverter.map(stringConverterType ->
                        handleStringConverter(sourceMethod, stringConverterType, false)))
                .orElseGet(() -> left(sourceMethod.fail(errorConverterType())));
    }

    private 
    Either handleSupplier(
            M sourceMethod,
            DeclaredType declaredType) {
        if (declaredType.getTypeArguments().size() != 1) {
            return left(sourceMethod.fail(converterRawType()));
        }
        TypeMirror typeArgument = declaredType.getTypeArguments().get(0);
        return AS_DECLARED.visit(typeArgument)
                .filter(suppliedFunction -> tool.isSameErasure(suppliedFunction,
                        StringConverter.class))
                .>map(Either::right)
                .orElseGet(() -> left(sourceMethod.fail(errorConverterType())))
                .flatMap(suppliedType -> handleStringConverter(sourceMethod, suppliedType, true));
    }

    private 
    Either handleStringConverter(
            M parameter,
            DeclaredType declaredType,
            boolean isSupplier) {
        if (declaredType.getTypeArguments().size() != 1) {
            return left(parameter.fail(converterRawType()));
        }
        TypeMirror typeArgument = declaredType.getTypeArguments().get(0);
        return right(new StringConverterType(typeArgument, isSupplier));
    }

    private Optional checkSupplier(TypeElement converter) {
        return converter.getInterfaces().stream()
                .filter(inter -> tool.isSameErasure(inter, Supplier.class))
                .map(AS_DECLARED::visit)
                .flatMap(Optional::stream)
                .findFirst();
    }

    private Optional checkStringConverter(TypeElement converter) {
        return Optional.of(converter.getSuperclass())
                .filter(inter -> tool.isSameErasure(inter, StringConverter.class))
                .flatMap(AS_DECLARED::visit);
    }

    private String errorConverterType() {
        return "converter must extend " + StringConverter.class.getSimpleName() +
                " or implement " + Supplier.class.getSimpleName() +
                "<" + StringConverter.class.getSimpleName() + ">";
    }

    private String converterRawType() {
        return "raw type in converter class";
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy