ProcessorEnvironment.java

/*
 * SPDX-FileCopyrightText: 2025 kaumei.io
 * SPDX-License-Identifier: Apache-2.0
 */
package io.kaumei.jdbc.anno;

import io.kaumei.jdbc.anno.ctx.ConfigService;
import io.kaumei.jdbc.anno.ctx.Context;
import io.kaumei.jdbc.anno.ctx.JavaMessenger;
import io.kaumei.jdbc.annotation.JdbcBatchUpdate;
import io.kaumei.jdbc.annotation.JdbcNative;
import io.kaumei.jdbc.annotation.JdbcSelect;
import io.kaumei.jdbc.annotation.JdbcUpdate;
import io.kaumei.jdbc.annotation.config.JdbcConfig;

import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import java.util.HashSet;
import java.util.Set;

import static java.util.Objects.requireNonNull;

public final class ProcessorEnvironment {

    // ----- services
    private final JavaMessenger logger;

    private final Set<? extends Element> jdbcConfig;
    private final ConfigService jdbcConfigService;
    private final Set<TypeElement> jdbcInterfaces;

    public ProcessorEnvironment(Context ctx, Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        this.logger = requireNonNull(ctx.logger);
        this.jdbcConfigService = requireNonNull(ctx.kaumeiConfig);
        var rootElements = roundEnv.getRootElements();
        this.jdbcConfig = roundEnv.getElementsAnnotatedWith(JdbcConfig.class);
        this.jdbcInterfaces = new HashSet<>();
        var jdbcNative = updateJdbcInterfaces(roundEnv.getElementsAnnotatedWith(JdbcNative.class));
        var jdbcSelect = updateJdbcInterfaces(roundEnv.getElementsAnnotatedWith(JdbcSelect.class));
        var jdbcUpdate = updateJdbcInterfaces(roundEnv.getElementsAnnotatedWith(JdbcUpdate.class));
        var jdbcBatchUpdate = updateJdbcInterfaces(roundEnv.getElementsAnnotatedWith(JdbcBatchUpdate.class));

        if (logger.isDebugEnabled()) {
            logger.debug("annotations....", annotations);
            logger.debug("rootElements...", rootElements);
            logger.debug("jdbcNative.....", jdbcNative);
            logger.debug("jdbcSelect.....", jdbcSelect);
            logger.debug("jdbcUpdate.....", jdbcUpdate);
            logger.debug("jdbcBatchUpdate", jdbcBatchUpdate);
            logger.debug("jdbcInterfaces.", jdbcInterfaces);
        } else {
            logger.always("Kaumei JDBC input annotation types.", annotations);
            logger.always("Kaumei JDBC found annotations.", "rootElements", rootElements.size(),
                    "jdbcNative", jdbcNative.size(),
                    "jdbcSelect", jdbcSelect.size(),
                    "jdbcUpdate", jdbcUpdate.size(),
                    "jdbcBatchUpdate", jdbcBatchUpdate.size(),
                    "jdbcInterfaces", jdbcInterfaces.size());
        }
    }

    private Set<ExecutableElement> updateJdbcInterfaces(Set<? extends Element> elements) {
        var methods = new HashSet<ExecutableElement>();
        for (Element elem : elements) {
            if (elem.getKind() != ElementKind.METHOD || !(elem instanceof ExecutableElement method)) {
                logger.warn(elem, "Skip element, because it is not a method.");
                continue;
            }
            var enclosing = method.getEnclosingElement();
            if (enclosing.getKind() != ElementKind.INTERFACE
                    || !(enclosing instanceof TypeElement iface)) {
                logger.warn(method, "Skip method, because it is not a member of an interface.");
                continue;
            }
            methods.add(method);
            jdbcInterfaces.add(iface);
        }
        return methods;
    }

    public Set<? extends Element> jdbcConfig() {
        return this.jdbcConfig;
    }

    public Set<ExecutableElement> jdbcToJava() {
        return jdbcConfigService.jdbcToJava();
    }

    public Set<ExecutableElement> javaToJdbc() {
        return jdbcConfigService.javaToJdbc();
    }

    public Set<TypeElement> jdbcInterfaces() {
        return this.jdbcInterfaces;
    }

}