diff --git a/spring-data-neo4j-aspects/src/main/aspect/org/springframework/data/neo4j/aspects/support/node/Neo4jNodeBacking.aj b/spring-data-neo4j-aspects/src/main/aspect/org/springframework/data/neo4j/aspects/support/node/Neo4jNodeBacking.aj index bba4f515c..8ebbfe904 100644 --- a/spring-data-neo4j-aspects/src/main/aspect/org/springframework/data/neo4j/aspects/support/node/Neo4jNodeBacking.aj +++ b/spring-data-neo4j-aspects/src/main/aspect/org/springframework/data/neo4j/aspects/support/node/Neo4jNodeBacking.aj @@ -210,7 +210,7 @@ public privileged aspect Neo4jNodeBacking { // extends AbstractTypeAnnotatingMix } public void NodeBacked.removeRelationshipTo(NodeBacked target, String relationshipType) { - template().removeRelationshipBetween(this, target, relationshipType); + template().deleteRelationshipBetween(this, target, relationshipType); } public R NodeBacked.getRelationshipTo( NodeBacked target, Class relationshipClass, String type) { diff --git a/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/support/NodeEntityTest.java b/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/support/NodeEntityTest.java index 388fefbec..b0672d3af 100644 --- a/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/support/NodeEntityTest.java +++ b/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/support/NodeEntityTest.java @@ -102,7 +102,7 @@ public class NodeEntityTest extends EntityTestBase { Person spouse = persistedPerson("Tina", 36); p.setSpouse(spouse); long id = spouse.getId(); - neo4jTemplate.remove(spouse); + neo4jTemplate.delete(spouse); tx.success(); tx.finish(); Assert.assertNull("spouse removed " + p.getSpouse(), p.getSpouse()); diff --git a/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/support/typerepresentation/SubReferenceNodeTypeRepresentationStrategyTest.java b/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/support/typerepresentation/SubReferenceNodeTypeRepresentationStrategyTest.java index c1d594940..8609ce4a9 100644 --- a/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/support/typerepresentation/SubReferenceNodeTypeRepresentationStrategyTest.java +++ b/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/support/typerepresentation/SubReferenceNodeTypeRepresentationStrategyTest.java @@ -80,7 +80,7 @@ public class SubReferenceNodeTypeRepresentationStrategyTest extends EntityTestBa } @Test(expected = IllegalArgumentException.class) public void gettingTypeFromNonTypeNodeShouldThrowAnDescriptiveException() throws Exception { - Node referenceNode = neo4jTemplate.getReferenceNode(Node.class); + Node referenceNode = neo4jTemplate.getReferenceNode(); nodeTypeRepresentationStrategy.getJavaType(referenceNode); } diff --git a/spring-data-neo4j-aspects/src/main/java/org/springframework/data/neo4j/aspects/fieldaccess/JpaIdFieldAccessListenerFactory.java b/spring-data-neo4j-cross-store/src/main/java/org/springframework/data/neo4j/cross_store/fieldaccess/JpaIdFieldAccessListenerFactory.java similarity index 97% rename from spring-data-neo4j-aspects/src/main/java/org/springframework/data/neo4j/aspects/fieldaccess/JpaIdFieldAccessListenerFactory.java rename to spring-data-neo4j-cross-store/src/main/java/org/springframework/data/neo4j/cross_store/fieldaccess/JpaIdFieldAccessListenerFactory.java index 41209f0fa..c420e85b2 100644 --- a/spring-data-neo4j-aspects/src/main/java/org/springframework/data/neo4j/aspects/fieldaccess/JpaIdFieldAccessListenerFactory.java +++ b/spring-data-neo4j-cross-store/src/main/java/org/springframework/data/neo4j/cross_store/fieldaccess/JpaIdFieldAccessListenerFactory.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.data.neo4j.aspects.fieldaccess; +package org.springframework.data.neo4j.cross_store.fieldaccess; import org.springframework.data.neo4j.fieldaccess.FieldAccessListener; import org.springframework.data.neo4j.fieldaccess.FieldAccessorListenerFactory; diff --git a/spring-data-neo4j-cross-store/src/main/java/org/springframework/data/neo4j/cross_store/support/node/CrossStoreNodeEntityState.java b/spring-data-neo4j-cross-store/src/main/java/org/springframework/data/neo4j/cross_store/support/node/CrossStoreNodeEntityState.java index 194791bb5..18efbf25c 100644 --- a/spring-data-neo4j-cross-store/src/main/java/org/springframework/data/neo4j/cross_store/support/node/CrossStoreNodeEntityState.java +++ b/spring-data-neo4j-cross-store/src/main/java/org/springframework/data/neo4j/cross_store/support/node/CrossStoreNodeEntityState.java @@ -24,7 +24,7 @@ import org.springframework.dao.InvalidDataAccessResourceUsageException; import org.springframework.data.neo4j.annotation.GraphProperty; import org.springframework.data.neo4j.annotation.RelatedTo; import org.springframework.data.neo4j.aspects.core.NodeBacked; -import org.springframework.data.neo4j.aspects.fieldaccess.JpaIdFieldAccessListenerFactory; +import org.springframework.data.neo4j.cross_store.fieldaccess.JpaIdFieldAccessListenerFactory; import org.springframework.data.neo4j.fieldaccess.*; import org.springframework.data.neo4j.mapping.Neo4jPersistentEntity; import org.springframework.data.neo4j.mapping.Neo4jPersistentProperty; diff --git a/spring-data-neo4j-examples/imdb/src/main/java/org/neo4j/examples/imdb/domain/ImdbServiceImpl.java b/spring-data-neo4j-examples/imdb/src/main/java/org/neo4j/examples/imdb/domain/ImdbServiceImpl.java index 72cb85214..0e6ba745a 100644 --- a/spring-data-neo4j-examples/imdb/src/main/java/org/neo4j/examples/imdb/domain/ImdbServiceImpl.java +++ b/spring-data-neo4j-examples/imdb/src/main/java/org/neo4j/examples/imdb/domain/ImdbServiceImpl.java @@ -1,91 +1,91 @@ -package org.neo4j.examples.imdb.domain; - -import org.neo4j.graphalgo.GraphAlgoFactory; -import org.neo4j.graphdb.Node; -import org.neo4j.graphdb.Path; -import org.neo4j.kernel.StandardExpander; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.neo4j.support.Neo4jTemplate; -import org.springframework.transaction.annotation.Transactional; - -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.NoSuchElementException; - -class ImdbServiceImpl implements ImdbService { - @Autowired - private Neo4jTemplate template; - @Autowired - private ImdbSearchEngine searchEngine; - @Autowired - private MovieRepository movieRepository; - @Autowired - private ActorRepository actorRepository; - - public Actor createActor(final String name) { - final Actor actor = new Actor().persist(); - actor.setName(name); - searchEngine.indexActor(actor); - return actor; - } - - public Movie createMovie(final String title, final int year) { - final Movie movie = new Movie().persist(); - movie.setTitle(title); - movie.setYear(year); - searchEngine.indexMovie(movie); - return movie; - } - - public Actor getActor(final String name) { - Actor actor = actorRepository.findByPropertyValue("name", name); - if (actor != null) return actor; - return searchEngine.searchActor(name); - } - - public Movie getMovie(final String title) { - Movie movie = getExactMovie(title); - if (movie != null) return movie; - - return searchEngine.searchMovie(title); - } - - public Movie getExactMovie(final String title) { - return movieRepository.findByPropertyValue("title", title); - } - - - @Transactional - public void setupReferenceRelationship() { - Node referenceNode = template.getReferenceNode(Node.class); - Actor bacon = actorRepository.findByPropertyValue("name", "Bacon, Kevin"); - - if (bacon == null) throw new NoSuchElementException("Unable to find Kevin Bacon actor"); - - referenceNode.createRelationshipTo(bacon.getPersistentState(), RelTypes.IMDB); - } - - public List getBaconPath(final Actor actor) { - if (actor == null) throw new IllegalArgumentException("Null actor"); - - Actor bacon = actorRepository.findByPropertyValue("name", "Bacon, Kevin"); - - Path path = GraphAlgoFactory.shortestPath(StandardExpander.DEFAULT.add(RelTypes.ACTS_IN), 10).findSinglePath(bacon.getPersistentState(), actor.getPersistentState()); - if (path==null) return Collections.emptyList(); - return convertNodesToActorsAndMovies(path); - } - - private List convertNodesToActorsAndMovies(final Path list) { - final List actorAndMovieList = new LinkedList(); - int mod = 0; - for (Node node : list.nodes()) { - if (mod++ % 2 == 0) { - actorAndMovieList.add(template.createEntityFromState(node, Actor.class)); - } else { - actorAndMovieList.add(template.createEntityFromState(node, Movie.class)); - } - } - return actorAndMovieList; - } +package org.neo4j.examples.imdb.domain; + +import org.neo4j.graphalgo.GraphAlgoFactory; +import org.neo4j.graphdb.Node; +import org.neo4j.graphdb.Path; +import org.neo4j.kernel.StandardExpander; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.neo4j.support.Neo4jTemplate; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.NoSuchElementException; + +class ImdbServiceImpl implements ImdbService { + @Autowired + private Neo4jTemplate template; + @Autowired + private ImdbSearchEngine searchEngine; + @Autowired + private MovieRepository movieRepository; + @Autowired + private ActorRepository actorRepository; + + public Actor createActor(final String name) { + final Actor actor = new Actor().persist(); + actor.setName(name); + searchEngine.indexActor(actor); + return actor; + } + + public Movie createMovie(final String title, final int year) { + final Movie movie = new Movie().persist(); + movie.setTitle(title); + movie.setYear(year); + searchEngine.indexMovie(movie); + return movie; + } + + public Actor getActor(final String name) { + Actor actor = actorRepository.findByPropertyValue("name", name); + if (actor != null) return actor; + return searchEngine.searchActor(name); + } + + public Movie getMovie(final String title) { + Movie movie = getExactMovie(title); + if (movie != null) return movie; + + return searchEngine.searchMovie(title); + } + + public Movie getExactMovie(final String title) { + return movieRepository.findByPropertyValue("title", title); + } + + + @Transactional + public void setupReferenceRelationship() { + Node referenceNode = template.getReferenceNode(); + Actor bacon = actorRepository.findByPropertyValue("name", "Bacon, Kevin"); + + if (bacon == null) throw new NoSuchElementException("Unable to find Kevin Bacon actor"); + + referenceNode.createRelationshipTo(bacon.getPersistentState(), RelTypes.IMDB); + } + + public List getBaconPath(final Actor actor) { + if (actor == null) throw new IllegalArgumentException("Null actor"); + + Actor bacon = actorRepository.findByPropertyValue("name", "Bacon, Kevin"); + + Path path = GraphAlgoFactory.shortestPath(StandardExpander.DEFAULT.add(RelTypes.ACTS_IN), 10).findSinglePath(bacon.getPersistentState(), actor.getPersistentState()); + if (path==null) return Collections.emptyList(); + return convertNodesToActorsAndMovies(path); + } + + private List convertNodesToActorsAndMovies(final Path list) { + final List actorAndMovieList = new LinkedList(); + int mod = 0; + for (Node node : list.nodes()) { + if (mod++ % 2 == 0) { + actorAndMovieList.add(template.createEntityFromState(node, Actor.class)); + } else { + actorAndMovieList.add(template.createEntityFromState(node, Movie.class)); + } + } + return actorAndMovieList; + } } \ No newline at end of file diff --git a/spring-data-neo4j-rest/src/main/java/org/springframework/data/neo4j/rest/SpringRestGraphDatabase.java b/spring-data-neo4j-rest/src/main/java/org/springframework/data/neo4j/rest/SpringRestGraphDatabase.java index 36c83267f..e4fc01a4a 100644 --- a/spring-data-neo4j-rest/src/main/java/org/springframework/data/neo4j/rest/SpringRestGraphDatabase.java +++ b/spring-data-neo4j-rest/src/main/java/org/springframework/data/neo4j/rest/SpringRestGraphDatabase.java @@ -77,7 +77,7 @@ public class SpringRestGraphDatabase extends org.neo4j.rest.graphdb.RestGraphDat } @Override - public TraversalDescription createTraversalDescription() { + public TraversalDescription traversalDescription() { return super.getRestAPI().createTraversalDescription(); } @@ -144,8 +144,7 @@ public class SpringRestGraphDatabase extends org.neo4j.rest.graphdb.RestGraphDat @Override public void setResultConverter(ResultConverter resultConverter) { - - + this.resultConverter = resultConverter; } private void removeFromIndexes(Node node) { diff --git a/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/support/RestEntityTest.java b/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/support/RestEntityTest.java index 36d81d597..fbc2ce078 100644 --- a/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/support/RestEntityTest.java +++ b/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/support/RestEntityTest.java @@ -20,17 +20,21 @@ import org.junit.Assert; import org.junit.Test; import org.neo4j.graphdb.Direction; import org.neo4j.graphdb.Node; +import org.neo4j.graphdb.NotFoundException; import org.neo4j.graphdb.Relationship; import java.util.Arrays; +import static org.junit.Assert.assertEquals; +import static org.neo4j.helpers.collection.MapUtil.map; + public class RestEntityTest extends RestTestBase { @Test public void testSetProperty() { restGraphDatabase.getReferenceNode().setProperty( "name", "test" ); Node node = restGraphDatabase.getReferenceNode(); - Assert.assertEquals( "test", node.getProperty( "name" ) ); + assertEquals("test", node.getProperty("name")); } @Test @@ -51,9 +55,30 @@ public class RestEntityTest extends RestTestBase { public void testRemoveProperty() { Node node = restGraphDatabase.getReferenceNode(); node.setProperty( "name", "test" ); - Assert.assertEquals( "test", node.getProperty( "name" ) ); + assertEquals("test", node.getProperty("name")); node.removeProperty( "name" ); - Assert.assertEquals( false, node.hasProperty( "name" ) ); + assertEquals(false, node.hasProperty("name")); + } + + @Test(expected = NotFoundException.class) + public void testRemoveNode() { + Node node = restGraphDatabase.createNode(); + node.setProperty( "name", "test" ); + final long nodeId = node.getId(); + assertEquals("test", node.getProperty("name")); + restGraphDatabase.remove(node); + assertEquals(null, restGraphDatabase.getNodeById(nodeId)); + } + + @Test(expected = NotFoundException.class) + public void testRemoveRelationship() { + Node refNode = restGraphDatabase.getReferenceNode(); + Node node = restGraphDatabase.createNode(); + Relationship rel = restGraphDatabase.createRelationship(refNode, node, Type.TEST, map("name","test")); + final long relId = rel.getId(); + assertEquals("test", rel.getProperty("name")); + restGraphDatabase.remove(rel); + assertEquals(null, restGraphDatabase.getRelationshipById(relId)); } @@ -63,9 +88,9 @@ public class RestEntityTest extends RestTestBase { Node node = restGraphDatabase.createNode(); Relationship rel = refNode.createRelationshipTo( node, Type.TEST ); rel.setProperty( "name", "test" ); - Assert.assertEquals( "test", rel.getProperty( "name" ) ); + assertEquals("test", rel.getProperty("name")); Relationship foundRelationship = IsRelationshipToNodeMatcher.relationshipFromTo( refNode.getRelationships( Type.TEST, Direction.OUTGOING ), refNode, node ); - Assert.assertEquals( "test", foundRelationship.getProperty( "name" ) ); + assertEquals("test", foundRelationship.getProperty("name")); } @Test @@ -74,13 +99,13 @@ public class RestEntityTest extends RestTestBase { Node node = restGraphDatabase.createNode(); Relationship rel = refNode.createRelationshipTo( node, Type.TEST ); rel.setProperty( "name", "test" ); - Assert.assertEquals( "test", rel.getProperty( "name" ) ); + assertEquals("test", rel.getProperty("name")); Relationship foundRelationship = IsRelationshipToNodeMatcher.relationshipFromTo( refNode.getRelationships( Type.TEST, Direction.OUTGOING ), refNode, node ); - Assert.assertEquals( "test", foundRelationship.getProperty( "name" ) ); + assertEquals("test", foundRelationship.getProperty("name")); rel.removeProperty( "name" ); - Assert.assertEquals( false, rel.hasProperty( "name" ) ); + assertEquals(false, rel.hasProperty("name")); Relationship foundRelationship2 = IsRelationshipToNodeMatcher.relationshipFromTo( refNode.getRelationships( Type.TEST, Direction.OUTGOING ), refNode, node ); - Assert.assertEquals( false, foundRelationship2.hasProperty( "name" ) ); + assertEquals(false, foundRelationship2.hasProperty("name")); } } diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/config/ConfigurationCheck.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/config/ConfigurationCheck.java index c0e59a633..8fdfc2b7d 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/config/ConfigurationCheck.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/config/ConfigurationCheck.java @@ -16,7 +16,6 @@ package org.springframework.data.neo4j.config; -import org.neo4j.graphdb.Node; import org.neo4j.graphdb.Transaction; import org.springframework.beans.factory.BeanCreationException; import org.springframework.context.ApplicationListener; @@ -83,6 +82,6 @@ public class ConfigurationCheck implements ApplicationListenergraphDatabase.createNode(PropertyMap._("name","value")); - * graphDatabase.createNode(PropertyMap.props().set("name","value").set("prop","anotherValue").toMap(), "name", "prop"); - * - * - * @param props properties to be set at node creation might be null - * @return the newly created node - */ Node createNode(Map props); /** @@ -62,20 +52,6 @@ public interface GraphDatabase { */ Relationship getRelationshipById(long id); - /** - * Transactionally creates the relationship, sets the properties (if any) and indexes the given fielss (if any) - * Two shortcut means of providing the properties (very short with static imports) - * graphDatabase.createRelationship(from,to,TYPE, PropertyMap._("name","value")); - * graphDatabase.createRelationship(from,to,TYPE, PropertyMap.props().set("name","value").set("prop","anotherValue").toMap(), "name", "prop"); - * - * - * - * @param startNode start-node of relationship - * @param endNode end-node of relationship - * @param type relationship type, might by an enum implementing RelationshipType or a DynamicRelationshipType.withName("name") - * @param props optional initial properties - * @return the newly created relationship - */ Relationship createRelationship(Node startNode, Node endNode, RelationshipType type, Map props); /** @@ -98,7 +74,7 @@ public interface GraphDatabase { /** * @return a TraversalDescription as starting point for defining a traversal */ - TraversalDescription createTraversalDescription(); + TraversalDescription traversalDescription(); QueryEngine queryEngineFor(QueryType type); diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/mapping/EntityPersister.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/mapping/EntityPersister.java index ff18ddb12..a372c9a07 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/mapping/EntityPersister.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/mapping/EntityPersister.java @@ -23,7 +23,7 @@ import org.neo4j.graphdb.PropertyContainer; */ public interface EntityPersister { - T projectTo(Object entity, Class targetType); + T projectTo(Object entity, Class targetType); T createEntityFromState(S state, Class type); T createEntityFromStoredType(S state); boolean isNodeEntity(Class targetType); diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/mapping/Neo4jEntityPersister.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/mapping/Neo4jEntityPersister.java index 12c7ae20f..93c17a3a7 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/mapping/Neo4jEntityPersister.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/mapping/Neo4jEntityPersister.java @@ -164,8 +164,8 @@ public class Neo4jEntityPersister implements EntityPersister, Neo4jEntityConvert return state instanceof Node; } - public T projectTo(Object entity, Class targetType) { - S state = getPersistentState(entity); + public T projectTo(Object entity, Class targetType) { + PropertyContainer state = getPersistentState(entity); return createEntityFromState(state, targetType); } diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/mapping/Neo4jPersistentEntityImpl.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/mapping/Neo4jPersistentEntityImpl.java index 0294dad56..fa644d7cc 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/mapping/Neo4jPersistentEntityImpl.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/mapping/Neo4jPersistentEntityImpl.java @@ -56,6 +56,12 @@ public class Neo4jPersistentEntityImpl extends BasicPersistentEntity extends BasicPersistentEntity extends AbstractGraphRepository implements GraphRepository { public RelationshipGraphRepository(final Class clazz, final Neo4jTemplate template) { @@ -40,13 +41,17 @@ public class RelationshipGraphRepository extends AbstractGraphRepository save(Iterable entities) { - return (Iterable) entities; + List result=new ArrayList(); + for (T entity : entities) { + result.add(template.save(entity)); + } + return result; } } diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/DelegatingGraphDatabase.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/DelegatingGraphDatabase.java index c94c32368..5635a8c49 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/DelegatingGraphDatabase.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/DelegatingGraphDatabase.java @@ -165,7 +165,7 @@ public class DelegatingGraphDatabase implements GraphDatabase { } @Override - public TraversalDescription createTraversalDescription() { + public TraversalDescription traversalDescription() { return Traversal.description(); } diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/EntityStateHandler.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/EntityStateHandler.java index 92e6c9dd9..5d3aa6c8b 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/EntityStateHandler.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/EntityStateHandler.java @@ -122,8 +122,8 @@ public class EntityStateHandler { @SuppressWarnings("unchecked") private S createRelationship(Object entity, Neo4jPersistentEntityImpl persistentEntity) { final RelationshipProperties relationshipProperties = persistentEntity.getRelationshipProperties(); - Node startNode = (Node) relationshipProperties.getStartNodeProperty().getValue(entity); - Node endNode = (Node) relationshipProperties.getStartNodeProperty().getValue(entity); + Node startNode = (Node) getPersistentState(relationshipProperties.getStartNodeProperty().getValue(entity)); + Node endNode = (Node) getPersistentState(relationshipProperties.getEndeNodeProperty().getValue(entity)); Object relType = relationshipProperties.getTypeProperty().getValue(entity); if (relType instanceof RelationshipType) { return (S) startNode.createRelationshipTo(endNode, (RelationshipType) relType); @@ -207,9 +207,4 @@ public class EntityStateHandler { } - public Node getNodeState(Object entity) { - final PropertyContainer result = getPersistentState(entity); - if (result==null || result instanceof Node) return (Node) result; - throw new IllegalArgumentException("State of "+entity+" is no Node but "+result); - } } diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/Neo4jTemplate.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/Neo4jTemplate.java index d4f46c484..08b9a19b7 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/Neo4jTemplate.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/Neo4jTemplate.java @@ -48,8 +48,6 @@ import org.springframework.transaction.support.TransactionTemplate; import javax.annotation.PostConstruct; import javax.validation.Validator; -import java.util.ArrayList; -import java.util.Collection; import java.util.Map; import static org.springframework.data.neo4j.support.ParameterCheck.notNull; @@ -135,6 +133,21 @@ public class Neo4jTemplate implements Neo4jOperations, EntityPersister { } + @Override + public T findOne(long id, final Class entityClass) { + if (isNodeEntity(entityClass)) { + final Node node = getNode(id); + if (node==null) return null; + return infrastructure.getTypeRepresentationStrategies().projectEntity(node, entityClass); + } + if (isRelationshipEntity(entityClass)) { + final Relationship relationship = getRelationship(id); + if (relationship==null) return null; + return infrastructure.getTypeRepresentationStrategies().projectEntity(relationship, entityClass); + } + throw new IllegalArgumentException("provided entity type is not annotated with @NodeEntiy nor @RelationshipEntity"); + } + @Override public ClosableIterable findAll(final Class entityClass) { notNull(entityClass,"entity type"); @@ -158,7 +171,7 @@ public class Neo4jTemplate implements Neo4jOperations, EntityPersister { } @Override - public T projectTo(Object entity, Class targetType) { + public T projectTo(Object entity, Class targetType) { notNull(entity,"entity",targetType,"new entity class"); return infrastructure.getEntityPersister().projectTo(entity, targetType); } @@ -183,7 +196,7 @@ public class Neo4jTemplate implements Neo4jOperations, EntityPersister { } @Override - public void remove(Object entity) { + public void delete(Object entity) { notNull(entity,"entity"); infrastructure.getEntityRemover().remove(entity); } @@ -218,25 +231,6 @@ public class Neo4jTemplate implements Neo4jOperations, EntityPersister { return convert(node, target); } - @Override - public Result createNodes(Map... allProperties) { - Collection result = new ArrayList(allProperties.length); - for (Map properties : allProperties) { - result.add(createNode(properties)); - } - return convert(result); - } - - @Override - public Iterable createNodesAs(Class target, Map... allProperties) { - final TypeRepresentationStrategy nodeTypeRepresentationStrategy = isNodeEntity(target) ? infrastructure.getTypeRepresentationStrategies().getNodeTypeRepresentationStrategy() : null; - Collection result = new ArrayList(allProperties.length); - for (Map properties : allProperties) { - result.add(createNode(properties, target, nodeTypeRepresentationStrategy)); - } - return convert(result).to(target); - } - private Node createNode(Map properties, Class target, TypeRepresentationStrategy nodeTypeRepresentationStrategy) { final Node node = createNode(properties); if (nodeTypeRepresentationStrategy != null) { @@ -304,7 +298,7 @@ public class Neo4jTemplate implements Neo4jOperations, EntityPersister { return infrastructure.getEntityStateHandler().getRelationshipBetween(start,end,relationshipType); } @Override - public void removeRelationshipBetween(Object start, Object end, String type) { + public void deleteRelationshipBetween(Object start, Object end, String type) { notNull(start,"start",end,"end",type,"relationshipType"); infrastructure.getEntityRemover().removeRelationshipBetween(start, end, type); } @@ -321,12 +315,12 @@ public class Neo4jTemplate implements Neo4jOperations, EntityPersister { } @Override - public Relationship createRelationshipBetween(final Node startNode, final Node endNode, final RelationshipType relationshipType, final Map properties) { + public Relationship createRelationshipBetween(final Node startNode, final Node endNode, final String relationshipType, final Map properties) { notNull(startNode, "startNode", endNode, "endNode", relationshipType, "relationshipType", properties, "properties"); return exec(new GraphCallback() { @Override public Relationship doWithGraph(GraphDatabase graph) throws Exception { - return graph.createRelationship(startNode, endNode, relationshipType, properties); + return graph.createRelationship(startNode, endNode, DynamicRelationshipType.withName(relationshipType), properties); } }); } @@ -364,11 +358,9 @@ public class Neo4jTemplate implements Neo4jOperations, EntityPersister { @Override @SuppressWarnings("unchecked") - public T getReferenceNode(Class target) { + public Node getReferenceNode() { try { - final Node node = infrastructure.getGraphDatabase().getReferenceNode(); - if (Node.class.isAssignableFrom(target)) return (T) node; - return convert(node, target); + return infrastructure.getGraphDatabase().getReferenceNode(); } catch (RuntimeException e) { throw translateExceptionIfPossible(e); } @@ -499,6 +491,11 @@ public class Neo4jTemplate implements Neo4jOperations, EntityPersister { } } + @Override + public TraversalDescription traversalDescription() { + return infrastructure.getGraphDatabase().traversalDescription(); + } + public EntityStateHandler getEntityStateHandler() { return infrastructure.getEntityStateHandler(); } @@ -522,4 +519,9 @@ public class Neo4jTemplate implements Neo4jOperations, EntityPersister { public MappingInfrastructure getInfrastructure() { return infrastructure; } + + @Override + public GraphDatabase getGraphDatabase() { + return infrastructure.getGraphDatabase(); + } } diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/template/Neo4jOperations.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/template/Neo4jOperations.java index 37466b1bb..e5b2f0592 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/template/Neo4jOperations.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/template/Neo4jOperations.java @@ -22,6 +22,7 @@ import org.neo4j.graphdb.traversal.TraversalDescription; import org.neo4j.helpers.collection.ClosableIterable; import org.springframework.data.neo4j.annotation.QueryType; import org.springframework.data.neo4j.conversion.Result; +import org.springframework.data.neo4j.core.GraphDatabase; import org.springframework.data.neo4j.repository.GraphRepository; import org.springframework.data.neo4j.support.query.QueryEngine; @@ -48,7 +49,10 @@ public interface Neo4jOperations { GraphRepository repositoryFor(Class clazz); - T getReferenceNode(Class target); + /** + * Returns the reference node. + */ + Node getReferenceNode(); /** * Delegates to the GraphDatabase @@ -74,20 +78,6 @@ public interface Neo4jOperations { */ T createNodeAs(Class target, Map properties); - /** - * Creates a number of nodes in a single step - * @param allProperties - * @return the nodes as a Result, which can be converted - */ - Result createNodes(Map... allProperties); - - /** - * Creates a number of nodes mapped by the given entity class - * @param target mapped entity class or Node.class - * @param allProperties properties for each of the created nodes - */ - Iterable createNodesAs(Class target, Map... allProperties); - /** * Delegates to the GraphDatabase @@ -101,7 +91,7 @@ public interface Neo4jOperations { /** * Creates a relationship with the given initial properties. */ - Relationship createRelationshipBetween(Node startNode, Node endNode, RelationshipType type, Map props); + Relationship createRelationshipBetween(Node startNode, Node endNode, String type, Map props); /** * Retrieves a single relationship entity between two node entities with the given relationship type projected to the provided @@ -117,7 +107,7 @@ public interface Neo4jOperations { /** * Removes the relationship of this type between the two node entities */ - void removeRelationshipBetween(Object start, Object end, String type); + void deleteRelationshipBetween(Object start, Object end, String type); /** * Creates a single relationship entity between two node entities with the given relationship type projected to the provided @@ -149,19 +139,19 @@ public interface Neo4jOperations { T index(String indexName, T element, String field, Object value); /** - * The value is looked up in the Neo4j index returning the IndexHits wrapped in a QueryResult to be converted + * The value is looked up in the Neo4j index returning the IndexHits wrapped in a Result to be converted * into Paths or Entities. */ Result lookup(String indexName, String field, Object value); /** - * The query is executed on the index returning the IndexHits wrapped in a QueryResult to be converted + * The query is executed on the index returning the IndexHits wrapped in a Result to be converted * into Paths or Entities. */ Result lookup(String indexName, Object query); /** - * The query is executed on the index for this entity type returning the IndexHits wrapped in a QueryResult to be converted + * The query is executed on the index for this entity type returning the IndexHits wrapped in a Result to be converted * into Paths or Entities. */ Result lookup(Class indexedType, Object query); @@ -172,33 +162,33 @@ public interface Neo4jOperations { QueryEngine queryEngineFor(QueryType type); /** - * Runs the given cypher statement and packages the result in a QueryResult, simple conversions via the + * Runs the given cypher statement and packages the result in a Result, simple conversions via the * registered converter-factories are already executed via this method. */ Result> query(String statement, Map params); /** - * Executes the given Gremlin statement and returns the result packaged as QueryResult as Neo4j types, not + * Executes the given Gremlin statement and returns the result packaged as Result as Neo4j types, not * Gremlin types. The Neo4j-Graph is provided as variable "g". Table rows are converted to Map. */ Result execute(String statement, Map params); /** * Traverses the graph starting at the given node with the provided traversal description. The Path's of the - * traversal will be packaged into a QueryResult which can be easily converted into Nodes, Relationships or + * traversal will be packaged into a Result which can be easily converted into Nodes, Relationships or * Graph-Entities. */ Result traverse(Node startNode, TraversalDescription traversal); /** * Traverses the graph starting at the given node entity with the provided traversal description. The Path's of the - * traversal will be packaged into a QueryResult which can be easily converted into Nodes, Relationships or + * traversal will be packaged into a Result which can be easily converted into Nodes, Relationships or * Graph-Entities. */ Result traverse(Object start, TraversalDescription traversal); /** - * Converts the Iterable into a QueryResult object for uniform handling. E.g. + * Converts the Iterable into a Result object for uniform handling. E.g. * template.convert(node.getRelationships()); */ Result convert(Iterable iterable); @@ -208,6 +198,11 @@ public interface Neo4jOperations { */ T convert(Object value, Class type); + /** + * Retrieves a node or relationship and returns it mapped to the appropriate type + * @return mapped entity or null + */ + T findOne(long id, Class type); /** * Provides all instances of a given entity type using the typerepresentation strategy configured for this template. * This method is also provided by the appropriate repository. @@ -224,7 +219,7 @@ public interface Neo4jOperations { * Projects a node or relationship entity to a different type. This can be used to use the same, schema free data * in different contexts. */ - T projectTo(Object entity, Class targetType); + T projectTo(Object entity, Class targetType); /** * Stores the given entity in the graph, if the entity is already attached to the graph, the node is updated, otherwise @@ -237,11 +232,14 @@ public interface Neo4jOperations { * Removes the given node or relationship entity or node or relationship from the graph, the entity is first removed * from all indexes and then deleted. */ - void remove(Object entity); + void delete(Object entity); /** * Returns the node or relationship that backs the given entity. */ S getPersistentState(Object entity); + TraversalDescription traversalDescription(); + + GraphDatabase getGraphDatabase(); } diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/template/PropertyMap.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/template/PropertyMap.java deleted file mode 100644 index c5e096130..000000000 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/template/PropertyMap.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Copyright 2011 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.data.neo4j.template; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -public class PropertyMap { - - private final Map properties = new HashMap(); - - public PropertyMap set(String name, Object value) { - properties.put(name, value); - return this; - } - - public static PropertyMap props() { - return new PropertyMap(); - } - - public Map toMap() { - return properties; - } - - public static Map _(String name, Object value) { - return Collections.singletonMap(name,value); - } -} diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/template/util/Converter.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/template/util/Converter.java deleted file mode 100644 index 9b7a94aaa..000000000 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/template/util/Converter.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Copyright 2011 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.data.neo4j.template.util; - -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.Map; - -public class Converter -{ - private final Map valueOfs = new HashMap(); - - public Object convert(final String typeName, final String value) - { - if (value == null) return null; - if (typeName == null) - throw new IllegalArgumentException("TypeName must not be null"); - try - { - Method valueOf = valueOfs.get(typeName); - if (valueOf == null) - { - final Class type = Class.forName(typeName.contains(".") ? typeName : "java.lang." + typeName); - valueOf = type.getMethod("valueOf", String.class); - valueOfs.put(typeName, valueOf); - } - return valueOf.invoke(null, value); - } catch (Exception e) - { - throw new RuntimeException(String.format("Error converting value %s from String to type %s", value, typeName), e); - } - } -} diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/model/Named.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/model/Named.java index 5761f64ee..91192c9c1 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/model/Named.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/model/Named.java @@ -16,6 +16,7 @@ package org.springframework.data.neo4j.model; +import org.springframework.data.neo4j.annotation.GraphId; import org.springframework.data.neo4j.annotation.NodeEntity; /** @@ -24,6 +25,8 @@ import org.springframework.data.neo4j.annotation.NodeEntity; */ @NodeEntity public class Named { + @GraphId + Long id; public String name; public String getName() { diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/template/util/NodeEvaluator.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/FriendshipRepository.java similarity index 77% rename from spring-data-neo4j/src/main/java/org/springframework/data/neo4j/template/util/NodeEvaluator.java rename to spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/FriendshipRepository.java index fd54deee3..97d93d76c 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/template/util/NodeEvaluator.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/FriendshipRepository.java @@ -14,10 +14,9 @@ * limitations under the License. */ -package org.springframework.data.neo4j.template.util; +package org.springframework.data.neo4j.repository; -import org.neo4j.graphdb.Node; +import org.springframework.data.neo4j.model.Friendship; -public interface NodeEvaluator { - boolean accept(final Node node); +public interface FriendshipRepository extends GraphRepository { } diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/GraphRepositoryTest.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/GraphRepositoryTest.java index 38a4e28d4..379eeb7ac 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/GraphRepositoryTest.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/GraphRepositoryTest.java @@ -66,6 +66,8 @@ public class GraphRepositoryTest { @Autowired GroupRepository groupRepository; + @Autowired FriendshipRepository friendshipRepository; + private TestTeam testTeam; @BeforeTransaction @@ -75,7 +77,7 @@ public class GraphRepositoryTest { @Before public void setUp() throws Exception { testTeam = new TestTeam(); - testTeam.createSDGTeam(personRepository, groupRepository); + testTeam.createSDGTeam(personRepository, groupRepository,friendshipRepository); } @Test diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/TestTeam.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/TestTeam.java index ae622925c..9f5d868db 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/TestTeam.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/TestTeam.java @@ -16,14 +16,12 @@ package org.springframework.data.neo4j.repository; +import org.neo4j.helpers.collection.MapUtil; +import org.springframework.data.neo4j.model.*; + import java.util.Arrays; import java.util.Map; -import org.neo4j.helpers.collection.MapUtil; -import org.springframework.data.neo4j.model.Group; -import org.springframework.data.neo4j.model.Person; -import org.springframework.data.neo4j.model.Personality; - /** * @author mh * @since 13.06.11 @@ -33,11 +31,12 @@ public class TestTeam { public Person emil; public Person david; public Group sdg; + public Friendship friendShip; public TestTeam() { } - public void createSDGTeam(PersonRepository repo, GroupRepository groupRepo) { + public void createSDGTeam(GraphRepository repo, GraphRepository groupRepo, GraphRepository friendshipRepository) { emil = new Person("Emil", 30); michael = new Person("Michael", 36); @@ -46,7 +45,8 @@ public class TestTeam { david = new Person("David", 25); david.setBoss(emil); - + friendShip = michael.knows(david); + friendShip.setYears(2); sdg = new Group(); sdg.setName("SDG"); sdg.addPerson(michael); @@ -54,6 +54,7 @@ public class TestTeam { sdg.addPerson(david); repo.save(Arrays.asList(emil, david, michael)); + friendshipRepository.save(friendShip); groupRepo.save(sdg); } diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/query/Group.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/query/Group.java index 122f97d84..f8c0545e3 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/query/Group.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/query/Group.java @@ -15,16 +15,19 @@ */ package org.springframework.data.neo4j.repository.query; -import java.util.Set; - import org.neo4j.graphdb.Direction; +import org.springframework.data.neo4j.annotation.GraphId; import org.springframework.data.neo4j.annotation.Indexed; import org.springframework.data.neo4j.annotation.NodeEntity; import org.springframework.data.neo4j.annotation.RelatedTo; +import java.util.Set; + @NodeEntity class Group { + @GraphId Long id; + @Indexed String name; diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/query/Person.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/query/Person.java index 5f65329e8..535260768 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/query/Person.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/query/Person.java @@ -16,6 +16,7 @@ package org.springframework.data.neo4j.repository.query; import org.neo4j.graphdb.Direction; +import org.springframework.data.neo4j.annotation.GraphId; import org.springframework.data.neo4j.annotation.Indexed; import org.springframework.data.neo4j.annotation.NodeEntity; import org.springframework.data.neo4j.annotation.RelatedTo; @@ -23,6 +24,8 @@ import org.springframework.data.neo4j.annotation.RelatedTo; @NodeEntity class Person { + @GraphId Long id; + @Indexed String name; int age; diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/support/EntityNeo4jTemplateTest.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/support/EntityNeo4jTemplateTest.java new file mode 100644 index 000000000..7e8db17e9 --- /dev/null +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/support/EntityNeo4jTemplateTest.java @@ -0,0 +1,314 @@ +/** + * Copyright 2011 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.neo4j.support; + +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.neo4j.graphdb.*; +import org.neo4j.graphdb.index.Index; +import org.neo4j.graphdb.traversal.TraversalDescription; +import org.neo4j.helpers.collection.MapUtil; +import org.neo4j.kernel.Traversal; +import org.springframework.data.neo4j.conversion.EndResult; +import org.springframework.data.neo4j.model.Friendship; +import org.springframework.data.neo4j.model.Group; +import org.springframework.data.neo4j.model.Named; +import org.springframework.data.neo4j.model.Person; +import org.springframework.data.neo4j.repository.GraphRepository; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Arrays; +import java.util.Collection; + +import static org.junit.Assert.*; +import static org.neo4j.graphdb.Direction.OUTGOING; +import static org.neo4j.helpers.collection.IteratorUtil.asCollection; + +/** + * @author mh + * @since 17.10.11 + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = {"classpath:template-config-context.xml"}) +@Transactional +public class EntityNeo4jTemplateTest extends EntityTestBase { + + public static final DynamicRelationshipType KNOWS = DynamicRelationshipType.withName("knows"); + + @Before + public void setUp() throws Exception { + createTeam(); + } + + @Test + public void testRepositoryFor() throws Exception { + final GraphRepository personRepository = neo4jTemplate.repositoryFor(Person.class); + final GraphRepository groupRepository = neo4jTemplate.repositoryFor(Group.class); + final GraphRepository friendshipRepository = neo4jTemplate.repositoryFor(Friendship.class); + testTeam.createSDGTeam(personRepository,groupRepository,friendshipRepository); + final Person found = personRepository.findOne(testTeam.michael.getId()); + assertEquals(found.getId(),testTeam.michael.getId()); + } + + @Test + public void testRelationshipRepositoryFor() throws Exception { + + final GraphRepository friendshipRepository = neo4jTemplate.repositoryFor(Friendship.class); + final Friendship found = friendshipRepository.findOne(testTeam.friendShip.getId()); + assertEquals(found.getId(),testTeam.friendShip.getId()); + } + + @Test + public void testGetIndexForType() throws Exception { + + final Index personIndex = neo4jTemplate.getIndex(Person.class); + assertEquals("Person",personIndex.getName()); + } + + @Test + public void testGetIndexForName() throws Exception { + + final Index nameIndex = neo4jTemplate.getIndex(Person.NAME_INDEX); + assertEquals(Person.NAME_INDEX, nameIndex.getName()); + } + + @Test + public void testGetIndexForNoTypeAndName() throws Exception { + + final Index nameIndex = neo4jTemplate.getIndex(null,Person.NAME_INDEX); + assertEquals(Person.NAME_INDEX,nameIndex.getName()); + } + + @Test + public void testGetIndexForTypeAndNoName() throws Exception { + + final Index nameIndex = neo4jTemplate.getIndex(Person.class,null); + assertEquals("Person",nameIndex.getName()); + } + @Test + public void testGetIndexForTypeAndName() throws Exception { + + final Index nameIndex = neo4jTemplate.getIndex(Person.class,Person.NAME_INDEX); + assertEquals(Person.NAME_INDEX, nameIndex.getName()); + } + + @Test + public void testFindOne() throws Exception { + + final Person found = neo4jTemplate.findOne(testTeam.michael.getId(), Person.class); + assertEquals(found.getId(),testTeam.michael.getId()); + } + + @Test + public void testFindAll() throws Exception { + + final Collection people = asCollection(neo4jTemplate.findAll(Person.class)); + assertEquals(3,people.size()); + } + + @Test + public void testCount() throws Exception { + + assertEquals(3,neo4jTemplate.count(Person.class)); + } + + @Test + public void testCreateRelationshipEntityFromStoredType() throws Exception { + + final Relationship friendshipRelationship = getRelationshipState(testTeam.friendShip); + Friendship found = neo4jTemplate.createEntityFromStoredType(friendshipRelationship); + assertEquals(testTeam.friendShip.getId(),found.getId()); + } + + @Test + public void testCreateNodeEntityFromStoredType() throws Exception { + + final Node michaelNode = getNodeState(testTeam.michael); + Person found = neo4jTemplate.createEntityFromStoredType(michaelNode); + assertEquals(testTeam.michael.getId(),found.getId()); + } + + @Test + public void testCreateEntityFromState() throws Exception { + + final PropertyContainer michaelNode = getNodeState(testTeam.michael); + Person found = neo4jTemplate.createEntityFromStoredType(michaelNode); + assertEquals(testTeam.michael.getId(),found.getId()); + } + + @Test + public void testProjectTo() throws Exception { + final Named named = neo4jTemplate.projectTo(testTeam.sdg, Named.class); + assertEquals(testTeam.sdg.getName(),named.getName()); + } + + @Test + public void testGetPersistentState() throws Exception { + assertEquals(testTeam.michael.getId(),(Long)((Node)neo4jTemplate.getPersistentState(testTeam.michael)).getId()); + } + + @Test + public void testSetPersistentState() throws Exception { + + } + + + @Test + @Ignore("TODO execute non tx") + public void testDelete() throws Exception { + final Long id = testTeam.michael.getId(); + neo4jTemplate.delete(testTeam.michael); + assertNull(neo4jTemplate.getGraphDatabase().getNodeById(id)); + } + + @Test + @Ignore("TODO execute non tx") + public void testRemoveNodeEntity() throws Exception { + final Long id = testTeam.michael.getId(); + neo4jTemplate.removeNodeEntity(testTeam.michael); + assertNull(neo4jTemplate.getGraphDatabase().getNodeById(id)); + } + + @Test + @Ignore("TODO execute non tx") + public void testRemoveRelationshipEntity() throws Exception { + final Long id = testTeam.friendShip.getId(); + neo4jTemplate.removeRelationshipEntity(testTeam.friendShip); + assertNull(neo4jTemplate.getGraphDatabase().getRelationshipById(id)); + + } + + + @Test + public void testCreateNodeAs() throws Exception { + + } + + @Test + public void testIsNodeEntity() throws Exception { + + } + + @Test + public void testIsRelationshipEntity() throws Exception { + + } + + @Test + public void testSave() throws Exception { + + } + + @Test + public void testIsManaged() throws Exception { + + } + + @Test + public void testQuery() throws Exception { + + } + + @Test + public void testGetRelationshipBetweenNodes() throws Exception { + + final Relationship knows = neo4jTemplate.getRelationshipBetween(getNodeState(testTeam.michael), getNodeState(testTeam.david), "knows"); + assertEquals(testTeam.friendShip.getId(),(Long)knows.getId()); + } + @Test + + public void testGetAutoPersistedRelationshipBetweenNodes() throws Exception { + + final Node emilNode = getNodeState(testTeam.emil); + final Node michaelNode = getNodeState(testTeam.michael); + final Relationship boss = neo4jTemplate.getRelationshipBetween(emilNode, michaelNode, "boss"); + assertNotNull("found relationship",boss); + assertEquals(michaelNode,boss.getEndNode()); + assertEquals(emilNode,boss.getStartNode()); + } + + @Test + public void testGetRelationshipBetween() throws Exception { + + final Friendship knows = neo4jTemplate.getRelationshipBetween(testTeam.michael, testTeam.david, Friendship.class, "knows"); + assertEquals(testTeam.friendShip.getId(),knows.getId()); + } + + @Test + public void testDeleteRelationshipBetween() throws Exception { + + neo4jTemplate.deleteRelationshipBetween(testTeam.michael,testTeam.david,"knows"); + assertNull("relationship deleted", getNodeState(testTeam.michael).getSingleRelationship(KNOWS, OUTGOING)); + } + + @Test + public void testCreateRelationshipBetweenNodes() throws Exception { + + final Friendship friendship = neo4jTemplate.createRelationshipBetween(testTeam.david, testTeam.emil, Friendship.class, "knows", false); + assertEquals(friendship.getId(),(Long)getNodeState(testTeam.david).getSingleRelationship(KNOWS, OUTGOING).getId()); + } + @Test + public void testCreateDuplicateRelationshipBetweenNodes() throws Exception { + + neo4jTemplate.createRelationshipBetween(testTeam.michael, testTeam.david, Friendship.class, "knows", true); + assertEquals(2, asCollection(getNodeState(testTeam.michael).getRelationships(KNOWS, OUTGOING)).size()); + } + + @Test + public void testCreateRelationshipBetween() throws Exception { + + final Node davidNode = getNodeState(testTeam.david); + final Relationship friendship = neo4jTemplate.createRelationshipBetween(davidNode, getNodeState(testTeam.emil), "knows", MapUtil.map("years", 10)); + assertEquals(friendship.getId(),davidNode.getSingleRelationship(KNOWS, OUTGOING).getId()); + assertEquals(10,friendship.getProperty("years")); + + } + + @Test + public void testConvertSingle() throws Exception { + + final Person p = neo4jTemplate.convert(neo4jTemplate.getPersistentState(testTeam.michael), Person.class); + assertEquals(testTeam.michael.getName(),p.getName()); + } + + @Test + public void testConvert() throws Exception { + final EndResult groups = neo4jTemplate.convert(Arrays.asList(getNodeState(testTeam.sdg))).to(Group.class); + assertEquals(testTeam.sdg.getName(),groups.iterator().next().getName()); + } + + @Test + public void testQueryEngineFor() throws Exception { + + } + + @Test + public void testTraverse() throws Exception { + + final TraversalDescription traversalDescription = neo4jTemplate.traversalDescription().relationships(DynamicRelationshipType.withName("knows"), Direction.OUTGOING).filter(Traversal.returnAllButStartNode()); + final Person knows = neo4jTemplate.traverse(testTeam.michael, traversalDescription).to(Person.class).single(); + assertEquals(testTeam.david.getName(), knows.getName()); + } + + @Test + public void testLookup() throws Exception { + + } +} diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/support/EntityTestBase.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/support/EntityTestBase.java new file mode 100644 index 000000000..9f89b9392 --- /dev/null +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/support/EntityTestBase.java @@ -0,0 +1,107 @@ +/** + * Copyright 2011 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.neo4j.support; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Before; +import org.neo4j.graphdb.GraphDatabaseService; +import org.neo4j.graphdb.Node; +import org.neo4j.graphdb.Relationship; +import org.neo4j.graphdb.Transaction; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.convert.ConversionService; +import org.springframework.data.neo4j.model.FriendshipRepository; +import org.springframework.data.neo4j.model.GroupRepository; +import org.springframework.data.neo4j.model.PersonRepository; +import org.springframework.data.neo4j.repository.TestTeam; +import org.springframework.data.neo4j.support.node.Neo4jHelper; +import org.springframework.test.context.transaction.BeforeTransaction; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +/** + * @author mh + * @since 15.10.11 + */ +public class EntityTestBase { + protected final Log log = LogFactory.getLog(getClass()); + + @Autowired protected Neo4jTemplate neo4jTemplate; + @Autowired protected ConversionService conversionService; + + @Autowired protected GraphDatabaseService graphDatabaseService; + + @Autowired protected PersonRepository personRepository; + @Autowired protected GroupRepository groupRepository; + @Autowired protected FriendshipRepository friendshipRepository; + protected TestTeam testTeam = new TestTeam(); + + public void createTeam() throws Exception { + testTeam.createSDGTeam(personRepository, groupRepository,friendshipRepository); + } + + protected Node getNodeState(Object entity) { + return neo4jTemplate.getPersistentState(entity); + } + protected Long getNodeId(Object entity) { + final Node node = neo4jTemplate.getPersistentState(entity); + return node == null ? null : node.getId(); + } + protected Long getRelationshipId(Object entity) { + final Relationship rel = neo4jTemplate.getPersistentState(entity); + return rel == null ? null : rel.getId(); + } + + protected boolean hasPersistentState(Object entity) { + return neo4jTemplate.getPersistentState(entity)!=null; + } + + protected Relationship getRelationshipState(Object entity) { + return neo4jTemplate.getPersistentState(entity); + } + + @SuppressWarnings("unchecked") + public T persist(T entity) { + return (T) neo4jTemplate.save(entity); + } + + protected Set set(T... values) { + return new HashSet(Arrays.asList(values)); + } + + protected void manualCleanDb() { + Transaction tx = graphDatabaseService.beginTx(); + try { + cleanDb(); + tx.success(); + } finally { + tx.finish(); + } + } + + @Before + public void cleanDbBeforeTest() { + Neo4jHelper.cleanDb(neo4jTemplate); + } + + @BeforeTransaction + public void cleanDb() { + Neo4jHelper.cleanDb(neo4jTemplate); + } +} diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/template/GraphDatabaseContextTemplateTest.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/template/FullNeo4jTemplateTest.java similarity index 99% rename from spring-data-neo4j/src/test/java/org/springframework/data/neo4j/template/GraphDatabaseContextTemplateTest.java rename to spring-data-neo4j/src/test/java/org/springframework/data/neo4j/template/FullNeo4jTemplateTest.java index 244b2ba63..48f04e4d3 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/template/GraphDatabaseContextTemplateTest.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/template/FullNeo4jTemplateTest.java @@ -51,7 +51,7 @@ import static org.neo4j.helpers.collection.MapUtil.map; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:template-config-context.xml"}) -public class GraphDatabaseContextTemplateTest { +public class FullNeo4jTemplateTest { private static final DynamicRelationshipType KNOWS = DynamicRelationshipType.withName("knows"); private static final DynamicRelationshipType HAS = DynamicRelationshipType.withName("has"); @Autowired @@ -190,7 +190,7 @@ public class GraphDatabaseContextTemplateTest { @Test public void testGetReferenceNode() throws Exception { - assertEquals(referenceNode, neo4jTemplate.getReferenceNode(Node.class)); + assertEquals(referenceNode, neo4jTemplate.getReferenceNode()); } @Test @@ -316,7 +316,7 @@ public class GraphDatabaseContextTemplateTest { @Test public void shouldCreateRelationshipWithProperty() throws Exception { - Relationship relationship = neo4jTemplate.createRelationshipBetween(referenceNode, node1, HAS, map("name", "rel2")); + Relationship relationship = neo4jTemplate.createRelationshipBetween(referenceNode, node1, "has", map("name", "rel2")); assertNotNull(relationship); assertEquals(referenceNode, relationship.getStartNode()); assertEquals(node1, relationship.getEndNode()); diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/template/Neo4jTemplateApiTest.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/template/Neo4jTemplateApiTest.java index 177b1f805..ddae6bb3f 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/template/Neo4jTemplateApiTest.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/template/Neo4jTemplateApiTest.java @@ -202,7 +202,7 @@ public class Neo4jTemplateApiTest { @Test public void testGetReferenceNode() throws Exception { - assertEquals(referenceNode,template.getReferenceNode(Node.class)); + assertEquals(referenceNode,template.getReferenceNode()); } @Test @@ -318,7 +318,7 @@ public class Neo4jTemplateApiTest { @Test public void shouldCreateRelationshipWithProperty() throws Exception { - Relationship relationship = template.createRelationshipBetween(referenceNode, node1, HAS, map("name", "rel2")); + Relationship relationship = template.createRelationshipBetween(referenceNode, node1, "has", map("name", "rel2")); assertNotNull(relationship); assertEquals(referenceNode, relationship.getStartNode()); assertEquals(node1,relationship.getEndNode()); diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/template/NeoTraversalTest.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/template/NeoTraversalTest.java index 141243647..777bc2d3f 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/template/NeoTraversalTest.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/template/NeoTraversalTest.java @@ -52,13 +52,14 @@ public class NeoTraversalTest extends NeoApiTest { final Set resultSet = new HashSet(); @SuppressWarnings("deprecation") final TraversalDescription description = Traversal.description().relationships(HAS).filter(returnAllButStartNode()).prune(Traversal.pruneAfterDepth(2)); - final Result queryResult = template.traverse(template.getReferenceNode(Node.class), description); - queryResult.handle(new Handler() { + final Result result = template.traverse(template.getReferenceNode(), description); + result.handle(new Handler() { @Override public void handle(Path value) { final String name = (String) value.endNode().getProperty("name", ""); resultSet.add(name); - }}); + } + }); assertEquals("all members", new HashSet(asList("grandpa", "grandma", "daughter", "son", "man", "wife", "family")), resultSet); } diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/test/snippets/SnippetNeo4jTemplateMethodsTest.java b/spring-data-neo4j/src/test/java/org/springframework/data/test/snippets/SnippetNeo4jTemplateMethodsTest.java index 88a6b9499..62ea879e0 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/test/snippets/SnippetNeo4jTemplateMethodsTest.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/test/snippets/SnippetNeo4jTemplateMethodsTest.java @@ -61,7 +61,7 @@ public class SnippetNeo4jTemplateMethodsTest extends DocumentingTestBase { Node mark = neo.createNode(map("name", "Mark")); Node thomas = neo.createNode(map("name", "Thomas")); - neo.createRelationshipBetween(mark, thomas, WORKS_WITH, map("project", "spring-data")); + neo.createRelationshipBetween(mark, thomas, "WORKS_WITH", map("project", "spring-data")); neo.index("devs", thomas, "name", "Thomas"); // Cypher TODO diff --git a/src/docbkx/reference/template.xml b/src/docbkx/reference/template.xml index 6c2533c83..8831c9808 100644 --- a/src/docbkx/reference/template.xml +++ b/src/docbkx/reference/template.xml @@ -9,15 +9,15 @@
- QueryResult + Result - All querying methods of the template return a uniform result type: QueryResult<T> + All querying methods of the template return a uniform result type: Result<T> which is also an Iterable<T>. The query result offers methods of converting each - element to a target type queryResult.to(Type.class) optionally supplying a + element to a target type result.to(Type.class) optionally supplying a ResultConverter<FROM,TO> which takes care of custom conversions. By default most query methods can already handle conversions from and to: Paths, Nodes, Relationship and GraphEntities - as well as conversions backed by registered ConversionServices. A converted QueryResult<FROM> is an - Iterable<TO>. QueryResults can be limited to a single value using the queryResult.single() + as well as conversions backed by registered ConversionServices. A converted Result<FROM> is an + Iterable<TO>. Results can be limited to a single value using the result.single() method. It also offers support for a pure callback function using a Handler<T>.
@@ -29,7 +29,7 @@ The lookup() methods either take a field/value combination to look for exact matches in the index, or a Lucene query object or string to handle more complex queries. All lookup() - methods return a QueryResult<PropertyContainer> to be used or transformed. + methods return a Result<PropertyContainer> to be used or transformed.
@@ -38,7 +38,7 @@ The traversal methods are at the core of graph operations. The traverse() method covers the full traversal operation that takes a TraversalDescription (typically built with the Traversal.description() - DSL) and runs it from the given start node. traverse returns a QueryResult<Path> + DSL) and runs it from the given start node. traverse returns a Result<Path> to be used or transformed.
@@ -47,7 +47,7 @@ The Neo4jTemplate also allows execution of arbitrary Cypher queries. Via the query methods the statement and parameter-Map are provided. Cypher Queries return tabular results, so the - QueryResult<Map<String,Object>> contains the rows which can be either used as they are + Result<Map<String,Object>> contains the rows which can be either used as they are or converted as needed. @@ -56,7 +56,7 @@ Gremlin Scripts can run with the execute method, which also takes the parameters that will be available as variables inside the script. The result of the executions is a generic - QueryResult<Object> fit for conversion or usage. + Result<Object> fit for conversion or usage.