001 (ns vl-data-insert.core
002 ^{:author "wactbprot"
003 :doc "Inserts data into documents. This documents may be
004 calibration documents but also measurement docs."}
005 (:require [vl-data-insert.utils :as u]
006 [clojure.string :as string]))
007
008 ;;------------------------------
009 ;; data to doc
010 ;;------------------------------
011 (defn vector-vals
012 "Ensures that the values of `:Value`,`:SdValue` and `:N` are
013 vectors."
014 [m]
015 (-> m
016 (u/vector-if :Value)
017 (u/vector-if :SdValue)
018 (u/vector-if :N)))
019
020 (defn append-and-replace
021 "Append `:Value`, `:SdValue` and `:N` if present. Relaces `:Type` and
022 `:Unit`."
023 [struct {t :Type v :Value u :Unit n :N s :SdValue}]
024 (->
025 (-> struct
026 (u/replace-if :Type t)
027 (u/replace-if :Unit u))
028 (u/append-if :Value v)
029 (u/append-if :SdValue s)
030 (u/append-if :N n)))
031
032 (defn fit-in-struct
033 "Fits `m` into the given structure `s`. Function looks up the
034 `:Type` of `m`. If a structure with the same `:Type` exist
035 [[append-and-replace]] is called."
036 [s m]
037 (if-let [t (:Type m)]
038 (let [same-type? (fn [x] (= (:Type x) t))
039 idx? (fn [i x] (when (same-type? x) i))]
040 (if-let [idx (first (keep-indexed idx? s))]
041 (assoc s idx (append-and-replace (nth s idx) m))
042 (conj s (vector-vals m))))))
043
044 (defn store-result
045 "Stores the result map `m` in the given `doc`ument under `p`ath. If
046 `m` contains `:Type` and `:Value` `m` is [[fit-in-struct]] and the
047 structure `s` is assumed to be a `vector`. Other cases (e.g. merge
048 in `:AuxValues`) are straight
049 forward (see [[vl-data-insert/test/cmp/doc_test.clj]] for details)."
050 [doc m p]
051 (let [v (u/path->kw-vec p)]
052 (if (and (:Type m) (:Value m))
053 (if-let [s (get-in doc v)]
054 (assoc-in doc v (fit-in-struct s m))
055 (assoc-in doc v [(vector-vals m)]))
056 (if-let [s (get-in doc v)]
057 (assoc-in doc v (merge s m))
058 (assoc-in doc v m)))))
059
060 (defn store-results
061 "Takes a vector of maps. Calls `store-result` on each map.
062
063 Example:
064 ```clojure
065 (def p \"Calibration.Measurement.Values.Pressure\")
066 (def m {:Type \"a\"
067 :Unit \"b\"
068 :Value [0]
069 :SdValue [0]
070 :N [1]})
071
072 (def d {:Calibration
073 {:Measurement
074 {:Values
075 {:Pressure
076 [{:Type \"a\"
077 :Unit \"b\"
078 :Value [0]
079 :SdValue [0]
080 :N [1]}]}}}})
081
082 (store-results d [m m m m] p)
083
084 ;; =>
085 ;; {:Calibration
086 ;; {:Measurement
087 ;; {:Values
088 ;; {:Pressure
089 ;; [{:Type \"a\",
090 ;; :Unit \"b\",
091 ;; :Value [0 0 0 0 0],
092 ;; :SdValue [0 0 0 0 0],
093 ;; :N [1 1 1 1 1]}]}}}}
094 ```
095
096 "
097 [doc v p]
098 (reduce (fn [doc m] (store-result doc m p)) doc v))