CMR-8790: Added testing and combined some common functions. (#1780)

Co-authored-by: siwei xu <6532de1a8b5e90ff3cadd14b3ab551515d3f3d37@raytheon.com>

--- system-int-test/test/cmr/system_int_test/search/generic_association_test.clj
+++ system-int-test/test/cmr/system_int_test/search/generic_association_test.clj
@@ -40,6 +40,20 @@
         :connection-manager (system/conn-mgr)
         :throw-exceptions false}
        (client/request))))
+
+(defn- get-associations-and-details
+  "Get the search result and extract asssociations and association-details."
+  [concept-type-ext params concept-type-plural meta?]
+  (let [search-result (search-request concept-type-ext params)
+        search-body (json/parse-string (:body search-result) true)
+        associations (if meta?
+                       (get-in (first (:items search-body)) [:meta :associations concept-type-plural])
+                       (get-in (first (:items search-body)) [:associations concept-type-plural]))
+        association-details (if meta?
+                              (get-in (first (:items search-body)) [:meta :association-details concept-type-plural])
+                              (get-in (first (:items search-body)) [:association-details concept-type-plural]))]
+    {:associations associations
+     :association-details association-details}))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Tests
@@ -87,39 +101,31 @@
                                              {:concept-id coll2-concept-id :data "some data"}])
             _ (index/wait-until-indexed)
             ;;Search for the tool tl1, it should return the association
-            tl1-search-result (search-request "tools.umm_json" "native_id=tl1")
-            tl1-search-body (json/parse-string (:body tl1-search-result) true)
-            tl1-search-generic-associations (get-in (first (:items tl1-search-body)) [:meta :associations :collections])
-            tl1-search-generic-association-details (get-in (first (:items tl1-search-body)) [:meta :association-details :collections])
-
+            tl1-search-result (get-associations-and-details "tools.umm_json" "native_id=tl1" :collections true)
+
             ;;Search for the collection coll1, it should return the association
-            coll1-search-result (search-request "collections.umm-json" "entry_title=entry-title1")
-            coll1-search-body (json/parse-string (:body coll1-search-result) true)
-            coll1-search-generic-associations (get-in (first (:items coll1-search-body)) [:meta :associations :tools])
-            coll1-search-generic-association-details (get-in (first (:items coll1-search-body)) [:meta :association-details :tools])
+            coll1-search-result (get-associations-and-details "collections.umm-json" "entry_title=entry-title1" :tools true)

             ;;Search for the collection coll2, it should return the association
-            coll2-search-result (search-request "collections.umm-json" "entry_title=entry-title2")
-            coll2-search-body (json/parse-string (:body coll2-search-result) true)
-            coll2-search-generic-associations (get-in (first (:items coll2-search-body)) [:meta :associations :tools])]
+            coll2-search-result (get-associations-and-details "collections.umm-json" "entry_title=entry-title2" :tools true)]
         (is (= 200 (:status response1)))

         ;; Search for the tool tl1 returns the coll1 and coll2 as association
         (is (= (set [coll2-concept-id coll1-concept-id])
-               (set tl1-search-generic-associations)))
+               (set (:associations tl1-search-result))))
         (is (= (set [{:concept-id coll1-concept-id, :revision-id coll1-revision-id}
                      {:data "some data", :concept-id coll2-concept-id}])
-               (set tl1-search-generic-association-details)))
+               (set (:association-details tl1-search-result))))

         ;; Search for the collection coll1 returns the tl1 as association
         (is (= [tl1-concept-id]
-               coll1-search-generic-associations))
+               (:associations coll1-search-result)))
         (is (= [{:concept-id tl1-concept-id}]
-               coll1-search-generic-association-details))
+               (:association-details coll1-search-result)))

         ;; Search for the collection coll2 returns the tl1 as association
         (is (= [tl1-concept-id]
-               coll2-search-generic-associations))))
+               (:associations coll2-search-result)))))

     (testing "Associate tool with tool by concept-id and revision-ids"
       (let [response1 (association-util/generic-associate-by-concept-ids-revision-ids
@@ -135,14 +141,10 @@
             _ (index/wait-until-indexed)

             ;;Search for the tool tl1, it should return the association
-            tl1-search-result (search-request "tools.umm_json" "native_id=tl1")
-            tl1-search-body (json/parse-string (:body tl1-search-result) true)
-            tl1-search-generic-associations (get-in (first (:items tl1-search-body)) [:meta :associations :tools])
+            tl1-search-result (get-associations-and-details "tools.umm_json" "native_id=tl1" :tools true)

             ;;Search for the tool tl2, it should return the association
-            tl2-search-result (search-request "tools.umm_json" "native_id=tl2")
-            tl2-search-body (json/parse-string (:body tl2-search-result) true)
-            tl2-search-generic-associations (get-in (first (:items tl2-search-body)) [:meta :associations :tools])
+            tl2-search-result (get-associations-and-details "tools.umm_json" "native_id=tl2" :tools true)

             ;;Dissociate the association
             response4 (association-util/generic-dissociate-by-concept-ids-revision-ids
@@ -150,14 +152,10 @@
             _ (index/wait-until-indexed)

             ;;Search for the tool tl1 again, it should NOT return the association
-            tl1-search-result1 (search-request "tools.umm_json" "native_id=tl1")
-            tl1-search-body1 (json/parse-string (:body tl1-search-result1) true)
-            tl1-search-generic-associations1 (get-in (first (:items tl1-search-body1)) [:meta :associations :tools])
+            tl1-search-result1 (get-associations-and-details "tools.umm_json" "native_id=tl1" :tools true)

             ;;Search for the tool tl2 again, it should NOT return the association
-            tl2-search-result1 (search-request "tools.umm_json" "native_id=tl2")
-            tl2-search-body1 (json/parse-string (:body tl2-search-result1) true)
-            tl2-search-generic-associations1 (get-in (first (:items tl2-search-body1)) [:meta :associations :tools])]
+            tl2-search-result1 (get-associations-and-details "tools.umm_json" "native_id=tl2" :tools true)]
         ;; The first and second associations are successful
         (is (= 200 (:status response1) (:status response2)))

@@ -178,20 +176,20 @@

         ;; Search for the tool tl1 returns the tl2 as generic association
         (is (= [tl2-concept-id]
-               tl1-search-generic-associations))
+               (:associations tl1-search-result)))

         ;; Search for the tool tl2 returns the tl1 as generic association
         (is (= [tl1-concept-id]
-               tl2-search-generic-associations))
+               (:associations tl2-search-result)))

         ;; Dissociation of the association is successful
         (is (= 200 (:status response4)))

         ;; Search for the tool tl1 again doesn't return the tl2 as generic association
-        (is (= nil tl1-search-generic-associations1))
+        (is (= nil (:associations tl1-search-result1)))

         ;; Search for the tool tl2 again doesn't return the tl1 as generic association
-        (is (= nil tl2-search-generic-associations1))))
+        (is (= nil (:associations tl2-search-result1)))))
     (testing "Associate grid with tool by concept-id and revision-ids"
       (let [response1 (association-util/generic-associate-by-concept-ids-revision-ids
                        token grid-concept-id grid-revision-id [{:concept-id tl1-concept-id  :revision-id tl1-revision-id}])
@@ -206,15 +204,17 @@
             _ (index/wait-until-indexed)

             ;;Search for the grid, it should return the association
-            grid-search-result (search-request "grids.json" "name=Grid-A7-v1")
-            grid-search-body (json/parse-string (:body grid-search-result) true)
-            grid-search-generic-associations (get-in (first (:items grid-search-body)) [:associations :tools])
-            grid-search-generic-association-details (get-in (first (:items grid-search-body)) [:association-details :tools])
+            grid-search-result (get-associations-and-details "grids.json" "name=Grid-A7-v1" :tools false)

             ;;Search for the tool, it should return the association
-            tl1-search-result (search-request "tools.umm_json" "native_id=tl1")
-            tl1-search-body (json/parse-string (:body tl1-search-result) true)
-            tl1-search-generic-associations (get-in (first (:items tl1-search-body)) [:meta :associations :grids])
+            tl1-search-result (get-associations-and-details "tools.umm_json" "native_id=tl1" :grids true)
+
+            ;;Update the tool and the grid, search for the grid and the tool, it should return the association.
+            _ (gen-util/ingest-generic-document nil "PROV1" native-id :grid grid-doc :post)
+            _ (tool-util/ingest-tool-with-attrs {:native-id "tl1" :Name "tool1"})
+            grid-search-result-update (get-associations-and-details "grids.json" "name=Grid-A7-v1" :tools false)
+
+            tl1-search-result-update (get-associations-and-details "tools.umm_json" "native_id=tl1" :grids true)

             ;;Dissociate the association
             response4 (association-util/generic-dissociate-by-concept-ids-revision-ids
@@ -222,14 +222,10 @@
             _ (index/wait-until-indexed)

             ;;Search for the grid again, it should NOT return the association
-            grid-search-result1 (search-request "grids.json" "name=Grid-A7-v1")
-            grid-search-body1 (json/parse-string (:body grid-search-result1) true)
-            grid-search-generic-associations1 (get-in (first (:items grid-search-body1)) [:associations :tools])
+            grid-search-result1 (get-associations-and-details "grids.json" "name=Grid-A7-v1" :tools false)

             ;;Search for the tool again, it should NOT return the association
-            tl1-search-result1 (search-request "tools.umm_json" "native_id=tl1")
-            tl1-search-body1 (json/parse-string (:body tl1-search-result1) true)
-            tl1-search-generic-associations1 (get-in (first (:items tl1-search-body1)) [:meta :associations :grids])]
+            tl1-search-result1 (get-associations-and-details "tools.umm_json" "native_id=tl1" :grids true)]
         ;; The first and second associations are successful
         (is (= 200 (:status response1) (:status response2)))

@@ -250,22 +246,25 @@

         ;; Search for the grid returns the tl1 as generic association
         (is (= [tl1-concept-id]
-               grid-search-generic-associations))
+               (:associations grid-search-result)
+               (:associations grid-search-result-update)))
         (is (= [{:concept-id tl1-concept-id :revision-id tl1-revision-id}]
-               grid-search-generic-association-details))
+               (:association-details grid-search-result)
+               (:association-details grid-search-result-update)))

         ;; Search for the tool returns the grid as generic association
         (is (= [grid-concept-id]
-               tl1-search-generic-associations))
+               (:associations tl1-search-result)
+               (:associations tl1-search-result-update)))

         ;; Dissociation of the association is successful
         (is (= 200 (:status response4)))

         ;; Search for the grid again doesn't return the tl1 as generic association
-        (is (= nil grid-search-generic-associations1))
+        (is (= nil (:associations grid-search-result1)))

         ;; Search for the tool again doesn't return the grid as generic association
-        (is (= nil  tl1-search-generic-associations1))))))
+        (is (= nil  (:associations tl1-search-result1)))))))

 ;; Test that generic associations can be made between generic documents and services.
 ;; Also test the collection-service associations through the old association api and verify
@@ -311,36 +310,29 @@
                                              {:concept-id coll2-concept-id :data "some data"}])
             _ (index/wait-until-indexed)
             ;;Search for the service sv1, it should return the association
-            sv1-search-result (search-request "services.umm_json" "native_id=sv1")
-            sv1-search-body (json/parse-string (:body sv1-search-result) true)
-            sv1-search-generic-associations (get-in (first (:items sv1-search-body)) [:meta :associations :collections])
-            sv1-search-generic-association-details (get-in (first (:items sv1-search-body)) [:meta :association-details :collections])
-
+            sv1-search-result (get-associations-and-details "services.umm_json" "native_id=sv1" :collections true)
+
             ;;Search for the collection coll1, it should return the association
-            coll1-search-result (search-request "collections.umm-json" "entry_title=entry-title1")
-            coll1-search-body (json/parse-string (:body coll1-search-result) true)
-            coll1-search-generic-associations (get-in (first (:items coll1-search-body)) [:meta :associations :services])
+            coll1-search-result (get-associations-and-details "collections.umm-json" "entry_title=entry-title1" :services true)

             ;;Search for the collection coll2, it should return the association
-            coll2-search-result (search-request "collections.umm-json" "entry_title=entry-title2")
-            coll2-search-body (json/parse-string (:body coll2-search-result) true)
-            coll2-search-generic-associations (get-in (first (:items coll2-search-body)) [:meta :associations :services])]
+            coll2-search-result (get-associations-and-details "collections.umm-json" "entry_title=entry-title2" :services true)]
         (is (= 200 (:status response1)))

         ;; Search for the service sv1 returns the coll1 as association
         (is (= (set [coll2-concept-id coll1-concept-id])
-               (set sv1-search-generic-associations)))
+               (set (:associations sv1-search-result))))
         (is (= (set [{:concept-id coll1-concept-id, :revision-id coll1-revision-id}
                      {:data "some data", :concept-id coll2-concept-id}])
-               (set sv1-search-generic-association-details)))
+               (set (:association-details sv1-search-result))))

         ;; Search for the collection coll1 returns the sv1 as association
         (is (= [sv1-concept-id]
-               coll1-search-generic-associations))
+               (:associations coll1-search-result)))

         ;; Search for the collection coll2 returns the sv1 as association
         (is (= [sv1-concept-id]
-               coll2-search-generic-associations))))
+               (:associations coll2-search-result)))))

     (testing "Associate service with service by concept-id and revision-ids"
       (let [response1 (association-util/generic-associate-by-concept-ids-revision-ids
@@ -356,14 +348,10 @@
             _ (index/wait-until-indexed)

             ;;Search for the service sv1, it should return the association
-            sv1-search-result (search-request "services.umm_json" "native_id=sv1")
-            sv1-search-body (json/parse-string (:body sv1-search-result) true)
-            sv1-search-generic-associations (get-in (first (:items sv1-search-body)) [:meta :associations :services])
+            sv1-search-result (get-associations-and-details "services.umm_json" "native_id=sv1" :services true)

             ;;Search for the service sv2, it should return the association
-            sv2-search-result (search-request "services.umm_json" "native_id=sv2")
-            sv2-search-body (json/parse-string (:body sv2-search-result) true)
-            sv2-search-generic-associations (get-in (first (:items sv2-search-body)) [:meta :associations :services])
+            sv2-search-result (get-associations-and-details "services.umm_json" "native_id=sv2" :services true)

             ;;Dissociate the association
             response4 (association-util/generic-dissociate-by-concept-ids-revision-ids
@@ -371,14 +359,10 @@
             _ (index/wait-until-indexed)

             ;;Search for the service sv1 again, it should NOT return the association
-            sv1-search-result1 (search-request "services.umm_json" "native_id=sv1")
-            sv1-search-body1 (json/parse-string (:body sv1-search-result1) true)
-            sv1-search-generic-associations1 (get-in (first (:items sv1-search-body1)) [:meta :associations :services])
+            sv1-search-result1 (get-associations-and-details "services.umm_json" "native_id=sv1" :services true)

             ;;Search for the service sv2 again, it should NOT return the association
-            sv2-search-result1 (search-request "services.umm_json" "native_id=sv2")
-            sv2-search-body1 (json/parse-string (:body sv2-search-result1) true)
-            sv2-search-generic-associations1 (get-in (first (:items sv2-search-body1)) [:meta :associations :services])]
+            sv2-search-result1 (get-associations-and-details "services.umm_json" "native_id=sv2" :services true)]
         ;; The first and second associations are successful
         (is (= 200 (:status response1) (:status response2)))

@@ -399,20 +383,20 @@

         ;; Search for the service sv1 returns the sv2 as generic association
         (is (= [sv2-concept-id]
-               sv1-search-generic-associations))
+               (:associations sv1-search-result)))

         ;; Search for the service sv2 returns the sv1 as generic association
         (is (= [sv1-concept-id]
-               sv2-search-generic-associations))
+               (:associations sv2-search-result)))

         ;; Dissociation of the association is successful
         (is (= 200 (:status response4)))

         ;; Search for the service sv1 again doesn't return the sv2 as generic association
-        (is (= nil sv1-search-generic-associations1))
+        (is (= nil (:associations sv1-search-result1)))

         ;; Search for the service sv2 again doesn't return the sv1 as generic association
-        (is (= nil sv2-search-generic-associations1))))
+        (is (= nil (:associations sv2-search-result1)))))
     (testing "Associate grid with service by concept-id and revision-ids"
       (let [response1 (association-util/generic-associate-by-concept-ids-revision-ids
                        token grid-concept-id grid-revision-id [{:concept-id sv1-concept-id  :revision-id sv1-revision-id}])
@@ -427,14 +411,10 @@
             _ (index/wait-until-indexed)

             ;;Search for the grid, it should return the association
-            grid-search-result (search-request "grids.json" "name=Grid-A7-v1")
-            grid-search-body (json/parse-string (:body grid-search-result) true)
-            grid-search-generic-associations (get-in (first (:items grid-search-body)) [:associations :services])
+            grid-search-result (get-associations-and-details "grids.json" "name=Grid-A7-v1" :services false)

             ;;Search for the service, it should return the association
-            sv1-search-result (search-request "services.umm_json" "native_id=sv1")
-            sv1-search-body (json/parse-string (:body sv1-search-result) true)
-            sv1-search-generic-associations (get-in (first (:items sv1-search-body)) [:meta :associations :grids])
+            sv1-search-result (get-associations-and-details "services.umm_json" "native_id=sv1" :grids true)

             ;;Dissociate the association
             response4 (association-util/generic-dissociate-by-concept-ids-revision-ids
@@ -442,14 +422,10 @@
             _ (index/wait-until-indexed)

             ;;Search for the grid again, it should NOT return the association
-            grid-search-result1 (search-request "grids.json" "name=Grid-A7-v1")
-            grid-search-body1 (json/parse-string (:body grid-search-result1) true)
-            grid-search-generic-associations1 (get-in (first (:items grid-search-body1)) [:associations :services])
+            grid-search-result1 (get-associations-and-details "grids.json" "name=Grid-A7-v1" :services false)

             ;;Search for the service again, it should NOT return the association
-            sv1-search-result1 (search-request "services.umm_json" "native_id=sv1")
-            sv1-search-body1 (json/parse-string (:body sv1-search-result1) true)
-            sv1-search-generic-associations1 (get-in (first (:items sv1-search-body1)) [:meta :associations :grids])]
+            sv1-search-result1 (get-associations-and-details "services.umm_json" "native_id=sv1" :grids true)]
         ;; The first and second associations are successful
         (is (= 200 (:status response1) (:status response2)))

@@ -470,20 +446,20 @@

         ;; Search for the grid returns the sv1 as generic association
         (is (= [sv1-concept-id]
-               grid-search-generic-associations))
+               (:associations grid-search-result)))

         ;; Search for the service returns the grid as generic association
         (is (= [grid-concept-id]
-               sv1-search-generic-associations))
+               (:associations sv1-search-result)))

         ;; Dissociation of the association is successful
         (is (= 200 (:status response4)))

         ;; Search for the grid again doesn't return the sv1 as generic association
-        (is (= nil grid-search-generic-associations1))
+        (is (= nil (:associations grid-search-result1)))

         ;; Search for the service again doesn't return the grid as generic association
-        (is (= nil  sv1-search-generic-associations1))))))
+        (is (= nil  (:associations sv1-search-result1)))))))

 ;; Test that generic associations can be made between generic documents and variables.
 (deftest test-variable-and-generic-association
@@ -549,18 +525,12 @@
             _ (index/wait-until-indexed)

             ;;Search for the variable var1, it should return the association
-            var1-search-result (search-request "variables.umm_json" "native_id=var1")
-            var1-search-body (json/parse-string (:body var1-search-result) true)
-            var1-search-generic-associations (get-in (first (:items var1-search-body)) [:associations :variables])
-            var1-search-generic-associations-in-meta (get-in (first (:items var1-search-body)) [:meta :associations :variables])
-            var1-search-generic-association-details-in-meta (get-in (first (:items var1-search-body)) [:meta :association-details :variables])
+            var1-search-result (get-associations-and-details "variables.umm_json" "native_id=var1" :variables false)
+            var1-search-result-in-meta (get-associations-and-details "variables.umm_json" "native_id=var1" :variables true)

             ;;Search for the variable var2, it should return the association
-            var2-search-result (search-request "variables.umm_json" "native_id=var2")
-            var2-search-body (json/parse-string (:body var2-search-result) true)
-            var2-search-generic-associations (get-in (first (:items var2-search-body)) [:associations :variables])
-            var2-search-generic-associations-in-meta (get-in (first (:items var2-search-body)) [:meta :associations :variables])
-            var2-search-generic-association-details-in-meta (get-in (first (:items var2-search-body)) [:meta :association-details :variables])
+            var2-search-result (get-associations-and-details "variables.umm_json" "native_id=var2" :variables false)
+            var2-search-result-in-meta (get-associations-and-details "variables.umm_json" "native_id=var2" :variables true)

             ;;Dissociate the association
             response4 (association-util/generic-dissociate-by-concept-ids-revision-ids
@@ -568,14 +538,10 @@
             _ (index/wait-until-indexed)

             ;;Search for the variable var1 again, it should NOT return the association
-            var1-search-result1 (search-request "variables.umm_json" "native_id=var1")
-            var1-search-body1 (json/parse-string (:body var1-search-result1) true)
-            var1-search-generic-associations1 (get-in (first (:items var1-search-body1)) [:associations :variables])
+            var1-search-result1 (get-associations-and-details "variables.umm_json" "native_id=var1" :variables false)

             ;;Search for the variable var2 again, it should NOT return the association
-            var2-search-result1 (search-request "variables.umm_json" "native_id=var2")
-            var2-search-body1 (json/parse-string (:body var2-search-result1) true)
-            var2-search-generic-associations1 (get-in (first (:items var2-search-body1)) [:associations :variables])]
+            var2-search-result1 (get-associations-and-details "variables.umm_json" "native_id=var2" :variables false)]
         ;; The first and second associations are successful
         (is (= 200 (:status response1) (:status response2)))

@@ -596,29 +562,29 @@

         ;; Search for the variable var1 returns the var2 as generic association
         (is (= [{:concept-id var2-concept-id :revision-id var2-revision-id}]
-               var1-search-generic-associations))
+               (:associations var1-search-result)))
         (is (= [{:concept-id var2-concept-id :revision-id var2-revision-id}]
-               var1-search-generic-association-details-in-meta))
+               (:association-details var1-search-result-in-meta)))
         (is (= [var2-concept-id]
-               var1-search-generic-associations-in-meta))
+               (:associations var1-search-result-in-meta)))

         ;; Search for the variable var2 returns the var1 as generic association
         (is (= [{:concept-id var1-concept-id :revision-id var1-revision-id}]
-               var2-search-generic-associations))
+               (:associations var2-search-result)))
         (is (= [{:concept-id var1-concept-id :revision-id var1-revision-id}]
-               var2-search-generic-association-details-in-meta))
+               (:association-details var2-search-result-in-meta)))
         (is (= [var1-concept-id]
-               var2-search-generic-associations-in-meta))
+               (:associations var2-search-result-in-meta)))

         ;; Dissociation of the association is successful
         (is (= 200 (:status response4)))

         ;; Search for the variable var1 again doesn't return the var2 as generic association
-        (is (= nil var1-search-generic-associations1))
+        (is (= nil (:associations var1-search-result1)))

         ;; Search for the variable var2 again doesn't return the var1 as generic association
         (is (= nil
-               var2-search-generic-associations1))))
+               (:associations var2-search-result1)))))
     (testing "Associate grid with variable by concept-id and revision-ids"
       (let [response1 (association-util/generic-associate-by-concept-ids-revision-ids
                        token grid-concept-id grid-revision-id [{:concept-id var1-concept-id  :revision-id var1-revision-id}])
@@ -633,14 +599,10 @@
             _ (index/wait-until-indexed)

             ;;Search for the grid, it should return the association
-            grid-search-result (search-request "grids.json" "name=Grid-A7-v1")
-            grid-search-body (json/parse-string (:body grid-search-result) true)
-            grid-search-generic-associations (get-in (first (:items grid-search-body)) [:associations])
+            grid-search-result (get-associations-and-details "grids.json" "name=Grid-A7-v1" :variables false)

             ;;Search for the variable, it should return the association
-            var1-search-result (search-request "variables.umm_json" "native_id=var1")
-            var1-search-body (json/parse-string (:body var1-search-result) true)
-            var1-search-generic-associations (get-in (first (:items var1-search-body)) [:associations :grids])
+            var1-search-result (get-associations-and-details "variables.umm_json" "native_id=var1" :grids false)

             ;;Dissociate the association
             response4 (association-util/generic-dissociate-by-concept-ids-revision-ids
@@ -648,14 +610,10 @@
             _ (index/wait-until-indexed)

             ;;Search for the grid again, it should NOT return the association
-            grid-search-result1 (search-request "grids.json" "name=Grid-A7-v1")
-            grid-search-body1 (json/parse-string (:body grid-search-result1) true)
-            grid-search-generic-associations1 (get-in (first (:items grid-search-body1)) [:associations])
+            grid-search-result1 (get-associations-and-details "grids.json" "name=Grid-A7-v1" :variables false)

             ;;Search for the variable again, it should NOT return the association
-            var1-search-result1 (search-request "variables.umm_json" "native_id=var1")
-            var1-search-body1 (json/parse-string (:body var1-search-result1) true)
-            var1-search-generic-associations1 (get-in (first (:items var1-search-body1)) [:associations :grids])]
+            var1-search-result1 (get-associations-and-details "variables.umm_json" "native_id=var1" :grids false)]
         ;; The first and second associations are successful
         (is (= 200 (:status response1) (:status response2)))

@@ -676,20 +634,20 @@

         ;; Search for the grid returns the var1 as generic association
         (is (= [var1-concept-id]
-               (:variables grid-search-generic-associations)))
+               (:associations grid-search-result)))

         ;; Search for the variable returns the grid as generic association
         (is (= [{:concept-id grid-concept-id :revision-id grid-revision-id}]
-               var1-search-generic-associations))
+               (:associations var1-search-result)))

         ;; Dissociation of the association is successful
         (is (= 200 (:status response4)))

         ;; Search for the grid again doesn't return the var1 as generic association
-        (is (= nil grid-search-generic-associations1))
+        (is (= nil (:associations grid-search-result1)))

         ;; Search for the variable again doesn't return the grid as generic association
-        (is (= nil  var1-search-generic-associations1))))
+        (is (= nil  (:associations var1-search-result1)))))

     (testing "Associate collection with collection by concept-id and revision-ids"
       ;;since we ingested two collections in this test, it's better to do the collection-to-collection association test here.
@@ -706,14 +664,10 @@
             _ (index/wait-until-indexed)

             ;;Search for the collection coll1, it should return the association
-            coll1-search-result (search-request "collections.umm-json" "entry_title=entry-title1")
-            coll1-search-body (json/parse-string (:body coll1-search-result) true)
-            coll1-search-generic-associations (get-in (first (:items coll1-search-body)) [:meta :associations :collections])
+            coll1-search-result (get-associations-and-details "collections.umm-json" "entry_title=entry-title1" :collections true)

             ;;Search for the collection coll2, it should return the association
-            coll2-search-result (search-request "collections.umm-json" "entry_title=entry-title2")
-            coll2-search-body (json/parse-string (:body coll2-search-result) true)
-            coll2-search-generic-associations (get-in (first (:items coll2-search-body)) [:meta :associations :collections])
+            coll2-search-result (get-associations-and-details "collections.umm-json" "entry_title=entry-title2" :collections true)

             ;;Dissociate the association
             response4 (association-util/generic-dissociate-by-concept-ids-revision-ids
@@ -721,14 +675,10 @@
             _ (index/wait-until-indexed)

             ;;Search for the collection coll1 again, it should NOT return the association
-            coll1-search-result1 (search-request "collections.umm-json" "entry_title=entry-title1")
-            coll1-search-body1 (json/parse-string (:body coll1-search-result1) true)
-            coll1-search-generic-associations1 (get-in (first (:items coll1-search-body1)) [:meta :associations :collections])
+            coll1-search-result1 (get-associations-and-details "collections.umm-json" "entry_title=entry-title1" :collections true)

             ;;Search for the collection coll2 again, it should NOT return the association
-            coll2-search-result1 (search-request "collections.umm-json" "entry_title=entry-title2")
-            coll2-search-body1 (json/parse-string (:body coll2-search-result1) true)
-            coll2-search-generic-associations1 (get-in (first (:items coll2-search-body1)) [:meta :associations :collections])]
+            coll2-search-result1 (get-associations-and-details "collections.umm-json" "entry_title=entry-title2" :collections true)]
         ;; The first and second associations are successful
         (is (= 200 (:status response1) (:status response2)))

@@ -749,22 +699,22 @@

         ;; Search for the collection coll1 returns the coll2 as generic association
         (is (= [coll2-concept-id]
-               coll1-search-generic-associations))
+               (:associations coll1-search-result)))

         ;; Search for the collection coll2 returns the coll1 as generic association
         (is (= [coll1-concept-id]
-               coll2-search-generic-associations))
+               (:associations coll2-search-result)))

         ;; Dissociation of the association is successful
         (is (= 200 (:status response4)))

         ;; Search for the collection coll1 again doesn't return the coll2 as generic association
         (is (= nil
-               coll1-search-generic-associations1))
+               (:associations coll1-search-result1)))

         ;; Search for the collection coll2 again doesn't return the coll1 as generic association
         (is (= nil
-               coll2-search-generic-associations1))))))
+               (:associations coll2-search-result1)))))))

 ;; Test that generic associations can be made between generic documents and collections.
 (deftest test-collection-and-generic-association
@@ -809,14 +759,10 @@
             _ (index/wait-until-indexed)

             ;;Search for the grid, it should return the association
-            grid-search-result (search-request "grids.json" "name=Grid-A7-v1")
-            grid-search-body (json/parse-string (:body grid-search-result) true)
-            grid-search-generic-associations (get-in (first (:items grid-search-body)) [:associations])
+            grid-search-result (get-associations-and-details "grids.json" "name=Grid-A7-v1" :collections false)

             ;;Search for the collection, it should return the association
-            coll-search-result (search-request "collections.umm-json" "entry_title=entry-title1")
-            coll-search-body (json/parse-string (:body coll-search-result) true)
-            coll-search-generic-associations (get-in (first (:items coll-search-body)) [:meta :associations :grids])
+            coll-search-result (get-associations-and-details "collections.umm-json" "entry_title=entry-title1" :grids true)

             ;;Dissociate the association
             response4 (association-util/generic-dissociate-by-concept-ids-revision-ids
@@ -824,14 +770,10 @@
             _ (index/wait-until-indexed)

             ;;Search for the grid again, it should NOT return the association
-            grid-search-result1 (search-request "grids.json" "name=Grid-A7-v1")
-            grid-search-body1 (json/parse-string (:body grid-search-result1) true)
-            grid-search-generic-associations1 (get-in (first (:items grid-search-body1)) [:associations])
+            grid-search-result1 (get-associations-and-details "grids.json" "name=Grid-A7-v1" :collections false)

             ;;Search for the collection again, it should NOT return the association
-            coll-search-result1 (search-request "collections.umm-json" "entry_title=entry-title1")
-            coll-search-body1 (json/parse-string (:body coll-search-result1) true)
-            coll-search-generic-associations1 (get-in (first (:items coll-search-body1)) [:meta :associations :grids])]
+            coll-search-result1 (get-associations-and-details "collections.umm-json" "entry_title=entry-title1" :grids true)]

         ;; The first and second associations are successful
         (is (= 200 (:status response1) (:status response2)))
@@ -859,23 +801,23 @@
                                 (first)))))

         ;; Search for the grid returns the collection as generic association
-        (is (= {:collections [coll-concept-id]}
-               grid-search-generic-associations))
+        (is (= [coll-concept-id]
+               (:associations grid-search-result)))

         ;; Search for the collection returns the grid as generic association
         (is (= [grid-concept-id]
-               coll-search-generic-associations))
+               (:associations coll-search-result)))

         ;; Dissociation of the association is successful
         (is (= 200 (:status response4)) "Dissociation of the association failed.")

         ;; Search for the grid again doesn't return the collection as generic association
         (is (= nil
-               grid-search-generic-associations1))
+               (:associations grid-search-result1)))

         ;; Search for the collection again doesn't return the grid as generic association
         (is (= nil
-               coll-search-generic-associations1))))))
+               (:associations coll-search-result1)))))))

 (deftest test-all-associations
   (let [;; ingest two collections - the first for the test, and the second to put more assocation


add failing test case for nils

add failing test case for nils

--- test/rum/server_render_test.cljc
+++ test/rum/server_render_test.cljc
@@ -23,15 +23,17 @@
     [:li.menu-item {:key "outlet"} "Outlet"]])

 (rum/defc comp-nil1 []
+  "In this case nil will be not counted against reactid"
   [:div {:class "parent"}
    nil
    [:div.child]])

 (rum/defc comp-nil2 []
+  "In this case *both* nils will be counted against reactid"
   [:div {:class "parent"}
+   nil
+   [:div.child]
    (list
-     nil
-     [:div.child]
      nil
      [:div.child2])])


Change movement approach and temporary disable align related stuff.

--- src/uxbox/ui/workspace/movement.cljs
+++ src/uxbox/ui/workspace/movement.cljs
@@ -19,19 +19,23 @@
             [uxbox.util.geom :as geom]
             [uxbox.util.geom.point :as gpt]))

-(declare initialize)
-(declare handle-movement)

 ;; --- Lenses

-(declare translate-to-viewport)
+;; (declare translate-to-viewport)
+
+;; (defn- resolve-selected
+;;   [state]
+;;   (let [selected (get-in state [:workspace :selected])
+;;         xf (comp
+;;             (map #(get-in state [:shapes-by-id %]))
+;;             (map translate-to-viewport))]
+;;     (into #{} xf selected)))

 (defn- resolve-selected
   [state]
   (let [selected (get-in state [:workspace :selected])
-        xf (comp
-            (map #(get-in state [:shapes-by-id %]))
-            (map translate-to-viewport))]
+        xf (map #(get-in state [:shapes-by-id %]))]
     (into #{} xf selected)))

 (def ^:const ^:private selected-shapes-l
@@ -48,6 +52,8 @@

 ;; --- Public Api

+(declare initialize)
+
 (defn watch-move-actions
   []
   (as-> uuc/actions-s $
@@ -56,62 +62,77 @@

 ;; --- Implementation

-(def coords
-  (gpt/point c/canvas-start-x
-             c/canvas-start-y))
+;; (def coords
+;;   (gpt/point c/canvas-start-x
+;;              c/canvas-start-y))

-(defn- translate-to-viewport
-  [shape]
-  (let [dx (- (:x2 shape) (:x1 shape))
-        dy (- (:y2 shape) (:y1 shape))
-        p1 (gpt/point (:x1 shape) (:y1 shape))
-        p2 (gpt/add p1 coords)
-        p3 (gpt/add p2 [dx dy])]
-    (assoc shape
-           :x1 (:x p2)
-           :y1 (:y p2)
-           :x2 (:x p3)
-           :y2 (:y p3))))
+;; (defn- translate-to-viewport
+;;   [shape]
+;;   (let [dx (- (:x2 shape) (:x1 shape))
+;;         dy (- (:y2 shape) (:y1 shape))
+;;         p1 (gpt/point (:x1 shape) (:y1 shape))
+;;         p2 (gpt/add p1 coords)
+;;         p3 (gpt/add p2 [dx dy])]
+;;     (assoc shape
+;;            :x1 (:x p2)
+;;            :y1 (:y p2)
+;;            :x2 (:x p3)
+;;            :y2 (:y p3))))

-(defn- translate-to-canvas
-  [shape]
-  (let [dx (- (:x2 shape) (:x1 shape))
-        dy (- (:y2 shape) (:y1 shape))
-        p1 (gpt/point (:x1 shape) (:y1 shape))
-        p2 (gpt/subtract p1 coords)
-        p3 (gpt/add p2 [dx dy])]
-    (assoc shape
-           :x1 (:x p2)
-           :y1 (:y p2)
-           :x2 (:x p3)
-           :y2 (:y p3))))
+;; (defn- translate-to-canvas
+;;   [shape]
+;;   (let [dx (- (:x2 shape) (:x1 shape))
+;;         dy (- (:y2 shape) (:y1 shape))
+;;         p1 (gpt/point (:x1 shape) (:y1 shape))
+;;         p2 (gpt/subtract p1 coords)
+;;         p3 (gpt/add p2 [dx dy])]
+;;     (assoc shape
+;;            :x1 (:x p2)
+;;            :y1 (:y p2)
+;;            :x2 (:x p3)
+;;            :y2 (:y p3))))
+
+;; (defn- initialize
+;;   []
+;;   (let [shapes @selected-shapes-l
+;;         align? @alignment-l
+;;         stoper (->> uuc/actions-s
+;;                     (rx/map :type)
+;;                     (rx/filter empty?)
+;;                     (rx/take 1))]
+;;     (as-> wb/mouse-delta-s $
+;;       (rx/take-until stoper $)
+;;       (rx/map #(gpt/divide % @wb/zoom-l) $)
+;;       (rx/scan (fn [acc delta]
+;;                  (let [xf (map #(geom/move % delta))]
+;;                    (into [] xf acc))) shapes $)
+;;       (rx/mapcat (fn [items]
+;;                    (if align?
+;;                      (->> (apply rx/of items)
+;;                           (rx/mapcat align/translate)
+;;                           (rx/reduce conj []))
+;;                      (rx/of items))) $)
+;;       (rx/map (fn [items]
+;;                 (mapv translate-to-canvas items)) $)
+;;       (rx/subscribe $ handle-movement))))
+
+(defn- handle-movement
+  [{:keys [id] :as shape} delta]
+  (rs/emit! (uds/move-shape id delta)))
+
+(defn- watch-movement
+  [stoper shape]
+  (as-> wb/mouse-delta-s $
+    (rx/take-until stoper $)
+    (rx/map #(gpt/divide % @wb/zoom-l) $)
+    (rx/subscribe $ (partial handle-movement shape))))

 (defn- initialize
   []
-  (let [shapes @selected-shapes-l
-        align? @alignment-l
+  (let [;; align? @alignment-l
         stoper (->> uuc/actions-s
                     (rx/map :type)
                     (rx/filter empty?)
                     (rx/take 1))]
-    (as-> wb/mouse-delta-s $
-      (rx/take-until stoper $)
-      (rx/map #(gpt/divide % @wb/zoom-l) $)
-      (rx/scan (fn [acc delta]
-                 (let [xf (map #(geom/move % delta))]
-                   (into [] xf acc))) shapes $)
-      (rx/mapcat (fn [items]
-                   (if align?
-                     (->> (apply rx/of items)
-                          (rx/mapcat align/translate)
-                          (rx/reduce conj []))
-                     (rx/of items))) $)
-      (rx/map (fn [items]
-                (mapv translate-to-canvas items)) $)
-
-      (rx/subscribe $ handle-movement))))
-
-(defn- handle-movement
-  [delta]
-  (doseq [shape delta]
-    (rs/emit! (uds/update-shape shape))))
+    (run! (partial watch-movement stoper)
+          (deref selected-shapes-l))))


Add util/approx-diff

Add util/approx-diff

This is useful for debugging tests that use approx=.

--- cortex/src/cortex/util.cljc
+++ cortex/src/cortex/util.cljc
@@ -197,7 +197,9 @@

   Does not require collections to be of compatible types, i.e. sets can be
   equal to vectors. As a result, works seamlessly with core.matrix vectors
-  of different implementations."
+  of different implementations.
+
+  See also approx-diff."
   [error & colls]
   (let [seqs (map (partial tree-seq seq-like? seq)
                   colls)]
@@ -214,6 +216,39 @@
                           :else
                           (apply = items))))
            (every? identity)))))
+
+(defn approx-diff
+  "Recursively traverses the given data structures, which should be
+  identical except for corresponding floating-point numbers and the
+  concrete types of sequence-like objects.
+
+  Returns a data structure of the same form as the provided ones,
+  with floating-point numbers replaced with the relative errors of
+  the corresponding sets of numbers.
+
+  See also approx=."
+  [& colls]
+  (cond
+    (every? float? colls)
+    (relative-error (apply min colls)
+                    (apply max colls))
+    (every? list? colls)
+    (->> colls
+      (apply map (partial apply approx-diff))
+      (apply list))
+    (every? map-entry? colls)
+    (map-entry (apply approx-diff (map key colls))
+               (apply approx-diff (map val colls)))
+    (every? seq-like? colls)
+    (->> colls
+      (apply map approx-diff)
+      (into (empty (first colls))))
+    (apply = colls)
+    (first colls)
+    :else
+    (throw
+      (IllegalArgumentException.
+        (str "Divergent nodes: " colls)))))

 (defn vectorize
   "Recursively turns a data structure into nested vectors. All sequence-like


Minor

Minor

--- storm-core/src/clj/backtype/storm/config.clj
+++ storm-core/src/clj/backtype/storm/config.clj
@@ -254,11 +254,12 @@

 (defn worker-artifacts-root
   ([conf]
-    (let [workers-artifacts-dir (conf STORM-WORKERS-ARTIFACTS-DIR)]
-      (if workers-artifacts-dir
-        (if (is-absolute-path? workers-artifacts-dir)
-          workers-artifacts-dir
-          (str backtype.storm.util/LOG-DIR file-path-separator workers-artifacts-dir)))))
+   (let [workers-artifacts-dir (conf STORM-WORKERS-ARTIFACTS-DIR)]
+     (if workers-artifacts-dir
+       (if (is-absolute-path? workers-artifacts-dir)
+         workers-artifacts-dir
+         (str backtype.storm.util/LOG-DIR file-path-separator workers-artifacts-dir))
+       (str backtype.storm.util/LOG-DIR file-path-separator "workers-artifacts"))))
   ([conf id]
    (str (worker-artifacts-root conf) file-path-separator id))
   ([conf id port]


Fix schema tests

Fix schema tests

--- test/clojurewerkz/cassaforte/schema_test.clj
+++ test/clojurewerkz/cassaforte/schema_test.clj
@@ -21,7 +21,7 @@
 (let [s (client/connect ["127.0.0.1"])]
   (use-fixtures :each (fn [f]
                         (try
-                          (drop-keyspace s :new_cql_keyspace)
+                          (drop-keyspace s "new_cql_keyspace")
                           (catch Exception _ nil))
                         (create-keyspace s "new_cql_keyspace"
                                          (with {:replication
@@ -32,22 +32,22 @@

   (deftest test-create-drop-keyspace
     (try
-      (drop-keyspace s :new_cql_keyspace)
+      (drop-keyspace s "new_cql_keyspace")
       (catch Exception _ nil))
-    (is (nil? (describe-keyspace s :new_cql_keyspace)))
-    (create-keyspace s :new_cql_keyspace
+    (is (nil? (describe-keyspace s "new_cql_keyspace")))
+    (create-keyspace s "new_cql_keyspace"
                      (with {:replication
                             {:class              "SimpleStrategy"
                              :replication_factor 1 }}))
-    (is (describe-keyspace s :new_cql_keyspace)))
+    (is (describe-keyspace s "new_cql_keyspace")))

   (deftest test-create-alter-keyspace
-    (alter-keyspace s :new_cql_keyspace
+    (alter-keyspace s "new_cql_keyspace"
                     (with {:durable_writes false
                            :replication    {:class "NetworkTopologyStrategy"
                                             :dc1 1
                                             :dc2 2}}))
-    (let [res (describe-keyspace s :new_cql_keyspace)]
+    (let [res (describe-keyspace s "new_cql_keyspace")]
       (is (= "new_cql_keyspace" (:keyspace_name res)))
       (is (= false (:durable_writes res)))
       (is (= "{\"dc2\":\"2\",\"dc1\":\"1\"}" (:strategy_options res)))))
@@ -116,7 +116,7 @@
                                        :city       :varchar
                                        :info :text
                                        :primary-key [:first_name :last_name :city]}))
-    (let [cfd (describe-table s :new_cql_keyspace :people)]
+    (let [cfd (describe-table s "new_cql_keyspace" "people")]
       (is (= "[\"first_name\"]" (:key_aliases cfd)))
       (is (= "[\"last_name\",\"city\"]" (:column_aliases cfd)))))

@@ -127,6 +127,6 @@
                                        :city       :varchar
                                        :info :text
                                        :primary-key [[:first_name :last_name] :city]}))
-    (let [cfd (describe-table s :new_cql_keyspace :people)]
+    (let [cfd (describe-table s "new_cql_keyspace" :people)]
       (is (= "[\"first_name\",\"last_name\"]" (:key_aliases cfd)))
       (is (= "[\"city\"]" (:column_aliases cfd))))))


SER-1338 | add store to the tests

SER-1338 | add store to the tests

--- test/vignette/storage/static_assets_test.clj
+++ test/vignette/storage/static_assets_test.clj
@@ -6,14 +6,16 @@
             ))

 (facts :static-assets :get-original
+       (let [store (create-image-storage ..disk-store..)]
+
        (get-original
-         (sa/create-static-image-storage --static-asset-get--) {:uuid ..uuid..}) => ..object..
+         (sa/create-static-image-storage store --static-asset-get--) {:uuid ..uuid..}) => ..object..
        (provided
          (--static-asset-get-- ..uuid..) => ..static-asset-url..
          (http/get ..static-asset-url.. {:as :stream}) => (future {:status 200})
          (sa/->AsyncResponseStoredObject {:status 200}) => ..object..)
        (get-original
-         (sa/create-static-image-storage --static-asset-get--) {:uuid ..uuid.. :options {:status ..statuses..}}) => nil
+         (sa/create-static-image-storage store --static-asset-get--) {:uuid ..uuid.. :options {:status ..statuses..}}) => nil
        (provided
          (--static-asset-get-- ..uuid..) => ..static-asset-url..
          (http/get ..static-asset-url.. {:as :stream}) => (future {:status 404})))
@@ -35,8 +37,9 @@
          (sa/->AsyncResponseStoredObject ..response..)) => nil)

 (facts :static-assets :get-blocked-placeholder
+       (let [store (create-image-storage ..disk-store..)]
        (get-original
-         (sa/create-static-image-storage --static-asset-get--) {:uuid ..uuid.. :blocked-placeholder ..placeholder-id..}) => ..placeholder..
+         (sa/create-static-image-storage store --static-asset-get--) {:uuid ..uuid.. :blocked-placeholder ..placeholder-id..}) => ..placeholder..
        (provided
          (--static-asset-get-- ..uuid..) => ..static-asset-url..
          (http/get ..static-asset-url.. {:as :stream}) => (future {:status 451})


Separate out Java class generation into own function

--- src/active/clojure/record.cljc
+++ src/active/clojure/record.cljc
@@ -274,81 +274,40 @@
                (resolve* accessor)))
            ?constructor-args)))))

-#?(:clj
-(defmacro define-record-type
-  "Attach doc properties to the type and the field names to get reasonable docstrings."
-  [?type ?constructor-call ?predicate ?field-specs & ?opt+specs]
-  (when-not (and (list? ?constructor-call)
-                 (not (empty? ?constructor-call)))
-    (throw (throw-illegal-argument-exception (str "constructor call must be a list in " *ns* " " (meta &form)))))
-  (when-not (vector? ?field-specs)
-    (throw (throw-illegal-argument-exception (str "field specs must be a vector in " *ns* " " (meta &form)))))
-  (when-not (even? (count (remove seq? ?field-specs)))
-    (throw (throw-illegal-argument-exception (str "odd number of elements in field specs in " *ns* " " (meta &form)))))
-  (when-not (every? true? (map #(= 3 (count %1)) (filter seq? ?field-specs)))
-    (throw (throw-illegal-argument-exception (str "wrong number of elements in field specs with lens in " *ns* " " (meta &form)))))
-
-  (let [?field-triples (loop [specs (seq ?field-specs)
-                              triples '()]
-                         (if (empty? specs)
-                           (reverse triples)
-                           (let [spec (first specs)]
-
-                             (cond
-                              (list? spec)
-                              (do
-                                (when-not (and (= 3 (count spec))
-                                               (every? symbol spec))
-                                  (throw-illegal-argument-exception (str "invalid field spec " spec " in " *ns* " " (meta &form))))
-                                (recur (rest specs) (list* spec triples)))
-
-                              (symbol? spec)
-                              (do
-                                (when (empty? (rest specs))
-                                  (throw (throw-illegal-argument-exception (str "incomplete field spec for " spec " in " *ns* " " (meta &form)))))
-                                (when-not (symbol? (fnext specs))
-                                  (throw (throw-illegal-argument-exception (str "invalid accessor " (fnext specs) " for " spec " in " *ns* " " (meta &form)))))
-                                (recur (nnext specs)
-                                       (list* [spec (fnext specs) nil] triples)))
-
-                              :else
-                              (throw (throw-illegal-argument-exception (str "invalid field spec " spec " in " *ns* " " (meta &form))))))))
-
-        ?constructor (first ?constructor-call)
-        ?constructor-args (rest ?constructor-call)
-        ?constructor-args-set (set ?constructor-args)
-        document (fn [n doc]
-                   (vary-meta n
-                              (fn [m]
-                                (if (contains? m :doc)
-                                  m
-                                  (assoc m :doc doc)))))
-        document-with-arglist (fn [n arglist doc]
-                                (vary-meta n
-                                           (fn [m]
-                                             (let [m (if (contains? m :doc)
-                                                       m
-                                                       (assoc m :doc doc))]
-                                               (if (contains? m :arglists)
-                                                 m
-                                                 (assoc m :arglists `'(~arglist)))))))
-        name-doc (fn [field]
-                    (if-let [doc (:doc (meta field))]
-                      (str " (" doc ")")
-                      ""))
-
-        ?field-names (map first ?field-triples)
-        reference (fn [name]
-                    (str "[[" (ns-name *ns*) "/" name "]]"))
-        ?docref (str "See " (reference ?constructor) ".")
-
-        record-meta `(make-record-meta ~?predicate ~?constructor ~?constructor-args ~?field-triples)]
-
-    (let [?field-names-set (set ?field-names)]
-      (doseq [?constructor-arg ?constructor-args]
-        (when-not (contains? ?field-names-set ?constructor-arg)
-          (throw (throw-illegal-argument-exception (str "constructor argument " ?constructor-arg " is not a field in " *ns* " " (meta &form)))))))
-
+(defn- document
+  [n doc]
+  (vary-meta n
+             (fn [m]
+               (if (contains? m :doc)
+                 m
+                 (assoc m :doc doc)))))
+
+(defn- document-with-arglist
+  [n arglist doc]
+  (vary-meta n
+             (fn [m]
+               (let [m (if (contains? m :doc)
+                         m
+                         (assoc m :doc doc))]
+                 (if (contains? m :arglists)
+                   m
+                   (assoc m :arglists `'(~arglist)))))))
+
+(defn- name-doc
+  [field]
+  (if-let [doc (:doc (meta field))]
+    (str " (" doc ")")
+    ""))
+
+(defn- reference
+  [name]
+  (str "[[" (ns-name *ns*) "/" name "]]"))
+
+(defn emit-java-record-definition
+  [?type ?constructor ?constructor-args ?predicate ?field-triples ?opt+specs]
+  (let [?docref (str "See " (reference ?constructor) ".")
+        record-meta `(make-record-meta ~?predicate ~?constructor ~?constructor-args ~?field-triples)
+        ?constructor-args-set (set ?constructor-args)]
     `(do
        ~(let [fields (mapv first ?field-triples)]
           (validate-fields fields ?type)
@@ -374,17 +333,17 @@
          (fn [x#]
            (instance? ~?type x#)))
        (def ~(document-with-arglist ?constructor
-                                 (vec ?constructor-args)
-                                 (str "Construct a `" ?type "`"
-                                      (name-doc ?type)
-                                      " record.\n"
-                                      (apply str
-                                             (map (fn [[?field ?accessor ?lens]]
-                                                    (str "\n`" ?field "`" (name-doc ?field) ": access via " (reference ?accessor)
-                                                         (if ?lens
-                                                           (str ", lens " (reference ?lens))
-                                                           "")))
-                                                  ?field-triples))))
+                                    (vec ?constructor-args)
+                                    (str "Construct a `" ?type "`"
+                                         (name-doc ?type)
+                                         " record.\n"
+                                         (apply str
+                                                (map (fn [[?field ?accessor ?lens]]
+                                                       (str "\n`" ?field "`" (name-doc ?field) ": access via " (reference ?accessor)
+                                                            (if ?lens
+                                                              (str ", lens " (reference ?lens))
+                                                              "")))
+                                                     ?field-triples))))
          (fn [~@?constructor-args]
            (new ~?type
                 ~@(map (fn [[?field _]]
@@ -416,8 +375,53 @@
                                                                     `(~?shove-accessor ~?data)))
                                                                 ?field-triples)))))))
                            '()))))
-                 ?field-triples)))))
-
+                 ?field-triples))))
+
+#?(:clj
+(defmacro define-record-type
+  "Attach doc properties to the type and the field names to get reasonable docstrings."
+  [?type ?constructor-call ?predicate ?field-specs & ?opt+specs]
+  (when-not (and (list? ?constructor-call)
+                 (not (empty? ?constructor-call)))
+    (throw (throw-illegal-argument-exception (str "constructor call must be a list in " *ns* " " (meta &form)))))
+  (when-not (vector? ?field-specs)
+    (throw (throw-illegal-argument-exception (str "field specs must be a vector in " *ns* " " (meta &form)))))
+  (when-not (even? (count (remove seq? ?field-specs)))
+    (throw (throw-illegal-argument-exception (str "odd number of elements in field specs in " *ns* " " (meta &form)))))
+  (when-not (every? true? (map #(= 3 (count %1)) (filter seq? ?field-specs)))
+    (throw (throw-illegal-argument-exception (str "wrong number of elements in field specs with lens in " *ns* " " (meta &form)))))
+
+  (let [?field-triples (loop [specs (seq ?field-specs)
+                              triples '()]
+                         (if (empty? specs)
+                           (reverse triples)
+                           (let [spec (first specs)]
+
+                             (cond
+                              (list? spec)
+                              (do
+                                (when-not (and (= 3 (count spec))
+                                               (every? symbol spec))
+                                  (throw-illegal-argument-exception (str "invalid field spec " spec " in " *ns* " " (meta &form))))
+                                (recur (rest specs) (list* spec triples)))
+
+                              (symbol? spec)
+                              (do
+                                (when (empty? (rest specs))
+                                  (throw (throw-illegal-argument-exception (str "incomplete field spec for " spec " in " *ns* " " (meta &form)))))
+                                (when-not (symbol? (fnext specs))
+                                  (throw (throw-illegal-argument-exception (str "invalid accessor " (fnext specs) " for " spec " in " *ns* " " (meta &form)))))
+                                (recur (nnext specs)
+                                       (list* [spec (fnext specs) nil] triples)))
+
+                              :else
+                              (throw (throw-illegal-argument-exception (str "invalid field spec " spec " in " *ns* " " (meta &form))))))))
+
+        ?constructor (first ?constructor-call)
+        ?constructor-args (rest ?constructor-call)
+        ?field-names (map first ?field-triples)]
+    (emit-java-record-definition ?type ?constructor ?constructor-args ?predicate ?field-triples ?opt+specs)))
+)

 (defn predicate->record-meta [predicate]
   ;; Expects a namespace resolved predicate


Remove obsolete comment

Remove obsolete comment

--- src/asciinema/player/core.cljs
+++ src/asciinema/player/core.cljs
@@ -89,7 +89,7 @@
   "Mounts player's Reagent component at given DOM element."
   [player-atom dom-node]
   (reagent/render-component [view/player-component player-atom] dom-node)
-  nil) ; TODO: return JS object with control functions (play/pause) here
+  nil)

 (defn create-player
   "Creates initial player state and mounts player's Reagent component at given


added become

added become

--- src/babel/english/lexicon.cljc
+++ src/babel/english/lexicon.cljc
@@ -228,6 +228,10 @@
                  :synsem {:cat :verb
                           :sem {:pred :to-be-missing}}}

+   "become" {:synsem {:cat :verb
+                    :sem {:pred :become}}
+           :english {:past "became"}}
+
    "begin" {:synsem {:cat :verb
                      :sem {:pred :begin}}
             :english {:past "began"


add intransitive "become"

add intransitive "become"

--- src/babel/english/lexicon.cljc
+++ src/babel/english/lexicon.cljc
@@ -307,10 +307,14 @@
                            :pred :beach
                            :artifact false}}}

-   "become" {:synsem {:cat :verb
-                      :sem {:pred :become}
-                      :subcat {:2 {:cat :adjective}}}
-             :english {:past "became"}}
+   "become" [{:synsem {:cat :verb
+                       :sem {:pred :become}
+                       :subcat {:2 {:cat :adjective}}}
+              :english {:past "became"}}
+             {:synsem {:cat :verb
+                       :sem {:pred :become}
+                       :subcat {:2 '()}}
+              :english {:past "became"}}]

    "begin" {:synsem {:cat :verb
                      :sem {:pred :begin}}


wait +PP[for]

wait +PP[for]

--- src/babel/english/lexicon.cljc
+++ src/babel/english/lexicon.cljc
@@ -1977,7 +1977,9 @@
                     :sem {:pred :usare}}}

    "wait"  {:synsem {:cat :verb
-                     :sem {:pred :wait-for}}}
+                     :sem {:pred :wait-for}
+                     :subcat {:2 {:sem {:pred :for}}}}}
+
    "wake up"
    (let [subject-semantics (atom :top)]
      {:synsem {:cat :verb


indent code

indent code

--- src/ca_recipe/family_async.clj
+++ src/ca_recipe/family_async.clj
@@ -1,6 +1,9 @@
 (ns ca-recipe.family-async)

-(def shopping-list (ref #{})) (def assignments (ref {})) (def shopping-cart (ref #{}))
+(def shopping-list (ref #{}))
+(def assignments (ref {}))
+(def shopping-cart (ref #{}))
+
 (defn init []
   (store/init {:eggs 2 :bacon 3 :apples 3
                :candy 5 :soda 2 :milk 1
@@ -8,5 +11,6 @@
                :cheese 3})
   (dosync
    (ref-set shopping-list #{:milk :butter :bacon :eggs
-                            :carrots :potatoes :cheese :apples}) (ref-set assignments {})
+                            :carrots :potatoes :cheese :apples})
+   (ref-set assignments {})
    (ref-set shopping-cart #{})))


Fixing up the macro

Fixing up the macro

--- src/clj/clumcl/uts/content.clj
+++ src/clj/clumcl/uts/content.clj
@@ -1,12 +1,13 @@
 (ns clumcl.uts.content
-  "This namespace contains functions for accessing the content API of UTS."
+  "This namespace contains functions for accessing the content API of UTS.
+Not all of the methods are implemented yet. If there is one missing that you need you can use the defcontentfn macro to create it."
   (:require [clumcl.uts.security :as sec]
             [clojure.java.data :refer [to-java]]
             [taoensso.timbre :as timbre
              :refer (trace debug info warn error fatal spy with-log-level)])
   (:import [gov.nih.nlm.uts.webservice.content Psf UtsWsContentControllerImplService]))

-(def ^{:private true} content-service
+(def ^{:doc "Content service"} content-service
   (.getUtsWsContentControllerImplPort (UtsWsContentControllerImplService.)))

 (def ^{:private true} option-application
@@ -32,6 +33,7 @@

 (defn create-psf
   "Create a page, sort, filter object optionally using the arguments in the provided map.
+You only need to provide the keys that you want to change from their defaults.

    Valid keys are:
      :pageLn                           int
@@ -49,18 +51,37 @@
   ([]
      (Psf.)))

-(defmacro ^{:private true} defcontentfn
-  "Create a function that calls the given content API method."
-  [f docstring args api-name]
-  `(defn ~f ~docstring [~'conn ~'version ~@args]
-     (. content-service ~api-name (sec/single-use-ticket ~'conn) ~'version ~@args)))
+(defmacro defcontentfn
+  "Creates a function that calls the given content API method. It adds the conn and version arguments first then all the provided
+arguments for the function. If a transform-fns are provided it will thread the result of the method call through apply them using ->> threading macro.
+
+For example:
+
+   (defcontentfn get-concept
+     \"Get the concept\"
+     [cui]
+     getConcept)
+
+will generate a function with the following signature:
+
+   (defn get-concept
+     \"Get the concept\"
+     [conn version cui]
+     ...)"
+  [f docstring args api-name & transform-fns]
+  (if transform-fns
+   `(defn ~f ~docstring [~'conn ~'version ~@args]
+      (let [result# (. content-service ~api-name (sec/single-use-ticket ~'conn) ~'version ~@args)]
+        (->> result# ~@transform-fns)))
+   `(defn ~f ~docstring [~'conn ~'version ~@args]
+       (. content-service ~api-name (sec/single-use-ticket ~'conn) ~'version ~@args))))

 (defcontentfn get-concept
-  "Get the concept for the CUI. Returns a ConceptDTO object."
+  "Get the concept for the CUI. Returns a map constructed from the ConceptDTO object."
   [cui]
-  getConcept)
+  getConcept bean)

 (defcontentfn get-concept-definitions
-  "Get the definitions for the given concept CUI using the provided PSF."
+  "Get the definitions for the given concept CUI using the provided PSF. Returns a list of maps constructred from the DefinitionDTO objects."
   [cui psf]
-  getConceptDefinitions)
+  getConceptDefinitions (map bean))


Fix typo

Fix typo

--- src/clj_ns_browser/browser.clj
+++ src/clj_ns_browser/browser.clj
@@ -402,7 +402,7 @@
     (config! (id :doc-ta) :text "                                                                        ")
     (selection! (id :ns-cbx) "loaded")
     (selection! (id :vars-cbx) "publics")
-    (selection! (id :vars-cbx) "Doc")))
+    (selection! (id :doc-cbx) "Doc")))

 (defn init-after-bind


Add API functions for other server calls

--- src/cljs/comic_reader/api.cljs
+++ src/cljs/comic_reader/api.cljs
@@ -9,3 +9,15 @@
   (GET "/api/v1/sites" {:handler #(dispatch [:site-list %])
                         :error-handler error-handler
                         :response-format :edn}))
+
+(defn get-comics [site]
+  (GET (format "/api/v1/comics/%s" (pr-str site))
+      {:handler #(dispatch [:comic-list %])
+       :error-handler error-handler
+       :response-format :edn}))
+
+(defn get-comic-urls [comic-name]
+  (GET (format "/api/v1/comic/%s" (pr-str comic-name))
+      {:handler #(dispatch [:comic-urls %])
+       :error-handler error-handler
+       :response-format :edn}))


[WR] returning deleting-column to false after running

--- src/cljs/retrobard/client.cljs
+++ src/cljs/retrobard/client.cljs
@@ -111,14 +111,15 @@
     om/IRenderState
     (render-state [this {:keys [deleting-column]}]
       (let [{:keys [connection column-id]} app
-            ask-to-confirm (fn [el]
+            begin-delete-column (fn [el]
                              (om/set-state! owner :deleting-column true))
-            do-not-delete (fn [el]
+            end-delete-column (fn [el]
                              (om/set-state! owner :deleting-column false))
             delete-column (fn []
-                            (delete-column (om/value connection) column-id))]
+                            (delete-column (om/value connection) column-id)
+                            (end-delete-column))]
         (dom/div nil
-                 (dom/div #js {:onClick ask-to-confirm
+                 (dom/div #js {:onClick begin-delete-column
                                :style (display (not deleting-column))
                                :className "delete-column"}
                           "Delete Column")
@@ -128,7 +129,7 @@
                           (dom/div #js {:onClick delete-column
                                         :className "confirm-delete"}
                                    "Yes")
-                          (dom/div #js {:onClick do-not-delete
+                          (dom/div #js {:onClick end-delete-column
                                         :className "cancel-delete"}
                                    "No")))))))


fix style update on drop

fix style update on drop

--- src/cljs/smgui/components.cljs
+++ src/cljs/smgui/components.cljs
@@ -36,12 +36,12 @@

     om/IRenderState
     (render-state [_ {:keys [over view onFiles] :as state}]
-      (let [update-over #(pd (om/set-state! owner :over %))
+      (let [update-over #(om/set-state! owner :over %)
             classes (class-set {"dragging" over})]
         (dom/div #js {:className   (str "flex flex-row " classes)
-                      :onDragEnter #(update-over true)
-                      :onDragOver  #(update-over true)
-                      :onDragLeave #(update-over false)
-                      :onDragEnd   #(update-over false)
-                      :onDrop      (pd #(onFiles (read-file-paths %)))}
+                      :onDragEnter (pd #(update-over true))
+                      :onDragOver  (pd #(update-over true))
+                      :onDragLeave (pd #(update-over false))
+                      :onDragEnd   (pd #(update-over false))
+                      :onDrop      (pd #(do (update-over false) (onFiles (read-file-paths %))))}
                  view)))))


[neko.ui] Add dimensions support to layout width and height

--- src/clojure/neko/ui/traits.clj
+++ src/clojure/neko/ui/traits.clj
@@ -186,7 +186,7 @@
     Keyword (.setImageDrawable wdg (neko.resource/get-drawable image))
     Uri (.setImageURI wdg image)
     ;; Otherwise assume `image` to be resource ID.
-    :else (.setImageResource wdg image)))
+    (.setImageResource wdg image)))

 ;; ### Layout parameters attributes

@@ -209,9 +209,14 @@
   {:attributes [:layout-width :layout-height]
    :applies? (and (or layout-width layout-height) (nil? container-type))}
   [^View wdg, {:keys [layout-width layout-height]} {:keys [container-type]}]
-  (let [^int width  (kw/value :layout-params (or layout-width  :wrap))
-        ^int height (kw/value :layout-params (or layout-height :wrap))]
-   (.setLayoutParams wdg (ViewGroup$LayoutParams. width height))))
+  (let [^int width (->> (or layout-width :wrap)
+                        (kw/value :layout-params)
+                        (to-dimension (.getContext wdg)))
+        ^int height (->> (or layout-height :wrap)
+                         (kw/value :layout-params)
+                         (to-dimension (.getContext wdg)))
+        lp (RelativeLayout$LayoutParams. width height)]
+    (.setLayoutParams wdg (ViewGroup$LayoutParams. width height))))

 (deftrait :linear-layout-params
   "Takes `:layout-width`, `:layout-height`, `:layout-weight`,
@@ -274,8 +279,12 @@
   [^View wdg, {:keys [layout-width layout-height
                       layout-align-with-parent-if-missing] :as attributes}
    {:keys [container-type]}]
-  (let [^int width  (kw/value :layout-params (or layout-width  :wrap))
-        ^int height (kw/value :layout-params (or layout-height :wrap))
+  (let [^int width (->> (or layout-width :wrap)
+                        (kw/value :layout-params)
+                        (to-dimension (.getContext wdg)))
+        ^int height (->> (or layout-height :wrap)
+                         (kw/value :layout-params)
+                         (to-dimension (.getContext wdg)))
         lp (RelativeLayout$LayoutParams. width height)]
     (when-not (nil? layout-align-with-parent-if-missing)
       (set! (. lp alignWithParent) layout-align-with-parent-if-missing))
@@ -294,8 +303,12 @@
   [^View wdg, {:keys [layout-width layout-height layout-view-type]
                :as attributes}
    {:keys [container-type]}]
-  (let [^int width  (kw/value :layout-params (or layout-width  :wrap))
-        ^int height (kw/value :layout-params (or layout-height :wrap))]
+  (let [^int width (->> (or layout-width :wrap)
+                        (kw/value :layout-params)
+                        (to-dimension (.getContext wdg)))
+        ^int height (->> (or layout-height :wrap)
+                         (kw/value :layout-params)
+                         (to-dimension (.getContext wdg)))]
     (.setLayoutParams
      wdg (if layout-view-type
            (AbsListView$LayoutParams. width height layout-view-type)


Endpoint needs 200 GET access for health checks.

--- src/cmr/opendap/rest/route.clj
+++ src/cmr/opendap/rest/route.clj
@@ -17,7 +17,8 @@

 (defn ous
   [httpd-component]
-  [["/ous/collections" {
+  [["/" {:get core-handler/ok}]
+   ["/ous/collections" {
     :post {
       :handler collection-handler/batch-generate
       ;; XXX protecting collections will be a little different than


Abortion of exploration now propagates upto toplevel

Signed-off-by: Daniel Borchmann <25857343a15bf1edafebc2912e82ecf775c585c1@mailbox.tu-dresden.de>

--- src/conexp/fca/exploration.clj
+++ src/conexp/fca/exploration.clj
@@ -207,10 +207,7 @@
                                   last)
                  ctx)
           (let [new-impl        (make-implication last conclusion-from-last),
-                counterexamples (try
-                                  (handler ctx implications new-impl)
-                                  (catch Throwable e
-                                    :abort))]
+                counterexamples (handler ctx implications new-impl)]
             (cond
              (= counterexamples :abort)
              (recur implications nil ctx) ; forget all other sets
@@ -258,10 +255,7 @@
                  possible-ctx
                  certain-ctx)
           (let [new-impl        (make-implication last conclusion-from-last),
-                counterexamples (try
-                                  (handler possible-ctx certain-ctx implications new-impl)
-                                  (catch Throwable e
-                                    :abort))]
+                counterexamples (handler possible-ctx certain-ctx implications new-impl)]
             (cond
              (= counterexamples :abort) ; abort exploration
              (recur implications nil possible-ctx certain-ctx)


Stub for core_test.clj

Stub for core_test.clj

--- test/zg/core_test.clj
+++ test/zg/core_test.clj
@@ -2,6 +2,12 @@
   (:require [clojure.test :refer :all]
             [zg.core :refer :all]))

-(deftest a-test
-  (testing "FIXME, I fail."
-    (is (= 0 1))))
+;
+; Common functions used by tests.
+;
+
+(defn callable?
+    "Test if given function-name is bound to the real function."
+    [function-name]
+    (clojure.test/function? function-name))
+


Fixed typo

Fixed typo

--- test/flatgui/java_test.clj
+++ test/flatgui/java_test.clj
@@ -1,4 +1,4 @@
-; Copyright (c) 2075 Denys Lebediev and contributors. All rights reserved.
+; Copyright (c) 2017 Denys Lebediev and contributors. All rights reserved.
 ; The use and distribution terms for this software are covered by the
 ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
 ; which can be found in the file LICENSE at the root of this distribution.


make the event index mapping safer for ES

--- src/ctia/stores/es/mapping.clj
+++ src/ctia/stores/es/mapping.clj
@@ -616,7 +616,7 @@

 (def event-mapping
   {"event"
-   {:dynamic_templates dynamic-templates
+   {:dynamic false
     :properties
     {:owner token
      :groups token
@@ -624,9 +624,11 @@
      :entity {:enabled false
               :type "object"}
      :id token
-     :http-params {:type "object"}
+     :http-params {:enabled false
+                   :type "object"}
      :type token
-     :fields {:type "object"}
+     :fields {:enabled false
+              :type "object"}
      :judgement_id token}}})

 (def store-settings


CMR-1878: Change field name in cubby index so that it works for live deployment

--- cubby-app/src/cmr/cubby/data/elastic_cache_store.clj
+++ cubby-app/src/cmr/cubby/data/elastic_cache_store.clj
@@ -34,7 +34,12 @@
     :_all {:enabled false},
     :_id   {:path "key-name"},
     :properties {:key-name string-type
-                 :value string-type}}})
+
+                 ;; Deprecated, remove in future sprint. We changed the value to support values
+                 ;; larger than 32KB.
+                 :value string-type
+
+                 :value2 string-type}}})

 (def index-settings
   "Defines the cubby elasticsearch index settings."
@@ -88,7 +93,7 @@
               index-name type-name
               :query {:filtered {:query (q/match-all)
                                  :filter {:term {:key-name "foo"}}}}
-              :fields [:value])
+              :fields [:value2])

   )

@@ -148,13 +153,13 @@
   (get-value
     [this key-name]
     (get-in (esd/get conn index-name type-name key-name)
-            [:_source :value]))
+            [:_source :value2]))

   (set-value
     [this key-name value]
     (try-elastic-operation
       (esd/create conn index-name type-name
-                  {:key-name key-name :value value}
+                  {:key-name key-name :value2 value}
                   :id key-name
                   :refresh true)))


percolation matching working

percolation matching working

--- Clojure-Websockets/src/clj/birdwatch/main.clj
+++ Clojure-Websockets/src/clj/birdwatch/main.clj
@@ -55,11 +55,15 @@
   (def chsk-send!                    send-fn) ; ChannelSocket's send API fn
   (def connected-uids                connected-uids)) ; Watchable, read-only atom

+(def subscriptions (atom {}))

 (defn start-percolator [params]
+  "register percolation search with ID based on hash of the query"
   (let [q (:query params)
-        sha (sha1 (str q))]
-    (perc/register-query conn "percolator" sha :query q) ; register percolation search with ID based on hash of the query
+        sha (sha1 (str q))
+        uid (:uid params)]
+    (swap! subscriptions assoc uid sha)
+    (perc/register-query conn "percolator" sha :query q)
     (log/info "Percolation registered for query" q "with SHA1" sha)))

 (defn query [params]
@@ -183,11 +187,9 @@
    (let [t (<! tweets-chan)]
      (let [response (perc/percolate conn "percolator" "tweet" :doc t)
            matches (into #{} (map #(:_id %1) (esrsp/matches-from response)))]
-       (log/info "esrsp/matches-from" matches))
-
-     (doseq [uid (:any @connected-uids)]
-       (chsk-send! uid [:tweet/new t]))
-
+       (doseq [uid (:any @connected-uids)]
+         (when (contains? matches (get @subscriptions uid))
+           (chsk-send! uid [:tweet/new t]))))
      (try
        (esd/put conn (:es-index twitter-conf) "tweet" (:id_str t) t)
        (catch Exception ex (log/error ex "esd/put error"))))))


Make the processing display keep-on-top and resizable.

--- dev/org/playasophy/wonderdome/display/processing.clj
+++ dev/org/playasophy/wonderdome/display/processing.clj
@@ -124,6 +124,7 @@
     (assoc this :sketch
       (quil/sketch
         :title "Playasophy Wonderdome"
+        :features [:keep-on-top :resizable]
         :setup setup-sketch
         :draw #(render this)
         :size (:size this)


new basecamp featuring noun phrases with relative clauses

--- src/babel/english/lab.cljc
+++ src/babel/english/lab.cljc
@@ -24,33 +24,24 @@
                             model)
                            :show-notes false))))))
 (defn basecamp []
+  ;; TODO: improve performance by using {:mod {:first {:obj :modified}}.
   (let [specs
         [
-
-         {:synsem {:cat :verb
-                   :sem {:pred :give-x-to-y
-                         :reflexive false
-                         :obj {:pred :cat
-                               :mod {:first {:pred :black}}}}
-                   :subcat []}}
-
-         {:head {:comp {:synsem {:cat :prep}}}
-          :synsem {:cat :verb
-                   :sem {:pred :give-x-to-y
-                         :reflexive false
-                         :obj {:pred :book
-                               :mod {:first {:pred :red}}}}
-                   :subcat []}}
-
-         {:synsem {:cat :verb
-                   :sem {:pred :give-x-to-y
-                         :reflexive true}
-                   :subcat []}}]]
+         {:synsem {:cat :verb :subcat []}
+          :comp {:phrasal true :rule "noun-phrase"
+                 :head {:rule "nbar-s-obj" :head {:rule "nbar"} :comp {:rule "s/obj"}}
+                 :synsem {:sem {:mod {:first {:pred :eat}
+                                      :rest {:first {:pred :red
+                                                     :rest []}}}}}}}
+         {:synsem {:cat :verb :subcat []}
+          :comp {:phrasal true :rule "noun-phrase"
+                 :head {:rule "nbar-s-obj"}
+                 :synsem {:sem {:mod {:first {:pred :see}
+                                      :rest {:first {:pred :tall
+                                                     :rest []}}}}}}}]]
     (repeatedly #(println
                   (let [spec (first (shuffle specs))]
-                    (morph (time (generate spec model))
-                           :show-notes false))))))
-
+                    (morph (time (generate spec model))))))))
 (defn nextcamp []
   (let [parse (-> "the small dogs you see" parse first)]
     (pprint (u/get-in parse [:synsem :sem]))))


allow yesterdays in EN

allow yesterdays in EN

--- resources/languages/en/rules/time.clj
+++ resources/languages/en/rules/time.clj
@@ -188,15 +188,15 @@
   (cycle-nth :second 0)

   "today"
-  #"(?i)today|(at this time)"
+  #"(?i)todays?|(at this time)"
   (cycle-nth :day 0)

   "tomorrow"
-  #"(?i)(tmrw?|tomm?or?row)"
+  #"(?i)(tmrw?|tomm?or?rows?)"
   (cycle-nth :day 1)

   "yesterday"
-  #"(?i)yesterday"
+  #"(?i)yesterdays?"
   (cycle-nth :day -1)

   "EOM|End of month"


validation mapping

validation mapping

--- src/celestial/persistency/systems.clj
+++ src/celestial/persistency/systems.clj
@@ -23,6 +23,7 @@
     [celestial.common :refer (import-logging)]
     [physical.validations :as ph]
     [proxmox.validations :as pv]
+    [openstack.validations :as ov]
     [docker.validations :as dv]
     [aws.validations :as av]
     [vc.validations :as vc]
@@ -113,6 +114,7 @@
   (get-in (get-system id) [:machine :ip]))

 (def hyp-to-v {
+   :openstack ov/validate-entity
    :physical ph/validate-entity
    :proxmox pv/validate-entity
    :docker dv/validate-entity


Documentation examples.

Documentation examples.

--- src/clj/elephantdb/keyval/testing.clj
+++ src/clj/elephantdb/keyval/testing.clj
@@ -115,6 +115,16 @@
              :shard-fn shard-fn)))

 (defmacro with-domain
+  "Used as:
+
+   (with-domain [my-domain domain-spec
+                 [[1 2] [3 4]]
+                 :version 5
+                 :shard-fn (constantly 10)]
+          (seq my-domain))
+
+  A domain with the supplied domain-spec is bound to `sym` inside the
+  body of `with-domain`."
   [[sym spec kv-pairs & {:keys [version shard-fn]}] & body]
   `(t/with-fs-tmp [fs# path#]
      (mk-kv-domain ~spec path# ~kv-pairs
@@ -135,6 +145,14 @@
              :version  version)))

 (defmacro with-presharded-domain
+  "Unlike with-domain, with-presharded-domain accepts a map of
+   shard->key-val sequence.
+
+   (with-domain [my-domain domain-spec
+                {0 [[1 2] [3 4]]
+                 3 [[4 5]]}
+                 :version 100]
+          (seq my-domain))"
   [[sym spec shard-map & {:keys [version]}] & body]
   `(t/with-fs-tmp [fs# path#]
      (mk-presharded-kv-domain ~spec path# ~shard-map


Thread ID no longer needs to be a string

I was doing this pre-spec, when some IDs were sent as strings and some
as Uuids. I changed them all to Uuids, so this code was no longer
necessary.

--- src/clj/memento/routes/api/memory.clj
+++ src/clj/memento/routes/api/memory.clj
@@ -58,6 +58,4 @@
   (ok (->> id
            memory/query-thread
            (filter #(= (:username %) username))
-           ;; I'll return the id as a string so that the frontend doesn't
-           ;; have to do any parsing guesswork.
-           (hash-map :id (str id) :results))))+           (hash-map :id id :results))))


Listen for commands on channel, and extract functions for handling events/commands

--- src/cljs/goya/components/drawing.cljs
+++ src/cljs/goya/components/drawing.cljs
@@ -362,6 +362,84 @@

 ;; =============================================================================

+(defn handle-mouse-event [app owner e]
+  (let [event-type (.-type e)
+        [x y] (unpack-event e)
+        zoom-factor (get-in @app [:zoom-factor])
+        [doc-x doc-y] (geometry/screen-to-doc x y zoom-factor)
+        doc-width (get-in @app [:main-app :canvas-width])
+        doc-height (get-in @app [:main-app :canvas-height])
+        paint-tool (get-in @app [:tools :paint-tool])]
+    (when (= event-type "mousedown")
+      (when (not (= paint-tool :selection))
+        (reset! guistate/transient-state
+                (assoc @guistate/transient-state :user-is-drawing true))
+        (reset! guistate/transient-state
+                (assoc @guistate/transient-state :mouse-down-pos [doc-x doc-y]))
+        (paint-canvas-mouse-pos app owner e))
+      (when (= paint-tool :selection)
+        (let [mouse-is-within-selection (geometry/contains-point
+                                           (om/get-state owner :selection)
+                                           [doc-x doc-y])
+              [x1 y1 x2 y2] (om/get-state owner :selection)
+              offset-in-selection [(- doc-x x1) (- doc-y y1)]]
+           (when mouse-is-within-selection
+                 (om/set-state! owner :user-is-moving-selection true)
+                 (om/set-state! owner :mouse-offset-in-selection offset-in-selection)))
+        (reset! guistate/transient-state
+                (assoc @guistate/transient-state :user-is-drawing true))
+        (reset! guistate/transient-state
+                (assoc @guistate/transient-state :mouse-down-pos [doc-x doc-y]))
+        (paint-canvas-mouse-pos app owner e)))
+
+    (when (= event-type "mouseup")
+      (when (= paint-tool :brush)
+        (reset! guistate/transient-state
+                (assoc @guistate/transient-state :last-mouse-pos [])))
+      (when (= paint-tool :box)
+        (visit-pixels-for-rect-tool doc-x doc-y doc-width))
+      (when (= paint-tool :line)
+        (let [last-x ((get-in @guistate/transient-state [:mouse-down-pos]) 0)
+              last-y ((get-in @guistate/transient-state [:mouse-down-pos]) 1)]
+          (visit-pixels-for-line-segment doc-x doc-y last-x last-y doc-width)))
+      (when (= paint-tool :fill)
+        (visit-pixels-for-fill-tool doc-x doc-y (canvas/get-current-pixels @app) doc-width doc-height))
+      (when (= paint-tool :picker)
+        (pick-color app doc-x doc-y doc-width))
+      (when (and (= paint-tool :selection) (not (om/get-state owner :user-is-moving-selection)))
+        (make-selection app owner doc-x doc-y doc-width))
+      (when (and (= paint-tool :selection) (om/get-state owner :user-is-moving-selection))
+        (let [[xOff yOff] (om/get-state owner :mouse-offset-in-selection)
+              [x1 y1 x2 y2] (om/get-state owner :selection)
+              paste-x (- doc-x xOff)
+              paste-y (- doc-y yOff)
+              backfill (create-sub-image-for-rect (om/get-state owner :selection)
+                                                  (get-in @app [:tools :paint-color]))]
+        (paste-image app owner x1 y1 backfill)
+        (paste-image app owner paste-x paste-y (om/get-state owner :selection-image)))
+        (clear-selection-state owner)
+        (om/transact! app
+          [:main-app :undo-history]
+          #(conj % {:action (str "Moved Pixels") :icon "move"})
+          :add-to-undo))
+      (commit-stroke app)
+      (reset! guistate/transient-state
+              (assoc @guistate/transient-state :user-is-drawing false)))
+
+    (when (and (= event-type "mousemove") (:user-is-drawing @guistate/transient-state))
+      (paint-canvas-mouse-pos app owner e))
+
+    (when (= event-type "mousemove")
+      (reset! guistate/transient-state (assoc @guistate/transient-state :mouse-pos [doc-x doc-y])))))
+
+
+
+(defn handle-command [app owner e]
+  (println (str "Command Request: " e))
+)
+
+;; =============================================================================
+
 (defn canvas-painting-component [app owner]
   (reify
     om/IInitState
@@ -381,80 +459,13 @@

     om/IWillMount
     (will-mount [_]
-       (let [mouse-chan (om/get-state owner :mouse-chan)]
+       (let [mouse-chan (om/get-state owner :mouse-chan)
+             command-chan (om/get-shared owner :command-chan)]
         (go
           (loop []
-            (let [e (<! mouse-chan)
-                  event-type (.-type e)
-                  [x y] (unpack-event e)
-                  zoom-factor (get-in @app [:zoom-factor])
-                  [doc-x doc-y] (geometry/screen-to-doc x y zoom-factor)
-                  doc-width (get-in @app [:main-app :canvas-width])
-                  doc-height (get-in @app [:main-app :canvas-height])
-                  paint-tool (get-in @app [:tools :paint-tool])]
-
-                  (when (= event-type "mousedown")
-                    (when (not (= paint-tool :selection))
-                      (reset! guistate/transient-state
-                              (assoc @guistate/transient-state :user-is-drawing true))
-                      (reset! guistate/transient-state
-                              (assoc @guistate/transient-state :mouse-down-pos [doc-x doc-y]))
-                      (paint-canvas-mouse-pos app owner e))
-                    (when (= paint-tool :selection)
-                      (let [mouse-is-within-selection (geometry/contains-point
-                                                         (om/get-state owner :selection)
-                                                         [doc-x doc-y])
-                            [x1 y1 x2 y2] (om/get-state owner :selection)
-                            offset-in-selection [(- doc-x x1) (- doc-y y1)]]
-                         (when mouse-is-within-selection
-                               (om/set-state! owner :user-is-moving-selection true)
-                               (om/set-state! owner :mouse-offset-in-selection offset-in-selection)))
-                      (reset! guistate/transient-state
-                              (assoc @guistate/transient-state :user-is-drawing true))
-                      (reset! guistate/transient-state
-                              (assoc @guistate/transient-state :mouse-down-pos [doc-x doc-y]))
-                      (paint-canvas-mouse-pos app owner e)))
-
-                  (when (= event-type "mouseup")
-                    (when (= paint-tool :brush)
-                      (reset! guistate/transient-state
-                              (assoc @guistate/transient-state :last-mouse-pos [])))
-                    (when (= paint-tool :box)
-                      (visit-pixels-for-rect-tool doc-x doc-y doc-width))
-                    (when (= paint-tool :line)
-                      (let [last-x ((get-in @guistate/transient-state [:mouse-down-pos]) 0)
-                            last-y ((get-in @guistate/transient-state [:mouse-down-pos]) 1)]
-                        (visit-pixels-for-line-segment doc-x doc-y last-x last-y doc-width)))
-                    (when (= paint-tool :fill)
-                      (visit-pixels-for-fill-tool doc-x doc-y (canvas/get-current-pixels @app) doc-width doc-height))
-                    (when (= paint-tool :picker)
-                      (pick-color app doc-x doc-y doc-width))
-                    (when (and (= paint-tool :selection) (not (om/get-state owner :user-is-moving-selection)))
-                      (make-selection app owner doc-x doc-y doc-width))
-                    (when (and (= paint-tool :selection) (om/get-state owner :user-is-moving-selection))
-                      (let [[xOff yOff] (om/get-state owner :mouse-offset-in-selection)
-                            [x1 y1 x2 y2] (om/get-state owner :selection)
-                            paste-x (- doc-x xOff)
-                            paste-y (- doc-y yOff)
-                            backfill (create-sub-image-for-rect (om/get-state owner :selection)
-                                                                (get-in @app [:tools :paint-color]))]
-                      (paste-image app owner x1 y1 backfill)
-                      (paste-image app owner paste-x paste-y (om/get-state owner :selection-image)))
-                      (clear-selection-state owner)
-                      (om/transact! app
-                        [:main-app :undo-history]
-                        #(conj % {:action (str "Moved Pixels") :icon "move"})
-                        :add-to-undo))
-                    (commit-stroke app)
-                    (reset! guistate/transient-state
-                            (assoc @guistate/transient-state :user-is-drawing false)))
-
-                  (when (and (= event-type "mousemove") (:user-is-drawing @guistate/transient-state))
-                    (paint-canvas-mouse-pos app owner e))
-
-                  (when (= event-type "mousemove")
-                    (reset! guistate/transient-state (assoc @guistate/transient-state :mouse-pos [doc-x doc-y])))
-
+            (let [[v ch] (alts! [mouse-chan command-chan])]
+              (when (= ch mouse-chan) (handle-mouse-event app owner v))
+              (when (= ch command-chan) (handle-command app owner v))
           (recur))))))

     ;; =============================================================================


- "?§=)&&t!&%!!

- "?§=)&&t!&%!!

--- src/clojure/spring/surf/webscript.clj
+++ src/clojure/spring/surf/webscript.clj
@@ -54,16 +54,51 @@
 ;;   (-> (c/getbean "javaScriptProcessor")
 ;;       ()))

+;; (defmacro let-jmap [vars & forms]
+;;   "Set up bindings for the entire map. Yes, that may look dangerous and bad. It
+;;  makes sense. Trust me."
+;;   (let [model ~vars])
+;;   `(eval
+;;       (list 'let (->> ~vars
+;;                       .entrySet
+;;                       (map (fn [sym#] [(-> sym# .getKey symbol)
+;;                                        (.get ~vars (.getValue sym#))]))
+;;                       ;; (.get ~vars (.getKey sym#))]))
+;;                       ;; (.getValue sym#)
+;;                       (cons [(symbol "model") ~vars])
+;;                       (apply concat)
+;;                       vec)
+;;             '~(conj forms 'do)))
+;;   )
+
 (defmacro let-jmap [vars & forms]
   "Set up bindings for the entire map. Yes, that may look dangerous and bad. It
  makes sense. Trust me."
-  `(eval (list 'let (->> ~vars
-                         .entrySet
-                         (map (fn [sym#] [(-> sym# .getKey symbol)
-                                          (.getValue sym#)]))
-                         (apply concat)
-                         vec)
-               '~(conj forms 'do))))
+  `(eval
+    (list 'let (->> ~vars
+                    .entrySet
+                    (map (fn [sym#] [(-> sym# .getKey symbol)
+                                     (list '.get
+                                           (symbol "model")
+                                           (.getKey sym#))]))
+                    (cons [(symbol "model") '~vars])
+                    (apply concat)
+                    vec)
+          '~(conj forms 'do))))
+
+;; )
+
+;; (defmacro let-jmap2 [vars & forms]
+;;   "Set up bindings for the entire map. Yes, that may look dangerous and bad. It
+;;  makes sense. Trust me."
+;;   `(list 'let (->> ~vars
+;;                    .entrySet
+;;                    (map (fn [sym#] [(-> sym# .getKey symbol)
+;;                                     (.getValue sym#)]))
+;;                    (apply concat)
+;;                    vec)
+;;                '~(conj forms 'do)))
+

 (defmacro create-script
   "Create a (web)script for the processor(s)."
@@ -71,6 +106,10 @@
   (let [{:keys [webscript] :or {webscript true}} options]
     `(reify spring.surf.webscript.WebScript
        (run [~'this ~'model]
-         ~(if webscript
-            `(merge-jmap-model ~'model (~f ~'model))
-            `(~f ~'model))))))
+         ;; Wrap bindings
+         ;; (let [~'model ~'model]
+         (let-jmap ~'model
+           ~(if webscript
+              `(merge-jmap-model ~'model (~f))
+              `(~f)))
+         ))))


debugs for fix

debugs for fix

--- src/clojure/tfevent_sink/event_io.clj
+++ src/clojure/tfevent_sink/event_io.clj
@@ -104,13 +104,17 @@
 (defmethod make-event
   [String java.lang.Double]
   [tag v]
-  (let [sum1 (doto
-              (Summary/newBuilder)
-               (.addValue
-                (.build (doto (Summary$Value/newBuilder)
-                          (.setTag tag)
-                          (.setSimpleValue v)))))]
-    (summary tag sum1)))
+  (try
+    (let [sum1 (doto
+                   (Summary/newBuilder)
+                 (.addValue
+                  (.build (doto (Summary$Value/newBuilder)
+                            (.setTag tag)
+                            (.setSimpleValue v)))))]
+      (summary tag sum1))
+    (catch Exception e
+      (println (str " error in make-event " tag " - " v) (.getMessage e))
+      nil)))

 (defn build-hist
   [tag values]