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    [doc res path]
063    (reduce 
064     (fn [doc m] (store-result doc m path))
065     doc res))