[cl-neo4j-cvs] r1 -
Kevin Raison
kraison at common-lisp.net
Tue May 18 19:43:41 UTC 2010
Author: kraison
Date: Tue May 18 15:43:41 2010
New Revision: 1
Log:
initial check in
Added:
LICENSE
README
cl-neo4j-package.lisp
cl-neo4j.asd
conditions.lisp
globals.lisp
neo4j.lisp
utilities.lisp
Added: LICENSE
==============================================================================
--- (empty file)
+++ LICENSE Tue May 18 15:43:41 2010
@@ -0,0 +1,25 @@
+ cl-neo4j
+
+ Copyright (c) 2010 Kevin Raison <raison at chatsubo.net>
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the "Software"), to deal in the Software without
+ restriction, including without limitation the rights to use,
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following
+ conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ OTHER DEALINGS IN THE SOFTWARE.
+
Added: README
==============================================================================
--- (empty file)
+++ README Tue May 18 15:43:41 2010
@@ -0,0 +1 @@
+TODO.
Added: cl-neo4j-package.lisp
==============================================================================
--- (empty file)
+++ cl-neo4j-package.lisp Tue May 18 15:43:41 2010
@@ -0,0 +1,35 @@
+(in-package #:cl-user)
+
+(defpackage #:cl-neo4j
+ (:use #:cl
+ #:json
+ #:json-rpc
+ #:drakma)
+ (:export #:do-neo4j-query
+ #:get-node
+ #:extract-node-id
+ #:create-node
+ #:set-node-properties
+ #:get-node-properties
+ #:del-node-properties
+ #:set-node-property
+ #:get-node-property
+ #:del-node-property
+ #:delete-node
+ #:create-relationship
+ #:set-relationship-properties
+ #:get-relationship-properties
+ #:del-relationship-properties
+ #:set-relationship-property
+ #:get-relationship-property
+ #:del-relationship-property
+ #:delete-relationship
+ #:get-node-relationships
+ #:list-indices
+ #:add-to-index
+ #:remove-from-index
+ #:query-index
+ #:traverse
+ ;; Vars
+ #:*neo4j-host*
+ #:*neo4j-port*))
Added: cl-neo4j.asd
==============================================================================
--- (empty file)
+++ cl-neo4j.asd Tue May 18 15:43:41 2010
@@ -0,0 +1,22 @@
+;; ASDF package description for cl-neo4j -*- Lisp -*-
+
+(defpackage :cl-neo4j-system (:use :cl :asdf))
+(in-package :cl-neo4j-system)
+
+(defsystem cl-neo4j
+ :name "neo4j RESTful Client Interface ()"
+ :maintainer "Kevin Raison"
+ :author "Kevin Raison <last name @ chatsubo dot net>"
+ :version "0.1"
+ :description "neo4j RESTful Client Interface"
+ :long-description "neo4j RESTful Client Interface."
+ :depends-on (:drakma
+ :cl-json)
+ :components ((:file "cl-neo4j-package")
+ (:file "globals" :depends-on ("cl-neo4j-package"))
+ (:file "utilities" :depends-on ("globals"))
+ (:file "conditions" :depends-on ("utilities"))
+ (:file "neo4j" :depends-on ("conditions"))))
+
+
+
Added: conditions.lisp
==============================================================================
--- (empty file)
+++ conditions.lisp Tue May 18 15:43:41 2010
@@ -0,0 +1,44 @@
+(in-package #:cl-neo4j)
+
+(define-condition unknown-return-type-error (error)
+ ((uri :accessor uri :initarg :uri)
+ (property :accessor property :initarg :property)
+ (status :accessor status :initarg :status))
+ (:report (lambda (condition stream)
+ (format stream "Unknown status ~A returned for ~A (~A)"
+ (status condition) (uri condition) (property condition)))))
+
+(define-condition invalid-data-sent-error (error)
+ ((json :accessor json :initarg :json)
+ (uri :accessor uri :initarg :uri))
+ (:report (lambda (condition stream)
+ (format stream "Invalid data sent to ~A: ~A" (uri condition) (json condition)))))
+
+(define-condition node-not-found-error (error)
+ ((uri :accessor uri :initarg :uri)
+ (property :accessor property :initarg :property))
+ (:report (lambda (condition stream)
+ (if (slot-boundp condition 'property)
+ (format stream "Property ~A not found for node ~A"
+ (property condition) (uri condition))
+ (format stream "Node not found ~A" (uri condition))))))
+
+(define-condition unable-to-delete-node-error (error)
+ ((uri :accessor uri :initarg :uri))
+ (:report (lambda (condition stream)
+ (format stream "Unable to delete node ~A. Still has relationships?" (uri condition)))))
+
+(define-condition relationship-not-found-error (error)
+ ((uri :accessor uri :initarg :uri)
+ (property :accessor property :initarg :property))
+ (:report (lambda (condition stream)
+ (if (slot-boundp condition 'property)
+ (format stream "Property ~A not found for relationship ~A"
+ (property condition) (uri condition))
+ (format stream "Relationship not found ~A" (uri condition))))))
+
+(define-condition index-entry-not-found-error (error)
+ ((uri :accessor uri :initarg :uri))
+ (:report (lambda (condition stream)
+ (format stream "Index entry not found ~A" (uri condition)))))
+
Added: globals.lisp
==============================================================================
--- (empty file)
+++ globals.lisp Tue May 18 15:43:41 2010
@@ -0,0 +1,4 @@
+(in-package #:cl-neo4j)
+
+(defvar *neo4j-host* "localhost")
+(defvar *neo4j-port* 9999)
Added: neo4j.lisp
==============================================================================
--- (empty file)
+++ neo4j.lisp Tue May 18 15:43:41 2010
@@ -0,0 +1,269 @@
+(in-package #:cl-neo4j)
+
+(defun do-neo4j-query (uri method &key json decode?)
+ (multiple-value-bind (body status headers uri stream must-close reason)
+ (http-request uri
+ :method method
+ :content json
+ :content-type (if json "application/json")
+ :accept "application/json")
+ (declare (ignore headers uri stream must-close reason))
+ (values status (if decode?
+ (decode-json-from-string (map 'string #'code-char body))
+ body))))
+
+(defmacro def-neo4j-fun (name lambda-list method &rest args)
+ `(progn
+ (defun ,name ,(append '(&key (host *neo4j-host*) (port *neo4j-port*)) lambda-list)
+ (let ((uri ,(cadr (assoc :uri-spec args)))
+ (json ,(cond ((cadr (assoc :encode-properties? args))
+ `(encode-json-to-string properties))
+ ((cadr (assoc :encode-value? args))
+ `(encode-json-to-string value))
+ ((cadr (assoc :encode-node-id? args))
+ `(format nil "http://~A:~A/node/~A" host port node-id))
+ ((cadr (assoc :encode-relationship? args))
+ `(encode-json-to-string
+ (list (cons "to"
+ (format nil "http://~A:~A/node/~A" host port to-node-id))
+ (cons "type" relationship-type)
+ (cons "data" properties))))
+ (t nil))))
+ (multiple-value-bind (body status headers drakma-uri stream must-close reason)
+ (http-request uri
+ :method ,method
+ :content json
+ :content-type (if json "application/json" nil)
+ :accept "application/json")
+ (declare (ignore headers drakma-uri stream must-close reason))
+ (case status
+ ,@(mapcar
+ #'(lambda (s) s)
+ (append (cadr (assoc :status-handlers args))
+ `((othwerwise
+ (error 'unknown-return-type-error :uri uri :status status
+ :property (cond ((boundp 'properties) (symbol-value 'properties))
+ ((boundp 'value) (symbol-value 'value))
+ ((boundp 'node-id) (symbol-value 'node-id))
+ (t nil)))))))))))))
+
+(defun extract-node-id (url)
+ "http://localhost:9999/node/1"
+ (subseq url (1+ (search "/" url :from-end t))))
+
+(def-neo4j-fun get-node (node-id)
+ :get
+ (:uri-spec (if node-id
+ (format nil "http://~A:~A/node/~A" host port node-id)
+ (format nil "http://~A:~A/" host port)))
+ (:status-handlers
+ ((200 (decode-json-from-string (map 'string #'code-char body)))
+ (404 (error 'node-not-found-error :uri uri :property node-id)))))
+
+(def-neo4j-fun create-node (properties)
+ :post
+ (:encode-properties? t)
+ (:uri-spec (format nil "http://~A:~A/node" host port))
+ (:status-handlers
+ ((201 (decode-json-from-string (map 'string #'code-char body)))
+ (400 (error 'invalid-data-sent-error :uri uri :json json)))))
+
+(def-neo4j-fun delete-node (node-id)
+ :delete
+ (:uri-spec (format nil "http://~A:~A/node/~A" host port node-id))
+ (:status-handlers
+ ((204 (values t body))
+ (404 (error 'node-not-found-error :uri uri))
+ (409 (error 'unable-to-delete-node-error :uri uri)))))
+
+(def-neo4j-fun set-node-properties (node-id properties)
+ :put
+ (:encode-properties? t)
+ (:uri-spec (format nil "http://~A:~A/node/~A/properties" host port node-id))
+ (:status-handlers
+ ((204 (values t body))
+ (400 (error 'invalid-data-sent-error :uri uri :json json))
+ (404 (error 'node-not-found-error :uri uri)))))
+
+(def-neo4j-fun get-node-properties (node-id)
+ :get
+ (:uri-spec (format nil "http://~A:~A/node/~A/properties" host port node-id))
+ (:status-handlers
+ ((200 (decode-json-from-string (map 'string #'code-char body)))
+ (204 nil)
+ (404 (error 'node-not-found-error :uri uri)))))
+
+(def-neo4j-fun del-node-properties (node-id)
+ :delete
+ (:uri-spec (format nil "http://~A:~A/node/~A/properties" host port node-id))
+ (:status-handlers
+ ((202 (values t body))
+ (404 (error 'node-not-found-error :uri uri)))))
+
+(def-neo4j-fun set-node-property (node-id property value)
+ :put
+ (:encode-value? t)
+ (:uri-spec (format nil "http://~A:~A/node/~A/properties/~A" host port node-id
+ (if (symbolp property)
+ (string-downcase (symbol-name property))
+ property)))
+ (:status-handlers
+ ((204 (values t body))
+ (400 (error 'invalid-data-sent-error :uri uri :json json)))))
+
+(def-neo4j-fun get-node-property (node-id property)
+ :get
+ (:uri-spec (format nil "http://~A:~A/node/~A/properties/~A" host port node-id
+ (if (symbolp property)
+ (string-downcase (symbol-name property))
+ property)))
+ (:status-handlers
+ ((200 (decode-json-from-string (map 'string #'code-char body)))
+ (400 (error 'invalid-data-sent-error :uri uri :json json)))))
+
+(def-neo4j-fun del-node-property (node-id property)
+ :delete
+ (:uri-spec (format nil "http://~A:~A/node/~A/properties/~A" host port node-id
+ (if (symbolp property)
+ (string-downcase (symbol-name property))
+ property)))
+ (:status-handlers
+ ((204 (values t body))
+ (404 (error 'node-not-found-error :uri uri))
+ (409 (error 'unable-to-delete-node-error :uri uri)))))
+
+(def-neo4j-fun create-relationship (node-id to-node-id relationship-type properties)
+ :post
+ (:encode-relationship? t)
+ (:uri-spec (format nil "http://~A:~A/node/~A/relationships" host port node-id))
+ (:status-handlers
+ ((201 (decode-json-from-string (map 'string #'code-char body)))
+ (400 (error 'invalid-data-sent-error :uri uri :json json))
+ (404 (error 'node-not-found-error :uri to-node-id)))))
+
+(def-neo4j-fun set-relationship-properties (relationship-id properties)
+ :put
+ (:encode-properties? t)
+ (:uri-spec (format nil "http://~A:~A/relationship/~A/properties" host port relationship-id))
+ (:status-handlers
+ ((204 (values t body))
+ (400 (error 'invalid-data-sent-error :uri uri :json json))
+ (404 (error 'relationship-not-found-error :uri uri)))))
+
+(def-neo4j-fun get-relationship-properties (relationship-id)
+ :get
+ (:uri-spec (format nil "http://~A:~A/relationship/~A/properties" host port relationship-id))
+ (:status-handlers
+ ((200 (decode-json-from-string (map 'string #'code-char body)))
+ (204 nil)
+ (404 (error 'relationship-not-found-error :uri uri)))))
+
+(def-neo4j-fun del-relationship-properties (relationship-id)
+ :delete
+ (:uri-spec (format nil "http://~A:~A/relationship/~A/properties" host port relationship-id))
+ (:status-handlers
+ ((202 (values t body))
+ (404 (error 'relationship-not-found-error :uri uri)))))
+
+(def-neo4j-fun set-relationship-property (relationship-id property value)
+ :put
+ (:encode-value? t)
+ (:uri-spec (format nil "http://~A:~A/relationship/~A/properties/~A"
+ host port relationship-id property))
+ (:status-handlers
+ ((204 (values t body))
+ (400 (error 'invalid-data-sent-error :uri uri :json json))
+ (404 (error 'relationship-not-found-error :uri uri)))))
+
+(def-neo4j-fun get-relationship-property (relationship-id property)
+ :get
+ (:uri-spec (format nil "http://~A:~A/relationship/~A/properties/~A"
+ host port relationship-id property))
+ (:status-handlers
+ ((200 (decode-json-from-string (map 'string #'code-char body)))
+ (400 (error 'invalid-data-sent-error :uri uri :json json)))))
+
+(def-neo4j-fun del-relationship-property (relationship-id property)
+ :delete
+ (:uri-spec (format nil "http://~A:~A/relationship/~A/properties/~A"
+ host port relationship-id property))
+ (:status-handlers
+ ((204 (values t body))
+ (404 (error 'relationship-not-found-error :uri uri)))))
+
+(def-neo4j-fun delete-relationship (relationship-id)
+ :delete
+ (:uri-spec (format nil "http://~A:~A/relationship/~A" host port relationship-id))
+ (:status-handlers
+ ((204 (values t body))
+ (404 (error 'relationship-not-found-error :uri uri)))))
+
+(def-neo4j-fun get-node-relationships (node-id direction types)
+ :get
+ (:uri-spec (format nil "http://~A:~A/node/~A/relationships/~A/~{~A~^\\&~}"
+ host port node-id
+ (cond ((null direction) "all")
+ ((symbolp direction)
+ (string-downcase (symbol-name direction)))
+ (t direction))
+ types))
+ (:status-handlers
+ ((200 (decode-json-from-string (map 'string #'code-char body)))
+ (404 (error 'node-not-found-error :uri uri :property node-id)))))
+
+(def-neo4j-fun list-indices ()
+ :get
+ (:uri-spec (format nil "http://~A:~A/index" host port))
+ (:status-handlers
+ ((200 (decode-json-from-string (map 'string #'code-char body))))))
+
+(def-neo4j-fun add-to-index (node-id key value)
+ :post
+ (:uri-spec (format nil "http://~A:~A/index/node/~A/~A" host port key value))
+ (:encode-node-id? t)
+ (:status-handlers
+ ((201 (values t body)))))
+
+(def-neo4j-fun remove-from-index (node-id key value)
+ :delete
+ (:uri-spec (format nil "http://~A:~A/index/node/~A/~A/~A" host port key value node-id))
+ (:status-handlers
+ ((204 (values t body))
+ (404 (error 'index-entry-not-found-error :uri uri)))))
+
+(def-neo4j-fun query-index (key value)
+ :get
+ (:uri-spec (format nil "http://~A:~A/index/node/~A/~A" host port key value))
+ (:status-handlers
+ ((200 (decode-json-from-string (map 'string #'code-char body))))))
+
+(def-neo4j-fun query-fulltext-index (key value)
+ :get
+ (:uri-spec (format nil "http://~A:~A/index/node-fulltext/~A/~A" host port key value))
+ (:status-handlers
+ ((200 (decode-json-from-string (map 'string #'code-char body))))))
+
+(defun traverse (&key (host *neo4j-host*) (port *neo4j-port*) node-id (return-type :node)
+ (max-depth 1) (order :depth-first) uniqueness relationships prune-evaluator
+ return-filter)
+ (let ((uri (format nil "http://~A:~A/node/~A/traverse/~A"
+ host port node-id (string-downcase (symbol-name return-type))))
+ (json (with-output-to-string (s)
+ (format s "{\"order\":\"~A\"," (case order
+ (:depth-first "depth first")
+ (:breadth-first "breadth first")))
+ (if uniqueness (format s "\"uniqueness\":\"~A\"," uniqueness))
+ (if relationships (format s "\"relationships\":~A,"
+ (encode-json-to-string relationships)))
+ (if prune-evaluator (format s "\"prune evaluator\":~A,"
+ (encode-json-to-string prune-evaluator)))
+ (if return-filter (format s "\"return filter\":~A,"
+ (encode-json-to-string return-filter)))
+ (format s "\"max depth\":~A}" max-depth))))
+ (multiple-value-bind (status body) (do-neo4j-query uri :post :json json)
+ (case status
+ (200 (decode-json-from-string (map 'string #'code-char body)))
+ (404 (error 'node-not-found-error :uri uri))
+ (otherwise
+ (error 'unknown-return-type-error :status status :uri uri :property nil))))))
+
Added: utilities.lisp
==============================================================================
--- (empty file)
+++ utilities.lisp Tue May 18 15:43:41 2010
@@ -0,0 +1 @@
+(in-package #:cl-neo4j)
More information about the cl-neo4j-cvs
mailing list