Unverified Commit ff18c728 authored by Gregory Cage's avatar Gregory Cage Committed by GitHub
Browse files

Merge pull request #3 from eclipse/next

Next
parents 1ae7dae1 dd3d5f82
...@@ -43,7 +43,7 @@ public class Field { ...@@ -43,7 +43,7 @@ public class Field {
* *
* This handles cases like the default field {@link DefaultFields#privateId} * This handles cases like the default field {@link DefaultFields#privateId}
* being accessible through the method * being accessible through the method
* {@link org.eclipse.ice.dev.annotations.IDataElement#getUUID()} rather than * {@link org.eclipse.ice.data.IDataElement#getUUID()} rather than
* {@code getPrivateId()}. In that example, the variable name would be * {@code getPrivateId()}. In that example, the variable name would be
* {@code privateId} and the field name would be {@code UUID}. * {@code privateId} and the field name would be {@code UUID}.
*/ */
...@@ -103,7 +103,7 @@ public class Field { ...@@ -103,7 +103,7 @@ public class Field {
/** /**
* Whether this field should be searchable with PersistenceHandler. * Whether this field should be searchable with PersistenceHandler.
*/ */
@Builder.Default boolean search = true; @Builder.Default boolean searchable = true;
/** /**
* Whether this field should return only one from PersistenceHandler. * Whether this field should return only one from PersistenceHandler.
......
...@@ -65,7 +65,7 @@ public class Fields implements Iterable<Field> { ...@@ -65,7 +65,7 @@ public class Fields implements Iterable<Field> {
* Return iterator over fields that are set to be used in matches. * Return iterator over fields that are set to be used in matches.
* *
* @return iterator over the fields * @return iterator over the fields
* @see org.eclipse.ice.dev.annotations.IDataElement#matches(Object) * @see org.eclipse.ice.data.IDataElement#matches(Object)
*/ */
public Iterator<Field> getMatch() { public Iterator<Field> getMatch() {
return fields.stream() return fields.stream()
......
...@@ -43,6 +43,11 @@ public class PersistenceHandlerWriter extends VelocitySourceWriter { ...@@ -43,6 +43,11 @@ public class PersistenceHandlerWriter extends VelocitySourceWriter {
*/ */
private static final String CLASS = "class"; private static final String CLASS = "class";
/**
* Context key for interface of PersistenceHandlers
*/
private static final String INTERFACE = "interface";
/** /**
* Context key for collection. * Context key for collection.
*/ */
...@@ -60,14 +65,16 @@ public class PersistenceHandlerWriter extends VelocitySourceWriter { ...@@ -60,14 +65,16 @@ public class PersistenceHandlerWriter extends VelocitySourceWriter {
@Builder @Builder
public PersistenceHandlerWriter( public PersistenceHandlerWriter(
String packageName, String elementInterface, String className, String packageName, String elementInterface, String interfaceName,
String implementation, String collection, @NonNull Fields fields String className, String implementation, String collection,
@NonNull Fields fields
) { ) {
super(); super();
this.template = PERSISTENCE_HANDLER_TEMPLATE; this.template = PERSISTENCE_HANDLER_TEMPLATE;
this.context.put(PACKAGE, packageName); this.context.put(PACKAGE, packageName);
this.context.put(ELEMENT_INTERFACE, elementInterface); this.context.put(ELEMENT_INTERFACE, elementInterface);
this.context.put(CLASS, className); this.context.put(CLASS, className);
this.context.put(INTERFACE, interfaceName);
this.context.put(COLLECTION, collection); this.context.put(COLLECTION, collection);
this.context.put(IMPLEMENTATION, implementation); this.context.put(IMPLEMENTATION, implementation);
this.context.put(FIELDS, fields); this.context.put(FIELDS, fields);
......
/******************************************************************************
* 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:
* Initial API and implementation and/or initial documentation -
* Jay Jay Billings, Daniel Bluhm
*****************************************************************************/
package org.eclipse.ice.dev.annotations.webform;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
* @author Jay Jay Billings and Daniel Bluhm
*
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface FinishLoadHook {
}
/******************************************************************************
* 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:
* Initial API and implementation and/or initial documentation -
* Jay Jay Billings, Daniel Bluhm
*****************************************************************************/
package org.eclipse.ice.dev.annotations.webform;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
* @author Jay Jay Billings and Daniel Bluhm
*
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface StartLoadHook {
}
/******************************************************************************
* 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:
* Initial API and implementation and/or initial documentation -
* Jay Jay Billings, Daniel Bluhm
*****************************************************************************/
package org.eclipse.ice.dev.annotations.webform;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.RetentionPolicy;
/**
* Mark a class as a WebForm Specification.
*
* Classes marked as {@code @WebForm} are expected to ....
* * need to have required methods annotated
* * declare hooks
*
* Discuss lifecycle when appropriate and injection of dependencies
*
*
* For example:
*
* <pre>
* {@literal @WebForm}(name = "Talk Submission Page")
* public class TalkFormSpec {
* ...
* }
* </pre>
*
* Will generate an interface like the following:
*
* <pre>
* public interface TalkForm extends ... {
* .... FIXME
* }
* </pre>
*
* And an associated implementing class (in this case, the class would be called
* {@code TalkFormImplementation}) that implements that interface.
*
* @author Jay Jay Billings and Daniel Bluhm
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface WebForm {
/**
* Name of the DataElement to generate
* @return name annotation value
*/
String name();
}
...@@ -22,6 +22,8 @@ import lombok.NoArgsConstructor; ...@@ -22,6 +22,8 @@ import lombok.NoArgsConstructor;
import lombok.NonNull; import lombok.NonNull;
import lombok.Setter; import lombok.Setter;
import org.eclipse.ice.data.JavascriptValidator;
/** /**
* This is an implementation of $interface that satisfies the dependencies of * This is an implementation of $interface that satisfies the dependencies of
* the @DataElement Annotation and was auto-generated by the ICE Framework. * the @DataElement Annotation and was auto-generated by the ICE Framework.
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
package $package; package $package;
#end #end
import org.eclipse.ice.dev.annotations.IDataElement; import org.eclipse.ice.data.IDataElement;
/** /**
* This interface satisfies the dependencies of the @DataElement Annotation and * This interface satisfies the dependencies of the @DataElement Annotation and
......
## Declarations
#set($interface = "IPersistenceHandler")
##
#if($package) #if($package)
package $package; package $package;
#end #end
import java.util.Map;
import java.util.UUID;
import org.bson.Document; import org.bson.Document;
import org.eclipse.ice.dev.annotations.IDataElement; import org.eclipse.ice.data.IPersistenceHandler;
import org.eclipse.ice.dev.annotations.IPersistenceHandler;
import org.eclipse.ice.dev.annotations.PersistenceFilters; import org.eclipse.ice.dev.annotations.PersistenceFilters;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase; import com.mongodb.client.MongoDatabase;
...@@ -46,7 +38,6 @@ public class $class implements $interface<$elementInterface> { ...@@ -46,7 +38,6 @@ public class $class implements $interface<$elementInterface> {
/** /**
* Save the $elementInterface. * Save the $elementInterface.
* @param <T> Object extending IDataElement
* @param element * @param element
* @throws Exception * @throws Exception
*/ */
...@@ -57,7 +48,6 @@ public class $class implements $interface<$elementInterface> { ...@@ -57,7 +48,6 @@ public class $class implements $interface<$elementInterface> {
/** /**
* Find and retrieve all $elementInterface from the collection. * Find and retrieve all $elementInterface from the collection.
* @param <T>
* @return an iterable of the retrieved elements. * @return an iterable of the retrieved elements.
* @throws Exception * @throws Exception
*/ */
...@@ -74,26 +64,26 @@ public class $class implements $interface<$elementInterface> { ...@@ -74,26 +64,26 @@ public class $class implements $interface<$elementInterface> {
*/ */
@Override @Override
public long clear() throws Exception { public long clear() throws Exception {
long count = this.collection.count(); long count = this.collection.countDocuments();
this.collection.drop(); this.collection.drop();
return count; return count;
} }
#macro(findmethod $var $type $docName) #foreach($field in $fields)
#if(${var.Getter} && ${var.Search}) #if(${field.Getter} && ${field.Searchable})
#if(${var.Unique}) #if(${field.Unique})
/** /**
* Find $elementInterface by ${var.Name}. * Find $elementInterface by ${field.Name}.
* @param ${var.VarName} * @param ${field.VarName}
* @return found element or null * @return found element or null
*/ */
#if(${var.DefaultField}) #if(${field.DefaultField})
@Override @Override
#end #end
public $elementInterface findBy${var.NameForMethod}($type ${var.VarName}) throws Exception { public $elementInterface findBy${field.NameForMethod}(#fieldtype ${field.VarName}) throws Exception {
Document doc = this.collection Document doc = this.collection
.find(PersistenceFilters.eq("${docName}", ${var.VarName})) .find(PersistenceFilters.eq("${field.VarName}", ${field.VarName}))
.first(); .first();
if (doc == null) { if (doc == null) {
return null; return null;
...@@ -104,21 +94,18 @@ public class $class implements $interface<$elementInterface> { ...@@ -104,21 +94,18 @@ public class $class implements $interface<$elementInterface> {
#else #else
/** /**
* Find $elementInterface by ${var.Name}. * Find $elementInterface by ${field.Name}.
* @param ${var.VarName} * @param ${field.VarName}
* @return Iterator of results * @return Iterator of results
*/ */
#if(${var.DefaultField}) #if(${field.DefaultField})
@Override @Override
#end #end
public Iterable<$elementInterface> findBy${var.NameForMethod}(${var.Type} ${var.VarName}) throws Exception { public Iterable<$elementInterface> findBy${field.NameForMethod}(#fieldtype ${field.VarName}) throws Exception {
return this.collection.find(PersistenceFilters.eq("${var.VarName}", ${var.VarName})) return this.collection.find(PersistenceFilters.eq("${field.VarName}", ${field.VarName}))
.map(doc -> mapper.convertValue(doc, ${implementation}.class)); .map(doc -> mapper.convertValue(doc, ${implementation}.class));
} }
#end## if unique #end## if unique
#end## if getter and search #end## if getter and search
#end## macro findmethod #end## foreach
#foreach($field in $fields)
#findmethod($field ${field.Type} ${field.VarName})
#end
} }
\ No newline at end of file
/*******************************************************************************
* 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.annotations.processors;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import javax.annotation.processing.Processor;
import javax.tools.JavaFileObject;
import org.eclipse.ice.dev.annotations.processors.DataElementProcessor;
import com.google.testing.compile.Compilation;
import static com.google.testing.compile.Compiler.*;
/**
* Helper class for testing DataElement related annotations.
* @author Daniel Bluhm
*/
public class DataElementAnnotationTestHelper {
/**
* Retrieve an instance of Lombok's Annotation Processor.
*
* This is a nasty method that violates the accessibility of the Processor by
* reflection but is necessary to correctly process and test the generated code.
* @return lombok annotation processor
*/
private Processor getLombokAnnotationProcessor() {
Processor p = null;
try {
Class<?> c = Class.forName("lombok.launch.AnnotationProcessorHider$AnnotationProcessor");
Constructor<?> constructor = c.getConstructor();
constructor.setAccessible(true);
p = (Processor) constructor.newInstance();
} catch (
ClassNotFoundException | InstantiationException |
IllegalAccessException | IllegalArgumentException |
InvocationTargetException | NoSuchMethodException |
SecurityException e
) {
System.err.println("Failed to get Lombok AnnotationProcessor!");
e.printStackTrace();
}
return p;
}
/**
* Compile the sources with needed processors.
* @param sources to compile
* @return Compilation result
*/
public Compilation compile(JavaFileObject... sources) {
return javac()
.withProcessors(
getLombokAnnotationProcessor(),
new DataElementProcessor()
).compile(sources);
}
}
package org.eclipse.ice.tests.dev.annotations.processors; /*******************************************************************************
* Copyright (c) 2020- UT-Battelle, LLC.
import static org.junit.jupiter.api.Assertions.fail; * 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
*******************************************************************************/
import java.lang.reflect.Constructor; package org.eclipse.ice.tests.dev.annotations.processors;
import java.lang.reflect.InvocationTargetException;
import static com.google.testing.compile.Compiler.*;
import static com.google.testing.compile.CompilationSubject.*; import static com.google.testing.compile.CompilationSubject.*;
import javax.annotation.processing.Processor;
import javax.tools.JavaFileObject; import javax.tools.JavaFileObject;
import org.eclipse.ice.dev.annotations.processors.DataElementProcessor;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import com.google.testing.compile.Compilation; import com.google.testing.compile.Compilation;
import com.google.testing.compile.JavaFileObjects;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
...@@ -38,6 +40,12 @@ import lombok.AllArgsConstructor; ...@@ -38,6 +40,12 @@ import lombok.AllArgsConstructor;
*/ */
class DataElementProcessorTest { class DataElementProcessorTest {
/**
* Helper for testing DataElement related annotations.
*/
private static DataElementAnnotationTestHelper helper =
new DataElementAnnotationTestHelper();
/** /**
* Fully qualified name of the generated interface. * Fully qualified name of the generated interface.
*/ */
...@@ -53,7 +61,7 @@ class DataElementProcessorTest { ...@@ -53,7 +61,7 @@ class DataElementProcessorTest {
* @author Daniel Bluhm * @author Daniel Bluhm
*/ */
@AllArgsConstructor @AllArgsConstructor
private static enum Inputs { private static enum Inputs implements JavaFileObjectResource{
HELLO_WORLD("HelloWorld.java"), HELLO_WORLD("HelloWorld.java"),
NAME_MISSING("DataElementNameMissing.java"), NAME_MISSING("DataElementNameMissing.java"),
ON_ENUM("DataElementOnEnum.java"), ON_ENUM("DataElementOnEnum.java"),
...@@ -75,19 +83,16 @@ class DataElementProcessorTest { ...@@ -75,19 +83,16 @@ class DataElementProcessorTest {
/** /**
* Parent directory of inputs. Prepended to all paths. * Parent directory of inputs. Prepended to all paths.
*/ */
private static final String PARENT = "input/"; private static final String PARENT = "input/DataElement/";
/** /**
* Path to inputs. * Path to inputs.
*/ */
private String path; private String filename;
/** @Override
* Retrieve the JavaFileObject corresponding to this input. public String getPath() {
* @return input as a JavaFileObject return PARENT + this.filename;
*/
public JavaFileObject get() {
return JavaFileObjects.forResource(PARENT + this.path);
} }
} }
...@@ -96,7 +101,7 @@ class DataElementProcessorTest { ...@@ -96,7 +101,7 @@ class DataElementProcessorTest {
* @author Daniel Bluhm * @author Daniel Bluhm