Compare commits

..

3 Commits

  1. 87
      src/main/java/de/kreth/property2java/Configuration.java
  2. 202
      src/main/java/de/kreth/property2java/Generator.java
  3. 122
      src/main/java/de/kreth/property2java/cli/ArgumentConfiguration.java
  4. 6
      src/main/java/de/kreth/property2java/cli/CliConfig.java
  5. 46
      src/main/java/de/kreth/property2java/config/FreemarkerConfig.java
  6. 40
      src/main/java/de/kreth/property2java/processor/Format.java
  7. 4
      src/main/java/de/kreth/property2java/processor/GenerateProperty2Java.java
  8. 4
      src/main/java/de/kreth/property2java/processor/GenerateResourceBundleProperty2Java.java
  9. 4
      src/main/java/de/kreth/property2java/processor/GenerateResourceBundleProperty2Javas.java
  10. 148
      src/main/java/de/kreth/property2java/processor/ProcessorConfiguration.java
  11. 96
      src/main/java/de/kreth/property2java/processor/Property2JavaGenerator.java
  12. 7
      src/test/java/de/kreth/property2java/ConfigurationTest.java
  13. 278
      src/test/java/de/kreth/property2java/GeneratorTests.java
  14. 27
      src/test/java/de/kreth/property2java/TestImplConfig.java
  15. 49
      src/test/java/de/kreth/property2java/processor/Property2JavaGeneratorTest.java

@ -16,50 +16,47 @@ import de.kreth.property2java.processor.Format;
public interface Configuration { public interface Configuration {
/** /**
* Package for generated Java Classes eg. "de.kreth.property2java". If null - no * Package for generated Java Classes eg. "de.kreth.property2java". If null - no
* package line is generated. * package line is generated.
* *
* @return * @return
*/ */
String getPackage(); String getPackage();
default Format getFormat() { default Format getFormat() {
return Format.WithUnaryOperatorParameter; return Format.WithUnaryOperatorParameter;
} }
/** /**
* Filename to InputReader Entries * Filename to InputReader Entries
* *
* @return * @return
*/ */
Map<String, Reader> getInput(); Map<String, Reader> getInput();
/** /**
* Path of java source folder. * Path of java source folder.
* *
* @return * @return
*/ */
Path getRootPath(); Path getRootPath();
default Writer outWriter(String fileName) throws IOException { default Writer outWriter(String fileName) throws IOException {
return new FileWriter(new File(getRootPath().toFile(), mapFilenameToClassName(fileName) + ".java"), return new FileWriter(new File(getRootPath().toFile(), mapFilenameToClassName(fileName) + ".java"),
outputCharset()); outputCharset());
} }
default Charset outputCharset() { default Charset outputCharset() {
return Charset.defaultCharset(); return Charset.defaultCharset();
} }
default String mapFilenameToClassName(String fileName) { default String mapFilenameToClassName(String fileName) {
String path = Regex.PATTERN.matcher(fileName) String path = Regex.PATTERN.matcher(fileName).replaceAll(".").replaceAll("\\.", "_").replaceAll(" ", "_")
.replaceAll(".") .replaceAll("/", "_");
.replaceAll("\\.", "_") path = WordUtils.capitalize(path, '_');
.replaceAll(" ", "_") return path;
.replaceAll("/", "_"); }
path = WordUtils.capitalize(path, '_');
return path;
}
} }

@ -22,143 +22,137 @@ import freemarker.template.TemplateException;
public class Generator { public class Generator {
private static final DateFormat dateTimeInstance = DateFormat.getDateTimeInstance(); private static final DateFormat dateTimeInstance = DateFormat.getDateTimeInstance();
private final Configuration config; private final Configuration config;
private final Template template; private final Template template;
public Generator(Configuration config) { public Generator(Configuration config) {
this.config = config; this.config = config;
try { try {
template = FreemarkerConfig.INSTANCE.getTemplate(config.getFormat()); 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);
}
} }
}
public void start() throws IOException, GeneratorException { public void start() throws IOException, GeneratorException {
for (Map.Entry<String, Reader> entry : config.getInput().entrySet()) { for (Map.Entry<String, Reader> entry : config.getInput().entrySet()) {
String fileName = entry.getKey(); String fileName = entry.getKey();
try (Writer out = config.outWriter(fileName)) { try (Writer out = config.outWriter(fileName)) {
Properties properties = new Properties(); Properties properties = new Properties();
properties.load(entry.getValue()); properties.load(entry.getValue());
try { try {
generate(properties, out, fileName, config); generate(properties, out, fileName, config);
} catch (TemplateException e) { } catch (TemplateException e) {
throw new GeneratorException("Error configuring Engine", e); throw new GeneratorException("Error configuring Engine", e);
}
}
} }
}
} }
}
void generate(Properties properties, Writer out, String fileName, Configuration config) void generate(Properties properties, Writer out, String fileName, Configuration config)
throws IOException, TemplateException { throws IOException, TemplateException {
Map<String, Object> root = new HashMap<>(); Map<String, Object> root = new HashMap<>();
root.put("generator_name", getClass().getName()); root.put("generator_name", getClass().getName());
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("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<>();
root.put("entries", entries); root.put("entries", entries);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
List<String> propertyNames = Collections.list((Enumeration<String>) properties.propertyNames()); List<String> propertyNames = Collections.list((Enumeration<String>) properties.propertyNames());
Collections.sort(propertyNames); Collections.sort(propertyNames);
for (String propertyKeyString : propertyNames) { for (String propertyKeyString : propertyNames) {
final String propertyValue = properties.getProperty(propertyKeyString); final String propertyValue = properties.getProperty(propertyKeyString);
entries.add(new Entry(propertyKeyString.toUpperCase().replaceAll("[\\.-]", "_"), propertyKeyString, entries.add(new Entry(propertyKeyString.toUpperCase().replaceAll("[\\.-]", "_"), propertyKeyString,
propertyValue)); propertyValue));
}
template.process(root, out);
} }
template.process(root, out);
}
int min(int a, int b) { int min(int a, int b) {
int result = Math.min(a, b); int result = Math.min(a, b);
if (result < 0) { if (result < 0) {
result = Math.max(a, b); result = Math.max(a, b);
}
return result;
} }
return result;
}
public static void main(String[] args) throws IOException, GeneratorException {
Generator generator = new Generator(ArgumentConfiguration.parse(args));
generator.start();
}
public static void generateFor(Class<?> locationClass, List<URL> rescources, String relativeTargetDir) public static void main(String[] args) throws IOException, GeneratorException {
throws IOException, GeneratorException { Generator generator = new Generator(ArgumentConfiguration.parse(args));
generator.start();
ArgumentConfiguration.Builder config = new ArgumentConfiguration.Builder(); }
rescources
.stream()
.map(URL::getFile)
.map(File::new)
.map(File::getAbsolutePath)
.forEach(config::addPropFile);
config.setPackageName(locationClass.getPackageName())
.setTarget(relativeTargetDir);
Generator g = new Generator(config.build()); public static void generateFor(Class<?> locationClass, List<URL> rescources, String relativeTargetDir)
g.start(); throws IOException, GeneratorException {
}
/** ArgumentConfiguration.Builder config = new ArgumentConfiguration.Builder();
* Represents an Property Entry for the generated java class.
*
* @author markus
*
*/
public class Entry {
public final String constant; rescources.stream().map(URL::getFile).map(File::new).map(File::getAbsolutePath).forEach(config::addPropFile);
public final String key; config.setPackageName(locationClass.getPackageName()).setTarget(relativeTargetDir);
public final String value; Generator g = new Generator(config.build());
g.start();
}
/** /**
* Creates Property Entry data for the generated java class. * Represents an Property Entry for the generated java class.
*
* @author markus
* *
* @param constant name for the created constant.
* @param key property key
* @param value property value
*/ */
public Entry(String constant, String key, String value) { public class Entry {
super();
this.constant = constant; public final String constant;
this.key = key;
this.value = value; public final String key;
}
public final String value;
/**
* Creates Property Entry data for the generated java class.
*
* @param constant name for the created constant.
* @param key property key
* @param value property value
*/
public Entry(String constant, String key, String value) {
super();
this.constant = constant;
this.key = key;
this.value = value;
}
public String getConstant() { public String getConstant() {
return constant; return constant;
} }
public String getKey() { public String getKey() {
return key; return key;
} }
public String getValue() { public String getValue() {
return value; return value;
} }
@Override @Override
public String toString() { public String toString() {
return "Entry [constant=" + constant + ", key=" + key + ", value=" + value + "]"; return "Entry [constant=" + constant + ", key=" + key + ", value=" + value + "]";
} }
} }
} }

@ -16,81 +16,81 @@ import de.kreth.property2java.Configuration;
public class ArgumentConfiguration implements Configuration { public class ArgumentConfiguration implements Configuration {
private final String packageName; private final String packageName;
private final Map<String, Reader> files; private final Map<String, Reader> files;
private final Path rootPath; private final Path rootPath;
private ArgumentConfiguration(Builder builder) throws IOException { private ArgumentConfiguration(Builder builder) throws IOException {
this.packageName = builder.packageName; this.packageName = builder.packageName;
rootPath = new File(builder.target).toPath(); rootPath = new File(builder.target).toPath();
files = new HashMap<>(); files = new HashMap<>();
for (String filePath : builder.propFiles) { for (String filePath : builder.propFiles) {
File f = new File(filePath); File f = new File(filePath);
files.put(f.getName(), new FileReader(f)); files.put(f.getName(), new FileReader(f));
} }
}
@Override
public String getPackage() {
return packageName;
}
@Override
public Map<String, Reader> getInput() {
return files;
}
@Override
public Path getRootPath() {
return rootPath;
}
@Override
public Writer outWriter(String fileName) throws IOException {
File dir;
if (packageName != null && packageName.isBlank() == false) {
dir = new File(rootPath.toFile(), packageName.replace('.', File.separatorChar));
} else {
dir = rootPath.toFile();
} }
return new FileWriter(new File(dir, mapFilenameToClassName(fileName) + ".java"), false);
}
public static Configuration parse(String[] args) throws IOException { @Override
CliConfig cliConfig = new CliConfig(); public String getPackage() {
return packageName;
}
Builder builder = new Builder(); @Override
cliConfig.fill(builder, args); public Map<String, Reader> getInput() {
return builder.build(); return files;
} }
public static class Builder { @Override
String target; public Path getRootPath() {
return rootPath;
}
List<String> propFiles = new ArrayList<>(); @Override
public Writer outWriter(String fileName) throws IOException {
File dir;
if (packageName != null && packageName.isBlank() == false) {
dir = new File(rootPath.toFile(), packageName.replace('.', File.separatorChar));
} else {
dir = rootPath.toFile();
}
return new FileWriter(new File(dir, mapFilenameToClassName(fileName) + ".java"), false);
}
String packageName; public static Configuration parse(String[] args) throws IOException {
CliConfig cliConfig = new CliConfig();
public Builder setTarget(String target) { Builder builder = new Builder();
this.target = target; cliConfig.fill(builder, args);
return this; return builder.build();
} }
public Builder addPropFile(String propFile) { public static class Builder {
this.propFiles.add(propFile); String target;
return this;
}
public Builder setPackageName(String packageName) { List<String> propFiles = new ArrayList<>();
this.packageName = packageName;
return this; String packageName;
}
public Builder setTarget(String target) {
this.target = target;
return this;
}
public Builder addPropFile(String propFile) {
this.propFiles.add(propFile);
return this;
}
public Builder setPackageName(String packageName) {
this.packageName = packageName;
return this;
}
public Configuration build() throws IOException { public Configuration build() throws IOException {
return new ArgumentConfiguration(this); return new ArgumentConfiguration(this);
}
} }
}
} }

@ -35,12 +35,10 @@ public class CliConfig {
for (String value : cmd.getOptionValues("f")) { for (String value : cmd.getOptionValues("f")) {
builder.addPropFile(value); builder.addPropFile(value);
} }
} } catch (MissingOptionException e) {
catch (MissingOptionException e) {
printHelp(); printHelp();
throw new IllegalStateException(e); throw new IllegalStateException(e);
} } catch (ParseException e) {
catch (ParseException e) {
throw new IOException("Unable to parse Arguments", e); throw new IOException("Unable to parse Arguments", e);
} }
} }

@ -8,30 +8,30 @@ import freemarker.template.Template;
public enum FreemarkerConfig { public enum FreemarkerConfig {
INSTANCE; INSTANCE;
private final Configuration cfg; private final Configuration cfg;
public Template getTemplate(Format format) throws IOException { public Template getTemplate(Format format) throws IOException {
switch (format) { switch (format) {
case WithInitializer: case WithInitializer:
return cfg.getTemplate("enum_template_with_initializer.tpl"); return cfg.getTemplate("enum_template_with_initializer.tpl");
case WithInnerPropertyLoader: case WithInnerPropertyLoader:
return cfg.getTemplate("enum_template_with_inner_properties.tpl"); return cfg.getTemplate("enum_template_with_inner_properties.tpl");
case WithInnerPropertyResourceBundle: case WithInnerPropertyResourceBundle:
return cfg.getTemplate("enum_template_with_inner_propertyresourcebundle.tpl"); return cfg.getTemplate("enum_template_with_inner_propertyresourcebundle.tpl");
case WithUnaryOperatorParameter: case WithUnaryOperatorParameter:
return cfg.getTemplate("enum_template.tpl"); return cfg.getTemplate("enum_template.tpl");
default: default:
throw new IllegalArgumentException("Format " + format + " is not supported."); throw new IllegalArgumentException("Format " + format + " is not supported.");
} }
} }
private FreemarkerConfig() { private FreemarkerConfig() {
cfg = new Configuration(Configuration.VERSION_2_3_28); cfg = new Configuration(Configuration.VERSION_2_3_28);
cfg.setClassForTemplateLoading(this.getClass(), "/template/"); cfg.setClassForTemplateLoading(this.getClass(), "/template/");
cfg.setDefaultEncoding("UTF-8"); cfg.setDefaultEncoding("UTF-8");
} }
} }

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

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

@ -40,7 +40,7 @@ import java.lang.annotation.Target;
* *
*/ */
public @interface GenerateResourceBundleProperty2Java { public @interface GenerateResourceBundleProperty2Java {
String resource(); String resource();
Format format(); Format format();
} }

@ -15,7 +15,7 @@ import java.lang.annotation.Target;
*/ */
@Target(ElementType.TYPE) @Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface GenerateResourceBundleProperty2Javas { @interface GenerateResourceBundleProperty2Javas {
GenerateResourceBundleProperty2Java[] value(); GenerateResourceBundleProperty2Java[] value();
} }

@ -24,93 +24,93 @@ import de.kreth.property2java.GeneratorException;
public class ProcessorConfiguration implements Configuration { 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; 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.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, "", resource);
input.put(resource, ressource.openReader(false)); input.put(resource, ressource.openReader(false));
}
} }
}
@Override @Override
public String getPackage() { public String getPackage() {
String packageName = ""; String packageName = "";
if (element instanceof TypeElement) { if (element instanceof TypeElement) {
TypeElement typeElement = (TypeElement) element; TypeElement typeElement = (TypeElement) element;
PackageElement packageElement = (PackageElement) typeElement.getEnclosingElement(); PackageElement packageElement = (PackageElement) typeElement.getEnclosingElement();
packageName = packageElement.getQualifiedName().toString(); packageName = packageElement.getQualifiedName().toString();
}
return packageName;
} }
return packageName;
}
@Override
public Format getFormat() {
return format;
}
@Override
public Map<String, Reader> getInput() {
return input;
}
@Override
public Path getRootPath() {
throw new UnsupportedOperationException(
"For Annotation Processor this is not supported as outWriter is overwritten.");
}
@Override
public Writer outWriter(String fileName) throws IOException {
String packageName = getPackage();
if (packageName != null && !packageName.isBlank()) {
fileName = packageName + "." + mapFilenameToClassName(fileName);
}
return filer.createSourceFile(fileName, element).openWriter();
}
static Builder builder(Filer filer, Element element) {
return new Builder(filer, element);
}
static class Builder { @Override
private final Filer filer; public Format getFormat() {
private final Element element; return format;
private final List<String> resourcenames; }
private Format format = Format.WithUnaryOperatorParameter;
private Builder(Filer filer, Element element) { @Override
this.filer = filer; public Map<String, Reader> getInput() {
this.element = element; return input;
this.resourcenames = new ArrayList<>();
} }
public Builder withFormat(Format format) { @Override
this.format = format; public Path getRootPath() {
return this; throw new UnsupportedOperationException(
"For Annotation Processor this is not supported as outWriter is overwritten.");
} }
public Builder addAll(String[] resourceNames) { @Override
this.resourcenames.addAll(Arrays.asList(resourceNames)); public Writer outWriter(String fileName) throws IOException {
return this; String packageName = getPackage();
if (packageName != null && !packageName.isBlank()) {
fileName = packageName + "." + mapFilenameToClassName(fileName);
}
return filer.createSourceFile(fileName, element).openWriter();
} }
public Builder addAll(List<String> resourceNames) { static Builder builder(Filer filer, Element element) {
this.resourcenames.addAll(resourceNames); return new Builder(filer, element);
return this;
} }
public void startGeneration() throws IOException, GeneratorException { static class Builder {
Generator g = new Generator(new ProcessorConfiguration(this)); private final Filer filer;
g.start(); private final Element element;
private final List<String> resourcenames;
private Format format = Format.WithUnaryOperatorParameter;
private Builder(Filer filer, Element element) {
this.filer = filer;
this.element = element;
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;
}
public Builder addAll(List<String> resourceNames) {
this.resourcenames.addAll(resourceNames);
return this;
}
public void startGeneration() throws IOException, GeneratorException {
Generator g = new Generator(new ProcessorConfiguration(this));
g.start();
}
} }
}
} }

@ -19,73 +19,65 @@ 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.GenerateResourceBundleProperty2Javas",
"de.kreth.property2java.processor.GenerateResourceBundleProperty2Java" }) "de.kreth.property2java.processor.GenerateResourceBundleProperty2Java" })
@SupportedSourceVersion(SourceVersion.RELEASE_8) @SupportedSourceVersion(SourceVersion.RELEASE_8)
public class Property2JavaGenerator extends AbstractProcessor { public class Property2JavaGenerator extends AbstractProcessor {
@Override @Override
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); processGenerateProperty2Java(roundEnv);
processGenerateResourceBundleProperty2Javas(roundEnv); processGenerateResourceBundleProperty2Javas(roundEnv);
} else { } else {
processingEnv.getMessager().printMessage(Kind.NOTE, processingEnv.getMessager().printMessage(Kind.NOTE, "finished working on annotation " + annotations);
"finished working on annotation " + annotations); }
return true;
} }
return true;
}
private void processGenerateProperty2Java(RoundEnvironment roundEnv) { 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);
for (Element element : elementsAnnotatedWith) { for (Element element : elementsAnnotatedWith) {
GenerateProperty2Java generateAnnotation = element.getAnnotation(GenerateProperty2Java.class); GenerateProperty2Java generateAnnotation = element.getAnnotation(GenerateProperty2Java.class);
String[] resources = generateAnnotation.resources(); String[] resources = generateAnnotation.resources();
Format format = generateAnnotation.format(); Format format = generateAnnotation.format();
generateElementProperties(element, Arrays.asList(resources), format); generateElementProperties(element, Arrays.asList(resources), format);
}
} }
}
private void processGenerateResourceBundleProperty2Javas(RoundEnvironment roundEnv) { private void processGenerateResourceBundleProperty2Javas(RoundEnvironment roundEnv) {
processingEnv.getMessager().printMessage(Kind.NOTE, processingEnv.getMessager().printMessage(Kind.NOTE,
"Processing annotation " + GenerateResourceBundleProperty2Javas.class); "Processing annotation " + GenerateResourceBundleProperty2Javas.class);
Set<? extends Element> elementsAnnotatedWith = roundEnv Set<? extends Element> elementsAnnotatedWith = roundEnv
.getElementsAnnotatedWith(GenerateResourceBundleProperty2Javas.class); .getElementsAnnotatedWith(GenerateResourceBundleProperty2Javas.class);
for (Element element : elementsAnnotatedWith) { for (Element element : elementsAnnotatedWith) {
GenerateResourceBundleProperty2Java[] value = element GenerateResourceBundleProperty2Java[] value = element
.getAnnotation(GenerateResourceBundleProperty2Javas.class).value(); .getAnnotation(GenerateResourceBundleProperty2Javas.class).value();
for (GenerateResourceBundleProperty2Java generateResourceBundleProperty2Java : value) { for (GenerateResourceBundleProperty2Java generateResourceBundleProperty2Java : value) {
List<String> resources = Arrays.asList(generateResourceBundleProperty2Java.resource()); List<String> resources = Arrays.asList(generateResourceBundleProperty2Java.resource());
generateElementProperties(element, resources, generateResourceBundleProperty2Java.format()); generateElementProperties(element, resources, generateResourceBundleProperty2Java.format());
} }
}
} }
}
private void generateElementProperties(Element element, List<String> resources, Format 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.builder(processingEnv.getFiler(), element).addAll(resources).withFormat(format)
ProcessorConfiguration .startGeneration();
.builder(processingEnv.getFiler(), element) } catch (IOException | GeneratorException e) {
.addAll(resources) StringWriter out = new StringWriter();
.withFormat(format) e.printStackTrace(new PrintWriter(out));
.startGeneration(); out.flush();
} catch (IOException | GeneratorException e) { processingEnv.getMessager().printMessage(Kind.ERROR, "Exception " + e + "\n" + out.toString(), element);
StringWriter out = new StringWriter(); }
e.printStackTrace(new PrintWriter(out));
out.flush();
processingEnv.getMessager().printMessage(Kind.ERROR, "Exception " + e + "\n" + out.toString(),
element);
} }
}
} }

@ -16,18 +16,18 @@ import org.mockito.Mockito;
class ConfigurationTest { class ConfigurationTest {
private Configuration config; private TestImplConfig config;
@BeforeEach @BeforeEach
void initConfig() { void initConfig() {
config = Mockito.mock(Configuration.class); config = Mockito.spy(TestImplConfig.class);
} }
@Test @Test
void defaultWriterIsFileWriter() throws IOException { void defaultWriterIsFileWriter() throws IOException {
when(config.outWriter(anyString())).thenCallRealMethod();
when(config.getRootPath()).thenReturn(new File(".").toPath()); when(config.getRootPath()).thenReturn(new File(".").toPath());
when(config.outWriter(anyString())).thenCallRealMethod();
when(config.mapFilenameToClassName(anyString())).thenCallRealMethod(); when(config.mapFilenameToClassName(anyString())).thenCallRealMethod();
when(config.outputCharset()).thenCallRealMethod(); when(config.outputCharset()).thenCallRealMethod();
@ -50,5 +50,4 @@ class ConfigurationTest {
className = config.mapFilenameToClassName("application_en_US.properties"); className = config.mapFilenameToClassName("application_en_US.properties");
assertEquals("Application_Properties", className); assertEquals("Application_Properties", className);
} }
} }

@ -10,6 +10,7 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.Reader; import java.io.Reader;
import java.io.StringReader; import java.io.StringReader;
@ -26,152 +27,143 @@ import java.util.stream.Collectors;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import de.kreth.property2java.processor.Format;
class GeneratorTests { class GeneratorTests {
private String path = "application.properties"; private String path = "application.properties";
private Configuration config; private Configuration config;
private Generator generator; private Generator generator;
@BeforeEach @BeforeEach
void setUp() throws Exception { void setUp() throws Exception {
Map<String, Reader> input = new HashMap<>(); Map<String, Reader> input = new HashMap<>();
input.put(path, testProperties()); input.put(path, testProperties());
config = mock(Configuration.class); config = Mockito.spy(TestImplConfig.class);
when(config.getInput()).thenReturn(input); when(config.getRootPath()).thenReturn(new File(".").toPath());
when(config.mapFilenameToClassName(anyString())).thenCallRealMethod(); when(config.getFormat()).thenReturn(Format.WithInitializer);
when(config.outputCharset()).thenCallRealMethod(); when(config.getInput()).thenReturn(input);
when(config.mapFilenameToClassName(anyString())).thenCallRealMethod();
generator = new Generator(config); when(config.outputCharset()).thenCallRealMethod();
}
generator = new Generator(config);
@Test }
void testClassDefinition() throws IOException, GeneratorException {
@Test
when(config.getPackage()).thenReturn("de.kreth.property2java"); void testClassDefinition() throws IOException, GeneratorException {
when(config.mapFilenameToClassName(anyString())).thenCallRealMethod();
when(config.getPackage()).thenReturn("de.kreth.property2java");
StringWriter out = new StringWriter(); when(config.mapFilenameToClassName(anyString())).thenCallRealMethod();
when(config.outWriter(anyString())).thenReturn(out);
StringWriter out = new StringWriter();
generator.start(); when(config.outWriter(anyString())).thenReturn(out);
String sourceCode = out.toString().trim(); generator.start();
StringTokenizer sourceTokenizer = new StringTokenizer(sourceCode, "\n");
String linePackage = null; String sourceCode = out.toString().trim();
String lineClass = null; StringTokenizer sourceTokenizer = new StringTokenizer(sourceCode, "\n");
int countOpenBaces = 0; String linePackage = null;
int countCloseBaces = 0; String lineClass = null;
while (sourceTokenizer.hasMoreTokens()) { int countOpenBaces = 0;
String line = sourceTokenizer.nextToken(); int countCloseBaces = 0;
if (line.trim().startsWith("package")) { while (sourceTokenizer.hasMoreTokens()) {
linePackage = line; String line = sourceTokenizer.nextToken();
} else if (line.trim().startsWith("public enum")) { if (line.trim().startsWith("package")) {
lineClass = line; linePackage = line;
} } else if (line.trim().startsWith("public enum")) {
if (line.contains("{")) { lineClass = line;
countOpenBaces++; }
} if (line.contains("{")) {
if (line.contains("}")) { countOpenBaces++;
countCloseBaces++; }
} if (line.contains("}")) {
countCloseBaces++;
}
}
assertEquals(countCloseBaces, countOpenBaces,
"Count of Braces doesn't match. Open = " + countOpenBaces + ", Close = " + countCloseBaces);
assertNotNull(linePackage);
assertNotNull(lineClass);
assertThat(linePackage,
Matchers.stringContainsInOrder(Arrays.asList("package", "de.kreth.property2java", ";")));
assertThat(lineClass,
Matchers.stringContainsInOrder(Arrays.asList("public", "enum", "Application_Properties")));
}
@Test
void testOneInputGeneratesOneOutput() throws IOException, GeneratorException {
Writer out = mock(Writer.class);
Writer nonOut = mock(Writer.class);
when(config.outWriter(anyString())).thenReturn(out, nonOut);
generator.start();
verify(out).close();
verify(nonOut, never()).close();
verify(nonOut, never()).flush();
} }
assertEquals(countCloseBaces, countOpenBaces, @Test
"Count of Braces doesn't match. Open = " + countOpenBaces + ", Close = " + countCloseBaces); void testKeys() throws IOException, GeneratorException {
assertNotNull(linePackage); StringWriter out = new StringWriter();
assertNotNull(lineClass); when(config.outWriter(anyString())).thenReturn(out);
generator.start();
assertThat(linePackage,
Matchers.stringContainsInOrder(Arrays.asList("package", "de.kreth.property2java", ";"))); List<String> lines = out.toString().lines().filter(line -> line.contains(" (\"")).collect(Collectors.toList());
assertThat(lineClass, assertEquals(21, lines.size());
Matchers.stringContainsInOrder(Arrays.asList("public", "enum", "Application_Properties"))); assertLineMatch(lines, "label", "label");
assertLineMatch(lines, "label_addarticle", "label.addarticle");
} assertLineMatch(lines, "label_user_register", "label.user.register");
assertLineMatch(lines, "message_article_priceerror", "message.article.priceerror");
@Test assertLineMatch(lines, "message_invoiceitem_startbeforeend", "message.invoiceitem.startbeforeend");
void testOneInputGeneratesOneOutput() throws IOException, GeneratorException { assertLineMatch(lines, "message_invoiceitem_allfieldsmustbeset", "message.invoiceitem.allfieldsmustbeset");
}
Writer out = mock(Writer.class);
Writer nonOut = mock(Writer.class); private void assertLineMatch(List<String> lines, String key, String expected) {
when(config.outWriter(anyString())).thenReturn(out, nonOut); Optional<String> found = lines.stream().filter(line -> keyMatches(line, key)).findFirst();
generator.start();
verify(out).close(); assertTrue(found.isPresent(), "No line found with key = " + key);
verify(nonOut, never()).close(); final String line = found.get().trim();
verify(nonOut, never()).flush(); int indexEquals = line.indexOf('(');
} String value = line.substring(indexEquals + 1).trim().substring(1);
value = value.substring(0, value.length() - 3);
@Test assertEquals(expected, value, "Line \"" + line + "\" don't match expected Value \"" + expected + "\"");
void testKeys() throws IOException, GeneratorException {
}
StringWriter out = new StringWriter();
when(config.outWriter(anyString())).thenReturn(out); private boolean keyMatches(String line, String key) {
generator.start(); line = line.toLowerCase();
key = key.toLowerCase();
List<String> lines = out.toString().lines().filter(line -> line.contains(" (\"")) return line.contains("\t" + key + " ");
.collect(Collectors.toList()); }
assertEquals(21, lines.size()); private StringReader testProperties() {
assertLineMatch(lines, "label", "label"); return new StringReader("\r\n" + "label = \r\n" + "\r\n" + "label.addarticle = Add Article\r\n"
assertLineMatch(lines, "label_addarticle", "label.addarticle"); + "label.cancel = Cancel\r\n" + "label.close = Close\r\n"
assertLineMatch(lines, "label_user_register", "label.user.register"); + "label.delete = Delete\r\n" + "label.discart = Discart\r\n"
assertLineMatch(lines, "message_article_priceerror", "message.article.priceerror"); + "label.loggedin = Logged in:\r\n" + "label.logout = Logout\r\n"
assertLineMatch(lines, "message_invoiceitem_startbeforeend", + "label.ok = OK\r\n" + "label.store = Store\r\n"
"message.invoiceitem.startbeforeend"); + "label.preview = Preview\r\n" + "label.open = Open\r\n"
assertLineMatch(lines, "message_invoiceitem_allfieldsmustbeset", + "label.user.register = Register\r\n" + "\r\n"
"message.invoiceitem.allfieldsmustbeset"); + "message.article.priceerror = Please set the price.\r\n"
} + "message.delete.text = Delete {0}?\r\n"
+ "message.delete.title = Really delete?\r\n"
private void assertLineMatch(List<String> lines, String key, String expected) { + "message.invoiceitem.allfieldsmustbeset = Start, end and article must not be \\r\\n"
Optional<String> found = lines.stream().filter(line -> keyMatches(line, key)) + " empty!\r\n"
.findFirst(); + "message.invoiceitem.startbeforeend = End must be later than start.\r\n"
+ "message.user.create.success = Thanks {0} created!\r\n"
assertTrue(found.isPresent(), "No line found with key = " + key); + "message.user.loginfailure = Login Error! Wrong user or password?\r\n"
final String line = found.get().trim(); + "message.user.passwordmissmatch = Passwords don't match.\r\n" + "");
int indexEquals = line.indexOf('('); }
String value = line.substring(indexEquals + 1).trim().substring(1);
value = value.substring(0, value.length() - 3);
assertEquals(expected, value, "Line \"" + line + "\" don't match expected Value \"" + expected + "\"");
}
private boolean keyMatches(String line, String key) {
line = line.toLowerCase();
key = key.toLowerCase();
return line.contains("\t" + key + " ");
}
private StringReader testProperties() {
return new StringReader("\r\n" +
"label = \r\n" +
"\r\n" +
"label.addarticle = Add Article\r\n" +
"label.cancel = Cancel\r\n" +
"label.close = Close\r\n" +
"label.delete = Delete\r\n" +
"label.discart = Discart\r\n" +
"label.loggedin = Logged in:\r\n" +
"label.logout = Logout\r\n" +
"label.ok = OK\r\n" +
"label.store = Store\r\n" +
"label.preview = Preview\r\n" +
"label.open = Open\r\n" +
"label.user.register = Register\r\n" +
"\r\n" +
"message.article.priceerror = Please set the price.\r\n" +
"message.delete.text = Delete {0}?\r\n" +
"message.delete.title = Really delete?\r\n" +
"message.invoiceitem.allfieldsmustbeset = Start, end and article must not be \\r\\n" +
" empty!\r\n" +
"message.invoiceitem.startbeforeend = End must be later than start.\r\n" +
"message.user.create.success = Thanks {0} created!\r\n" +
"message.user.loginfailure = Login Error! Wrong user or password?\r\n" +
"message.user.passwordmissmatch = Passwords don't match.\r\n" +
"");
}
} }

@ -0,0 +1,27 @@
package de.kreth.property2java;
import java.io.Reader;
import java.nio.file.Path;
import java.util.Map;
class TestImplConfig implements Configuration {
@Override
public String getPackage() {
// TODO Auto-generated method stub
return null;
}
@Override
public Map<String, Reader> getInput() {
// TODO Auto-generated method stub
return null;
}
@Override
public Path getRootPath() {
// TODO Auto-generated method stub
return null;
}
}

@ -18,29 +18,28 @@ import org.mockito.MockitoAnnotations;
public class Property2JavaGeneratorTest { public class Property2JavaGeneratorTest {
private Property2JavaGenerator processor; private Property2JavaGenerator processor;
@Mock @Mock
private ProcessingEnvironment processingEnv; private ProcessingEnvironment processingEnv;
@Mock @Mock
private RoundEnvironment roundEnv; private RoundEnvironment roundEnv;
private Set<TypeElement> annotations; private Set<TypeElement> annotations;
@Mock @Mock
private Messager messanger; private Messager messanger;
@BeforeEach @BeforeEach
void initProcesor() { void initProcesor() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
annotations = new HashSet<>(); annotations = new HashSet<>();
processor = new Property2JavaGenerator(); processor = new Property2JavaGenerator();
processor.init(processingEnv); processor.init(processingEnv);
when(processingEnv.getMessager()).thenReturn(messanger); when(processingEnv.getMessager()).thenReturn(messanger);
} }
@Test @Test
void testGeneratorInitializedCorrectly() { void testGeneratorInitializedCorrectly() {
when(roundEnv.getElementsAnnotatedWith(ArgumentMatchers.any(Class.class))) when(roundEnv.getElementsAnnotatedWith(ArgumentMatchers.any(Class.class))).thenReturn(annotations);
.thenReturn(annotations); processor.process(annotations, roundEnv);
processor.process(annotations, roundEnv); }
}
} }

Loading…
Cancel
Save