Added support for enum properties.
This commit is contained in:
@@ -28,6 +28,8 @@ import org.springframework.persistence.support.AbstractTypeAnnotatingMixinFields
|
||||
import org.springframework.persistence.support.EntityInstantiator;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
|
||||
import javax.transaction.Status;
|
||||
import javax.transaction.SystemException;
|
||||
|
||||
@@ -53,10 +55,14 @@ public aspect Neo4jNodeBacking extends AbstractTypeAnnotatingMixinFields<GraphEn
|
||||
private FieldAccessorFactory fieldAccessorFactory;
|
||||
|
||||
public EntityInstantiator<RelationshipBacked, Relationship> relationshipEntityInstantiator;
|
||||
|
||||
private IndexService indexService;
|
||||
|
||||
// private ConversionService conversionService;
|
||||
|
||||
@Autowired
|
||||
public void init(GraphDatabaseService gds, EntityInstantiator<NodeBacked, Node> graphEntityInstantiator, EntityInstantiator<RelationshipBacked, Relationship> relationshipEntityInstantiator, IndexService indexService) {
|
||||
public void init(GraphDatabaseService gds, EntityInstantiator<NodeBacked, Node> graphEntityInstantiator,
|
||||
EntityInstantiator<RelationshipBacked, Relationship> relationshipEntityInstantiator, IndexService indexService) {
|
||||
this.graphDatabaseService = gds;
|
||||
this.graphEntityInstantiator = graphEntityInstantiator;
|
||||
this.relationshipEntityInstantiator = relationshipEntityInstantiator;
|
||||
@@ -229,11 +235,11 @@ public aspect Neo4jNodeBacking extends AbstractTypeAnnotatingMixinFields<GraphEn
|
||||
private ShouldProceedOrReturn getNodePropertyOrRelationship(Field field, NodeBacked entity) {
|
||||
// TODO fix arrays, TODO serialize other types as byte[] or string (for indexing, querying) via Annotation
|
||||
if (isIdField(field)) return new ShouldProceedOrReturn(entity.getUnderlyingNode().getId());
|
||||
if (isPropertyType(field.getType())) {
|
||||
if (isNeo4jPropertyType(field.getType()) || isConvertableType(field.getType())) {
|
||||
String propName = FieldAccessorFactory.getNeo4jPropertyName(field);
|
||||
log.info("GET " + field + " <- Neo4J simple node property [" + propName + "]");
|
||||
Node node = entity.getUnderlyingNode();
|
||||
Object nodeProperty = node.getProperty(propName, getDefaultValue(field.getType()));
|
||||
Object nodeProperty = deserializePropertyValue(node.getProperty(propName, getDefaultValue(field.getType())), field.getType());
|
||||
return new ShouldProceedOrReturn(nodeProperty);
|
||||
}
|
||||
|
||||
@@ -300,14 +306,14 @@ public aspect Neo4jNodeBacking extends AbstractTypeAnnotatingMixinFields<GraphEn
|
||||
try {
|
||||
if (isIdField(field)) return new ShouldProceedOrReturn(null);
|
||||
if (Modifier.isFinal(field.getModifiers())) return new ShouldProceedOrReturn(newVal);
|
||||
if (isPropertyType(field.getType())) {
|
||||
if (isNeo4jPropertyType(field.getType()) || isConvertableType(field.getType())) {
|
||||
String propName = FieldAccessorFactory.getNeo4jPropertyName(field);
|
||||
Node node = entity.getUnderlyingNode();
|
||||
if (newVal==null) {
|
||||
node.removeProperty(propName);
|
||||
if (isIndexedProperty(field)) indexService.removeIndex(node,propName);
|
||||
} else {
|
||||
node.setProperty(propName, newVal);
|
||||
node.setProperty(propName, serializePropertyValue(newVal, field.getType()));
|
||||
if (isIndexedProperty(field)) indexService.index(node,propName,newVal);
|
||||
}
|
||||
log.info("SET " + field + " -> Neo4J simple node property [" + propName + "] with value=[" + newVal + "]");
|
||||
@@ -316,7 +322,7 @@ public aspect Neo4jNodeBacking extends AbstractTypeAnnotatingMixinFields<GraphEn
|
||||
|
||||
FieldAccessor accessor = fieldAccessorFactory.forField(field);
|
||||
if (accessor == null) {
|
||||
log.info("Ignored SET " + field + ": " + field.getType().getName() + " not primitive or GraphEntity");
|
||||
log.info("Ignored SET " + field + ": " + field.getType().getName() + " not primitive, convertable, or GraphEntity");
|
||||
return new ShouldProceedOrReturn(true,newVal);
|
||||
}
|
||||
log.info("SET " + field + " -> Neo4J relationship with value=[" + newVal + "]");
|
||||
@@ -377,16 +383,37 @@ public aspect Neo4jNodeBacking extends AbstractTypeAnnotatingMixinFields<GraphEn
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isPropertyType(Class<?> fieldType) {
|
||||
private boolean isNeo4jPropertyType(Class<?> fieldType) {
|
||||
// todo: add array support
|
||||
return fieldType.isPrimitive()
|
||||
|| (fieldType.isArray() && !fieldType.getComponentType().isArray() && isPropertyType(fieldType.getComponentType()))
|
||||
|| (fieldType.isArray() && !fieldType.getComponentType().isArray() && isNeo4jPropertyType(fieldType.getComponentType()))
|
||||
|| fieldType.equals(String.class)
|
||||
|| fieldType.equals(Character.class)
|
||||
|| fieldType.equals(Boolean.class)
|
||||
|| (fieldType.getName().startsWith("java.lang") && Number.class.isAssignableFrom(fieldType));
|
||||
}
|
||||
|
||||
private boolean isConvertableType(Class<?> fieldType) {
|
||||
//return conversionService.canConvert(fieldType, String.class);
|
||||
return fieldType.isEnum();
|
||||
}
|
||||
|
||||
private Object serializePropertyValue(Object newVal, Class<?> fieldType) {
|
||||
if (isNeo4jPropertyType(fieldType)) {
|
||||
return newVal;
|
||||
}
|
||||
// return conversionService.convert(newVal, String.class);
|
||||
return ((Enum<?>)newVal).name();
|
||||
}
|
||||
|
||||
private Object deserializePropertyValue(Object value, Class<?> fieldType) {
|
||||
if (isNeo4jPropertyType(fieldType)) {
|
||||
return value;
|
||||
}
|
||||
// return conversionService.convert(value, fieldType);
|
||||
return Enum.valueOf((Class<Enum>)fieldType, (String)value);
|
||||
}
|
||||
|
||||
// todo @property annotation
|
||||
// todo fieldlist in @graphentity
|
||||
private boolean isIndexedProperty(Field field) {
|
||||
|
||||
@@ -16,6 +16,8 @@ public class Person {
|
||||
private int age;
|
||||
|
||||
private Short height;
|
||||
|
||||
private Personality personality;
|
||||
|
||||
private Person spouse;
|
||||
|
||||
@@ -105,4 +107,12 @@ public class Person {
|
||||
public Friendship knows(Person p) {
|
||||
return (Friendship)relateTo(p, Friendship.class,"knows");
|
||||
}
|
||||
|
||||
public void setPersonality(Personality personality) {
|
||||
this.personality = personality;
|
||||
}
|
||||
|
||||
public Personality getPersonality() {
|
||||
return personality;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package org.springframework.datastore.graph.neo4j;
|
||||
|
||||
public enum Personality {
|
||||
EXTROVERT, INTROVERT
|
||||
}
|
||||
@@ -18,13 +18,14 @@ import org.springframework.datastore.graph.api.NodeBacked;
|
||||
import org.springframework.datastore.graph.neo4j.Friendship;
|
||||
import org.springframework.datastore.graph.neo4j.Group;
|
||||
import org.springframework.datastore.graph.neo4j.Person;
|
||||
import org.springframework.datastore.graph.neo4j.Personality;
|
||||
import org.springframework.datastore.graph.neo4j.finder.Finder;
|
||||
import org.springframework.datastore.graph.neo4j.finder.FinderFactory;
|
||||
import org.springframework.datastore.graph.neo4j.spi.node.Neo4jHelper;
|
||||
import org.springframework.persistence.support.EntityInstantiator;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.persistence.support.EntityInstantiator;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -175,7 +176,6 @@ public class Neo4jGraphPersistenceTest {
|
||||
Assert.assertEquals(20,p.getAge());
|
||||
}
|
||||
|
||||
// @Test(expected = InvalidDataAccessResourceUsageException.class)
|
||||
@Test
|
||||
public void testCreateRelationshipOutsideTransaction() {
|
||||
Transaction tx = graphDatabaseService.beginTx();
|
||||
@@ -359,6 +359,7 @@ public class Neo4jGraphPersistenceTest {
|
||||
Assert.assertEquals(p, f.getPerson1());
|
||||
Assert.assertEquals(p2, f.getPerson2());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testGetRelationshipToReturnsRelationship() {
|
||||
@@ -403,6 +404,7 @@ public class Neo4jGraphPersistenceTest {
|
||||
Group group = new Group();
|
||||
group.setReadOnlyPersons(new HashSet<Person>());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testFindGroupByIndex() {
|
||||
@@ -425,6 +427,7 @@ public class Neo4jGraphPersistenceTest {
|
||||
final Collection<Group> result = IteratorUtil.addToCollection(found.iterator(), new HashSet<Group>());
|
||||
Assert.assertEquals(new HashSet<Group>(Arrays.asList(group,group2)), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testFindAllPersonByIndexOnAnnotatedField() {
|
||||
@@ -433,35 +436,53 @@ public class Neo4jGraphPersistenceTest {
|
||||
final Person found = finder.findByPropertyValue("Person.name", "Michael");
|
||||
Assert.assertEquals(person, found);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testTraverseFromGroupToPeople() {
|
||||
Person p=new Person("Michael",35);
|
||||
Person p = new Person("Michael", 35);
|
||||
Group group = new Group();
|
||||
group.setName("dev");
|
||||
group.addPerson(p);
|
||||
final TraversalDescription traversalDescription = new TraversalDescriptionImpl().relationships(DynamicRelationshipType.withName("persons")).filter(Traversal.returnAllButStartNode());
|
||||
Iterable<Person> people=(Iterable<Person>)group.find(Person.class, traversalDescription);
|
||||
Iterable<Person> people = (Iterable<Person>) group.find(Person.class, traversalDescription);
|
||||
final HashSet<Person> found = new HashSet<Person>();
|
||||
for (Person person : people) {
|
||||
found.add(person);
|
||||
}
|
||||
Assert.assertEquals(Collections.singleton(p),found);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testTraverseFromGroupToPeopleWithFinder() {
|
||||
final Finder<Person> finder = finderFactory.getFinderForClass(Person.class);
|
||||
Person p=new Person("Michael",35);
|
||||
Person p = new Person("Michael", 35);
|
||||
Group group = new Group();
|
||||
group.setName("dev");
|
||||
group.addPerson(p);
|
||||
final TraversalDescription traversalDescription = new TraversalDescriptionImpl().relationships(DynamicRelationshipType.withName("persons")).filter(Traversal.returnAllButStartNode());
|
||||
Iterable<Person> people=finder.findAllByTraversal(group, traversalDescription);
|
||||
Iterable<Person> people = finder.findAllByTraversal(group, traversalDescription);
|
||||
final HashSet<Person> found = new HashSet<Person>();
|
||||
for (Person person : people) {
|
||||
found.add(person);
|
||||
}
|
||||
Assert.assertEquals(Collections.singleton(p),found);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testSetPropertyConversionOfEnumProperty() {
|
||||
Person p = new Person("Michael", 35);
|
||||
p.setPersonality(Personality.EXTROVERT);
|
||||
Assert.assertEquals("Wrong enum serialization.", "EXTROVERT", p.getUnderlyingNode().getProperty("Person.personality"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testGetPropertyConversionOfEnumProperty() {
|
||||
Person p = new Person("Michael", 35);
|
||||
p.getUnderlyingNode().setProperty("Person.personality", "EXTROVERT");
|
||||
Assert.assertEquals("Did not deserialize property value properly.", Personality.EXTROVERT, p.getPersonality());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user