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

net.jbock.annotated.Item Maven / Gradle / Ivy

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

import net.jbock.common.ValidationFailure;

import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;
import java.lang.annotation.Annotation;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Supplier;

import static java.util.stream.Collectors.toList;
import static javax.lang.model.element.Modifier.PROTECTED;
import static javax.lang.model.element.Modifier.PUBLIC;
import static net.jbock.common.Suppliers.memoize;
import static net.jbock.common.TypeTool.ANNOTATION_VALUE_AS_TYPE;
import static net.jbock.common.TypeTool.AS_DECLARED;
import static net.jbock.common.TypeTool.AS_TYPE_ELEMENT;

public abstract class Item {

    private static final Set ACCESS_MODIFIERS = EnumSet.of(PUBLIC, PROTECTED);

    private final Supplier> converter = memoize(() -> {
        String canonicalName = annotation().annotationType().getCanonicalName();
        AnnotationMirror annotationMirror = method().getAnnotationMirrors().stream()
                .filter(mirror -> AS_TYPE_ELEMENT.visit(mirror.getAnnotationType().asElement())
                        .map(TypeElement::getQualifiedName)
                        .map(Name::toString)
                        .filter(canonicalName::equals)
                        .isPresent())
                .findFirst()
                .orElseThrow(AssertionError::new);
        return findConverterAttribute(annotationMirror);
    });

    private final ExecutableElement method;
    private final String enumName;

    Item(ExecutableElement method,
         String enumName) {
        this.method = method;
        this.enumName = enumName;
    }

    static Item create(
            ExecutableElement method,
            Annotation annotation,
            String enumName) {
        if (annotation instanceof net.jbock.Option) {
            return new Option(method, (net.jbock.Option) annotation, enumName);
        }
        if (annotation instanceof net.jbock.Parameter) {
            return new Parameter(method, (net.jbock.Parameter) annotation, enumName);
        }
        if (annotation instanceof net.jbock.VarargsParameter) {
            return new VarargsParameter(method, (net.jbock.VarargsParameter) annotation, enumName);
        }
        throw new AssertionError();
    }

    public abstract boolean isParameter();

    public abstract boolean isVarargsParameter();

    public abstract String paramLabel();

    public abstract Optional descriptionKey();

    public abstract List description();

    abstract Annotation annotation();

    public final ExecutableElement method() {
        return method;
    }

    final Name simpleName() {
        return method.getSimpleName();
    }

    public final List accessModifiers() {
        return method().getModifiers().stream()
                .filter(ACCESS_MODIFIERS::contains)
                .collect(toList());
    }

    private static Optional findConverterAttribute(AnnotationMirror annotationMirror) {
        Map elementValues =
                annotationMirror.getElementValues();
        return elementValues.entrySet().stream()
                .filter(e -> "converter".contentEquals(e.getKey().getSimpleName()))
                .map(Map.Entry::getValue)
                .findFirst()
                .flatMap(ANNOTATION_VALUE_AS_TYPE::visit)
                .flatMap(AS_DECLARED::visit)
                .map(DeclaredType::asElement)
                .flatMap(AS_TYPE_ELEMENT::visit)
                .filter(element -> !"java.lang.Void".contentEquals(element.getQualifiedName()));
    }

    public final Optional converter() {
        return converter.get();
    }

    public final ValidationFailure fail(String message) {
        return new ValidationFailure(message, method);
    }

    public final String enumName() {
        return enumName;
    }

    public final String methodName() {
        return method.getSimpleName().toString();
    }

    public final TypeMirror returnType() {
        return method.getReturnType();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy