Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

v0.1.0

  • Loading branch information...
commit 2462e73a52a3e8c509bbda69a32a6370774a7c9b 1 parent 5d635f0
@eduardoejp authored
Showing with 134 additions and 57 deletions.
  1. +6 −8 project.clj
  2. +128 −49 src/clj_blueprints.clj
View
14 project.clj
@@ -1,18 +1,16 @@
-(defproject clj-blueprints "0.1.0-SNAPSHOT"
- :description "Wrapper for the TinkerPop Blueprints API for Graph DBMSs. It supports version 0.7 of the Blueprints API."
+(defproject clj-blueprints "0.1.0"
+ :description "Wrapper for the TinkerPop Blueprints API for Graph DBMSs. It supports version 1.1 of the Blueprints API."
:url "https://github.com/eduardoejp/clj-blueprints"
:license {:name "Eclipse Public License - v 1.0"
:url "http://www.eclipse.org/legal/epl-v10.html"
:distribution :repo
:comments "same as Clojure"}
- :dependencies [[org.clojure/clojure "1.2.0"]
- [org.clojure/clojure-contrib "1.2.0"]
- [com.tinkerpop.blueprints/blueprints-core "0.7"]
- [active-vars "0.1.0"]]
- :dev-dependencies [[org.clojars.rayne/autodoc "0.8.0-SNAPSHOT"]]
+ :plugins [[lein-autodoc "0.9.0"]]
+ :dependencies [[org.clojure/clojure "1.3.0"]
+ [com.tinkerpop.blueprints/blueprints-core "1.1"]]
:repositories {"tinkerpop" "http://tinkerpop.com/maven2"}
:autodoc {:name "clj-blueprints"
- :description "Wrapper for the TinkerPop Blueprints API for Graph DBMSs. It supports version 0.7 of the Blueprints API."
+ :description "Wrapper for the TinkerPop Blueprints API for Graph DBMSs. It supports version 1.1 of the Blueprints API."
:copyright "Copyright 2011 Eduardo Julian"
:web-src-dir "http://github.com/eduardoejp/clj-blueprints/blob/"
:web-home "http://eduardoejp.github.com/clj-blueprints/"
View
177 src/clj_blueprints.clj
@@ -10,15 +10,20 @@
;;
;; You must not remove this notice, or any other, from this software.
-(ns clj-blueprints
- "Wrapper for the TinkerPop Blueprints API for Graph DBMSs. It supports version 0.7 of the Blueprints API."
- (:import (com.tinkerpop.blueprints.pgm Graph Element Vertex Edge TransactionalGraph TransactionalGraph$Mode TransactionalGraph$Conclusion IndexableGraph Index Index$Type)
+(ns ^{:doc "Wrapper for the TinkerPop Blueprints API for Graph DBMSs. It supports version 1.1 of the Blueprints API."
+ :author "Eduardo Julián"}
+ clj-blueprints
+ (:import (com.tinkerpop.blueprints.pgm Graph Element Vertex Edge TransactionalGraph TransactionalGraph$Conclusion IndexableGraph Index Index$Type)
(com.tinkerpop.blueprints.pgm.impls.readonly ReadOnlyGraph ReadOnlyEdge ReadOnlyVertex ReadOnlyIndex)
- (com.tinkerpop.blueprints.pgm.util.graphml GraphMigrator GraphMLReader GraphMLWriter))
- (:use active-vars))
+ (com.tinkerpop.blueprints.pgm.util.graphml GraphMigrator GraphMLReader GraphMLWriter)
+ (com.tinkerpop.blueprints.pgm.util.json GraphSONReader GraphSONWriter)
+ (com.tinkerpop.blueprints.pgm.impls.event EventGraph)
+ (com.tinkerpop.blueprints.pgm.impls.event.listener GraphChangedListener)
+ (com.tinkerpop.blueprints.pgm.impls.tg TinkerGraph))
+ (:require [clojure.walk :as walk]))
-(def #^{:doc "This dynamic var holds the currently used database."}
- *db* nil)
+(def ^{:doc "This dynamic var holds the currently used database."}
+ ^:dynamic *db* nil)
; Element fns
(defn get-id "" [elem] (.getId elem))
@@ -26,15 +31,17 @@
(defn pget "Retrieves an element's property (given as a keyword)."
[elem prop]
(let [v (.getProperty elem (name prop))]
- (if (and (string? v)
- (= (first v) \:))
+ (if (and (string? v) (= (first v) \:))
(keyword (subs v 1))
- v))
- )
+ v)))
(defn passoc! "Assocs an element's property (given as a keyword)."
- ([elem prop v] (.setProperty elem (name prop) (if (keyword? v) (str v) v)) elem)
- ([elem prop v & kvs] (.setProperty elem (name prop) (if (keyword? v) (str v) v)) (apply passoc! elem kvs)))
+ ([elem prop v]
+ (if (keyword? v)
+ (recur elem prop (str v))
+ (do (.setProperty elem (name prop) (if (keyword? v) (str v) v))
+ elem)))
+ ([elem prop v & kvs] (passoc! elem prop v) (apply passoc! elem kvs)))
(defn pdissoc! "Dissocs an element's property (given as a keyword)."
[elem prop] (.removeProperty elem (name prop)) elem)
@@ -52,25 +59,16 @@
(def +tx-success+ TransactionalGraph$Conclusion/SUCCESS)
(def +tx-failure+ TransactionalGraph$Conclusion/FAILURE)
-(defn set-transaction-mode!
- "Sets the transaction mode as either :automatic or :manual."
- [mode]
- (let [mode (case mode :automatic TransactionalGraph$Mode/AUTOMATIC, :manual TransactionalGraph$Mode/MANUAL)]
- (.setTransactionMode *db* mode)))
-
-(defactive *transaction-mode*
- "[ActiveVar] The transaction mode. Can be either :automatic or :manual."
- (get {TransactionalGraph$Mode/AUTOMATIC :automatic, TransactionalGraph$Mode/MANUAL :manual}
- (.getTransactionMode *db*)))
-
(defmacro with-tx "Evaluates the given forms inside a transaction."
[& forms]
- `(if (= :manual @*transaction-mode*)
- (do (.startTransaction *db*)
- (try
- (let [r# (do ~@forms)] (.stopTransaction *db* +tx-success+) r#)
- (catch Exception ~'e (.stopTransaction *db* +tx-failure+) (.printStackStrace ~'e))))
- (throw (Exception. "Transaction mode must be MANUAL."))))
+ `(do (.startTransaction *db*)
+ (try
+ (let [r# (do ~@forms)] (.stopTransaction *db* +tx-success+) r#)
+ (catch Exception ~'e (.stopTransaction *db* +tx-failure+) (throw ~'e)))))
+
+(defn get-max-buffer-size "Get Max Transaction Buffer Size" [] (.getMaxBufferSize *db*))
+(defn set-max-buffer-size "Set Max Transaction Buffer Size" [buffer-size] (.setMaxBufferSize *db* buffer-size))
+(defn current-buffer-size "Current Transaction Buffer Size" [] (.getCurrentBufferSize *db*))
; Graph fns
(defmacro with-db "Evaluates the given forms with the given Graph DB bound to *db*."
@@ -78,17 +76,19 @@
`(binding [*db* ~graph-db] ~@forms))
(defn set-db! "Given a Graph instance (like OrientGraph, TinkerGraph, etc), sets it as the global DB."
- [graph-db] (alter-var-root #'*db* (fn [_] graph-db)) graph-db)
+ [graph-db]
+ (alter-var-root #'*db* (fn [_] graph-db))
+ graph-db)
(defn shutdown! "" [] (.shutdown *db*))
(defn clear! "Clears *db* of all nodes and edges." [] (.clear *db*))
-(defactive *vertices* "[ActiveVar] All the vertices."
- (.getVertices *db*))
+(defn get-vertices "Returns all the vertices."
+ [] (.getVertices *db*))
-(defactive *edges* "[ActiveVar] All the edges."
- (.getEdges *db*))
+(defn get-edges "Returns all the edges."
+ [] (.getEdges *db*))
(defn load-vertex "" [id] (.getVertex *db* id))
@@ -102,8 +102,9 @@
(defn link!
"Adds an edge between vertex1 and vertex 2 given a vector like [label props-map]. The label must be a keyword and props-map can be nil."
- ([id v1 [label props] v2] (let [e (.addEdge *db* id v1 v2 (name label))] (when props (apply passoc! e (interleave (map name (keys props)) (vals props)))) e))
- ([v1 lab-props v2] (link! nil v1 lab-props v2)))
+ ([id v1 label props v2] (let [e (.addEdge *db* id v1 v2 (name label))] (when props (apply passoc! e (apply concat (seq props)))) e))
+ ([v1 label props v2] (link! nil v1 label props v2))
+ ([v1 label v2] (link! nil v1 label nil v2)))
(defn remove! "Removes either a vertex or an edge from the Graph."
[elem]
@@ -155,7 +156,8 @@
(defn get-index "" [kname class] (let [class (case class :vertices Index/VERTICES, :edges Index/EDGES)] (.getIndex *db* (name kname) class)))
-(defactive *indices* "[ActiveVar] The indices of the graph." (.getIndices *db*))
+(defn get-indices "Returns the indices of the graph."
+ [] (.getIndices *db*))
(defn drop-index! "" [kname] (.dropIndex *db* (name kname)))
@@ -165,13 +167,21 @@
(defn index-type
"Returns whether the given index is :automatic or :manual."
- [i] (get {Index$Type/AUTOMATIC :automatic, Index$Type/MANUAL :manual} (.getIndexType i)))
+ [i]
+ (get {Index$Type/AUTOMATIC :automatic, Index$Type/MANUAL :manual}
+ (.getIndexType i)))
-(defn iget "Gets an element from an index." [index key val] (.get index (name key) val))
+(defn iget "Gets an element from an index."
+ [index key val]
+ (.get index (name key) val))
-(defn iput "Puts an element from an index." [index key val element] (.put index key val element))
+(defn iput "Puts an element from an index."
+ [index key val element]
+ (.put index key val element))
-(defn iremove "Removes an element from an index." [index key val element] (.remove index key val element))
+(defn iremove "Removes an element from an index."
+ [index key val element]
+ (.remove index key val element))
; Read-Only
(defn as-read-only
@@ -187,10 +197,79 @@ When called with one argument (Graph, Vertex, Edge or Index), it returns a read
; GraphML
(defn migrate-graph! "" [g1 g2] (GraphMigrator/migrateGraph g1 g2))
-(defn read-graph! "Reads GraphML formatted data into the current *db*"
- ([input-stream] (GraphMLReader/inputGraph *db* input-stream))
- ([input-stream buffer-size vertex-id edge-id edge-label] (GraphMLReader/inputGraph *db* input-stream buffer-size vertex-id edge-id edge-label)))
-
-(defn write-graph! "Writes GraphML formatted data from the current *db*"
- ([out-stream] (GraphMLWriter/outputGraph *db* out-stream))
- ([out-stream vertex-key-types edge-key-types] (GraphMLWriter/outputGraph *db* out-stream vertex-key-types edge-key-types)))
+(defn read-graph-ml!
+ "Reads GraphML formatted data into the current *db*.
+All the keys are optional."
+ [input-stream & {:keys [buffer-size vertex-id-key edge-id-key edge-label-key]}]
+ (let [gr (doto (GraphMLReader. *db*)
+ (.setVertexIdKey (name vertex-id-key))
+ (.setEdgeIdKey (name edge-id-key))
+ (.setEdgeLabelKey (name edge-label-key)))]
+ (if buffer-size
+ (.inputGraph gr input-stream buffer-size)
+ (.inputGraph gr input-stream))))
+
+(defn write-graph-ml!
+ "Writes GraphML formatted data from the current *db*.
+All the keys are optional."
+ [out-stream & {:keys [vertex-types edge-types normalize]}]
+ (doto (GraphMLWriter. *db*)
+ (.setVertexKeyTypes (walk/stringify-keys vertex-types))
+ (.setEdgeKeyTypes (walk/stringify-keys vertex-types))
+ (.setNormalize (boolean normalize))
+ (.outputGraph out-stream)))
+
+; GraphSON
+(defn read-graph-json! "Reads GraphSON formatted data into the current *db*."
+ ([input-stream] (GraphSONReader/inputGraph *db* input-stream))
+ ([input-stream buffer-size] (GraphSONReader/inputGraph *db* input-stream buffer-size)))
+
+(defn write-graph-json!
+ "Writes GraphSON formatted data from the current *db*.
+All the keys are optional."
+ [out-stream & {:keys [vertex-props edge-props show-types]}]
+ (GraphSONWriter/outputGraph *db* out-stream (map name edge-props) (map name vertex-props) (boolean show-types)))
+
+; Graph Event Listeners
+(defn graph-listener
+ "Creates a GraphChangedListener object by being passed a hash-map of functions to be used. All the functions are optional.
+Notation: vx = vertex; e = edge; k = key; v = val
+Signatures:
+edge-add [e]
+edge-prop-changed[e k v]
+edge-prop-remove [e k v]
+edge-remove [e]
+vertex-add [vx]
+vertex-prop-changed [vx k v]
+vertex-prop-remove [vx k v]
+vertex-remove [vx]
+graph-cleared []"
+ [{:keys [edge-add edge-prop-changed edge-prop-remove edge-remove
+ vertex-add vertex-prop-changed vertex-prop-remove vertex-remove
+ graph-cleared]}]
+ (reify GraphChangedListener
+ (edgeAdded [_ e] (if edge-add (edge-add e)))
+ (edgePropertyChanged [_ e k v] (if edge-prop-changed (edge-prop-changed e k v)))
+ (edgePropertyRemoved [_ e k v] (if edge-prop-remove (edge-prop-remove e k v)))
+ (edgeRemoved [_ e] (if edge-remove (edge-remove e)))
+ (vertexAdded [_ vx] (if vertex-add (vertex-add vx)))
+ (vertexPropertyChanged [_ vx k v] (if vertex-prop-changed (vertex-prop-changed vx k v)))
+ (vertexPropertyRemoved [_ vx k v] (if vertex-prop-remove (vertex-prop-remove vx k v)))
+ (vertexRemoved [_ vx] (if vertex-remove (vertex-remove vx)))
+ (graphCleared [_] (if graph-cleared (graph-cleared)))
+ ))
+
+(defn event-graph "" [graph] (EventGraph. graph))
+
+(defn add-listener
+ "Adds a listener to an EventGraph.
+Can be passed either a GraphChangedListener or a hash-map that is compatible with graph-listener."
+ [g l] (.addListener g (if (map? l) (graph-listener l) l)))
+
+(defn get-raw-graph "Returns the graph wrapped by an EventGraph."
+ [eg] (.getRawGraph eg))
+
+; TinkerGraph
+(defn tinker-graph ""
+ ([] (TinkerGraph.))
+ ([dir] (TinkerGraph. dir)))
Please sign in to comment.
Something went wrong with that request. Please try again.