Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion project.clj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
:profiles {:dev {:dependencies [[org.clojure/clojure "1.8.0"]
[cheshire "5.5.0"]
[prismatic/schema "1.0.5"]
[com.datomic/datomic-free "0.9.5201" :exclusions [joda-time]]]
[com.datomic/datomic-free "0.9.5201" :exclusions [joda-time]]
[com.rpl/specter "0.13.0"]]
:plugins [[com.jakemccrary/lein-test-refresh "0.10.0"]]
:main lovii-schema.core}}
:plugins [[lein-cljfmt "0.5.1"]]
Expand Down
80 changes: 77 additions & 3 deletions src/lovii_schema/schema.clj
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
(ns lovii-schema.schema)
(ns lovii-schema.schema
(:require [com.rpl.specter :as sp])
(:use [com.rpl.specter.macros]))

(defn- add-namespace
[k n]
Expand Down Expand Up @@ -79,9 +81,55 @@
(apply-fns [cardinality-one])
(apply-fns fns)))))

(defn- expand-schema-variant
(defn expand-schema-variant2 [sch]
(let [; able to transform
;{:users {:schema/variant :users}} into
;{:users {:schema/variant {:variant :users}}}
vm [sp/MAP-VALS (sp/must :schema/variant) keyword?]
; able to transform
;{:users [{:schema/variant :users}}] into
;{:users [{:schema/variant {:variant :users}}]}
vv [sp/MAP-VALS sp/ALL (sp/must :schema/variant) keyword?]

fix (fn [v] {:variant v})]
(->> sch
(sp/transform vm fix)
(sp/transform vv fix))))

(defn expand-schema-abstract2 [sch]
(let [; able to transform
;{:users {:schema/abstract :users}} into
;{:users {:schema/abstract {:abstract :users}}}
vm [sp/MAP-VALS (sp/must :schema/abstract) keyword?]

; able to transform
;{:users [{:schema/abstract :users}}] into
;{:users [{:schema/abstract {:abstract :users}}]}
vv [sp/MAP-VALS sp/ALL (sp/must :schema/abstract) keyword?]

fix (fn [v] {:abstract v})]
(->> sch
(sp/transform vm fix)
(sp/transform vv fix))))

(comment
(sp/select [sp/MAP-VALS] {:a 1 :b 2} )
(sp/select [sp/ALL] {:a 1 :b 2} )
(sp/select [sp/VAL] {:a 1 :b 2 :c {:d 5} } )
(sp/select [sp/MAP-VALS keyword?] {:a :FF :b 2} )
(sp/select [:c] {:a 1 :b 2} )
(sp/transform [sp/MAP-VALS] (fn [m] :vv) {:a 5 :b 2})
(sp/transform [sp/MAP-VALS map? (sp/must :e) ] (fn [m] :vv) {:a 5 :b 2 :c {:d 5} })
(sp/transform (sp/select [sp/MAP-VALS {:a 5 :b 2} ]) inc {:a 5 :b 2})
(sp/transform (sp/select [sp/ALL sp/LAST] {:a 5 :b 2} ) inc {:a 5 :b 2})
(sp/transform (sp/select [sp/VAL] {:a 5 :b 2} ) (fn [m] {:c 9}) {:a 5 :b 2})
(sp/transform [sp/ALL :a] dec [{:a 2 :b 3} {:a 1} {:a 4}])
)


(defn expand-schema-variant
[m]
(let [variant (-> m :schema/variant)
(let [variant (-> m :schema/variant)
abstract (-> m :schema/abstract)
variant-map (if (keyword? variant)
{:schema/variant {:variant variant}}
Expand Down Expand Up @@ -157,3 +205,29 @@
expand-enums
expand-abstracts
(vec)))


(defn parse-schema2
[lo-schema & fns]
(let [sch (-> lo-schema
expand-schema-variant2
expand-schema-abstract2)]
(->> sch
(reduce (fn [res [_ sch]]
(when res
(cond (vector? sch)
(when-some [abstract (first (filter #(-> % :schema/abstract :abstract) sch))]
(some->> (filter #(-> % :schema/variant :variant) sch)
(map #(merge abstract %))
(map (expand-variant-keys lo-schema fns))
(concat res)))

(map? sch)
(let [variant (-> sch :schema/variant :variant)]
(some->> (merge sch {:schema/abstract {:abstract variant}})
((expand-variant-keys lo-schema fns))
(conj res))))))
[])
expand-enums
expand-abstracts
(vec))))
111 changes: 111 additions & 0 deletions test/lovii_schema/schema_test.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
(ns lovii-schema.schema-test
(:require [clojure.test :refer :all]
[lovii-schema.core :refer :all]
[lovii-schema.schema :as ls]
[datomic.api :as d]
[schema.core :as s]
[schema.coerce :as coerce]
[lovii-schema.validation :as v]
[lovii-schema.data :as ldata]
[cheshire.core :as json]
[com.rpl.specter :as sp])
(:import [java.util UUID])
(:use [com.rpl.specter.macros]))

(def example
{:users {:schema/variant {:variant :users}
:uuid {:type :uuid :unique :identity :required true}
:name {:type :string :label "Full Name"}
:tags {:type :ref :variants [:tags/set] :cardinality :one}
:social {:type :ref :variants [:social] :cardinality :has-many}}

:social {:schema/variant {:variant :social :required [#{:social/all-nothing-1 :social/all-nothing-2}]}
:uuid {:type :uuid :unique :identity :required true}
:all-nothing-1 {:type :string}
:all-nothing-2 {:type :string}
:service {:type :enum :values {:twitter "Twitter"
:google "Google"
:facebook "Facebook"
:linkedin "LinkedIn"
:icq "ICQ"
:myspace "MySpace"}
:label "Social Service"}
:account {:type :string :index true :label "Social Account"}}

:tags [{:schema/abstract {:abstract :tags :required [[:uuid]]}
:uuid {:type :uuid :unique :identity
;; set above as part of abstract requireds
; :required true
}
:service {:type :enum :values :social/service}
:one-or-more1 {:type :string}
:one-or-more2 {:type :string}
:label {:type :string :required false
:min-length 2
:max-length 60
:regex ".*3.*"
:index true
:label "Label"}
:inactive {:type :boolean :required false :index true :default false}}

;; Test the one or more required with :tag instead of setting to :required true
{:schema/variant {:variant :tags/set :required [[:one-or-more1 :one-or-more2]]}
:tags {:type :ref :required false
:cardinality :has-many
:variants [:tags/leaf]}}
{:schema/variant {:variant :tags/leaf}
:tag {:type :string :required true :index true}}]})

(def variant-pre
{
:users1 {:schema/variant :users1} ; should be expanded
:users2 {:schema/variant {:variant :users2}}
:users3 [{:schema/variant :users3}] ; should be expanded
:users4 [{:schema/variant {:variant :users4}} ]
})

(def variant-after
{:users1 {:schema/variant {:variant :users1}}
:users2 {:schema/variant {:variant :users2}}
:users3 [{:schema/variant {:variant :users3}}]
:users4 [{:schema/variant {:variant :users4}}]})

(deftest expand-schema-variant-test
(testing "expand"
(is (= variant-after
(ls/expand-schema-variant2 variant-pre))))
(testing "parse"
(let [p1 (ls/parse-schema variant-pre)
p2 (ls/parse-schema2 variant-pre)]
(is (map? p1))
(is (= p1 p2))
(is (= p1 variant-after)))))

(def abstract-pre
{:users1 {:schema/abstract :users1} ; should be expanded
:users2 {:schema/abstract {:abstract :users2}}
:users3 [{:schema/abstract :users3}] ; should be expanded
:users4 [{:schema/abstract {:abstract :users4}}]})

(def abstract-after
{:users1 {:schema/abstract {:abstract :users1}}
:users2 {:schema/abstract {:abstract :users2}}
:users3 [{:schema/abstract {:abstract :users3}}]
:users4 [{:schema/abstract {:abstract :users4}}]})

(deftest expand-schema-abstract-test
(testing "expand"
(is (= abstract-after
(ls/expand-schema-abstract2 abstract-pre))))
(testing "parse"
(let [p1 (ls/parse-schema abstract-pre)
p2 (ls/parse-schema2 abstract-pre)]
(is (map? p1))
(is (= p1 p2))
(is (= p1 abstract-after)))))

(comment
(ls/parse-schema variant-pre)
(ls/parse-schema2 variant-pre)
(ls/parse-schema example)
(ls/parse-schema2 example))