Permalink
Browse files

Split CRUD operations into abstract methods for easier alternative im…

…plementations
  • Loading branch information...
1 parent bef4e86 commit fc9f190a1b598261a4d1d52e2672cee0d059f0ab Martin Kleppmann committed Jun 14, 2009
@@ -0,0 +1,15 @@
+package com.eptcomputing.neo4j
+
+/**
+ * Extend your class with this trait to get implicit conversion between Java and Scala
+ * Iterators/Iterables.
+ */
+trait IteratorConverters {
+ /** Implicitly convert a Java iterable to a Scala iterator. */
+ protected implicit def java2scala[T](iter: java.lang.Iterable[T]): scala.Iterator[T] =
+ new scala.collection.jcl.MutableIterator.Wrapper(iter.iterator)
+
+ /** Implicitly convert a Java iterator to a Scala iterator. */
+ protected implicit def java2scala[T](iter: java.util.Iterator[T]): scala.Iterator[T] =
+ new scala.collection.jcl.MutableIterator.Wrapper(iter)
+}
@@ -9,7 +9,7 @@ import org.codehaus.jettison.json.{JSONObject, JSONArray, JSONException}
/**
* Provides helpers for converting Neo4j nodes to/from JSON.
*/
-object NeoJsonConverter {
+object NeoJsonConverter extends IteratorConverters {
val log = Logger.getLogger(this.getClass.getName)
@@ -170,13 +170,4 @@ object NeoJsonConverter {
" relationship in JSON: " + e.getMessage)
}
}
-
-
- /** Implicitly convert a Java iterable to a Scala iterator. */
- implicit def java2scala[T](iter: java.lang.Iterable[T]): scala.Iterator[T] =
- new scala.collection.jcl.MutableIterator.Wrapper(iter.iterator)
-
- /** Implicitly convert a Java iterator to a Scala iterator. */
- implicit def java2scala[T](iter: java.util.Iterator[T]): scala.Iterator[T] =
- new scala.collection.jcl.MutableIterator.Wrapper(iter)
}
@@ -5,15 +5,42 @@ import javax.ws.rs._
import javax.ws.rs.core._
import org.codehaus.jettison.json.JSONObject
+import org.neo4j.api.core.{NeoService, Node}
import com.eptcomputing.neo4j.NeoServer
import NeoJsonConverter._
/**
- * A straightforward Create/Read/Update/Delete JSON resource where an entity maps
- * directly to a Neo4j node.
+ * A template for a CRUD (Create/Read/Update/Delete) RESTful JSON resource. You can
+ * override each of the operations with a concise method to perform the desired task.
+ * See <tt>SimpleNeoResource</tt> for a default implementation.
*/
-class NeoResource extends RequiredParam {
+abstract class NeoResource extends RequiredParam {
+
+ /**
+ * Override this method to perform the creation of a Neo4j node based on a given
+ * JSON object. Should return the newly created node. Is called within a Neo4j
+ * transaction.
+ */
+ def create(neo: NeoService, json: JSONObject): Node
+
+ /**
+ * Override this method to perform mapping from a Neo4j node to a JSON object
+ * for output. Should return the desired JSON serialisation.
+ */
+ def read(neo: NeoService, node: Node): JSONObject
+
+ /**
+ * Override this method to perform the overwriting of a Neo4j node with new data.
+ */
+ def update(neo: NeoService, existing: Node, newValue: JSONObject)
+
+ /**
+ * Override this method to perform the deletion of a Neo4j node. Should return
+ * a JSON serialisation of the node in its most recent version before it was
+ * deleted.
+ */
+ def delete(neo: NeoService, node: Node): JSONObject
/**
* <tt>POST /neo_resource</tt> with a JSON document as body creates a new entity
@@ -25,9 +52,9 @@ class NeoResource extends RequiredParam {
@Produces(Array(MediaType.APPLICATION_JSON))
def createJSON(json: JSONObject) = {
NeoServer.exec { neo =>
- val node = jsonToNeo(json, neo, null)
+ val node = create(neo, json)
val uri = UriBuilder.fromResource(this.getClass).path("{id}").build(new java.lang.Long(node.getId))
- Response.created(uri).entity(neoToJson(node)).build
+ Response.created(uri).entity(read(neo, node)).build
}
}
@@ -39,9 +66,7 @@ class NeoResource extends RequiredParam {
@Produces(Array(MediaType.APPLICATION_JSON))
def readJSON(@PathParam("id") node: NeoNodeParam) = {
requiredParam("id", node)
- NeoServer.exec {
- neo => neoToJson(node.getNode(neo))
- }
+ NeoServer.exec { neo => read(neo, node.getNode(neo)) }
}
/**
@@ -54,8 +79,10 @@ class NeoResource extends RequiredParam {
@Produces(Array(MediaType.APPLICATION_JSON))
def updateJSON(@PathParam("id") node: NeoNodeParam, json: JSONObject) = {
requiredParam("id", node)
- NeoServer.exec {
- neo => neoToJson(jsonToNeo(json, neo, node.getNode(neo)))
+ NeoServer.exec { neo =>
+ val neoNode = node.getNode(neo)
+ update(neo, neoNode, json)
+ read(neo, neoNode)
}
}
@@ -67,10 +94,30 @@ class NeoResource extends RequiredParam {
@Produces(Array(MediaType.APPLICATION_JSON))
def deleteJSON(@PathParam("id") node: NeoNodeParam) = {
requiredParam("id", node)
- NeoServer.exec { neo =>
- val json = neoToJson(node.getNode(neo))
- node.deleteNode(neo)
- json
- }
+ NeoServer.exec { neo => delete(neo, node.getNode(neo)) }
+ }
+}
+
+
+/**
+ * Simple default implementation of a CRUD resource which maps to a single Neo4j node.
+ * See <tt>NeoJsonConverter</tt> for the format used.
+ */
+class SimpleNeoResource extends NeoResource with IteratorConverters {
+
+ def create(neo: NeoService, json: JSONObject) =
+ jsonToNeo(json, neo, null)
+
+ def read(neo: NeoService, node: Node) =
+ neoToJson(node)
+
+ def update(neo: NeoService, existing: Node, newValue: JSONObject) =
+ jsonToNeo(newValue, neo, existing)
+
+ def delete(neo: NeoService, node: Node) = {
+ val json = neoToJson(node)
+ node.getRelationships.foreach{_.delete}
+ node.delete
+ json
}
}
@@ -50,20 +50,6 @@ class NeoNodeParam(param: String) extends ParamType[Int](param) {
)
}
}
-
- /**
- * Tries to delete a node in a Neo server instance, raises HTTP 404 ("not found") if the node
- * does not exist.
- */
- def deleteNode(neo: NeoService) {
- val node = getNode(neo)
- node.getRelationships.foreach{_.delete}
- node.delete
- }
-
- /** Implicitly convert a Java iterable to a Scala iterator. */
- private implicit def java2scala[T](iter: java.lang.Iterable[T]): scala.Iterator[T] =
- new scala.collection.jcl.MutableIterator.Wrapper(iter.iterator)
}
@@ -1,7 +1,12 @@
package com.eptcomputing.neo4j.rest.test
-import javax.ws.rs._
-import com.eptcomputing.neo4j.rest.NeoResource
+import javax.ws.rs.Path
+import com.eptcomputing.neo4j.rest.SimpleNeoResource
+/**
+ * Example of a RESTful CRUD (create/read/update/delete) resource which maps to a single
+ * Neo4j node. JSON object fields are mapped to node attributes, and relationships are
+ * represented explicitly -- see <tt>NeoJsonConverter</tt>.
+ */
@Path("/neo_resource")
-class ExampleNeoResource extends NeoResource
+class ExampleNeoResource extends SimpleNeoResource

0 comments on commit fc9f190

Please sign in to comment.