diff --git a/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/RestGraphDatabase.java b/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/RestGraphDatabase.java index 69345e013..eaca8e9f2 100644 --- a/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/RestGraphDatabase.java +++ b/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/RestGraphDatabase.java @@ -2,16 +2,24 @@ package org.neo4j.rest.graphdb; import com.sun.jersey.api.client.ClientResponse; import org.neo4j.graphdb.*; +import org.neo4j.graphdb.event.KernelEventHandler; +import org.neo4j.graphdb.event.TransactionEventHandler; import org.neo4j.graphdb.index.Index; import org.neo4j.graphdb.traversal.TraversalDescription; +import org.neo4j.kernel.AbstractGraphDatabase; +import org.neo4j.kernel.Config; +import org.neo4j.kernel.RestConfig; import org.neo4j.rest.graphdb.index.RestIndexManager; import org.springframework.data.graph.core.GraphDatabase; +import org.springframework.data.graph.core.Property; import javax.ws.rs.core.Response.Status; +import java.io.Serializable; import java.net.URI; import java.util.Map; -public class RestGraphDatabase implements GraphDatabase { +public class RestGraphDatabase extends AbstractGraphDatabase implements GraphDatabase { + private RestRequest restRequest; private long propertyRefetchTimeInMillis = 1000; @@ -25,7 +33,7 @@ public class RestGraphDatabase implements GraphDatabase { } @Override - public Node getNode(long id) { + public Node getNodeById(long id) { ClientResponse response = restRequest.get("node/" + id); if ( restRequest.statusIs(response, Status.NOT_FOUND) ) { throw new NotFoundException( "" + id ); @@ -34,17 +42,17 @@ public class RestGraphDatabase implements GraphDatabase { } @Override - public Node createNode(Map props, String... indexFields) { + public Node createNode(Property... props) { ClientResponse response = restRequest.post("node", null); - if ( restRequest.statusOtherThan( response, Status.CREATED ) ) { + if ( restRequest.statusOtherThan(response, Status.CREATED) ) { throw new RuntimeException( "" + response.getStatus() ); } return new RestNode( response.getLocation(), this ); } @Override - public Relationship getRelationship(long id) { - ClientResponse response = restRequest.get( "relationship/" + id ); + public Relationship getRelationshipById(long id) { + ClientResponse response = restRequest.get("relationship/" + id); if ( restRequest.statusIs( response, Status.NOT_FOUND ) ) { throw new NotFoundException( "" + id ); } @@ -52,7 +60,7 @@ public class RestGraphDatabase implements GraphDatabase { } @Override - public Relationship createRelationship(Node startNode, Node endNode, RelationshipType type, Map props, String... indexFields) { + public Relationship createRelationship(Node startNode, Node endNode, RelationshipType type, Property... props) { Relationship relationship = startNode.createRelationshipTo(endNode, type); return relationship; } @@ -72,7 +80,7 @@ public class RestGraphDatabase implements GraphDatabase { return new RestTraversal(); } - private RestIndexManager index() { + public RestIndexManager index() { return new RestIndexManager( restRequest, this ); } @@ -89,4 +97,91 @@ public class RestGraphDatabase implements GraphDatabase { public long getPropertyRefetchTimeInMillis() { return propertyRefetchTimeInMillis; } + + @Override + public Node createNode() { + return createNode((Property[])null); + } + + @Override + public Iterable getAllNodes() { + throw new UnsupportedOperationException(); + } + + @Override + public Iterable getRelationshipTypes() { + throw new UnsupportedOperationException(); + } + + @Override + public void shutdown() { + + } + + @Override + public boolean enableRemoteShell() { + return false; + } + + @Override + public boolean enableRemoteShell(Map initialProperties) { + return false; + } + + @Override + public Transaction beginTx() { + return new Transaction() { + @Override + public void failure() { + } + + @Override + public void success() { + } + + @Override + public void finish() { + } + }; + } + + @Override + public TransactionEventHandler registerTransactionEventHandler(TransactionEventHandler handler) { + return handler; + } + + @Override + public TransactionEventHandler unregisterTransactionEventHandler(TransactionEventHandler handler) { + return handler; + } + + @Override + public KernelEventHandler registerKernelEventHandler(KernelEventHandler handler) { + return handler; + } + + @Override + public KernelEventHandler unregisterKernelEventHandler(KernelEventHandler handler) { + return handler; + } + + @Override + public String getStoreDir() { + return getRestRequest().getUri().toString(); + } + + @Override + public Config getConfig() { + return new RestConfig(this); + } + + @Override + public T getManagementBean(Class type) { + return null; + } + + @Override + public boolean isReadOnly() { + return false; + } } diff --git a/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/RestTraversal.java b/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/RestTraversal.java index ba2a734d1..d7598115a 100644 --- a/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/RestTraversal.java +++ b/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/RestTraversal.java @@ -207,7 +207,7 @@ public class RestTraversal implements RestTraversalDescription { throw new RuntimeException( String.format( "Unexpected traversal result, %s instead of collection", col != null ? col.getClass() : null ) ); } - return new RestTraverser( (Collection)col, restNode.getGraphDatabase() ); + return new RestTraverser( (Collection)col, restNode.getRestGraphDatabase() ); } public static RestTraversalDescription description() diff --git a/spring-data-neo4j-rest/src/test/java/org/neo4j/rest/graphdb/RestTestBase.java b/spring-data-neo4j-rest/src/test/java/org/neo4j/rest/graphdb/RestTestBase.java index b1e04a5bc..d737eb92f 100644 --- a/spring-data-neo4j-rest/src/test/java/org/neo4j/rest/graphdb/RestTestBase.java +++ b/spring-data-neo4j-rest/src/test/java/org/neo4j/rest/graphdb/RestTestBase.java @@ -1,23 +1,13 @@ package org.neo4j.rest.graphdb; -import com.sun.jersey.api.client.Client; -import com.sun.jersey.api.client.ClientResponse; import org.apache.log4j.BasicConfigurator; -import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.neo4j.graphdb.Direction; -import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.graphdb.Node; import org.neo4j.graphdb.Relationship; -import org.neo4j.server.AddressResolver; -import org.neo4j.server.NeoServerWithEmbeddedWebServer; -import org.neo4j.server.modules.RESTApiModule; -import org.neo4j.server.modules.ThirdPartyJAXRSModule; -import org.neo4j.server.startup.healthcheck.StartupHealthCheck; -import org.neo4j.server.web.Jetty6WebServer; import java.net.URI; import java.net.URISyntaxException; diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/core/GraphDatabase.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/core/GraphDatabase.java index 81e71a67e..d73b2ec94 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/core/GraphDatabase.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/core/GraphDatabase.java @@ -7,8 +7,6 @@ import org.neo4j.graphdb.RelationshipType; import org.neo4j.graphdb.index.Index; import org.neo4j.graphdb.traversal.TraversalDescription; -import java.util.Map; - /** * @author mh * @since 29.03.11 @@ -24,39 +22,40 @@ public interface GraphDatabase { * @return the requested node of the underlying graph database * @throws org.neo4j.graphdb.NotFoundException */ - Node getNode(long id); + Node getNodeById(long id); /** - * Transactionally creates the node, sets the properties (if any) and indexes the given fields (if any). + * Transactionally creates the node, sets the properties (if any). * Two shortcut means of providing the properties (very short with static imports) * graphDatabase.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 - * @param indexFields fields that are automatically indexed from the given properties for the newly created ndoe * @return the newly created node */ - Node createNode(Map props, String... indexFields); + Node createNode(Property... props); /** * @param id relationship id * @return the requested relationship of the underlying graph database * @throws org.neo4j.graphdb.NotFoundException */ - Relationship getRelationship(long id); + 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 - * @param indexFields optional indexed fields * @return the newly created relationship */ - Relationship createRelationship(Node startNode, Node endNode, RelationshipType type, Map props, String... indexFields); + Relationship createRelationship(Node startNode, Node endNode, RelationshipType type, Property... props); /** * @param indexName existing index name, not null @@ -79,4 +78,5 @@ public interface GraphDatabase { * @return a TraversalDescription as starting point for defining a traversal */ TraversalDescription createTraversalDescription(); + } diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/core/GraphDatabaseFactory.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/core/GraphDatabaseFactory.java index 166656aee..f2d3a6740 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/core/GraphDatabaseFactory.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/core/GraphDatabaseFactory.java @@ -1,8 +1,9 @@ package org.springframework.data.graph.core; import org.neo4j.graphdb.GraphDatabaseService; +import org.neo4j.kernel.EmbeddedGraphDatabase; import org.springframework.beans.factory.FactoryBean; -import org.springframework.data.graph.neo4j.support.LocalGraphDatabase; +import org.springframework.data.graph.neo4j.support.DelegatingGraphDatabase; import javax.annotation.PreDestroy; import java.io.File; @@ -54,7 +55,7 @@ public class GraphDatabaseFactory implements FactoryBean { } File file = new File( path ); // if (!file.isDirectory()) file=file.getParentFile(); - return new LocalGraphDatabase(file); + return new DelegatingGraphDatabase(new EmbeddedGraphDatabase(file.getAbsolutePath())); } private GraphDatabase createRestGraphDatabase(String url, String username, String password) throws Exception { @@ -71,8 +72,8 @@ public class GraphDatabaseFactory implements FactoryBean { @PreDestroy public void shutdown() { - if (graphDatabase instanceof LocalGraphDatabase) { - ((LocalGraphDatabase)graphDatabase).shutdown(); + if (graphDatabase instanceof DelegatingGraphDatabase) { + ((DelegatingGraphDatabase)graphDatabase).shutdown(); } } diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/DelegatingGraphDatabase.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/DelegatingGraphDatabase.java index e2d9a4e4d..9ac73e436 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/DelegatingGraphDatabase.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/DelegatingGraphDatabase.java @@ -41,12 +41,17 @@ public class DelegatingGraphDatabase implements GraphDatabase { return setProperties(delegate.createNode(), props); } - private T setProperties(T element, Property[] props) { - if (props==null || props.length==0) return element; - for (Property prop : props) { - element.setProperty(prop.name, prop.value); + private T setProperties(T primitive, Property... properties) { + assert primitive != null; + if (properties==null || properties.length==0) return primitive; + for (Property prop : properties) { + if (prop.value==null) { + primitive.removeProperty(prop.name); + } else { + primitive.setProperty(prop.name, prop.value); + } } - return element; + return primitive; } @Override diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/template/Neo4jOperations.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/template/Neo4jOperations.java index 6636c9b7a..38b26ac58 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/template/Neo4jOperations.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/template/Neo4jOperations.java @@ -2,6 +2,7 @@ package org.springframework.data.graph.neo4j.template; import org.neo4j.graphdb.*; import org.neo4j.graphdb.traversal.TraversalDescription; +import org.springframework.data.graph.core.Property; import java.util.Map; @@ -40,11 +41,12 @@ public interface Neo4jOperations { * Two shortcut means of providing the properties (very short with static imports) * template.createNode(PropertyMap._("name","value")); * template.createNode(PropertyMap.props().set("name","value").set("prop","anotherValue").toMap(), "name", "prop"); + * + * * @param props properties to be set at node creation might be null - * @param indexFields fields that are automatically indexed from the given properties for the newly created ndoe * @return the newly created node */ - Node createNode(Map props, String... indexFields); + Node createNode(Property... props); /** * Delegates to the GraphDatabaseService @@ -59,14 +61,15 @@ public interface Neo4jOperations { * Two shortcut means of providing the properties (very short with static imports) * template.createRelationship(from,to,TYPE, PropertyMap._("name","value")); * template.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 - * @param indexFields optional indexed fields * @return the newly created relationship */ - Relationship createRelationship(Node startNode, Node endNode, RelationshipType type, Map props, String... indexFields); + Relationship createRelationship(Node startNode, Node endNode, RelationshipType type, Property... props); /** * Queries the supplied index with a lucene query string or query object (if the neo4j-index provider is lucene) @@ -144,14 +147,4 @@ public interface Neo4jOperations { * @return the provided element for convenience */ T index(String indexName, T element, String field, Object value); - /** - * Auto-indexes all indexFields for the given element's properties if they exist - * @param indexName Name of the index, will be checked against existing indexes according to the given element - * assumes a "node" node index or "relationship" relationship index for a null value - * @param element node or relationship to auto-index - * @param indexProperties property names to index - * @param the provided element type - * @return the provided element for convenience - */ - T autoIndex(String indexName, T element, String... indexProperties); } diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/template/Neo4jTemplate.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/template/Neo4jTemplate.java index f6e90caa7..0281d5e98 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/template/Neo4jTemplate.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/template/Neo4jTemplate.java @@ -25,8 +25,7 @@ import org.neo4j.helpers.collection.IterableWrapper; import org.springframework.dao.DataAccessException; import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.graph.UncategorizedGraphStoreException; - -import java.util.Map; +import org.springframework.data.graph.core.Property; public class Neo4jTemplate implements Neo4jOperations { @@ -117,13 +116,13 @@ public class Neo4jTemplate implements Neo4jOperations { } @Override - public Node createNode(final Map properties, final String... indexFields) { + public Node createNode(final Property... properties) { return exec(new GraphCallback() { @Override public Node doWithGraph(GraphDatabaseService graph) throws Exception { Node node = graphDatabaseService.createNode(); if (properties == null) return node; - return autoIndex(null, setProperties(node, properties), indexFields); + return setProperties(node, properties); } }); } @@ -148,15 +147,6 @@ public class Neo4jTemplate implements Neo4jOperations { } } - @Override - public T autoIndex(String indexName, T element, String... indexFields) { - for (String indexField : indexFields) { - if (!element.hasProperty(indexField)) continue; - index(indexName,element, indexField,element.getProperty(indexField)); - } - return element; - } - @Override public T index(final String indexName, final T element, final String field, final Object value) { notNull(element, "element", field, "field", value, "value"); @@ -290,26 +280,26 @@ public class Neo4jTemplate implements Neo4jOperations { } @Override - public Relationship createRelationship(final Node startNode, final Node endNode, final RelationshipType relationshipType, final Map properties, final String... indexFields) { + public Relationship createRelationship(final Node startNode, final Node endNode, final RelationshipType relationshipType, final Property... properties) { notNull(startNode, "startNode", endNode, "endNode", relationshipType, "relationshipType", properties, "properties"); return exec(new GraphCallback() { @Override public Relationship doWithGraph(GraphDatabaseService graph) throws Exception { Relationship relationship = startNode.createRelationshipTo(endNode, relationshipType); if (properties == null) return relationship; - return autoIndex("relationship", setProperties(relationship, properties), indexFields); + return setProperties(relationship, properties); } }); } - private T setProperties(T primitive, Map properties) { + private T setProperties(T primitive, Property... properties) { assert primitive != null; if (properties==null) return primitive; - for (Map.Entry prop : properties.entrySet()) { - if (prop.getValue()==null) { - primitive.removeProperty(prop.getKey()); + for (Property prop : properties) { + if (prop.value==null) { + primitive.removeProperty(prop.name); } else { - primitive.setProperty(prop.getKey(), prop.getValue()); + primitive.setProperty(prop.name, prop.value); } } return primitive; diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/graph/core/GraphDatabaseFactoryTest.java b/spring-data-neo4j/src/test/java/org/springframework/data/graph/core/GraphDatabaseFactoryTest.java index 98278f4a8..7c7a4065b 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/graph/core/GraphDatabaseFactoryTest.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/graph/core/GraphDatabaseFactoryTest.java @@ -2,7 +2,7 @@ package org.springframework.data.graph.core; import org.junit.Test; import org.springframework.context.support.ClassPathXmlApplicationContext; -import org.springframework.data.graph.neo4j.support.LocalGraphDatabase; +import org.springframework.data.graph.neo4j.support.DelegatingGraphDatabase; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsInstanceOf.instanceOf; @@ -22,7 +22,7 @@ public class GraphDatabaseFactoryTest { try { GraphDatabase graphDatabase = ctx.getBean("graphDatabase", GraphDatabase.class); assertThat(graphDatabase, is(not(nullValue()))); - assertThat(graphDatabase, is(instanceOf(LocalGraphDatabase.class))); + assertThat(graphDatabase, is(instanceOf(DelegatingGraphDatabase.class))); } finally { ctx.close(); } @@ -35,7 +35,7 @@ public class GraphDatabaseFactoryTest { factory.setStoreLocation("target/test-db"); GraphDatabase graphDatabase = factory.getObject(); assertThat(graphDatabase, is(not(nullValue()))); - assertThat(graphDatabase,is(instanceOf(LocalGraphDatabase.class))); + assertThat(graphDatabase,is(instanceOf(DelegatingGraphDatabase.class))); } finally { factory.shutdown(); } diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/template/Neo4jTemplateApiTest.java b/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/template/Neo4jTemplateApiTest.java index 0374db728..de6c7f1b0 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/template/Neo4jTemplateApiTest.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/template/Neo4jTemplateApiTest.java @@ -19,8 +19,7 @@ import java.util.Iterator; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.not; import static org.junit.Assert.*; -import static org.springframework.data.graph.neo4j.template.PropertyMap._; -import static org.springframework.data.graph.neo4j.template.PropertyMap.props; +import static org.springframework.data.graph.core.Property._; /** * @author mh @@ -189,7 +188,7 @@ public class Neo4jTemplateApiTest { @Test public void testCreateNodeWithProperties() throws Exception { - Node node=template.createNode(props().set("test", "testCreateNodeWithProperties").toMap()); + Node node=template.createNode(_("test", "testCreateNodeWithProperties")); assertTestPropertySet(node, "testCreateNodeWithProperties"); } diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/template/NeoTraversalTest.java b/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/template/NeoTraversalTest.java index 80d4cfb9a..3fc670fb4 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/template/NeoTraversalTest.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/template/NeoTraversalTest.java @@ -13,8 +13,8 @@ import java.util.Set; import static java.util.Arrays.asList; import static org.junit.Assert.assertEquals; import static org.neo4j.kernel.Traversal.returnAllButStartNode; +import static org.springframework.data.graph.core.Property._; import static org.springframework.data.graph.neo4j.template.NeoTraversalTest.Type.HAS; -import static org.springframework.data.graph.neo4j.template.PropertyMap._; public class NeoTraversalTest extends NeoApiTest {