-
Notifications
You must be signed in to change notification settings - Fork 1
/
conversion.clj
122 lines (98 loc) · 3.3 KB
/
conversion.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
(ns tupelo.neo4j.conversion
"Neo4j communicates with Java via custom data structures. Those are
can contain lists, maps, nulls, values or combinations. This namespace
has functions to help to convert between Neo4j's data structures and Clojure"
(:require
[clojure.walk :as walk])
(:import
[clojure.lang ISeq]
[java.util Map List]
[org.neo4j.driver Values]
[org.neo4j.driver.internal
InternalNode InternalResult
InternalPair
InternalRecord
InternalRelationship]
[org.neo4j.driver.internal.value
BooleanValue
ListValue
MapValue
NodeValue
NullValue
NumberValueAdapter
ObjectValueAdapter
RelationshipValue
StringValue]
))
(defn clj->neo4j
"## Convert to Neo4j
Neo4j expects a map of key/value pairs. The map has to be constructed as
a `Values.parameters` instance which expects the values as an `Object` array"
[val]
(->> val
walk/stringify-keys
(mapcat identity)
(into-array Object)
Values/parameters))
;---------------------------------------------------------------------------------------------------
(defmulti neo4j->clj
"## Convert from Neo4j
Neo4j returns results as `StatementResults`, which contain `InternalRecords`,
which contain `InternalPairs` etc. Therefore, this multimethod recursively
calls itself with the extracted content of the data structure until we have
values, lists or `nil`."
class)
(defn walk-transform [m]
(let [f (fn [[k v]]
[(if (string? k)
(keyword k)
k)
(neo4j->clj v)])]
; applies only to maps
(walk/postwalk
(fn [x]
(if (or (map? x) (instance? Map x))
(with-meta (into {} (map f x))
(meta x))
x))
m)))
(defmethod neo4j->clj InternalResult [record]
(map neo4j->clj (iterator-seq record)))
(defmethod neo4j->clj InternalRecord [record]
(apply merge (map neo4j->clj (.fields record))))
(defmethod neo4j->clj InternalPair [^InternalPair pair]
(let [k (-> pair .key keyword)
v (-> pair .value neo4j->clj)]
{k v}))
(defmethod neo4j->clj NodeValue [^NodeValue value]
(walk-transform (into {} (.asMap value))))
(defmethod neo4j->clj RelationshipValue [^RelationshipValue value]
(walk-transform (into {} (.asMap (.asRelationship value)))))
(defmethod neo4j->clj StringValue [^StringValue v]
(.asObject v))
(defmethod neo4j->clj ObjectValueAdapter [^ObjectValueAdapter v]
(.asObject v))
(defmethod neo4j->clj BooleanValue [^BooleanValue v]
(.asBoolean v))
(defmethod neo4j->clj NumberValueAdapter [^NumberValueAdapter v]
(.asNumber v))
(defmethod neo4j->clj ListValue [^ListValue l]
(map neo4j->clj (into [] (.asList l))))
(defmethod neo4j->clj ISeq [^ISeq s]
(map neo4j->clj s))
(defmethod neo4j->clj MapValue [^MapValue l]
(walk-transform (into {} (.asMap l))))
(defmethod neo4j->clj InternalNode [^InternalNode n]
(with-meta (walk-transform (into {} (.asMap n)))
{:labels (.labels n)
:id (.id n)}))
(defmethod neo4j->clj InternalRelationship [^InternalRelationship r]
(neo4j->clj (.asValue r)))
(defmethod neo4j->clj NullValue [n]
nil)
(defmethod neo4j->clj List [^List l]
(map neo4j->clj (into [] l)))
(defmethod neo4j->clj Map [^Map m]
(walk-transform (into {} m)))
(defmethod neo4j->clj :default [x]
x)