1575 lines
126 KiB
HTML
1575 lines
126 KiB
HTML
<html>
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|
<link rel="stylesheet" href="../../../coverage.css"/> <title> dog_and_duck/quack/picky/objects.clj </title>
|
|
</head>
|
|
<body>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
001 (ns dog-and-duck.quack.picky.objects
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
002 (:require [clojure.data.json :as json]
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
003 [clojure.set :refer [union]]
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
004 [dog-and-duck.quack.picky.constants :refer [actor-types
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
005 noun-types
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
006 re-rfc5646]]
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
007 [dog-and-duck.quack.picky.control-variables :refer [*reify-refs*]]
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
008 [dog-and-duck.quack.picky.time :refer [date-time-property-or-fault
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
009 xsd-date-time?
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
010 xsd-duration?]]
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
011 [dog-and-duck.quack.picky.utils :refer [concat-non-empty
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
012 cond-make-fault-object
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
013 has-activity-type?
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
014 has-context?
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
015 has-type?
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
016 has-type-or-fault
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
017 make-fault-object
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
018 nil-if-empty
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
019 object-or-uri?
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
020 truthy?
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
021 xsd-non-negative-integer?]]
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
022 [taoensso.timbre :refer [info warn]])
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
023 (:import [java.io FileNotFoundException]
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
024 [java.net URI URISyntaxException]))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
025
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
026 (defn- xsd-float?
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
027 [pv]
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 10 forms covered">
|
|
028 (or (integer? pv) (float? pv)))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
029
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
030 ;;; Copyright (C) Simon Brooke, 2022
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
031
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
032 ;;; This program is free software; you can redistribute it and/or
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
033 ;;; modify it under the terms of the GNU General Public License
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
034 ;;; as published by the Free Software Foundation; either version 2
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
035 ;;; of the License, or (at your option) any later version.
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
036
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
037 ;;; This program is distributed in the hope that it will be useful,
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
038 ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
039 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
040 ;;; GNU General Public License for more details.
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
041
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
042 ;;; You should have received a copy of the GNU General Public License
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
043 ;;; along with this program; if not, write to the Free Software
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
044 ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
045
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
046 (def object-expected-properties
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
047 "Requirements of properties of object, cribbed from
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
048 https://www.w3.org/TR/activitystreams-vocabulary/#properties
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
049
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
050 Note the following sub-key value types:
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
051
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
052 * `:collection` opposite of `:functional`: if true, value should be a
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
053 collection (in the Clojure sense), not a single object;
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
054 * `:functional` if true, value should be a single object; if false, may
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
055 be a single object or a sequence of objects, but each must pass
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
056 validation checks;
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
057 * `:if-invalid` a sequence of two keywords, first indicating severity,
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
058 second being a message key;
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
059 * `:if-missing` a sequence of two keywords, first indicating severity,
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
060 second being a message key;
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
061 * `:required` a boolean, or a function of one argument returning a
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
062 boolean, in which case the function will be applied to the object
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
063 having the property;
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
064 * `:validator` a function of one argument returning a boolean, which will
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
065 be applied to the value or values of the identified property."
|
|
</span><br/>
|
|
<span class="covered" title="68 out of 68 forms covered">
|
|
066 {:accuracy {:functional false
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
067 :if-invalid [:must :invalid-number]
|
|
</span><br/>
|
|
<span class="partial" title="1 out of 14 forms covered">
|
|
068 :validator (fn [pv] (and (xsd-float? pv)
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 3 forms covered">
|
|
069 (>= pv 0)
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 1 forms covered">
|
|
070 (<= pv 100)))}
|
|
</span><br/>
|
|
<span class="covered" title="7 out of 7 forms covered">
|
|
071 :actor {:functional false
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
072 :if-invalid [:must :invalid-actor]
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
073 :if-missing [:must :no-actor]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
074 :required has-activity-type?
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
075 :validator object-or-uri?}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
076 :altitude {:functional false
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
077 :if-invalid [:must :invalid-number]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
078 :validator xsd-float?}
|
|
</span><br/>
|
|
<span class="covered" title="7 out of 7 forms covered">
|
|
079 :anyOf {:collection true
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
080 :functional false
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
081 ;; a Question should have a `:oneOf` or `:anyOf`, but at this layer
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
082 ;; that's hard to check.
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
083 :if-invalid [:must :invalid-option]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
084 :validator object-or-uri?}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
085 :attachment {:functional false
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
086 :if-invalid [:must :invalid-attachment]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
087 :validator object-or-uri?}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
088 :attributedTo {:functional false
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
089 :if-invalid [:must :invalid-attribution]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
090 :validator object-or-uri?}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
091 :audience {:functional false
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
092 :if-invalid [:must :invalid-audience]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
093 :validator object-or-uri?}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
094 :bcc {:functional false
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
095 :if-invalid [:must :invalid-audience] ;; do we need a separate message for bcc, cc, etc?
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
096 :validator object-or-uri?}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
097 :cc {:functional false
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
098 :if-invalid [:must :invalid-audience] ;; do we need a separate message for bcc, cc, etc?
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
099 :validator object-or-uri?}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
100 :closed {:functional false
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
101 :if-invalid [:must :invalid-closed]
|
|
</span><br/>
|
|
<span class="partial" title="1 out of 15 forms covered">
|
|
102 :validator (fn [pv] (truthy? (or (object-or-uri? pv)
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 3 forms covered">
|
|
103 (xsd-date-time? pv)
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 4 forms covered">
|
|
104 (#{"true" "false"} pv))))}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
105 :content {:functional false
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
106 :if-invalid [:must :invalid-content]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
107 :validator string?}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
108 :context {:functional false
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
109 :if-invalid [:must :invalid-context]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
110 :validator object-or-uri?}
|
|
</span><br/>
|
|
<span class="covered" title="7 out of 7 forms covered">
|
|
111 :current {:functional true
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
112 :if-missing [:minor :paged-collection-no-current]
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
113 :if-invalid [:must :paged-collection-invalid-current]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
114 :required (fn [x] ;; if an object is a collection which has pages,
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
115 ;; it ought to have a `:current` page. But
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
116 ;; 1. it isn't required to, and
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
117 ;; 2. there's no certain way of telling that it
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
118 ;; does have pages - although if it has a
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
119 ;; `:first`, then it is.
|
|
</span><br/>
|
|
<span class="covered" title="6 out of 6 forms covered">
|
|
120 (and
|
|
</span><br/>
|
|
<span class="covered" title="10 out of 10 forms covered">
|
|
121 (or (has-type? x "Collection")
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
122 (has-type? x "OrderedCollection"))
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
123 (:first x)))
|
|
</span><br/>
|
|
<span class="partial" title="1 out of 7 forms covered">
|
|
124 :validator (fn [pv] (object-or-uri? pv #{"CollectionPage"
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
125 "OrderedCollectionPage"}))}
|
|
</span><br/>
|
|
<span class="covered" title="7 out of 7 forms covered">
|
|
126 :deleted {:functional true
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
127 :if-missing [:minor :tombstone-missing-deleted]
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
128 :if-invalid [:must :invalid-deleted]
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
129 :required (fn [x] (has-type? x "Tombstone"))
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
130 :validator xsd-date-time?}
|
|
</span><br/>
|
|
<span class="covered" title="6 out of 6 forms covered">
|
|
131 :describes {:functional true
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
132 :required (fn [x] (has-type? x "Profile"))
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
133 :if-invalid [:must :invalid-describes]
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
134 ;; TODO: actually the spec says this MUST be an object and
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
135 ;; not a URI, which it doesn't say anywhere else, but this seems
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
136 ;; to make no sense?
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
137 :validator object-or-uri?}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
138 :duration {:functional false
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
139 :if-invalid [:must :invalid-duration]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
140 :validator xsd-duration?}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
141 :endTime {:functional true
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
142 :if-invalid [:must :invalid-date-time]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
143 :validator xsd-date-time?}
|
|
</span><br/>
|
|
<span class="covered" title="7 out of 7 forms covered">
|
|
144 :first {:functional true
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
145 :if-missing [:minor :paged-collection-no-first]
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
146 :if-invalid [:must :paged-collection-invalid-first]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
147 :required (fn [x] ;; if an object is a collection which has pages,
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
148 ;; it ought to have a `:first` page. But
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
149 ;; 1. it isn't required to, and
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
150 ;; 2. there's no certain way of telling that it
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
151 ;; does have pages - although if it has a
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
152 ;; `:last`, then it is.
|
|
</span><br/>
|
|
<span class="covered" title="6 out of 6 forms covered">
|
|
153 (and
|
|
</span><br/>
|
|
<span class="covered" title="12 out of 12 forms covered">
|
|
154 (or (has-type? x "Collection")
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
155 (has-type? x "OrderedCollection"))
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
156 (:last x)))
|
|
</span><br/>
|
|
<span class="covered" title="7 out of 7 forms covered">
|
|
157 :validator (fn [pv] (object-or-uri? pv #{"CollectionPage"
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
158 "OrderedCollectionPage"}))}
|
|
</span><br/>
|
|
<span class="covered" title="7 out of 7 forms covered">
|
|
159 :formerType {:functional false
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
160 :if-missing [:minor :tombstone-missing-former-type]
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
161 :if-invalid [:must :invalid-former-type]
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
162 :required (fn [x] (has-type? x "Tombstone"))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
163 ;; The narrative of the spec says this should be an `Object`,
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
164 ;; but in all the provided examples it's a string.
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
165 :validator string?}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
166 :generator {:functional false
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
167 :if-invalid [:must :invalid-generator]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
168 :validator object-or-uri?}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
169 :height {:functional false
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
170 :if-invalid [:must :invalid-non-negative]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
171 :validator xsd-non-negative-integer?}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
172 :href {:functional false
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
173 :if-invalid [:must :invalid-href]
|
|
</span><br/>
|
|
<span class="partial" title="1 out of 7 forms covered">
|
|
174 :validator (fn [pv] (try (uri? (URI. pv))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
175 (catch URISyntaxException _ false)))}
|
|
</span><br/>
|
|
<span class="partial" title="3 out of 9 forms covered">
|
|
176 :hreflang {:validator (fn [pv] (truthy? (re-matches re-rfc5646 pv)))}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
177 :icon {:functional false
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
178 :if-invalid [:must :invalid-icon]
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
179 ;; an icon is also expected to have a 1:1 aspect ratio, but that's
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
180 ;; too much detail at this level of verification
|
|
</span><br/>
|
|
<span class="partial" title="1 out of 5 forms covered">
|
|
181 :validator (fn [pv] (object-or-uri? pv "Image"))}
|
|
</span><br/>
|
|
<span class="covered" title="6 out of 6 forms covered">
|
|
182 :id {:functional true
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
183 :if-missing [:minor :no-id-transient]
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
184 :if-invalid [:must :invalid-id]
|
|
</span><br/>
|
|
<span class="covered" title="7 out of 7 forms covered">
|
|
185 :validator (fn [pv] (try (uri? (URI. pv))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
186 (catch URISyntaxException _ false)))}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
187 :image {:functional false
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
188 :if-invalid [:must :invalid-image]
|
|
</span><br/>
|
|
<span class="partial" title="1 out of 5 forms covered">
|
|
189 :validator (fn [pv] (object-or-uri? pv "Image"))}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
190 :inReplyTo {:functional false
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
191 :if-invalid [:must :invalid-in-reply-to]
|
|
</span><br/>
|
|
<span class="partial" title="1 out of 5 forms covered">
|
|
192 :validator (fn [pv] (object-or-uri? pv noun-types))}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
193 :instrument {:functional false
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
194 :if-invalid [:must :invalid-instrument]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
195 :validator object-or-uri?}
|
|
</span><br/>
|
|
<span class="covered" title="9 out of 9 forms covered">
|
|
196 :items {:collection true
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
197 :functional false
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
198 :if-invalid [:must :invalid-items]
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
199 :if-missing [:must :no-items-or-pages]
|
|
</span><br/>
|
|
<span class="partial" title="19 out of 22 forms covered">
|
|
200 :required (fn [x] (or (has-type? x "CollectionPage")
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
201 (and (has-type? x "Collection")
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
202 ;; if it's a collection and has pages,
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
203 ;; it doesn't need items.
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
204 (not (:current x))
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
205 (not (:first x))
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
206 (not (:last x)))))
|
|
</span><br/>
|
|
<span class="partial" title="11 out of 12 forms covered">
|
|
207 :validator (fn [pv] (and (coll? pv) (every? object-or-uri? pv)))}
|
|
</span><br/>
|
|
<span class="covered" title="7 out of 7 forms covered">
|
|
208 :last {:functional true
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
209 :if-missing [:minor :paged-collection-no-last]
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
210 :if-invalid [:must :paged-collection-invalid-last]
|
|
</span><br/>
|
|
<span class="partial" title="6 out of 9 forms covered">
|
|
211 :required (fn [x] (if (and
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
212 (string? x)
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 4 forms covered">
|
|
213 (try (uri? (URI. x))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
214 (catch URISyntaxException _ false)))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
215 true
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
216 ;; if an object is a collection which has pages,
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
217 ;; it ought to have a `:last` page. But
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
218 ;; 1. it isn't required to, and
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
219 ;; 2. there's no certain way of telling that it
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
220 ;; does have pages - although if it has a
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
221 ;; `:first`, then it is.
|
|
</span><br/>
|
|
<span class="covered" title="6 out of 6 forms covered">
|
|
222 (and
|
|
</span><br/>
|
|
<span class="covered" title="6 out of 6 forms covered">
|
|
223 (has-type? x #{"Collection"
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
224 "OrderedCollection"})
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
225 (:first x))))
|
|
</span><br/>
|
|
<span class="covered" title="7 out of 7 forms covered">
|
|
226 :validator (fn [pv] (object-or-uri? pv #{"CollectionPage"
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
227 "OrderedCollectionPage"}))}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
228 :latitude {:functional true
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
229 :if-invalid [:must :invalid-latitude]
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
230 ;; The XSD spec says this is an IEEE 754-2008, and the IEEE
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
231 ;; wants US$104 for me to find out what that is. So I don't
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
232 ;; strictly know that an integer is valid here.
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
233 :validator xsd-float?}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
234 :location {:functional false
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
235 :if-invalid [:must :invalid-location]
|
|
</span><br/>
|
|
<span class="partial" title="1 out of 6 forms covered">
|
|
236 :validator (fn [pv] (object-or-uri? pv #{"Place"}))}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
237 :longitude {:functional true
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
238 :if-invalid [:must :invalid-longitude]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
239 :validator xsd-float?}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
240 :mediaType {:functional true
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
241 :if-invalid [:must :invalid-mime-type]
|
|
</span><br/>
|
|
<span class="partial" title="1 out of 7 forms covered">
|
|
242 :validator (fn [pv] (truthy? (re-matches #"\w+/[-.\w]+(?:\+[-.\w]+)?" pv)))}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
243 :name {:functional false
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
244 :if-invalid [:must :invalid-name]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
245 :validator string?}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
246 :next {:functional true
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
247 :if-invalid [:must :invalid-next-page]
|
|
</span><br/>
|
|
<span class="covered" title="7 out of 7 forms covered">
|
|
248 :validator (fn [pv] (object-or-uri? pv #{"CollectionPage"
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
249 "OrderedCollectionPage"}))}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
250 :object {:functional false
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
251 :if-invalid [:must :invalid-direct-object]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
252 :validator object-or-uri?}
|
|
</span><br/>
|
|
<span class="covered" title="7 out of 7 forms covered">
|
|
253 :oneOf {:collection true
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
254 :functional false
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
255 ;; a Question should have a `:oneOf` ot `:anyOf`, but at this layer
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
256 ;; that's hard to check.
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
257 :if-invalid [:must :invalid-option]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
258 :validator object-or-uri?}
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
259
|
|
</span><br/>
|
|
<span class="covered" title="9 out of 9 forms covered">
|
|
260 :orderedItems {:collection true
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
261 :functional false
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
262 :if-invalid [:must :invalid-items]
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
263 :if-missing [:must :no-items-or-pages]
|
|
</span><br/>
|
|
<span class="partial" title="20 out of 22 forms covered">
|
|
264 :required (fn [x] (or (has-type? x "OrderedCollectionPage")
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
265 (and (has-type? x "OrderedCollection")
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
266 ;; if it's a collection and has pages,
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
267 ;; it doesn't need items.
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
268 (not (:current x))
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
269 (not (:first x))
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 4 forms covered">
|
|
270 (not (:last x)))))
|
|
</span><br/>
|
|
<span class="partial" title="11 out of 12 forms covered">
|
|
271 :validator (fn [pv] (and (coll? pv) (every? object-or-uri? pv)))}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
272 :origin {:functional false
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
273 :if-invalid [:must :invalid-origin]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
274 :validator object-or-uri?}
|
|
</span><br/>
|
|
<span class="covered" title="7 out of 7 forms covered">
|
|
275 :partOf {:functional true
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
276 :if-missing [:must :missing-part-of]
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
277 :if-invalid [:must :invalid-part-of]
|
|
</span><br/>
|
|
<span class="covered" title="7 out of 7 forms covered">
|
|
278 :required (fn [x] (object-or-uri? x #{"CollectionPage"
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
279 "OrderedCollectionPage"}))
|
|
</span><br/>
|
|
<span class="covered" title="7 out of 7 forms covered">
|
|
280 :validator (fn [pv] (object-or-uri? pv #{"Collection"
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
281 "OrderedCollection"}))}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
282 :prev {:functional true
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
283 :if-invalid [:must :invalid-prior-page]
|
|
</span><br/>
|
|
<span class="covered" title="7 out of 7 forms covered">
|
|
284 :validator (fn [pv] (object-or-uri? pv #{"CollectionPage"
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
285 "OrderedCollectionPage"}))}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
286 :preview {:functional false
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
287 :if-invalid [:must :invalid-preview]
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
288 ;; probably likely to be an Image or Video, but that isn't stated.
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
289 :validator object-or-uri?}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
290 :published {:functional true
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
291 :if-invalid [:must :invalid-date-time]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
292 :validator xsd-date-time?}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
293 :replies {:functional true
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
294 :if-invalid [:must :invalid-replies]
|
|
</span><br/>
|
|
<span class="partial" title="1 out of 7 forms covered">
|
|
295 :validator (fn [pv] (object-or-uri? pv #{"Collection"
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
296 "OrderedCollection"}))}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
297 :radius {:functional true
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
298 :if-invalid [:must :invalid-positive-number]
|
|
</span><br/>
|
|
<span class="partial" title="1 out of 11 forms covered">
|
|
299 :validator (fn [pv] (and (xsd-float? pv) (> pv 0)))}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
300 :rel {:functional false
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
301 :if-invalid [:must :invalid-link-relation]
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
302 ;; TODO: this is not really good enough.
|
|
</span><br/>
|
|
<span class="partial" title="1 out of 7 forms covered">
|
|
303 :validator (fn [pv] (truthy? (re-matches #"[a-zA-A0-9_\-\.\:\?/\\]*" pv)))}
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
304 :relationship {;; this exists in the spec, but it doesn't seem to be required and it's
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
305 ;; extremely hazily specified.
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
306 }
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
307 :result {:functional false
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
308 :if-invalid [:must :invalid-result]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
309 :validator object-or-uri?}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
310 :startIndex {:functional true
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
311 :if-invalid [:must :invalid-start-index]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
312 :validator xsd-non-negative-integer?}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
313 :start-time {:functional true
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
314 :if-invalid [:must :invalid-date-time]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
315 :validator xsd-date-time?}
|
|
</span><br/>
|
|
<span class="covered" title="7 out of 7 forms covered">
|
|
316 :subject {:functional true
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
317 :if-invalid [:must :invalid-subject]
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
318 :if-missing [:minor :no-relationship-subject]
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
319 :required (fn [x] (has-type? x "Relationship"))
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
320 :validator object-or-uri?}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
321 :summary {:functional false
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
322 :if-invalid [:must :invalid-summary]
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
323 ;; TODO: HTML formatting is allowed, but other forms of formatting
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
324 ;; are not. Can this be validated?
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
325 :validator string?}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
326 :tag {:functional false
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
327 :if-invalid [:must :invalid-tag]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
328 :validator object-or-uri?}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
329 :target {:functional false
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
330 :if-invalid [:must :invalid-target]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
331 :validator object-or-uri?}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
332 :to {:functional false
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
333 :if-invalid [:must :invalid-to]
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
334 :validator (fn [pv] (object-or-uri? pv actor-types))}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
335 :totalItems {:functional true
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
336 :if-invalid [:must :invalid-total-items]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
337 :validator xsd-non-negative-integer?}
|
|
</span><br/>
|
|
<span class="covered" title="6 out of 6 forms covered">
|
|
338 :type {:functional false
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
339 :if-missing [:minor :no-type]
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
340 :if-invalid [:must :invalid-type]
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
341 ;; strictly, it's an `anyURI`, but realistically these are not checkable.
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
342 :validator string?}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
343 :units {:functional true
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
344 :if-invalid [:must :invalid-units]
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
345 ;; the narrative says that `anyURI`, but actually unless it's a recognised
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
346 ;; unit the property is useless. These are the units explicitly specified.
|
|
</span><br/>
|
|
<span class="partial" title="1 out of 10 forms covered">
|
|
347 :validator (fn [pv] (#{"cm" "feet" "inches" "km" "m" "miles"} pv))}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
348 :updated {:functional true
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
349 :if-invalid [:must :invalid-updated]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
350 :validator xsd-date-time?}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
351 :url {:functional false
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
352 :if-invalid [:must :invalid-url-property]
|
|
</span><br/>
|
|
<span class="partial" title="1 out of 5 forms covered">
|
|
353 :validator (fn [pv] (object-or-uri? pv "Link"))}
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
354 :width {:functional true
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
355 :if-invalid [:must :invalid-width]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
356 :validator xsd-non-negative-integer?}})
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
357
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
358 (defn check-property-required [obj prop clause]
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
359 (let [required (:required clause)
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
360 [severity token] (:if-missing clause)]
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
361 (when required
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
362 (when
|
|
</span><br/>
|
|
<span class="covered" title="15 out of 15 forms covered">
|
|
363 (and (apply required (list obj)) (not (obj prop)))
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
364 (make-fault-object severity token)))))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
365
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
366 (defn check-property-valid
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
367 [obj prop clause]
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
368 ;; (info "obj" obj "prop" prop "clause" clause)
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
369 (let [val (obj prop)
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
370 validator (:validator clause)
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
371 [severity token] (:if-invalid clause)]
|
|
</span><br/>
|
|
<span class="covered" title="8 out of 8 forms covered">
|
|
372 (when (and val validator)
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
373 (cond-make-fault-object
|
|
</span><br/>
|
|
<span class="covered" title="6 out of 6 forms covered">
|
|
374 (apply validator (list val))
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
375 severity token))))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
376
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
377 (defn check-property [obj prop]
|
|
</span><br/>
|
|
<span class="covered" title="14 out of 14 forms covered">
|
|
378 (assert (map? obj))
|
|
</span><br/>
|
|
<span class="partial" title="5 out of 14 forms covered">
|
|
379 (assert (keyword? prop))
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
380 (let [clause (object-expected-properties prop)]
|
|
</span><br/>
|
|
<span class="partial" title="7 out of 8 forms covered">
|
|
381 (nil-if-empty
|
|
</span><br/>
|
|
<span class="covered" title="9 out of 9 forms covered">
|
|
382 (remove nil?
|
|
</span><br/>
|
|
<span class="covered" title="6 out of 6 forms covered">
|
|
383 (list
|
|
</span><br/>
|
|
<span class="covered" title="15 out of 15 forms covered">
|
|
384 (check-property-required obj prop clause)
|
|
</span><br/>
|
|
<span class="covered" title="15 out of 15 forms covered">
|
|
385 (check-property-valid obj prop clause))))))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
386
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
387 (defn properties-faults
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
388 "Return a lost of faults found on properties of the object `x`, or
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
389 `nil` if none are."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
390 [x]
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
391 (apply
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
392 concat-non-empty
|
|
</span><br/>
|
|
<span class="covered" title="6 out of 6 forms covered">
|
|
393 (let [props (set (keys x))
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
394 required (set
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
395 (filter
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
396 #((object-expected-properties %) :required)
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
397 (keys object-expected-properties)))]
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
398 (map
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
399 (fn [p] (check-property x p))
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
400 (union props required)))))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
401
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
402 (defn object-faults
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
403 "Return a list of faults found in object `x`, or `nil` if none are.
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
404
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
405 If `expected-type` is also passed, verify that `x` has `expected-type`.
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
406 `expected-type` may be passed as a string or as a set of strings. Detailed
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
407 verification of the particular features of types is not done here."
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
408
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
409 ;; TODO: many more properties which are nor required, nevertheless have required
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
410 ;; property TYPES as detailed in
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
411 ;; https://www.w3.org/TR/activitystreams-vocabulary/#properties
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
412 ;; if these properties are present, these types should be checked.
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
413 ([x]
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
414 (concat-non-empty
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
415 (remove empty?
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
416 (list
|
|
</span><br/>
|
|
<span class="covered" title="6 out of 6 forms covered">
|
|
417 (when-not (map? x)
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
418 (make-fault-object :critical :not-an-object))
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
419 (when-not
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
420 (has-context? x)
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
421 (make-fault-object :should :no-context))
|
|
</span><br/>
|
|
<span class="covered" title="6 out of 6 forms covered">
|
|
422 (when-not (:type x)
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
423 (make-fault-object :minor :no-type))
|
|
</span><br/>
|
|
<span class="covered" title="14 out of 14 forms covered">
|
|
424 (when-not (and (map? x) (contains? x :id))
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
425 (make-fault-object :minor :no-id-transient))))
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
426 (properties-faults x)))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
427 ([x expected-type]
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
428 (concat-non-empty
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
429 (object-faults x)
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
430 (when expected-type
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
431 (list
|
|
</span><br/>
|
|
<span class="covered" title="6 out of 6 forms covered">
|
|
432 (has-type-or-fault x expected-type :critical :unexpected-type))))))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
433
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
434 (def maybe-reify
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
435 "If `*reify-refs*` is `true`, return the object at this `target` URI.
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
436 Returns `nil` if
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
437
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
438 1. `*reify-refs*` is false;
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
439 2. the object was not found;
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
440 3. access to the object was not permitted.
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
441
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
442 Consequently, use with care."
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
443 (memoize
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
444 (fn [target]
|
|
</span><br/>
|
|
<span class="partial" title="4 out of 6 forms covered">
|
|
445 (try (let [uri (URI. target)]
|
|
</span><br/>
|
|
<span class="partial" title="2 out of 3 forms covered">
|
|
446 (when *reify-refs*
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 5 forms covered">
|
|
447 (json/read-str (slurp uri))))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
448 (catch URISyntaxException _
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 18 forms covered">
|
|
449 (warn "Reification target" target "was not a valid URI.")
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
450 nil)
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
451 (catch FileNotFoundException _
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 18 forms covered">
|
|
452 (warn "Reification target" target "was not found.")
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
453 nil)))))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
454
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
455 (defn maybe-reify-or-faults
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
456 "If `*reify-refs*` is `true`, runs basic checks on the object at this
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
457 `target` URI, if it is found, or a list containing a fault object with
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
458 this `severity` and `token` if it is not."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
459 [value expected-type severity token]
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
460 (let [object (maybe-reify value)]
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
461 (cond object
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 4 forms covered">
|
|
462 (object-faults object expected-type)
|
|
</span><br/>
|
|
<span class="partial" title="1 out of 7 forms covered">
|
|
463 *reify-refs* (list (make-fault-object severity token)))))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
464
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
465 (defn object-reference-or-faults
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
466 "If this `value` is either
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
467
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
468 1. an object of `expected-type`;
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
469 2. a URI referencing an object of `expected-type`; or
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
470 3. a link object referencing an object of `expected-type`
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
471
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
472 and no faults are returned from validating the linked object, then return
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
473 `nil`; else return a sequence comprising a fault object with this `severity`
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
474 and `token`, prepended to the faults returned.
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
475
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
476 As with `has-type-or-fault` (q.v.), `expected-type` may be passed as a
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
477 string, as a set of strings, or `nil` (indicating the type of the
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
478 referenced object should not be checked).
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
479
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
480 **NOTE THAT** if `*reify-refs*` is `false`, referenced objects will not
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
481 actually be checked."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
482 [value expected-type severity token]
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
483 (let [faults (cond
|
|
</span><br/>
|
|
<span class="covered" title="9 out of 9 forms covered">
|
|
484 (string? value) (maybe-reify-or-faults value severity token expected-type)
|
|
</span><br/>
|
|
<span class="covered" title="8 out of 8 forms covered">
|
|
485 (map? value) (if (has-type? value "Link")
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 7 forms covered">
|
|
486 (cond
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
487 ;; if we were looking for a link and we've
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
488 ;; found a link, that's OK.
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 3 forms covered">
|
|
489 (= expected-type "Link") nil
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 10 forms covered">
|
|
490 (and (set? expected-type) (expected-type "Link")) nil
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 3 forms covered">
|
|
491 (nil? expected-type) nil
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
492 :else
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 2 forms covered">
|
|
493 (object-reference-or-faults
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 6 forms covered">
|
|
494 (:href value) expected-type severity token))
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
495 (object-faults value expected-type))
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
496 :else (throw
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
497 (ex-info
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
498 "Argument `value` was not an object or a link to an object"
|
|
</span><br/>
|
|
<span class="covered" title="8 out of 8 forms covered">
|
|
499 {:arguments {:value value}
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
500 :expected-type expected-type
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
501 :severity severity
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
502 :token token})))]
|
|
</span><br/>
|
|
<span class="covered" title="10 out of 10 forms covered">
|
|
503 (when faults (cons (make-fault-object severity token) faults))))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
504
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
505 (defn coll-object-reference-or-fault
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
506 "As object-reference-or-fault, except `value` argument may also be a list of
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
507 objects and/or object references."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
508 [value expected-type severity token]
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 3 forms covered">
|
|
509 (cond
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 9 forms covered">
|
|
510 (map? value) (object-reference-or-faults value expected-type severity token)
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 5 forms covered">
|
|
511 (coll? value) (concat-non-empty
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 3 forms covered">
|
|
512 (map
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 3 forms covered">
|
|
513 #(object-reference-or-faults
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 3 forms covered">
|
|
514 % expected-type severity token)
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 1 forms covered">
|
|
515 value))
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 1 forms covered">
|
|
516 :else (throw
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 3 forms covered">
|
|
517 (ex-info
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
518 "Argument `value` was not an object, a link to an object, nor a list of these."
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 8 forms covered">
|
|
519 {:arguments {:value value}
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 1 forms covered">
|
|
520 :expected-type expected-type
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 1 forms covered">
|
|
521 :severity severity
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 1 forms covered">
|
|
522 :token token}))))
|
|
</span><br/>
|
|
</body>
|
|
</html>
|