 (defn filter-spec [f spec]
   (filter f (partition 2 spec)))
 
-(defn contains-option? [attr kw]
-  (contains? (attr-options attr) kw))
+(defn contains-options? [attr & keywords]
+  (let [options (attr-options attr)]
+    (reduce #(and %1 (contains? options %2))
+            keywords)))
 
 (defn required-attrs [spec]
   (filter-spec #(= :required (:type (attr-options %)))

               spec))

(defn pair-attrs [spec]
  (filter-spec #(and (not (contains-option? % :enums))
                     (not (contains-option? % :type)))
               spec))

(defn attrs-with-defaults [spec]
  (filter-spec #(contains-option? % :default)
              spec))

(defn pair-field? [spec token]
  (some #(if (= token (attr-name %)) %) (pair-attrs spec)))

(defn enum-field? [spec token]
  (some #(if (contains? (:enums (attr-options %)) token) %)
        (enum-attrs spec)))

(defn enum-name [spec val]
  (attr-name (get-enum val spec)))

(defn parse-pair [spec parsed key [value & tail]]
  [(assoc parsed key value) tail])

(defn parse-items [spec items]
  (map #(parse-item spec %) items))

(def demographic-spec
     [:name {:type :required}
      :age  {:type :required}
      :gender {:enums #{:male :female}}])

(def dick ["dick" 1 :male  ])
(def jane ["jane" 1 :female])

(assert (= (parse-item demographic-spec dick)
           {:gender :male, :age 1, :name "dick"}))

(assert (= (parse-items demographic-spec [dick jane])
           [{:gender :male, :age 1, :name "dick"}
            {:gender :female, :age 1, :name "jane"}]))


