-
Notifications
You must be signed in to change notification settings - Fork 17
/
templater.clj
105 lines (87 loc) · 3.32 KB
/
templater.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
(ns grafter-2.rdf4j.templater
"Functions for converting tree's of turtle-like data into Linked
Data statements (triples/quads)."
(:require [grafter-2.rdf.protocols :as rdf])
(:import org.eclipse.rdf4j.model.URI))
(defn- valid-uri? [node]
(let [types [java.lang.String java.net.URL java.net.URI URI]]
(some (fn [t] (instance? t node)) types))
;; todo consider replacing with...
#_(or (= java.lang.String node) (satisfies? url/IURIable)))
(defn- is-literal? [node]
(not (or (nil? node)
(vector? node)
(map? node)
(set? node))))
(defn- valid-subject? [node]
(or (valid-uri? node)
(keyword? node)))
(defn- valid-predicate? [node]
(valid-uri? node))
(defn- valid-object? [object]
(if (or (valid-subject? object)
(is-literal? object))
true
(when (vector? object)
(cond
(= 2 (count object)) (let [[p o] object]
(and (valid-predicate? p)
(valid-object? o)))
(= 1 (count object)) (valid-object? (first object))))))
(defn- blank-node? [node]
(vector? node))
(defn- make-triples [subject predicate object-or-nested-subject]
(if (blank-node? object-or-nested-subject)
(let [bnode-resource (rdf/make-blank-node)
nested-pairs object-or-nested-subject]
(-> (mapcat (partial make-triples bnode-resource)
(map first nested-pairs)
(map second nested-pairs))
(conj (rdf/->Triple subject predicate bnode-resource))))
(let [object object-or-nested-subject]
[(rdf/->Triple subject predicate object)])))
(defn- expand-subj
"Takes a turtle like data structure, like that passed to graph and
converts it to triples."
[[subject & po-pairs]]
(mapcat (fn [[predicate object]]
(make-triples subject predicate object)) po-pairs))
(defn triplify
"Takes many turtle like structures and converts them to a lazy-seq
of grafter-2.rdf.protocols.IStatement's. Users should generally tend
to prefer to using graph to triplify."
[& subjects]
(mapcat expand-subj subjects))
(defn- quad
"Build a quad from a graph and a grafter-2.rdf.protocols/Triple."
[graph triple]
(rdf/->Quad (rdf/subject triple)
(rdf/predicate triple)
(rdf/object triple)
graph))
(defn graph
"Takes a graph-uri and a turtle-like template of vectors and returns
a lazy-sequence of quad Statements. A turtle-like template should
be structured like this:
````
[subject [predicate1 object1]
[predicate2 object2]
[predicate3 [[blank-node-predicate blank-node-object]]]]
````
Subjects, predicates and objects can be strings, URI's or URL's,
whilst objects can also be literal types such as java numeric types,
Dates etc.
For convenience strings in these templates are assumed to be URI's
and are cast as such, as URI's are the most common type in linked
data. If you want an RDF string you should use the s function to
build one."
[graph-uri & triples]
(map (partial quad graph-uri)
(apply triplify triples)))
(defn add-properties
"Appends the key/value pairs from the supplied hash-map into the
triple-template form. Assumes it is given a vector representing a
single subject."
[triple-template hash-map]
(reduce conj triple-template
(mapcat vector hash-map)))