Added finder support via FinderFactory. Improved check for neo4j supported types. Fixed tests to clean db between test cases.
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
package org.springframework.persistence.graph.neo4j;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.neo4j.graphdb.Direction;
|
||||
import org.neo4j.graphdb.GraphDatabaseService;
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.neo4j.graphdb.NotFoundException;
|
||||
import org.neo4j.graphdb.Relationship;
|
||||
import org.springframework.persistence.support.EntityInstantiator;
|
||||
|
||||
public class Finder<T extends NodeBacked> {
|
||||
|
||||
private final Class<T> clazz;
|
||||
private final GraphDatabaseService graphDatabaseService;
|
||||
private final EntityInstantiator<NodeBacked, Node> graphEntityInstantiator;
|
||||
|
||||
public Finder(Class<T> clazz, GraphDatabaseService graphDatabaseService, EntityInstantiator<NodeBacked, Node> graphEntityInstantiator) {
|
||||
this.clazz = clazz;
|
||||
this.graphDatabaseService = graphDatabaseService;
|
||||
this.graphEntityInstantiator = graphEntityInstantiator;
|
||||
}
|
||||
|
||||
public long count() {
|
||||
return Neo4jHelper.count(clazz, graphDatabaseService);
|
||||
}
|
||||
|
||||
public Iterable<T> findAll() {
|
||||
Node subrefNode = Neo4jHelper.findSubreferenceNode(clazz, graphDatabaseService);
|
||||
// TODO add lazy list on top of graph
|
||||
List<T> result = new ArrayList<T>((int) count());
|
||||
for (Relationship rel : subrefNode.getRelationships(Neo4jHelper.INSTANCE_OF_RELATIONSHIP_TYPE, Direction.INCOMING)) {
|
||||
Node node = rel.getStartNode();
|
||||
result.add(graphEntityInstantiator.createEntityFromState(node, clazz));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public T findById(long id) {
|
||||
try {
|
||||
return graphEntityInstantiator.createEntityFromState(graphDatabaseService.getNodeById(id), clazz);
|
||||
} catch(NotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package org.springframework.persistence.graph.neo4j;
|
||||
|
||||
import org.neo4j.graphdb.GraphDatabaseService;
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.springframework.persistence.support.EntityInstantiator;
|
||||
|
||||
public class FinderFactory {
|
||||
|
||||
private final GraphDatabaseService graphDatabaseService;
|
||||
private final EntityInstantiator<NodeBacked, Node> graphEntityInstantiator;
|
||||
|
||||
public FinderFactory(GraphDatabaseService graphDatabaseService, EntityInstantiator<NodeBacked, Node> graphEntityInstantiator) {
|
||||
this.graphDatabaseService = graphDatabaseService;
|
||||
this.graphEntityInstantiator = graphEntityInstantiator;
|
||||
}
|
||||
|
||||
public <T extends NodeBacked> Finder<T> getFinderForClass(Class<T> clazz) {
|
||||
return new Finder<T>(clazz, graphDatabaseService, graphEntityInstantiator);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package org.springframework.persistence.graph.neo4j;
|
||||
import org.neo4j.graphdb.DynamicRelationshipType;
|
||||
import org.neo4j.graphdb.GraphDatabaseService;
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.neo4j.graphdb.Relationship;
|
||||
import org.neo4j.graphdb.RelationshipType;
|
||||
import org.neo4j.util.GraphDatabaseUtil;
|
||||
|
||||
@@ -21,12 +22,20 @@ public abstract class Neo4jHelper {
|
||||
}
|
||||
|
||||
public static long count(Class<? extends NodeBacked> entityClass, GraphDatabaseService gds) {
|
||||
// TODO: Need to figure out what to do here
|
||||
// Node subrefNode = findSubreferenceNode(Person.class, gds);
|
||||
// If the subref node is new, there are 0 instances of this entity class
|
||||
// int count = ((Integer) subrefNode.getProperty(SUBREFERENCE_NODE_COUNTER_KEY, 0));
|
||||
// return count;
|
||||
return 1;
|
||||
Node subrefNode = findSubreferenceNode(entityClass, gds);
|
||||
return (Integer) subrefNode.getProperty(SUBREFERENCE_NODE_COUNTER_KEY, 0);
|
||||
}
|
||||
|
||||
public static void cleanDb(GraphDatabaseService graphDatabaseService) {
|
||||
Node refNode = graphDatabaseService.getReferenceNode();
|
||||
for (Node node : graphDatabaseService.getAllNodes()) {
|
||||
for (Relationship rel : node.getRelationships()) {
|
||||
rel.delete();
|
||||
}
|
||||
if (!refNode.equals(node)) {
|
||||
node.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,9 +2,11 @@ package org.springframework.persistence.graph.neo4j;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.AbstractSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
@@ -100,7 +102,7 @@ public aspect Neo4jNodeBacking extends AbstractTypeAnnotatingMixinFields<GraphEn
|
||||
public long NodeBacked.getId() {
|
||||
return underlyingNode.getId();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Equals and hashCode for Neo4j entities.
|
||||
@@ -144,7 +146,7 @@ public aspect Neo4jNodeBacking extends AbstractTypeAnnotatingMixinFields<GraphEn
|
||||
FieldSignature fieldSignature=(FieldSignature) thisJoinPoint.getSignature();
|
||||
Field f = fieldSignature.getField();
|
||||
// TODO fix arrays
|
||||
Class fieldType=f.getType();
|
||||
Class<?> fieldType = f.getType();
|
||||
if (isPropertyType(fieldType)) {
|
||||
String propName = getNeo4jPropertyName(f);
|
||||
entity.getUnderlyingNode().setProperty(propName, newVal);
|
||||
@@ -158,21 +160,21 @@ public aspect Neo4jNodeBacking extends AbstractTypeAnnotatingMixinFields<GraphEn
|
||||
return proceed(entity, newVal);
|
||||
}
|
||||
log.info("SET " + f + " -> Neo4J relationship with value=[" + newVal + "]");
|
||||
Object result=relInfo.apply(entity, newVal);
|
||||
Object result = relInfo.apply(entity, newVal);
|
||||
return proceed(entity,result);
|
||||
} catch(NotInTransactionException e) {
|
||||
throw new InvalidDataAccessResourceUsageException("Not in a Neo4j transaction.", e);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isPropertyType(Class fieldType) {
|
||||
return fieldType.isPrimitive() || fieldType.equals(String.class) || (fieldType.getName().startsWith("java.lang") && Number.class.isAssignableFrom(fieldType));
|
||||
// TODO boolean, arrays, character
|
||||
}
|
||||
|
||||
private boolean isSingleRelationshipField(Field f) {
|
||||
return f.getType().isAnnotationPresent(GraphEntity.class);
|
||||
//return NodeBacked.class.isAssignableFrom(f.getType());
|
||||
private boolean isPropertyType(Class<?> fieldType) {
|
||||
// todo: add array support
|
||||
return fieldType.isPrimitive()
|
||||
|| (fieldType.isArray() && !fieldType.getComponentType().isArray() && isPropertyType(fieldType.getComponentType()))
|
||||
|| fieldType.equals(String.class)
|
||||
|| fieldType.equals(Character.class)
|
||||
|| fieldType.equals(Boolean.class)
|
||||
|| (fieldType.getName().startsWith("java.lang") && Number.class.isAssignableFrom(fieldType));
|
||||
}
|
||||
|
||||
private static String getNeo4jPropertyName(Field field) {
|
||||
|
||||
@@ -14,9 +14,13 @@ import org.neo4j.graphdb.GraphDatabaseService;
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.neo4j.graphdb.Relationship;
|
||||
import org.neo4j.graphdb.Transaction;
|
||||
import org.neo4j.helpers.collection.IteratorUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.dao.InvalidDataAccessResourceUsageException;
|
||||
import org.springframework.persistence.graph.neo4j.Finder;
|
||||
import org.springframework.persistence.graph.neo4j.FinderFactory;
|
||||
import org.springframework.persistence.graph.neo4j.Neo4jHelper;
|
||||
import org.springframework.persistence.graph.neo4j.NodeBacked;
|
||||
import org.springframework.persistence.support.EntityInstantiator;
|
||||
import org.springframework.persistence.test.Group;
|
||||
@@ -25,6 +29,7 @@ import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
@@ -43,6 +48,9 @@ public class Neo4jGraphPersistenceTest {
|
||||
@Autowired
|
||||
protected GraphDatabaseService graphDatabaseService;
|
||||
|
||||
@Autowired
|
||||
private FinderFactory finderFactory;
|
||||
|
||||
private Long insertedId = 0L;
|
||||
|
||||
@Test
|
||||
@@ -50,14 +58,24 @@ public class Neo4jGraphPersistenceTest {
|
||||
Assert.assertNotNull( graphDatabaseService );
|
||||
Assert.assertNotNull( nodeInstantiator );
|
||||
}
|
||||
|
||||
|
||||
@Before
|
||||
@Transactional
|
||||
public void cleanDb() {
|
||||
Neo4jHelper.cleanDb(graphDatabaseService);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testUserConstructor() {
|
||||
Person p = new Person("Rod", 39);
|
||||
Assert.assertEquals(p.getName(), p.getUnderlyingNode().getProperty("Person.name"));
|
||||
Assert.assertEquals(p.getAge(), p.getUnderlyingNode().getProperty("Person.age"));
|
||||
insertedId = p.getId();
|
||||
Node n = findPersonTestNode();
|
||||
Person found = nodeInstantiator.createEntityFromState(n, Person.class);
|
||||
Assert.assertEquals("Rod", found.getUnderlyingNode().getProperty("Person.name"));
|
||||
Assert.assertEquals(39, found.getUnderlyingNode().getProperty("Person.age"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -221,14 +239,42 @@ public class Neo4jGraphPersistenceTest {
|
||||
Assert.assertEquals(new HashSet<Person>(Arrays.asList(david,michael)), personsFromGet);
|
||||
Assert.assertTrue(Set.class.isAssignableFrom(personsFromGet.getClass()));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testInstantiatedFinder() {
|
||||
Node n = findPersonTestNode();
|
||||
Person found = nodeInstantiator.createEntityFromState(n, Person.class);
|
||||
Assert.assertEquals("Rod", found.getUnderlyingNode().getProperty("Person.name"));
|
||||
Assert.assertEquals(39, found.getUnderlyingNode().getProperty("Person.age"));
|
||||
public void testFinderFindAll() {
|
||||
Person p1 = new Person("Michael", 35);
|
||||
Person p2 = new Person("David", 25);
|
||||
Finder<Person> finder = finderFactory.getFinderForClass(Person.class);
|
||||
Iterable<Person> allPersons = finder.findAll();
|
||||
Assert.assertEquals(new HashSet<Person>(Arrays.asList(p1, p2)), IteratorUtil.addToCollection(allPersons.iterator(), new HashSet<Person>()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testFinderFindById() {
|
||||
Person p = new Person("Michael", 35);
|
||||
Finder<Person> finder = finderFactory.getFinderForClass(Person.class);
|
||||
Person pById = finder.findById(p.getId());
|
||||
Assert.assertEquals(p, pById);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testFinderFindByIdNonexistent() {
|
||||
Person p = new Person("Michael", 35);
|
||||
Finder<Person> finder = finderFactory.getFinderForClass(Person.class);
|
||||
Person p2 = finder.findById(589736218);
|
||||
Assert.assertNull(p2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testFinderCount() {
|
||||
Finder<Person> finder = finderFactory.getFinderForClass(Person.class);
|
||||
Assert.assertEquals(0, finder.count());
|
||||
Person p = new Person("Michael", 35);
|
||||
Assert.assertEquals(1, finder.count());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -81,7 +81,12 @@
|
||||
<constructor-arg index="0" value="${neo4j.databaseDirectory}" />
|
||||
</bean>
|
||||
|
||||
<bean class="org.springframework.persistence.graph.neo4j.Neo4jConstructorEntityInstantiator" />
|
||||
<bean id="finderFactory" class="org.springframework.persistence.graph.neo4j.FinderFactory">
|
||||
<constructor-arg ref="graphDbService" />
|
||||
<constructor-arg ref="entityInstantiator" />
|
||||
</bean>
|
||||
|
||||
<bean id="entityInstantiator" class="org.springframework.persistence.graph.neo4j.Neo4jConstructorEntityInstantiator" />
|
||||
|
||||
<!--
|
||||
-->
|
||||
|
||||
Reference in New Issue
Block a user