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

org.dominokit.domino.apt.commons.ProcessorUtil Maven / Gradle / Ivy

package org.dominokit.domino.apt.commons;

import com.squareup.javapoet.TypeName;

import javax.annotation.processing.Filer;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.*;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import java.lang.annotation.Annotation;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static java.util.Objects.isNull;
import static java.util.Objects.nonNull;

public class ProcessorUtil {
    private static final int FIRST_ARGUMENT = 0;
    private static final int SECOND_ARGUMENT = 1;

    protected final Messager messager;
    protected final Filer filer;
    protected final Types types;
    protected final Elements elements;
    protected final ProcessingEnvironment processingEnv;

    public ProcessorUtil(ProcessingEnvironment processingEnv) {
        this.messager = processingEnv.getMessager();
        this.filer = processingEnv.getFiler();
        this.types = processingEnv.getTypeUtils();
        this.elements = processingEnv.getElementUtils();
        this.processingEnv = processingEnv;
    }

    public Messager getMessager() {
        return messager;
    }

    public Types getTypes() {
        return types;
    }

    public Elements getElements() {
        return elements;
    }

    public List getAnnotatedMethods(TypeMirror beanType, Class annotation) {
        return getAnnotatedElements(beanType, annotation, element -> ElementKind.METHOD.equals(element.getKind()));
    }

    public List getAnnotatedFields(TypeMirror beanType, Class annotation) {
        return getAnnotatedElements(beanType, annotation, element -> ElementKind.FIELD.equals(element.getKind()));
    }

    public List getAnnotatedElements(TypeMirror beanType, Class annotation, Function filter) {
        TypeElement typeElement = (TypeElement) types.asElement(beanType);

        final List methods = new ArrayList<>();

        List annotatedMethods = getAnnotatedElements(typeElement, annotation, filter);
        methods.addAll(annotatedMethods);

        return methods;
    }

    public List getAnnotatedElements(TypeElement typeElement, Class annotation, Function filter) {
        TypeMirror superclass = typeElement.getSuperclass();
        if (superclass.getKind().equals(TypeKind.NONE)) {
            return new ArrayList<>();
        }

        List methods = typeElement.getEnclosedElements()
                .stream()
                .filter(filter::apply)
                .filter(element -> nonNull(element.getAnnotation(annotation)))
                .collect(Collectors.toList());

        methods.addAll(getAnnotatedElements((TypeElement) types.asElement(superclass), annotation, filter));
        return methods;
    }

    public Optional findTypeArgument(TypeMirror element, Class targetClass) {
        if (element.getKind().equals(TypeKind.NONE)) {
            return Optional.empty();
        }

        DeclaredType elementType = (DeclaredType) element;
        List typeArguments = elementType.getTypeArguments();
        for (TypeMirror type : typeArguments) {
            if (isAssignableFrom(type, targetClass)) {
                return Optional.of(type);
            }
        }


        TypeElement typeElement = (TypeElement) types.asElement(element);

        List interfaces = typeElement.getInterfaces();
        for (TypeMirror interfaceType : interfaces) {
            List interfaceTypeArguments = ((DeclaredType) interfaceType).getTypeArguments();
            for (TypeMirror type : interfaceTypeArguments) {
                if (isAssignableFrom(type, targetClass)) {
                    return Optional.of(type);
                }
            }
        }
        return findTypeArgument(typeElement.getSuperclass(), targetClass);
    }

    public String capitalizeFirstLetter(String input) {
        return input.substring(0, 1).toUpperCase() + input.substring(1);
    }

    public String smallFirstLetter(String input) {
        return input.substring(0, 1).toLowerCase() + input.substring(1);
    }

    public String lowerFirstLetter(String input) {
        return input.substring(0, 1).toLowerCase() + input.substring(1);
    }

    public boolean isAssignableFrom(Element element, Class targetClass) {
        return types.isAssignable(element.asType(), types.getDeclaredType(elements.getTypeElement(targetClass.getCanonicalName())));
    }

    public boolean isAssignableFrom(TypeMirror element, Class targetClass) {
        return types.isAssignable(element, types.getDeclaredType(elements.getTypeElement(targetClass.getCanonicalName())));
    }

    public  A findClassAnnotation(Element classElement, Class annotation){
        A result = classElement.getAnnotation(annotation);
        if(nonNull(result)){
            return result;
        }
        TypeMirror superclass = ((TypeElement) classElement).getSuperclass();
        if (superclass.getKind().equals(TypeKind.NONE)) {
            return null;
        } else {
            return findClassAnnotation(types.asElement(superclass), annotation);
        }
    }


    public Optional findClassValueFromClassAnnotation(Element classElement, Class annotation, String paramName){
        Optional result = getClassValueFromAnnotation(classElement, annotation, paramName);
        if(result.isPresent()){
            return result;
        }
        TypeMirror superclass = ((TypeElement) classElement).getSuperclass();
        if (superclass.getKind().equals(TypeKind.NONE)) {
            return Optional.empty();
        } else {
            return findClassValueFromClassAnnotation(types.asElement(superclass), annotation,paramName);
        }
    }

    public Optional getClassValueFromAnnotation(Element element, Class annotation, String paramName) {
        for (AnnotationMirror am : element.getAnnotationMirrors()) {
            if (types.isSameType(am.getAnnotationType(), elements.getTypeElement(annotation.getCanonicalName()).asType())) {
                for (Map.Entry entry : am.getElementValues().entrySet()) {
                    if (paramName.equals(entry.getKey().getSimpleName().toString())) {
                        AnnotationValue annotationValue = entry.getValue();
                        return Optional.of((DeclaredType) annotationValue.getValue());
                    }
                }
            }
        }
        return Optional.empty();
    }


    public List getClassArrayValueFromAnnotation(Element element, Class annotation, String paramName) {

        List values = new ArrayList<>();

        for (AnnotationMirror am : element.getAnnotationMirrors()) {
            if (types.isSameType(am.getAnnotationType(), elements.getTypeElement(annotation.getCanonicalName()).asType())) {
                for (Map.Entry entry : am.getElementValues().entrySet()) {
                    if (paramName.equals(entry.getKey().getSimpleName().toString())) {
                        List classesTypes = (List) entry.getValue().getValue();
                        Iterator iterator = classesTypes.iterator();

                        while (iterator.hasNext()) {
                            AnnotationValue next = iterator.next();
                            values.add((TypeMirror) next.getValue());
                        }
                    }
                }
            }
        }
        return values;
    }


    public List getElementMethods(Element element) {
        return element.getEnclosedElements()
                .stream()
                .filter(e -> e.getKind() == ElementKind.METHOD)
                .map(e -> (ExecutableElement) e)
                .collect(Collectors.toList());
    }

    public boolean isStringType(TypeMirror typeMirror) {
        TypeMirror stringType = elements.getTypeElement("java.lang.String").asType();
        return types.isAssignable(stringType, typeMirror);
    }

    /**
     * 

wrapperType.

* * @param type a {@link TypeMirror} object. * @return a {@link TypeName} object. */ public TypeName wrapperType(TypeMirror type) { if (isPrimitive(type)) { if ("boolean".equals(type.toString())) { return TypeName.get(Boolean.class); } else if ("byte".equals(type.toString())) { return TypeName.get(Byte.class); } else if ("short".equals(type.toString())) { return TypeName.get(Short.class); } else if ("int".equals(type.toString())) { return TypeName.get(Integer.class); } else if ("long".equals(type.toString())) { return TypeName.get(Long.class); } else if ("char".equals(type.toString())) { return TypeName.get(Character.class); } else if ("float".equals(type.toString())) { return TypeName.get(Float.class); } else if ("double".equals(type.toString())) { return TypeName.get(Double.class); } else { return TypeName.get(Void.class); } } else { return TypeName.get(type); } } public boolean isPrimitive(TypeMirror typeMirror) { return typeMirror.getKind().isPrimitive(); } /** *

isPrimitiveArray.

* * @param typeMirror a {@link TypeMirror} object. * @return a boolean. */ public boolean isPrimitiveArray(TypeMirror typeMirror) { return (isArray(typeMirror) && isPrimitive(arrayComponentType(typeMirror))) || isPrimitive2dArray(typeMirror); } private boolean isPrimitive2dArray(TypeMirror typeMirror) { return is2dArray(typeMirror) && isPrimitiveArray(arrayComponentType(typeMirror)); } /** *

isArray.

* * @param typeMirror a {@link TypeMirror} object. * @return a boolean. */ public boolean isArray(TypeMirror typeMirror) { return TypeKind.ARRAY.compareTo(typeMirror.getKind()) == 0; } /** *

is2dArray.

* * @param typeMirror a {@link TypeMirror} object. * @return a boolean. */ public boolean is2dArray(TypeMirror typeMirror) { return isArray(typeMirror) && isArray(arrayComponentType(typeMirror)); } /** *

arrayComponentType.

* * @param typeMirror a {@link TypeMirror} object. * @return a {@link TypeMirror} object. */ public TypeMirror arrayComponentType(TypeMirror typeMirror) { return ((ArrayType) typeMirror).getComponentType(); } /** *

deepArrayComponentType.

* * @param typeMirror a {@link TypeMirror} object. * @return a {@link TypeMirror} object. */ public TypeMirror deepArrayComponentType(TypeMirror typeMirror) { TypeMirror type = ((ArrayType) typeMirror).getComponentType(); return isArray(type) ? arrayComponentType(type) : type; } /** *

isEnum.

* * @param typeMirror a {@link TypeMirror} object. * @return a boolean. */ public boolean isEnum(TypeMirror typeMirror) { return !isNull(types.asElement(typeMirror)) && !isPrimitive(typeMirror) && !isPrimitiveArray(typeMirror) && ElementKind.ENUM.compareTo(types.asElement(typeMirror).getKind()) == 0; } /** *

isCollection.

* * @param typeMirror a {@link TypeMirror} object. * @return a boolean. */ public boolean isCollection(TypeMirror typeMirror) { return !isPrimitive(typeMirror) && isAssignableFrom(typeMirror, Collection.class); } /** *

isIterable.

* * @param typeMirror a {@link TypeMirror} object. * @return a boolean. */ public boolean isIterable(TypeMirror typeMirror) { return !isPrimitive(typeMirror) && isAssignableFrom(typeMirror, Iterable.class); } /** *

isMap.

* * @param typeMirror a {@link TypeMirror} object. * @return a boolean. */ public boolean isMap(TypeMirror typeMirror) { return !isPrimitive(typeMirror) && isAssignableFrom(typeMirror, Map.class); } /** *

firstTypeArgument.

* * @param typeMirror a {@link TypeMirror} object. * @return a {@link TypeMirror} object. */ public TypeMirror firstTypeArgument(TypeMirror typeMirror) { return ((DeclaredType) typeMirror).getTypeArguments().get(FIRST_ARGUMENT); } /** *

secondTypeArgument.

* * @param typeMirror a {@link TypeMirror} object. * @return a {@link TypeMirror} object. */ public TypeMirror secondTypeArgument(TypeMirror typeMirror) { return ((DeclaredType) typeMirror).getTypeArguments().get(SECOND_ARGUMENT); } /** *

getPackage.

* * @param typeMirror a {@link TypeMirror} object. * @return a {@link String} object. */ public String getPackage(TypeMirror typeMirror) { return elements.getPackageOf(types.asElement(typeMirror)).getSimpleName().toString(); } /** *

simpleName.

* * @param typeMirror a {@link TypeMirror} object. * @return a {@link Name} object. */ public Name simpleName(TypeMirror typeMirror) { return types.asElement(typeMirror).getSimpleName(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy