mirror of
https://github.com/JHUAPL/Jackfruit.git
synced 2026-01-09 14:18:05 -05:00
Resolve "add comments to Apache file"
This commit is contained in:
80
README.md
80
README.md
@@ -1,2 +1,82 @@
|
||||
# jackfruit
|
||||
|
||||
## Introduction
|
||||
|
||||
Jackfruit processes annotations on Java interfaces to generate code that can read and write Apache Configuration files. Include Jackfruit in your project with the following POM:
|
||||
|
||||
```
|
||||
POM GOES HERE
|
||||
```
|
||||
|
||||
An example of an annotated interface is
|
||||
```
|
||||
@Jackfruit(prefix = "prefix")
|
||||
public interface DemoConfig {
|
||||
|
||||
// default key is field name
|
||||
@Key("key")
|
||||
@Comment("field comment")
|
||||
@DefaultValue("0")
|
||||
public int intMethod();
|
||||
|
||||
@DefaultValue("0.")
|
||||
public Double doubleMethod();
|
||||
|
||||
@DefaultValue("Default String")
|
||||
public String StringMethod();
|
||||
|
||||
@Comment("This string is serialized into an object")
|
||||
@DefaultValue("serialized string")
|
||||
@ParserClass(SomeRandomClassParser.class)
|
||||
public SomeRandomClass randomClass();
|
||||
}
|
||||
```
|
||||
|
||||
This corresponds to this Apache Configuration file:
|
||||
```
|
||||
# field comment
|
||||
prefix.key = 0
|
||||
prefix.doubleMethod = 0.0
|
||||
prefix.StringMethod = Default String
|
||||
# This string is serialized into an object
|
||||
prefix.randomClass = serialized string
|
||||
```
|
||||
|
||||
The annotation processor generates a class called DemoConfigFactory. An example of use is
|
||||
```
|
||||
// this factory is built by the annotation processor after reading the DemoConfig interface
|
||||
DemoConfigFactory factory = new DemoConfigFactory();
|
||||
|
||||
// get an example config object
|
||||
DemoConfig template = factory.getTemplate();
|
||||
|
||||
// generate an Apache PropertiesConfiguration object. This can be written out to a file
|
||||
PropertiesConfiguration config =
|
||||
factory.toConfig(template, new PropertiesConfigurationLayout());
|
||||
|
||||
try {
|
||||
// this is the template, with comments
|
||||
config.write(new PrintWriter(System.out));
|
||||
|
||||
// write to file
|
||||
File tmpFile = File.createTempFile("tmp", ".config");
|
||||
tmpFile.deleteOnExit();
|
||||
// System.out.println("wrote "+tmpFile.getAbsolutePath());
|
||||
config.write(new PrintWriter(tmpFile));
|
||||
|
||||
// read from file
|
||||
config = new Configurations().properties(tmpFile);
|
||||
|
||||
// print to screen
|
||||
config.write(new PrintWriter(System.out));
|
||||
|
||||
} catch (ConfigurationException | IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// create a config object from an Apache PropertiesConfiguration
|
||||
template = factory.fromConfig(config);
|
||||
|
||||
// get one of the config object's properties
|
||||
System.out.printf("config.StringMethod() = %s\n", template.StringMethod());
|
||||
```
|
||||
@@ -7,6 +7,6 @@ import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface ConfigParams {
|
||||
public @interface Jackfruit {
|
||||
public String prefix() default "";
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package jackfruit.processor;
|
||||
|
||||
import org.apache.commons.configuration2.Configuration;
|
||||
import org.apache.commons.configuration2.PropertiesConfiguration;
|
||||
import org.apache.commons.configuration2.PropertiesConfigurationLayout;
|
||||
|
||||
public interface ConfigFactory<T> {
|
||||
|
||||
@@ -9,6 +10,6 @@ public interface ConfigFactory<T> {
|
||||
|
||||
public T fromConfig(Configuration config);
|
||||
|
||||
public PropertiesConfiguration toConfig(T t);
|
||||
public PropertiesConfiguration toConfig(T t, PropertiesConfigurationLayout layout);
|
||||
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ import com.squareup.javapoet.TypeName;
|
||||
import com.squareup.javapoet.TypeSpec;
|
||||
import com.squareup.javapoet.TypeVariableName;
|
||||
import jackfruit.annotations.Comment;
|
||||
import jackfruit.annotations.ConfigParams;
|
||||
import jackfruit.annotations.Jackfruit;
|
||||
import jackfruit.annotations.DefaultValue;
|
||||
import jackfruit.annotations.Key;
|
||||
import jackfruit.annotations.ParserClass;
|
||||
@@ -53,7 +53,7 @@ import jackfruit.annotations.ParserClass;
|
||||
*
|
||||
*/
|
||||
@SupportedSourceVersion(SourceVersion.RELEASE_17)
|
||||
@SupportedAnnotationTypes("jackfruit.annotations.ConfigParams")
|
||||
@SupportedAnnotationTypes("jackfruit.annotations.Jackfruit")
|
||||
@AutoService(Processor.class)
|
||||
public class ConfigProcessor extends AbstractProcessor {
|
||||
|
||||
@@ -68,8 +68,8 @@ public class ConfigProcessor extends AbstractProcessor {
|
||||
|
||||
Messager messager = processingEnv.getMessager();
|
||||
|
||||
List<Element> annotatedInterfaces = roundEnv.getElementsAnnotatedWith(ConfigParams.class)
|
||||
.stream().filter(e -> e.getKind() == ElementKind.INTERFACE).collect(Collectors.toList());
|
||||
List<Element> annotatedInterfaces = roundEnv.getElementsAnnotatedWith(Jackfruit.class).stream()
|
||||
.filter(e -> e.getKind() == ElementKind.INTERFACE).collect(Collectors.toList());
|
||||
|
||||
for (Element element : annotatedInterfaces) {
|
||||
|
||||
@@ -77,8 +77,7 @@ public class ConfigProcessor extends AbstractProcessor {
|
||||
if (element instanceof TypeElement) {
|
||||
TypeElement annotatedType = (TypeElement) element;
|
||||
|
||||
ConfigParams configParams =
|
||||
(ConfigParams) annotatedType.getAnnotation(ConfigParams.class);
|
||||
Jackfruit configParams = (Jackfruit) annotatedType.getAnnotation(Jackfruit.class);
|
||||
String prefix = configParams.prefix();
|
||||
if (prefix.length() > 0)
|
||||
prefix += ".";
|
||||
@@ -87,8 +86,8 @@ public class ConfigProcessor extends AbstractProcessor {
|
||||
TypeVariableName tvn = TypeVariableName.get(annotatedType.getSimpleName().toString());
|
||||
|
||||
// This is the generic class; e.g. "ConfigFactory<TestConfig>"
|
||||
ParameterizedTypeName ptn =
|
||||
ParameterizedTypeName.get(ClassName.get(jackfruit.processor.ConfigFactory.class), tvn);
|
||||
ParameterizedTypeName ptn = ParameterizedTypeName
|
||||
.get(ClassName.get(jackfruit.processor.ConfigFactory.class), tvn);
|
||||
|
||||
String factoryName = String.format("%sFactory", annotatedType.getSimpleName());
|
||||
|
||||
@@ -209,28 +208,44 @@ public class ConfigProcessor extends AbstractProcessor {
|
||||
private MethodSpec buildToConfig(TypeVariableName tvn, Method m,
|
||||
Map<ExecutableElement, AnnotationBundle> annotationsMap, String prefix) {
|
||||
ParameterSpec ps = ParameterSpec.builder(tvn, "t").build();
|
||||
ParameterSpec layout = ParameterSpec.builder(TypeVariableName.get(
|
||||
org.apache.commons.configuration2.PropertiesConfigurationLayout.class.getCanonicalName()),
|
||||
"layout").build();
|
||||
MethodSpec.Builder methodBuilder =
|
||||
MethodSpec.methodBuilder(m.getName()).addAnnotation(Override.class)
|
||||
.addModifiers(Modifier.PUBLIC).returns(m.getGenericReturnType()).addParameter(ps);
|
||||
.addModifiers(Modifier.PUBLIC).returns(m.getGenericReturnType());
|
||||
methodBuilder.addParameter(ps);
|
||||
methodBuilder.addParameter(layout);
|
||||
|
||||
methodBuilder.addStatement("$T config = new $T()",
|
||||
org.apache.commons.configuration2.PropertiesConfiguration.class,
|
||||
org.apache.commons.configuration2.PropertiesConfiguration.class);
|
||||
methodBuilder.addStatement("config.setLayout($N)", layout);
|
||||
|
||||
boolean needBlank = true;
|
||||
for (ExecutableElement method : annotationsMap.keySet()) {
|
||||
AnnotationBundle ab = annotationsMap.get(method);
|
||||
String key = prefix + ab.key();
|
||||
if (needBlank) {
|
||||
methodBuilder.addStatement(String.format("$N.setBlancLinesBefore(\"%s\", 1)", key), layout);
|
||||
needBlank = false;
|
||||
}
|
||||
if (ab.parserClass().isPresent()) {
|
||||
TypeMirror parser = ab.parserClass().get();
|
||||
String parserName = method.getSimpleName() + "parser";
|
||||
methodBuilder.addStatement("$T " + parserName + " = new $T()", parser, parser);
|
||||
methodBuilder.addStatement(String.format("config.setProperty(\"%s\", %s.toString($N.%s()))",
|
||||
prefix + ab.key(), parserName, method.getSimpleName()), ps);
|
||||
key, parserName, method.getSimpleName()), ps);
|
||||
} else {
|
||||
methodBuilder.addStatement(String.format("config.setProperty(\"%s\", t.%s())",
|
||||
prefix + ab.key(), method.getSimpleName()));
|
||||
methodBuilder.addStatement(
|
||||
String.format("config.setProperty(\"%s\", t.%s())", key, method.getSimpleName()));
|
||||
}
|
||||
if (ab.comment().length() > 0)
|
||||
methodBuilder.addStatement(
|
||||
String.format("$N.setComment(\"%s\", \"%s\")", key, ab.comment()), layout);
|
||||
}
|
||||
|
||||
|
||||
methodBuilder.addCode("return config;");
|
||||
|
||||
return methodBuilder.build();
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
169
demo/pom.xml
169
demo/pom.xml
@@ -1,90 +1,95 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>jackfruit</artifactId>
|
||||
<groupId>edu.jhuapl.ses.srn</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>jackfruit</artifactId>
|
||||
<groupId>edu.jhuapl.ses.srn</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>demo</artifactId>
|
||||
<artifactId>demo</artifactId>
|
||||
|
||||
<name>demo</name>
|
||||
<!-- FIXME change it to the project's website -->
|
||||
<url>http://www.example.com</url>
|
||||
<name>demo</name>
|
||||
<!-- FIXME change it to the project's website -->
|
||||
<url>http://www.example.com</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
</properties>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>edu.jhuapl.ses.saa</groupId>
|
||||
<artifactId>crucible-all</artifactId>
|
||||
<version>1.0.0-b74-7d477359</version>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>edu.jhuapl.ses.srn</groupId>
|
||||
<artifactId>annotations</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.11</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>commons-beanutils</groupId>
|
||||
<artifactId>commons-beanutils</artifactId>
|
||||
<version>1.9.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>edu.jhuapl.ses.saa</groupId>
|
||||
<artifactId>crucible-all</artifactId>
|
||||
<version>1.0.0-b74-7d477359</version>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>edu.jhuapl.ses.srn</groupId>
|
||||
<artifactId>annotations</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.11</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<pluginManagement><!-- lock down plugins versions to avoid using Maven
|
||||
defaults (may be moved to parent pom) -->
|
||||
<plugins>
|
||||
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
|
||||
<plugin>
|
||||
<artifactId>maven-clean-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
</plugin>
|
||||
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
|
||||
<plugin>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>3.0.2</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.22.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.0.2</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-install-plugin</artifactId>
|
||||
<version>2.5.2</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<version>2.8.2</version>
|
||||
</plugin>
|
||||
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
|
||||
<plugin>
|
||||
<artifactId>maven-site-plugin</artifactId>
|
||||
<version>3.7.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-project-info-reports-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
<build>
|
||||
<pluginManagement><!-- lock down plugins versions to avoid using Maven
|
||||
defaults (may be moved to parent pom) -->
|
||||
<plugins>
|
||||
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
|
||||
<plugin>
|
||||
<artifactId>maven-clean-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
</plugin>
|
||||
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
|
||||
<plugin>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>3.0.2</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.22.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.0.2</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-install-plugin</artifactId>
|
||||
<version>2.5.2</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<version>2.8.2</version>
|
||||
</plugin>
|
||||
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
|
||||
<plugin>
|
||||
<artifactId>maven-site-plugin</artifactId>
|
||||
<version>3.7.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-project-info-reports-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
</project>
|
||||
|
||||
Binary file not shown.
@@ -1,7 +1,7 @@
|
||||
package jackfruit.demo;
|
||||
|
||||
import jackfruit.annotations.Comment;
|
||||
import jackfruit.annotations.ConfigParams;
|
||||
import jackfruit.annotations.Jackfruit;
|
||||
import jackfruit.annotations.DefaultValue;
|
||||
import jackfruit.annotations.Key;
|
||||
import jackfruit.annotations.ParserClass;
|
||||
@@ -45,7 +45,7 @@ import jackfruit.annotations.ParserClass;
|
||||
*
|
||||
*/
|
||||
|
||||
@ConfigParams(prefix = "prefix")
|
||||
@Jackfruit(prefix = "prefix")
|
||||
public interface DemoConfig {
|
||||
|
||||
// default key is field name
|
||||
@@ -60,7 +60,7 @@ public interface DemoConfig {
|
||||
@DefaultValue("Default String")
|
||||
public String StringMethod();
|
||||
|
||||
// parser creates an object from a string
|
||||
@Comment("This string is serialized into an object")
|
||||
@DefaultValue("serialized string")
|
||||
@ParserClass(SomeRandomClassParser.class)
|
||||
public SomeRandomClass randomClass();
|
||||
|
||||
Binary file not shown.
@@ -1,8 +1,11 @@
|
||||
package jackfruit.demo;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import org.apache.commons.configuration2.PropertiesConfiguration;
|
||||
import org.apache.commons.configuration2.PropertiesConfigurationLayout;
|
||||
import org.apache.commons.configuration2.builder.fluent.Configurations;
|
||||
import org.apache.commons.configuration2.ex.ConfigurationException;
|
||||
|
||||
public class JackfruitDemo {
|
||||
@@ -15,22 +18,35 @@ public class JackfruitDemo {
|
||||
// get an example config object
|
||||
DemoConfig template = factory.getTemplate();
|
||||
|
||||
// generate an Apache PropertiesConfiguration object. This can be written out to a file
|
||||
PropertiesConfiguration config = factory.toConfig(template);
|
||||
// generate an Apache PropertiesConfiguration object. This can be written out to a file
|
||||
PropertiesConfiguration config =
|
||||
factory.toConfig(template, new PropertiesConfigurationLayout());
|
||||
|
||||
try {
|
||||
// this is the template, with comments
|
||||
config.write(new PrintWriter(System.out));
|
||||
|
||||
// write to file
|
||||
File tmpFile = File.createTempFile("tmp", ".config");
|
||||
tmpFile.deleteOnExit();
|
||||
// System.out.println("wrote "+tmpFile.getAbsolutePath());
|
||||
config.write(new PrintWriter(tmpFile));
|
||||
|
||||
// read from file
|
||||
config = new Configurations().properties(tmpFile);
|
||||
|
||||
// print to screen - this still has comments?
|
||||
config.write(new PrintWriter(System.out));
|
||||
|
||||
} catch (ConfigurationException | IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// create a config object from an Apache PropertiesConfiguration
|
||||
template = factory.fromConfig(config);
|
||||
|
||||
System.out.printf("config.StringMethod() = %s\n", template.StringMethod());
|
||||
|
||||
|
||||
|
||||
// get one of the config object's properties
|
||||
System.out.printf("config.StringMethod() = %s\n", template.StringMethod());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -36,7 +36,7 @@ public class TestProcessor {
|
||||
System.out.println(System.getProperty("java.class.path"));
|
||||
*/
|
||||
|
||||
boolean ignore = false;
|
||||
boolean ignore = true;
|
||||
if (!ignore) {
|
||||
Log4j2Configurator lc = Log4j2Configurator.getInstance();
|
||||
lc.setPattern("%highlight{%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%c{1}:%L] %msg%n%throwable}");
|
||||
|
||||
Reference in New Issue
Block a user