Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Eclipse Projects
The Eclipse Integrated Computational Environment
ice
Commits
a83b5135
Unverified
Commit
a83b5135
authored
Jul 24, 2020
by
Jay Jay Billings
Committed by
GitHub
Jul 24, 2020
Browse files
Merge pull request #440 from dbluhm/persistence-fixes-tests
Tests and fixes for Persistence
parents
8add1651
819dca1e
Changes
47
Hide whitespace changes
Inline
Side-by-side
org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/DataField.java
View file @
a83b5135
...
@@ -53,10 +53,10 @@ public @interface DataField {
...
@@ -53,10 +53,10 @@ public @interface DataField {
* Flag whether this field should be searchable in a collection.
* Flag whether this field should be searchable in a collection.
* This causes persistence retrieval methods to be generated for this
* This causes persistence retrieval methods to be generated for this
* field.
* field.
* @return search annotation value
* @return search
able
annotation value
* @see org.eclipse.ice.dev.annotations.processors.Field#search
* @see org.eclipse.ice.dev.annotations.processors.Field#search
able
*/
*/
boolean
search
()
default
true
;
boolean
search
able
()
default
true
;
/**
/**
* Flag whether this field can have a value of null. This causes
* Flag whether this field can have a value of null. This causes
...
...
org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/DataElementProcessor.java
View file @
a83b5135
...
@@ -174,6 +174,7 @@ public class DataElementProcessor extends AbstractProcessor {
...
@@ -174,6 +174,7 @@ public class DataElementProcessor extends AbstractProcessor {
.
packageName
(
element
.
getPackageName
())
.
packageName
(
element
.
getPackageName
())
.
elementInterface
(
element
.
getName
())
.
elementInterface
(
element
.
getName
())
.
className
(
element
.
getPersistenceHandlerName
())
.
className
(
element
.
getPersistenceHandlerName
())
.
interfaceName
(
element
.
getPersistenceHandlerInterfaceName
())
.
implementation
(
element
.
getImplName
())
.
implementation
(
element
.
getImplName
())
.
collection
(
collectionName
)
.
collection
(
collectionName
)
.
fields
(
fields
)
.
fields
(
fields
)
...
...
org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/DataElementSpec.java
View file @
a83b5135
...
@@ -13,6 +13,7 @@ import javax.lang.model.util.Elements;
...
@@ -13,6 +13,7 @@ import javax.lang.model.util.Elements;
import
org.eclipse.ice.dev.annotations.DataElement
;
import
org.eclipse.ice.dev.annotations.DataElement
;
import
org.eclipse.ice.dev.annotations.DataFieldJson
;
import
org.eclipse.ice.dev.annotations.DataFieldJson
;
import
org.eclipse.ice.dev.annotations.IPersistenceHandler
;
import
org.eclipse.ice.dev.annotations.Persisted
;
import
org.eclipse.ice.dev.annotations.Persisted
;
import
lombok.Getter
;
import
lombok.Getter
;
...
@@ -179,4 +180,15 @@ public class DataElementSpec extends AnnotatedElement {
...
@@ -179,4 +180,15 @@ public class DataElementSpec extends AnnotatedElement {
.
map
(
jsons
->
Arrays
.
asList
(
jsons
.
value
()))
.
map
(
jsons
->
Arrays
.
asList
(
jsons
.
value
()))
.
orElse
(
Collections
.
emptyList
());
.
orElse
(
Collections
.
emptyList
());
}
}
/**
* Get the interface name of the persistence handler.
*
* Right now, this is simply the IPersistenceHandler interface. In the future
* this will be a data element specific interface.
* @return Interface name of the Persistence Handler
*/
public
String
getPersistenceHandlerInterfaceName
()
{
return
IPersistenceHandler
.
class
.
getSimpleName
();
}
}
}
org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/DataFieldSpec.java
View file @
a83b5135
...
@@ -138,7 +138,7 @@ public class DataFieldSpec extends AnnotatedElement {
...
@@ -138,7 +138,7 @@ public class DataFieldSpec extends AnnotatedElement {
.
setter
(
fieldInfo
.
setter
())
.
setter
(
fieldInfo
.
setter
())
.
match
(
fieldInfo
.
match
())
.
match
(
fieldInfo
.
match
())
.
unique
(
fieldInfo
.
unique
())
.
unique
(
fieldInfo
.
unique
())
.
search
(
fieldInfo
.
search
())
.
search
able
(
fieldInfo
.
search
able
())
.
nullable
(
fieldInfo
.
nullable
())
.
nullable
(
fieldInfo
.
nullable
())
.
build
();
.
build
();
}
}
...
...
org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/DefaultFields.java
View file @
a83b5135
...
@@ -117,7 +117,7 @@ public class DefaultFields {
...
@@ -117,7 +117,7 @@ public class DefaultFields {
.
docString
(
"The validator used to check the correctness of the data."
)
.
docString
(
"The validator used to check the correctness of the data."
)
.
nullable
(
true
)
.
nullable
(
true
)
.
defaultField
(
true
)
.
defaultField
(
true
)
.
search
(
false
)
.
search
able
(
false
)
.
build
();
.
build
();
/**
/**
...
...
org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/Field.java
View file @
a83b5135
...
@@ -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
search
able
=
true
;
/**
/**
* Whether this field should return only one from PersistenceHandler.
* Whether this field should return only one from PersistenceHandler.
...
...
org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/java/org/eclipse/ice/dev/annotations/processors/PersistenceHandlerWriter.java
View file @
a83b5135
...
@@ -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
);
...
...
org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/main/resources/templates/PersistenceHandler.vm
View file @
a83b5135
## 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.dev.annotations.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.count
Documents
();
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
.
Search
able
})
#
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
}
(
#
field
type
${
field
.
VarName
}
) throws Exception
{
Document doc = this.collection
Document doc = this.collection
.find(PersistenceFilters.eq("
${
doc
Name
}
",
${
var
.
VarName
}
))
.find(PersistenceFilters.eq("
${
field
.
Var
Name
}
",
${
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
.
T
ype
}
${
var
.
VarName
}
) throws Exception
{
public Iterable
<
$
elementInterface
>
findBy
${
field
.
NameForMethod
}
(
#
fieldt
ype
${
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
org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/test/java/org/eclipse/ice/tests/dev/annotations/processors/DataElementAnnotationTestHelper.java
0 → 100644
View file @
a83b5135
/*******************************************************************************
* 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
);
}
}
org.eclipse.ice.dev/org.eclipse.ice.dev.annotations/src/test/java/org/eclipse/ice/tests/dev/annotations/processors/DataElementProcessorTest.java
View file @
a83b5135
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
*/
*/
@AllArgsConstructor
@AllArgsConstructor
private
static
enum
Patterns
{
private
static
enum
Patterns
implements
JavaFileObjectResource
{
DEFAULTS_INT
(
"Defaults.java"
),
DEFAULTS_INT
(
"Defaults.java"
),
DEFAULTS_IMPL
(
"DefaultsImplementation.java"
),
DEFAULTS_IMPL
(
"DefaultsImplementation.java"
),
SINGLE_INT
(
"Single.java"
),
SINGLE_INT
(
"Single.java"
),
...
@@ -116,61 +121,19 @@ class DataElementProcessorTest {
...
@@ -116,61 +121,19 @@ class DataElementProcessorTest {
/**
/**
* Parent directory of inputs. Prepended to all paths.
* Parent directory of inputs. Prepended to all paths.
*/
*/
private
static
final
String
PARENT
=
"patterns/"
;
private
static
final
String
PARENT
=
"patterns/
DataElement/
"
;
/**
/**
* Path to inputs.
* Path to inputs.
*/
*/
private
String
path
;
private
String
filename
;
/**
@Override
* Retrieve the JavaFileObject corresponding to this pattern.
public
String
getPath
()
{
* @return input as a JavaFileObject
return
PARENT
+
this
.
filename
;
*/
public
JavaFileObject
get
()
{
return
JavaFileObjects
.
forResource
(
PARENT
+
this
.
path
);
}
}
}
}
/**
* 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
static
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