diff --git a/org.eclipse.ice.dev/.gitignore b/org.eclipse.ice.dev/.gitignore index 0f630157f4bf530f9697788f383cabaab83dc2e8..e4df9b2abca99d5c34e012b667282a0ccf423a0f 100644 --- a/org.eclipse.ice.dev/.gitignore +++ b/org.eclipse.ice.dev/.gitignore @@ -1,2 +1,3 @@ /target/ /bin/ +.factorypath diff --git a/org.eclipse.ice.dev/org.eclipse.ice.dev.annotations.proxytest/.classpath b/org.eclipse.ice.dev/org.eclipse.ice.dev.annotations.proxytest/.classpath index d66f66369ba7e695bb907957bafee643d23a5820..edcf841d21c05aff38d44630d216029bd76d72bc 100644 --- a/org.eclipse.ice.dev/org.eclipse.ice.dev.annotations.proxytest/.classpath +++ b/org.eclipse.ice.dev/org.eclipse.ice.dev.annotations.proxytest/.classpath @@ -24,5 +24,16 @@ </attributes> </classpathentry> <classpathentry kind="src" path="/org.eclipse.ice.dev.annotations"/> + <classpathentry kind="src" path="target/generated-sources/annotations"> + <attributes> + <attribute name="optional" value="true"/> + </attributes> + </classpathentry> + <classpathentry kind="src" output="target/test-classes" path="target/generated-test-sources/test-annotations"> + <attributes> + <attribute name="optional" value="true"/> + <attribute name="test" value="true"/> + </attributes> + </classpathentry> <classpathentry kind="output" path="target/classes"/> </classpath> diff --git a/org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/DataElementProcessor.java b/org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/DataElementProcessor.java index 7876883d1220db90d4ce05660bd7d58b7fe76132..17536a24f6cdb791441a24a86fce749673180b15 100644 --- a/org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/DataElementProcessor.java +++ b/org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/DataElementProcessor.java @@ -8,7 +8,6 @@ import java.io.Writer; import java.util.Arrays; import java.util.ArrayList; import java.util.List; -import java.util.Properties; import java.util.Set; import javax.annotation.processing.AbstractProcessor; @@ -26,8 +25,6 @@ import javax.tools.Diagnostic; import javax.tools.JavaFileObject; import javax.tools.StandardLocation; -import org.apache.velocity.VelocityContext; -import org.apache.velocity.app.Velocity; import org.eclipse.ice.dev.annotations.DataElement; import org.eclipse.ice.dev.annotations.Persisted; @@ -50,31 +47,6 @@ import com.google.auto.service.AutoService; @SupportedSourceVersion(SourceVersion.RELEASE_11) @AutoService(Processor.class) public class DataElementProcessor extends AbstractProcessor { - - /** - * Location of DataElement template for use with velocity. - * - * Use of Velocity ClasspathResourceLoader means files are discovered relative - * to the src/main/resources folder. - */ - private static final String DATAELEMENT_TEMPLATE = "templates/DataElement.vm"; - - /** - * Location of PersistenceHandler template for use with velocity. - * - * Use of Velocity ClasspathResourceLoader means files are discovered relative - * to the src/main/resources folder. - */ - private static final String PERSISTENCE_HANDLER_TEMPLATE = "templates/PersistenceHandler.vm"; - - /** - * Location of Interface template for use with velocity. - * - * Use of Velocity ClasspathResourceLoader means files are discovered relative - * to the src/main/resources folder. - */ - private static final String INTERFACE_TEMPLATE = "templates/ElementInterface.vm"; - /** * Return stack trace as string. * @param e subject exception @@ -97,15 +69,6 @@ public class DataElementProcessor extends AbstractProcessor { messager = env.getMessager(); elementUtils = env.getElementUtils(); mapper = new ObjectMapper(); - - // Set up Velocity using the Singleton approach; ClasspathResourceLoader allows - // us to load templates from src/main/resources - final Properties p = new Properties(); - for (VelocityProperty vp : VelocityProperty.values()) { - p.setProperty(vp.key(), vp.value()); - } - Velocity.init(p); - super.init(env); } @@ -127,7 +90,7 @@ public class DataElementProcessor extends AbstractProcessor { writeInterface(dataElement, fields); // Write the DataElement Implementation to file. - writeClass(dataElement, fields); + writeImpl(dataElement, fields); // Check if Persistence should be generated. if (dataElement.hasAnnotation(Persisted.class)) { @@ -177,19 +140,17 @@ public class DataElementProcessor extends AbstractProcessor { * @param fields * @throws IOException */ - private void writeClass(DataElementSpec element, final Fields fields) throws IOException { - // Prepare context of template - final VelocityContext context = new VelocityContext(); - context.put(DataElementTemplateProperty.PACKAGE.getKey(), element.getPackageName()); - context.put(DataElementTemplateProperty.INTERFACE.getKey(), element.getName()); - context.put(DataElementTemplateProperty.CLASS.getKey(), element.getImplName()); - context.put(DataElementTemplateProperty.FIELDS.getKey(), fields); - - // Write to file + private void writeImpl(DataElementSpec element, final Fields fields) throws IOException { final JavaFileObject generatedClassFile = processingEnv.getFiler() .createSourceFile(element.getQualifiedImplName()); try (Writer writer = generatedClassFile.openWriter()) { - Velocity.mergeTemplate(DATAELEMENT_TEMPLATE, "UTF-8", context, writer); + ImplementationWriter.builder() + .packageName(element.getPackageName()) + .className(element.getImplName()) + .interfaceName(element.getName()) + .fields(fields) + .build() + .write(writer); } } @@ -205,38 +166,19 @@ public class DataElementProcessor extends AbstractProcessor { final String collectionName, Fields fields ) throws IOException { - // Prepare context of template - final VelocityContext context = new VelocityContext(); - context.put( - PersistenceHandlerTemplateProperty.PACKAGE.getKey(), - element.getPackageName() - ); - context.put( - PersistenceHandlerTemplateProperty.ELEMENT_INTERFACE.getKey(), - element.getName() - ); - context.put( - PersistenceHandlerTemplateProperty.CLASS.getKey(), - element.getPersistenceHandlerName() - ); - context.put( - PersistenceHandlerTemplateProperty.COLLECTION.getKey(), - collectionName - ); - context.put( - PersistenceHandlerTemplateProperty.IMPLEMENTATION.getKey(), - element.getImplName() - ); - context.put( - PersistenceHandlerTemplateProperty.FIELDS.getKey(), - fields - ); - // Write to file final JavaFileObject generatedClassFile = processingEnv.getFiler() .createSourceFile(element.getQualifiedPersistenceHandlerName()); try (Writer writer = generatedClassFile.openWriter()) { - Velocity.mergeTemplate(PERSISTENCE_HANDLER_TEMPLATE, "UTF-8", context, writer); + PersistenceHandlerWriter.builder() + .packageName(element.getPackageName()) + .elementInterface(element.getName()) + .className(element.getPersistenceHandlerName()) + .implementation(element.getImplName()) + .collection(collectionName) + .fields(fields) + .build() + .write(writer); } } @@ -250,26 +192,15 @@ public class DataElementProcessor extends AbstractProcessor { DataElementSpec element, Fields fields ) throws IOException { - // Prepare context of template - final VelocityContext context = new VelocityContext(); - context.put( - InterfaceTemplateProperty.PACKAGE.getKey(), - element.getPackageName() - ); - context.put( - InterfaceTemplateProperty.INTERFACE.getKey(), - element.getName() - ); - context.put( - PersistenceHandlerTemplateProperty.FIELDS.getKey(), - fields - ); - - // Write to file final JavaFileObject generatedClassFile = processingEnv.getFiler() .createSourceFile(element.getFullyQualifiedName()); try (Writer writer = generatedClassFile.openWriter()) { - Velocity.mergeTemplate(INTERFACE_TEMPLATE, "UTF-8", context, writer); + InterfaceWriter.builder() + .packageName(element.getPackageName()) + .interfaceName(element.getName()) + .fields(fields) + .build() + .write(writer); } } } diff --git a/org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/DataElementTemplateProperty.java b/org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/DataElementTemplateProperty.java deleted file mode 100644 index 33c4e622f482f5ac9f046b2f2aa5e11074194235..0000000000000000000000000000000000000000 --- a/org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/DataElementTemplateProperty.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.eclipse.ice.dev.annotations.processors; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * Enumeration for Keys used in DataElement Velocity Template. - */ -@AllArgsConstructor -enum DataElementTemplateProperty { - PACKAGE("package"), - FIELDS("fields"), - INTERFACE("interface"), - CLASS("class"); - - @Getter private String key; -} \ No newline at end of file diff --git a/org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/ImplementationWriter.java b/org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/ImplementationWriter.java new file mode 100644 index 0000000000000000000000000000000000000000..92accc8c84b1f1dcd180d7700d629de519eb351e --- /dev/null +++ b/org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/ImplementationWriter.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2020- UT-Battelle, LLC. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daniel Bluhm - Initial implementation + *******************************************************************************/ + +package org.eclipse.ice.dev.annotations.processors; + +import lombok.Builder; + +/** + * Writer for DataElement Implementation classes. + * @author Daniel Bluhm + */ +public class ImplementationWriter extends VelocitySourceWriter { + + /** + * Location of DataElement template for use with velocity. + * + * Use of Velocity ClasspathResourceLoader means files are discovered relative + * to the src/main/resources folder. + */ + private static final String IMPL_TEMPLATE = "templates/DataElement.vm"; + + /** + * Context key for package. + */ + private static final String PACKAGE = "package"; + + /** + * Context key for interface. + */ + private static final String INTERFACE = "interface"; + + /** + * Context key for fields. + */ + private static final String FIELDS = "fields"; + + /** + * Context key for class. + */ + private static final String CLASS = "class"; + + @Builder + public ImplementationWriter( + String packageName, String interfaceName, String className, Fields fields + ) { + super(); + this.template = IMPL_TEMPLATE; + this.context.put(PACKAGE, packageName); + this.context.put(INTERFACE, interfaceName); + this.context.put(CLASS, className); + this.context.put(FIELDS, fields); + } +} diff --git a/org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/InterfaceTemplateProperty.java b/org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/InterfaceTemplateProperty.java deleted file mode 100644 index b15ff2848a852b8e15789496818a085da63f34d8..0000000000000000000000000000000000000000 --- a/org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/InterfaceTemplateProperty.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.eclipse.ice.dev.annotations.processors; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * Enumeration of keys of Interface Template. - * @author Daniel Bluhm - */ -@AllArgsConstructor -enum InterfaceTemplateProperty { - PACKAGE("package"), - INTERFACE("interface"), - FIELDS("fields"); - - @Getter private String key; -} diff --git a/org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/InterfaceWriter.java b/org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/InterfaceWriter.java new file mode 100644 index 0000000000000000000000000000000000000000..c0b68bb7cf5c944aa4f02d589f1e8f9f9e50840a --- /dev/null +++ b/org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/InterfaceWriter.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2020- UT-Battelle, LLC. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daniel Bluhm - Initial implementation + *******************************************************************************/ + +package org.eclipse.ice.dev.annotations.processors; + +import lombok.Builder; +import lombok.NonNull; + +/** + * Writer for DataElement Interfaces. + * @author Daniel Bluhm + */ +public class InterfaceWriter extends VelocitySourceWriter { + + /** + * Location of Interface template for use with velocity. + * + * Use of Velocity ClasspathResourceLoader means files are discovered relative + * to the src/main/resources folder. + */ + private static final String TEMPLATE = "templates/ElementInterface.vm"; + + /** + * Context key for package. + */ + private static final String PACKAGE = "package"; + + /** + * Context key for interface. + */ + private static final String INTERFACE = "interface"; + + /** + * Context key for fields. + */ + private static final String FIELDS = "fields"; + + @Builder + public InterfaceWriter( + String packageName, String interfaceName, @NonNull Fields fields + ) { + super(); + this.template = TEMPLATE; + context.put(PACKAGE, packageName); + context.put(INTERFACE, interfaceName); + context.put(FIELDS, fields); + } +} diff --git a/org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/PersistenceHandlerTemplateProperty.java b/org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/PersistenceHandlerTemplateProperty.java deleted file mode 100644 index 53e51835f9533ed42a84e7e85de52aca0131536a..0000000000000000000000000000000000000000 --- a/org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/PersistenceHandlerTemplateProperty.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.eclipse.ice.dev.annotations.processors; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * Enumeration of keys of Persistence Handler Template. - * @author Daniel Bluhm - */ -@AllArgsConstructor -enum PersistenceHandlerTemplateProperty { - PACKAGE("package"), - ELEMENT_INTERFACE("elementInterface"), - CLASS("class"), - COLLECTION("collection"), - IMPLEMENTATION("implementation"), - FIELDS("fields"); - - @Getter private String key; -} \ No newline at end of file diff --git a/org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/PersistenceHandlerWriter.java b/org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/PersistenceHandlerWriter.java new file mode 100644 index 0000000000000000000000000000000000000000..1ba3f8a996bb1a8bd37c926c5e2e80e0bc241375 --- /dev/null +++ b/org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/PersistenceHandlerWriter.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * Copyright (c) 2020- UT-Battelle, LLC. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daniel Bluhm - Initial implementation + *******************************************************************************/ + +package org.eclipse.ice.dev.annotations.processors; + +import lombok.Builder; +import lombok.NonNull; + +/** + * Writer for DataElement Persistence classes. + * @author Daniel Bluhm + */ +public class PersistenceHandlerWriter extends VelocitySourceWriter { + + /** + * Location of PersistenceHandler template for use with velocity. + * + * Use of Velocity ClasspathResourceLoader means files are discovered relative + * to the src/main/resources folder. + */ + private static final String PERSISTENCE_HANDLER_TEMPLATE = "templates/PersistenceHandler.vm"; + + /** + * Context key for package. + */ + private static final String PACKAGE = "package"; + + /** + * Context key for element interface. + */ + private static final String ELEMENT_INTERFACE = "elementInterface"; + + /** + * Context key for class + */ + private static final String CLASS = "class"; + + /** + * Context key for collection. + */ + private static final String COLLECTION = "collection"; + + /** + * Context key for implementation. + */ + private static final String IMPLEMENTATION = "implementation"; + + /** + * Context key for fields. + */ + private static final String FIELDS = "fields"; + + @Builder + public PersistenceHandlerWriter( + String packageName, String elementInterface, String className, + String implementation, String collection, @NonNull Fields fields + ) { + super(); + this.template = PERSISTENCE_HANDLER_TEMPLATE; + this.context.put(PACKAGE, packageName); + this.context.put(ELEMENT_INTERFACE, elementInterface); + this.context.put(CLASS, className); + this.context.put(COLLECTION, collection); + this.context.put(IMPLEMENTATION, implementation); + this.context.put(FIELDS, fields); + } +} diff --git a/org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/VelocityProperties.java b/org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/VelocityProperties.java new file mode 100644 index 0000000000000000000000000000000000000000..6ca86eee41445863be38bdf86fdeea97a5f704ea --- /dev/null +++ b/org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/VelocityProperties.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (c) 2020- UT-Battelle, LLC. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daniel Bluhm - Initial implementation + *******************************************************************************/ + +package org.eclipse.ice.dev.annotations.processors; + +import java.util.Properties; + +/** + * Properties used to initialize Velocity. + */ +enum VelocityProperties { + + // Set up Velocity using the Singleton approach; ClasspathResourceLoader allows + // us to load templates from src/main/resources + RESOURCE_LOADER("resource.loader", "class"), + CLASS_RESOURCE_LOADER( + "class.resource.loader.class", + "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader" + ); + + /** + * Property key. + */ + private String key; + + /** + * Property value. + */ + private String value; + + VelocityProperties(String key, String value) { + this.key = key; + this.value = value; + } + + /** + * Get key from enum. + * @return key + */ + String key() { + return this.key; + } + + /** + * Get value from enum. + * @return value + */ + String value() { + return this.value; + } + + /** + * Generate and return Properties from enum. + * @return Properties + */ + public static Properties get() { + Properties p = new Properties(); + for (VelocityProperties vp : VelocityProperties.values()) { + p.setProperty(vp.key(), vp.value()); + } + return p; + } +} \ No newline at end of file diff --git a/org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/VelocityProperty.java b/org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/VelocityProperty.java deleted file mode 100644 index 80b7eaac68a3b4c227872b27b82c49dbc5deb993..0000000000000000000000000000000000000000 --- a/org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/VelocityProperty.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.eclipse.ice.dev.annotations.processors; - -/** - * Properties used to initialize Velocity. - */ -enum VelocityProperty { - RESOURCE_LOADER("resource.loader", "class"), - CLASS_RESOURCE_LOADER( - "class.resource.loader.class", - "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader" - ); - - private String key; - private String value; - - VelocityProperty(String key, String value) { - this.key = key; - this.value = value; - } - - String key() { - return this.key; - } - - String value() { - return this.value; - } -} \ No newline at end of file diff --git a/org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/VelocitySourceWriter.java b/org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/VelocitySourceWriter.java new file mode 100644 index 0000000000000000000000000000000000000000..a49aa7187cfb79101bc5008210bb5b29cbe1c1bf --- /dev/null +++ b/org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/VelocitySourceWriter.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2020- UT-Battelle, LLC. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daniel Bluhm - Initial implementation + *******************************************************************************/ + +package org.eclipse.ice.dev.annotations.processors; + +import java.io.Writer; +import java.util.HashMap; +import java.util.Map; + +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; + +/** + * Abstract base class for classes that render a Java Source file through + * velocity templates. + * @author Daniel Bluhm + */ +public abstract class VelocitySourceWriter { + + protected String template; + protected Map<String, Object> context; + + public VelocitySourceWriter() { + this.context = new HashMap<>(); + } + + /** + * Write the Java Source file to the open writer. + * @param writer to which the java source will be written + */ + public void write(Writer writer) { + // Make sure Velocity is initialized. Subsequent calls are harmless. + Velocity.init(VelocityProperties.get()); + + // Make velocity context from generic map context. + Context velocityContext = new VelocityContext(context); + + // Write template from context. + Velocity.mergeTemplate(template, "UTF-8", velocityContext, writer); + } +} diff --git a/org.eclipse.ice.dev/org.eclipse.ice.dev.pojofromjson/.classpath b/org.eclipse.ice.dev/org.eclipse.ice.dev.pojofromjson/.classpath new file mode 100644 index 0000000000000000000000000000000000000000..eacc5f13553b202ae71979fadf87d957afd02692 --- /dev/null +++ b/org.eclipse.ice.dev/org.eclipse.ice.dev.pojofromjson/.classpath @@ -0,0 +1,50 @@ +<?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 kind="src" output="target/test-classes" path="src/test/java"> + <attributes> + <attribute name="test" value="true"/> + <attribute name="optional" value="true"/> + <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="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 kind="src" path="target/generated-sources/annotations"> + <attributes> + <attribute name="optional" value="true"/> + <attribute name="maven.pomderived" value="true"/> + <attribute name="ignore_optional_problems" value="true"/> + <attribute name="m2e-apt" value="true"/> + </attributes> + </classpathentry> + <classpathentry kind="src" output="target/test-classes" path="target/generated-test-sources/test-annotations"> + <attributes> + <attribute name="optional" value="true"/> + <attribute name="maven.pomderived" value="true"/> + <attribute name="ignore_optional_problems" value="true"/> + <attribute name="m2e-apt" value="true"/> + <attribute name="test" value="true"/> + </attributes> + </classpathentry> + <classpathentry kind="output" path="target/classes"/> +</classpath> diff --git a/org.eclipse.ice.dev/org.eclipse.ice.dev.pojofromjson/.gitignore b/org.eclipse.ice.dev/org.eclipse.ice.dev.pojofromjson/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..0f630157f4bf530f9697788f383cabaab83dc2e8 --- /dev/null +++ b/org.eclipse.ice.dev/org.eclipse.ice.dev.pojofromjson/.gitignore @@ -0,0 +1,2 @@ +/target/ +/bin/ diff --git a/org.eclipse.ice.dev/org.eclipse.ice.dev.pojofromjson/.project b/org.eclipse.ice.dev/org.eclipse.ice.dev.pojofromjson/.project new file mode 100644 index 0000000000000000000000000000000000000000..847fff5e73500fb1dc96246a3cb6d6b3f829349d --- /dev/null +++ b/org.eclipse.ice.dev/org.eclipse.ice.dev.pojofromjson/.project @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.eclipse.ice.dev.pojofromjson</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> diff --git a/org.eclipse.ice.dev/org.eclipse.ice.dev.pojofromjson/pom.xml b/org.eclipse.ice.dev/org.eclipse.ice.dev.pojofromjson/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..ea38932167bfa2fc33e59ea3382850aa49720e21 --- /dev/null +++ b/org.eclipse.ice.dev/org.eclipse.ice.dev.pojofromjson/pom.xml @@ -0,0 +1,111 @@ +<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/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.eclipse.ice</groupId> + <artifactId>org.eclipse.ice.dev.pojofromjson</artifactId> + <packaging>jar</packaging> + <version>1.0-SNAPSHOT</version> + <name>org.eclipse.ice.dev.fromjson</name> + <url>http://maven.apache.org</url> + <properties> + <exec.mainClass>org.eclipse.ice.dev.pojofromjson.PojoFromJson</exec.mainClass> + </properties> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-assembly-plugin</artifactId> + <executions> + <execution> + <phase>package</phase> + <goals> + <goal>single</goal> + </goals> + <configuration> + <archive> + <manifest> + <mainClass> + org.eclipse.ice.dev.pojofromjson.PojoFromJson + </mainClass> + </manifest> + </archive> + <descriptorRefs> + <descriptorRef>jar-with-dependencies</descriptorRef> + </descriptorRefs> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.8.1</version> + <configuration> + <release>11</release> + <annotationProcessorPaths> + <path> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + <version>1.18.12</version> + </path> + </annotationProcessorPaths> + </configuration> + </plugin> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <version>2.22.2</version> + </plugin> + <plugin> + <artifactId>maven-failsafe-plugin</artifactId> + <version>2.22.2</version> + </plugin> + </plugins> + </build> + <dependencies> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-api</artifactId> + <version>5.6.2</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-engine</artifactId> + <version>5.6.2</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + <version>1.18.12</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-core</artifactId> + <version>2.10.2</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + <version>2.10.2</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>org.eclipse.ice.dev</groupId> + <artifactId>org.eclipse.ice.dev.annotations</artifactId> + <version>3.0.0-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>com.google.jimfs</groupId> + <artifactId>jimfs</artifactId> + <version>1.1</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>com.beust</groupId> + <artifactId>jcommander</artifactId> + <version>1.78</version> + </dependency> + </dependencies> +</project> diff --git a/org.eclipse.ice.dev/org.eclipse.ice.dev.pojofromjson/src/main/java/org/eclipse/ice/dev/pojofromjson/PojoFromJson.java b/org.eclipse.ice.dev/org.eclipse.ice.dev.pojofromjson/src/main/java/org/eclipse/ice/dev/pojofromjson/PojoFromJson.java new file mode 100644 index 0000000000000000000000000000000000000000..14e2a0815211eaf21ddcb294cce6710ba202191c --- /dev/null +++ b/org.eclipse.ice.dev/org.eclipse.ice.dev.pojofromjson/src/main/java/org/eclipse/ice/dev/pojofromjson/PojoFromJson.java @@ -0,0 +1,150 @@ +/******************************************************************************* + * Copyright (c) 2020- UT-Battelle, LLC. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daniel Bluhm - Initial implementation + *******************************************************************************/ + +package org.eclipse.ice.dev.pojofromjson; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.Writer; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.ice.dev.annotations.processors.DefaultFields; +import org.eclipse.ice.dev.annotations.processors.Fields; +import org.eclipse.ice.dev.annotations.processors.ImplementationWriter; +import org.eclipse.ice.dev.annotations.processors.InterfaceWriter; + +import com.beust.jcommander.JCommander; +import com.beust.jcommander.Parameter; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * Read JSON from Standard In and generate DataElement interface and + * implementation. + * @author Daniel Bluhm + */ +public class PojoFromJson { + + /** + * Mapper used for deserializing POJO Outline JSON + */ + private static ObjectMapper mapper = new ObjectMapper(); + + /** + * List of files to operate on. + */ + @Parameter(description = "FILE [FILE...]") + private List<String> jsonFiles = new ArrayList<>(); + + /** + * Directory to output generated files into. + */ + @Parameter(names = {"-o", "--output"}, description = "Output directory") + private String output = "."; + + /** + * Display help text. + */ + @Parameter(names = "--help", description = "Display this usage text", help = true) + private boolean help; + + /** + * Read from Input and write interface and implementation to files in + * destination. + * @param is InputStream of POJO Outline JSON + * @param destination directory in which files will be generated + * @throws JsonParseException On failure to parse POJO Outline JSON + * @throws JsonMappingException On failure to map to POJO Outline + * @throws IOException On failure to open file for writing + */ + public static void handleInputJson( + InputStream is, Path destination + ) throws JsonParseException, JsonMappingException, IOException { + // Parse outline from input stream + PojoOutline pojo = mapper.readValue(is, PojoOutline.class); + + // Collect fields + Fields fields = new Fields(); + fields.collect(DefaultFields.get()); + fields.collect(pojo.getFields()); + + // Write Interface + try (Writer elementInterface = Files.newBufferedWriter( + destination.resolve(pojo.getElement() + ".java") + )) { + InterfaceWriter.builder() + .packageName(pojo.getPackageName()) + .interfaceName(pojo.getElement()) + .fields(fields) + .build() + .write(elementInterface); + } + + // Write implementation + try (Writer elementImpl = Files.newBufferedWriter( + destination.resolve(pojo.getImplementation() + ".java") + )) { + ImplementationWriter.builder() + .packageName(pojo.getPackageName()) + .interfaceName(pojo.getElement()) + .className(pojo.getImplementation()) + .fields(fields) + .build() + .write(elementImpl); + } + } + + /** + * Execution entry point + * @param args from command line + */ + public static void main(String[] args) { + PojoFromJson pfj = new PojoFromJson(); + pfj.run(args); + } + + /** + * Read JSON form Standard In or from arguments and generate DataElement + * interfaces and implementations. + * @param args from command line + */ + public void run(String... args) { + JCommander jcomm = JCommander.newBuilder() + .addObject(this) + .build(); + jcomm.setProgramName("POJOfromJSON"); + jcomm.parse(args); + + if (help) { + jcomm.usage(); + return; + } + + try { + if (jsonFiles.size() == 0) { + handleInputJson(System.in, Path.of(output)); + } + for (String filePath : jsonFiles) { + try (FileInputStream inputJson = new FileInputStream(filePath)) { + handleInputJson(inputJson, Path.of(output)); + } + } + } catch (Exception ex) { + System.err.println(ex.getMessage()); + System.exit(1); + } + } +} diff --git a/org.eclipse.ice.dev/org.eclipse.ice.dev.pojofromjson/src/main/java/org/eclipse/ice/dev/pojofromjson/PojoOutline.java b/org.eclipse.ice.dev/org.eclipse.ice.dev.pojofromjson/src/main/java/org/eclipse/ice/dev/pojofromjson/PojoOutline.java new file mode 100644 index 0000000000000000000000000000000000000000..574f25c11a1ad0534997aefbc95a9f788334d4f9 --- /dev/null +++ b/org.eclipse.ice.dev/org.eclipse.ice.dev.pojofromjson/src/main/java/org/eclipse/ice/dev/pojofromjson/PojoOutline.java @@ -0,0 +1,91 @@ +/******************************************************************************* + * Copyright (c) 2020- UT-Battelle, LLC. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daniel Bluhm - Initial implementation + *******************************************************************************/ + +package org.eclipse.ice.dev.pojofromjson; + +import java.util.Collection; +import java.util.List; + +import org.eclipse.ice.dev.annotations.processors.Field; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; + +import lombok.Builder; +import lombok.Data; +import lombok.NonNull; +import lombok.Singular; + +/** + * Representation of information read in via JSON for POJO generation. + * @author Daniel Bluhm + */ +@Data +@Builder +@JsonDeserialize(builder = PojoOutline.PojoOutlineBuilder.class) +public class PojoOutline { + + /** + * Default suffix for implementation names. + */ + private static final String IMPL_SUFFIX = "Implementation"; + + /** + * Package of the generated classes. + */ + @JsonProperty("package") + @NonNull private String packageName; + + /** + * Name of the Element (interface) to be generated. + */ + @NonNull private String element; + + /** + * Name of the implementation to be generated. If null, element + IMPL_SUFFIX is + * used. + */ + private String implementation; + + /** + * List of fields to generate on element. + */ + @Singular("field") private List<Field> fields; + + /** + * Get name of the implementation to generate. + * @return implementation name. + */ + public String getImplementation() { + if (this.implementation == null) { + return this.element + IMPL_SUFFIX; + } + return this.implementation; + } + + /** + * JSON Serialization info for Builder. + */ + private interface PojoOutlineBuilderMeta { + @JsonDeserialize(contentAs = Field.class) + public PojoOutlineBuilder fields(Collection<? extends Field> fields); + + @JsonProperty("package") + public PojoOutlineBuilder packageName(@NonNull String package_); + } + + /** + * JSON Serialization info for Builder. + */ + @JsonPOJOBuilder(withPrefix = "") + public static class PojoOutlineBuilder implements PojoOutlineBuilderMeta {} +} diff --git a/org.eclipse.ice.dev/org.eclipse.ice.dev.pojofromjson/src/test/java/org/eclipse/ice/tests/dev/pojofromjson/PojoFromJsonTest.java b/org.eclipse.ice.dev/org.eclipse.ice.dev.pojofromjson/src/test/java/org/eclipse/ice/tests/dev/pojofromjson/PojoFromJsonTest.java new file mode 100644 index 0000000000000000000000000000000000000000..393363602fb8db85c3515c183d3006382edf447d --- /dev/null +++ b/org.eclipse.ice.dev/org.eclipse.ice.dev.pojofromjson/src/test/java/org/eclipse/ice/tests/dev/pojofromjson/PojoFromJsonTest.java @@ -0,0 +1,97 @@ +/******************************************************************************* + * Copyright (c) 2020- UT-Battelle, LLC. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daniel Bluhm - Initial implementation + *******************************************************************************/ + +package org.eclipse.ice.tests.dev.pojofromjson; + +import static org.junit.jupiter.api.Assertions.*; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.FileSystem; +import java.nio.file.Files; +import java.nio.file.Path; + +import org.eclipse.ice.dev.pojofromjson.PojoFromJson; +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.google.common.jimfs.Configuration; +import com.google.common.jimfs.Jimfs; + +/** + * Test PojoFromJson. + */ +class PojoFromJsonTest { + + /** + * Source JSON. + */ + private static final String TEST_ELEMENT_JSON = "TestElement.json"; + + /** + * Interface destination file name. + */ + private static final String TEST_ELEMENT_INTERFACE = "TestElement.java"; + + /** + * Implementation destination file name. + */ + private static final String TEST_ELEMENT_IMPLEMENTATION = "TestElementImplementation.java"; + + /** + * @return InputStream for JSON + * @throws FileNotFoundException + */ + public InputStream getTestElementJsonStream() throws FileNotFoundException { + return new FileInputStream( + getClass().getClassLoader().getResource(TEST_ELEMENT_JSON).getPath() + ); + } + + /** + * @return Path to in-memory destination. + * @throws IOException + */ + public Path inMemoryDestination() throws IOException { + FileSystem fs = Jimfs.newFileSystem(Configuration.unix()); + Path dest = fs.getPath("/dest"); + Files.createDirectory(dest); + return dest; + } + + /** + * Test that handleInputJson generates an interface and implementation as + * expected. + * + * There is no need to test the contents of the generated files as that is + * tested in + * {@link org.eclipse.ice.tests.dev.annotations.processors.DataElementProcessorTest}. + * @throws JsonParseException + * @throws JsonMappingException + * @throws FileNotFoundException + * @throws IOException + */ + @Test + public void testInterfaceAndImplementationGenerated() + throws JsonParseException, JsonMappingException, FileNotFoundException, + IOException + { + Path destination = inMemoryDestination(); + PojoFromJson.handleInputJson( + getTestElementJsonStream(), destination + ); + assertTrue(Files.exists(destination.resolve(TEST_ELEMENT_INTERFACE))); + assertTrue(Files.exists(destination.resolve(TEST_ELEMENT_IMPLEMENTATION))); + } +} diff --git a/org.eclipse.ice.dev/org.eclipse.ice.dev.pojofromjson/src/test/java/org/eclipse/ice/tests/dev/pojofromjson/PojoOutlineTest.java b/org.eclipse.ice.dev/org.eclipse.ice.dev.pojofromjson/src/test/java/org/eclipse/ice/tests/dev/pojofromjson/PojoOutlineTest.java new file mode 100644 index 0000000000000000000000000000000000000000..6433489d5a915345b1167a3a2ca93a60a48cbdde --- /dev/null +++ b/org.eclipse.ice.dev/org.eclipse.ice.dev.pojofromjson/src/test/java/org/eclipse/ice/tests/dev/pojofromjson/PojoOutlineTest.java @@ -0,0 +1,89 @@ +/******************************************************************************* + * Copyright (c) 2020- UT-Battelle, LLC. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daniel Bluhm - Initial implementation + *******************************************************************************/ + +package org.eclipse.ice.tests.dev.pojofromjson; + +import org.eclipse.ice.dev.annotations.processors.Field; +import org.eclipse.ice.dev.pojofromjson.PojoOutline; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; + +public class PojoOutlineTest { + + @Test + public void testSerialization() throws JsonProcessingException { + PojoOutline pojo = PojoOutline.builder() + .packageName("testpackage") + .element("TestElement") + .field( + Field.builder() + .name("test") + .type(String.class) + .docString("Test docs.") + .match(false) + .primitive(true) + .nullable(true) + .alias(Field.builder().name("another").getter(true).build()) + .build() + ).build(); + + ObjectMapper mapper = new ObjectMapper(); + String pojoJson = mapper.writeValueAsString(pojo); + System.out.println(pojoJson); + PojoOutline rehydratedPojo = mapper.readValue(pojoJson, PojoOutline.class); + assertEquals(pojo, rehydratedPojo); + } + + @Test + public void testImplementation() { + PojoOutline pojo = PojoOutline.builder() + .packageName("testpackage") + .element("TestElement") + .field( + Field.builder() + .name("test") + .type(String.class) + .docString("Test docs.") + .match(false) + .primitive(true) + .nullable(true) + .getter(false) + .setter(false) + .alias(Field.builder().name("another").getter(true).build()) + .build() + ).build(); + + assertEquals("TestElementImplementation", pojo.getImplementation()); + + pojo = PojoOutline.builder() + .packageName("testpackage") + .element("TestElement") + .implementation("TestElementImpl") + .field( + Field.builder() + .name("test") + .type(String.class) + .docString("Test docs.") + .match(false) + .primitive(true) + .nullable(true) + .getter(false) + .setter(false) + .alias(Field.builder().name("another").getter(true).build()) + .build() + ).build(); + assertEquals("TestElementImpl", pojo.getImplementation()); + } +} \ No newline at end of file diff --git a/org.eclipse.ice.dev/org.eclipse.ice.dev.pojofromjson/src/test/resources/TestElement.json b/org.eclipse.ice.dev/org.eclipse.ice.dev.pojofromjson/src/test/resources/TestElement.json new file mode 100644 index 0000000000000000000000000000000000000000..764456f0a22d801dc69a9d53c0809cea42cf5008 --- /dev/null +++ b/org.eclipse.ice.dev/org.eclipse.ice.dev.pojofromjson/src/test/resources/TestElement.json @@ -0,0 +1,8 @@ +{ + "package": "testpackage", + "element": "TestElement", + "fields": [{ + "name": "test", + "type": "String" + }] +} \ No newline at end of file diff --git a/org.eclipse.ice.dev/pom.xml b/org.eclipse.ice.dev/pom.xml index 6e71b30c908c4ac4bed1cc237c1f4a53bc81b25c..e3f118da7f3240ca70b803903687926cb298b541 100644 --- a/org.eclipse.ice.dev/pom.xml +++ b/org.eclipse.ice.dev/pom.xml @@ -8,5 +8,6 @@ <modules> <module>org.eclipse.ice.dev.annotations</module> <module>org.eclipse.ice.dev.annotations.proxytest</module> + <module>org.eclipse.ice.dev.pojofromjson</module> </modules> </project> \ No newline at end of file