Compare commits

..

5 Commits

  1. 38
      .classpath
  2. 6
      .gitignore
  3. 23
      .project
  4. 4
      pom.xml
  5. 5
      src/main/java/de/kreth/property2java/Configuration.java
  6. 11
      src/main/java/de/kreth/property2java/Generator.java
  7. 15
      src/main/java/de/kreth/property2java/config/FreemarkerConfig.java
  8. 27
      src/main/java/de/kreth/property2java/processor/Format.java
  9. 2
      src/main/java/de/kreth/property2java/processor/GenerateProperty2Java.java
  10. 46
      src/main/java/de/kreth/property2java/processor/GenerateResourceBundleProperty2Java.java
  11. 21
      src/main/java/de/kreth/property2java/processor/GenerateResourceBundleProperty2Javas.java
  12. 23
      src/main/java/de/kreth/property2java/processor/ProcessorConfiguration.java
  13. 48
      src/main/java/de/kreth/property2java/processor/Property2JavaGenerator.java
  14. 2
      src/main/resources/template/enum_template.tpl
  15. 62
      src/main/resources/template/enum_template_with_initializer.tpl
  16. 48
      src/main/resources/template/enum_template_with_inner_properties.tpl
  17. 50
      src/main/resources/template/enum_template_with_inner_propertyresourcebundle.tpl

@ -1,38 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="test" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="optional" value="true"/>
</attributes>
</classpathentry>
<classpathentry exported="true" kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

6
.gitignore vendored

@ -1,3 +1,5 @@
.classpath
\.settings/ .project
.factorypath
.settings
target target

@ -1,23 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>PropertyToJavaGenerator</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
</projectDescription>

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>de.kreth.property2java</groupId> <groupId>de.kreth.property2java</groupId>
<artifactId>PropertyToJavaGenerator</artifactId> <artifactId>PropertyToJavaGenerator</artifactId>
<version>2.0.2-SNAPSHOT</version> <version>2.0.2</version>
<properties> <properties>
@ -146,6 +146,6 @@
<scm> <scm>
<developerConnection>scm:git:https://gitea.kreth-development.de/markus/PropertyToJavaGenerator_migration.git</developerConnection> <developerConnection>scm:git:https://gitea.kreth-development.de/markus/PropertyToJavaGenerator_migration.git</developerConnection>
<connection>scm:git:https://gitea.kreth-development.de/markus/PropertyToJavaGenerator_migration.git</connection> <connection>scm:git:https://gitea.kreth-development.de/markus/PropertyToJavaGenerator_migration.git</connection>
<tag>HEAD</tag> <tag>PropertyToJavaGenerator-2.0.2</tag>
</scm> </scm>
</project> </project>

@ -12,6 +12,7 @@ import java.util.Map;
import org.apache.commons.text.WordUtils; import org.apache.commons.text.WordUtils;
import de.kreth.property2java.config.Regex; import de.kreth.property2java.config.Regex;
import de.kreth.property2java.processor.Format;
public interface Configuration { public interface Configuration {
@ -23,6 +24,10 @@ public interface Configuration {
*/ */
String getPackage(); String getPackage();
default Format getFormat() {
return Format.WithUnaryOperatorParameter;
}
/** /**
* Filename to InputReader Entries * Filename to InputReader Entries
* *

@ -31,7 +31,7 @@ public class Generator {
public Generator(Configuration config) { public Generator(Configuration config) {
this.config = config; this.config = config;
try { try {
template = FreemarkerConfig.INSTANCE.getTemplate(); template = FreemarkerConfig.INSTANCE.getTemplate(config.getFormat());
} catch (IOException e) { } catch (IOException e) {
throw new IllegalStateException("Unable to load freemarker template", 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("generation_date", dateTimeInstance.format(new Date()));
root.put("package", config.getPackage()); root.put("package", config.getPackage());
root.put("fileName", fileName); root.put("fileName", fileName);
root.put("bundle_base_name", fileName.substring(0, min(fileName.length(), fileName.lastIndexOf('.'))));
root.put("classname", config.mapFilenameToClassName(fileName)); root.put("classname", config.mapFilenameToClassName(fileName));
List<Entry> entries = new ArrayList<>(); List<Entry> entries = new ArrayList<>();
@ -81,6 +82,14 @@ public class Generator {
template.process(root, out); 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 { public static void main(String[] args) throws IOException, GeneratorException {
Generator generator = new Generator(ArgumentConfiguration.parse(args)); Generator generator = new Generator(ArgumentConfiguration.parse(args));
generator.start(); generator.start();

@ -2,6 +2,7 @@ package de.kreth.property2java.config;
import java.io.IOException; import java.io.IOException;
import de.kreth.property2java.processor.Format;
import freemarker.template.Configuration; import freemarker.template.Configuration;
import freemarker.template.Template; import freemarker.template.Template;
@ -11,8 +12,20 @@ public enum FreemarkerConfig {
private final Configuration cfg; private final Configuration cfg;
public Template getTemplate() throws IOException { 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"); return cfg.getTemplate("enum_template.tpl");
default:
throw new IllegalArgumentException("Format " + format + " is not supported.");
}
} }
private FreemarkerConfig() { private FreemarkerConfig() {

@ -0,0 +1,27 @@
package de.kreth.property2java.processor;
import java.util.PropertyResourceBundle;
public enum Format {
/**
* Offers a getString(UnaryOperator<String> resourceFunction) method to access
* the String value
*/
WithUnaryOperatorParameter,
/**
* Generates {@link PropertyResourceBundle} to offer a getText() method without
* parameters.
*/
WithInnerPropertyResourceBundle,
/**
* Offers a generated {@link PropertyResourceBundle} to offer a getText() method
* without parameters.
*/
WithInnerPropertyLoader,
/**
* Offers a static init(UnaryOperator<String> resourceFunction) method to offer
* a getText() method. The init method must be called before any getText() call.
*/
WithInitializer
}

@ -37,4 +37,6 @@ import java.lang.annotation.Target;
*/ */
public @interface GenerateProperty2Java { public @interface GenerateProperty2Java {
String[] resources(); String[] resources();
Format format() default Format.WithUnaryOperatorParameter;
} }

@ -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:
*
* <pre>
&lt;build&gt;
&lt;plugins&gt;
&lt;plugin&gt;
&lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
&lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;
&lt;version&gt;3.8.0&lt;/version&gt;
&lt;configuration&gt;
&lt;release&gt;${java.version}&lt;/release&gt;
<b>&lt;showWarnings&gt;true&lt;/showWarnings&gt;</b>
&lt;/configuration&gt;
&lt;/plugin&gt;
&lt;/plugins&gt;
&lt;/build&gt;
* </pre>
*
* @author Markus
*
*/
public @interface GenerateResourceBundleProperty2Java {
String resource();
Format format();
}

@ -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();
}

@ -9,6 +9,7 @@ import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import javax.annotation.processing.Filer; import javax.annotation.processing.Filer;
import javax.lang.model.element.Element; import javax.lang.model.element.Element;
@ -26,17 +27,16 @@ public class ProcessorConfiguration implements Configuration {
private final Filer filer; private final Filer filer;
private final Element element; private final Element element;
private final Map<String, Reader> input; private final Map<String, Reader> input;
private final Format format;
ProcessorConfiguration(Builder builder) throws IOException { ProcessorConfiguration(Builder builder) throws IOException {
this.filer = builder.filer; this.filer = builder.filer;
this.element = builder.element; this.element = builder.element;
this.format = Objects.requireNonNullElse(builder.format, Format.WithUnaryOperatorParameter);
this.input = new HashMap<>(); this.input = new HashMap<>();
for (String resource : builder.resourcenames) { for (String resource : builder.resourcenames) {
FileObject ressource = filer.getResource(StandardLocation.CLASS_PATH, "", resource);
FileObject ressource = filer.getResource(StandardLocation.CLASS_PATH, "", input.put(resource, ressource.openReader(false));
resource);
String className = mapFilenameToClassName(resource);
input.put(className, ressource.openReader(false));
} }
} }
@ -52,6 +52,11 @@ public class ProcessorConfiguration implements Configuration {
return packageName; return packageName;
} }
@Override
public Format getFormat() {
return format;
}
@Override @Override
public Map<String, Reader> getInput() { public Map<String, Reader> getInput() {
return input; return input;
@ -67,7 +72,7 @@ public class ProcessorConfiguration implements Configuration {
public Writer outWriter(String fileName) throws IOException { public Writer outWriter(String fileName) throws IOException {
String packageName = getPackage(); String packageName = getPackage();
if (packageName != null && !packageName.isBlank()) { if (packageName != null && !packageName.isBlank()) {
fileName = packageName + "." + fileName; fileName = packageName + "." + mapFilenameToClassName(fileName);
} }
return filer.createSourceFile(fileName, element).openWriter(); return filer.createSourceFile(fileName, element).openWriter();
} }
@ -80,6 +85,7 @@ public class ProcessorConfiguration implements Configuration {
private final Filer filer; private final Filer filer;
private final Element element; private final Element element;
private final List<String> resourcenames; private final List<String> resourcenames;
private Format format = Format.WithUnaryOperatorParameter;
private Builder(Filer filer, Element element) { private Builder(Filer filer, Element element) {
this.filer = filer; this.filer = filer;
@ -87,6 +93,11 @@ public class ProcessorConfiguration implements Configuration {
this.resourcenames = new ArrayList<>(); this.resourcenames = new ArrayList<>();
} }
public Builder withFormat(Format format) {
this.format = format;
return this;
}
public Builder addAll(String[] resourceNames) { public Builder addAll(String[] resourceNames) {
this.resourcenames.addAll(Arrays.asList(resourceNames)); this.resourcenames.addAll(Arrays.asList(resourceNames));
return this; return this;

@ -4,6 +4,7 @@ import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.StringWriter; import java.io.StringWriter;
import java.util.Arrays; import java.util.Arrays;
import java.util.List;
import java.util.Set; import java.util.Set;
import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.AbstractProcessor;
@ -17,7 +18,9 @@ import javax.tools.Diagnostic.Kind;
import de.kreth.property2java.GeneratorException; 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) @SupportedSourceVersion(SourceVersion.RELEASE_8)
public class Property2JavaGenerator extends AbstractProcessor { public class Property2JavaGenerator extends AbstractProcessor {
@ -25,29 +28,56 @@ public class Property2JavaGenerator extends AbstractProcessor {
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (!roundEnv.processingOver()) { if (!roundEnv.processingOver()) {
processGenerateProperty2Java(roundEnv);
processGenerateResourceBundleProperty2Javas(roundEnv);
} else {
processingEnv.getMessager().printMessage(Kind.NOTE,
"finished working on annotation " + annotations);
}
return true;
}
private void processGenerateProperty2Java(RoundEnvironment roundEnv) {
processingEnv.getMessager().printMessage(Kind.NOTE, processingEnv.getMessager().printMessage(Kind.NOTE,
"Processing annotation " + GenerateProperty2Java.class); "Processing annotation " + GenerateProperty2Java.class);
Set<? extends Element> elementsAnnotatedWith = roundEnv Set<? extends Element> elementsAnnotatedWith = roundEnv
.getElementsAnnotatedWith(GenerateProperty2Java.class); .getElementsAnnotatedWith(GenerateProperty2Java.class);
processElements(elementsAnnotatedWith); for (Element element : elementsAnnotatedWith) {
} else { GenerateProperty2Java generateAnnotation = element.getAnnotation(GenerateProperty2Java.class);
processingEnv.getMessager().printMessage(Kind.NOTE, String[] resources = generateAnnotation.resources();
"finished working on annotation " + GenerateProperty2Java.class); Format format = generateAnnotation.format();
generateElementProperties(element, Arrays.asList(resources), format);
} }
return true;
} }
private void processElements(Set<? extends Element> elementsAnnotatedWith) { private void processGenerateResourceBundleProperty2Javas(RoundEnvironment roundEnv) {
processingEnv.getMessager().printMessage(Kind.NOTE,
"Processing annotation " + GenerateResourceBundleProperty2Javas.class);
Set<? extends Element> elementsAnnotatedWith = roundEnv
.getElementsAnnotatedWith(GenerateResourceBundleProperty2Javas.class);
for (Element element : elementsAnnotatedWith) { for (Element element : elementsAnnotatedWith) {
String[] resources = element.getAnnotation(GenerateProperty2Java.class).resources(); GenerateResourceBundleProperty2Java[] value = element
.getAnnotation(GenerateResourceBundleProperty2Javas.class).value();
for (GenerateResourceBundleProperty2Java generateResourceBundleProperty2Java : value) {
List<String> resources = Arrays.asList(generateResourceBundleProperty2Java.resource());
generateElementProperties(element, resources, generateResourceBundleProperty2Java.format());
}
}
}
private void generateElementProperties(Element element, List<String> resources, Format format) {
processingEnv.getMessager().printMessage(Kind.NOTE, processingEnv.getMessager().printMessage(Kind.NOTE,
"Generating Java for " + Arrays.asList(resources)); "Generating Java for " + Arrays.asList(resources));
try { try {
ProcessorConfiguration ProcessorConfiguration
.builder(processingEnv.getFiler(), element) .builder(processingEnv.getFiler(), element)
.addAll(resources) .addAll(resources)
.withFormat(format)
.startGeneration(); .startGeneration();
} catch (IOException | GeneratorException e) { } catch (IOException | GeneratorException e) {
StringWriter out = new StringWriter(); StringWriter out = new StringWriter();
@ -57,5 +87,5 @@ public class Property2JavaGenerator extends AbstractProcessor {
element); element);
} }
} }
}
} }

@ -8,6 +8,8 @@ import javax.annotation.processing.Generated;
/** /**
* Property keys from ${fileName} * Property keys from ${fileName}
* {@link #getValue()} gives the key for the entry, with {@link #getString(UnaryOperator<String>)}
* the value is given directly.
*/ */
@Generated(date = "${generation_date}", value = "${generator_name}") @Generated(date = "${generation_date}", value = "${generator_name}")
public enum ${classname} { public enum ${classname} {

@ -0,0 +1,62 @@
<#if package??>package ${package};
</#if>import java.util.Properties;
import java.util.ResourceBundle;
import java.util.function.UnaryOperator;
import javax.annotation.processing.Generated;
/**
* Property keys from ${fileName}
* {@link #getValue()} gives the key for the entry, with {@link #getText()} the value for the key is given directly.
* This enum needs to be initialized before any use by {@link #init(UnaryOperator)}.
*/
@Generated(date = "${generation_date}", value = "${generator_name}")
public enum ${classname} {
<#list entries as e>
/**
* ${e.key} = "${e.value}"
*/
${e.constant} ("${e.key}")<#sep>,
</#sep>
</#list>;
private static UnaryOperator<String> function;
private final String value;
private ${classname} (String value) {
this.value = value;
}
public static void init(UnaryOperator<String> resourceFunction) {
function = resourceFunction;
}
/**
* Represented Key in property File.
* @return key
*/
public String getValue() {
return value;
}
/**
* Resolves the value for this key.
* {@link #init(UnaryOperator<String>)} must be called before.
*/
public String getText() {
return function.apply(value);
}
/**
* Resolves the value for this key from the parameter function.
* <p>
* e.g. <code>${classname}.getString(resBundle::getString)</code>
* @param resourceFunction {@link Properties#getProperty(String)} or {@link ResourceBundle#getString(String)}
* @return
*/
public String getString(UnaryOperator<String> resourceFunction) {
return resourceFunction.apply(value);
}
}

@ -0,0 +1,48 @@
<#if package??>package ${package};
</#if>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>,
</#sep>
</#list>;
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);
}
}

@ -0,0 +1,50 @@
<#if package??>package ${package};
</#if>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}
* {@link #getValue()} gives the key for the entry, with {@link #getText()} the value for the key is given directly.
* Initializationis generated also.
*/
@Generated(date = "${generation_date}", value = "${generator_name}")
public enum ${classname} {
<#list entries as e>
/**
* ${e.key} = "${e.value}"
*/
${e.constant} ("${e.key}")<#sep>,
</#sep>
</#list>;
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);
}
}
Loading…
Cancel
Save