From 204740ca8b46107376631ba6f35042f37d7e1a10 Mon Sep 17 00:00:00 2001 From: Markus Kreth Date: Sat, 20 Aug 2022 18:15:51 +0200 Subject: [PATCH] different Format Templates --- .../de/kreth/property2java/Configuration.java | 5 ++ .../de/kreth/property2java/Generator.java | 11 ++- .../config/FreemarkerConfig.java | 35 ++++++--- .../kreth/property2java/processor/Format.java | 9 +++ .../GenerateResourceBundleProperty2Java.java | 46 +++++++++++ .../GenerateResourceBundleProperty2Javas.java | 21 +++++ .../processor/ProcessorConfiguration.java | 23 ++++-- .../processor/Property2JavaGenerator.java | 77 +++++++++++++------ .../enum_template_with_initializer.tpl | 59 ++++++++++++++ .../enum_template_with_inner_properties.tpl | 48 ++++++++++++ ...late_with_inner_propertyresourcebundle.tpl | 48 ++++++++++++ 11 files changed, 340 insertions(+), 42 deletions(-) create mode 100644 src/main/java/de/kreth/property2java/processor/Format.java create mode 100644 src/main/java/de/kreth/property2java/processor/GenerateResourceBundleProperty2Java.java create mode 100644 src/main/java/de/kreth/property2java/processor/GenerateResourceBundleProperty2Javas.java create mode 100644 src/main/resources/template/enum_template_with_initializer.tpl create mode 100644 src/main/resources/template/enum_template_with_inner_properties.tpl create mode 100644 src/main/resources/template/enum_template_with_inner_propertyresourcebundle.tpl diff --git a/src/main/java/de/kreth/property2java/Configuration.java b/src/main/java/de/kreth/property2java/Configuration.java index 6c1c426..0e19fdf 100644 --- a/src/main/java/de/kreth/property2java/Configuration.java +++ b/src/main/java/de/kreth/property2java/Configuration.java @@ -12,6 +12,7 @@ import java.util.Map; import org.apache.commons.text.WordUtils; import de.kreth.property2java.config.Regex; +import de.kreth.property2java.processor.Format; public interface Configuration { @@ -23,6 +24,10 @@ public interface Configuration { */ String getPackage(); + default Format getFormat() { + return Format.WithUnaryOperatorParameter; + } + /** * Filename to InputReader Entries * diff --git a/src/main/java/de/kreth/property2java/Generator.java b/src/main/java/de/kreth/property2java/Generator.java index 38431aa..9bb690b 100644 --- a/src/main/java/de/kreth/property2java/Generator.java +++ b/src/main/java/de/kreth/property2java/Generator.java @@ -31,7 +31,7 @@ public class Generator { public Generator(Configuration config) { this.config = config; try { - template = FreemarkerConfig.INSTANCE.getTemplate(); + template = FreemarkerConfig.INSTANCE.getTemplate(config.getFormat()); } catch (IOException e) { throw new IllegalStateException("Unable to load freemarker template", e); } @@ -62,6 +62,7 @@ public class Generator { root.put("generation_date", dateTimeInstance.format(new Date())); root.put("package", config.getPackage()); root.put("fileName", fileName); + root.put("bundle_base_name", fileName.substring(0, min(fileName.length(), fileName.lastIndexOf('.')))); root.put("classname", config.mapFilenameToClassName(fileName)); List entries = new ArrayList<>(); @@ -81,6 +82,14 @@ public class Generator { template.process(root, out); } + int min(int a, int b) { + int result = Math.min(a, b); + if (result < 0) { + result = Math.max(a, b); + } + return result; + } + public static void main(String[] args) throws IOException, GeneratorException { Generator generator = new Generator(ArgumentConfiguration.parse(args)); generator.start(); diff --git a/src/main/java/de/kreth/property2java/config/FreemarkerConfig.java b/src/main/java/de/kreth/property2java/config/FreemarkerConfig.java index 4a66f9f..f994279 100644 --- a/src/main/java/de/kreth/property2java/config/FreemarkerConfig.java +++ b/src/main/java/de/kreth/property2java/config/FreemarkerConfig.java @@ -2,23 +2,36 @@ package de.kreth.property2java.config; import java.io.IOException; +import de.kreth.property2java.processor.Format; import freemarker.template.Configuration; import freemarker.template.Template; public enum FreemarkerConfig { - INSTANCE; - - private final Configuration cfg; - - public Template getTemplate() throws IOException { - return cfg.getTemplate("enum_template.tpl"); + INSTANCE; + + private final Configuration cfg; + + public Template getTemplate(Format format) throws IOException { + switch (format) { + case WithInitializer: + return cfg.getTemplate("enum_template_with_initializer.tpl"); + case WithInnerPropertyLoader: + return cfg.getTemplate("enum_template_with_inner_properties.tpl"); + case WithInnerPropertyResourceBundle: + return cfg.getTemplate("enum_template_with_inner_propertyresourcebundle.tpl"); + case WithUnaryOperatorParameter: + return cfg.getTemplate("enum_template.tpl"); + default: + throw new IllegalArgumentException("Format " + format + " is not supported."); } - private FreemarkerConfig() { - cfg = new Configuration(Configuration.VERSION_2_3_28); - cfg.setClassForTemplateLoading(this.getClass(), "/template/"); - cfg.setDefaultEncoding("UTF-8"); - } + } + + private FreemarkerConfig() { + cfg = new Configuration(Configuration.VERSION_2_3_28); + cfg.setClassForTemplateLoading(this.getClass(), "/template/"); + cfg.setDefaultEncoding("UTF-8"); + } } diff --git a/src/main/java/de/kreth/property2java/processor/Format.java b/src/main/java/de/kreth/property2java/processor/Format.java new file mode 100644 index 0000000..a0d271c --- /dev/null +++ b/src/main/java/de/kreth/property2java/processor/Format.java @@ -0,0 +1,9 @@ +package de.kreth.property2java.processor; + +public enum Format { + + WithUnaryOperatorParameter, + WithInnerPropertyResourceBundle, + WithInnerPropertyLoader, + WithInitializer +} diff --git a/src/main/java/de/kreth/property2java/processor/GenerateResourceBundleProperty2Java.java b/src/main/java/de/kreth/property2java/processor/GenerateResourceBundleProperty2Java.java new file mode 100644 index 0000000..69c7275 --- /dev/null +++ b/src/main/java/de/kreth/property2java/processor/GenerateResourceBundleProperty2Java.java @@ -0,0 +1,46 @@ +package de.kreth.property2java.processor; + +import static java.lang.annotation.ElementType.TYPE; + +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(TYPE) +@Retention(RetentionPolicy.SOURCE) +@Repeatable(value = GenerateResourceBundleProperty2Javas.class) +/** + * Für die konfigurierten Resourcen wird jeweils eine Java Klasse erzeugt. Es + * muss nur die Abhängigkeit eingebunden werden und die Annotation in einer + * Klasse verwendet werden, in deren Package die neuen Klassen generiert werden. + * Wenn mehrere Resourcen verarbeitet werden sollen, kann diese Annotation + * mehrfach parallel angegeben werden. + * + * Für die Ausgabe der Prozessornachrichten muss folgendes im maven compiler + * konfiguriert werden: + * + *
+<build>
+	<plugins>
+		<plugin>
+			<groupId>org.apache.maven.plugins</groupId>
+			<artifactId>maven-compiler-plugin</artifactId>
+			<version>3.8.0</version>
+			<configuration>
+				<release>${java.version}</release>
+				<showWarnings>true</showWarnings>
+			</configuration>
+		</plugin>
+	</plugins>
+</build>
+ * 
+ * + * @author Markus + * + */ +public @interface GenerateResourceBundleProperty2Java { + String resource(); + + Format format(); +} diff --git a/src/main/java/de/kreth/property2java/processor/GenerateResourceBundleProperty2Javas.java b/src/main/java/de/kreth/property2java/processor/GenerateResourceBundleProperty2Javas.java new file mode 100644 index 0000000..d879f60 --- /dev/null +++ b/src/main/java/de/kreth/property2java/processor/GenerateResourceBundleProperty2Javas.java @@ -0,0 +1,21 @@ +package de.kreth.property2java.processor; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Diese Annotation sollte nicht verwendet werden. Sie sammelt nur + * {@link GenerateResourceBundleProperty2Java} wenn diese mehrfach verwendet + * wird. + * + * @author Markus + * + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface GenerateResourceBundleProperty2Javas { + + GenerateResourceBundleProperty2Java[] value(); +} diff --git a/src/main/java/de/kreth/property2java/processor/ProcessorConfiguration.java b/src/main/java/de/kreth/property2java/processor/ProcessorConfiguration.java index 13e59ce..a6f5de2 100644 --- a/src/main/java/de/kreth/property2java/processor/ProcessorConfiguration.java +++ b/src/main/java/de/kreth/property2java/processor/ProcessorConfiguration.java @@ -9,6 +9,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import javax.annotation.processing.Filer; import javax.lang.model.element.Element; @@ -26,17 +27,16 @@ public class ProcessorConfiguration implements Configuration { private final Filer filer; private final Element element; private final Map input; + private final Format format; ProcessorConfiguration(Builder builder) throws IOException { this.filer = builder.filer; this.element = builder.element; + this.format = Objects.requireNonNullElse(builder.format, Format.WithUnaryOperatorParameter); this.input = new HashMap<>(); for (String resource : builder.resourcenames) { - - FileObject ressource = filer.getResource(StandardLocation.CLASS_PATH, "", - resource); - String className = mapFilenameToClassName(resource); - input.put(className, ressource.openReader(false)); + FileObject ressource = filer.getResource(StandardLocation.CLASS_PATH, "", resource); + input.put(resource, ressource.openReader(false)); } } @@ -52,6 +52,11 @@ public class ProcessorConfiguration implements Configuration { return packageName; } + @Override + public Format getFormat() { + return format; + } + @Override public Map getInput() { return input; @@ -67,7 +72,7 @@ public class ProcessorConfiguration implements Configuration { public Writer outWriter(String fileName) throws IOException { String packageName = getPackage(); if (packageName != null && !packageName.isBlank()) { - fileName = packageName + "." + fileName; + fileName = packageName + "." + mapFilenameToClassName(fileName); } return filer.createSourceFile(fileName, element).openWriter(); } @@ -80,6 +85,7 @@ public class ProcessorConfiguration implements Configuration { private final Filer filer; private final Element element; private final List resourcenames; + private Format format = Format.WithUnaryOperatorParameter; private Builder(Filer filer, Element element) { this.filer = filer; @@ -87,6 +93,11 @@ public class ProcessorConfiguration implements Configuration { this.resourcenames = new ArrayList<>(); } + public Builder withFormat(Format format) { + this.format = format; + return this; + } + public Builder addAll(String[] resourceNames) { this.resourcenames.addAll(Arrays.asList(resourceNames)); return this; diff --git a/src/main/java/de/kreth/property2java/processor/Property2JavaGenerator.java b/src/main/java/de/kreth/property2java/processor/Property2JavaGenerator.java index b89faf2..3273f32 100644 --- a/src/main/java/de/kreth/property2java/processor/Property2JavaGenerator.java +++ b/src/main/java/de/kreth/property2java/processor/Property2JavaGenerator.java @@ -4,6 +4,7 @@ import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.util.Arrays; +import java.util.List; import java.util.Set; import javax.annotation.processing.AbstractProcessor; @@ -17,7 +18,9 @@ import javax.tools.Diagnostic.Kind; import de.kreth.property2java.GeneratorException; -@SupportedAnnotationTypes({ "de.kreth.property2java.processor.GenerateProperty2Java" }) +@SupportedAnnotationTypes({ "de.kreth.property2java.processor.GenerateProperty2Java", + "de.kreth.property2java.processor.GenerateResourceBundleProperty2Javas", + "de.kreth.property2java.processor.GenerateResourceBundleProperty2Java" }) @SupportedSourceVersion(SourceVersion.RELEASE_8) public class Property2JavaGenerator extends AbstractProcessor { @@ -25,37 +28,63 @@ public class Property2JavaGenerator extends AbstractProcessor { public boolean process(Set annotations, RoundEnvironment roundEnv) { if (!roundEnv.processingOver()) { - processingEnv.getMessager().printMessage(Kind.NOTE, - "Processing annotation " + GenerateProperty2Java.class); - - Set elementsAnnotatedWith = roundEnv - .getElementsAnnotatedWith(GenerateProperty2Java.class); - - processElements(elementsAnnotatedWith); + processGenerateProperty2Java(roundEnv); + processGenerateResourceBundleProperty2Javas(roundEnv); } else { processingEnv.getMessager().printMessage(Kind.NOTE, - "finished working on annotation " + GenerateProperty2Java.class); + "finished working on annotation " + annotations); } return true; } - private void processElements(Set elementsAnnotatedWith) { + private void processGenerateProperty2Java(RoundEnvironment roundEnv) { + processingEnv.getMessager().printMessage(Kind.NOTE, + "Processing annotation " + GenerateProperty2Java.class); + + Set elementsAnnotatedWith = roundEnv + .getElementsAnnotatedWith(GenerateProperty2Java.class); + for (Element element : elementsAnnotatedWith) { - String[] resources = element.getAnnotation(GenerateProperty2Java.class).resources(); - processingEnv.getMessager().printMessage(Kind.NOTE, - "Generating Java for " + Arrays.asList(resources)); - try { - ProcessorConfiguration - .builder(processingEnv.getFiler(), element) - .addAll(resources) - .startGeneration(); - } catch (IOException | GeneratorException e) { - StringWriter out = new StringWriter(); - e.printStackTrace(new PrintWriter(out)); - out.flush(); - processingEnv.getMessager().printMessage(Kind.ERROR, "Exception " + e + "\n" + out.toString(), - element); + GenerateProperty2Java generateAnnotation = element.getAnnotation(GenerateProperty2Java.class); + String[] resources = generateAnnotation.resources(); + generateElementProperties(element, Arrays.asList(resources), Format.WithUnaryOperatorParameter); + } + } + + private void processGenerateResourceBundleProperty2Javas(RoundEnvironment roundEnv) { + + processingEnv.getMessager().printMessage(Kind.NOTE, + "Processing annotation " + GenerateResourceBundleProperty2Javas.class); + + Set elementsAnnotatedWith = roundEnv + .getElementsAnnotatedWith(GenerateResourceBundleProperty2Javas.class); + + for (Element element : elementsAnnotatedWith) { + GenerateResourceBundleProperty2Java[] value = element + .getAnnotation(GenerateResourceBundleProperty2Javas.class).value(); + for (GenerateResourceBundleProperty2Java generateResourceBundleProperty2Java : value) { + List resources = Arrays.asList(generateResourceBundleProperty2Java.resource()); + generateElementProperties(element, resources, generateResourceBundleProperty2Java.format()); } } } + + private void generateElementProperties(Element element, List resources, Format format) { + processingEnv.getMessager().printMessage(Kind.NOTE, + "Generating Java for " + Arrays.asList(resources)); + try { + ProcessorConfiguration + .builder(processingEnv.getFiler(), element) + .addAll(resources) + .withFormat(format) + .startGeneration(); + } catch (IOException | GeneratorException e) { + StringWriter out = new StringWriter(); + e.printStackTrace(new PrintWriter(out)); + out.flush(); + processingEnv.getMessager().printMessage(Kind.ERROR, "Exception " + e + "\n" + out.toString(), + element); + } + } + } diff --git a/src/main/resources/template/enum_template_with_initializer.tpl b/src/main/resources/template/enum_template_with_initializer.tpl new file mode 100644 index 0000000..ab44e1b --- /dev/null +++ b/src/main/resources/template/enum_template_with_initializer.tpl @@ -0,0 +1,59 @@ +<#if package??>package ${package}; + +import java.util.Properties; +import java.util.ResourceBundle; +import java.util.function.UnaryOperator; + +import javax.annotation.processing.Generated; + +/** + * Property keys from ${fileName} + */ +@Generated(date = "${generation_date}", value = "${generator_name}") +public enum ${classname} { + +<#list entries as e> + /** + * ${e.key} = "${e.value}" + */ + ${e.constant} ("${e.key}")<#sep>, + +; + private static UnaryOperator function; + private final String value; + + private ${classname} (String value) { + this.value = value; + } + + public static void init(UnaryOperator resourceFunction) { + function = resourceFunction; + } + + /** + * Represented Key in property File. + * @return key + */ + public String getValue() { + return value; + } + + /** + * Resolves the value for this key. + * {@link #init(UnaryOperator)} must be called before. + */ + public String getText() { + return function.apply(value); + } + + /** + * Resolves the value for this key from the parameter function. + *

+ * e.g. ${classname}.getString(resBundle::getString) + * @param resourceFunction {@link Properties#getProperty(String)} or {@link ResourceBundle#getString(String)} + * @return + */ + public String getString(UnaryOperator resourceFunction) { + return resourceFunction.apply(value); + } +} diff --git a/src/main/resources/template/enum_template_with_inner_properties.tpl b/src/main/resources/template/enum_template_with_inner_properties.tpl new file mode 100644 index 0000000..d3955af --- /dev/null +++ b/src/main/resources/template/enum_template_with_inner_properties.tpl @@ -0,0 +1,48 @@ +<#if package??>package ${package}; + +import java.util.Properties; +import java.util.PropertyResourceBundle; +import java.util.ResourceBundle; +import java.util.function.UnaryOperator; + +import javax.annotation.processing.Generated; + +/** + * Property keys from ${fileName} + */ +@Generated(date = "${generation_date}", value = "${generator_name}") +public enum ${classname} { + +<#list entries as e> + /** + * ${e.key} = "${e.value}" + */ + ${e.constant} ("${e.key}")<#sep>, + +; + + private final String value; + + private ${classname} (String value) { + this.value = value; + } + + /** + * Represented Key in property File. + * @return key + */ + public String getValue() { + return value; + } + + private static ResourceBundle bundle = PropertyResourceBundle.getBundle("${bundle_base_name}"); + + /** + * The Text for this Key from PropertyResourceBundle + * @return human readable text + */ + public String getText() { + return bundle.getString(value); + } + +} diff --git a/src/main/resources/template/enum_template_with_inner_propertyresourcebundle.tpl b/src/main/resources/template/enum_template_with_inner_propertyresourcebundle.tpl new file mode 100644 index 0000000..d3955af --- /dev/null +++ b/src/main/resources/template/enum_template_with_inner_propertyresourcebundle.tpl @@ -0,0 +1,48 @@ +<#if package??>package ${package}; + +import java.util.Properties; +import java.util.PropertyResourceBundle; +import java.util.ResourceBundle; +import java.util.function.UnaryOperator; + +import javax.annotation.processing.Generated; + +/** + * Property keys from ${fileName} + */ +@Generated(date = "${generation_date}", value = "${generator_name}") +public enum ${classname} { + +<#list entries as e> + /** + * ${e.key} = "${e.value}" + */ + ${e.constant} ("${e.key}")<#sep>, + +; + + private final String value; + + private ${classname} (String value) { + this.value = value; + } + + /** + * Represented Key in property File. + * @return key + */ + public String getValue() { + return value; + } + + private static ResourceBundle bundle = PropertyResourceBundle.getBundle("${bundle_base_name}"); + + /** + * The Text for this Key from PropertyResourceBundle + * @return human readable text + */ + public String getText() { + return bundle.getString(value); + } + +}