-
Notifications
You must be signed in to change notification settings - Fork 7
/
personae.clj
85 lines (70 loc) · 2.89 KB
/
personae.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
(ns com.yetanalytics.datasim.input.personae
"Personae input specs and parsing."
(:require [clojure.spec.alpha :as s]
[clojure.walk :as w]
[com.yetanalytics.datasim.xapi.actor :as agent]
[com.yetanalytics.datasim.util.errors :as errs]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Specs
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; We model the input personae as an xAPI group.
;; It can be anonymous, but the name may be used in some way.
;; If functionality is added to express further groupings we'll have to revise
;; this strategy.
;; Note: We cannot apply xapi-schema specs directly, as xapi-schema restrict
;; which properties can be in the Group, including the `role` property.
;; We still use `agent` and `group` spec namespaces from xapi-schema.
(s/def ::role string?)
(s/def ::agent
(s/keys :req-un [(or :agent/mbox
:agent/mbox_sha1sum
:agent/openid
:agent/account)]
:opt-un [:agent/name
:agent/objectType
::role]))
(s/def ::member
(s/coll-of ::agent :kind vector? :min-count 1 :gen-max 3))
(s/def ::group
(s/or :anonymous (s/keys :req-un [:group/objectType
(or :group/mbox
:group/mbox_sha1sum
:group/openid
:group/account)]
:opt-un [:group/name ::member])
:identified (s/keys :req-un [:group/objectType ::member]
:opt-un [:group/name])))
(defn- remove-nil-vals
"Remove nil values from an associative structure. Does not recurse."
[m]
(reduce-kv
(fn [m* k v] (cond-> m* (some? v) (assoc k v)))
{}
m))
;; An open-validating group spec, ignores extra nils
(s/def ::personae
(s/and (s/conformer remove-nil-vals)
(s/conformer w/keywordize-keys w/stringify-keys)
::group))
(defn- distinct-member-ids?
[personaes]
(let [member-ids (->> personaes
(map :member)
(apply concat)
(map agent/actor-ifi))]
(= (-> member-ids count)
(-> member-ids distinct count))))
(s/def ::personae-array
(s/and (s/every ::personae :min-count 1 :into [])
distinct-member-ids?))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Validation
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn validate-personae
[personae]
(some->> (s/explain-data ::personae personae)
(errs/explain-to-map-coll ::personae)))
(defn validate-personae-array
[personae-array]
(some->> (s/explain-data ::personae-array personae-array)
(errs/explain-to-map-coll ::personae-array)))