Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

merge pull request

  • Loading branch information...
commit faabdc1effe7bd7fef5a70632dc08a0b9819bd50 2 parents b4fedf7 + 7f5ba7c
@jexp authored
Showing with 2,152 additions and 446 deletions.
  1. +36 −3 pom.xml
  2. +68 −0 src/main/java/org/neo4j/rest/graphdb/AbstractRemoteDatabase.java
  3. +5 −0 src/main/java/org/neo4j/rest/graphdb/BatchCallback.java
  4. +31 −0 src/main/java/org/neo4j/rest/graphdb/BatchIterable.java
  5. +80 −0 src/main/java/org/neo4j/rest/graphdb/BatchRestAPI.java
  6. +147 −0 src/main/java/org/neo4j/rest/graphdb/ExecutingRestRequest.java
  7. +39 −39 src/main/java/org/neo4j/rest/graphdb/GraphDatabaseFactory.java
  8. +57 −57 src/main/java/org/neo4j/rest/graphdb/JsonHelper.java
  9. +55 −0 src/main/java/org/neo4j/rest/graphdb/NodePath.java
  10. +10 −0 src/main/java/org/neo4j/rest/graphdb/QueryEngine.java
  11. +112 −0 src/main/java/org/neo4j/rest/graphdb/RecordingRestRequest.java
  12. +54 −0 src/main/java/org/neo4j/rest/graphdb/RelationshipPath.java
  13. +47 −0 src/main/java/org/neo4j/rest/graphdb/RequestResult.java
  14. +127 −24 src/main/java/org/neo4j/rest/graphdb/RestAPI.java
  15. +40 −0 src/main/java/org/neo4j/rest/graphdb/RestCollectionConverter.java
  16. +66 −0 src/main/java/org/neo4j/rest/graphdb/RestCypherQueryEngine.java
  17. +37 −20 src/main/java/org/neo4j/rest/graphdb/RestEntity.java
  18. +43 −0 src/main/java/org/neo4j/rest/graphdb/RestEntityExtractor.java
  19. +9 −68 src/main/java/org/neo4j/rest/graphdb/RestGraphDatabase.java
  20. +117 −0 src/main/java/org/neo4j/rest/graphdb/RestGremlinQueryEngine.java
  21. +7 −18 src/main/java/org/neo4j/rest/graphdb/RestNode.java
  22. +111 −0 src/main/java/org/neo4j/rest/graphdb/RestOperations.java
  23. +5 −20 src/main/java/org/neo4j/rest/graphdb/RestRelationship.java
  24. +9 −142 src/main/java/org/neo4j/rest/graphdb/RestRequest.java
  25. +7 −0 src/main/java/org/neo4j/rest/graphdb/RestResultConverter.java
  26. +34 −0 src/main/java/org/neo4j/rest/graphdb/RestResultConverters.java
  27. +35 −0 src/main/java/org/neo4j/rest/graphdb/RestResultException.java
  28. +39 −0 src/main/java/org/neo4j/rest/graphdb/RestTableResultExtractor.java
  29. +4 −5 src/main/java/org/neo4j/rest/graphdb/RestTraversal.java
  30. +9 −0 src/main/java/org/neo4j/rest/graphdb/UpdatableRestResult.java
  31. +5 −5 src/main/java/org/neo4j/rest/graphdb/index/RestIndex.java
  32. +3 −3 src/main/java/org/neo4j/rest/graphdb/index/RestIndexManager.java
  33. +7 −0 src/main/java/org/neo4j/rest/graphdb/util/ConvertedResult.java
  34. +74 −0 src/main/java/org/neo4j/rest/graphdb/util/DefaultConverter.java
  35. +5 −0 src/main/java/org/neo4j/rest/graphdb/util/Handler.java
  36. +8 −0 src/main/java/org/neo4j/rest/graphdb/util/QueryResult.java
  37. +107 −0 src/main/java/org/neo4j/rest/graphdb/util/QueryResultBuilder.java
  38. +13 −0 src/main/java/org/neo4j/rest/graphdb/util/ResultConverter.java
  39. +84 −0 src/test/java/org/neo4j/rest/graphdb/BatchRestAPITest.java
  40. +50 −31 src/test/java/org/neo4j/rest/graphdb/MatrixDataGraph.java
  41. +1 −10 src/test/java/org/neo4j/rest/graphdb/MatrixDatabaseRestTest.java
  42. +79 −0 src/test/java/org/neo4j/rest/graphdb/RecordingRestRequestTest.java
  43. +118 −0 src/test/java/org/neo4j/rest/graphdb/RestCypherQueryEngineTest.java
  44. +157 −0 src/test/java/org/neo4j/rest/graphdb/RestGremlinQueryEngineTest.java
  45. +1 −1  src/test/java/org/neo4j/rest/graphdb/RestTestBase.java
View
39 pom.xml
@@ -9,8 +9,10 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<slf4j.version>1.6.1</slf4j.version>
- <neo4j.version>1.4</neo4j.version>
+ <neo4j.version>1.4.1</neo4j.version>
<jersey.version>1.4</jersey.version>
+ <blueprints.version>0.8</blueprints.version>
+ <gremlin.version>1.1</gremlin.version>
</properties>
<repositories>
@@ -100,8 +102,39 @@
<version>6.1.25</version>
<scope>test</scope>
</dependency>
-
- <dependency>
+ <dependency>
+ <groupId>org.neo4j.server.plugin</groupId>
+ <artifactId>neo4j-cypher-plugin</artifactId>
+ <version>${neo4j.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.neo4j.server.plugin</groupId>
+ <artifactId>neo4j-gremlin-plugin</artifactId>
+ <version>${neo4j.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.tinkerpop.blueprints</groupId>
+ <artifactId>blueprints-core</artifactId>
+ <version>${blueprints.version}</version>
+ <optional>true</optional>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.tinkerpop.blueprints</groupId>
+ <artifactId>blueprints-neo4j-graph</artifactId>
+ <version>${blueprints.version}</version>
+ <optional>true</optional>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.tinkerpop</groupId>
+ <artifactId>gremlin</artifactId>
+ <version>${gremlin.version}</version>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-lucene-index</artifactId>
<version>${neo4j.version}</version>
View
68 src/main/java/org/neo4j/rest/graphdb/AbstractRemoteDatabase.java
@@ -0,0 +1,68 @@
+package org.neo4j.rest.graphdb;
+
+import java.io.Serializable;
+import java.util.Map;
+
+import org.neo4j.graphdb.Node;
+import org.neo4j.graphdb.RelationshipType;
+import org.neo4j.graphdb.Transaction;
+import org.neo4j.graphdb.event.KernelEventHandler;
+import org.neo4j.graphdb.event.TransactionEventHandler;
+import org.neo4j.kernel.AbstractGraphDatabase;
+
+abstract class AbstractRemoteDatabase extends AbstractGraphDatabase {
+ public Transaction beginTx() {
+ return new Transaction() {
+ public void success() {
+ }
+
+ public void finish() {
+
+ }
+
+ public void failure() {
+ }
+ };
+ }
+
+ public <T> TransactionEventHandler<T> registerTransactionEventHandler( TransactionEventHandler<T> tTransactionEventHandler ) {
+ throw new UnsupportedOperationException();
+ }
+
+ public <T> TransactionEventHandler<T> unregisterTransactionEventHandler( TransactionEventHandler<T> tTransactionEventHandler ) {
+ throw new UnsupportedOperationException();
+ }
+
+ public KernelEventHandler registerKernelEventHandler( KernelEventHandler kernelEventHandler ) {
+ throw new UnsupportedOperationException();
+ }
+
+ public KernelEventHandler unregisterKernelEventHandler( KernelEventHandler kernelEventHandler ) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean enableRemoteShell() {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean enableRemoteShell( Map<String, Serializable> config ) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Iterable<Node> getAllNodes() {
+ throw new UnsupportedOperationException();
+ }
+
+ public Iterable<RelationshipType> getRelationshipTypes() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public <T> T getManagementBean(Class<T> type) {
+ return null;
+ }
+
+ public void shutdown() {
+ }
+
+}
View
5 src/main/java/org/neo4j/rest/graphdb/BatchCallback.java
@@ -0,0 +1,5 @@
+package org.neo4j.rest.graphdb;
+
+public interface BatchCallback<T> {
+ T recordBatch(RestAPI batchRestApi);
+}
View
31 src/main/java/org/neo4j/rest/graphdb/BatchIterable.java
@@ -0,0 +1,31 @@
+package org.neo4j.rest.graphdb;
+
+import org.neo4j.helpers.collection.IterableWrapper;
+
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * @author mh
+ * @since 21.09.11
+ */
+public class BatchIterable<T> implements Iterable<T>, UpdatableRestResult {
+ private final long batchId;
+ private RestAPI restApi;
+ private Iterable<T> data;
+
+ public BatchIterable(RequestResult requestResult) {
+ batchId = requestResult.getBatchId();
+ }
+
+ @Override
+ public void updateFrom(Object newValue, RestAPI restApi) {
+ this.data = (Iterable<T>) newValue;
+ this.restApi = restApi;
+ }
+
+ @Override
+ public Iterator<T> iterator() {
+ return data.iterator();
+ }
+}
View
80 src/main/java/org/neo4j/rest/graphdb/BatchRestAPI.java
@@ -0,0 +1,80 @@
+package org.neo4j.rest.graphdb;
+
+
+import java.util.Map;
+
+import org.neo4j.graphdb.Node;
+import org.neo4j.graphdb.Relationship;
+import org.neo4j.graphdb.RelationshipType;
+import org.neo4j.helpers.collection.MapUtil;
+
+public class BatchRestAPI extends RestAPI {
+
+ public BatchRestAPI( String uri ) {
+ super(uri);
+ }
+
+ public BatchRestAPI( String uri, String user, String password ) {
+ super(uri, user, password);
+ }
+
+ public BatchRestAPI(String uri, ExecutingRestRequest executingRestRequest){
+ super(uri);
+ this.restRequest = new RecordingRestRequest(executingRestRequest, new RestOperations());
+ }
+
+ @Override
+ protected RestRequest createRestRequest( String uri, String user, String password){
+ return new RecordingRestRequest(new ExecutingRestRequest(uri, user, password),new RestOperations());
+ }
+
+
+ @Override
+ public Node createRestNode(RequestResult requestResult) {
+ final long batchId = requestResult.getBatchId();
+ Node node = new RestNode("{"+batchId+"}", this);
+ (getRecordingRequest()).getOperations().addToRestOperation(batchId, node);
+ return node;
+ }
+
+ @Override
+ public RestRelationship createRelationship(Node startNode, Node endNode, RelationshipType type, Map<String, Object> props) {
+ final RestRequest restRequest = ((RestNode)startNode).getRestRequest();
+ Map<String, Object> data = MapUtil.map("to", ((RestNode)endNode).getUri(), "type", type.name());
+ if (props!=null && props.size()>0) {
+ data.put("data",props);
+ }
+ //RequestResult requestResult = restRequest.post(restRequest.getUri()+"/relationships", data);
+ RequestResult requestResult = restRequest.post( "relationships", data);
+ return createRestRelationship(requestResult, startNode);
+ }
+
+ @Override
+ public RestRelationship createRestRelationship(RequestResult requestResult, Node startNode) {
+ final long batchId = requestResult.getBatchId();
+ RestRelationship relationship = new RestRelationship("{"+batchId+"}", this);
+ getRecordingRequest().getOperations().addToRestOperation(batchId, relationship);
+ return relationship;
+ }
+
+ private RecordingRestRequest getRecordingRequest() {
+ return (RecordingRestRequest)this.restRequest;
+ }
+
+ public RestOperations getRecordedOperations(){
+ return (getRecordingRequest()).getOperations();
+ }
+
+ public void stop() {
+ getRecordingRequest().stop();
+ }
+
+ @SuppressWarnings("unchecked")
+ public Iterable<Relationship> wrapRelationships( RequestResult requestResult ) {
+ final long batchId = requestResult.getBatchId();
+ final BatchIterable<Relationship> result = new BatchIterable<Relationship>(requestResult);
+ getRecordingRequest().getOperations().addToRestOperation(batchId, result);
+ return result;
+ }
+
+}
View
147 src/main/java/org/neo4j/rest/graphdb/ExecutingRestRequest.java
@@ -0,0 +1,147 @@
+package org.neo4j.rest.graphdb;
+
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.WebResource;
+import com.sun.jersey.api.client.WebResource.Builder;
+import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
+
+import javax.ws.rs.core.MediaType;
+
+import org.neo4j.rest.graphdb.RequestResult;
+
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URLEncoder;
+
+import java.util.concurrent.TimeUnit;
+
+public class ExecutingRestRequest implements RestRequest {
+
+ public static final int CONNECT_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(30);
+ public static final int READ_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(30);
+ private final String baseUri;
+ private final Client client;
+
+ public ExecutingRestRequest( String baseUri ) {
+ this( baseUri, null, null );
+ }
+
+ public ExecutingRestRequest( String baseUri, String username, String password ) {
+ this.baseUri = uriWithoutSlash( baseUri );
+ client = createClient();
+ addAuthFilter(username, password);
+
+ }
+
+ protected void addAuthFilter(String username, String password) {
+ if (username == null) return;
+ client.addFilter( new HTTPBasicAuthFilter( username, password ) );
+ }
+
+ protected Client createClient() {
+ Client client = Client.create();
+
+ client.setConnectTimeout(CONNECT_TIMEOUT);
+ client.setReadTimeout(READ_TIMEOUT);
+
+ return client;
+ }
+
+ private ExecutingRestRequest( String uri, Client client ) {
+ this.baseUri = uriWithoutSlash( uri );
+ this.client = client;
+ }
+
+ protected String uriWithoutSlash( String uri ) {
+ String uriString = uri;
+ return (uriString.endsWith( "/" ) ? uriString.substring( 0, uriString.length() - 1 ) : uri);
+ }
+
+ public static String encode( Object value ) {
+ if ( value == null ) return "";
+ try {
+ return URLEncoder.encode( value.toString(), "utf-8" ).replaceAll( "\\+", "%20" );
+ } catch ( UnsupportedEncodingException e ) {
+ throw new RuntimeException( e );
+ }
+ }
+
+
+ private Builder builder( String path ) {
+ WebResource resource = client.resource( uri( pathOrAbsolute( path ) ) );
+ return resource.accept( MediaType.APPLICATION_JSON_TYPE );
+ }
+
+ private String pathOrAbsolute( String path ) {
+ if ( path.startsWith( "http://" ) ) return path;
+ return baseUri + "/" + path;
+ }
+
+
+ @Override
+ public RequestResult get( String path ) {
+ return RequestResult.extractFrom(builder(path).get(ClientResponse.class));
+ }
+
+
+ @Override
+ public RequestResult get( String path, Object data ) {
+ Builder builder = builder(path);
+ if ( data != null ) {
+ builder = builder.entity( JsonHelper.createJsonFrom( data ), MediaType.APPLICATION_JSON_TYPE );
+ }
+ return RequestResult.extractFrom(builder.get(ClientResponse.class));
+ }
+
+
+ @Override
+ public RequestResult delete(String path) {
+ return RequestResult.extractFrom(builder(path).delete(ClientResponse.class));
+ }
+
+
+ @Override
+ public RequestResult post( String path, Object data ) {
+ Builder builder = builder( path );
+ if ( data != null ) {
+ builder = builder.entity( JsonHelper.createJsonFrom( data ), MediaType.APPLICATION_JSON_TYPE );
+ }
+ return RequestResult.extractFrom(builder.post(ClientResponse.class));
+ }
+
+
+ @Override
+ public RequestResult put( String path, Object data ) {
+ Builder builder = builder( path );
+ if ( data != null ) {
+ builder = builder.entity( JsonHelper.createJsonFrom( data ), MediaType.APPLICATION_JSON_TYPE );
+ }
+ final ClientResponse response = builder.put(ClientResponse.class);
+ response.close();
+ return RequestResult.extractFrom(builder.put(ClientResponse.class));
+ }
+
+
+
+ @Override
+ public RestRequest with( String uri ) {
+ return new ExecutingRestRequest( uri , client );
+ }
+
+ private URI uri( String uri ) {
+ try {
+ return new URI( uri );
+ } catch ( URISyntaxException e ) {
+ throw new RuntimeException( e );
+ }
+ }
+
+
+ @Override
+ public String getUri() {
+ return baseUri;
+ }
+}
View
78 src/main/java/org/neo4j/rest/graphdb/GraphDatabaseFactory.java
@@ -1,39 +1,39 @@
-package org.neo4j.rest.graphdb;
-
-import org.neo4j.graphdb.GraphDatabaseService;
-import org.neo4j.kernel.EmbeddedGraphDatabase;
-
-import java.io.File;
-import java.net.URI;
-import java.net.URISyntaxException;
-
-/**
- * @author mh
- * @since 25.01.11
- */
-public class GraphDatabaseFactory {
- public static GraphDatabaseService databaseFor(String url) {
- return databaseFor( url, null,null );
- }
-
- public static GraphDatabaseService databaseFor(String url, String username, String password) {
- if (url.startsWith( "http://" ) || url.startsWith( "https://" )) {
- return new RestGraphDatabase( toURI( url ), username,password );
- }
- String path=url;
- if (url.startsWith( "file:" )) {
- path = toURI( url ).getPath();
- }
- File file = new File( path );
- if (!file.isDirectory()) file=file.getParentFile();
- return new EmbeddedGraphDatabase( file.getAbsolutePath() );
- }
-
- private static URI toURI( String uri ) {
- try {
- return new URI(uri);
- } catch ( URISyntaxException e ) {
- throw new RuntimeException( "Error using URI "+uri, e);
- }
- }
-}
+package org.neo4j.rest.graphdb;
+
+import org.neo4j.graphdb.GraphDatabaseService;
+import org.neo4j.kernel.EmbeddedGraphDatabase;
+
+import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+/**
+ * @author mh
+ * @since 25.01.11
+ */
+public class GraphDatabaseFactory {
+ public static GraphDatabaseService databaseFor(String url) {
+ return databaseFor( url, null,null );
+ }
+
+ public static GraphDatabaseService databaseFor(String url, String username, String password) {
+ if (url.startsWith( "http://" ) || url.startsWith( "https://" )) {
+ return new RestGraphDatabase( url , username,password );
+ }
+ String path=url;
+ if (url.startsWith( "file:" )) {
+ path = toURI( url ).getPath();
+ }
+ File file = new File( path );
+ if (!file.isDirectory()) file=file.getParentFile();
+ return new EmbeddedGraphDatabase( file.getAbsolutePath() );
+ }
+
+ private static URI toURI( String uri ) {
+ try {
+ return new URI(uri);
+ } catch ( URISyntaxException e ) {
+ throw new RuntimeException( "Error using URI "+uri, e);
+ }
+ }
+}
View
114 src/main/java/org/neo4j/rest/graphdb/JsonHelper.java
@@ -1,58 +1,58 @@
-package org.neo4j.rest.graphdb;
-
-/**
- * @author mh
- * @since 13.12.10
- */
-
-import org.codehaus.jackson.JsonGenerator;
-import org.codehaus.jackson.map.ObjectMapper;
-
-import java.io.IOException;
-import java.io.StringWriter;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-public class JsonHelper {
-
- static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
-
- @SuppressWarnings("unchecked")
- public static Map<String, Object> jsonToMap( String json ) {
- return (Map<String, Object>) readJson( json );
- }
-
- @SuppressWarnings("unchecked")
- public static List<Map<String, Object>> jsonToListOfRelationshipRepresentations( String json ) {
- return (List<Map<String, Object>>) readJson( json );
- }
-
- private static Object readJson( String json ) {
- ObjectMapper mapper = new ObjectMapper();
- try {
- return mapper.readValue( json, Object.class );
- } catch ( IOException e ) {
- throw new RuntimeException( e );
- }
- }
-
- public static Object jsonToSingleValue( String json ) {
- Object jsonObject = readJson( json );
- return jsonObject instanceof Collection<?> ? jsonObject :
- PropertiesMap.assertSupportedPropertyValue( jsonObject );
- }
-
- public static String createJsonFrom( Object data ) {
- try {
- StringWriter writer = new StringWriter();
- JsonGenerator generator = OBJECT_MAPPER.getJsonFactory()
- .createJsonGenerator( writer ).useDefaultPrettyPrinter();
- OBJECT_MAPPER.writeValue( generator, data );
- writer.close();
- return writer.getBuffer().toString();
- } catch ( IOException e ) {
- throw new RuntimeException( e );
- }
- }
+package org.neo4j.rest.graphdb;
+
+/**
+ * @author mh
+ * @since 13.12.10
+ */
+
+import org.codehaus.jackson.JsonGenerator;
+import org.codehaus.jackson.map.ObjectMapper;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+public class JsonHelper {
+
+ static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
+
+ @SuppressWarnings("unchecked")
+ public static Map<String, Object> jsonToMap( String json ) {
+ return (Map<String, Object>) readJson( json );
+ }
+
+ @SuppressWarnings("unchecked")
+ public static List<Map<String, Object>> jsonToListOfRelationshipRepresentations( String json ) {
+ return (List<Map<String, Object>>) readJson( json );
+ }
+
+ public static Object readJson( String json ) {
+ ObjectMapper mapper = new ObjectMapper();
+ try {
+ return mapper.readValue( json, Object.class );
+ } catch ( IOException e ) {
+ throw new RuntimeException( e );
+ }
+ }
+
+ public static Object jsonToSingleValue( String json ) {
+ Object jsonObject = readJson( json );
+ return jsonObject instanceof Collection<?> ? jsonObject :
+ PropertiesMap.assertSupportedPropertyValue( jsonObject );
+ }
+
+ public static String createJsonFrom( Object data ) {
+ try {
+ StringWriter writer = new StringWriter();
+ JsonGenerator generator = OBJECT_MAPPER.getJsonFactory()
+ .createJsonGenerator( writer ).useDefaultPrettyPrinter();
+ OBJECT_MAPPER.writeValue( generator, data );
+ writer.close();
+ return writer.getBuffer().toString();
+ } catch ( IOException e ) {
+ throw new RuntimeException( e );
+ }
+ }
}
View
55 src/main/java/org/neo4j/rest/graphdb/NodePath.java
@@ -0,0 +1,55 @@
+package org.neo4j.rest.graphdb;
+
+import static java.util.Arrays.asList;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+
+import org.neo4j.graphdb.Node;
+import org.neo4j.graphdb.Path;
+import org.neo4j.graphdb.PropertyContainer;
+import org.neo4j.graphdb.Relationship;
+
+public class NodePath implements Path {
+ private final Node node;
+
+ public NodePath(Node node) {
+ this.node = node;
+ }
+
+ @Override
+ public Node startNode() {
+ return node;
+ }
+
+ @Override
+ public Node endNode() {
+ return node;
+ }
+
+ @Override
+ public Relationship lastRelationship() {
+ return null;
+ }
+
+ @Override
+ public Iterable<Relationship> relationships() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public Iterable<Node> nodes() {
+ return asList(node);
+ }
+
+ @Override
+ public int length() {
+ return 0;
+ }
+
+ @Override
+ public Iterator<PropertyContainer> iterator() {
+ return Arrays.<PropertyContainer>asList(node).iterator();
+ }
+}
View
10 src/main/java/org/neo4j/rest/graphdb/QueryEngine.java
@@ -0,0 +1,10 @@
+package org.neo4j.rest.graphdb;
+
+import java.util.Map;
+
+import org.neo4j.rest.graphdb.util.QueryResult;
+
+public interface QueryEngine<T> {
+ QueryResult<T> query(String statement, Map<String, Object> params);
+
+}
View
112 src/main/java/org/neo4j/rest/graphdb/RecordingRestRequest.java
@@ -0,0 +1,112 @@
+package org.neo4j.rest.graphdb;
+
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.util.Map;
+
+import javax.ws.rs.core.MediaType;
+
+import org.neo4j.rest.graphdb.RestOperations.RestOperation;
+import org.neo4j.rest.graphdb.RestOperations.RestOperation.Methods;
+
+
+
+public class RecordingRestRequest implements RestRequest {
+
+ protected final String baseUri;
+ private MediaType contentType;
+ private MediaType acceptHeader;
+ private RestRequest restRequest;
+ private RestOperations operations;
+ private boolean stop;
+
+
+ public RestOperations getOperations() {
+ return operations;
+ }
+
+ public RecordingRestRequest( RestRequest restRequest) {
+ this( restRequest.getUri(), MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_JSON_TYPE );
+ this.restRequest = restRequest;
+ }
+
+ public RecordingRestRequest( RestRequest restRequest, RestOperations operations ) {
+ this(restRequest);
+ this.operations = operations;
+ }
+
+
+ public RecordingRestRequest(String baseUri, MediaType contentType, MediaType acceptHeader) {
+ this.baseUri = uriWithoutSlash( baseUri );
+ this.contentType = contentType;
+ this.acceptHeader = acceptHeader;
+ }
+
+ @Override
+ public RequestResult get(String path, Object data) {
+ return this.record(Methods.GET, path, data, baseUri);
+ }
+
+ @Override
+ public RequestResult delete(String path) {
+ return this.record(Methods.DELETE, path, null, baseUri);
+ }
+
+ @Override
+ public RequestResult post(String path, Object data) {
+ return this.record(Methods.POST, path, data, baseUri);
+ }
+
+ @Override
+ public RequestResult put(String path, Object data) {
+ return this.record(Methods.PUT, path, data, baseUri);
+
+ }
+
+ @Override
+ public RestRequest with(String uri) {
+ return new RecordingRestRequest(this.restRequest.with(uri), this.operations);
+ }
+
+ @Override
+ public String getUri() {
+ return baseUri;
+ }
+
+ @Override
+ public RequestResult get(String path) {
+ return this.record(Methods.GET, path, null, baseUri);
+ }
+
+ public RequestResult record(Methods method, String path, Object data, String baseUri){
+ if (stop) throw new IllegalStateException("BatchRequest already executed");
+ return this.operations.record(method, path, data,baseUri);
+ }
+
+
+
+
+ private String uriWithoutSlash( String uri ) {
+ String uriString = uri;
+ return uriString.endsWith( "/" ) ? uriString.substring( 0, uriString.length() - 1 ) : uri;
+ }
+
+ public static String encode( Object value ) {
+ if ( value == null ) return "";
+ try {
+ return URLEncoder.encode( value.toString(), "utf-8" ).replaceAll( "\\+", "%20" );
+ } catch ( UnsupportedEncodingException e ) {
+ throw new RuntimeException( e );
+ }
+ }
+
+ public Map<Long,RestOperation> getRecordedRequests(){
+ return this.operations.getRecordedRequests();
+ }
+
+ public void stop() {
+ this.stop = true;
+ }
+}
+
View
54 src/main/java/org/neo4j/rest/graphdb/RelationshipPath.java
@@ -0,0 +1,54 @@
+package org.neo4j.rest.graphdb;
+
+import static java.util.Arrays.asList;
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+import org.neo4j.graphdb.Node;
+import org.neo4j.graphdb.Path;
+import org.neo4j.graphdb.PropertyContainer;
+import org.neo4j.graphdb.Relationship;
+
+public class RelationshipPath implements Path {
+ private final Relationship relationship;
+
+ public RelationshipPath(Relationship relationship) {
+ this.relationship = relationship;
+ }
+
+ @Override
+ public Node startNode() {
+ return relationship.getStartNode();
+ }
+
+ @Override
+ public Node endNode() {
+ return relationship.getEndNode();
+ }
+
+ @Override
+ public Relationship lastRelationship() {
+ return relationship;
+ }
+
+ @Override
+ public Iterable<Relationship> relationships() {
+ return asList(relationship);
+ }
+
+ @Override
+ public Iterable<Node> nodes() {
+ return asList(startNode(),endNode());
+ }
+
+ @Override
+ public int length() {
+ return 1;
+ }
+
+ @Override
+ public Iterator<PropertyContainer> iterator() {
+ return Arrays.<PropertyContainer>asList(startNode(), lastRelationship(), endNode()).iterator();
+ }
+}
View
47 src/main/java/org/neo4j/rest/graphdb/RequestResult.java
@@ -18,7 +18,13 @@
import com.sun.jersey.api.client.ClientResponse;
import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.StatusType;
+
+import org.neo4j.rest.graphdb.RestOperations.RestOperation;
+
import java.net.URI;
+import java.util.Map;
+
/**
* @author Klemens Burchardi
@@ -28,12 +34,25 @@
private final int status;
private final URI location;
private final String entity;
+ private long batchId;
+ private boolean batchResult = false;
+
RequestResult(int status, URI location, String entity) {
this.status = status;
this.location = location;
this.entity = entity;
}
+
+ RequestResult(long batchId) {
+ this(0,null,"");
+ this.batchResult = true;
+ this.batchId = batchId;
+ }
+
+ public static RequestResult batchResult(RestOperation restOperation){
+ return new RequestResult(restOperation.getBatchId());
+ }
public static RequestResult extractFrom(ClientResponse clientResponse) {
final int status = clientResponse.getStatus();
@@ -42,6 +61,8 @@ public static RequestResult extractFrom(ClientResponse clientResponse) {
clientResponse.close();
return new RequestResult(status, location, data);
}
+
+
public int getStatus() {
return status;
@@ -54,4 +75,30 @@ public URI getLocation() {
public String getEntity() {
return entity;
}
+
+ public Object toEntity() {
+ return JsonHelper.jsonToSingleValue( getEntity() );
+ }
+
+ public Map<?, ?> toMap() {
+ final String json = getEntity();
+ return JsonHelper.jsonToMap(json);
+ }
+
+ public boolean statusIs( StatusType status ) {
+ return getStatus() == status.getStatusCode();
+ }
+
+ public boolean statusOtherThan( StatusType status ) {
+ return !statusIs(status );
+ }
+
+ public long getBatchId() {
+ return batchId;
+ }
+
+ public boolean isBatchResult(){
+ return batchResult;
+ }
+
}
View
151 src/main/java/org/neo4j/rest/graphdb/RestAPI.java
@@ -3,33 +3,41 @@
import org.neo4j.graphdb.*;
import org.neo4j.graphdb.index.Index;
import org.neo4j.graphdb.traversal.TraversalDescription;
+import org.neo4j.helpers.collection.IterableWrapper;
+import org.neo4j.helpers.collection.MapUtil;
import org.neo4j.index.impl.lucene.LuceneIndexImplementation;
+import org.neo4j.rest.graphdb.RestOperations.RestOperation;
import org.neo4j.rest.graphdb.index.RestIndexManager;
import javax.ws.rs.core.Response.Status;
import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
import java.util.Map;
+
public class RestAPI {
- private final RestRequest restRequest;
+ protected RestRequest restRequest;
private long propertyRefetchTimeInMillis = 1000;
-
-
- public RestAPI(RestRequest restRequest){
+
+ public RestAPI(RestRequest restRequest){
this.restRequest = restRequest;
}
- public RestAPI( URI uri ) {
- this(new RestRequest( uri ));
+ public RestAPI( String uri ) {
+ this.restRequest = createRestRequest(uri, null, null);
}
- public RestAPI( URI uri, String user, String password ) {
- this(new RestRequest( uri, user, password ));
+ public RestAPI( String uri, String user, String password ) {
+ this.restRequest = createRestRequest(uri, user, password);
}
-
+ protected RestRequest createRestRequest( String uri, String user, String password){
+ return new ExecutingRestRequest(uri, user, password);
+ }
public RestIndexManager index() {
return new RestIndexManager( restRequest, this);
@@ -37,35 +45,54 @@ public RestIndexManager index() {
public Node getNodeById( long id ) {
RequestResult response = restRequest.get( "node/" + id );
- if ( restRequest.statusIs( response, Status.NOT_FOUND ) ) {
+ if ( response.statusIs(Status.NOT_FOUND ) ) {
throw new NotFoundException( "" + id );
}
- return new RestNode( restRequest.toMap( response ), this );
+ return new RestNode( response.toMap(), this );
}
public Relationship getRelationshipById(long id) {
RequestResult requestResult = restRequest.get("relationship/" + id);
- if ( restRequest.statusIs(requestResult, Status.NOT_FOUND ) ) {
+ if ( requestResult.statusIs(Status.NOT_FOUND ) ) {
throw new NotFoundException( "" + id );
}
- return new RestRelationship( restRequest.toMap(requestResult), this );
+ return new RestRelationship( requestResult.toMap(), this );
}
public Node createNode(Map<String, Object> props) {
- RequestResult requestResult = restRequest.post("node", JsonHelper.createJsonFrom( props ));
- if ( restRequest.statusOtherThan(requestResult, Status.CREATED) ) {
- final int status = requestResult.getStatus();
- throw new RuntimeException( "" + status);
- }
- final URI location = requestResult.getLocation();
- return new RestNode(location, this );
+ RequestResult requestResult = restRequest.post("node", props);
+ return createRestNode(requestResult);
+ }
+
+ public Node createRestNode(RequestResult requestResult){
+ if ( requestResult.statusOtherThan(Status.CREATED) ) {
+ final int status = requestResult.getStatus();
+ throw new RuntimeException( "" + status);
+ }
+ final URI location = requestResult.getLocation();
+ return new RestNode(location, this );
}
- public RestRelationship createRelationship(Node startNode, Node endNode, RelationshipType type, Map<String, Object> props) {
- return RestRelationship.create((RestNode)startNode,(RestNode)endNode,type,props);
+ public RestRelationship createRelationship(Node startNode, Node endNode, RelationshipType type, Map<String, Object> props) {
+ final RestRequest restRequest = ((RestNode)startNode).getRestRequest();
+ Map<String, Object> data = MapUtil.map("to", ((RestNode)endNode).getUri(), "type", type.name());
+ if (props!=null && props.size()>0) {
+ data.put("data",props);
+ }
+ RequestResult requestResult = restRequest.post( "relationships", data);
+ return createRestRelationship(requestResult, startNode);
}
+ public RestRelationship createRestRelationship(RequestResult requestResult,Node startNode){
+
+ if ( requestResult.statusOtherThan(javax.ws.rs.core.Response.Status.CREATED ) ) {
+ final int status = requestResult.getStatus();
+ throw new RuntimeException( "" + status);
+ }
+ final URI location = requestResult.getLocation();
+ return new RestRelationship(location, ((RestNode)startNode).getRestApi() );
+ }
public <T extends PropertyContainer> Index<T> getIndex(String indexName) {
final RestIndexManager index = this.index();
@@ -95,7 +122,7 @@ public TraversalDescription createTraversalDescription() {
}
public Node getReferenceNode() {
- Map<?, ?> map = restRequest.toMap( restRequest.get( "" ) );
+ Map<?, ?> map = restRequest.get( "" ).toMap();
return new RestNode( (String) map.get( "reference_node" ), this);
}
@@ -110,7 +137,83 @@ public String getStoreDir() {
public void setPropertyRefetchTimeInMillis(long propertyRefetchTimeInMillis) {
this.propertyRefetchTimeInMillis = propertyRefetchTimeInMillis;
- }
+ }
+
+
+ public <T> T executeBatch( BatchCallback<T> batchCallback){
+ BatchRestAPI batchRestApi = new BatchRestAPI(this.restRequest.getUri(), (ExecutingRestRequest)this.restRequest);
+ T batchResult = batchCallback.recordBatch(batchRestApi);
+ batchRestApi.stop();
+ RestOperations operations = batchRestApi.getRecordedOperations();
+ RequestResult response = this.restRequest.post("batch", createBatchRequestData(operations));
+ Map<Long,Object> mappedObjects = convertRequestResultToEntities(response);
+ updateRestOperations(operations, mappedObjects);
+ return batchResult;
+ }
+
+ private Collection<Map<String,Object>> createBatchRequestData(RestOperations operations){
+ Collection<Map<String,Object>> batch = new ArrayList<Map<String,Object>>();
+ final String baseUri = restRequest.getUri();
+ for (RestOperation operation : operations.getRecordedRequests().values()){
+ Map<String,Object> params = new HashMap<String, Object>();
+ params.put("method", operation.getMethod());
+ if (operation.isSameUri(baseUri)) {
+ params.put("to", operation.getUri());
+ } else {
+ params.put("to", operation.getBaseUri() + "/" + operation.getUri()); // todo kapseln und op.getUri pruefen dass es nicht mit slash anfaengt
+ }
+ if (operation.getData() != null){
+ params.put("body", operation.getData());
+ }
+ params.put("id", operation.getBatchId());
+ batch.add(params);
+ }
+ return batch;
+ }
+
+ private Map<Long,Object> convertRequestResultToEntities(RequestResult response){
+ Object result = JsonHelper.readJson(response.getEntity());
+ if (RestResultException.isExceptionResult(result)) {
+ throw new RestResultException(result);
+ }
+ RestResultConverters converters = getConverters();
+ Collection<Map<String,Object>> responseCollection = (Collection<Map<String,Object>>)result;
+ Map<Long,Object> mappedObjects = new HashMap<Long,Object>(responseCollection.size());
+ for (Map<String,Object> entry : responseCollection) {
+ final Object singleRequestResult = entry.get("body");
+ if (converters.canHandle(singleRequestResult)) {
+ Object entity = converters.convertFromRepresentation(singleRequestResult);
+ mappedObjects.put(getBatchId(entry), entity);
+ }
+ }
+ return mappedObjects;
+ }
+
+ private Long getBatchId(Map<String, Object> entry) {
+ return ((Number)entry.get("id")).longValue();
+ }
+
+ private void updateRestOperations( RestOperations operations, Map<Long,Object> mappedObjects){
+ for (RestOperation operation : operations.getRecordedRequests().values()){
+ operation.updateEntity(mappedObjects.get(operation.getBatchId()), this);
+ }
+ }
+
+ private RestResultConverters getConverters(){
+ RestEntityExtractor entityConverter = new RestEntityExtractor(this);
+ RestResultConverter iterableConverter=new RestCollectionConverter(entityConverter);
+ return new RestResultConverters(entityConverter,iterableConverter);
+ }
+ @SuppressWarnings("unchecked")
+ public Iterable<Relationship> wrapRelationships( RequestResult requestResult ) {
+ return new IterableWrapper<Relationship, Object>(
+ (Collection<Object>) requestResult.toEntity() ) {
+ @Override
+ protected Relationship underlyingObjectToObject( Object data ) {
+ return new RestRelationship( (Map<?, ?>) data, RestAPI.this );
+ }
+ };
+ }
}
View
40 src/main/java/org/neo4j/rest/graphdb/RestCollectionConverter.java
@@ -0,0 +1,40 @@
+package org.neo4j.rest.graphdb;
+
+import org.neo4j.helpers.collection.IterableWrapper;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+
+import static org.codehaus.groovy.runtime.InvokerHelper.asList;
+
+/**
+ * @author mh
+ * @since 21.09.11
+ */
+public class RestCollectionConverter implements RestResultConverter {
+
+ RestResultConverters converters;
+
+ public RestCollectionConverter(RestResultConverter...converters) {
+ this.converters = new RestResultConverters(converters);
+ }
+
+ @Override
+ public boolean canHandle(Object value) {
+ if (!(value instanceof Iterable)) return false;
+ final Iterator it = ((Iterable) value).iterator();
+ return !it.hasNext() || converters.canHandle(it.next());
+ }
+
+ @Override
+ public Object convertFromRepresentation(Object values) {
+ Iterable it= (Iterable) values;
+ return new IterableWrapper<Object,Object>(it) {
+ @Override
+ protected Object underlyingObjectToObject(Object object) {
+ return converters.convertFromRepresentation(object);
+ }
+ };
+ }
+}
View
66 src/main/java/org/neo4j/rest/graphdb/RestCypherQueryEngine.java
@@ -0,0 +1,66 @@
+package org.neo4j.rest.graphdb;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.neo4j.helpers.collection.MapUtil;
+import org.neo4j.rest.graphdb.util.ConvertedResult;
+import org.neo4j.rest.graphdb.util.DefaultConverter;
+import org.neo4j.rest.graphdb.util.Handler;
+import org.neo4j.rest.graphdb.util.QueryResult;
+import org.neo4j.rest.graphdb.util.QueryResultBuilder;
+import org.neo4j.rest.graphdb.util.ResultConverter;
+
+
+public class RestCypherQueryEngine implements QueryEngine<Map<String,Object>> {
+ private final RestRequest restRequest;
+ private final RestAPI restApi;
+ private final ResultConverter resultConverter;
+
+ public RestCypherQueryEngine(RestAPI restApi) {
+ this(restApi,null);
+ }
+ public RestCypherQueryEngine(RestAPI restApi, ResultConverter resultConverter) {
+ this.restApi = restApi;
+ this.resultConverter = resultConverter!=null ? resultConverter : new DefaultConverter();
+ this.restRequest = restApi.getRestRequest();
+ }
+
+ @Override
+ public QueryResult<Map<String, Object>> query(String statement, Map<String, Object> params) {
+ final String parametrizedStatement = QueryResultBuilder.replaceParams(statement, params);
+ final RequestResult requestResult = restRequest.get("ext/CypherPlugin/graphdb/execute_query", MapUtil.map("query", parametrizedStatement));
+ return new RestQueryResult(requestResult.toMap(),restApi,resultConverter);
+ }
+
+ static class RestQueryResult implements QueryResult<Map<String,Object>> {
+ QueryResultBuilder<Map<String,Object>> result;
+
+ @Override
+ public <R> ConvertedResult<R> to(Class<R> type) {
+ return result.to(type);
+ }
+
+ @Override
+ public <R> ConvertedResult<R> to(Class<R> type, ResultConverter<Map<String, Object>, R> converter) {
+ return result.to(type,converter);
+ }
+
+ @Override
+ public void handle(Handler<Map<String, Object>> handler) {
+ result.handle(handler);
+ }
+
+ @Override
+ public Iterator<Map<String, Object>> iterator() {
+ return result.iterator();
+ }
+
+ public RestQueryResult(Map<?, ?> result, RestAPI restApi, ResultConverter resultConverter) {
+ final RestTableResultExtractor extractor = new RestTableResultExtractor(new RestEntityExtractor(restApi));
+ final List<Map<String, Object>> data = extractor.extract(result);
+ this.result=new QueryResultBuilder<Map<String,Object>>(data, resultConverter);
+ }
+ }
+}
View
57 src/main/java/org/neo4j/rest/graphdb/RestEntity.java
@@ -1,7 +1,6 @@
package org.neo4j.rest.graphdb;
-import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.NotFoundException;
import org.neo4j.graphdb.PropertyContainer;
import org.neo4j.helpers.collection.IterableWrapper;
@@ -14,23 +13,24 @@
import java.util.Collections;
import java.util.Map;
-public class RestEntity implements PropertyContainer {
+public class RestEntity implements PropertyContainer, UpdatableRestResult {
private Map<?, ?> structuralData;
private Map<String, Object> propertyData;
private long lastTimeFetchedPropertyData;
- private RestAPI restApi;
+ protected RestAPI restApi;
+
protected RestRequest restRequest;
private final ArrayConverter arrayConverter=new ArrayConverter();
public RestEntity( URI uri, RestAPI restApi ) {
this( uri.toString(), restApi );
- }
+ }
- public RestEntity( String uri, RestAPI restApi ) {
- this.restRequest = restApi.getRestRequest().with( uri );
- this.restApi = restApi;
- }
+ public RestEntity( String uri, RestAPI restApi ) {
+ this.restRequest = restApi.getRestRequest().with( uri );
+ this.restApi = restApi;
+ }
public RestEntity( Map<?, ?> data, RestAPI restApi ) {
this.structuralData = data;
@@ -41,23 +41,31 @@ public RestEntity( Map<?, ?> data, RestAPI restApi ) {
this.restRequest = restApi.getRestRequest().with( uri );
}
- public String getUri() {
- return this.restRequest.getUri().toString();
+ public String getUri() {
+ return this.restRequest.getUri();
+ }
+
+ public void updateRestEntity(RestEntity updateEntity, RestAPI restApi){
+ this.restApi = restApi;
+ this.restRequest = restApi.getRestRequest().with(updateEntity.getUri());
+ this.structuralData = updateEntity.getStructuralData();
+ this.propertyData = updateEntity.getPropertyData();
+ this.lastTimeFetchedPropertyData = System.currentTimeMillis();
}
Map<?, ?> getStructuralData() {
if ( this.structuralData == null ) {
- this.structuralData = restRequest.toMap( restRequest.get( "" ) );
+ this.structuralData = restRequest.get( "" ) .toMap();
}
return this.structuralData;
}
Map<String, Object> getPropertyData() {
- if ( this.propertyData == null || timeElapsed( this.lastTimeFetchedPropertyData, restApi.getPropertyRefetchTimeInMillis() ) ) {
+ if (hasToUpdateProperties()) {
RequestResult response = restRequest.get( "properties" );
- boolean ok = restRequest.statusIs( response, Status.OK );
+ boolean ok = response.statusIs( Status.OK );
if ( ok ) {
- this.propertyData = (Map<String, Object>) restRequest.toMap( response );
+ this.propertyData = (Map<String, Object>) response.toMap( );
} else {
this.propertyData = Collections.emptyMap();
}
@@ -66,12 +74,16 @@ public String getUri() {
return this.propertyData;
}
- private boolean timeElapsed( long since, long isItGreaterThanThis ) {
+ private boolean hasToUpdateProperties() {
+ return this.propertyData == null || timeElapsed( this.lastTimeFetchedPropertyData, restApi.getPropertyRefetchTimeInMillis() );
+ }
+
+ private boolean timeElapsed( long since, long isItGreaterThanThis ) {
return System.currentTimeMillis() - since > isItGreaterThanThis;
}
public Object getProperty( String key ) {
- Object value = getPropertyValue( key );
+ Object value = getPropertyValue(key);
if ( value == null ) {
throw new NotFoundException( "'" + key + "' on " + this );
}
@@ -120,13 +132,13 @@ public boolean hasProperty( String key ) {
public Object removeProperty( String key ) {
Object value = getProperty( key, null );
- restRequest.delete( "properties/" + key );
+ restRequest.delete("properties/" + key);
invalidatePropertyData();
return value;
}
public void setProperty( String key, Object value ) {
- restRequest.put( "properties/" + key, JsonHelper.createJsonFrom( value ) );
+ restRequest.put( "properties/" + key, value);
invalidatePropertyData();
}
@@ -135,10 +147,10 @@ private void invalidatePropertyData() {
}
static long getEntityId( String uri ) {
- return Long.parseLong( uri.substring( uri.lastIndexOf( '/' ) + 1 ) );
+ return Long.parseLong(uri.substring(uri.lastIndexOf('/') + 1));
}
- public long getId() {
+ public long getId() {
return getEntityId( getUri() );
}
@@ -175,4 +187,9 @@ public RestAPI getRestApi() {
return restApi;
}
+
+ @Override
+ public void updateFrom(Object newValue, RestAPI restApi) {
+ updateRestEntity((RestEntity) newValue,restApi);
+ }
}
View
43 src/main/java/org/neo4j/rest/graphdb/RestEntityExtractor.java
@@ -0,0 +1,43 @@
+package org.neo4j.rest.graphdb;
+
+import java.util.Map;
+
+
+public class RestEntityExtractor implements RestResultConverter {
+ private final RestAPI restApi;
+
+ public RestEntityExtractor(RestAPI restApi) {
+ this.restApi = restApi;
+ }
+
+ public Object convertFromRepresentation(Object value) {
+ if (value instanceof Map) {
+ RestEntity restEntity = createRestEntity((Map) value);
+ if (restEntity != null) return restEntity;
+ }
+ return value;
+ }
+
+ RestEntity createRestEntity(Map data) {
+ final String uri = (String) data.get("self");
+ if (uri == null || uri.isEmpty()) return null;
+ if (uri.contains("/node/")) {
+ return new RestNode(data, restApi);
+ }
+ if (uri.contains("/relationship/")) {
+ return new RestRelationship(data, restApi);
+ }
+ return null;
+ }
+
+ @Override
+ public boolean canHandle(Object value) {
+ if (value instanceof Map) {
+ final String uri = (String) ((Map)value).get("self");
+ if (uri != null && (uri.contains("/node/") || uri.contains("/relationship/"))){
+ return true;
+ }
+ }
+ return false;
+ }
+}
View
77 src/main/java/org/neo4j/rest/graphdb/RestGraphDatabase.java
@@ -2,17 +2,13 @@
import org.neo4j.graphdb.*;
-import org.neo4j.graphdb.event.KernelEventHandler;
-import org.neo4j.graphdb.event.TransactionEventHandler;
-import org.neo4j.kernel.AbstractGraphDatabase;
import org.neo4j.kernel.Config;
import org.neo4j.kernel.RestConfig;
import org.neo4j.rest.graphdb.index.RestIndexManager;
-import java.io.Serializable;
import java.net.URI;
-import java.util.Map;
-public class RestGraphDatabase extends AbstractGraphDatabase {
+
+public class RestGraphDatabase extends AbstractRemoteDatabase {
private RestAPI restAPI;
@@ -20,55 +16,24 @@ public RestGraphDatabase( RestAPI api){
this.restAPI = api;
}
- public RestGraphDatabase( URI uri ) {
- this( new RestRequest( uri ));
+ public RestGraphDatabase( String uri ) {
+ this( new ExecutingRestRequest( uri ));
}
- public RestGraphDatabase( URI uri, String user, String password ) {
- this(new RestRequest( uri, user, password ));
+ public RestGraphDatabase( String uri, String user, String password ) {
+ this(new ExecutingRestRequest( uri, user, password ));
}
public RestGraphDatabase( RestRequest restRequest){
this(new RestAPI(restRequest));
- }
-
-
+ }
public RestAPI getRestAPI(){
return this.restAPI;
}
- public Transaction beginTx() {
- return new Transaction() {
- public void success() {
- }
-
- public void finish() {
-
- }
-
- public void failure() {
- }
- };
- }
-
- public <T> TransactionEventHandler<T> registerTransactionEventHandler( TransactionEventHandler<T> tTransactionEventHandler ) {
- throw new UnsupportedOperationException();
- }
-
- public <T> TransactionEventHandler<T> unregisterTransactionEventHandler( TransactionEventHandler<T> tTransactionEventHandler ) {
- throw new UnsupportedOperationException();
- }
-
- public KernelEventHandler registerKernelEventHandler( KernelEventHandler kernelEventHandler ) {
- throw new UnsupportedOperationException();
- }
-
- public KernelEventHandler unregisterKernelEventHandler( KernelEventHandler kernelEventHandler ) {
- throw new UnsupportedOperationException();
- }
-
+
public RestIndexManager index() {
return this.restAPI.index();
}
@@ -76,24 +41,7 @@ public RestIndexManager index() {
public Node createNode() {
return this.restAPI.createNode(null);
}
-
-
- public boolean enableRemoteShell() {
- throw new UnsupportedOperationException();
- }
-
- public boolean enableRemoteShell( Map<String, Serializable> config ) {
- throw new UnsupportedOperationException();
- }
-
- public Iterable<Node> getAllNodes() {
- throw new UnsupportedOperationException();
- }
- public Iterable<RelationshipType> getRelationshipTypes() {
- throw new UnsupportedOperationException();
- }
-
public Node getNodeById( long id ) {
return this.restAPI.getNodeById(id);
}
@@ -106,9 +54,7 @@ public Relationship getRelationshipById( long id ) {
return this.restAPI.getRelationshipById(id);
}
- public void shutdown() {
- }
-
+
public RestRequest getRestRequest() {
return this.restAPI.getRestRequest();
}
@@ -127,11 +73,6 @@ public Config getConfig() {
}
@Override
- public <T> T getManagementBean(Class<T> type) {
- return null;
- }
-
- @Override
public boolean isReadOnly() {
return false;
}
View
117 src/main/java/org/neo4j/rest/graphdb/RestGremlinQueryEngine.java
@@ -0,0 +1,117 @@
+package org.neo4j.rest.graphdb;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.neo4j.helpers.collection.IterableWrapper;
+import org.neo4j.helpers.collection.MapUtil;
+import org.neo4j.rest.graphdb.util.ConvertedResult;
+import org.neo4j.rest.graphdb.util.DefaultConverter;
+import org.neo4j.rest.graphdb.util.Handler;
+import org.neo4j.rest.graphdb.util.QueryResult;
+import org.neo4j.rest.graphdb.util.QueryResultBuilder;
+import org.neo4j.rest.graphdb.util.ResultConverter;
+
+/**
+ * @author mh
+ * @since 22.06.11
+ */
+public class RestGremlinQueryEngine implements QueryEngine<Object> {
+ private final RestRequest restRequest;
+ private final RestAPI restApi;
+ private final ResultConverter resultConverter;
+
+
+ public RestGremlinQueryEngine(RestAPI restApi) {
+ this(restApi,null);
+ }
+ public RestGremlinQueryEngine(RestAPI restApi, ResultConverter resultConverter) {
+ this.restApi = restApi;
+ this.resultConverter = resultConverter!=null ? resultConverter : new DefaultConverter();
+ this.restRequest = restApi.getRestRequest();
+ }
+
+ @Override
+ public QueryResult<Object> query(String statement, Map<String, Object> params) {
+ final String paramsString = JsonHelper.createJsonFrom(params == null ? Collections.emptyMap() : params);
+ final Map<String, Object> data = MapUtil.map("script", statement,"params",paramsString);
+ final RequestResult requestResult = restRequest.get("ext/GremlinPlugin/graphdb/execute_script", data);
+ final Object result = JsonHelper.readJson(requestResult.getEntity());
+ if (requestResult.getStatus() == 500) {
+ return handleError(result);
+ } else {
+ return new RestQueryResult(result,restApi,resultConverter);
+ }
+ }
+
+ private QueryResult<Object> handleError(Object result) {
+ if (result instanceof Map) {
+ Map<?, ?> mapResult = (Map<?, ?>) result;
+ if (RestResultException.isExceptionResult(mapResult)) {
+ throw new RestResultException(mapResult);
+ }
+ }
+ throw new RestResultException(Collections.singletonMap("exception", result.toString()));
+ }
+
+ static class RestQueryResult<T> implements QueryResult<T> {
+ QueryResultBuilder<T> result;
+ private final RestAPI restApi;
+
+
+ @Override
+ public <R> ConvertedResult<R> to(Class<R> type) {
+ return result.to(type);
+ }
+
+ @Override
+ public <R> ConvertedResult<R> to(Class<R> type, ResultConverter<T, R> converter) {
+ return result.to(type,converter);
+ }
+
+ @Override
+ public void handle(Handler<T> handler) {
+ result.handle(handler);
+ }
+
+ @Override
+ public Iterator<T> iterator() {
+ return result.iterator();
+ }
+
+ public RestQueryResult(Object result, RestAPI restApi, ResultConverter resultConverter) {
+ this.restApi = restApi;
+ final Iterable<T> convertedResult = convertRestResult(result);
+ this.result=new QueryResultBuilder<T>(convertedResult, resultConverter);
+ }
+
+ private Iterable<T> convertRestResult(Object result) {
+ final RestEntityExtractor restEntityExtractor = new RestEntityExtractor(restApi);
+ if (result instanceof Map) {
+ Map<?,?> mapResult= (Map<?, ?>) result;
+ if (RestResultException.isExceptionResult(mapResult)) {
+ throw new RestResultException(mapResult);
+ }
+ if (isTableResult(mapResult)) {
+ return (Iterable<T>) new RestTableResultExtractor(restEntityExtractor).extract(mapResult);
+ }
+ }
+ if (result instanceof Iterable) {
+ return new IterableWrapper<T,Object>((Iterable<Object>)result) {
+ @Override
+ protected T underlyingObjectToObject(Object value) {
+ return (T) restEntityExtractor.convertFromRepresentation(value);
+ }
+ };
+ }
+ return Collections.singletonList((T) restEntityExtractor.convertFromRepresentation(result));
+ }
+
+ public static boolean isTableResult(Map<?, ?> mapResult) {
+ return mapResult.containsKey("columns") && mapResult.containsKey("data");
+ }
+ }
+
+
+}
View
25 src/main/java/org/neo4j/rest/graphdb/RestNode.java
@@ -24,25 +24,14 @@ public RestNode( String uri, RestAPI restApi ) {
public RestNode( Map<?, ?> data, RestAPI restApi ) {
super( data, restApi );
- }
-
+ }
+
public Relationship createRelationshipTo( Node toNode, RelationshipType type ) {
- return RestRelationship.create(this,(RestNode)toNode,type,null);
+ return this.restApi.createRelationship(this,(RestNode)toNode,type,null);
}
public Iterable<Relationship> getRelationships() {
- return wrapRelationships( restRequest.get( "relationships/all" ) );
- }
-
- @SuppressWarnings("unchecked")
- private Iterable<Relationship> wrapRelationships( RequestResult requestResult ) {
- return new IterableWrapper<Relationship, Object>(
- (Collection<Object>) restRequest.toEntity( requestResult ) ) {
- @Override
- protected Relationship underlyingObjectToObject( Object data ) {
- return new RestRelationship( (Map<?, ?>) data, getRestApi() );
- }
- };
+ return restApi.wrapRelationships( restRequest.get( "relationships/all" ) );
}
public Iterable<Relationship> getRelationships( RelationshipType... types ) {
@@ -54,19 +43,19 @@ protected Relationship underlyingObjectToObject( Object data ) {
}
path += type.name();
}
- return wrapRelationships( restRequest.get( path ) );
+ return restApi.wrapRelationships( restRequest.get( path ) );
}
public Iterable<Relationship> getRelationships( Direction direction ) {
- return wrapRelationships( restRequest.get( "relationships/" + RestDirection.from( direction ).shortName ) );
+ return restApi.wrapRelationships( restRequest.get( "relationships/" + RestDirection.from( direction ).shortName ) );
}
public Iterable<Relationship> getRelationships( RelationshipType type,
Direction direction ) {
String relationshipsKey = RestDirection.from( direction ).longName + "_relationships";
Object relationship = getStructuralData().get( relationshipsKey );
- return wrapRelationships( restRequest.get( relationship + "/" + type.name() ) );
+ return restApi.wrapRelationships( restRequest.get( relationship + "/" + type.name() ) );
}
public Relationship getSingleRelationship( RelationshipType type,
View
111 src/main/java/org/neo4j/rest/graphdb/RestOperations.java
@@ -0,0 +1,111 @@
+package org.neo4j.rest.graphdb;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicLong;
+
+import javax.ws.rs.core.MediaType;
+
+import org.neo4j.rest.graphdb.RestOperations.RestOperation.Methods;
+
+public class RestOperations {
+ private AtomicLong currentBatchId = new AtomicLong(0);
+ private Map<Long, RestOperation> operations = new LinkedHashMap<Long, RestOperation>();
+ private MediaType contentType;
+ private MediaType acceptHeader;
+
+ public RestOperations(){
+ this.contentType = MediaType.APPLICATION_JSON_TYPE;
+ this.acceptHeader = MediaType.APPLICATION_JSON_TYPE;
+ }
+
+ public static class RestOperation {
+ public enum Methods{
+ POST,
+ PUT,
+ GET,
+ DELETE
+ }
+
+ private Methods method;
+ private Object data;
+ private final String baseUri;
+ private long batchId;
+ private String uri;
+ private MediaType contentType;
+ private MediaType acceptHeader;
+ private Object entity;
+
+
+
+ public RestOperation(long batchId, Methods method, String uri, MediaType contentType, MediaType acceptHeader, Object data, String baseUri){
+ this.batchId = batchId;
+ this.method = method;
+ this.uri = uri;
+ this.contentType = contentType;
+ this.acceptHeader = acceptHeader;
+ this.data = data;
+ this.baseUri = baseUri;
+ }
+
+ public void updateEntity(Object updateObject, RestAPI restApi){
+ if (this.entity instanceof UpdatableRestResult){
+ ((UpdatableRestResult)this.entity).updateFrom(updateObject, restApi);
+ }
+ }
+
+ public Object getEntity() {
+ return entity;
+ }
+
+ public void setEntity(Object entity) {
+ this.entity = entity;
+ }
+
+ public Methods getMethod() {
+ return method;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public long getBatchId() {
+ return batchId;
+ }
+
+ public String getUri() {
+ return uri;
+ }
+
+ public MediaType getContentType() {
+ return contentType;
+ }
+
+ public MediaType getAcceptHeader() {
+ return acceptHeader;
+ }
+
+ public String getBaseUri() {
+ return baseUri;
+ }
+ public boolean isSameUri(String baseUri) {
+ return this.baseUri.equals(baseUri);
+ }
+ }
+
+ public Map<Long,RestOperation> getRecordedRequests(){
+ return this.operations;
+ }
+
+ public RequestResult record(Methods method, String path, Object data, String baseUri){
+ long batchId = this.currentBatchId.incrementAndGet();
+ RestOperation r = new RestOperation(batchId,method,path,this.contentType,this.acceptHeader,data,baseUri);
+ operations.put(batchId,r);
+ return RequestResult.batchResult(r);
+ }
+
+ public void addToRestOperation(long batchId, Object entity){
+ this.operations.get(batchId).setEntity(entity);
+ }
+}
View
25 src/main/java/org/neo4j/rest/graphdb/RestRelationship.java
@@ -1,13 +1,10 @@
package org.neo4j.rest.graphdb;
import org.neo4j.graphdb.*;
-import org.neo4j.helpers.collection.MapUtil;
-
-
-
import java.net.URI;
import java.util.Map;
+
public class RestRelationship extends RestEntity implements Relationship {
RestRelationship( URI uri, RestAPI restApi ) {
@@ -16,8 +13,8 @@
RestRelationship( String uri, RestAPI restApi ) {
super( uri, restApi );
- }
-
+ }
+
public RestRelationship( Map<?, ?> data, RestAPI restApi ) {
super( data, restApi );
}
@@ -63,20 +60,8 @@ public boolean isType( RelationshipType type ) {
}
- public static RestRelationship create(RestNode startNode, RestNode endNode, RelationshipType type, Map<String, Object> props) {
- final RestRequest restRequest = startNode.getRestRequest();
- Map<String, Object> data = MapUtil.map("to", endNode.getUri(), "type", type.name());
- if (props!=null && props.size()>0) {
- data.put("data",props);
- }
-
- RequestResult requestResult = restRequest.post( "relationships", JsonHelper.createJsonFrom( data ) );
- if ( restRequest.statusOtherThan(requestResult, javax.ws.rs.core.Response.Status.CREATED ) ) {
- final int status = requestResult.getStatus();
- throw new RuntimeException( "" + status);
- }
- final URI location = requestResult.getLocation();
- return new RestRelationship(location, startNode.getRestApi() );
+ public RestRelationship create(RestNode startNode, RestNode endNode, RelationshipType type, Map<String, Object> props) {
+ return this.restApi.createRelationship(startNode, endNode, type, props);
}
}
View
151 src/main/java/org/neo4j/rest/graphdb/RestRequest.java
@@ -1,154 +1,21 @@
package org.neo4j.rest.graphdb;
-import com.sun.jersey.api.client.Client;
-import com.sun.jersey.api.client.ClientResponse;
-import com.sun.jersey.api.client.WebResource;
-import com.sun.jersey.api.client.WebResource.Builder;
-import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
-
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import org.neo4j.rest.graphdb.RequestResult;
-
-
-import java.io.UnsupportedEncodingException;
import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URLEncoder;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-
-public class RestRequest {
-
- public static final int CONNECT_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(30);
- public static final int READ_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(30);
- private final URI baseUri;
- private final Client client;
-
- public RestRequest( URI baseUri ) {
- this( baseUri, null, null );
- }
-
- public RestRequest( URI baseUri, String username, String password ) {
- this.baseUri = uriWithoutSlash( baseUri );
- client = createClient();
- addAuthFilter(username, password);
-
- }
-
- private void addAuthFilter(String username, String password) {
- if (username == null) return;
- client.addFilter( new HTTPBasicAuthFilter( username, password ) );
- }
-
- private Client createClient() {
- Client client = Client.create();
-
- client.setConnectTimeout(CONNECT_TIMEOUT);
- client.setReadTimeout(READ_TIMEOUT);
-
- return client;
- }
-
- private RestRequest( URI uri, Client client ) {
- this.baseUri = uriWithoutSlash( uri );
- this.client = client;
- }
-
- private URI uriWithoutSlash( URI uri ) {
- String uriString = uri.toString();
- return uriString.endsWith( "/" ) ? uri( uriString.substring( 0, uriString.length() - 1 ) ) : uri;
- }
-
- public static String encode( Object value ) {
- if ( value == null ) return "";
- try {
- return URLEncoder.encode( value.toString(), "utf-8" ).replaceAll( "\\+", "%20" );
- } catch ( UnsupportedEncodingException e ) {
- throw new RuntimeException( e );
- }
- }
-
-
- private Builder builder( String path ) {
- WebResource resource = client.resource( uri( pathOrAbsolute( path ) ) );
- return resource.accept( MediaType.APPLICATION_JSON_TYPE );
- }
-
- private String pathOrAbsolute( String path ) {
- if ( path.startsWith( "http://" ) ) return path;
- return baseUri + "/" + path;
- }
-
- public RequestResult get( String path ) {
- return RequestResult.extractFrom(builder(path).get(ClientResponse.class));
- }
-
- public RequestResult get( String path, String data ) {
- Builder builder = builder(path);
- if ( data != null ) {
- builder = builder.entity( data, MediaType.APPLICATION_JSON_TYPE );
- }
- return RequestResult.extractFrom(builder.get(ClientResponse.class));
- }
-
- public RequestResult delete(String path) {
- return RequestResult.extractFrom(builder(path).delete(ClientResponse.class));
- }
-
- public RequestResult post( String path, String data ) {
- Builder builder = builder( path );
- if ( data != null ) {
- builder = builder.entity( data, MediaType.APPLICATION_JSON_TYPE );
- }
- return RequestResult.extractFrom(builder.post(ClientResponse.class));
- }
-
- public void put( String path, String data ) {
- Builder builder = builder( path );
- if ( data != null ) {
- builder = builder.entity( data, MediaType.APPLICATION_JSON_TYPE );
- }
- final ClientResponse response = builder.put(ClientResponse.class);
- response.close();
- }
+public interface RestRequest {
- public Object toEntity( RequestResult requestResult) {
- return JsonHelper.jsonToSingleValue( entityString(requestResult) );
- }
+ RequestResult get(String path);
- public Map<?, ?> toMap( RequestResult requestResult) {
- final String json = entityString(requestResult);
- return JsonHelper.jsonToMap(json);
- }
+ RequestResult get(String path, Object data);
- private String entityString( RequestResult requestResult) {
- return requestResult.getEntity();
- }
+ RequestResult delete(String path);
- public boolean statusIs( RequestResult requestResult, Response.StatusType status ) {
- return requestResult.getStatus() == status.getStatusCode();
- }
+ RequestResult post(String path, Object data);
- public boolean statusOtherThan( RequestResult requestResult, Response.StatusType status ) {
- return !statusIs(requestResult, status );
- }
+ RequestResult put(String path, Object data);
- public RestRequest with( String uri ) {
- return new RestRequest( uri( uri ), client );
- }
+ RestRequest with(String uri);
- private URI uri( String uri ) {
- try {
- return new URI( uri );
- } catch ( URISyntaxException e ) {
- throw new RuntimeException( e );
- }
- }
+ String getUri();
- public URI getUri() {
- return baseUri;
- }
-}
+}
View
7 src/main/java/org/neo4j/rest/graphdb/RestResultConverter.java
@@ -0,0 +1,7 @@
+package org.neo4j.rest.graphdb;
+
+public interface RestResultConverter {
+ public boolean canHandle(Object value);
+ public Object convertFromRepresentation(Object value);
+
+}
View
34 src/main/java/org/neo4j/rest/graphdb/RestResultConverters.java
@@ -0,0 +1,34 @@
+package org.neo4j.rest.graphdb;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+/**
+ * @author mh
+ * @since 21.09.11
+ */
+class RestResultConverters implements RestResultConverter {
+ private final Collection<RestResultConverter> converters;
+
+ public RestResultConverters(RestResultConverter... converters) {
+ this.converters = Arrays.asList(converters);
+ }
+
+ @Override
+ public boolean canHandle(Object value) {
+ for (RestResultConverter converter : converters) {
+ if (converter.canHandle(value)) return true;
+ }
+ return false;
+ }
+
+ @Override
+ public Object convertFromRepresentation(Object value) {
+ for (RestResultConverter converter : converters) {
+ if (converter.canHandle(value)) {
+ return converter.convertFromRepresentation(value);
+ }
+ }
+ return null;
+ }
+}
View
35 src/main/java/org/neo4j/rest/graphdb/RestResultException.java
@@ -0,0 +1,35 @@
+package org.neo4j.rest.graphdb;
+
+import java.util.List;
+import java.util.Map;
+
+public class RestResultException extends RuntimeException {
+ public RestResultException(Object result) {
+ super(format(toMap(result)));
+ }
+
+ private static String format(Map<?, ?> result) {
+ if (result==null) return "Unknown Exception";
+ StringBuilder sb = new StringBuilder();
+ sb.append(result.get("message")).append(" at\n");
+ sb.append(result.get("exception")).append("\n");
+ List<String> stacktrace = (List<String>) result.get("stacktrace");
+ if (stacktrace != null) {
+ for (String line : stacktrace) {
+ sb.append(" ").append(line).append("\n");
+ }
+ }
+ return sb.toString();
+ }
+
+ public static boolean isExceptionResult(Object result) {
+ final Map<String, Object> map = toMap(result);
+ return map!=null && map.containsKey("exception") && map.containsKey("message");
+ }
+
+ private static Map<String, Object> toMap(Object result) {
+ if (!(result instanceof Map)) return null;
+ return (Map<String, Object>) result;
+
+ }
+}
View
39 src/main/java/org/neo4j/rest/graphdb/RestTableResultExtractor.java
@@ -0,0 +1,39 @@
+package org.neo4j.rest.graphdb;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class RestTableResultExtractor {
+
+ private final RestEntityExtractor restEntityExtractor;
+
+ public RestTableResultExtractor(RestEntityExtractor restEntityExtractor) {
+ this.restEntityExtractor = restEntityExtractor;
+ }
+
+ public List<Map<String, Object>> extract(Map<?, ?> restResult) {
+ List<String> columns = (List<String>) restResult.get("columns");
+ return extractData(restResult, columns);
+ }
+
+ private List<Map<String, Object>> extractData(Map<?, ?> restResult, List<String> columns) {
+ List<List<?>> rows = (List<List<?>>) restResult.get("data");
+ List<Map<String, Object>> result = new ArrayList<Map<String, Object>>(rows.size());
+ for (List<?> row : rows) {
+ result.add(mapRow(columns, row));
+ }
+ return result;
+ }
+
+ private Map<String, Object> mapRow(List<String> columns, List<?> row) {
+ int columnCount = columns.size();
+ Map<String, Object> newRow = new HashMap<String, Object>(columnCount);
+ for (int i = 0; i < columnCount; i++) {
+ final Object value = row.get(i);
+ newRow.put(columns.get(i), restEntityExtractor.convertFromRepresentation(value));
+ }
+ return newRow;
+ }
+}
View
9 src/main/java/org/neo4j/rest/graphdb/RestTraversal.java
@@ -136,11 +136,10 @@ public RestTraversalDescription expand(RelationshipExpander relationshipExpander
public Traverser traverse(Node node) {
final RestNode restNode = (RestNode) node;
- final RestRequest request = restNode.getRestRequest();
- final String traversalJson = JsonHelper.createJsonFrom(description);
- final RequestResult result = request.post("traverse/" + FULLPATH, traversalJson);
- if (request.statusOtherThan(result, Response.Status.OK)) throw new RuntimeException(String.format("Error executing traversal: %d %s",result.getStatus(), traversalJson));
- final Object col = request.toEntity(result);
+ final RestRequest request = restNode.getRestRequest();
+ final RequestResult result = request.post("traverse/" + FULLPATH, description);
+ if (result.statusOtherThan(Response.Status.OK)) throw new RuntimeException(String.format("Error executing traversal: %d %s",result.getStatus(), description));
+ final Object col = result.toEntity();
if (!(col instanceof Collection)) throw new RuntimeException(String.format("Unexpected traversal result, %s instead of collection", col!=null ? col.getClass() : null));
return new RestTraverser((Collection) col,restNode.getRestApi());
}
View
9 src/main/java/org/neo4j/rest/graphdb/UpdatableRestResult.java
@@ -0,0 +1,9 @@
+package org.neo4j.rest.graphdb;
+
+/**
+ * @author mh
+ * @since 21.09.11
+ */
+public interface UpdatableRestResult {
+ void updateFrom(Object newValue, RestAPI restApi);
+}
View
10 src/main/java/org/neo4j/rest/graphdb/index/RestIndex.java
@@ -39,15 +39,15 @@ private String getTypeName() {
public void add( T entity, String key, Object value ) {
final RestEntity restEntity = (RestEntity) entity;
String uri = restEntity.getUri();
- final RequestResult response = restRequest.post(indexPath(key, value), JsonHelper.createJsonFrom(uri));
+ final RequestResult response = restRequest.post(indexPath(key, value), uri);
if (response.getStatus() != 201) throw new RuntimeException(String.format("Error adding element %d %s %s to index %s", restEntity.getId(), key, value, indexName));
}
private String indexPath( String key, Object value ) {
- return "index/" + getTypeName() + "/" + indexName + (key!=null? "/" + RestRequest.encode( key ) :"") + (value!=null ? "/" + RestRequest.encode( value ):"");
+ return "index/" + getTypeName() + "/" + indexName + (key!=null? "/" + ExecutingRestRequest.encode( key ) :"") + (value!=null ? "/" + ExecutingRestRequest.encode( value ):"");
}
private String queryPath( String key, Object value ) {
- return indexPath(key,null) + "?query="+RestRequest.encode( value );
+ return indexPath(key,null) + "?query="+ExecutingRestRequest.encode( value );
}
public void remove( T entity, String key, Object value ) {
@@ -78,8 +78,8 @@ public void delete() {
}
private IndexHits<T> handleQueryResults(RequestResult response) {
- if ( restRequest.statusIs( response, Response.Status.OK ) ) {
- Collection hits = (Collection) restRequest.toEntity( response );
+ if ( response.statusIs( Response.Status.OK ) ) {
+ Collection hits = (Collection) response.toEntity();
return new SimpleIndexHits<T>( hits, hits.size() );
} else {
return new SimpleIndexHits<T>( Collections.emptyList(), 0 );
View
6 src/main/java/org/neo4j/rest/graphdb/index/RestIndexManager.java
@@ -39,8 +39,8 @@ public boolean existsForNodes( String indexName ) {
@SuppressWarnings({"unchecked"})
private Map<String, ?> indexInfo( final String indexType ) {
RequestResult response = restRequest.get( "index/" + indexType );
- if ( restRequest.statusIs( response, ClientResponse.Status.NO_CONTENT ) ) return Collections.emptyMap();
- return (Map<String, ?>) restRequest.toMap( response );
+ if ( response.statusIs(ClientResponse.Status.NO_CONTENT ) ) return Collections.emptyMap();
+ return (Map<String, ?>) response.toMap();
}
@SuppressWarnings("unchecked")
@@ -112,7 +112,7 @@ private void createIndex(String type, String indexName, Map<String, String> conf
Map<String,Object> data=new HashMap<String, Object>();
data.put("name",indexName);
data.put("config",config);
- restRequest.post("index/" + type, JsonHelper.createJsonFrom(data));
+ restRequest.post("index/" + type, data);
}
public String[] relationshipIndexNames() {
View
7 src/main/java/org/neo4j/rest/graphdb/util/ConvertedResult.java
@@ -0,0 +1,7 @@
+package org.neo4j.rest.graphdb.util;
+
+
+public interface ConvertedResult<R>