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

colesico.framework.config.codegen.ConfRegistry Maven / Gradle / Ivy

There is a newer version: 5.3.0
Show newest version
/*
 * Copyright 20014-2018 Vladlen Larionov
 *             and others as noted
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package colesico.framework.config.codegen;

import colesico.framework.assist.codegen.CodegenException;
import colesico.framework.assist.codegen.CodegenUtils;
import colesico.framework.assist.codegen.model.AnnotationElement;
import colesico.framework.assist.codegen.model.ClassElement;
import colesico.framework.config.ConfigModel;
import colesico.framework.config.ConfigPrototype;
import colesico.framework.config.Configuration;
import colesico.framework.config.Default;
import colesico.framework.ioc.Classed;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.processing.ProcessingEnvironment;
import javax.inject.Named;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Vladlen Larionov
 */
public class ConfRegistry {

    private Logger logger = LoggerFactory.getLogger(ConfRegistry.class);

    protected final ProcessingEnvironment processingEnv;
    protected final Elements elementUtils;

    protected final Map byPackageMap = new HashMap<>();

    public ConfRegistry(ProcessingEnvironment processingEnv) {
        this.processingEnv = processingEnv;
        elementUtils = processingEnv.getElementUtils();
    }

    public boolean isEmpty() {
        return byPackageMap.isEmpty();
    }

    public void clear() {
        byPackageMap.clear();
    }

    public Map getByPackageMap() {
        return byPackageMap;
    }

    protected ClassElement getConfigBaseClass(ClassElement configImplementation) {
        TypeElement superClass = configImplementation.unwrap();
        do {
            superClass = (TypeElement) ((DeclaredType) superClass.getSuperclass()).asElement();
            ConfigPrototype cpAnn = superClass.getAnnotation(ConfigPrototype.class);
            if (cpAnn != null) {
                return new ClassElement(processingEnv, superClass);
            }
        } while (!superClass.getSimpleName().toString().equals("Object"));

        throw CodegenException.of().message("Unable to determine configuration prototype for: " + configImplementation.getName()).element(configImplementation).build();
    }

    protected ConfigElement createConfigElement(ClassElement configImplementation) {

        ClassElement configPrototype = getConfigBaseClass(configImplementation);

        AnnotationElement configurationAnn = configImplementation.getAnnotation(Configuration.class);
        String rank = configurationAnn.unwrap().rank();

        AnnotationElement prototypeAnn = configPrototype.getAnnotation(ConfigPrototype.class);
        ConfigModel model = prototypeAnn.unwrap().model();
        TypeMirror targetMirror = prototypeAnn.getValueTypeMirror(a -> a.target());
        ClassElement target;
        if (targetMirror.toString().equals(Object.class.getName())) {
            target = null;
        } else {
            target = new ClassElement(processingEnv, (DeclaredType) targetMirror);
        }

        AnnotationElement defaultAnn = configImplementation.getAnnotation(Default.class);
        boolean defaultMessage;
        if (defaultAnn != null) {
            if (!ConfigModel.MESSAGE.equals(model)) {
                throw CodegenException.of().message("@" + Default.class.getSimpleName() +
                        " annotation can be applied only to " + ConfigModel.MESSAGE.name() + " configuration model").build();
            }
            defaultMessage = true;
        } else {
            defaultMessage = false;
        }

        AnnotationElement classedAnn = configImplementation.getAnnotation(Classed.class);
        TypeMirror classed;
        if (classedAnn != null) {
            classed = classedAnn.getValueTypeMirror(a -> a.value());
        } else {
            classed = null;
        }

        AnnotationElement namedAnn = configImplementation.getAnnotation(Named.class);
        String named = namedAnn == null ? null : namedAnn.unwrap().value();

        return new ConfigElement(configImplementation, configPrototype, rank, model, target, defaultMessage, classed, named);
    }

    public ConfigElement register(ClassElement configImplementation) {

        String packageName = configImplementation.getPackageName();
        ByRankMap byRankMap = byPackageMap.computeIfAbsent(packageName, k -> new ByRankMap());

        AnnotationElement configurationAnn = configImplementation.getAnnotation(Configuration.class);
        String rank = configurationAnn.unwrap().rank();
        List rankConfigs = byRankMap.computeIfAbsent(rank, k -> new ArrayList<>());


        ConfigElement configurationElement = createConfigElement(configImplementation);
        rankConfigs.add(configurationElement);

        logger.debug("Configuration " + configurationElement.getImplementation().getName() + " has been registered");
        return configurationElement;
    }

    public static class ByRankMap extends HashMap> {
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy