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

com.moon.mapping.processing.ProcessUtils Maven / Gradle / Ivy

package com.moon.mapping.processing;

import com.moon.mapping.annotation.IgnoreMode;
import com.moon.mapping.annotation.MapProperty;
import com.moon.mapping.annotation.MappingFor;

import javax.lang.model.element.*;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.MirroredTypeException;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Types;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;

/**
 * @author moonsky
 */
final class ProcessUtils {

    private final static String MAPPING_FOR_CLASSNAME = MappingFor.class.getCanonicalName();
    private final static String CLASS_SUFFIX = ".class";
    private final static String TOP_CLASS = Object.class.getName();

    private ProcessUtils() {}

    private static BasicProperty ensureDetail(
        BasicDefinition definition, String name, TypeElement parsingElement, TypeElement thisElement
    ) {
        BasicProperty detail = definition.get(name);
        if (detail == null) {
            detail = new BasicProperty(name, parsingElement, thisElement);
            definition.put(name, detail);
        }
        return detail;
    }

    private static void handleMapProperty(Element element, Consumer handler) {
        MapProperty[] properties = element.getAnnotationsByType(MapProperty.class);
        for (MapProperty property : properties) {
            IgnoreMode ignore = property.ignore();
            String value = property.value();
            String format = property.format();
            String defaultValue = property.defaultValue();
            String targetCls;
            try {
                targetCls = property.target().getCanonicalName();
            } catch (MirroredTypeException mirrored) {
                targetCls = mirrored.getTypeMirror().toString();
            }
            handler.accept(new PropertyAttr(targetCls, value, format, defaultValue, ignore));
        }
    }

    private static void handleEnclosedElem(
        Set presentKeys,
        BasicDefinition definition,
        Element element,
        Map genericMap,
        TypeElement parsingElement,
        TypeElement thisElement
    ) {
        if (DetectUtils.isMemberField(element)) {
            String name = element.getSimpleName().toString();
            if (presentKeys.contains(name)) {
                return;
            }
            BasicProperty prop = ensureDetail(definition, name, parsingElement, thisElement);
            prop.setField((VariableElement) element, genericMap);
            handleMapProperty(element, attr -> definition.addFieldAttr(name, attr));
        } else if (DetectUtils.isSetterMethod(element)) {
            ExecutableElement elem = (ExecutableElement) element;
            String name = ElementUtils.toPropertyName(elem);
            if (presentKeys.contains(name)) {
                return;
            }
            BasicProperty prop = ensureDetail(definition, name, parsingElement, thisElement);
            handleMapProperty(element, attr -> definition.addSetterAttr(name, attr));
            prop.setSetter(elem, genericMap);
        } else if (DetectUtils.isGetterMethod(element)) {
            ExecutableElement elem = (ExecutableElement) element;
            String name = ElementUtils.toPropertyName(elem);
            if (presentKeys.contains(name)) {
                return;
            }
            BasicProperty prop = ensureDetail(definition, name, parsingElement, thisElement);
            handleMapProperty(element, attr -> definition.addGetterAttr(name, attr));
            prop.setGetter(elem, genericMap);
        } else if (DetectUtils.isConstructor(element)) {
            // definition.addConstructor((ExecutableElement) element);
        }
    }

    @SuppressWarnings("all")
    private static BasicDefinition parseRootPropertiesMap(final TypeElement rootElement) {
        BasicDefinition definition = new BasicDefinition(rootElement);
        Map thisGenericMap = GenericUtils.parse(rootElement);
        List elements = rootElement.getEnclosedElements();
        Set presents = new HashSet<>();
        for (Element element : CollectUtils.emptyIfNull(elements)) {
            handleEnclosedElem(presents, definition,//
                element, thisGenericMap, rootElement, rootElement);
        }
        return definition;
    }

    private static void parseSuperPropertiesMap(
        Set presentKeys, BasicDefinition definition, TypeElement thisElement, TypeElement rootElement
    ) {
        TypeMirror superclass = thisElement.getSuperclass();
        if (superclass.toString().equals(TOP_CLASS)) {
            return;
        }
        Types types = EnvUtils.getTypes();
        TypeElement superElement = ElementUtils.cast(types.asElement(superclass));
        if (superElement == null) {
            return;
        }
        Map genericModelMap = GenericUtils.parse(superclass, superElement);
        List elements = superElement.getEnclosedElements();
        for (Element element : elements) {
            handleEnclosedElem(presentKeys, definition, element, genericModelMap, superElement, rootElement);
        }
        presentKeys = new HashSet<>(definition.keySet());
        parseSuperPropertiesMap(presentKeys, definition, superElement, rootElement);
    }

    static BasicDefinition toPropertiesMap(TypeElement rootElement) {
        DetectUtils.assertRootElement(rootElement);
        BasicDefinition definition = parseRootPropertiesMap(rootElement);
        parseSuperPropertiesMap(new HashSet<>(), definition, rootElement, rootElement);
        definition.onCompleted();
        return definition;
    }

    static Collection getMappingForClasses(TypeElement element) {
        TypeMirror supportedType = EnvUtils.getUtils().getTypeElement(MAPPING_FOR_CLASSNAME).asType();
        Collection classes = new HashSet<>();
        for (AnnotationMirror mirror : element.getAnnotationMirrors()) {
            DeclaredType declaredType = mirror.getAnnotationType();
            if (!EnvUtils.getTypes().isSameType(supportedType, declaredType)) {
                continue;
            }
            for (AnnotationValue value : mirror.getElementValues().values()) {
                String[] classnames = value.getValue().toString().split(",");
                for (String classname : classnames) {
                    if (classname.endsWith(CLASS_SUFFIX)) {
                        classname = classname.substring(0, classname.length() - 6);
                    }
                    classes.add(classname);
                }
            }
        }
        return classes;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy