diff --git a/src/main/java/org/springframework/datastore/graph/neo4j/spi/node/Neo4jNodeBacking.aj b/src/main/java/org/springframework/datastore/graph/neo4j/spi/node/Neo4jNodeBacking.aj index bc605358e..8dc58861f 100644 --- a/src/main/java/org/springframework/datastore/graph/neo4j/spi/node/Neo4jNodeBacking.aj +++ b/src/main/java/org/springframework/datastore/graph/neo4j/spi/node/Neo4jNodeBacking.aj @@ -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 relationshipEntityInstantiator; + private IndexService indexService; + +// private ConversionService conversionService; @Autowired - public void init(GraphDatabaseService gds, EntityInstantiator graphEntityInstantiator, EntityInstantiator relationshipEntityInstantiator, IndexService indexService) { + public void init(GraphDatabaseService gds, EntityInstantiator graphEntityInstantiator, + EntityInstantiator relationshipEntityInstantiator, IndexService indexService) { this.graphDatabaseService = gds; this.graphEntityInstantiator = graphEntityInstantiator; this.relationshipEntityInstantiator = relationshipEntityInstantiator; @@ -229,11 +235,12 @@ public aspect Neo4jNodeBacking extends AbstractTypeAnnotatingMixinFields Neo4J simple node property [" + propName + "] with value=[" + newVal + "]"); @@ -316,7 +324,7 @@ public aspect Neo4jNodeBacking extends AbstractTypeAnnotatingMixinFields Neo4J relationship with value=[" + newVal + "]"); @@ -377,16 +385,37 @@ public aspect Neo4jNodeBacking extends AbstractTypeAnnotatingMixinFields 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)fieldType, (String)value); + } + // todo @property annotation // todo fieldlist in @graphentity private boolean isIndexedProperty(Field field) { diff --git a/src/test/java/org/springframework/datastore/graph/neo4j/Person.java b/src/test/java/org/springframework/datastore/graph/neo4j/Person.java index 333b4a5d2..569365f6a 100644 --- a/src/test/java/org/springframework/datastore/graph/neo4j/Person.java +++ b/src/test/java/org/springframework/datastore/graph/neo4j/Person.java @@ -16,6 +16,10 @@ public class Person { private int age; private Short height; + + private transient String thought; + + private Personality personality; private Person spouse; @@ -105,4 +109,20 @@ 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; + } + + public void setThought(String thought) { + this.thought = thought; + } + + public String getThought() { + return thought; + } } diff --git a/src/test/java/org/springframework/datastore/graph/neo4j/Personality.java b/src/test/java/org/springframework/datastore/graph/neo4j/Personality.java new file mode 100644 index 000000000..56aabee1a --- /dev/null +++ b/src/test/java/org/springframework/datastore/graph/neo4j/Personality.java @@ -0,0 +1,5 @@ +package org.springframework.datastore.graph.neo4j; + +public enum Personality { + EXTROVERT, INTROVERT +} diff --git a/src/test/java/org/springframework/datastore/graph/neo4j/spi/Neo4jGraphPersistenceTest.java b/src/test/java/org/springframework/datastore/graph/neo4j/spi/Neo4jGraphPersistenceTest.java index 2c1847f18..ee13e281d 100644 --- a/src/test/java/org/springframework/datastore/graph/neo4j/spi/Neo4jGraphPersistenceTest.java +++ b/src/test/java/org/springframework/datastore/graph/neo4j/spi/Neo4jGraphPersistenceTest.java @@ -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()); } + @Test @Transactional public void testFindGroupByIndex() { @@ -425,6 +427,7 @@ public class Neo4jGraphPersistenceTest { final Collection result = IteratorUtil.addToCollection(found.iterator(), new HashSet()); Assert.assertEquals(new HashSet(Arrays.asList(group,group2)), result); } + @Test @Transactional public void testFindAllPersonByIndexOnAnnotatedField() { @@ -433,35 +436,70 @@ 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 people=(Iterable)group.find(Person.class, traversalDescription); + Iterable people = (Iterable) group.find(Person.class, traversalDescription); final HashSet found = new HashSet(); for (Person person : people) { found.add(person); } Assert.assertEquals(Collections.singleton(p),found); } + @Test @Transactional public void testTraverseFromGroupToPeopleWithFinder() { final Finder 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 people=finder.findAllByTraversal(group, traversalDescription); + Iterable people = finder.findAllByTraversal(group, traversalDescription); final HashSet found = new HashSet(); 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()); + } + + @Test(expected = NotFoundException.class) + @Transactional + public void testSetTransientPropertyFieldNotManaged() { + Person p = new Person("Michael", 35); + p.setThought("food"); + p.getUnderlyingNode().getProperty("Person.thought"); + } + + @Test + @Transactional + public void testGetTransientPropertyFieldNotManaged() { + Person p = new Person("Michael", 35); + p.setThought("food"); + p.getUnderlyingNode().setProperty("Person.thought", "sleep"); + Assert.assertEquals("Should not have read transient value from graph.", "food", p.getThought()); + } }