0

I just got into java annotation processing and I wanted to create an annotation that does a similar job to @Value. I already created the annotation and annotation processor. so is there a way to inject the value from the process method? or am i going in the wrong direction? here is my annotation and processor

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomValue {
    String value();
}
import com.google.auto.service.AutoService;
import report.configurations.PropertyLoader;

import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.tools.*;
import java.io.File;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.Collections;
import java.util.Map;
import java.util.Set;

@SupportedAnnotationTypes("report.annotations.CustomValue")
@SupportedSourceVersion(SourceVersion.RELEASE_17)
@AutoService(javax.annotation.processing.Processor.class)
public class  CustomValueProcessor extends AbstractProcessor {

    private Messager messager;
    private Map<String, String> PropMap = PropertyLoader.parsePropertiesFile();

    @Override
    public synchronized void init(ProcessingEnvironment processingEnv) {
        super.init(processingEnv);
        messager = processingEnv.getMessager();

        // Retrieve the property name from options
    }

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        for (TypeElement annotation : annotations) {
            for (Element element : roundEnv.getElementsAnnotatedWith(annotation)) {
                if (element.getKind() == ElementKind.FIELD) {
                    CustomValue annotationValue = element.getAnnotation(CustomValue.class);
                    String paramName = annotationValue.value();
                    String newParaName = paramName.substring(2, paramName.length() - 1);
                    messager.printMessage(Diagnostic.Kind.NOTE, "Injecting: " + newParaName);

                    String propertyValue = PropMap.get(newParaName);
                    messager.printMessage(Diagnostic.Kind.NOTE, "Injecting: " + propertyValue);

                    if (element instanceof VariableElement) {
                        VariableElement variableElement = (VariableElement) element;
                        generateAndExecuteCode(variableElement, propertyValue);
                    }
                }
            }
        }
        return true;
    }

    private void generateAndExecuteCode(VariableElement variableElement, String propertyValue) {
        String fieldName = variableElement.getSimpleName().toString();
        String setterMethodName = "set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);

        String setterCode = String.format("%s.%s(\"%s\");", variableElement.getEnclosingElement(), setterMethodName, propertyValue);

        try {
            String generatedClassName = "GeneratedCode";
            String javaSourceCode = "public class " + generatedClassName + " {\n"
                    + "    public static void run() {\n"
                    + "        " + setterCode + "\n"
                    + "    }\n"
                    + "}\n";

            // Obtain a Filer instance
            Filer filer = processingEnv.getFiler();

            JavaFileObject sourceFileObject = filer.createSourceFile(generatedClassName);
            try (Writer writer = sourceFileObject.openWriter()) {
                writer.write(javaSourceCode);
            }

            File sourceFile = new File(".", generatedClassName + ".java");
            try (PrintWriter writer = new PrintWriter(sourceFile)) {
                writer.write(javaSourceCode);
            }

            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
            Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(Collections.singletonList(sourceFile));
            compiler.getTask(null, fileManager, null, null, null, compilationUnits).call();

            // Load and execute the compiled class
            Class<?> generatedClass = Class.forName(generatedClassName);
            generatedClass.getMethod("run").invoke(null);

            // Cleanup: Delete the temporary source file
            sourceFile.delete();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

I tried to generated a file to inject it at compile time but I suppose that`s not the right way to do it

0 Answers0