Skip to content

Instantly share code, notes, and snippets.

@ponzao
Created September 26, 2016 16:35
Show Gist options
  • Select an option

  • Save ponzao/6476b7df853402ac744222ab18efe1fa to your computer and use it in GitHub Desktop.

Select an option

Save ponzao/6476b7df853402ac744222ab18efe1fa to your computer and use it in GitHub Desktop.

Revisions

  1. ponzao created this gist Sep 26, 2016.
    113 changes: 113 additions & 0 deletions vice.clj
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,113 @@
    (ns vice
    (:require [clojure.spec :as s]
    [clj-time.core :as t]
    [clj-time.format :as tf])
    (:import [org.joda.time DateMidnight DateTime]
    [java.util UUID]
    [clojure.lang Keyword]
    [java.math BigInteger]
    [java.net URL URI]
    [java.util.regex Pattern]))

    (def invalid :clojure.spec/invalid)

    (defmulti coerce-uuid class)
    (defmethod coerce-uuid java.util.UUID [u] u)
    (defmethod coerce-uuid java.lang.String [s]
    (UUID/fromString s))
    (defmethod coerce-uuid :default [& args]
    invalid)

    (def ->uuid
    (s/conformer coerce-uuid))

    (defmulti coerce-boolean class)
    (defmethod coerce-boolean java.lang.Boolean [b] b)
    (defmethod coerce-boolean java.lang.String [s]
    (case s
    "true" true
    "false" false
    invalid))
    (defmethod coerce-boolean :default [& args]
    invalid)

    (defmulti coerce-bigint class)
    (defmethod coerce-bigint java.math.BigInteger [n] n)
    (defmethod coerce-bigint java.lang.String [s]
    (try
    (bigint s)
    (catch NumberFormatException e
    invalid)))
    (defmethod coerce-bigint :default [& args]
    invalid)

    (def ->uuid
    (s/conformer coerce-uuid))

    (def ->boolean
    (s/conformer coerce-boolean))

    (def ->bigint
    (s/conformer coerce-bigint))

    (def data
    (let [id (str (UUID/randomUUID))]
    {:vice/post.id id
    :vice/post.title "How to Spec"
    :vice/post.published? "true"
    :vice/post.price "10000"
    :vice/post.content (URI/create (str "http://www.google.com/"))
    :vice/post.authors [{:vice/author.id (str (UUID/randomUUID))
    :vice/author.name "Vesa Marttila"}]}))

    (s/def :vice/author.id ->uuid)
    (s/def :vice/author.name string?)

    (s/def :vice/author
    (s/keys :req [:vice/author.id
    :vice/author.name]))

    (s/def :vice/post.id ->uuid)
    (s/def :vice/post.title string?)
    (s/def :vice/post.published? ->boolean)
    (s/def :vice/post.price ->bigint)

    (defn content-resolver
    [entity]
    (if (uri? entity)
    (.substring (slurp entity) 0 50)
    entity))

    (def ->resolve
    (s/conformer content-resolver))

    (def ->upper-case
    (s/conformer
    (fn [s]
    (.toUpperCase s))))

    (s/def :vice/post.content
    (s/and ->resolve
    ->upper-case))

    (s/def :vice/post.authors (s/coll-of :vice/author))

    (s/def :vice/post
    (s/keys :req [:vice/post.id
    :vice/post.title
    :vice/post.published?
    :vice/post.price
    :vice/post.content
    :vice/post.authors]))

    (clojure.pprint/pprint
    (s/conform :vice/post data))
    ; =>
    ; #:vice{:post.id #uuid "364f316b-5452-407f-b0cf-ef377f5bacb4",
    ; :post.title "How to Spec",
    ; :post.published? true,
    ; :post.price 10000N,
    ; :post.content "<!DOCTYPE HTML><HTML ITEMSCOPE=\"\" ITEMTYPE=\"HTTP:/",
    ; :post.authors
    ; [#:vice{:author.id #uuid "6a4daf4a-749b-44e1-860a-a63cb9d69837",
    ; :author.name "Vesa Marttila"}]}