diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index a91a9094b..6d3ee7e4b 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -114,7 +114,7 @@ export default defineConfig({ collapsed: true, items: [ { text: "$compact", link: "/api/operation/compact" }, - { text: "$cql", link: "/api/operation/cql" } + { text: "$cql", link: "/api/operation/cql" }, ], }, { @@ -166,6 +166,7 @@ export default defineConfig({ { text: "CQL Queries", items: [ + { text: "Overview", link: "/cql-queries" }, { text: "via blazectl", link: "/cql-queries/blazectl" }, { text: "via API", link: "/cql-queries/api" }, { text: "Conformance", link: "/conformance/cql" }, diff --git a/docs/performance/cql/condition-sct-disease.cql b/docs/performance/cql/condition-sct-disease.cql new file mode 100644 index 000000000..5af61d39e --- /dev/null +++ b/docs/performance/cql/condition-sct-disease.cql @@ -0,0 +1,10 @@ +library "condition-sct-disease" +using FHIR version '4.0.0' +include FHIRHelpers version '4.0.0' + +valueset sct_disease: 'http://fhir.org/VCL?v1=(http://snomed.info/sct)concept<<22253000' + +context Patient + +define InInitialPopulation: + exists [Condition: sct_disease] diff --git a/docs/performance/cql/condition-sct-disease.yml b/docs/performance/cql/condition-sct-disease.yml new file mode 100644 index 000000000..80f746ebf --- /dev/null +++ b/docs/performance/cql/condition-sct-disease.yml @@ -0,0 +1,5 @@ +library: cql/condition-sct-disease.cql +group: +- type: Patient + population: + - expression: InInitialPopulation diff --git a/docs/terminology-service/vcl.md b/docs/terminology-service/vcl.md index 00bd044c5..56e59ab37 100644 --- a/docs/terminology-service/vcl.md +++ b/docs/terminology-service/vcl.md @@ -2,9 +2,38 @@ > [!CAUTION] > The VCL standard is curently in development. The implementation in currently **beta**. - + The VCL documentation can be found [here](https://build.fhir.org/ig/FHIR/ig-guidance/vcl.html). +## Operations + +The following operations support VCL: + +* [ValueSet \$expand](../api/operation/value-set-expand.md) +* [ValueSet \$validate-code](../api/operation/value-set-validate-code.md) + +## Usage + +ValueSets can be created on-the-fly by using the ValueSet Compose Language (VCL) at any place where a ValueSet URL can be specified. + +A VCL implicit value set URL has two parts: + +* The base URL which is `http://fhir.org/VCL` +* A query portion that specifies the VCL expression itself: `?v1=` where `` is the percent-encoded VCL expression. + +**Example:** + +To use the VCL expression `(http://loinc.org)COMPONENT=LP14449-0`, the full URL would be: + +`http://fhir.org/VCL?v1=(http://loinc.org)COMPONENT=LP14449-0` (properly encoded in actual usage). + +### Examples + +| Expression | URL | +|-----------------------------------------------------|----------------------------------------------------------------------------| +| `(http://loinc.org)(parent^{LP46821-2,LP259418-4})` | `http://fhir.org/VCL?v1=(http://loinc.org)(parent^{LP46821-2,LP259418-4})` | +| `(http://snomed.info/sct)concept<<119297000` | `http://fhir.org/VCL?v1=(http://snomed.info/sct)concept<<119297000` | + ## Tested VCL Expressions ``` diff --git a/modules/admin-api/test/blaze/admin_api_test.clj b/modules/admin-api/test/blaze/admin_api_test.clj index d4bcc1d3f..9bf465fe5 100644 --- a/modules/admin-api/test/blaze/admin_api_test.clj +++ b/modules/admin-api/test/blaze/admin_api_test.clj @@ -31,6 +31,8 @@ [blaze.module.test-util :refer [given-failed-system with-system]] [blaze.page-store-spec] [blaze.page-store.local] + [blaze.terminology-service :as-alias ts] + [blaze.terminology-service.local :as local] [blaze.test-util :as tu] [blaze.util-spec] [clojure.spec.alpha :as s] @@ -189,7 +191,15 @@ [:blaze.db.node.resource-indexer/executor :blaze.db.node.resource-indexer.admin/executor] {} :blaze.db/search-param-registry - {:structure-definition-repo structure-definition-repo} + {:structure-definition-repo structure-definition-repo + :terminology-service (ig/ref ::ts/local)} + + ::ts/local + {:clock (ig/ref :blaze.test/fixed-clock) + :rng-fn (ig/ref :blaze.test/fixed-rng-fn) + :graph-cache (ig/ref ::local/graph-cache)} + + ::local/graph-cache {} [:blaze.fhir/parsing-context :blaze.fhir.parsing-context/default] {:structure-definition-repo structure-definition-repo} diff --git a/modules/cql/src/blaze/elm/compiler/external_data.clj b/modules/cql/src/blaze/elm/compiler/external_data.clj index 274b61908..a7d1877f8 100644 --- a/modules/cql/src/blaze/elm/compiler/external_data.clj +++ b/modules/cql/src/blaze/elm/compiler/external_data.clj @@ -15,6 +15,7 @@ [blaze.elm.resource :as cr] [blaze.elm.spec] [blaze.elm.util :as elm-util] + [blaze.elm.value-set :as value-set] [blaze.fhir.spec.references :as fsr] [blaze.util :refer [str]] [prometheus.alpha :as prom :refer [defcounter]])) @@ -26,9 +27,6 @@ {:namespace "blaze" :subsystem "cql"}) -(defn- code->clause-value [{:keys [system code]}] - (str system "|" code)) - (defn- code-expr "Returns an expression which, when evaluated, returns all resources of type `data-type` which have a code equivalent to `code` at `property` and are @@ -37,26 +35,24 @@ Example: * data-type - \"Observation\" * eval-context - \"Patient\" - * property - \"code\" - * codes - [(code \"http://loinc.org\" nil \"39156-5\")]" - [node eval-context data-type property codes] - (let [clauses [(into [property] (map code->clause-value) codes)]] - (if-ok [type-query (d/compile-type-query node data-type clauses) - compartment-query (d/compile-compartment-query node eval-context - data-type clauses)] - (reify-expr core/Expression - (-optimize [expr db] - ;; if there is no resource, regardless of the individual patient, - ;; available, just return an empty list for further optimizations - (if (coll/empty? (d/execute-query db type-query)) - [] - expr)) - (-eval [_ {:keys [db]} {:keys [id]} _] - (prom/inc! retrieve-total) - (coll/eduction (cr/resource-mapper db) (d/execute-query db compartment-query id))) - (-form [_] - `(~'retrieve ~data-type ~(d/query-clauses compartment-query)))) - throw-anom))) + * codes-expr - [[\"code\" \"http://loinc.org|39156-5\"]]" + [node eval-context data-type clauses] + (if-ok [type-query (d/compile-type-query node data-type clauses) + compartment-query (d/compile-compartment-query node eval-context + data-type clauses)] + (reify-expr core/Expression + (-optimize [expr db] + ;; if there is no resource, regardless of the individual patient, + ;; available, just return an empty list for further optimizations + (if (coll/empty? (d/execute-query db type-query)) + [] + expr)) + (-eval [_ {:keys [db]} {:keys [id]} _] + (prom/inc! retrieve-total) + (coll/eduction (cr/resource-mapper db) (d/execute-query db compartment-query id))) + (-form [_] + `(~'retrieve ~data-type ~(d/query-clauses compartment-query)))) + throw-anom)) ;; TODO: find a better solution than hard coding this case (def ^:private specimen-patient-expr @@ -135,56 +131,54 @@ (list 'retrieve (core/-form related-context-expr) data-type (d/query-clauses query))))) (defn- related-context-expr - [node context-expr data-type code-property codes] - (if (seq codes) + [node context-expr data-type clauses] + (if (seq clauses) (if-let [result-type-name (:result-type-name (meta context-expr))] (let [[value-type-ns context-type] (elm-util/parse-qualified-name result-type-name)] (if (= "http://hl7.org/fhir" value-type-ns) - (let [clauses [(into [code-property] (map code->clause-value) codes)]] - (if-ok [query (d/compile-compartment-query node context-type data-type clauses)] - (related-context-expr-with-codes context-expr data-type query) - throw-anom)) + (if-ok [query (d/compile-compartment-query node context-type data-type clauses)] + (related-context-expr-with-codes context-expr data-type query) + throw-anom) (throw-anom (unsupported-type-ns-anom value-type-ns)))) (throw-anom unsupported-related-context-expr-without-type-anom)) (related-context-expr-without-codes context-expr data-type))) -(defn- unfiltered-context-expr [node data-type code-property codes] - (if (empty? codes) +(defn- unfiltered-context-expr [node data-type clauses] + (if (empty? clauses) (reify-expr core/Expression (-eval [_ {:keys [db]} _ _] (prom/inc! retrieve-total) (coll/eduction (cr/resource-mapper db) (d/type-list db data-type))) (-form [_] `(~'retrieve ~data-type))) - (let [clauses [(into [code-property] (map code->clause-value) codes)]] - (if-ok [query (d/compile-type-query node data-type clauses)] - (reify-expr core/Expression - (-eval [_ {:keys [db]} _ _] - (prom/inc! retrieve-total) - (coll/eduction (cr/resource-mapper db) (d/execute-query db query))) - (-form [_] - `(~'retrieve ~data-type ~(d/query-clauses query)))) - throw-anom)))) - -(defn- expr* [node eval-context data-type code-property codes] - (if (empty? codes) + (if-ok [query (d/compile-type-query node data-type clauses)] + (reify-expr core/Expression + (-eval [_ {:keys [db]} _ _] + (prom/inc! retrieve-total) + (coll/eduction (cr/resource-mapper db) (d/execute-query db query))) + (-form [_] + `(~'retrieve ~data-type ~(d/query-clauses query)))) + throw-anom))) + +(defn- expr* [node eval-context data-type clauses] + (if (empty? clauses) (if (= data-type eval-context) resource-expr (context-expr eval-context data-type)) - (code-expr node eval-context data-type code-property codes))) + (code-expr node eval-context data-type clauses))) ;; 11.1. Retrieve (defn- expr - [{:keys [node eval-context]} context-expr data-type code-property codes] + [{:keys [node eval-context]} context-expr data-type clauses] (cond context-expr - (related-context-expr node context-expr data-type code-property codes) + (related-context-expr node context-expr data-type clauses) (= "Unfiltered" eval-context) - (unfiltered-context-expr node data-type code-property codes) + (unfiltered-context-expr node data-type clauses) :else - (expr* node eval-context data-type code-property codes))) + (expr* node eval-context data-type clauses))) (defn- unsupported-dynamic-codes-expr-anom [codes-expr] (ba/unsupported @@ -196,10 +190,17 @@ (format "Unsupported type namespace `%s` in Retrieve expression." type-ns) :type-ns type-ns)) -(defn- compile-codes-expr [context codes-expr] +(defn- code->clause-value [{:keys [system code]}] + (str system "|" code)) + +(defn- compile-codes-expr [context code-property codes-expr] (let [codes-expr (core/compile* context codes-expr)] - (if (and (sequential? codes-expr) (every? code? codes-expr)) - codes-expr + (cond + (and (sequential? codes-expr) (every? code? codes-expr)) + [(into [code-property] (map code->clause-value) codes-expr)] + (value-set/value-set? codes-expr) + [[(str code-property ":in") (value-set/url codes-expr)]] + :else (throw-anom (unsupported-dynamic-codes-expr-anom codes-expr))))) (defmethod core/compile* :elm.compiler.type/retrieve @@ -215,6 +216,5 @@ context (some->> context-expr (core/compile* context)) data-type - code-property - (some->> codes-expr (compile-codes-expr context))) + (some->> codes-expr (compile-codes-expr context code-property))) (throw-anom (unsupported-type-namespace-anom type-ns))))) diff --git a/modules/cql/src/blaze/elm/ts_util.clj b/modules/cql/src/blaze/elm/ts_util.clj index 6219484c3..9082c4f5d 100644 --- a/modules/cql/src/blaze/elm/ts_util.clj +++ b/modules/cql/src/blaze/elm/ts_util.clj @@ -1,6 +1,7 @@ (ns blaze.elm.ts-util (:require [blaze.anomaly :as ba :refer [throw-anom]] + [blaze.elm.code :as code] [blaze.fhir.spec.type :as type])) (def ^:private result-pred @@ -12,6 +13,15 @@ (catch Exception e (throw-anom (ba/fault (msg-fn (ex-message (ex-cause e)))))))) +(defn- to-code [{:keys [system version code]}] + (code/code (:value system) (:value version) (:value code))) + +(defn extract-codes [response msg-fn] + (try + (mapv to-code (:contains (:expansion @response))) + (catch Exception e + (throw-anom (ba/fault (msg-fn (ex-message (ex-cause e)))))))) + (defn code-param [code] {:fhir/type :fhir.Parameters/parameter :name #fhir/string "code" diff --git a/modules/cql/src/blaze/elm/value_set.clj b/modules/cql/src/blaze/elm/value_set.clj index 6528d185e..046c4830c 100644 --- a/modules/cql/src/blaze/elm/value_set.clj +++ b/modules/cql/src/blaze/elm/value_set.clj @@ -6,6 +6,12 @@ [blaze.fhir.spec.type :as type] [blaze.terminology-service :as ts])) +(defn value-set? [x] + (satisfies? p/ValueSet x)) + +(defn url [value-set] + (p/-url value-set)) + (defn contains-string? [value-set code] (p/-contains-string value-set code)) @@ -15,6 +21,9 @@ (defn contains-concept? [value-set concept] (p/-contains-concept value-set concept)) +(defn expand [value-set] + (p/-expand value-set)) + (defn- system-param [system] {:fhir/type :fhir.Parameters/parameter :name #fhir/string "system" @@ -47,6 +56,8 @@ (list 'value-set url)) p/ValueSet + (-url [_] + url) (-contains-string [_ code] (tu/extract-result (ts/value-set-validate-code @@ -77,4 +88,14 @@ (fn [cause-msg] (format "Error while testing that the %s is in ValueSet `%s`. Cause: %s" - concept url cause-msg))))))) + concept url cause-msg)))) + (-expand [_] + (tu/extract-codes + (ts/expand-value-set + terminology-service + {:fhir/type :fhir/Parameters + :parameter [url-param]}) + (fn [cause-msg] + (format + "Error while expanding the ValueSet `%s`. Cause: %s" + url cause-msg))))))) diff --git a/modules/cql/src/blaze/elm/value_set/protocol.clj b/modules/cql/src/blaze/elm/value_set/protocol.clj index 3eca6b6a1..cfd474cd3 100644 --- a/modules/cql/src/blaze/elm/value_set/protocol.clj +++ b/modules/cql/src/blaze/elm/value_set/protocol.clj @@ -1,6 +1,8 @@ (ns blaze.elm.value-set.protocol) (defprotocol ValueSet - (-contains-string [_ code]) - (-contains-code [_ code]) - (-contains-concept [_ concept])) + (-url [_]) + (-contains-string [value-set code]) + (-contains-code [value-set code]) + (-contains-concept [value-set concept]) + (-expand [value-set])) diff --git a/modules/cql/test-perf/blaze/elm/compiler/library_test_perf.clj b/modules/cql/test-perf/blaze/elm/compiler/library_test_perf.clj index 8ca7311cc..a3bee170f 100644 --- a/modules/cql/test-perf/blaze/elm/compiler/library_test_perf.clj +++ b/modules/cql/test-perf/blaze/elm/compiler/library_test_perf.clj @@ -1,7 +1,7 @@ (ns blaze.elm.compiler.library-test-perf (:require [blaze.cql.translator :as t] - [blaze.db.api-stub :refer [mem-node-config]] + [blaze.db.api-stub :as api-stub] [blaze.elm.compiler.library :as library] [blaze.elm.compiler.library-spec] [blaze.fhir.spec.type.system] @@ -10,20 +10,12 @@ [blaze.terminology-service.local] [clojure.test :refer [deftest]] [criterium.core :as criterium] - [integrant.core :as ig] [taoensso.timbre :as log])) (log/set-min-level! :info) -(def config - (assoc - mem-node-config - ::ts/local - {:node (ig/ref :blaze.db/node) - :clock (ig/ref :blaze.test/fixed-clock)})) - (deftest compile-test (let [library (t/translate "library \"antidiabetika\"\nusing FHIR version '4.0.0'\ninclude FHIRHelpers version '4.0.0'\n\ncodesystem atc: 'http://fhir.de/CodeSystem/bfarm/atc'\n\ncontext Unfiltered\n\ndefine GliclazidA10BB09Ref:\n from [Medication: Code 'A10BB09' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Insulin degludec und Insulin aspartA10AD06Ref\":\n from [Medication: Code 'A10AD06' from atc] M\n return 'Medication/' + M.id\n\ndefine SulfonylharnstoffeA10BBRef:\n from [Medication: Code 'A10BB' from atc] M\n return 'Medication/' + M.id\n\ndefine TolbutamidA10BB03Ref:\n from [Medication: Code 'A10BB03' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Insuline und Analoga zur Injektion, intermediär oder lang wirkend kombiniert mit schnell wirkendA10ADRef\":\n from [Medication: Code 'A10AD' from atc] M\n return 'Medication/' + M.id\n\ndefine LiraglutidA10BJ02Ref:\n from [Medication: Code 'A10BJ02' from atc] M\n return 'Medication/' + M.id\n\ndefine EvogliptinA10BH07Ref:\n from [Medication: Code 'A10BH07' from atc] M\n return 'Medication/' + M.id\n\ndefine GlibornuridA10BB04Ref:\n from [Medication: Code 'A10BB04' from atc] M\n return 'Medication/' + M.id\n\ndefine ErtugliflozinA10BK04Ref:\n from [Medication: Code 'A10BK04' from atc] M\n return 'Medication/' + M.id\n\ndefine KombinationenA10AE30Ref:\n from [Medication: Code 'A10AE30' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Metformin und SulfonylharnstoffeA10BD02Ref\":\n from [Medication: Code 'A10BD02' from atc] M\n return 'Medication/' + M.id\n\ndefine AcetohexamidA10BB31Ref:\n from [Medication: Code 'A10BB31' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Metformin und AcarboseA10BD17Ref\":\n from [Medication: Code 'A10BD17' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Glimepirid und RosiglitazonA10BD04Ref\":\n from [Medication: Code 'A10BD04' from atc] M\n return 'Medication/' + M.id\n\ndefine ChlorpropamidA10BB02Ref:\n from [Medication: Code 'A10BB02' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Insuline und Analoga zur Injektion, schnell wirkendA10ABRef\":\n from [Medication: Code 'A10AB' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Insulin (human)A10AC01Ref\":\n from [Medication: Code 'A10AC01' from atc] M\n return 'Medication/' + M.id\n\ndefine VogliboseA10BF03Ref:\n from [Medication: Code 'A10BF03' from atc] M\n return 'Medication/' + M.id\n\ndefine GlimepiridA10BB12Ref:\n from [Medication: Code 'A10BB12' from atc] M\n return 'Medication/' + M.id\n\ndefine DapagliflozinA10BK01Ref:\n from [Medication: Code 'A10BK01' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Metformin und DapagliflozinA10BD15Ref\":\n from [Medication: Code 'A10BD15' from atc] M\n return 'Medication/' + M.id\n\ndefine KombinationenA10AB30Ref:\n from [Medication: Code 'A10AB30' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Insulin degludec und LiraglutidA10AE56Ref\":\n from [Medication: Code 'A10AE56' from atc] M\n return 'Medication/' + M.id\n\ndefine CanagliflozinA10BK02Ref:\n from [Medication: Code 'A10BK02' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Metformin und AlogliptinA10BD13Ref\":\n from [Medication: Code 'A10BD13' from atc] M\n return 'Medication/' + M.id\n\ndefine ExenatidA10BJ01Ref:\n from [Medication: Code 'A10BJ01' from atc] M\n return 'Medication/' + M.id\n\ndefine GliquidonA10BB08Ref:\n from [Medication: Code 'A10BB08' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Insulin glargin und LixisenatidA10AE54Ref\":\n from [Medication: Code 'A10AE54' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Insulin detemirA10AE05Ref\":\n from [Medication: Code 'A10AE05' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Metformin, Saxagliptin und DapagliflozinA10BD25Ref\":\n from [Medication: Code 'A10BD25' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Insulin (Rind)A10AB02Ref\":\n from [Medication: Code 'A10AB02' from atc] M\n return 'Medication/' + M.id\n\ndefine VildagliptinA10BH02Ref:\n from [Medication: Code 'A10BH02' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Phenformin und SulfonylharnstoffeA10BD01Ref\":\n from [Medication: Code 'A10BD01' from atc] M\n return 'Medication/' + M.id\n\ndefine KombinationenA10AC30Ref:\n from [Medication: Code 'A10AC30' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Metformin und ErtugliflozinA10BD23Ref\":\n from [Medication: Code 'A10BD23' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Metformin und SaxagliptinA10BD10Ref\":\n from [Medication: Code 'A10BD10' from atc] M\n return 'Medication/' + M.id\n\ndefine SaxagliptinA10BH03Ref:\n from [Medication: Code 'A10BH03' from atc] M\n return 'Medication/' + M.id\n\ndefine LinagliptinA10BH05Ref:\n from [Medication: Code 'A10BH05' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Guar-Mehl*A10BX01Ref\":\n from [Medication: Code 'A10BX01' from atc] M\n return 'Medication/' + M.id\n\ndefine RosiglitazonA10BG02Ref:\n from [Medication: Code 'A10BG02' from atc] M\n return 'Medication/' + M.id\n\ndefine GlisoxepidA10BB11Ref:\n from [Medication: Code 'A10BB11' from atc] M\n return 'Medication/' + M.id\n\ndefine GlibenclamidA10BB01Ref:\n from [Medication: Code 'A10BB01' from atc] M\n return 'Medication/' + M.id\n\ndefine TeneligliptinA10BH08Ref:\n from [Medication: Code 'A10BH08' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Insulin glulisinA10AB06Ref\":\n from [Medication: Code 'A10AB06' from atc] M\n return 'Medication/' + M.id\n\ndefine AldosereduktasehemmerA10XARef:\n from [Medication: Code 'A10XA' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Insulin aspartA10AB05Ref\":\n from [Medication: Code 'A10AB05' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Insulin glarginA10AE04Ref\":\n from [Medication: Code 'A10AE04' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Insuline Und AnalogaA10ARef\":\n from [Medication: Code 'A10A' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Insulin (Schwein)A10AE03Ref\":\n from [Medication: Code 'A10AE03' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Insulin (human)A10AB01Ref\":\n from [Medication: Code 'A10AB01' from atc] M\n return 'Medication/' + M.id\n\ndefine MetforminA10BA02Ref:\n from [Medication: Code 'A10BA02' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Sulfonamide (heterozyklisch)A10BCRef\":\n from [Medication: Code 'A10BC' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Pioglitazon und SitagliptinA10BD12Ref\":\n from [Medication: Code 'A10BD12' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Homöopathische und anthroposophische AntidiabetikaA10XHRef\":\n from [Medication: Code 'A10XH' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Metformin und EvogliptinA10BD22Ref\":\n from [Medication: Code 'A10BD22' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Insulin (human)A10AE01Ref\":\n from [Medication: Code 'A10AE01' from atc] M\n return 'Medication/' + M.id\n\ndefine SitagliptinA10BH01Ref:\n from [Medication: Code 'A10BH01' from atc] M\n return 'Medication/' + M.id\n\ndefine CopalchirindenextraktA10XP02Ref:\n from [Medication: Code 'A10XP02' from atc] M\n return 'Medication/' + M.id\n\ndefine ImegliminA10BX15Ref:\n from [Medication: Code 'A10BX15' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Metformin und GemigliptinA10BD18Ref\":\n from [Medication: Code 'A10BD18' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Dipeptidyl-Peptidase-4-(DPP-4)-InhibitorenA10BHRef\":\n from [Medication: Code 'A10BH' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Insulin lisproA10AC04Ref\":\n from [Medication: Code 'A10AC04' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Metformin und EmpagliflozinA10BD20Ref\":\n from [Medication: Code 'A10BD20' from atc] M\n return 'Medication/' + M.id\n\ndefine GlipizidA10BB07Ref:\n from [Medication: Code 'A10BB07' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Sitagliptin und SimvastatinA10BH51Ref\":\n from [Medication: Code 'A10BH51' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Metformin und RosiglitazonA10BD03Ref\":\n from [Medication: Code 'A10BD03' from atc] M\n return 'Medication/' + M.id\n\ndefine PhenforminA10BA01Ref:\n from [Medication: Code 'A10BA01' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Gemigliptin und RosuvastatinA10BH52Ref\":\n from [Medication: Code 'A10BH52' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Insulin (Rind)A10AD02Ref\":\n from [Medication: Code 'A10AD02' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Insulin (Schwein)A10AC03Ref\":\n from [Medication: Code 'A10AC03' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Insuline und Analoga zur InhalationA10AFRef\":\n from [Medication: Code 'A10AF' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Linagliptin und EmpagliflozinA10BD19Ref\":\n from [Medication: Code 'A10BD19' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Insuline und Analoga zur Injektion, lang wirkendA10AERef\":\n from [Medication: Code 'A10AE' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Metformin und GlibenclamidA10BD31Ref\":\n from [Medication: Code 'A10BD31' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Sitagliptin und ErtugliflozinA10BD24Ref\":\n from [Medication: Code 'A10BD24' from atc] M\n return 'Medication/' + M.id\n\ndefine BenfluorexA10BX06Ref:\n from [Medication: Code 'A10BX06' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Metformin und VildagliptinA10BD08Ref\":\n from [Medication: Code 'A10BD08' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Glucagon-like-Peptid-1-(GLP-1)-RezeptoragonistenA10BJRef\":\n from [Medication: Code 'A10BJ' from atc] M\n return 'Medication/' + M.id\n\ndefine TroglitazonA10BG01Ref:\n from [Medication: Code 'A10BG01' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Insulin aspartA10AD05Ref\":\n from [Medication: Code 'A10AD05' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Andere AntidiabetikaA10XRef\":\n from [Medication: Code 'A10X' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Insulin (human)A10AD01Ref\":\n from [Medication: Code 'A10AD01' from atc] M\n return 'Medication/' + M.id\n\ndefine AntidiabetikaA10Ref:\n from [Medication: Code 'A10' from atc] M\n return 'Medication/' + M.id\n\ndefine EmpagliflozinA10BK03Ref:\n from [Medication: Code 'A10BK03' from atc] M\n return 'Medication/' + M.id\n\ndefine PioglitazonA10BG03Ref:\n from [Medication: Code 'A10BG03' from atc] M\n return 'Medication/' + M.id\n\ndefine CarbutamidA10BB06Ref:\n from [Medication: Code 'A10BB06' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Insulin lisproA10AB04Ref\":\n from [Medication: Code 'A10AB04' from atc] M\n return 'Medication/' + M.id\n\ndefine MiglitolA10BF02Ref:\n from [Medication: Code 'A10BF02' from atc] M\n return 'Medication/' + M.id\n\ndefine RepaglinidA10BX02Ref:\n from [Medication: Code 'A10BX02' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Metformin und SitagliptinA10BD07Ref\":\n from [Medication: Code 'A10BD07' from atc] M\n return 'Medication/' + M.id\n\ndefine GemigliptinA10BH06Ref:\n from [Medication: Code 'A10BH06' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Insulin (Rind)A10AC02Ref\":\n from [Medication: Code 'A10AC02' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Metformin und RepaglinidA10BD14Ref\":\n from [Medication: Code 'A10BD14' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Insulin (Schwein)A10AB03Ref\":\n from [Medication: Code 'A10AB03' from atc] M\n return 'Medication/' + M.id\n\ndefine KombinationenA10AD30Ref:\n from [Medication: Code 'A10AD30' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Metformin und CanagliflozinA10BD16Ref\":\n from [Medication: Code 'A10BD16' from atc] M\n return 'Medication/' + M.id\n\ndefine SemaglutidA10BJ06Ref:\n from [Medication: Code 'A10BJ06' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Thiazolidindione (Glitazone)A10BGRef\":\n from [Medication: Code 'A10BG' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Kombinationen oraler AntidiabetikaA10BDRef\":\n from [Medication: Code 'A10BD' from atc] M\n return 'Medication/' + M.id\n\ndefine IpragliflozinA10BK05Ref:\n from [Medication: Code 'A10BK05' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Guar-MehlA10XP01Ref\":\n from [Medication: Code 'A10XP01' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Pioglitazon und AlogliptinA10BD09Ref\":\n from [Medication: Code 'A10BD09' from atc] M\n return 'Medication/' + M.id\n\ndefine AcarboseA10BF01Ref:\n from [Medication: Code 'A10BF01' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Saxagliptin und DapagliflozinA10BD21Ref\":\n from [Medication: Code 'A10BD21' from atc] M\n return 'Medication/' + M.id\n\ndefine AlbiglutidA10BJ04Ref:\n from [Medication: Code 'A10BJ04' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Pflanzliche AntidiabetikaA10XPRef\":\n from [Medication: Code 'A10XP' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Insuline und Analoga zur Injektion, intermediär wirkendA10ACRef\":\n from [Medication: Code 'A10AC' from atc] M\n return 'Medication/' + M.id\n\ndefine TolazamidA10BB05Ref:\n from [Medication: Code 'A10BB05' from atc] M\n return 'Medication/' + M.id\n\ndefine SotagliflozinA10BK06Ref:\n from [Medication: Code 'A10BK06' from atc] M\n return 'Medication/' + M.id\n\ndefine TolrestatA10XA01Ref:\n from [Medication: Code 'A10XA01' from atc] M\n return 'Medication/' + M.id\n\ndefine BuforminA10BA03Ref:\n from [Medication: Code 'A10BA03' from atc] M\n return 'Medication/' + M.id\n\ndefine BiguanideA10BARef:\n from [Medication: Code 'A10BA' from atc] M\n return 'Medication/' + M.id\n\ndefine LuseogliflozinA10BK07Ref:\n from [Medication: Code 'A10BK07' from atc] M\n return 'Medication/' + M.id\n\ndefine AlogliptinA10BH04Ref:\n from [Medication: Code 'A10BH04' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Insulin (human)A10AF01Ref\":\n from [Medication: Code 'A10AF01' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Metformin und PioglitazonA10BD05Ref\":\n from [Medication: Code 'A10BD05' from atc] M\n return 'Medication/' + M.id\n\ndefine MitiglinidA10BX08Ref:\n from [Medication: Code 'A10BX08' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Insulin degludecA10AE06Ref\":\n from [Medication: Code 'A10AE06' from atc] M\n return 'Medication/' + M.id\n\ndefine BeinaglutidA10BJ07Ref:\n from [Medication: Code 'A10BJ07' from atc] M\n return 'Medication/' + M.id\n\ndefine LobeglitazonA10BG04Ref:\n from [Medication: Code 'A10BG04' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Metformin und LobeglitazonA10BD26Ref\":\n from [Medication: Code 'A10BD26' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Insulin lisproA10AD04Ref\":\n from [Medication: Code 'A10AD04' from atc] M\n return 'Medication/' + M.id\n\ndefine DulaglutidA10BJ05Ref:\n from [Medication: Code 'A10BJ05' from atc] M\n return 'Medication/' + M.id\n\ndefine KombinationenA10XP30Ref:\n from [Medication: Code 'A10XP30' from atc] M\n return 'Medication/' + M.id\n\ndefine NateglinidA10BX03Ref:\n from [Medication: Code 'A10BX03' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Insulin (Rind)A10AE02Ref\":\n from [Medication: Code 'A10AE02' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Insulin (Schwein)A10AD03Ref\":\n from [Medication: Code 'A10AD03' from atc] M\n return 'Medication/' + M.id\n\ndefine PramlintidA10BX05Ref:\n from [Medication: Code 'A10BX05' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Natrium-Glucose-Cotransporter-2-(SGLT2)-InhibitorenA10BKRef\":\n from [Medication: Code 'A10BK' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Antidiabetika, Exkl. InsulineA10BRef\":\n from [Medication: Code 'A10B' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Metformin, Linagliptin und EmpagliflozinA10BD27Ref\":\n from [Medication: Code 'A10BD27' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Andere Antidiabetika, exkl. InsulineA10BXRef\":\n from [Medication: Code 'A10BX' from atc] M\n return 'Medication/' + M.id\n\ndefine KombinationenA10XH20Ref:\n from [Medication: Code 'A10XH20' from atc] M\n return 'Medication/' + M.id\n\ndefine MetahexamidA10BB10Ref:\n from [Medication: Code 'A10BB10' from atc] M\n return 'Medication/' + M.id\n\ndefine GlymidinA10BC01Ref:\n from [Medication: Code 'A10BC01' from atc] M\n return 'Medication/' + M.id\n\ndefine LixisenatidA10BJ03Ref:\n from [Medication: Code 'A10BJ03' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Glimepirid und PioglitazonA10BD06Ref\":\n from [Medication: Code 'A10BD06' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Alpha-GlukosidasehemmerA10BFRef\":\n from [Medication: Code 'A10BF' from atc] M\n return 'Medication/' + M.id\n\ndefine \"Metformin und LinagliptinA10BD11Ref\":\n from [Medication: Code 'A10BD11' from atc] M\n return 'Medication/' + M.id\n\ncontext Patient\n\ndefine InInitialPopulation:\n exists (from [MedicationAdministration] M\n where M.medication.reference in AntidiabetikaA10Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Antidiabetika, Exkl. InsulineA10BRef\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Alpha-GlukosidasehemmerA10BFRef\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in AcarboseA10BF01Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in MiglitolA10BF02Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in VogliboseA10BF03Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in BiguanideA10BARef) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in BuforminA10BA03Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in MetforminA10BA02Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in PhenforminA10BA01Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Dipeptidyl-Peptidase-4-(DPP-4)-InhibitorenA10BHRef\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in AlogliptinA10BH04Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in EvogliptinA10BH07Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in GemigliptinA10BH06Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Gemigliptin und RosuvastatinA10BH52Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in LinagliptinA10BH05Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in SaxagliptinA10BH03Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in SitagliptinA10BH01Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Sitagliptin und SimvastatinA10BH51Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in TeneligliptinA10BH08Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in VildagliptinA10BH02Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Glucagon-like-Peptid-1-(GLP-1)-RezeptoragonistenA10BJRef\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in AlbiglutidA10BJ04Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in BeinaglutidA10BJ07Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in DulaglutidA10BJ05Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in ExenatidA10BJ01Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in LiraglutidA10BJ02Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in LixisenatidA10BJ03Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in SemaglutidA10BJ06Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Kombinationen oraler AntidiabetikaA10BDRef\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Glimepirid und PioglitazonA10BD06Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Glimepirid und RosiglitazonA10BD04Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Linagliptin und EmpagliflozinA10BD19Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Metformin und AcarboseA10BD17Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Metformin und AlogliptinA10BD13Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Metformin und CanagliflozinA10BD16Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Metformin und DapagliflozinA10BD15Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Metformin und EmpagliflozinA10BD20Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Metformin und ErtugliflozinA10BD23Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Metformin und EvogliptinA10BD22Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Metformin und GemigliptinA10BD18Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Metformin und GlibenclamidA10BD31Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Metformin und LinagliptinA10BD11Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Metformin und LobeglitazonA10BD26Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Metformin und PioglitazonA10BD05Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Metformin und RepaglinidA10BD14Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Metformin und RosiglitazonA10BD03Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Metformin und SaxagliptinA10BD10Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Metformin und SitagliptinA10BD07Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Metformin und SulfonylharnstoffeA10BD02Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Metformin und VildagliptinA10BD08Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Metformin, Linagliptin und EmpagliflozinA10BD27Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Metformin, Saxagliptin und DapagliflozinA10BD25Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Phenformin und SulfonylharnstoffeA10BD01Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Pioglitazon und AlogliptinA10BD09Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Pioglitazon und SitagliptinA10BD12Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Saxagliptin und DapagliflozinA10BD21Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Sitagliptin und ErtugliflozinA10BD24Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Natrium-Glucose-Cotransporter-2-(SGLT2)-InhibitorenA10BKRef\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in CanagliflozinA10BK02Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in DapagliflozinA10BK01Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in EmpagliflozinA10BK03Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in ErtugliflozinA10BK04Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in IpragliflozinA10BK05Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in LuseogliflozinA10BK07Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in SotagliflozinA10BK06Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Sulfonamide (heterozyklisch)A10BCRef\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in GlymidinA10BC01Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in SulfonylharnstoffeA10BBRef) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in AcetohexamidA10BB31Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in CarbutamidA10BB06Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in ChlorpropamidA10BB02Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in GlibenclamidA10BB01Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in GlibornuridA10BB04Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in GliclazidA10BB09Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in GlimepiridA10BB12Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in GlipizidA10BB07Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in GliquidonA10BB08Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in GlisoxepidA10BB11Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in MetahexamidA10BB10Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in TolazamidA10BB05Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in TolbutamidA10BB03Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Thiazolidindione (Glitazone)A10BGRef\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in LobeglitazonA10BG04Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in PioglitazonA10BG03Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in RosiglitazonA10BG02Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in TroglitazonA10BG01Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Andere Antidiabetika, exkl. InsulineA10BXRef\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in BenfluorexA10BX06Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Guar-Mehl*A10BX01Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in ImegliminA10BX15Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in MitiglinidA10BX08Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in NateglinidA10BX03Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in PramlintidA10BX05Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in RepaglinidA10BX02Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Insuline Und AnalogaA10ARef\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Insuline und Analoga zur InhalationA10AFRef\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Insulin (human)A10AF01Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Insuline und Analoga zur Injektion, intermediär oder lang wirkend kombiniert mit schnell wirkendA10ADRef\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Insulin (human)A10AD01Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Insulin (Rind)A10AD02Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Insulin (Schwein)A10AD03Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Insulin aspartA10AD05Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Insulin degludec und Insulin aspartA10AD06Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Insulin lisproA10AD04Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in KombinationenA10AD30Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Insuline und Analoga zur Injektion, intermediär wirkendA10ACRef\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Insulin (human)A10AC01Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Insulin (Rind)A10AC02Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Insulin (Schwein)A10AC03Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Insulin lisproA10AC04Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in KombinationenA10AC30Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Insuline und Analoga zur Injektion, lang wirkendA10AERef\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Insulin (human)A10AE01Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Insulin (Rind)A10AE02Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Insulin (Schwein)A10AE03Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Insulin degludecA10AE06Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Insulin degludec und LiraglutidA10AE56Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Insulin detemirA10AE05Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Insulin glarginA10AE04Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Insulin glargin und LixisenatidA10AE54Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in KombinationenA10AE30Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Insuline und Analoga zur Injektion, schnell wirkendA10ABRef\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Insulin (human)A10AB01Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Insulin (Rind)A10AB02Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Insulin (Schwein)A10AB03Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Insulin aspartA10AB05Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Insulin glulisinA10AB06Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Insulin lisproA10AB04Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in KombinationenA10AB30Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Andere AntidiabetikaA10XRef\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in AldosereduktasehemmerA10XARef) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in TolrestatA10XA01Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Homöopathische und anthroposophische AntidiabetikaA10XHRef\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in KombinationenA10XH20Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Pflanzliche AntidiabetikaA10XPRef\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in CopalchirindenextraktA10XP02Ref) or\n exists (from [MedicationAdministration] M\n where M.medication.reference in \"Guar-MehlA10XP01Ref\") or\n exists (from [MedicationAdministration] M\n where M.medication.reference in KombinationenA10XP30Ref)\n")] - (with-system [{:blaze.db/keys [node] ::ts/keys [local]} config] + (with-system [{:blaze.db/keys [node] ::ts/keys [local]} api-stub/mem-node-config] ;; 1.7 ms / 15 µs - Macbook Pro M1 Pro, Oracle OpenJDK 17.0.2 (criterium/quick-bench (library/compile-library {:node node :terminology-service local} library {}))))) diff --git a/modules/cql/test/blaze/elm/compiler/clinical_operators_test.clj b/modules/cql/test/blaze/elm/compiler/clinical_operators_test.clj index d2be868c0..54f09e3f0 100644 --- a/modules/cql/test/blaze/elm/compiler/clinical_operators_test.clj +++ b/modules/cql/test/blaze/elm/compiler/clinical_operators_test.clj @@ -7,7 +7,7 @@ [blaze.anomaly :as ba] [blaze.async.comp :as ac] [blaze.db.api :as d] - [blaze.db.api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system with-system-data]] [blaze.elm.code :as code] [blaze.elm.compiler :as c] [blaze.elm.compiler.clinical-operators] @@ -20,15 +20,12 @@ [blaze.elm.literal :as elm] [blaze.elm.literal-spec] [blaze.elm.value-set-spec] - [blaze.module.test-util :refer [with-system]] [blaze.terminology-service :as-alias ts] [blaze.terminology-service-spec] - [blaze.terminology-service.local :as ts-local] [blaze.terminology-service.protocols :as p] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [are deftest is testing]] [cognitect.anomalies :as anom] - [integrant.core :as ig] [java-time.api :as time] [juxt.iota :refer [given]])) @@ -124,17 +121,6 @@ ;; ;; The third argument is expected to be a CodeSystem, allowing references to ;; code systems to be preserved as references. -(def ^:private ts-config - (assoc - mem-node-config - ::ts/local - {:node (ig/ref :blaze.db/node) - :clock (ig/ref :blaze.test/fixed-clock) - :rng-fn (ig/ref :blaze.test/fixed-rng-fn) - :graph-cache (ig/ref ::ts-local/graph-cache)} - :blaze.test/fixed-rng-fn {} - ::ts-local/graph-cache {})) - (defn- eval-context [db] {:db db :now (time/offset-date-time) :parameters {"nil" nil "code-115927" "code-115927"}}) @@ -152,7 +138,7 @@ (doseq [elm-constructor [elm/in-code-system #_elm/in-code-system-expression]] (testing "Null" - (with-system [{:blaze.db/keys [node] terminology-service ::ts/local} ts-config] + (with-system [{:blaze.db/keys [node] terminology-service ::ts/local} api-stub/mem-node-config] (let [context {:library {:parameters @@ -184,7 +170,7 @@ (is (false? (expr/eval (eval-context db) expr nil))))))))) (testing "String" - (with-system-data [{:blaze.db/keys [node] terminology-service ::ts/local} ts-config] + (with-system-data [{:blaze.db/keys [node] terminology-service ::ts/local} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/CodeSystem :id "0" :url #fhir/uri "system-115910" :content #fhir/code "complete" @@ -246,7 +232,7 @@ (is (true? (expr/eval (eval-context db) expr nil)))))))) (testing "with failing terminology service" - (with-system [{:blaze.db/keys [node]} ts-config] + (with-system [{:blaze.db/keys [node]} api-stub/mem-node-config] (let [context {:library {:parameters @@ -306,7 +292,7 @@ ::anom/message := "Error while testing that the code `code-115927` is in CodeSystem `code-system-135750`. Cause: msg-094502")))))))) (testing "Code" - (with-system-data [{:blaze.db/keys [node] terminology-service ::ts/local} ts-config] + (with-system-data [{:blaze.db/keys [node] terminology-service ::ts/local} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/CodeSystem :id "0" :url #fhir/uri "system-115910" :content #fhir/code "complete" @@ -337,7 +323,7 @@ (code-system "system-115910"))))))) (testing "Concept" - (with-system-data [{:blaze.db/keys [node] terminology-service ::ts/local} ts-config] + (with-system-data [{:blaze.db/keys [node] terminology-service ::ts/local} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/CodeSystem :id "0" :url #fhir/uri "system-115910" :content #fhir/code "complete" @@ -416,7 +402,7 @@ (doseq [elm-constructor [elm/in-value-set elm/in-value-set-expression]] (testing "Null" - (with-system [{:blaze.db/keys [node] terminology-service ::ts/local} ts-config] + (with-system [{:blaze.db/keys [node] terminology-service ::ts/local} api-stub/mem-node-config] (let [context {:library {:parameters @@ -448,7 +434,7 @@ (is (false? (expr/eval (eval-context db) expr nil))))))))) (testing "String" - (with-system-data [{:blaze.db/keys [node] terminology-service ::ts/local} ts-config] + (with-system-data [{:blaze.db/keys [node] terminology-service ::ts/local} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/CodeSystem :id "0" :url #fhir/uri "system-115910" :content #fhir/code "complete" @@ -532,7 +518,7 @@ (is (true? (expr/eval (eval-context db) expr nil)))))))) (testing "with failing terminology service" - (with-system [{:blaze.db/keys [node]} ts-config] + (with-system [{:blaze.db/keys [node]} api-stub/mem-node-config] (let [context {:library {:parameters @@ -592,7 +578,7 @@ ::anom/message := "Error while testing that the code `code-115927` is in ValueSet `value-set-135750`. Cause: msg-094502")))))))) (testing "Code" - (with-system-data [{:blaze.db/keys [node] terminology-service ::ts/local} ts-config] + (with-system-data [{:blaze.db/keys [node] terminology-service ::ts/local} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/CodeSystem :id "0" :url #fhir/uri "system-115910" :content #fhir/code "complete" @@ -633,7 +619,7 @@ (value-set "value-set-135750"))))))) (testing "Concept" - (with-system-data [{:blaze.db/keys [node] terminology-service ::ts/local} ts-config] + (with-system-data [{:blaze.db/keys [node] terminology-service ::ts/local} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/CodeSystem :id "0" :url #fhir/uri "system-115910" :content #fhir/code "complete" diff --git a/modules/cql/test/blaze/elm/compiler/external_data_test.clj b/modules/cql/test/blaze/elm/compiler/external_data_test.clj index b5613fa2b..b1479dcde 100644 --- a/modules/cql/test/blaze/elm/compiler/external_data_test.clj +++ b/modules/cql/test/blaze/elm/compiler/external_data_test.clj @@ -7,7 +7,7 @@ [blaze.anomaly :as ba] [blaze.cql.translator :as t] [blaze.db.api :as d] - [blaze.db.api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.elm.compiler :as c] [blaze.elm.compiler.core :as core] [blaze.elm.compiler.external-data] @@ -22,12 +22,10 @@ [blaze.module.test-util :refer [with-system]] [blaze.terminology-service :as-alias ts] [blaze.terminology-service-spec] - [blaze.terminology-service.local :as ts-local] [blaze.util-spec] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] [cognitect.anomalies :as anom] - [integrant.core :as ig] [java-time.api :as time] [juxt.iota :refer [given]])) @@ -42,17 +40,6 @@ (test/use-fixtures :each fixture) -(def ^:private config - (assoc - mem-node-config - ::ts/local - {:node (ig/ref :blaze.db/node) - :clock (ig/ref :blaze.test/fixed-clock) - :rng-fn (ig/ref :blaze.test/fixed-rng-fn) - :graph-cache (ig/ref ::ts-local/graph-cache)} - :blaze.test/fixed-rng-fn {} - ::ts-local/graph-cache {})) - (defn- compile-context [{:blaze.db/keys [node] ::ts/keys [local]}] {:node node :terminology-service local}) @@ -86,7 +73,7 @@ (deftest compile-retrieve-test (testing "Patient context" (testing "Patient" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}]]] (let [context @@ -119,7 +106,7 @@ (has-form expr '(retrieve-resource)))))) (testing "Observation" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}] [:put {:fhir/type :fhir/Observation :id "1" :subject #fhir/Reference{:reference #fhir/string "Patient/0"}}]]] @@ -154,7 +141,7 @@ (has-form expr '(retrieve "Observation"))))) (testing "with one code" - (with-system-data [{:blaze.db/keys [node] terminology-service ::ts/local} config] + (with-system-data [{:blaze.db/keys [node] terminology-service ::ts/local} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}] [:put {:fhir/type :fhir/Observation :id "0" :subject #fhir/Reference{:reference #fhir/string "Patient/0"}}] @@ -209,7 +196,7 @@ '(retrieve "Observation" [["code" "system-192253|code-192300"]]))))) (testing "optimizing into an empty list because Observation isn't available" - (with-system [{:blaze.db/keys [node] terminology-service ::ts/local} config] + (with-system [{:blaze.db/keys [node] terminology-service ::ts/local} api-stub/mem-node-config] (let [context {:node node :eval-context "Patient" @@ -229,7 +216,7 @@ (has-form (c/optimize expr db) []))))) (testing "with two codes" - (with-system-data [{:blaze.db/keys [node] terminology-service ::ts/local} config] + (with-system-data [{:blaze.db/keys [node] terminology-service ::ts/local} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}] [:put {:fhir/type :fhir/Observation :id "0" :subject #fhir/Reference{:reference #fhir/string "Patient/0"}}] @@ -299,7 +286,7 @@ "system-192253|code-140541"]])))))) (testing "with one concept" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}] [:put {:fhir/type :fhir/Observation :id "0" :subject #fhir/Reference{:reference #fhir/string "Patient/0"}}] @@ -370,8 +357,84 @@ "system-192253|code-192300" "system-192253|code-140541"]])))))) + (testing "with value set reference" + (with-system-data [{:blaze.db/keys [node] terminology-service ::ts/local} api-stub/mem-node-config] + [[[:put {:fhir/type :fhir/CodeSystem :id "0" + :url #fhir/uri "http://system-115910" + :content #fhir/code "complete" + :concept + [{:fhir/type :fhir.CodeSystem/concept + :code #fhir/code "code-115927"} + {:fhir/type :fhir.CodeSystem/concept + :code #fhir/code "code-140541"}]}]] + [[:put {:fhir/type :fhir/Patient :id "0"}] + [:put {:fhir/type :fhir/Observation :id "0" + :subject #fhir/Reference{:reference #fhir/string "Patient/0"}}] + [:put {:fhir/type :fhir/Observation :id "1" + :code + #fhir/CodeableConcept + {:coding + [#fhir/Coding + {:system #fhir/uri "http://system-115910" + :code #fhir/code "code-115927"}]} + :subject #fhir/Reference{:reference #fhir/string "Patient/0"}}] + [:put {:fhir/type :fhir/Observation :id "2" + :code + #fhir/CodeableConcept + {:coding + [#fhir/Coding + {:system #fhir/uri "http://system-115910" + :code #fhir/code "code-140541"}]} + :subject #fhir/Reference{:reference #fhir/string "Patient/0"}}]]] + + (let [context + {:node node + :eval-context "Patient" + :library + {:valueSets + {:def + [{:name "icd10_e10" + :id "http://fhir.org/VCL?v1=(http://system-115910)*"}]}} + :terminology-service terminology-service} + elm #elm/retrieve + {:type "Observation" + :codes #elm/value-set-ref "icd10_e10" + :codeComparator "in"} + expr (c/compile context elm) + db (d/db node) + patient (ctu/resource db "Patient" "0")] + + (testing "eval" + (given (expr/eval (eval-context db) expr patient) + count := 2 + [0 :fhir/type] := :fhir/Observation + [0 :id] := "1" + [1 :fhir/type] := :fhir/Observation + [1 :id] := "2")) + + (testing "expression is dynamic" + (is (false? (core/-static expr)))) + + (ctu/testing-constant-attach-cache expr) + + (ctu/testing-constant-patient-count expr) + + (ctu/testing-constant-resolve-refs expr) + + (ctu/testing-constant-resolve-params expr) + + (testing "optimize" + (is (= expr (c/optimize expr db)))) + + (testing "form" + (has-form expr + '(retrieve + "Observation" + [["code:in" + "http://fhir.org/VCL?v1=(http://system-115910)*"]])))))) + (testing "unknown code property" - (with-system [{:blaze.db/keys [node] terminology-service ::ts/local} config] + (with-system [{:blaze.db/keys [node] terminology-service ::ts/local} api-stub/mem-node-config] (let [context {:node node :eval-context "Patient" @@ -393,7 +456,7 @@ (testing "Specimen context" (testing "Patient" - (with-system-data [{:blaze.db/keys [node]} (assoc-in mem-node-config [:blaze.db/node :enforce-referential-integrity] false)] + (with-system-data [{:blaze.db/keys [node]} (assoc-in api-stub/mem-node-config [:blaze.db/node :enforce-referential-integrity] false)] [[[:put {:fhir/type :fhir/Patient :id "0"}] [:put {:fhir/type :fhir/Specimen :id "0" :subject #fhir/Reference{:reference #fhir/string "Patient/0"}}] @@ -454,7 +517,7 @@ (testing "Unfiltered context" (testing "Medication" - (with-system-data [{:blaze.db/keys [node] terminology-service ::ts/local} config] + (with-system-data [{:blaze.db/keys [node] terminology-service ::ts/local} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Medication :id "0" :code #fhir/CodeableConcept @@ -503,7 +566,7 @@ '(retrieve "Medication" [["code" "system-225806|code-225809"]])))))) (testing "unknown code property" - (with-system [{:blaze.db/keys [node] terminology-service ::ts/local} config] + (with-system [{:blaze.db/keys [node] terminology-service ::ts/local} api-stub/mem-node-config] (let [context {:node node :eval-context "Unfiltered" @@ -530,7 +593,7 @@ (testing "with related context" (testing "without code" - (with-system-data [{:blaze.db/keys [node] :as system} config] + (with-system-data [{:blaze.db/keys [node] :as system} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}] [:put {:fhir/type :fhir/Observation :id "0" :subject #fhir/Reference{:reference #fhir/string "Patient/0"}}]]] @@ -579,7 +642,7 @@ '(retrieve (singleton-from (retrieve-resource)) "Observation")))))) (testing "with pre-compiled database query" - (with-system-data [{:blaze.db/keys [node] :as system} config] + (with-system-data [{:blaze.db/keys [node] :as system} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}] [:put {:fhir/type :fhir/Observation :id "0" :code @@ -637,7 +700,7 @@ [["code" "system-133620|code-133657"]])))))) (testing "unknown code property" - (with-system [{:blaze.db/keys [node] terminology-service ::ts/local} config] + (with-system [{:blaze.db/keys [node] terminology-service ::ts/local} api-stub/mem-node-config] (let [library {:codeSystems {:def [{:name "sys-def-174848" :id "system-174915"}]} :statements @@ -657,7 +720,7 @@ ::anom/message := "The search-param with code `foo` and type `Observation` was not found.")))) (testing "missing context result type" - (with-system [{:blaze.db/keys [node] terminology-service ::ts/local} config] + (with-system [{:blaze.db/keys [node] terminology-service ::ts/local} api-stub/mem-node-config] (let [library {:codeSystems {:def [{:name "sys-def-174848" :id "system-174915"}]} :statements @@ -675,7 +738,7 @@ ::anom/message := "Unsupported related context retrieve expression without result type.")))) (testing "unsupported context result type namespace" - (with-system [{:blaze.db/keys [node] terminology-service ::ts/local} config] + (with-system [{:blaze.db/keys [node] terminology-service ::ts/local} api-stub/mem-node-config] (let [library {:codeSystems {:def [{:name "sys-def-174848" :id "system-174915"}]} :statements diff --git a/modules/cql/test/blaze/elm/compiler/library_test.clj b/modules/cql/test/blaze/elm/compiler/library_test.clj index f2505b222..c12c75ca5 100644 --- a/modules/cql/test/blaze/elm/compiler/library_test.clj +++ b/modules/cql/test/blaze/elm/compiler/library_test.clj @@ -2,7 +2,7 @@ (:require [blaze.cql.translator :as t] [blaze.db.api :as d] - [blaze.db.api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.elm.compiler :as c] [blaze.elm.compiler-spec] [blaze.elm.compiler.core :as core] @@ -15,12 +15,10 @@ [blaze.module.test-util :refer [with-system]] [blaze.terminology-service :as-alias ts] [blaze.terminology-service-spec] - [blaze.terminology-service.local :as ts-local] [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] [cognitect.anomalies :as anom] - [integrant.core :as ig] [java-time.api :as time] [juxt.iota :refer [given]] [taoensso.timbre :as log])) @@ -30,17 +28,6 @@ (test/use-fixtures :each tu/fixture) -(def ^:private config - (assoc - mem-node-config - ::ts/local - {:node (ig/ref :blaze.db/node) - :clock (ig/ref :blaze.test/fixed-clock) - :rng-fn (ig/ref :blaze.test/fixed-rng-fn) - :graph-cache (ig/ref ::ts-local/graph-cache)} - :blaze.test/fixed-rng-fn {} - ::ts-local/graph-cache {})) - (defn- compile-context [{:blaze.db/keys [node] ::ts/keys [local]}] {:node node :terminology-service local}) @@ -98,13 +85,13 @@ (deftest compile-library-test (testing "empty library" (let [library (t/translate "library Test")] - (with-system [system config] + (with-system [system api-stub/mem-node-config] (given (library/compile-library (compile-context system) library default-opts) :expression-defs := {})))) (testing "one static expression" (let [library (t/translate "library Test define Foo: true")] - (with-system [{:blaze.db/keys [node] :as system} config] + (with-system [{:blaze.db/keys [node] :as system} api-stub/mem-node-config] (let [{:keys [expression-defs]} (library/compile-library (compile-context system) library default-opts)] (given expression-defs ["Foo" :context] := "Patient" @@ -118,7 +105,7 @@ using FHIR version '4.0.0' context Patient define Gender: Patient.gender")] - (with-system [{:blaze.db/keys [node] :as system} config] + (with-system [{:blaze.db/keys [node] :as system} api-stub/mem-node-config] (let [{:keys [expression-defs]} (library/compile-library (compile-context system) library default-opts)] (given expression-defs ["Gender" :context] := "Patient" @@ -136,7 +123,7 @@ context Patient define function Gender(P Patient): P.gender define InInitialPopulation: Gender(Patient)")] - (with-system [{:blaze.db/keys [node] :as system} config] + (with-system [{:blaze.db/keys [node] :as system} api-stub/mem-node-config] (let [{:keys [expression-defs] :as context} (library/compile-library (compile-context system) library default-opts)] @@ -166,7 +153,7 @@ define function Inc(i System.Integer): i + 1 define function Inc2(i System.Integer): Inc(i) + 1 define InInitialPopulation: Inc2(1)")] - (with-system [{:blaze.db/keys [node] :as system} config] + (with-system [{:blaze.db/keys [node] :as system} api-stub/mem-node-config] (let [{:keys [expression-defs] :as context} (library/compile-library (compile-context system) library default-opts)] (given expression-defs @@ -201,7 +188,7 @@ define function Inc(i System.Integer): i + 1 define function Add(i System.Integer, j System.Integer): i + j define function Add(i System.Integer, j System.Integer, k System.Integer): { i, j, k }")] - (with-system [system config] + (with-system [system api-stub/mem-node-config] (let [context (library/compile-library (compile-context system) library default-opts)] (given context [(function-def "Const" 0) :context] := "Patient" @@ -265,7 +252,7 @@ define InInitialPopulation: Inclusion and not Exclusion")] - (with-system [{:blaze.db/keys [node] :as system} config] + (with-system [{:blaze.db/keys [node] :as system} api-stub/mem-node-config] (let [{:keys [expression-defs]} (library/compile-library (compile-context system) library default-opts)] (given expression-defs ["InInitialPopulation" :context] := "Patient" @@ -306,7 +293,7 @@ Patient.gender = 'female' and exists from [MedicationStatement] M where M.medication.reference in TemozolomidRefs")] - (with-system [{:blaze.db/keys [node] :as system} config] + (with-system [{:blaze.db/keys [node] :as system} api-stub/mem-node-config] (let [{:keys [expression-defs]} (library/compile-library (compile-context system) library default-opts)] (given expression-defs ["TemozolomidRefs" :context] := "Unfiltered" @@ -403,7 +390,7 @@ define Gender: Patient.gender")] - (with-system [{:blaze.db/keys [node] :as system} config] + (with-system [{:blaze.db/keys [node] :as system} api-stub/mem-node-config] (let [{:keys [expression-defs]} (library/compile-library (compile-context system) library default-opts)] (given expression-defs ["Patient" :context] := "Patient" @@ -432,7 +419,7 @@ define InInitialPopulation: exists from [MedicationAdministration] M where M.medication.reference in {'Medication/0', 'Medication/1'}")] - (with-system [{:blaze.db/keys [node] :as system} config] + (with-system [{:blaze.db/keys [node] :as system} api-stub/mem-node-config] (let [{:keys [expression-defs]} (library/compile-library (compile-context system) library default-opts)] (given expression-defs ["InInitialPopulation" :context] := "Patient" @@ -476,7 +463,7 @@ define InInitialPopulation: exists from [MedicationAdministration] M where M.medication.reference in MedicationRefs")] - (with-system [{:blaze.db/keys [node] :as system} config] + (with-system [{:blaze.db/keys [node] :as system} api-stub/mem-node-config] (let [{:keys [expression-defs]} (library/compile-library (compile-context system) library default-opts)] (given expression-defs ["InInitialPopulation" :context] := "Patient" @@ -524,7 +511,7 @@ where M.medication.reference in MedicationRefsA) or exists (from [MedicationAdministration] M where M.medication.reference in MedicationRefsB)")] - (with-system [{:blaze.db/keys [node] :as system} config] + (with-system [{:blaze.db/keys [node] :as system} api-stub/mem-node-config] (let [{:keys [expression-defs]} (library/compile-library (compile-context system) library default-opts)] (given expression-defs ["InInitialPopulation" :context] := "Patient" @@ -577,7 +564,7 @@ where M.medication.reference in MedicationRefsA) or exists (from [MedicationAdministration] M where M.medication.reference in {'Medication/0'})")] - (with-system [{:blaze.db/keys [node] :as system} config] + (with-system [{:blaze.db/keys [node] :as system} api-stub/mem-node-config] (let [{:keys [expression-defs]} (library/compile-library (compile-context system) library default-opts)] (given expression-defs ["InInitialPopulation" :context] := "Patient" @@ -618,7 +605,7 @@ (testing "function" (let [library (t/translate "library Test define function Error(): singleton from {1, 2}")] - (with-system [system config] + (with-system [system api-stub/mem-node-config] (given (library/compile-library (compile-context system) library default-opts) ::anom/category := ::anom/conflict ::anom/message := "More than one element in `SingletonFrom` expression.")))) @@ -626,7 +613,7 @@ (testing "expression" (let [library (t/translate "library Test define Error: singleton from {1, 2}")] - (with-system [system config] + (with-system [system api-stub/mem-node-config] (given (library/compile-library (compile-context system) library default-opts) ::anom/category := ::anom/conflict ::anom/message := "More than one element in `SingletonFrom` expression."))))) @@ -642,7 +629,7 @@ define InInitialPopulation: Patient.gender = Gender")] - (with-system [{:blaze.db/keys [node] :as system} config] + (with-system [{:blaze.db/keys [node] :as system} api-stub/mem-node-config] (let [{:keys [expression-defs]} (library/compile-library (compile-context system) library default-opts)] (given expression-defs ["InInitialPopulation" :context] := "Patient" @@ -668,7 +655,7 @@ (testing "with parameter default" (let [library (t/translate "library Test parameter \"Measurement Period\" Interval default Interval[@2020-01-01, @2020-12-31]")] - (with-system [system config] + (with-system [system api-stub/mem-node-config] (given (library/compile-library (compile-context system) library default-opts) [:parameter-default-values "Measurement Period" :low] := #system/date"2020-01-01" [:parameter-default-values "Measurement Period" :high] := #system/date"2020-12-31")))) @@ -676,7 +663,7 @@ (testing "with invalid parameter default" (let [library (t/translate "library Test parameter \"Measurement Start\" Integer default singleton from {1, 2}")] - (with-system [system config] + (with-system [system api-stub/mem-node-config] (given (library/compile-library (compile-context system) library default-opts) ::anom/category := ::anom/conflict ::anom/message "More than one element in `SingletonFrom` expression.")))) @@ -692,7 +679,7 @@ exists [Observation] O with [Encounter] E such that O.encounter.reference = 'Encounter/' + E.id")] - (with-system [{:blaze.db/keys [node] :as system} config] + (with-system [{:blaze.db/keys [node] :as system} api-stub/mem-node-config] (let [{:keys [expression-defs] :as context} (library/compile-library (compile-context system) library {})] (given expression-defs @@ -737,7 +724,7 @@ define InInitialPopulation: [\"name-133756\" -> Observation]")] - (with-system [{:blaze.db/keys [node] :as system} config] + (with-system [{:blaze.db/keys [node] :as system} api-stub/mem-node-config] (let [{:keys [expression-defs]} (library/compile-library (compile-context system) library {})] (given expression-defs ["InInitialPopulation" :context] := "Patient" @@ -768,7 +755,7 @@ define InInitialPopulation: exists [Condition: prostata]")] - (with-system [system config] + (with-system [system api-stub/mem-node-config] (let [{:keys [expression-defs]} (library/compile-library (compile-context system) library {})] (given expression-defs ["InInitialPopulation" :context] := "Patient" @@ -795,7 +782,7 @@ exists [Condition] and exists [Encounter] and exists [Specimen]")] - (with-system [{:blaze.db/keys [node] :as system} config] + (with-system [{:blaze.db/keys [node] :as system} api-stub/mem-node-config] (let [{:keys [expression-defs]} (library/compile-library (compile-context system) library {})] (given expression-defs ["InInitialPopulation" :context] := "Patient" @@ -832,7 +819,7 @@ define InInitialPopulation: Criterion_1 and Criterion_2")] - (with-system [{:blaze.db/keys [node] :as system} config] + (with-system [{:blaze.db/keys [node] :as system} api-stub/mem-node-config] (let [{:keys [expression-defs]} (library/compile-library (compile-context system) library default-opts) in-initial-population (get expression-defs "InInitialPopulation")] @@ -879,7 +866,7 @@ exists [Condition] or exists [Encounter] or exists [Specimen]")] - (with-system [{:blaze.db/keys [node] :as system} config] + (with-system [{:blaze.db/keys [node] :as system} api-stub/mem-node-config] (let [{:keys [expression-defs]} (library/compile-library (compile-context system) library {})] (given expression-defs ["InInitialPopulation" :context] := "Patient" @@ -916,7 +903,7 @@ define InInitialPopulation: Criterion_1 or Criterion_2")] - (with-system [{:blaze.db/keys [node] :as system} config] + (with-system [{:blaze.db/keys [node] :as system} api-stub/mem-node-config] (let [{:keys [expression-defs]} (library/compile-library (compile-context system) library default-opts) in-initial-population (get expression-defs "InInitialPopulation")] @@ -969,7 +956,7 @@ define InInitialPopulation: Criterion_1 and Criterion_2")] - (with-system [{:blaze.db/keys [node] :as system} config] + (with-system [{:blaze.db/keys [node] :as system} api-stub/mem-node-config] (let [{:keys [expression-defs]} (library/compile-library (compile-context system) library default-opts) in-initial-population (get expression-defs "InInitialPopulation")] @@ -1017,7 +1004,7 @@ define InInitialPopulation: Patient.identifier.where(type ~ Code 'GKV' from IdentifierType).exists()")] - (with-system [{:blaze.db/keys [node] :as system} config] + (with-system [{:blaze.db/keys [node] :as system} api-stub/mem-node-config] (let [{:keys [expression-defs]} (library/compile-library (compile-context system) library {})] (given expression-defs ["InInitialPopulation" :context] := "Patient" @@ -1057,7 +1044,7 @@ define InInitialPopulation: exists [Observation: Code '788-0' from loinc]")] - (with-system-data [{:blaze.db/keys [node] :as system} config] + (with-system-data [{:blaze.db/keys [node] :as system} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Observation :id "0" :code (codeable-concept "http://loinc.org" "788-0")}]]] @@ -1085,7 +1072,7 @@ define InInitialPopulation: exists [Observation: Code '788-0' from loinc]")] - (with-system [{:blaze.db/keys [node] :as system} config] + (with-system [{:blaze.db/keys [node] :as system} api-stub/mem-node-config] (let [{:keys [expression-defs]} (library/compile-library (compile-context system) library {})] (given expression-defs ["InInitialPopulation" :context] := "Patient" @@ -1099,7 +1086,43 @@ (testing "the whole expression will be optimized to false" (given (library/optimize (d/db node) expression-defs) ["InInitialPopulation" :context] := "Patient" - ["InInitialPopulation" expr-form] := false))))))) + ["InInitialPopulation" expr-form] := false)))))) + + (testing "with value set" + (let [library (t/translate "library test + using FHIR version '4.0.0' + include FHIRHelpers version '4.0.0' + + valueset vs: 'http://fhir.org/VCL?v1=(http://system-115910)*' + + context Patient + + define InInitialPopulation: + exists [Condition: vs]")] + (with-system-data [{:blaze.db/keys [node] :as system} api-stub/mem-node-config] + [[[:put {:fhir/type :fhir/CodeSystem :id "0" + :url #fhir/uri "http://system-115910" + :content #fhir/code "complete" + :concept + [{:fhir/type :fhir.CodeSystem/concept + :code #fhir/code "code-115927"} + {:fhir/type :fhir.CodeSystem/concept + :code #fhir/code "code-140541"}]}]] + [[:put {:fhir/type :fhir/Condition :id "0" + :code (codeable-concept "http://system-115910" "code-115927")}]]] + + (let [{:keys [expression-defs]} (library/compile-library (compile-context system) library {})] + (given expression-defs + ["InInitialPopulation" :context] := "Patient" + ["InInitialPopulation" expr-form] := + '(exists + (retrieve "Condition" [["code:in" "http://fhir.org/VCL?v1=(http://system-115910)*"]]))) + + (testing "there are no references to resolve" + (is (= expression-defs (library/resolve-all-refs expression-defs)))) + + (testing "there are no optimizations available" + (is (= expression-defs (library/optimize (d/db node) expression-defs))))))))) (testing "query with where clause" (let [library (t/translate "library test @@ -1113,7 +1136,7 @@ define InInitialPopulation: exists [Observation: body_weight] O where O.value < 3.3 'kg'")] - (with-system-data [{:blaze.db/keys [node] :as system} config] + (with-system-data [{:blaze.db/keys [node] :as system} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Observation :id "0" :code (codeable-concept "http://loinc.org" "29463-7")}]]] @@ -1147,7 +1170,7 @@ define InInitialPopulation: exists [Observation: body_weight] O where O.value < 3.3 'kg'")] - (with-system [{:blaze.db/keys [node] :as system} config] + (with-system [{:blaze.db/keys [node] :as system} api-stub/mem-node-config] (let [{:keys [expression-defs]} (library/compile-library (compile-context system) library {})] (given expression-defs ["InInitialPopulation" :context] := "Patient" @@ -1181,7 +1204,7 @@ exists from [Procedure: Code '431182000' from snomed] P where P.performed overlaps Interval[@2020-02-01, @2020-06-01]")] - (with-system [system config] + (with-system [system api-stub/mem-node-config] (let [{:keys [expression-defs]} (library/compile-library (compile-context system) library {})] (given expression-defs ["InInitialPopulation" :context] := "Patient" @@ -1218,7 +1241,7 @@ define InInitialPopulation: Patient.gender in FemaleAdministrativeSex")] - (with-system-data [system config] + (with-system-data [system api-stub/mem-node-config] [[[:put {:fhir/type :fhir/ValueSet :id "0" :url #fhir/uri "urn:oid:2.16.840.1.113883.3.560.100.2" :compose diff --git a/modules/cql/test/blaze/elm/compiler/list_operators_test.clj b/modules/cql/test/blaze/elm/compiler/list_operators_test.clj index 9e49d9fef..64d7e5432 100644 --- a/modules/cql/test/blaze/elm/compiler/list_operators_test.clj +++ b/modules/cql/test/blaze/elm/compiler/list_operators_test.clj @@ -7,7 +7,7 @@ [blaze.anomaly :as ba] [blaze.anomaly-spec] [blaze.db.api :as d] - [blaze.db.api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.elm.compiler :as c] [blaze.elm.compiler-spec] [blaze.elm.compiler.core :as core] @@ -250,11 +250,12 @@ ;; ;; If the argument is null, the result is false. (def ^:private exists-config - (assoc mem-node-config - ::expr/cache - {:node (ig/ref :blaze.db/node) - :executor (ig/ref :blaze.test/executor)} - :blaze.test/executor {})) + (assoc + api-stub/mem-node-config + ::expr/cache + {:node (ig/ref :blaze.db/node) + :executor (ig/ref :blaze.test/executor)} + :blaze.test/executor {})) (defmethod elm-spec/expression :elm.spec.type/exists-test [_] map?) @@ -353,7 +354,7 @@ (is (false? (expr/eval eval-context expr patient))))))))) (testing "without caching expressions" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}]]] (let [db (d/db node) diff --git a/modules/cql/test/blaze/elm/compiler/queries_test.clj b/modules/cql/test/blaze/elm/compiler/queries_test.clj index f24d382b7..788c9c748 100644 --- a/modules/cql/test/blaze/elm/compiler/queries_test.clj +++ b/modules/cql/test/blaze/elm/compiler/queries_test.clj @@ -5,7 +5,7 @@ https://cql.hl7.org/04-logicalspecification.html." (:require [blaze.db.api :as d] - [blaze.db.api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.elm.code :as code] [blaze.elm.code-spec] [blaze.elm.compiler :as c] @@ -156,7 +156,7 @@ (has-form expr [1 1]))))) (testing "Retrieve queries" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0" :gender #fhir/code "female"}] [:put {:fhir/type :fhir/Patient :id "1" @@ -356,7 +356,7 @@ (retrieve "Patient")))))))))) (testing "With clause" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}] [:put {:fhir/type :fhir/Encounter :id "0" :subject #fhir/Reference{:reference #fhir/string "Patient/0"}}] @@ -652,7 +652,7 @@ (retrieve "Observation"))))))))))) (testing "Without clause" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}] [:put {:fhir/type :fhir/Encounter :id "0" :subject #fhir/Reference{:reference #fhir/string "Patient/0"}}] @@ -697,7 +697,7 @@ (testing "Sort" (testing "ByExpression" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}] [:put {:fhir/type :fhir/Encounter :id "0" :subject #fhir/Reference{:reference #fhir/string "Patient/0"} @@ -731,7 +731,7 @@ (is (= ["0" "1"] (map :id (core/-eval expr {:db db} patient nil)))))))))) (deftest compile-query-medication-reference-test - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}] [:put {:fhir/type :fhir/MedicationAdministration :id "0" :medication #fhir/Reference{:reference #fhir/string "Medication/0"} diff --git a/modules/cql/test/blaze/elm/compiler/string_operators_test.clj b/modules/cql/test/blaze/elm/compiler/string_operators_test.clj index de044def9..03194188d 100644 --- a/modules/cql/test/blaze/elm/compiler/string_operators_test.clj +++ b/modules/cql/test/blaze/elm/compiler/string_operators_test.clj @@ -5,7 +5,7 @@ https://cql.hl7.org/04-logicalspecification.html." (:require [blaze.db.api :as d] - [blaze.db.api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.elm.compiler :as c] [blaze.elm.compiler.core :as core] [blaze.elm.compiler.core-spec] @@ -221,7 +221,7 @@ (testing "retrieve" (doseq [count [0 1 2]] - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [(into [[:put {:fhir/type :fhir/Patient :id "0"}]] (map (fn [id] [:put {:fhir/type :fhir/Observation :id (str id) diff --git a/modules/cql/test/blaze/elm/expression/cache/bloom_filter_test.clj b/modules/cql/test/blaze/elm/expression/cache/bloom_filter_test.clj index 84fe6fca1..c06632ba9 100644 --- a/modules/cql/test/blaze/elm/expression/cache/bloom_filter_test.clj +++ b/modules/cql/test/blaze/elm/expression/cache/bloom_filter_test.clj @@ -1,7 +1,7 @@ (ns blaze.elm.expression.cache.bloom-filter-test (:require [blaze.db.api :as d] - [blaze.db.api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.elm.compiler :as c] [blaze.elm.compiler.test-util :as ctu] [blaze.elm.expression.cache.bloom-filter :as bloom-filter] @@ -32,7 +32,7 @@ (deftest create-test (testing "with empty database" - (with-system [{:blaze.db/keys [node]} mem-node-config] + (with-system [{:blaze.db/keys [node]} api-stub/mem-node-config] (let [elm #elm/exists #elm/retrieve{:type "Observation"} expr (c/compile {:eval-context "Patient"} elm)] @@ -43,7 +43,7 @@ ::bloom-filter/mem-size := 11981)))) (testing "with one Patient with one Observation" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}] [:put {:fhir/type :fhir/Observation :id "0" :subject #fhir/Reference{:reference #fhir/string "Patient/0"}}]]] @@ -58,7 +58,7 @@ ::bloom-filter/mem-size := 11981)))) (testing "with two Patients on of which has one Observation" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}] [:put {:fhir/type :fhir/Observation :id "0" :subject #fhir/Reference{:reference #fhir/string "Patient/0"}}] @@ -75,7 +75,7 @@ (deftest recreate-test (testing "with empty database" - (with-system [{:blaze.db/keys [node]} mem-node-config] + (with-system [{:blaze.db/keys [node]} api-stub/mem-node-config] (let [elm #elm/exists #elm/retrieve{:type "Observation"} expr (c/compile {:eval-context "Patient"} elm) bloom-filter (bloom-filter/create node expr)] @@ -87,7 +87,7 @@ ::bloom-filter/mem-size := 11981)))) (testing "with one Patient with one Observation added" - (with-system [{:blaze.db/keys [node]} mem-node-config] + (with-system [{:blaze.db/keys [node]} api-stub/mem-node-config] (let [elm #elm/exists #elm/retrieve{:type "Observation"} expr (c/compile {:eval-context "Patient"} elm) bloom-filter (bloom-filter/create node expr)] @@ -103,7 +103,7 @@ ::bloom-filter/mem-size := 11981)))) (testing "with one additional Patient with one Observation added" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}]]] (let [elm #elm/exists #elm/retrieve{:type "Observation"} diff --git a/modules/cql/test/blaze/elm/expression/cache_test.clj b/modules/cql/test/blaze/elm/expression/cache_test.clj index 63842dee6..1aa98a9a3 100644 --- a/modules/cql/test/blaze/elm/expression/cache_test.clj +++ b/modules/cql/test/blaze/elm/expression/cache_test.clj @@ -5,7 +5,7 @@ [blaze.cache-collector.protocols :as ccp] [blaze.coll.core :as coll] [blaze.db.api :as d] - [blaze.db.api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.elm.compiler :as c] [blaze.elm.compiler.test-util :as ctu] [blaze.elm.expression :as expr] @@ -46,11 +46,12 @@ (test/use-fixtures :each fixture) (def ^:private config - (assoc mem-node-config - ::expr/cache - {:node (ig/ref :blaze.db/node) - :executor (ig/ref :blaze.test/executor)} - :blaze.test/executor {})) + (assoc + api-stub/mem-node-config + ::expr/cache + {:node (ig/ref :blaze.db/node) + :executor (ig/ref :blaze.test/executor)} + :blaze.test/executor {})) (deftest init-test (testing "nil config" @@ -136,11 +137,12 @@ (is (s/valid? :blaze.metrics/collector collector)))) (def ^:private config - (assoc mem-node-config - ::expr/cache - {:node (ig/ref :blaze.db/node) - :executor (ig/ref :blaze.test/executor)} - :blaze.test/executor {})) + (assoc + api-stub/mem-node-config + ::expr/cache + {:node (ig/ref :blaze.db/node) + :executor (ig/ref :blaze.test/executor)} + :blaze.test/executor {})) (defn- compile-exists-expr [resource-type] (let [elm (elm/exists (elm/retrieve {:type resource-type}))] diff --git a/modules/cql/test/blaze/elm/literal.clj b/modules/cql/test/blaze/elm/literal.clj index 60ec6bbd2..e9f6266b4 100644 --- a/modules/cql/test/blaze/elm/literal.clj +++ b/modules/cql/test/blaze/elm/literal.clj @@ -125,7 +125,9 @@ ;; 3.12. ValueSetRef (defn value-set-ref [name] - {:type "ValueSetRef" :name name}) + {:type "ValueSetRef" + :name name + :resultTypeName "{urn:hl7-org:elm-types:r1}ValueSet"}) ;; 7. Parameters diff --git a/modules/cql/test/blaze/elm/resource_test.clj b/modules/cql/test/blaze/elm/resource_test.clj index 5244c89fc..80eec6852 100644 --- a/modules/cql/test/blaze/elm/resource_test.clj +++ b/modules/cql/test/blaze/elm/resource_test.clj @@ -1,7 +1,7 @@ (ns blaze.elm.resource-test (:require [blaze.db.api :as d] - [blaze.db.api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.elm.compiler.test-util :as ctu :refer [has-form]] [blaze.elm.expression-spec] [blaze.elm.resource :as cr] @@ -32,7 +32,7 @@ (:id x)) (deftest resource-test - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0" :gender #fhir/code "female"}]]] (let [resource (resource (d/db node) "Patient" "0")] diff --git a/modules/cql/test/blaze/elm/value_set_spec.clj b/modules/cql/test/blaze/elm/value_set_spec.clj index 265298d53..ad4a98764 100644 --- a/modules/cql/test/blaze/elm/value_set_spec.clj +++ b/modules/cql/test/blaze/elm/value_set_spec.clj @@ -1,5 +1,6 @@ (ns blaze.elm.value-set-spec (:require + [blaze.elm.code :as code] [blaze.elm.code :refer [code?]] [blaze.elm.concept :refer [concept?]] [blaze.elm.value-set :as value-set] @@ -7,6 +8,14 @@ [blaze.terminology-service.spec] [clojure.spec.alpha :as s])) +(s/fdef value-set/value-set? + :args (s/cat :x any?) + :ret boolean?) + +(s/fdef value-set/url + :args (s/cat :value-set :blaze.elm/value-set) + :ret string?) + (s/fdef value-set/contains-string? :args (s/cat :value-set :blaze.elm/value-set :code string?) :ret boolean?) @@ -19,6 +28,10 @@ :args (s/cat :value-set :blaze.elm/value-set :concept concept?) :ret boolean?) +(s/fdef value-set/expand + :args (s/cat :value-set :blaze.elm/value-set) + :ret (s/coll-of code/code?)) + (s/fdef value-set/value-set :args (s/cat :terminology-service :blaze/terminology-service :url string?) :ret :blaze.elm/value-set) diff --git a/modules/db-protocols/src/blaze/db/impl/protocols.clj b/modules/db-protocols/src/blaze/db/impl/protocols.clj index 8e5f1c0b5..722a39d85 100644 --- a/modules/db-protocols/src/blaze/db/impl/protocols.clj +++ b/modules/db-protocols/src/blaze/db/impl/protocols.clj @@ -33,6 +33,8 @@ "Returns a CompletableFuture that will complete with the count of the matching resource handles.") + (-optimize-query [db query]) + (-execute-query [db query] [db query arg1]) (-explain-query [db query]) @@ -88,6 +90,8 @@ "Returns a CompletableFuture that will complete with the count of the matching resource handles.") + (-optimize [query batch-db]) + (-execute [query batch-db] [query batch-db arg1]) (-query-clauses [query]) @@ -133,11 +137,11 @@ [search-param batch-db tid direction] [search-param batch-db tid direction start-id] "Returns a reducible collection of index handles sorted by the sort clause.") - (-supports-ordered-compartment-index-handles [search-param values] + (-supports-ordered-compartment-index-handles [search-param modifier values] "Returns true if `search-param` supports fetching ordered compartment index handles with `values`.") (-ordered-compartment-index-handles - [search-param batch-db compartment tid compiled-value] - [search-param batch-db compartment tid compiled-value start-id] + [search-param batch-db compartment tid modifier compiled-value] + [search-param batch-db compartment tid modifier compiled-value start-id] "Returns a reducible collection.") (-matcher [_ batch-db modifier compiled-values]) (-single-version-id-matcher [_ batch-db tid modifier compiled-values]) diff --git a/modules/db-stub/resources/clj-kondo.exports/blaze/db-stub/config.edn b/modules/db-stub/resources/clj-kondo.exports/blaze/db-stub/config.edn index 2ceab4c4d..0a54623b4 100644 --- a/modules/db-stub/resources/clj-kondo.exports/blaze/db-stub/config.edn +++ b/modules/db-stub/resources/clj-kondo.exports/blaze/db-stub/config.edn @@ -1,2 +1,3 @@ {:lint-as - {blaze.db.api-stub/with-system-data clojure.core/with-open}} + {blaze.db.api-stub/with-system clojure.core/with-open + blaze.db.api-stub/with-system-data clojure.core/with-open}} diff --git a/modules/db-stub/src/blaze/db/api_stub.clj b/modules/db-stub/src/blaze/db/api_stub.clj index 0a54b62af..a813d90c3 100644 --- a/modules/db-stub/src/blaze/db/api_stub.clj +++ b/modules/db-stub/src/blaze/db/api_stub.clj @@ -16,7 +16,9 @@ [blaze.fhir.parsing-context] [blaze.fhir.test-util :refer [structure-definition-repo]] [blaze.fhir.writing-context] - [blaze.module.test-util :refer [with-system]] + [blaze.module.test-util :as mtu] + [blaze.terminology-service :as-alias ts] + [blaze.terminology-service.local :as local] [integrant.core :as ig] [java-time.api :as time])) @@ -100,10 +102,24 @@ :blaze.db.node.resource-indexer/executor {} :blaze.db/search-param-registry - {:structure-definition-repo structure-definition-repo} + {:structure-definition-repo structure-definition-repo + :terminology-service (ig/ref ::ts/local)} + + ::ts/local + {:clock (ig/ref :blaze.test/fixed-clock) + :rng-fn (ig/ref :blaze.test/fixed-rng-fn) + :graph-cache (ig/ref ::local/graph-cache)} + + :blaze.test/fixed-rng-fn {} + ::local/graph-cache {} :blaze/scheduler {}}) +(defmacro with-system [[binding-form config] & body] + `(mtu/with-system [system# ~config] + (ts/post-init! (::ts/local system#) (:blaze.db/node system#)) + (let [~binding-form system#] ~@body))) + (defmacro with-system-data "Runs `body` inside a system that is initialized from `config`, bound to `binding-form` and finally halted. diff --git a/modules/db/deps.edn b/modules/db/deps.edn index 0420dabbe..9cd708407 100644 --- a/modules/db/deps.edn +++ b/modules/db/deps.edn @@ -43,6 +43,9 @@ blaze/spec {:local/root "../spec"} + blaze/terminology-service + {:local/root "../terminology-service"} + commons-codec/commons-codec {:mvn/version "1.20.0"}} diff --git a/modules/db/src/blaze/db/api.clj b/modules/db/src/blaze/db/api.clj index b2e654d8e..3e08fc19e 100644 --- a/modules/db/src/blaze/db/api.clj +++ b/modules/db/src/blaze/db/api.clj @@ -317,9 +317,24 @@ [db query] (p/-count-query db query)) +(defn optimize-query + "Optimizes a pre-compiled `query` on `db`. + + The optimized query can be only used on `db` because the optimizations might + depend on `db`. Returns the optimized query. + + See: + * compile-type-query + * compile-compartment-query" + [db query] + (p/-optimize-query db query)) + (defn execute-query "Executes a pre-compiled `query` with `args` on `db`. + You may optimize the query before running it, especially if plan to run it + multiple times with different arguments. + Returns a reducible collection of all matching resource handles. See: diff --git a/modules/db/src/blaze/db/impl/batch_db.clj b/modules/db/src/blaze/db/impl/batch_db.clj index cf90f8407..b564c906f 100644 --- a/modules/db/src/blaze/db/impl/batch_db.clj +++ b/modules/db/src/blaze/db/impl/batch_db.clj @@ -3,7 +3,6 @@ A batch database keeps key-value store iterators open in order to avoid the cost associated with open and closing them." - (:refer-clojure :exclude [str]) (:require [blaze.anomaly :as ba :refer [if-ok when-ok]] [blaze.async.comp :as ac] @@ -22,12 +21,12 @@ [blaze.db.impl.index.type-as-of :as tao] [blaze.db.impl.index.type-stats :as type-stats] [blaze.db.impl.protocols :as p] + [blaze.db.impl.query.util :as qu] [blaze.db.impl.search-param.chained :as spc] [blaze.db.impl.search-param.util :as u] [blaze.db.kv :as kv] [blaze.db.node.resource-indexer :as resource-indexer] - [blaze.db.search-param-registry :as sr] - [blaze.util :refer [str]]) + [blaze.db.search-param-registry :as sr]) (:import [java.io Writer] [java.lang AutoCloseable])) @@ -66,6 +65,8 @@ (or (sr/get-by-url search-param-registry url) (ba/not-found (format "Search parameter with URL `%s` not found." url)))) +(declare new-batch-db) + (defrecord BatchDb [node kv-store snapshot basis-t t since-t] p/Db (-node [_] @@ -136,6 +137,9 @@ (-count-query [db query] (p/-count query db)) + (-optimize-query [db query] + (p/-optimize query db)) + (-execute-query [db query] (p/-execute query db)) @@ -227,6 +231,11 @@ (resource-indexer/re-index-resources (:resource-indexer node) search-param (sp-list db search-param start-type start-id)) ac/completed-future)) + ;; ---- Batch DB ------------------------------------------------------------ + + (-new-batch-db [_] + (new-batch-db node basis-t t since-t)) + ;; ---- Transaction --------------------------------------------------------- p/Tx @@ -276,26 +285,18 @@ (defmethod print-method BatchDb [^BatchDb db ^Writer w] (.write w (format "BatchDb[t=%d]" (.t db)))) -(defn- decode-clauses [clauses] - (into - [] - (keep - (fn [[search-param modifier values]] - (if (#{"asc" "desc"} modifier) - [:sort (:code search-param) (keyword modifier)] - (into [(cond-> (:code search-param) modifier (str ":" modifier))] values)))) - clauses)) - (defrecord TypeQuery [tid clauses] p/Query (-count [_ batch-db] (index/type-query-total batch-db tid clauses)) + (-optimize [query _] + query) (-execute [_ batch-db] (index/type-query batch-db tid clauses)) (-execute [_ batch-db start-id] (index/type-query batch-db tid clauses (codec/id-byte-string start-id))) (-query-clauses [_] - (decode-clauses clauses)) + (qu/decode-clauses clauses)) (-query-plan [_ batch-db] (index/type-query-plan batch-db tid clauses))) @@ -313,6 +314,8 @@ p/Query (-count [query batch-db] (ac/completed-future (count (p/-execute query batch-db)))) + (-optimize [query _] + query) (-execute [_ batch-db] (coll/eduction (mapcat #(compartment-query batch-db %)) patient-ids)) (-execute [_ batch-db start-id] @@ -327,7 +330,7 @@ (mapcat #(compartment-query batch-db %))) patient-ids)]))) (-query-clauses [_] - (decode-clauses (into [compartment-clause] clauses))) + (qu/decode-clauses (into [compartment-clause] clauses))) (-query-plan [_ _] (index/compartment-query-plan clauses))) @@ -347,6 +350,8 @@ (-count [_ batch-db] (ac/completed-future (:total (type-stats/seek-value (:snapshot batch-db) tid (:t batch-db)) 0))) + (-optimize [query _] + query) (-execute [_ batch-db] (rao/type-list batch-db tid)) (-execute [_ batch-db start-id] @@ -357,39 +362,23 @@ (defrecord SystemQuery [clauses] p/Query + (-optimize [query _] + query) (-execute [_ batch-db] (index/system-query batch-db clauses))) -(defrecord CompartmentQuery [c-hash tid clauses] - p/Query - (-execute [_ batch-db arg1] - (index/compartment-query batch-db [c-hash (codec/id-byte-string arg1)] - tid clauses)) - (-query-clauses [_] - (decode-clauses clauses)) - (-query-plan [_ _] - (index/compartment-query-plan clauses))) - -(defrecord EmptyCompartmentQuery [c-hash tid] - p/Query - (-execute [_ batch-db arg1] - (cr/resource-handles batch-db [c-hash (codec/id-byte-string arg1)] tid)) - (-query-clauses [_]) - (-query-plan [_ _] - {:query-type :compartment})) - (defrecord Matcher [clauses] p/Matcher (-transducer [_ batch-db] (index/other-clauses-resource-handle-filter batch-db clauses)) (-matcher-clauses [_] - (decode-clauses clauses))) + (qu/decode-clauses clauses))) (defn new-batch-db "Creates a new batch database. A batch database can be used instead of a normal database. It's functionally - the same. Only the performance for multiple calls differs. It's not thread + is the same. Only the performance for multiple calls differs. It's not thread save and has to be closed after usage because it holds open iterators." ^AutoCloseable [{:keys [kv-store] :as node} basis-t t since-t] diff --git a/modules/db/src/blaze/db/impl/db.clj b/modules/db/src/blaze/db/impl/db.clj index f3d322642..dc39da21c 100644 --- a/modules/db/src/blaze/db/impl/db.clj +++ b/modules/db/src/blaze/db/impl/db.clj @@ -98,6 +98,10 @@ (-> (p/-count-query batch-db query) (ac/when-complete (fn [_ _] (.close batch-db)))))) + (-optimize-query [_ query] + (with-open [batch-db (batch-db/new-batch-db node basis-t t since-t)] + (p/-optimize-query batch-db query))) + (-execute-query [_ query] (with-open-coll [batch-db (batch-db/new-batch-db node basis-t t since-t)] (p/-execute-query batch-db query))) diff --git a/modules/db/src/blaze/db/impl/index.clj b/modules/db/src/blaze/db/impl/index.clj index 3075caa59..fa7186112 100644 --- a/modules/db/src/blaze/db/impl/index.clj +++ b/modules/db/src/blaze/db/impl/index.clj @@ -325,8 +325,8 @@ ;; TODO: implement []) -(defn- supports-ordered-compartment-index-handles [[search-param _ values]] - (p/-supports-ordered-compartment-index-handles search-param values)) +(defn- supports-ordered-compartment-index-handles [[search-param modifier values]] + (p/-supports-ordered-compartment-index-handles search-param modifier values)) (defn- compartment-query-plan* [clauses] (let [{scan-clauses true other-clauses false} @@ -334,12 +334,12 @@ [scan-clauses other-clauses])) (defn- ordered-compartment-index-handles* - ([batch-db compartment tid [search-param _ _ compiled-values]] + ([batch-db compartment tid [search-param modifier _ compiled-values]] (search-param/ordered-compartment-index-handles - search-param batch-db compartment tid compiled-values)) - ([batch-db compartment tid [search-param _ _ compiled-values] start-id] + search-param batch-db compartment tid modifier compiled-values)) + ([batch-db compartment tid [search-param modifier _ compiled-values] start-id] (search-param/ordered-compartment-index-handles - search-param batch-db compartment tid compiled-values start-id))) + search-param batch-db compartment tid modifier compiled-values start-id))) (defn- ordered-compartment-index-handles ([batch-db compartment tid clauses] diff --git a/modules/db/src/blaze/db/impl/query/compartment.clj b/modules/db/src/blaze/db/impl/query/compartment.clj new file mode 100644 index 000000000..dd406754b --- /dev/null +++ b/modules/db/src/blaze/db/impl/query/compartment.clj @@ -0,0 +1,46 @@ +(ns blaze.db.impl.query.compartment + (:require + [blaze.coll.core :as coll] + [blaze.db.impl.codec :as codec] + [blaze.db.impl.index :as index] + [blaze.db.impl.index.compartment.resource :as cr] + [blaze.db.impl.protocols :as p] + [blaze.db.impl.query.util :as qu])) + +(defn- code-clause [[search-param] compiled-value] + [search-param nil [] [compiled-value]]) + +(defn- optimize-in-compiled-value [batch-db tid clause compiled-value] + (filterv #(coll/first (index/type-query batch-db tid [(code-clause clause %)])) + compiled-value)) + +(defn- optimize-in-compiled-values [batch-db tid [_ _ _ compiled-values :as clause]] + (mapv (partial optimize-in-compiled-value batch-db tid clause) compiled-values)) + +(defn- optimize-clause [batch-db tid [_ modifier :as clause]] + (if (= "in" modifier) + (assoc clause 3 (optimize-in-compiled-values batch-db tid clause)) + clause)) + +(defrecord CompartmentQuery [c-hash tid clauses] + p/Query + (-optimize [_ batch-db] + (->> (mapv (partial optimize-clause batch-db tid) clauses) + (->CompartmentQuery c-hash tid))) + (-execute [_ batch-db arg1] + (index/compartment-query batch-db [c-hash (codec/id-byte-string arg1)] + tid clauses)) + (-query-clauses [_] + (qu/decode-clauses clauses)) + (-query-plan [_ _] + (index/compartment-query-plan clauses))) + +(defrecord EmptyCompartmentQuery [c-hash tid] + p/Query + (-optimize [query _] + query) + (-execute [_ batch-db arg1] + (cr/resource-handles batch-db [c-hash (codec/id-byte-string arg1)] tid)) + (-query-clauses [_]) + (-query-plan [_ _] + {:query-type :compartment})) diff --git a/modules/db/src/blaze/db/impl/query/util.clj b/modules/db/src/blaze/db/impl/query/util.clj new file mode 100644 index 000000000..e2a973a1b --- /dev/null +++ b/modules/db/src/blaze/db/impl/query/util.clj @@ -0,0 +1,14 @@ +(ns blaze.db.impl.query.util + (:refer-clojure :exclude [str]) + (:require + [blaze.util :refer [str]])) + +(defn decode-clauses [clauses] + (into + [] + (keep + (fn [[search-param modifier values]] + (if (#{"asc" "desc"} modifier) + [:sort (:code search-param) (keyword modifier)] + (into [(cond-> (:code search-param) modifier (str ":" modifier))] values)))) + clauses)) diff --git a/modules/db/src/blaze/db/impl/search_param.clj b/modules/db/src/blaze/db/impl/search_param.clj index 84f8606f9..fff7f4204 100644 --- a/modules/db/src/blaze/db/impl/search_param.clj +++ b/modules/db/src/blaze/db/impl/search_param.clj @@ -5,7 +5,6 @@ [blaze.coll.core :as coll] [blaze.db.impl.codec :as codec] [blaze.db.impl.index.compartment.search-param-value-resource :as c-sp-vr] - [blaze.db.impl.index.index-handle :as ih] [blaze.db.impl.index.resource-search-param-value :as r-sp-v] [blaze.db.impl.index.search-param-value-resource :as sp-vr] [blaze.db.impl.protocols :as p] @@ -18,6 +17,7 @@ [blaze.db.impl.search-param.quantity] [blaze.db.impl.search-param.string] [blaze.db.impl.search-param.token] + [blaze.db.impl.search-param.util :as u] [blaze.fhir-path :as fhir-path] [blaze.fhir.spec.references :as fsr] [blaze.util :refer [str]])) @@ -101,22 +101,22 @@ `search-param`. The index handles are distinct and ordered by id." - ([search-param batch-db compartment tid compiled-values] + ([search-param batch-db compartment tid modifier compiled-values] (if (= 1 (count compiled-values)) (p/-ordered-compartment-index-handles - search-param batch-db compartment tid (first compiled-values)) + search-param batch-db compartment tid modifier (first compiled-values)) (->> (map #(p/-ordered-compartment-index-handles - search-param batch-db compartment tid %) + search-param batch-db compartment tid modifier %) compiled-values) - (apply coll/union ih/id-comp ih/union)))) - ([search-param batch-db compartment tid compiled-values start-id] + (u/union-index-handles)))) + ([search-param batch-db compartment tid modifier compiled-values start-id] (if (= 1 (count compiled-values)) (p/-ordered-compartment-index-handles - search-param batch-db compartment tid (first compiled-values) start-id) + search-param batch-db compartment tid modifier (first compiled-values) start-id) (->> (map #(p/-ordered-compartment-index-handles - search-param batch-db compartment tid % start-id) + search-param batch-db compartment tid modifier % start-id) compiled-values) - (apply coll/union ih/id-comp ih/union))))) + (u/union-index-handles))))) (defn matcher "Returns a stateful transducer that filters resource handles depending on diff --git a/modules/db/src/blaze/db/impl/search_param/chained.clj b/modules/db/src/blaze/db/impl/search_param/chained.clj index 1d071c0d2..d899cb61a 100644 --- a/modules/db/src/blaze/db/impl/search_param/chained.clj +++ b/modules/db/src/blaze/db/impl/search_param/chained.clj @@ -130,13 +130,13 @@ (map ih/from-resource-handle)) (p/-index-handles this batch-db tid modifier compiled-value)))) - (-supports-ordered-compartment-index-handles [_ _] + (-supports-ordered-compartment-index-handles [_ _ _] false) - (-ordered-compartment-index-handles [_ _ _ _ _] + (-ordered-compartment-index-handles [_ _ _ _ _ _] (ba/unsupported)) - (-ordered-compartment-index-handles [_ _ _ _ _ _] + (-ordered-compartment-index-handles [_ _ _ _ _ _ _] (ba/unsupported)) (-matcher [_ batch-db modifier values] diff --git a/modules/db/src/blaze/db/impl/search_param/composite.clj b/modules/db/src/blaze/db/impl/search_param/composite.clj index 612a68fec..b9a83d34a 100644 --- a/modules/db/src/blaze/db/impl/search_param/composite.clj +++ b/modules/db/src/blaze/db/impl/search_param/composite.clj @@ -68,6 +68,6 @@ (assoc anomaly ::anom/category ::anom/unsupported)) (defmethod sc/search-param "composite" - [index search-param] + [{:keys [index]} search-param] (-> (create-search-param index search-param) (ba/exceptionally #(handle-anomaly search-param %)))) diff --git a/modules/db/src/blaze/db/impl/search_param/composite/token_quantity.clj b/modules/db/src/blaze/db/impl/search_param/composite/token_quantity.clj index b7bfaafbe..c7d979f38 100644 --- a/modules/db/src/blaze/db/impl/search_param/composite/token_quantity.clj +++ b/modules/db/src/blaze/db/impl/search_param/composite/token_quantity.clj @@ -66,13 +66,13 @@ (-index-handles [_ batch-db tid _ compiled-value start-id] (spq/index-handles batch-db c-hash tid prefix-length compiled-value start-id)) - (-supports-ordered-compartment-index-handles [_ _] + (-supports-ordered-compartment-index-handles [_ _ _] false) - (-ordered-compartment-index-handles [_ _ _ _ _] + (-ordered-compartment-index-handles [_ _ _ _ _ _] (ba/unsupported)) - (-ordered-compartment-index-handles [_ _ _ _ _ _] + (-ordered-compartment-index-handles [_ _ _ _ _ _ _] (ba/unsupported)) (-matcher [_ batch-db _ compiled-values] diff --git a/modules/db/src/blaze/db/impl/search_param/composite/token_token.clj b/modules/db/src/blaze/db/impl/search_param/composite/token_token.clj index 8725b5882..f00d475b7 100644 --- a/modules/db/src/blaze/db/impl/search_param/composite/token_token.clj +++ b/modules/db/src/blaze/db/impl/search_param/composite/token_token.clj @@ -49,13 +49,13 @@ (-index-handles [_ batch-db tid _ compiled-value start-id] (spt/index-handles batch-db c-hash tid compiled-value start-id)) - (-supports-ordered-compartment-index-handles [_ _] + (-supports-ordered-compartment-index-handles [_ _ _] false) - (-ordered-compartment-index-handles [_ _ _ _ _] + (-ordered-compartment-index-handles [_ _ _ _ _ _] (ba/unsupported)) - (-ordered-compartment-index-handles [_ _ _ _ _ _] + (-ordered-compartment-index-handles [_ _ _ _ _ _ _] (ba/unsupported)) (-matcher [_ batch-db _ compiled-values] diff --git a/modules/db/src/blaze/db/impl/search_param/core.clj b/modules/db/src/blaze/db/impl/search_param/core.clj index 2e3a3dd30..ad6bb1ac5 100644 --- a/modules/db/src/blaze/db/impl/search_param/core.clj +++ b/modules/db/src/blaze/db/impl/search_param/core.clj @@ -10,7 +10,7 @@ in the registry. Other namespaces can provide their own implementations here. The conversion can return an anomaly." - {:arglists '([index definition])} + {:arglists '([context definition])} (fn [_ {:keys [type]}] type)) (defmethod search-param :default diff --git a/modules/db/src/blaze/db/impl/search_param/date.clj b/modules/db/src/blaze/db/impl/search_param/date.clj index d3b010fea..581fd37fa 100644 --- a/modules/db/src/blaze/db/impl/search_param/date.clj +++ b/modules/db/src/blaze/db/impl/search_param/date.clj @@ -428,13 +428,13 @@ (all-keys batch-db c-hash tid start-id) (all-keys-prev batch-db c-hash tid start-id)))) - (-supports-ordered-compartment-index-handles [_ _] + (-supports-ordered-compartment-index-handles [_ _ _] false) - (-ordered-compartment-index-handles [_ _ _ _ _] + (-ordered-compartment-index-handles [_ _ _ _ _ _] (ba/unsupported)) - (-ordered-compartment-index-handles [_ _ _ _ _ _] + (-ordered-compartment-index-handles [_ _ _ _ _ _ _] (ba/unsupported)) (-matcher [_ batch-db _ values] diff --git a/modules/db/src/blaze/db/impl/search_param/has.clj b/modules/db/src/blaze/db/impl/search_param/has.clj index 8a6c61142..c06bcc340 100644 --- a/modules/db/src/blaze/db/impl/search_param/has.clj +++ b/modules/db/src/blaze/db/impl/search_param/has.clj @@ -132,13 +132,13 @@ (map ih/from-resource-handle)) (resource-handles batch-db tid compiled-value))) - (-supports-ordered-compartment-index-handles [_ _] + (-supports-ordered-compartment-index-handles [_ _ _] false) - (-ordered-compartment-index-handles [_ _ _ _ _] + (-ordered-compartment-index-handles [_ _ _ _ _ _] (ba/unsupported)) - (-ordered-compartment-index-handles [_ _ _ _ _ _] + (-ordered-compartment-index-handles [_ _ _ _ _ _ _] (ba/unsupported)) (-matcher [_ batch-db _ compiled-values] diff --git a/modules/db/src/blaze/db/impl/search_param/list.clj b/modules/db/src/blaze/db/impl/search_param/list.clj index f6a5d0fb9..cf7291a6c 100644 --- a/modules/db/src/blaze/db/impl/search_param/list.clj +++ b/modules/db/src/blaze/db/impl/search_param/list.clj @@ -80,13 +80,13 @@ (referenced-index-handles batch-db list-id hash tid start-id) [])) - (-supports-ordered-compartment-index-handles [_ _] + (-supports-ordered-compartment-index-handles [_ _ _] false) - (-ordered-compartment-index-handles [_ _ _ _ _] + (-ordered-compartment-index-handles [_ _ _ _ _ _] (ba/unsupported)) - (-ordered-compartment-index-handles [_ _ _ _ _ _] + (-ordered-compartment-index-handles [_ _ _ _ _ _ _] (ba/unsupported)) (-postprocess-matches [_ _ _ _]) diff --git a/modules/db/src/blaze/db/impl/search_param/near.clj b/modules/db/src/blaze/db/impl/search_param/near.clj index f77b17048..51048ce99 100644 --- a/modules/db/src/blaze/db/impl/search_param/near.clj +++ b/modules/db/src/blaze/db/impl/search_param/near.clj @@ -166,13 +166,13 @@ (map ih/from-resource-handle)) (p/-type-list batch-db tid start-id))) - (-supports-ordered-compartment-index-handles [_ _] + (-supports-ordered-compartment-index-handles [_ _ _] false) - (-ordered-compartment-index-handles [_ _ _ _ _] + (-ordered-compartment-index-handles [_ _ _ _ _ _] (ba/unsupported)) - (-ordered-compartment-index-handles [_ _ _ _ _ _] + (-ordered-compartment-index-handles [_ _ _ _ _ _ _] (ba/unsupported)) (-matcher [_ batch-db _ compiled-values] diff --git a/modules/db/src/blaze/db/impl/search_param/number.clj b/modules/db/src/blaze/db/impl/search_param/number.clj index 448bb2f4a..cc5030ba8 100644 --- a/modules/db/src/blaze/db/impl/search_param/number.clj +++ b/modules/db/src/blaze/db/impl/search_param/number.clj @@ -82,13 +82,13 @@ (-index-handles [_ batch-db tid _ compiled-value start-id] (spq/index-handles batch-db c-hash tid 0 compiled-value start-id)) - (-supports-ordered-compartment-index-handles [_ _] + (-supports-ordered-compartment-index-handles [_ _ _] false) - (-ordered-compartment-index-handles [_ _ _ _ _] + (-ordered-compartment-index-handles [_ _ _ _ _ _] (ba/unsupported)) - (-ordered-compartment-index-handles [_ _ _ _ _ _] + (-ordered-compartment-index-handles [_ _ _ _ _ _ _] (ba/unsupported)) (-matcher [_ batch-db _ compiled-values] diff --git a/modules/db/src/blaze/db/impl/search_param/quantity.clj b/modules/db/src/blaze/db/impl/search_param/quantity.clj index 8fc9a7dc0..2415e6bdd 100644 --- a/modules/db/src/blaze/db/impl/search_param/quantity.clj +++ b/modules/db/src/blaze/db/impl/search_param/quantity.clj @@ -280,13 +280,13 @@ (index-handles batch-db c-hash tid codec/v-hash-size compiled-value start-id)) - (-supports-ordered-compartment-index-handles [_ _] + (-supports-ordered-compartment-index-handles [_ _ _] false) - (-ordered-compartment-index-handles [_ _ _ _ _] + (-ordered-compartment-index-handles [_ _ _ _ _ _] (ba/unsupported)) - (-ordered-compartment-index-handles [_ _ _ _ _ _] + (-ordered-compartment-index-handles [_ _ _ _ _ _ _] (ba/unsupported)) (-matcher [_ batch-db _ values] diff --git a/modules/db/src/blaze/db/impl/search_param/special.clj b/modules/db/src/blaze/db/impl/search_param/special.clj index 28df9099e..f153a0f3d 100644 --- a/modules/db/src/blaze/db/impl/search_param/special.clj +++ b/modules/db/src/blaze/db/impl/search_param/special.clj @@ -8,7 +8,7 @@ (fn [_ {:keys [name]}] name)) (defmethod sc/search-param "special" - [index search-param] + [{:keys [index]} search-param] (special-search-param index search-param)) (defmethod special-search-param :default diff --git a/modules/db/src/blaze/db/impl/search_param/string.clj b/modules/db/src/blaze/db/impl/search_param/string.clj index 3db388c4d..585be7f13 100644 --- a/modules/db/src/blaze/db/impl/search_param/string.clj +++ b/modules/db/src/blaze/db/impl/search_param/string.clj @@ -99,13 +99,13 @@ (-index-handles [_ batch-db tid _ compiled-value start-id] (index-handles batch-db c-hash tid compiled-value start-id)) - (-supports-ordered-compartment-index-handles [_ _] + (-supports-ordered-compartment-index-handles [_ _ _] false) - (-ordered-compartment-index-handles [_ _ _ _ _] + (-ordered-compartment-index-handles [_ _ _ _ _ _] (ba/unsupported)) - (-ordered-compartment-index-handles [_ _ _ _ _ _] + (-ordered-compartment-index-handles [_ _ _ _ _ _ _] (ba/unsupported)) (-matcher [_ batch-db _ compled-values] diff --git a/modules/db/src/blaze/db/impl/search_param/token.clj b/modules/db/src/blaze/db/impl/search_param/token.clj index adf9a73e1..1e6416777 100644 --- a/modules/db/src/blaze/db/impl/search_param/token.clj +++ b/modules/db/src/blaze/db/impl/search_param/token.clj @@ -17,7 +17,9 @@ [blaze.db.impl.search-param.util :as u] [blaze.fhir-path :as fhir-path] [blaze.fhir.spec.references :as fsr] + [blaze.fhir.spec.type :as type] [blaze.fhir.spec.type.system :as system] + [blaze.terminology-service :as ts] [blaze.util :refer [str]] [clojure.string :as str] [taoensso.timbre :as log])) @@ -167,7 +169,32 @@ (def ^:private known-reference-modifier #{"above" "below" "code-text" "contains" "identifier" "missing" "not-in" "text" "text-advanced"}) -(defrecord SearchParamToken [name url type base code target c-hash expression] +(defn- url-param [url] + {:fhir/type :fhir.Parameters/parameter + :name #fhir/string "url" + :value (type/uri url)}) + +(defn- parameters [url] + {:fhir/type :fhir/Parameters + :parameter [(url-param url)]}) + +(defn- compile-concept [{:keys [system code]}] + (codec/v-hash (str (:value system) "|" (:value code)))) + +(defn- expand-value-set-msg [url cause-msg] + (format "Error while expanding the ValueSet `%s`. Cause: %s" url cause-msg)) + +(defn- compile-concepts [response url] + (try + (mapv compile-concept (:contains (:expansion @response))) + (catch Exception e + (ba/fault (expand-value-set-msg url (ex-message (ex-cause e))))))) + +(defn- compile-value-set [terminology-service url] + (-> (ts/expand-value-set terminology-service (parameters url)) + (compile-concepts url))) + +(defrecord SearchParamToken [terminology-service name url type base code target c-hash expression] p/SearchParam (-validate-modifier [_ modifier] (condp = type @@ -175,18 +202,23 @@ (when-not (#{"below"} modifier) (some->> modifier (u/modifier-anom known-uri-modifier code))) "token" - (some->> modifier (u/modifier-anom known-token-modifier code)) + (when-not (#{"in"} modifier) + (some->> modifier (u/modifier-anom known-token-modifier code))) ; else / "reference" (when-not ((into #{"identifier"} target) modifier) (some->> modifier (u/modifier-anom (into known-reference-modifier target) code))))) - (-compile-value [_ _ value] - (if (= "reference" type) + (-compile-value [_ modifier value] + (cond + (= "reference" type) (if-let [[type id] (fsr/split-literal-ref value)] (codec/tid-id (codec/tid type) (codec/id-byte-string id)) (if (and (= 1 (count target)) (.matches (re-matcher #"[A-Za-z0-9\-\.]{1,64}" value))) (codec/tid-id (codec/tid (first target)) (codec/id-byte-string value)) (codec/v-hash value))) + (= "in" modifier) + (compile-value-set terminology-service value) + :else (codec/v-hash value))) (-estimated-scan-size [_ batch-db tid modifier compiled-value] @@ -198,17 +230,21 @@ (-ordered-index-handles [search-param batch-db tid modifier compiled-values] - (if (= 1 (count compiled-values)) - (p/-index-handles search-param batch-db tid modifier (first compiled-values)) - (let [index-handles #(p/-index-handles search-param batch-db tid modifier %)] - (u/union-index-handles (map index-handles compiled-values))))) + (if (= "in" modifier) + (p/-ordered-index-handles search-param batch-db tid nil (flatten compiled-values)) + (if (= 1 (count compiled-values)) + (p/-index-handles search-param batch-db tid modifier (first compiled-values)) + (let [index-handles #(p/-index-handles search-param batch-db tid modifier %)] + (u/union-index-handles (map index-handles compiled-values)))))) (-ordered-index-handles [search-param batch-db tid modifier compiled-values start-id] - (if (= 1 (count compiled-values)) - (p/-index-handles search-param batch-db tid modifier (first compiled-values) start-id) - (let [index-handles #(p/-index-handles search-param batch-db tid modifier % start-id)] - (u/union-index-handles (map index-handles compiled-values))))) + (if (= "in" modifier) + (p/-ordered-index-handles search-param batch-db tid nil (flatten compiled-values) start-id) + (if (= 1 (count compiled-values)) + (p/-index-handles search-param batch-db tid modifier (first compiled-values) start-id) + (let [index-handles #(p/-index-handles search-param batch-db tid modifier % start-id)] + (u/union-index-handles (map index-handles compiled-values)))))) (-index-handles [_ batch-db tid modifier compiled-value] (index-handles batch-db (c-hash-w-modifier c-hash code modifier) tid @@ -218,14 +254,19 @@ (index-handles batch-db (c-hash-w-modifier c-hash code modifier) tid compiled-value start-id)) - (-supports-ordered-compartment-index-handles [_ values] + (-supports-ordered-compartment-index-handles [_ modifier values] ;; the CompartmentSearchParamValueResource index only contains values with systems - (every? has-system? values)) + ;; with in-modifier, a ValueSet expansion contains always systems + (or (= "in" modifier) (every? has-system? values))) - (-ordered-compartment-index-handles [_ batch-db compartment tid compiled-value] - (c-sp-vr/index-handles (:snapshot batch-db) compartment c-hash tid compiled-value)) + (-ordered-compartment-index-handles [_ batch-db compartment tid modifier compiled-value] + (if (= "in" modifier) + (let [index-handles #(c-sp-vr/index-handles (:snapshot batch-db) compartment c-hash tid %)] + (u/union-index-handles (map index-handles compiled-value))) + (c-sp-vr/index-handles (:snapshot batch-db) compartment c-hash tid compiled-value))) - (-ordered-compartment-index-handles [_ batch-db compartment tid compiled-value start-id] + (-ordered-compartment-index-handles [_ batch-db compartment tid _modifier compiled-value start-id] + ;; TODO: is that method called? (c-sp-vr/index-handles (:snapshot batch-db) compartment c-hash tid compiled-value start-id)) (-matcher [_ batch-db modifier compiled-values] @@ -315,13 +356,13 @@ (index-handles batch-db (c-hash-w-modifier c-hash code modifier) tid compiled-value start-id)) - (-supports-ordered-compartment-index-handles [_ _] + (-supports-ordered-compartment-index-handles [_ _ _] false) - (-ordered-compartment-index-handles [_ _ _ _ _] + (-ordered-compartment-index-handles [_ _ _ _ _ _] (ba/unsupported)) - (-ordered-compartment-index-handles [_ _ _ _ _ _] + (-ordered-compartment-index-handles [_ _ _ _ _ _ _] (ba/unsupported)) (-matcher [_ batch-db modifier compiled-values] @@ -398,13 +439,13 @@ (map ih/from-resource-handle) (rao/type-list batch-db tid start-id))) - (-supports-ordered-compartment-index-handles [_ _] + (-supports-ordered-compartment-index-handles [_ _ _] false) - (-ordered-compartment-index-handles [_ _ _ _ _] + (-ordered-compartment-index-handles [_ _ _ _ _ _] (ba/unsupported)) - (-ordered-compartment-index-handles [_ _ _ _ _ _] + (-ordered-compartment-index-handles [_ _ _ _ _ _ _] (ba/unsupported)) (-postprocess-matches [_ _ _ _]) @@ -422,7 +463,7 @@ expression)) (defmethod sc/search-param "token" - [_ {:keys [name url type base code target expression]}] + [{:keys [terminology-service]} {:keys [name url type base code target expression]}] (if (= "_id" code) (->SearchParamId "_id" "id" "_id") (if expression @@ -430,22 +471,22 @@ (if (= "identifier" code) (->SearchParamTokenIdentifier name url type base code target (codec/c-hash code) expression) - (->SearchParamToken name url type base code target (codec/c-hash code) - expression))) + (->SearchParamToken terminology-service name url type base code target + (codec/c-hash code) expression))) (ba/unsupported (u/missing-expression-msg url))))) (defmethod sc/search-param "reference" - [_ {:keys [name url type base code target expression]}] + [{:keys [terminology-service]} {:keys [name url type base code target expression]}] (if expression (when-ok [expression (fhir-path/compile expression)] - (->SearchParamToken name url type base code target (codec/c-hash code) - expression)) + (->SearchParamToken terminology-service name url type base code target + (codec/c-hash code) expression)) (ba/unsupported (u/missing-expression-msg url)))) (defmethod sc/search-param "uri" - [_ {:keys [name url type base code target expression]}] + [{:keys [terminology-service]} {:keys [name url type base code target expression]}] (if expression (when-ok [expression (fhir-path/compile expression)] - (->SearchParamToken name url type base code target (codec/c-hash code) - expression)) + (->SearchParamToken terminology-service name url type base code target + (codec/c-hash code) expression)) (ba/unsupported (u/missing-expression-msg url)))) diff --git a/modules/db/src/blaze/db/node.clj b/modules/db/src/blaze/db/node.clj index c1d00f769..ebe2d6cdb 100644 --- a/modules/db/src/blaze/db/node.clj +++ b/modules/db/src/blaze/db/node.clj @@ -16,6 +16,7 @@ [blaze.db.impl.index.tx-error :as tx-error] [blaze.db.impl.index.tx-success :as tx-success] [blaze.db.impl.protocols :as p] + [blaze.db.impl.query.compartment :as qc] [blaze.db.kv :as kv] [blaze.db.node.protocols :as np] [blaze.db.node.resource-indexer :as resource-indexer] @@ -270,9 +271,9 @@ (when-ok [clauses (index/resolve-search-params search-param-registry type clauses lenient?)] (if (empty? clauses) - (batch-db/->EmptyCompartmentQuery (codec/c-hash code) (codec/tid type)) - (batch-db/->CompartmentQuery (codec/c-hash code) (codec/tid type) - clauses)))) + (qc/->EmptyCompartmentQuery (codec/c-hash code) (codec/tid type)) + (qc/->CompartmentQuery (codec/c-hash code) (codec/tid type) + clauses)))) (def ^:private add-subsetted-xf (map #(update % :meta update :tag conj-vec fu/subsetted))) diff --git a/modules/db/src/blaze/db/search_param_registry.clj b/modules/db/src/blaze/db/search_param_registry.clj index 9c01d8d4c..fd250bd4e 100644 --- a/modules/db/src/blaze/db/search_param_registry.clj +++ b/modules/db/src/blaze/db/search_param_registry.clj @@ -9,6 +9,7 @@ [blaze.db.impl.search-param.core :as sc] [blaze.db.search-param-registry.spec] [blaze.module :as m] + [blaze.terminology-service.spec] [blaze.util :refer [conj-vec str]] [clojure.java.io :as io] [clojure.spec.alpha :as s] @@ -169,8 +170,11 @@ extra-bundle-file (into (:entry (read-file-json-resource extra-bundle-file))))) -(defn- index-search-param [index {:keys [url] :as sp}] - (if-ok [search-param (sc/search-param index sp)] +(defn- search-param [terminology-service index def] + (sc/search-param {:terminology-service terminology-service :index index} def)) + +(defn- index-search-param [terminology-service index {:keys [url] :as sp}] + (if-ok [search-param (search-param terminology-service index sp)] (assoc index url search-param) #(if (ba/unsupported? %) index @@ -229,16 +233,16 @@ "Add special search params to `index`. See: https://www.hl7.org/fhir/search.html#special" - [index] - (-> (assoc-in index ["Resource" "_list"] (sc/search-param nil list-search-param)) - (assoc-in ["Resource" "_has"] (sc/search-param index has-search-param)) - (assoc-in ["Location" "near"] (sc/search-param index near-search-param)))) + [terminology-service index] + (-> (assoc-in index ["Resource" "_list"] (search-param terminology-service nil list-search-param)) + (assoc-in ["Resource" "_has"] (search-param terminology-service index has-search-param)) + (assoc-in ["Location" "near"] (search-param terminology-service index near-search-param)))) -(defn- build-url-index* [index filter entries] +(defn- build-url-index* [terminology-service index filter entries] (transduce (comp (map :resource) filter) - (completing index-search-param) + (completing (partial index-search-param terminology-service)) index entries)) @@ -253,9 +257,9 @@ Ensures that non-composite search params are build first so that composite search params will find it's components in the already partial build index." - [entries] - (when-ok [non-composite (build-url-index* {} remove-composite entries)] - (build-url-index* non-composite filter-composite entries))) + [terminology-service entries] + (when-ok [non-composite (build-url-index* terminology-service {} remove-composite entries)] + (build-url-index* terminology-service non-composite filter-composite entries))) (defn- build-index "Builds an index from [type code] to search param." @@ -348,19 +352,19 @@ :else #{"subject" "patient"}))) (defmethod m/pre-init-spec :blaze.db/search-param-registry [_] - (s/keys :req-un [:blaze.fhir/structure-definition-repo] + (s/keys :req-un [:blaze.fhir/structure-definition-repo :blaze/terminology-service] :opt-un [::extra-bundle-file])) (defmethod ig/init-key :blaze.db/search-param-registry - [_ {:keys [extra-bundle-file]}] + [_ {:keys [terminology-service extra-bundle-file]}] (log/info (cond-> "Init in-memory fixed R4 search parameter registry" extra-bundle-file (str " including extra search parameters from file: " extra-bundle-file))) (let [entries (read-bundle-entries extra-bundle-file) patient-compartment (read-classpath-json-resource "blaze/db/compartment/patient.json")] - (if-ok [url-index (build-url-index entries)] - (let [index (-> (build-index url-index entries) add-special) + (if-ok [url-index (build-url-index terminology-service entries)] + (let [index (->> (build-index url-index entries) (add-special terminology-service)) index-compartment-resources-by-type (index-compartment-resources-by-type patient-compartment)] (->MemSearchParamRegistry url-index diff --git a/modules/db/test-perf/blaze/db/api_test_perf.clj b/modules/db/test-perf/blaze/db/api_test_perf.clj index c6ea6fa10..055bcb1f9 100644 --- a/modules/db/test-perf/blaze/db/api_test_perf.clj +++ b/modules/db/test-perf/blaze/db/api_test_perf.clj @@ -16,6 +16,7 @@ [blaze.fhir.writing-context] [blaze.log] [blaze.module.test-util :refer [with-system]] + [blaze.terminology-service.not-available] [clojure.test :refer [deftest]] [criterium.core :as criterium] [integrant.core :as ig] @@ -84,7 +85,10 @@ :blaze.db.node.resource-indexer/executor {} :blaze.db/search-param-registry - {:structure-definition-repo structure-definition-repo} + {:structure-definition-repo structure-definition-repo + :terminology-service (ig/ref :blaze.terminology-service/not-available)} + + :blaze.terminology-service/not-available {} [:blaze.fhir/parsing-context :blaze.fhir.parsing-context/resource-store] {:structure-definition-repo structure-definition-repo diff --git a/modules/db/test-perf/blaze/db/search_param_registry_test_perf.clj b/modules/db/test-perf/blaze/db/search_param_registry_test_perf.clj index 313cb9201..4ad6ecaeb 100644 --- a/modules/db/test-perf/blaze/db/search_param_registry_test_perf.clj +++ b/modules/db/test-perf/blaze/db/search_param_registry_test_perf.clj @@ -3,15 +3,20 @@ [blaze.db.search-param-registry :as sr] [blaze.fhir.test-util :refer [structure-definition-repo]] [blaze.module.test-util :refer [with-system]] + [blaze.terminology-service :as-alias ts] + [blaze.terminology-service.not-available] [clojure.test :refer [deftest testing]] [criterium.core :as criterium] + [integrant.core :as ig] [taoensso.timbre :as log])) (log/set-min-level! :info) -(def config +(def ^:private config {:blaze.db/search-param-registry - {:structure-definition-repo structure-definition-repo}}) + {:structure-definition-repo structure-definition-repo + :terminology-service (ig/ref ::ts/not-available)} + ::ts/not-available {}}) (deftest linked-compartments-test (with-system [{:blaze.db/keys [search-param-registry]} config] diff --git a/modules/db/test/blaze/db/api_test.clj b/modules/db/test/blaze/db/api_test.clj index dc25bf583..5bf035fc3 100644 --- a/modules/db/test/blaze/db/api_test.clj +++ b/modules/db/test/blaze/db/api_test.clj @@ -27,6 +27,7 @@ [blaze.fhir.spec.type :as type] [blaze.fhir.spec.type.system :as system] [blaze.module.test-util :as mtu :refer [given-failed-future with-system]] + [blaze.terminology-service :as ts] [blaze.test-util :as tu :refer [satisfies-prop]] [clojure.math.combinatorics :as combo] [clojure.spec.alpha :as s] @@ -1761,8 +1762,11 @@ (is (= ~count (count-type-query ~node-or-db ~type ~clauses))))) (defn- pull-compartment-query [node code id type clauses] - (when-ok [handles (d/compartment-query (d/db node) code id type clauses)] - @(d/pull-many node (vec handles)))) + (with-open [db (d/new-batch-db (d/db node))] + (when-ok [query (d/compile-compartment-query db code type clauses) + query (d/optimize-query db query) + handles (d/execute-query db query id)] + @(d/pull-many node (vec handles))))) (defn- pull-system-list ([node-or-db] @@ -4137,7 +4141,7 @@ #fhir/CodeableConcept {:coding [#fhir/Coding - {:system #fhir/uri "http://fhir.de/CodeSystem/dimdi/icd-10-gm" + {:system #fhir/uri "http://fhir.de/CodeSystem/bfarm/icd-10-gm" :code #fhir/code "C71.4"}]} :subject #fhir/Reference{:reference #fhir/string "Patient/id-0"} :onset #fhir/Age{:value #fhir/decimal 63M}}] @@ -8308,6 +8312,115 @@ :scan-clauses := nil [:seek-clauses count] := 0))))))) +(deftest query-condition-code-in-test + (with-system-data [{:blaze.db/keys [node]} config] + [[[:put {:fhir/type :fhir/CodeSystem :id "0" + :url #fhir/uri "http://fhir.de/CodeSystem/bfarm/icd-10-gm" + :content #fhir/code "fragment" + :concept + [{:fhir/type :fhir.CodeSystem/concept + :code #fhir/code "C69-C72"} + {:fhir/type :fhir.CodeSystem/concept + :code #fhir/code "C69" + :property + [{:fhir/type :fhir.CodeSystem.concept/property + :code #fhir/code "parent" + :value #fhir/code "C69-C72"}]} + {:fhir/type :fhir.CodeSystem/concept + :code #fhir/code "C71" + :property + [{:fhir/type :fhir.CodeSystem.concept/property + :code #fhir/code "parent" + :value #fhir/code "C69-C72"}]} + {:fhir/type :fhir.CodeSystem/concept + :code #fhir/code "C69.4" + :property + [{:fhir/type :fhir.CodeSystem.concept/property + :code #fhir/code "parent" + :value #fhir/code "C69"}]} + {:fhir/type :fhir.CodeSystem/concept + :code #fhir/code "C71.4" + :property + [{:fhir/type :fhir.CodeSystem.concept/property + :code #fhir/code "parent" + :value #fhir/code "C71"}]} + {:fhir/type :fhir.CodeSystem/concept + :code #fhir/code "C73-C75"} + {:fhir/type :fhir.CodeSystem/concept + :code #fhir/code "C73" + :property + [{:fhir/type :fhir.CodeSystem.concept/property + :code #fhir/code "parent" + :value #fhir/code "C73-C75"}]}]}]] + [[:put {:fhir/type :fhir/Patient :id "0"}] + [:put {:fhir/type :fhir/Condition :id "0" + :subject #fhir/Reference{:reference #fhir/string "Patient/0"} + :code + #fhir/CodeableConcept + {:coding + [#fhir/Coding + {:system #fhir/uri "http://fhir.de/CodeSystem/bfarm/icd-10-gm" + :code #fhir/code "C71.4"}]}}] + [:put {:fhir/type :fhir/Condition :id "1" + :subject #fhir/Reference{:reference #fhir/string "Patient/0"}}] + [:put {:fhir/type :fhir/Condition :id "2" + :subject #fhir/Reference{:reference #fhir/string "Patient/0"} + :code + #fhir/CodeableConcept + {:coding + [#fhir/Coding + {:system #fhir/uri "http://fhir.de/CodeSystem/bfarm/icd-10-gm" + :code #fhir/code "C69.4"}]}}] + [:put {:fhir/type :fhir/Condition :id "3" + :subject #fhir/Reference{:reference #fhir/string "Patient/0"} + :code + #fhir/CodeableConcept + {:coding + [#fhir/Coding + {:system #fhir/uri "http://fhir.de/CodeSystem/bfarm/icd-10-gm" + :code #fhir/code "C73"}]}}]]] + + (let [clauses [["code:in" "http://fhir.org/VCL?v1=(http://fhir.de/CodeSystem/bfarm/icd-10-gm)concept< date-range-bytes diff --git a/modules/db/test/blaze/db/impl/search_param/has_test.clj b/modules/db/test/blaze/db/impl/search_param/has_test.clj index 8ddb474e1..851c78b56 100644 --- a/modules/db/test/blaze/db/impl/search_param/has_test.clj +++ b/modules/db/test/blaze/db/impl/search_param/has_test.clj @@ -12,9 +12,12 @@ [blaze.fhir.hash-spec] [blaze.fhir.test-util :refer [structure-definition-repo]] [blaze.module.test-util :refer [with-system]] + [blaze.terminology-service :as-alias ts] + [blaze.terminology-service.not-available] [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] + [integrant.core :as ig] [taoensso.timbre :as log])) (st/instrument) @@ -22,9 +25,11 @@ (test/use-fixtures :each tu/fixture) -(def config +(def ^:private config {:blaze.db/search-param-registry - {:structure-definition-repo structure-definition-repo}}) + {:structure-definition-repo structure-definition-repo + :terminology-service (ig/ref ::ts/not-available)} + ::ts/not-available {}}) (deftest estimated-scan-size-test (with-system [{:blaze.db/keys [search-param-registry]} config] @@ -41,9 +46,9 @@ (deftest ordered-compartment-index-handles-test (with-system [{:blaze.db/keys [search-param-registry]} config] (let [search-param (sr/get search-param-registry "_has" "Resource")] - (is (false? (p/-supports-ordered-compartment-index-handles search-param nil))) - (is (ba/unsupported? (p/-ordered-compartment-index-handles search-param nil nil nil nil))) - (is (ba/unsupported? (p/-ordered-compartment-index-handles search-param nil nil nil nil nil)))))) + (is (false? (p/-supports-ordered-compartment-index-handles search-param nil nil))) + (is (ba/unsupported? (p/-ordered-compartment-index-handles search-param nil nil nil nil nil))) + (is (ba/unsupported? (p/-ordered-compartment-index-handles search-param nil nil nil nil nil nil)))))) (deftest validate-modifier-test (with-system [{:blaze.db/keys [search-param-registry]} config] diff --git a/modules/db/test/blaze/db/impl/search_param/list_test.clj b/modules/db/test/blaze/db/impl/search_param/list_test.clj index e5350b875..9d20b0750 100644 --- a/modules/db/test/blaze/db/impl/search_param/list_test.clj +++ b/modules/db/test/blaze/db/impl/search_param/list_test.clj @@ -9,10 +9,13 @@ [blaze.db.search-param-registry-spec] [blaze.fhir.test-util :refer [structure-definition-repo]] [blaze.module.test-util :refer [with-system]] + [blaze.terminology-service :as-alias ts] + [blaze.terminology-service.not-available] [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] [cognitect.anomalies :as anom] + [integrant.core :as ig] [juxt.iota :refer [given]] [taoensso.timbre :as log])) @@ -24,9 +27,11 @@ (defn list-param [search-param-registry] (sr/get search-param-registry "_list" "Patient")) -(def config +(def ^:private config {:blaze.db/search-param-registry - {:structure-definition-repo structure-definition-repo}}) + {:structure-definition-repo structure-definition-repo + :terminology-service (ig/ref ::ts/not-available)} + ::ts/not-available {}}) (deftest list-param-test (with-system [{:blaze.db/keys [search-param-registry]} config] @@ -42,9 +47,9 @@ (deftest ordered-compartment-index-handles-test (with-system [{:blaze.db/keys [search-param-registry]} config] (let [search-param (list-param search-param-registry)] - (is (false? (p/-supports-ordered-compartment-index-handles search-param nil))) - (is (ba/unsupported? (p/-ordered-compartment-index-handles search-param nil nil nil nil))) - (is (ba/unsupported? (p/-ordered-compartment-index-handles search-param nil nil nil nil nil)))))) + (is (false? (p/-supports-ordered-compartment-index-handles search-param nil nil))) + (is (ba/unsupported? (p/-ordered-compartment-index-handles search-param nil nil nil nil nil))) + (is (ba/unsupported? (p/-ordered-compartment-index-handles search-param nil nil nil nil nil nil)))))) (deftest validate-modifier-test (with-system [{:blaze.db/keys [search-param-registry]} config] diff --git a/modules/db/test/blaze/db/impl/search_param/near_test.clj b/modules/db/test/blaze/db/impl/search_param/near_test.clj index 87cf4b0cf..c7f16438a 100644 --- a/modules/db/test/blaze/db/impl/search_param/near_test.clj +++ b/modules/db/test/blaze/db/impl/search_param/near_test.clj @@ -14,6 +14,8 @@ [blaze.fhir.spec.type] [blaze.fhir.test-util :refer [structure-definition-repo]] [blaze.module.test-util :refer [with-system]] + [blaze.terminology-service :as-alias ts] + [blaze.terminology-service.not-available] [blaze.test-util :as tu :refer [satisfies-prop]] [clojure.alpha.spec :as s] [clojure.spec.test.alpha :as st] @@ -21,6 +23,7 @@ [clojure.test.check.generators :as gen] [clojure.test.check.properties :as prop] [cognitect.anomalies :as anom] + [integrant.core :as ig] [juxt.iota :refer [given]] [taoensso.timbre :as log])) @@ -29,9 +32,11 @@ (test/use-fixtures :each tu/fixture) -(def config +(def ^:private config {:blaze.db/search-param-registry - {:structure-definition-repo structure-definition-repo}}) + {:structure-definition-repo structure-definition-repo + :terminology-service (ig/ref ::ts/not-available)} + ::ts/not-available {}}) (defn- near-param [search-param-registry] (sr/get search-param-registry "near" "Location")) @@ -138,9 +143,9 @@ (deftest ordered-compartment-index-handles-test (with-system [{:blaze.db/keys [search-param-registry]} config] (let [search-param (near-param search-param-registry)] - (is (false? (p/-supports-ordered-compartment-index-handles search-param nil))) - (is (ba/unsupported? (p/-ordered-compartment-index-handles search-param nil nil nil nil))) - (is (ba/unsupported? (p/-ordered-compartment-index-handles search-param nil nil nil nil nil)))))) + (is (false? (p/-supports-ordered-compartment-index-handles search-param nil nil))) + (is (ba/unsupported? (p/-ordered-compartment-index-handles search-param nil nil nil nil nil))) + (is (ba/unsupported? (p/-ordered-compartment-index-handles search-param nil nil nil nil nil nil)))))) (defn- index-entries [search-param linked-compartments hash resource] (vec (search-param/index-entries search-param linked-compartments hash resource))) diff --git a/modules/db/test/blaze/db/impl/search_param/number_test.clj b/modules/db/test/blaze/db/impl/search_param/number_test.clj index 71fc3acd9..c96411818 100644 --- a/modules/db/test/blaze/db/impl/search_param/number_test.clj +++ b/modules/db/test/blaze/db/impl/search_param/number_test.clj @@ -18,10 +18,13 @@ [blaze.fhir.hash-spec] [blaze.fhir.test-util :refer [structure-definition-repo]] [blaze.module.test-util :refer [with-system]] + [blaze.terminology-service :as-alias ts] + [blaze.terminology-service.not-available] [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] [cognitect.anomalies :as anom] + [integrant.core :as ig] [juxt.iota :refer [given]] [taoensso.timbre :as log])) @@ -38,9 +41,11 @@ (search-param/compile-values nil [value]) (first))) -(def config +(def ^:private config {:blaze.db/search-param-registry - {:structure-definition-repo structure-definition-repo}}) + {:structure-definition-repo structure-definition-repo + :terminology-service (ig/ref ::ts/not-available)} + ::ts/not-available {}}) (deftest validate-modifier-test (with-system [{:blaze.db/keys [search-param-registry]} config] @@ -116,9 +121,9 @@ (deftest ordered-compartment-index-handles-test (with-system [{:blaze.db/keys [search-param-registry]} config] (let [search-param (probability-param search-param-registry)] - (is (false? (p/-supports-ordered-compartment-index-handles search-param nil))) - (is (ba/unsupported? (p/-ordered-compartment-index-handles search-param nil nil nil nil))) - (is (ba/unsupported? (p/-ordered-compartment-index-handles search-param nil nil nil nil nil)))))) + (is (false? (p/-supports-ordered-compartment-index-handles search-param nil nil))) + (is (ba/unsupported? (p/-ordered-compartment-index-handles search-param nil nil nil nil nil))) + (is (ba/unsupported? (p/-ordered-compartment-index-handles search-param nil nil nil nil nil nil)))))) (defn- index-entries [search-param linked-compartments hash resource] (vec (search-param/index-entries search-param linked-compartments hash resource))) diff --git a/modules/db/test/blaze/db/impl/search_param/quantity_test.clj b/modules/db/test/blaze/db/impl/search_param/quantity_test.clj index 6f12d51d2..d5e80270a 100644 --- a/modules/db/test/blaze/db/impl/search_param/quantity_test.clj +++ b/modules/db/test/blaze/db/impl/search_param/quantity_test.clj @@ -18,10 +18,13 @@ [blaze.fhir.hash-spec] [blaze.fhir.test-util :refer [structure-definition-repo]] [blaze.module.test-util :refer [with-system]] + [blaze.terminology-service :as-alias ts] + [blaze.terminology-service.not-available] [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] [cognitect.anomalies :as anom] + [integrant.core :as ig] [juxt.iota :refer [given]] [taoensso.timbre :as log])) @@ -30,9 +33,11 @@ (test/use-fixtures :each tu/fixture) -(def config +(def ^:private config {:blaze.db/search-param-registry - {:structure-definition-repo structure-definition-repo}}) + {:structure-definition-repo structure-definition-repo + :terminology-service (ig/ref ::ts/not-available)} + ::ts/not-available {}}) (deftest resource-keys-test (testing "non matching op" @@ -174,9 +179,9 @@ (deftest ordered-compartment-index-handles-test (with-system [{:blaze.db/keys [search-param-registry]} config] (let [search-param (value-quantity-param search-param-registry)] - (is (false? (p/-supports-ordered-compartment-index-handles search-param nil))) - (is (ba/unsupported? (p/-ordered-compartment-index-handles search-param nil nil nil nil))) - (is (ba/unsupported? (p/-ordered-compartment-index-handles search-param nil nil nil nil nil)))))) + (is (false? (p/-supports-ordered-compartment-index-handles search-param nil nil))) + (is (ba/unsupported? (p/-ordered-compartment-index-handles search-param nil nil nil nil nil))) + (is (ba/unsupported? (p/-ordered-compartment-index-handles search-param nil nil nil nil nil nil)))))) (defn- index-entries [search-param linked-compartments hash resource] (vec (search-param/index-entries search-param linked-compartments hash resource))) diff --git a/modules/db/test/blaze/db/impl/search_param/string_test.clj b/modules/db/test/blaze/db/impl/search_param/string_test.clj index 00be5e0cf..96e4446a8 100644 --- a/modules/db/test/blaze/db/impl/search_param/string_test.clj +++ b/modules/db/test/blaze/db/impl/search_param/string_test.clj @@ -19,10 +19,13 @@ [blaze.fhir.hash-spec] [blaze.fhir.test-util :refer [structure-definition-repo]] [blaze.module.test-util :refer [with-system]] + [blaze.terminology-service :as-alias ts] + [blaze.terminology-service.not-available] [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] [cognitect.anomalies :as anom] + [integrant.core :as ig] [juxt.iota :refer [given]] [taoensso.timbre :as log])) @@ -34,9 +37,11 @@ (defn phonetic-param [search-param-registry] (sr/get search-param-registry "phonetic" "Patient")) -(def config +(def ^:private config {:blaze.db/search-param-registry - {:structure-definition-repo structure-definition-repo}}) + {:structure-definition-repo structure-definition-repo + :terminology-service (ig/ref ::ts/not-available)} + ::ts/not-available {}}) (deftest phonetic-param-test (with-system [{:blaze.db/keys [search-param-registry]} config] @@ -60,9 +65,9 @@ (deftest ordered-compartment-index-handles-test (with-system [{:blaze.db/keys [search-param-registry]} config] (let [search-param (phonetic-param search-param-registry)] - (is (false? (p/-supports-ordered-compartment-index-handles search-param nil))) - (is (ba/unsupported? (p/-ordered-compartment-index-handles search-param nil nil nil nil))) - (is (ba/unsupported? (p/-ordered-compartment-index-handles search-param nil nil nil nil nil)))))) + (is (false? (p/-supports-ordered-compartment-index-handles search-param nil nil))) + (is (ba/unsupported? (p/-ordered-compartment-index-handles search-param nil nil nil nil nil))) + (is (ba/unsupported? (p/-ordered-compartment-index-handles search-param nil nil nil nil nil nil)))))) (defn- index-entries [search-param linked-compartments hash resource] (vec (search-param/index-entries search-param linked-compartments hash resource))) diff --git a/modules/db/test/blaze/db/impl/search_param/token_test.clj b/modules/db/test/blaze/db/impl/search_param/token_test.clj index 038b755a2..bbb833b57 100644 --- a/modules/db/test/blaze/db/impl/search_param/token_test.clj +++ b/modules/db/test/blaze/db/impl/search_param/token_test.clj @@ -20,10 +20,13 @@ [blaze.fhir.spec.type :as type] [blaze.fhir.test-util :refer [structure-definition-repo]] [blaze.module.test-util :refer [with-system]] + [blaze.terminology-service :as-alias ts] + [blaze.terminology-service.not-available] [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] [cognitect.anomalies :as anom] + [integrant.core :as ig] [juxt.iota :refer [given]] [taoensso.timbre :as log])) @@ -35,9 +38,11 @@ (defn code-param [search-param-registry] (sr/get search-param-registry "code" "Observation")) -(def config +(def ^:private config {:blaze.db/search-param-registry - {:structure-definition-repo structure-definition-repo}}) + {:structure-definition-repo structure-definition-repo + :terminology-service (ig/ref ::ts/not-available)} + ::ts/not-available {}}) (deftest code-param-test (with-system [{:blaze.db/keys [search-param-registry]} config] @@ -56,16 +61,16 @@ (testing "id params" (with-system [{:blaze.db/keys [search-param-registry]} config] (let [search-param (id-param search-param-registry)] - (is (false? (p/-supports-ordered-compartment-index-handles search-param nil))) - (is (ba/unsupported? (p/-ordered-compartment-index-handles search-param nil nil nil nil))) - (is (ba/unsupported? (p/-ordered-compartment-index-handles search-param nil nil nil nil nil)))))) + (is (false? (p/-supports-ordered-compartment-index-handles search-param nil nil))) + (is (ba/unsupported? (p/-ordered-compartment-index-handles search-param nil nil nil nil nil))) + (is (ba/unsupported? (p/-ordered-compartment-index-handles search-param nil nil nil nil nil nil)))))) (testing "identifier params" (with-system [{:blaze.db/keys [search-param-registry]} config] (let [search-param (identifier-param search-param-registry)] - (is (false? (p/-supports-ordered-compartment-index-handles search-param nil))) - (is (ba/unsupported? (p/-ordered-compartment-index-handles search-param nil nil nil nil))) - (is (ba/unsupported? (p/-ordered-compartment-index-handles search-param nil nil nil nil nil))))))) + (is (false? (p/-supports-ordered-compartment-index-handles search-param nil nil))) + (is (ba/unsupported? (p/-ordered-compartment-index-handles search-param nil nil nil nil nil))) + (is (ba/unsupported? (p/-ordered-compartment-index-handles search-param nil nil nil nil nil nil))))))) (defn- index-entries [search-param linked-compartments hash resource] (vec (search-param/index-entries search-param linked-compartments hash resource))) diff --git a/modules/db/test/blaze/db/impl/search_param_spec.clj b/modules/db/test/blaze/db/impl/search_param_spec.clj index 07539ac56..edf4d076f 100644 --- a/modules/db/test/blaze/db/impl/search_param_spec.clj +++ b/modules/db/test/blaze/db/impl/search_param_spec.clj @@ -80,6 +80,7 @@ :batch-db :blaze.db.impl/batch-db :compartment :blaze.db/compartment :tid :blaze.db/tid + :modifier (s/nilable :blaze.db.search-param/modifier) :compiled-values (s/coll-of some? :min-count 1) :start-id (s/? :blaze.db/id-byte-string)) :ret (cs/coll-of ::index/handle)) diff --git a/modules/db/test/blaze/db/impl/search_param_test.clj b/modules/db/test/blaze/db/impl/search_param_test.clj index d1b3f72b4..535387994 100644 --- a/modules/db/test/blaze/db/impl/search_param_test.clj +++ b/modules/db/test/blaze/db/impl/search_param_test.clj @@ -14,10 +14,13 @@ [blaze.fhir.hash-spec] [blaze.fhir.test-util :refer [structure-definition-repo]] [blaze.module.test-util :refer [with-system]] + [blaze.terminology-service :as-alias ts] + [blaze.terminology-service.not-available] [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] [cognitect.anomalies :as anom] + [integrant.core :as ig] [juxt.iota :refer [given]])) (set! *warn-on-reflection* true) @@ -44,9 +47,11 @@ (defn compile-birthdate [search-param-registry value] (first (search-param/compile-values (birthdate search-param-registry) nil [value]))) -(def config +(def ^:private config {:blaze.db/search-param-registry - {:structure-definition-repo structure-definition-repo}}) + {:structure-definition-repo structure-definition-repo + :terminology-service (ig/ref ::ts/not-available)} + ::ts/not-available {}}) (deftest compile-value-test (with-system [{:blaze.db/keys [search-param-registry]} config] diff --git a/modules/db/test/blaze/db/node/resource_indexer_test.clj b/modules/db/test/blaze/db/node/resource_indexer_test.clj index c8ca0ee51..9c7cbf098 100644 --- a/modules/db/test/blaze/db/node/resource_indexer_test.clj +++ b/modules/db/test/blaze/db/node/resource_indexer_test.clj @@ -28,6 +28,8 @@ [blaze.fhir.writing-context] [blaze.metrics.spec] [blaze.module.test-util :refer [given-failed-future given-failed-system with-system]] + [blaze.terminology-service :as-alias ts] + [blaze.terminology-service.not-available] [blaze.test-util :as tu] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] @@ -65,7 +67,10 @@ ::rs-kv/executor {} :blaze.db/search-param-registry - {:structure-definition-repo structure-definition-repo} + {:structure-definition-repo structure-definition-repo + :terminology-service (ig/ref ::ts/not-available)} + + ::ts/not-available {} [:blaze.fhir/parsing-context :blaze.fhir.parsing-context/resource-store] {:structure-definition-repo structure-definition-repo diff --git a/modules/db/test/blaze/db/search_param_registry_test.clj b/modules/db/test/blaze/db/search_param_registry_test.clj index 86f15c9ad..c084da007 100644 --- a/modules/db/test/blaze/db/search_param_registry_test.clj +++ b/modules/db/test/blaze/db/search_param_registry_test.clj @@ -7,6 +7,8 @@ [blaze.fhir-path :as fhir-path] [blaze.fhir.test-util :refer [structure-definition-repo]] [blaze.module.test-util :refer [given-failed-system with-system]] + [blaze.terminology-service :as-alias ts] + [blaze.terminology-service.not-available] [blaze.test-util :as tu] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] @@ -21,14 +23,17 @@ (test/use-fixtures :each tu/fixture) -(def config +(def ^:private config {:blaze.db/search-param-registry - {:structure-definition-repo structure-definition-repo}}) + {:structure-definition-repo structure-definition-repo + :terminology-service (ig/ref ::ts/not-available)} + ::ts/not-available {}}) (def config-extra - {:blaze.db/search-param-registry - {:structure-definition-repo structure-definition-repo - :extra-bundle-file "../../.github/custom-search-parameters-test/custom-search-parameters.json"}}) + (assoc-in + config + [:blaze.db/search-param-registry :extra-bundle-file] + "../../.github/custom-search-parameters-test/custom-search-parameters.json")) (deftest init-test (testing "nil config" @@ -41,7 +46,8 @@ (given-failed-system {:blaze.db/search-param-registry {}} :key := :blaze.db/search-param-registry :reason := ::ig/build-failed-spec - [:cause-data ::s/problems 0 :pred] := `(fn ~'[%] (contains? ~'% :structure-definition-repo)))) + [:cause-data ::s/problems 0 :pred] := `(fn ~'[%] (contains? ~'% :structure-definition-repo)) + [:cause-data ::s/problems 1 :pred] := `(fn ~'[%] (contains? ~'% :terminology-service)))) (testing "invalid structure-definition-repo" (given-failed-system (assoc-in config [:blaze.db/search-param-registry :structure-definition-repo] ::invalid) @@ -69,9 +75,10 @@ :reason := ::ig/build-threw-exception))) (testing "with nil extra bundle file" - (is (->> (ig/init {:blaze.db/search-param-registry - {:structure-definition-repo structure-definition-repo - :extra-bundle-file nil}}) + (is (->> (ig/init (assoc-in + config + [:blaze.db/search-param-registry :extra-bundle-file] + nil)) :blaze.db/search-param-registry (s/valid? :blaze.db/search-param-registry)))) diff --git a/modules/db/test/blaze/db/test_util.clj b/modules/db/test/blaze/db/test_util.clj index 1def847fe..67bfad2a0 100644 --- a/modules/db/test/blaze/db/test_util.clj +++ b/modules/db/test/blaze/db/test_util.clj @@ -15,14 +15,25 @@ [blaze.fhir.test-util :refer [structure-definition-repo]] [blaze.fhir.writing-context] [blaze.module.test-util :refer [with-system]] + [blaze.terminology-service :as-alias ts] + [blaze.terminology-service-spec] + [blaze.terminology-service.local :as ts-local] [integrant.core :as ig] [java-time.api :as time])) -(def ^:private root-system +(def root-system "Root part of the system initialized for performance reasons." (ig/init {:blaze.db/search-param-registry - {:structure-definition-repo structure-definition-repo} + {:structure-definition-repo structure-definition-repo + :terminology-service (ig/ref ::ts/local)} + ::ts/local + {:clock (ig/ref :blaze.test/fixed-clock) + :rng-fn (ig/ref :blaze.test/fixed-rng-fn) + :graph-cache (ig/ref ::ts-local/graph-cache)} + ::ts-local/graph-cache {} + :blaze.test/fixed-clock {} + :blaze.test/fixed-rng-fn {} :blaze.fhir/parsing-context {:structure-definition-repo structure-definition-repo :fail-on-unknown-property false @@ -107,5 +118,6 @@ Additionally the database is initialized with `txs`." [[binding-form config] txs & body] `(with-system [system# ~config] + (ts/post-init! (::ts/local root-system) (:blaze.db/node system#)) (run! #(deref (d/transact (:blaze.db/node system#) %)) ~txs) (let [~binding-form system#] ~@body))) diff --git a/modules/interaction/test/blaze/interaction/conditional_delete_type_test.clj b/modules/interaction/test/blaze/interaction/conditional_delete_type_test.clj index a3b19f8ff..03fa9fe8c 100644 --- a/modules/interaction/test/blaze/interaction/conditional_delete_type_test.clj +++ b/modules/interaction/test/blaze/interaction/conditional_delete_type_test.clj @@ -45,12 +45,13 @@ [:cause-data ::s/problems 0 :via] := [:blaze.db/node] [:cause-data ::s/problems 0 :val] := ::invalid))) -(def config - (assoc api-stub/mem-node-config - :blaze.interaction/conditional-delete-type - {:node (ig/ref :blaze.db/node) - :executor (ig/ref :blaze.test/executor)} - :blaze.test/executor {})) +(def ^:private config + (assoc + api-stub/mem-node-config + :blaze.interaction/conditional-delete-type + {:node (ig/ref :blaze.db/node) + :executor (ig/ref :blaze.test/executor)} + :blaze.test/executor {})) (defmacro with-handler [[handler-binding] & more] (let [[txs body] (api-stub/extract-txs-body more)] diff --git a/modules/interaction/test/blaze/interaction/create_test.clj b/modules/interaction/test/blaze/interaction/create_test.clj index 00de3d6db..1294b0faf 100644 --- a/modules/interaction/test/blaze/interaction/create_test.clj +++ b/modules/interaction/test/blaze/interaction/create_test.clj @@ -8,7 +8,7 @@ [blaze.anomaly :as ba] [blaze.anomaly-spec] [blaze.async.comp :as ac] - [blaze.db.api-stub :as api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.db.resource-store :as rs] [blaze.db.spec] [blaze.fhir.response.create-spec] @@ -43,16 +43,15 @@ {:syntax :bracket :path context-path})) -(def config +(def ^:private config (assoc - mem-node-config + api-stub/mem-node-config :blaze.interaction/create {:node (ig/ref :blaze.db/node) :executor (ig/ref :blaze.test/executor) :clock (ig/ref :blaze.test/fixed-clock) :rng-fn (ig/ref :blaze.test/fixed-rng-fn)} - :blaze.test/executor {} - :blaze.test/fixed-rng-fn {})) + :blaze.test/executor {})) (deftest init-test (testing "nil config" diff --git a/modules/interaction/test/blaze/interaction/delete_history_test.clj b/modules/interaction/test/blaze/interaction/delete_history_test.clj index 40907dd1e..ca9234f23 100644 --- a/modules/interaction/test/blaze/interaction/delete_history_test.clj +++ b/modules/interaction/test/blaze/interaction/delete_history_test.clj @@ -40,10 +40,11 @@ [:cause-data ::s/problems 0 :via] := [:blaze.db/node] [:cause-data ::s/problems 0 :val] := ::invalid))) -(def config - (assoc api-stub/mem-node-config - :blaze.interaction/delete-history - {:node (ig/ref :blaze.db/node)})) +(def ^:private config + (assoc + api-stub/mem-node-config + :blaze.interaction/delete-history + {:node (ig/ref :blaze.db/node)})) (defmacro with-handler [[handler-binding] & more] (let [[txs body] (api-stub/extract-txs-body more)] diff --git a/modules/interaction/test/blaze/interaction/delete_test.clj b/modules/interaction/test/blaze/interaction/delete_test.clj index b34842e01..e0975ad00 100644 --- a/modules/interaction/test/blaze/interaction/delete_test.clj +++ b/modules/interaction/test/blaze/interaction/delete_test.clj @@ -40,10 +40,11 @@ [:cause-data ::s/problems 0 :via] := [:blaze.db/node] [:cause-data ::s/problems 0 :val] := ::invalid))) -(def config - (assoc api-stub/mem-node-config - :blaze.interaction/delete - {:node (ig/ref :blaze.db/node)})) +(def ^:private config + (assoc + api-stub/mem-node-config + :blaze.interaction/delete + {:node (ig/ref :blaze.db/node)})) (defmacro with-handler [[handler-binding] & more] (let [[txs body] (api-stub/extract-txs-body more)] diff --git a/modules/interaction/test/blaze/interaction/history/instance_test.clj b/modules/interaction/test/blaze/interaction/history/instance_test.clj index 23f97e884..7ef9c5440 100644 --- a/modules/interaction/test/blaze/interaction/history/instance_test.clj +++ b/modules/interaction/test/blaze/interaction/history/instance_test.clj @@ -96,7 +96,6 @@ :rng-fn (ig/ref :blaze.test/fixed-rng-fn) :page-id-cipher (ig/ref :blaze.test/page-id-cipher)} ::search-util/link {:fhir/version "4.0.1"} - :blaze.test/fixed-rng-fn {} :blaze.test/page-id-cipher {})) (deftest init-test diff --git a/modules/interaction/test/blaze/interaction/history/system_test.clj b/modules/interaction/test/blaze/interaction/history/system_test.clj index 0ac1509e8..b50efeeda 100644 --- a/modules/interaction/test/blaze/interaction/history/system_test.clj +++ b/modules/interaction/test/blaze/interaction/history/system_test.clj @@ -65,7 +65,7 @@ :name :history-page} :path (str context-path "/__history-page")})) -(def config +(def ^:private config (assoc api-stub/mem-node-config :blaze.interaction.history/system @@ -74,7 +74,6 @@ :rng-fn (ig/ref :blaze.test/fixed-rng-fn) :page-id-cipher (ig/ref :blaze.test/page-id-cipher)} ::search-util/link {:fhir/version "4.0.1"} - :blaze.test/fixed-rng-fn {} :blaze.test/page-id-cipher {})) (deftest init-test diff --git a/modules/interaction/test/blaze/interaction/history/type_test.clj b/modules/interaction/test/blaze/interaction/history/type_test.clj index 5faf03f44..e2d470caa 100644 --- a/modules/interaction/test/blaze/interaction/history/type_test.clj +++ b/modules/interaction/test/blaze/interaction/history/type_test.clj @@ -86,7 +86,7 @@ :name :CodeSystem/history} :path (str context-path "/CodeSystem/_history")})) -(def config +(def ^:private config (assoc api-stub/mem-node-config :blaze.interaction.history/type @@ -96,7 +96,6 @@ :rng-fn (ig/ref :blaze.test/fixed-rng-fn) :page-id-cipher (ig/ref :blaze.test/page-id-cipher)} ::search-util/link {:fhir/version "4.0.1"} - :blaze.test/fixed-rng-fn {} :blaze.test/page-id-cipher {})) (deftest init-test diff --git a/modules/interaction/test/blaze/interaction/read_test.clj b/modules/interaction/test/blaze/interaction/read_test.clj index c5b1462b4..5bbb0c157 100644 --- a/modules/interaction/test/blaze/interaction/read_test.clj +++ b/modules/interaction/test/blaze/interaction/read_test.clj @@ -26,10 +26,10 @@ (test/use-fixtures :each tu/fixture) -(def config +(def ^:private config (assoc api-stub/mem-node-config :blaze.interaction/read {})) -(def match +(def ^:private match (reitit/map->Match {:data {:fhir.resource/type "Patient"}})) (def operation-outcome diff --git a/modules/interaction/test/blaze/interaction/search/include_test.clj b/modules/interaction/test/blaze/interaction/search/include_test.clj index 9162bed7d..96afd6882 100644 --- a/modules/interaction/test/blaze/interaction/search/include_test.clj +++ b/modules/interaction/test/blaze/interaction/search/include_test.clj @@ -1,7 +1,7 @@ (ns blaze.interaction.search.include-test (:require [blaze.db.api :as d] - [blaze.db.api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.interaction.search.include :as include] [blaze.interaction.search.include-spec] [blaze.test-util :as tu] @@ -13,13 +13,13 @@ (test/use-fixtures :each tu/fixture) -(def non-ref-int-config - (assoc-in mem-node-config [:blaze.db/node :enforce-referential-integrity] false)) +(def ^:private non-ref-int-config + (assoc-in api-stub/mem-node-config [:blaze.db/node :enforce-referential-integrity] false)) (deftest add-includes-test (testing "one direct forward include" (testing "enforcing referential integrity" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}] [:put {:fhir/type :fhir/Observation :id "0" :subject #fhir/Reference{:reference #fhir/string "Patient/0"}}]]] @@ -45,7 +45,7 @@ [0 :fhir/type] := :fhir/Patient)))) (testing "with non-matching target type" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}] [:put {:fhir/type :fhir/Observation :id "0" :subject #fhir/Reference{:reference #fhir/string "Patient/0"}}]]] @@ -59,7 +59,7 @@ (is (empty? (include/add-includes db include-defs observations))))))) (testing "two direct forward includes with the same type" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}] [:put {:fhir/type :fhir/Encounter :id "1" :subject #fhir/Reference{:reference #fhir/string "Patient/0"}}] @@ -79,7 +79,7 @@ [1 :fhir/type] := :fhir/Encounter)))) (testing "one direct reverse include" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}] [:put {:fhir/type :fhir/Observation :id "1" :subject #fhir/Reference{:reference #fhir/string "Patient/0"}}]]] @@ -95,7 +95,7 @@ [0 :fhir/type] := :fhir/Observation)))) (testing "direct forward include followed by iterate forward include" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Organization :id "0"}] [:put {:fhir/type :fhir/Patient :id "0" :managingOrganization #fhir/Reference{:reference #fhir/string "Organization/0"}}] @@ -112,7 +112,7 @@ [1 :fhir/type] := :fhir/Patient)))) (testing "direct forward include followed by iterate reverse include" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}] [:put {:fhir/type :fhir/Condition :id "0" :subject #fhir/Reference{:reference #fhir/string "Patient/0"}}] @@ -129,7 +129,7 @@ [1 :fhir/type] := :fhir/Patient)))) (testing "direct reverse include followed by iterate forward include" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}] [:put {:fhir/type :fhir/Condition :id "0" :subject #fhir/Reference{:reference #fhir/string "Patient/0"} @@ -146,7 +146,7 @@ [1 :fhir/type] := :fhir/Encounter)))) (testing "direct reverse include followed by iterate reverse include" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}] [:put {:fhir/type :fhir/Encounter :id "0" :subject #fhir/Reference{:reference #fhir/string "Patient/0"}}] diff --git a/modules/interaction/test/blaze/interaction/search_compartment_test.clj b/modules/interaction/test/blaze/interaction/search_compartment_test.clj index 3db894860..178c40ecb 100644 --- a/modules/interaction/test/blaze/interaction/search_compartment_test.clj +++ b/modules/interaction/test/blaze/interaction/search_compartment_test.clj @@ -63,7 +63,7 @@ :name :Patient/compartment-page} :path (str context-path "/Patient/0/Observation")})) -(def config +(def ^:private config (assoc api-stub/mem-node-config :blaze.interaction/search-compartment @@ -73,7 +73,6 @@ :page-store (ig/ref :blaze.page-store/local) :page-id-cipher (ig/ref :blaze.test/page-id-cipher)} ::search-util/link {:fhir/version "4.0.1"} - :blaze.test/fixed-rng-fn {} :blaze.page-store/local {} :blaze.test/fixed-rng {} :blaze.test/page-id-cipher {})) diff --git a/modules/interaction/test/blaze/interaction/search_system_test.clj b/modules/interaction/test/blaze/interaction/search_system_test.clj index 791635dcd..6c171dad2 100644 --- a/modules/interaction/test/blaze/interaction/search_system_test.clj +++ b/modules/interaction/test/blaze/interaction/search_system_test.clj @@ -59,7 +59,7 @@ :blaze/base-url ""} :path ""})) -(def config +(def ^:private config (assoc api-stub/mem-node-config :blaze.interaction/search-system @@ -70,7 +70,6 @@ :page-store (ig/ref :blaze.page-store/local) :page-id-cipher (ig/ref :blaze.test/page-id-cipher)} ::search-util/link {:fhir/version "4.0.1"} - :blaze.test/fixed-rng-fn {} :blaze.page-store/local {} :blaze.test/fixed-rng {} :blaze.test/page-id-cipher {})) diff --git a/modules/interaction/test/blaze/interaction/search_type_test.clj b/modules/interaction/test/blaze/interaction/search_type_test.clj index eb0b66bae..466f81b7f 100644 --- a/modules/interaction/test/blaze/interaction/search_type_test.clj +++ b/modules/interaction/test/blaze/interaction/search_type_test.clj @@ -99,7 +99,7 @@ (def patient-page-match (page-match-of "Patient")) -(def config +(def ^:private config (assoc api-stub/mem-node-config :blaze.interaction/search-type @@ -117,7 +117,6 @@ ::search-util/link {:fhir/version "4.0.1"} :blaze.page-store/local {} - :blaze.test/fixed-rng-fn {} :blaze.test/fixed-rng {} :blaze.test/page-id-cipher {})) @@ -2269,7 +2268,7 @@ #fhir/CodeableConcept {:coding [#fhir/Coding - {:system #fhir/uri "http://fhir.de/CodeSystem/dimdi/icd-10-gm" + {:system #fhir/uri "http://fhir.de/CodeSystem/bfarm/icd-10-gm" :code #fhir/code "C71.4"}]}}]]] (doseq [handling ["strict" "lenient"]] diff --git a/modules/interaction/test/blaze/interaction/transaction/bundle_test.clj b/modules/interaction/test/blaze/interaction/transaction/bundle_test.clj index 40f4158fa..56e580f4b 100644 --- a/modules/interaction/test/blaze/interaction/transaction/bundle_test.clj +++ b/modules/interaction/test/blaze/interaction/transaction/bundle_test.clj @@ -1,7 +1,7 @@ (ns blaze.interaction.transaction.bundle-test (:require [blaze.db.api :as d] - [blaze.db.api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.fhir.spec.type :as type] [blaze.interaction.transaction.bundle :as bundle] [blaze.interaction.transaction.bundle-spec] @@ -17,7 +17,7 @@ (test/use-fixtures :each tu/fixture) (deftest tx-ops-test - (with-system [{:blaze.db/keys [node]} mem-node-config] + (with-system [{:blaze.db/keys [node]} api-stub/mem-node-config] (testing "create" (given (bundle/assoc-tx-ops (d/db node) @@ -169,7 +169,7 @@ count := 1 [0 :tx-op] := [:conditional-delete "Patient" [["name-170043" "value-170047"]]])))) - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:create {:fhir/type :fhir/Patient :id "0" :gender #fhir/code "female"}]] [[:put {:fhir/type :fhir/Patient :id "0" :gender #fhir/code "male"}]]] diff --git a/modules/interaction/test/blaze/interaction/transaction_test.clj b/modules/interaction/test/blaze/interaction/transaction_test.clj index 850b81b39..c7dcf1319 100644 --- a/modules/interaction/test/blaze/interaction/transaction_test.clj +++ b/modules/interaction/test/blaze/interaction/transaction_test.clj @@ -118,7 +118,7 @@ (derive ::batch-router ::router) -(def config +(def ^:private config (assoc api-stub/mem-node-config :blaze.interaction/transaction @@ -180,7 +180,6 @@ :rng-fn (ig/ref :blaze.test/fixed-rng-fn)} ::search-util/link {:fhir/version "4.0.1"} - :blaze.test/fixed-rng-fn {} :blaze.page-store/local {} :blaze.test/fixed-rng {} :blaze.test/page-id-cipher {})) diff --git a/modules/interaction/test/blaze/interaction/update_test.clj b/modules/interaction/test/blaze/interaction/update_test.clj index c4828247d..ff93f7246 100644 --- a/modules/interaction/test/blaze/interaction/update_test.clj +++ b/modules/interaction/test/blaze/interaction/update_test.clj @@ -73,12 +73,13 @@ [:cause-data ::s/problems 0 :via] := [:blaze.db/node] [:cause-data ::s/problems 0 :val] := ::invalid))) -(def config - (assoc api-stub/mem-node-config - :blaze.interaction/update - {:node (ig/ref :blaze.db/node) - :executor (ig/ref :blaze.test/executor)} - :blaze.test/executor {})) +(def ^:private config + (assoc + api-stub/mem-node-config + :blaze.interaction/update + {:node (ig/ref :blaze.db/node) + :executor (ig/ref :blaze.test/executor)} + :blaze.test/executor {})) (def disabled-referential-integrity-check-config (assoc-in config [:blaze.db/node :enforce-referential-integrity] false)) diff --git a/modules/interaction/test/blaze/interaction/util_test.clj b/modules/interaction/test/blaze/interaction/util_test.clj index dda7fff24..ed483999b 100644 --- a/modules/interaction/test/blaze/interaction/util_test.clj +++ b/modules/interaction/test/blaze/interaction/util_test.clj @@ -1,7 +1,7 @@ (ns blaze.interaction.util-test (:require [blaze.db.api :as d] - [blaze.db.api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.db.tx-log.spec] [blaze.fhir.hash :as hash] [blaze.interaction.util :as iu] @@ -32,7 +32,7 @@ (deftest put-tx-op-test (testing "on empty database" - (with-system [{:blaze.db/keys [node]} mem-node-config] + (with-system [{:blaze.db/keys [node]} api-stub/mem-node-config] (testing "with empty if-match header" (given (iu/update-tx-op (d/db node) {:fhir/type :fhir/Patient :id "0"} "" nil) ::anom/category := ::anom/conflict @@ -60,7 +60,7 @@ (testing "with an existing, identical patient; the other patient is there in order to show that the t depends only on the matching patient" (let [male-patient {:fhir/type :fhir/Patient :id "0" :gender #fhir/code "male"} hash (hash/generate male-patient)] - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0" :gender #fhir/code "female"}]] [[:put male-patient]] [[:put {:fhir/type :fhir/Patient :id "1"}]]] diff --git a/modules/interaction/test/blaze/interaction/vread_test.clj b/modules/interaction/test/blaze/interaction/vread_test.clj index 40ecfda23..6c7ae1c3f 100644 --- a/modules/interaction/test/blaze/interaction/vread_test.clj +++ b/modules/interaction/test/blaze/interaction/vread_test.clj @@ -24,16 +24,13 @@ (test/use-fixtures :each tu/fixture) -(def config +(def ^:private config (assoc api-stub/mem-node-config :blaze.interaction/vread {})) -(def match +(def ^:private match (reitit/map->Match {:data {:fhir.resource/type "Patient"}})) -(def operation-outcome - #fhir/uri "http://terminology.hl7.org/CodeSystem/operation-outcome") - -(defn wrap-defaults [handler] +(defn- wrap-defaults [handler] (fn [request] (handler (assoc request ::reitit/match match)))) diff --git a/modules/job-async-interaction/test/blaze/job/async_interaction/request_test.clj b/modules/job-async-interaction/test/blaze/job/async_interaction/request_test.clj index acbe9f972..5c964d53c 100644 --- a/modules/job-async-interaction/test/blaze/job/async_interaction/request_test.clj +++ b/modules/job-async-interaction/test/blaze/job/async_interaction/request_test.clj @@ -2,7 +2,7 @@ (:require [blaze.async.comp :as ac] [blaze.db.api :as d] - [blaze.db.api-stub :refer [mem-node-config]] + [blaze.db.api-stub :as api-stub] [blaze.fhir.test-util] [blaze.job.async-interaction.request :as req] [blaze.job.async-interaction.request-spec] @@ -23,7 +23,7 @@ (def ^:private config (assoc - mem-node-config + api-stub/mem-node-config :blaze/job-scheduler {:node (ig/ref :blaze.db/node) :clock (ig/ref :blaze.test/fixed-clock) diff --git a/modules/job-async-interaction/test/blaze/job/async_interaction/util_test.clj b/modules/job-async-interaction/test/blaze/job/async_interaction/util_test.clj index f32005fec..12e431a76 100644 --- a/modules/job-async-interaction/test/blaze/job/async_interaction/util_test.clj +++ b/modules/job-async-interaction/test/blaze/job/async_interaction/util_test.clj @@ -1,7 +1,7 @@ (ns blaze.job.async-interaction.util-test (:require [blaze.db.api-spec] - [blaze.db.api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.db.kv.mem] [blaze.db.search-param-registry] [blaze.db.search-param-registry-spec] @@ -35,13 +35,13 @@ (deftest pull-request-bundle-test (testing "missing request bundle reference" - (with-system [{:blaze.db/keys [node]} mem-node-config] + (with-system [{:blaze.db/keys [node]} api-stub/mem-node-config] (given-failed-future (u/pull-request-bundle node {:fhir/type :fhir/Task}) ::anom/category := ::anom/incorrect ::anom/message := "Missing request bundle reference."))) (testing "invalid request bundle reference" - (with-system [{:blaze.db/keys [node]} mem-node-config] + (with-system [{:blaze.db/keys [node]} api-stub/mem-node-config] (given-failed-future (u/pull-request-bundle node @@ -51,7 +51,7 @@ ::anom/message := "Invalid request bundle reference `invalid-173750`."))) (testing "request bundle not found" - (with-system [{:blaze.db/keys [node]} mem-node-config] + (with-system [{:blaze.db/keys [node]} api-stub/mem-node-config] (given-failed-future (u/pull-request-bundle node @@ -62,7 +62,7 @@ ::anom/message := "Can't find the request bundle with id `175805` of job with id `175832`."))) (testing "request bundle deleted" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:create {:fhir/type :fhir/Bundle :id "180302"}]] [[:delete "Bundle" "180302"]]] @@ -76,7 +76,7 @@ ::anom/message := "The request bundle with id `180302` of job with id `180340` was deleted."))) (testing "success" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:create {:fhir/type :fhir/Bundle :id "180302"}]]] (let [task {:fhir/type :fhir/Task :id "180340" diff --git a/modules/job-async-interaction/test/blaze/job/async_interaction_test.clj b/modules/job-async-interaction/test/blaze/job/async_interaction_test.clj index ad7021630..d2e933aa1 100644 --- a/modules/job-async-interaction/test/blaze/job/async_interaction_test.clj +++ b/modules/job-async-interaction/test/blaze/job/async_interaction_test.clj @@ -25,6 +25,8 @@ [blaze.job.util :as job-util] [blaze.luid :as luid] [blaze.module.test-util :refer [given-failed-system with-system]] + [blaze.terminology-service :as-alias ts] + [blaze.terminology-service.not-available] [blaze.test-util :as tu] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] @@ -175,7 +177,10 @@ ::rs-kv/executor {} :blaze.db/search-param-registry - {:structure-definition-repo structure-definition-repo} + {:structure-definition-repo structure-definition-repo + :terminology-service (ig/ref ::ts/not-available)} + + ::ts/not-available {} [:blaze.fhir/parsing-context :blaze.fhir.parsing-context/resource-store] {:structure-definition-repo structure-definition-repo diff --git a/modules/job-compact/test/blaze/job/compact_test.clj b/modules/job-compact/test/blaze/job/compact_test.clj index 4944a9e04..e021890e5 100644 --- a/modules/job-compact/test/blaze/job/compact_test.clj +++ b/modules/job-compact/test/blaze/job/compact_test.clj @@ -21,6 +21,8 @@ [blaze.job.test-util :as jtu] [blaze.job.util :as job-util] [blaze.module.test-util :refer [given-failed-system with-system]] + [blaze.terminology-service :as-alias ts] + [blaze.terminology-service.not-available] [blaze.test-util :as tu] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] @@ -127,7 +129,10 @@ ::rs-kv/executor {} :blaze.db/search-param-registry - {:structure-definition-repo structure-definition-repo} + {:structure-definition-repo structure-definition-repo + :terminology-service (ig/ref ::ts/not-available)} + + ::ts/not-available {} [:blaze.fhir/parsing-context :blaze.fhir.parsing-context/resource-store] {:structure-definition-repo structure-definition-repo diff --git a/modules/job-re-index/test/blaze/job/re_index_test.clj b/modules/job-re-index/test/blaze/job/re_index_test.clj index 6727178a6..792a08da8 100644 --- a/modules/job-re-index/test/blaze/job/re_index_test.clj +++ b/modules/job-re-index/test/blaze/job/re_index_test.clj @@ -25,6 +25,8 @@ [blaze.luid :as luid] [blaze.module.test-util :refer [given-failed-system with-system]] [blaze.spec] + [blaze.terminology-service :as-alias ts] + [blaze.terminology-service.not-available] [blaze.test-util :as tu] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] @@ -170,7 +172,10 @@ ::rs-kv/executor {} :blaze.db/search-param-registry - {:structure-definition-repo structure-definition-repo} + {:structure-definition-repo structure-definition-repo + :terminology-service (ig/ref ::ts/not-available)} + + ::ts/not-available {} [:blaze.fhir/parsing-context :blaze.fhir.parsing-context/resource-store] {:structure-definition-repo structure-definition-repo diff --git a/modules/job-scheduler/test/blaze/job_scheduler_test.clj b/modules/job-scheduler/test/blaze/job_scheduler_test.clj index 361723330..5ebe18770 100644 --- a/modules/job-scheduler/test/blaze/job_scheduler_test.clj +++ b/modules/job-scheduler/test/blaze/job_scheduler_test.clj @@ -26,6 +26,8 @@ [blaze.job.util :as job-util] [blaze.module.test-util :as mtu :refer [given-failed-future given-failed-system with-system]] [blaze.spec] + [blaze.terminology-service :as-alias ts] + [blaze.terminology-service.not-available] [blaze.test-util :as tu] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] @@ -235,7 +237,10 @@ ::rs-kv/executor {} :blaze.db/search-param-registry - {:structure-definition-repo structure-definition-repo} + {:structure-definition-repo structure-definition-repo + :terminology-service (ig/ref ::ts/not-available)} + + ::ts/not-available {} [:blaze.fhir/parsing-context :blaze.fhir.parsing-context/resource-store] {:structure-definition-repo structure-definition-repo diff --git a/modules/job-util/test/blaze/job/util_test.clj b/modules/job-util/test/blaze/job/util_test.clj index ecc7d8f72..fa95ce22c 100644 --- a/modules/job-util/test/blaze/job/util_test.clj +++ b/modules/job-util/test/blaze/job/util_test.clj @@ -2,7 +2,7 @@ (:require [blaze.anomaly :as ba] [blaze.db.api :as d] - [blaze.db.api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.fhir.spec.type :as type] [blaze.job.util :as job-util] [blaze.job.util-spec] @@ -134,7 +134,7 @@ (assoc job :status #fhir/code "in-progress")) (deftest pull-job-test - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Task :id "0"}]]] (given @(mtu/assoc-thread-name (job-util/pull-job node "0")) @@ -143,7 +143,7 @@ :id := "0"))) (deftest update-job-test - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Task :id "0"}]]] (let [job @(job-util/pull-job node "0")] @@ -160,7 +160,7 @@ job-util/error-msg := "msg-181135")))))) (testing "lost updates are detected" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Task :id "0"}]]] (let [job @(job-util/pull-job node "0")] @@ -184,7 +184,7 @@ (deftest update-job-plus-test (testing "without other resources" (testing "with no argument" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Task :id "0"}]]] (let [job @(job-util/pull-job node "0")] @@ -194,7 +194,7 @@ :status := #fhir/code "in-progress")))) (testing "with one argument" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Task :id "0"}]]] (let [job @(job-util/pull-job node "0")] @@ -204,7 +204,7 @@ job-util/error-msg := "msg-162452")))) (testing "with two arguments" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Task :id "0"}]]] (let [job @(job-util/pull-job node "0")] @@ -213,7 +213,7 @@ :status := #fhir/code "on-hold"))))) (testing "with one Bundle" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Task :id "0"}]]] (let [job @(job-util/pull-job node "0")] diff --git a/modules/operation-code-system-validate-code/test/blaze/fhir/operation/code_system/validate_code_test.clj b/modules/operation-code-system-validate-code/test/blaze/fhir/operation/code_system/validate_code_test.clj index dc2e8ab41..c3a1122c7 100644 --- a/modules/operation-code-system-validate-code/test/blaze/fhir/operation/code_system/validate_code_test.clj +++ b/modules/operation-code-system-validate-code/test/blaze/fhir/operation/code_system/validate_code_test.clj @@ -10,7 +10,6 @@ [blaze.middleware.fhir.db-spec] [blaze.module.test-util :refer [given-failed-system]] [blaze.terminology-service :as ts] - [blaze.terminology-service.local :as ts-local] [blaze.test-util :as tu] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] @@ -44,18 +43,11 @@ [:cause-data ::s/problems 0 :via] := [:blaze/terminology-service] [:cause-data ::s/problems 0 :val] := ::invalid))) -(def config +(def ^:private config (assoc api-stub/mem-node-config :blaze.fhir.operation.code-system/validate-code - {:terminology-service (ig/ref ::ts/local)} - ::ts/local - {:node (ig/ref :blaze.db/node) - :clock (ig/ref :blaze.test/fixed-clock) - :rng-fn (ig/ref :blaze.test/fixed-rng-fn) - :graph-cache (ig/ref ::ts-local/graph-cache)} - :blaze.test/fixed-rng-fn {} - ::ts-local/graph-cache {})) + {:terminology-service (ig/ref ::ts/local)})) (defn wrap-error [handler] (fn [request] diff --git a/modules/operation-compact/test/blaze/fhir/operation/compact_test.clj b/modules/operation-compact/test/blaze/fhir/operation/compact_test.clj index 9faf4e2b3..bb869bcef 100644 --- a/modules/operation-compact/test/blaze/fhir/operation/compact_test.clj +++ b/modules/operation-compact/test/blaze/fhir/operation/compact_test.clj @@ -50,8 +50,7 @@ :blaze/job-scheduler {:node (ig/ref :blaze.db/node) :clock (ig/ref :blaze.test/fixed-clock) - :rng-fn (ig/ref :blaze.test/fixed-rng-fn)} - :blaze.test/fixed-rng-fn {})) + :rng-fn (ig/ref :blaze.test/fixed-rng-fn)})) (defn- wrap-defaults [handler] (fn [request] diff --git a/modules/operation-cql/test/blaze/fhir/operation/cql_test.clj b/modules/operation-cql/test/blaze/fhir/operation/cql_test.clj index 701e2eddb..b37733321 100644 --- a/modules/operation-cql/test/blaze/fhir/operation/cql_test.clj +++ b/modules/operation-cql/test/blaze/fhir/operation/cql_test.clj @@ -16,7 +16,6 @@ [blaze.module.test-util :refer [given-failed-system with-system]] [blaze.terminology-service :as-alias ts] [blaze.terminology-service-spec] - [blaze.terminology-service.local :as ts-local] [blaze.test-util :as tu] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] @@ -48,14 +47,7 @@ ::expr/cache {:node (ig/ref :blaze.db/node) :executor (ig/ref :blaze.test/executor)} - ::ts/local - {:node (ig/ref :blaze.db/node) - :clock (ig/ref :blaze.test/fixed-clock) - :rng-fn (ig/ref :blaze.test/fixed-rng-fn) - :graph-cache (ig/ref ::ts-local/graph-cache)} - :blaze.test/executor {} - :blaze.test/fixed-rng-fn {} - ::ts-local/graph-cache {})) + :blaze.test/executor {})) (deftest init-test (testing "nil config" diff --git a/modules/operation-graph/test/blaze/operation/graph_test.clj b/modules/operation-graph/test/blaze/operation/graph_test.clj index 8318356d2..68c3e3a34 100644 --- a/modules/operation-graph/test/blaze/operation/graph_test.clj +++ b/modules/operation-graph/test/blaze/operation/graph_test.clj @@ -31,7 +31,7 @@ (test/use-fixtures :each tu/fixture) -(def config +(def ^:private config (assoc api-stub/mem-node-config :blaze.operation/graph @@ -40,7 +40,6 @@ :rng-fn (ig/ref :blaze.test/fixed-rng-fn) :page-id-cipher (ig/ref :blaze.test/page-id-cipher)} ::graph/compiled-graph-cache {} - :blaze.test/fixed-rng-fn {} :blaze.test/page-id-cipher {})) (deftest init-test diff --git a/modules/operation-graphql/test/blaze/fhir/operation/graphql_test.clj b/modules/operation-graphql/test/blaze/fhir/operation/graphql_test.clj index ff710fa10..33ef79a3c 100644 --- a/modules/operation-graphql/test/blaze/fhir/operation/graphql_test.clj +++ b/modules/operation-graphql/test/blaze/fhir/operation/graphql_test.clj @@ -25,7 +25,7 @@ (test/use-fixtures :each tu/fixture) -(def config +(def ^:private config (assoc api-stub/mem-node-config ::graphql/handler diff --git a/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/cql_test.clj b/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/cql_test.clj index 4ddba2c75..9e3901661 100644 --- a/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/cql_test.clj +++ b/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/cql_test.clj @@ -4,7 +4,7 @@ [blaze.anomaly-spec] [blaze.cql.translator :as cql-translator] [blaze.db.api :as d] - [blaze.db.api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.elm.compiler.library :as library] [blaze.elm.compiler.library-spec] [blaze.elm.expression :as expr] @@ -14,7 +14,6 @@ [blaze.module.test-util :refer [given-failed-future with-system]] [blaze.terminology-service :as-alias ts] [blaze.terminology-service-spec] - [blaze.terminology-service.local :as ts-local] [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] @@ -104,18 +103,11 @@ (def ^:private config (assoc - mem-node-config + api-stub/mem-node-config ::expr/cache {:node (ig/ref :blaze.db/node) :executor (ig/ref :blaze.test/executor)} - ::ts/local - {:node (ig/ref :blaze.db/node) - :clock (ig/ref :blaze.test/fixed-clock) - :rng-fn (ig/ref :blaze.test/fixed-rng-fn) - :graph-cache (ig/ref ::ts-local/graph-cache)} - :blaze.test/executor {} - :blaze.test/fixed-rng-fn {} - ::ts-local/graph-cache {})) + :blaze.test/executor {})) (def ^:private conj-reduce-op (fn [_db] conj)) diff --git a/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/measure/stratifier_test.clj b/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/measure/stratifier_test.clj index e23284553..1d6c94915 100644 --- a/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/measure/stratifier_test.clj +++ b/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/measure/stratifier_test.clj @@ -4,7 +4,7 @@ [blaze.anomaly-spec] [blaze.cql.translator :as cql-translator] [blaze.db.api :as d] - [blaze.db.api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.elm.compiler.library :as library] [blaze.elm.compiler.library-spec] [blaze.fhir.operation.evaluate-measure.measure.stratifier :as strat] @@ -14,12 +14,10 @@ [blaze.module.test-util :refer [with-system]] [blaze.terminology-service :as-alias ts] [blaze.terminology-service-spec] - [blaze.terminology-service.local :as ts-local] [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] [cognitect.anomalies :as anom] - [integrant.core :as ig] [java-time.api :as time] [juxt.iota :refer [given]])) @@ -166,16 +164,7 @@ (assoc :function-defs function-defs)))) (def ^:private config - (assoc - mem-node-config - ::ts/local - {:node (ig/ref :blaze.db/node) - :clock (ig/ref :blaze.test/fixed-clock) - :rng-fn (ig/ref :blaze.test/fixed-rng-fn) - :graph-cache (ig/ref ::ts-local/graph-cache)} - :blaze.test/executor {} - :blaze.test/fixed-rng-fn {} - ::ts-local/graph-cache {})) + (assoc api-stub/mem-node-config :blaze.test/executor {})) (deftest reduce-op-test (testing "one component" diff --git a/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/measure_test.clj b/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/measure_test.clj index d816fb191..f63018ddf 100644 --- a/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/measure_test.clj +++ b/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/measure_test.clj @@ -2,7 +2,7 @@ (:require [blaze.anomaly :as ba :refer [when-ok]] [blaze.db.api :as d] - [blaze.db.api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.elm.expression :as-alias expr] [blaze.elm.expression.cache :as ec] [blaze.elm.expression.cache.bloom-filter :as-alias bloom-filter] @@ -19,7 +19,6 @@ [blaze.module.test-util :refer [given-failed-future]] [blaze.terminology-service :as-alias ts] [blaze.terminology-service-spec] - [blaze.terminology-service.local :as ts-local] [blaze.test-util :as tu] [clojure.java.io :as io] [clojure.spec.alpha :as s] @@ -87,18 +86,12 @@ (update bundle :entry conj library))) (def ^:private config - (assoc mem-node-config - ::expr/cache - {:node (ig/ref :blaze.db/node) - :executor (ig/ref :blaze.test/executor)} - ::ts/local - {:node (ig/ref :blaze.db/node) - :clock (ig/ref :blaze.test/fixed-clock) - :rng-fn (ig/ref :blaze.test/fixed-rng-fn) - :graph-cache (ig/ref ::ts-local/graph-cache)} - :blaze.test/fixed-rng-fn {} - :blaze.test/executor {} - ::ts-local/graph-cache {})) + (assoc + api-stub/mem-node-config + ::expr/cache + {:node (ig/ref :blaze.db/node) + :executor (ig/ref :blaze.test/executor)} + :blaze.test/executor {})) (defn- evaluate ([name] @@ -980,6 +973,8 @@ (testing-query "q65-in-code-system-gender" 2) + (testing-query "q66-icd10-value-set" 2) + (let [result (evaluate "q1" "subject-list")] (testing "MeasureReport is valid" (is (s/valid? :fhir/Resource (:resource result)))) @@ -1247,4 +1242,4 @@ (comment (log/set-min-level! :debug) - (evaluate "q65-in-code-system-gender")) + (evaluate "q66-icd10-value-set")) diff --git a/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q66-icd10-value-set.cql b/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q66-icd10-value-set.cql new file mode 100644 index 000000000..76ace17e8 --- /dev/null +++ b/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q66-icd10-value-set.cql @@ -0,0 +1,10 @@ +library "q66-icd10-value-set" +using FHIR version '4.0.0' +include FHIRHelpers version '4.0.0' + +valueset icd10_e10: 'http://fhir.org/VCL?v1=(http://fhir.de/CodeSystem/bfarm/icd-10-gm)concept< (handler request) (ac/exceptionally handler-util/error-response)))) diff --git a/modules/page-id-cipher/test/blaze/page_id_cipher_test.clj b/modules/page-id-cipher/test/blaze/page_id_cipher_test.clj index 43ec77fd0..8f8ac0679 100644 --- a/modules/page-id-cipher/test/blaze/page_id_cipher_test.clj +++ b/modules/page-id-cipher/test/blaze/page_id_cipher_test.clj @@ -19,6 +19,8 @@ [blaze.page-id-cipher] [blaze.page-id-cipher.spec] [blaze.scheduler.spec] + [blaze.terminology-service :as-alias ts] + [blaze.terminology-service.not-available] [blaze.test-util :as tu] [clojure.datafy :as datafy] [clojure.spec.alpha :as s] @@ -110,7 +112,10 @@ ::rs-kv/executor {} :blaze.db/search-param-registry - {:structure-definition-repo structure-definition-repo} + {:structure-definition-repo structure-definition-repo + :terminology-service (ig/ref ::ts/not-available)} + + ::ts/not-available {} [:blaze.fhir/parsing-context :blaze.fhir.parsing-context/resource-store] {:structure-definition-repo structure-definition-repo diff --git a/modules/rest-api/test/blaze/rest_api/async_status_cancel_handler_test.clj b/modules/rest-api/test/blaze/rest_api/async_status_cancel_handler_test.clj index 6e43d4d9c..74925b9b3 100644 --- a/modules/rest-api/test/blaze/rest_api/async_status_cancel_handler_test.clj +++ b/modules/rest-api/test/blaze/rest_api/async_status_cancel_handler_test.clj @@ -66,8 +66,7 @@ ::rest-api/async-status-cancel-handler {:job-scheduler (ig/ref :blaze/job-scheduler)} - :blaze.job/no-op {} - :blaze.test/fixed-rng-fn {})) + :blaze.job/no-op {})) (defn wrap-error [handler] (fn [request] diff --git a/modules/rest-api/test/blaze/rest_api/capabilities_handler_test.clj b/modules/rest-api/test/blaze/rest_api/capabilities_handler_test.clj index e3d0f0149..7ed22ec33 100644 --- a/modules/rest-api/test/blaze/rest_api/capabilities_handler_test.clj +++ b/modules/rest-api/test/blaze/rest_api/capabilities_handler_test.clj @@ -1,7 +1,7 @@ (ns blaze.rest-api.capabilities-handler-test (:require [blaze.db.api :as d] - [blaze.db.api-stub :as api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.db.impl.search-param] [blaze.fhir.parsing-context] [blaze.fhir.spec :as fhir-spec] @@ -17,7 +17,6 @@ [blaze.rest-api.spec] [blaze.spec] [blaze.terminology-service :as-alias ts] - [blaze.terminology-service.local :as ts-local] [blaze.test-util :as tu :refer [satisfies-prop]] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] @@ -38,7 +37,7 @@ (def ^:private minimal-config (assoc - mem-node-config + api-stub/mem-node-config ::rest-api/capabilities-handler {:version "version-131640" :release-date (system/parse-date-time "2024-01-07") @@ -503,18 +502,10 @@ [:rest 0 :operation 0 :documentation] := #fhir/markdown "documentation-141700"))) (def ^:private terminology-service-config - (-> minimal-config - (assoc-in - [::rest-api/capabilities-handler :terminology-service] - (ig/ref ::ts/local)) - (assoc - ::ts/local - {:node (ig/ref :blaze.db/node) - :clock (ig/ref :blaze.test/fixed-clock) - :rng-fn (ig/ref :blaze.test/fixed-rng-fn) - :graph-cache (ig/ref ::ts-local/graph-cache)} - :blaze.test/fixed-rng-fn {} - ::ts-local/graph-cache {}))) + (assoc-in + minimal-config + [::rest-api/capabilities-handler :terminology-service] + (ig/ref ::ts/local))) (deftest terminology-test (testing "with no code system" diff --git a/modules/rest-api/test/blaze/rest_api/routes_test.clj b/modules/rest-api/test/blaze/rest_api/routes_test.clj index 301f4047e..eb29e960c 100644 --- a/modules/rest-api/test/blaze/rest_api/routes_test.clj +++ b/modules/rest-api/test/blaze/rest_api/routes_test.clj @@ -1,6 +1,6 @@ (ns blaze.rest-api.routes-test (:require - [blaze.db.api-stub :refer [mem-node-config]] + [blaze.db.api-stub :as api-stub] [blaze.db.impl.search-param] [blaze.fhir.parsing-context] [blaze.fhir.test-util :refer [structure-definition-repo]] @@ -83,12 +83,11 @@ (def ^:private system-config (assoc - mem-node-config + api-stub/mem-node-config :blaze/job-scheduler {:node (ig/ref :blaze.db/node) :clock (ig/ref :blaze.test/fixed-clock) :rng-fn (ig/ref :blaze.test/fixed-rng-fn)} - :blaze.test/fixed-rng-fn {} [:blaze.fhir/parsing-context :blaze.fhir.parsing-context/default] {:structure-definition-repo structure-definition-repo} :blaze.fhir/writing-context diff --git a/modules/rest-api/test/blaze/rest_api/structure_definitions_test.clj b/modules/rest-api/test/blaze/rest_api/structure_definitions_test.clj index a576e8fe5..502810543 100644 --- a/modules/rest-api/test/blaze/rest_api/structure_definitions_test.clj +++ b/modules/rest-api/test/blaze/rest_api/structure_definitions_test.clj @@ -1,7 +1,7 @@ (ns blaze.rest-api.structure-definitions-test (:require [blaze.db.api :as d] - [blaze.db.api-stub :refer [mem-node-config]] + [blaze.db.api-stub :as api-stub] [blaze.fhir.parsing-context] [blaze.fhir.test-util :refer [structure-definition-repo]] [blaze.module-spec] @@ -17,9 +17,9 @@ (test/use-fixtures :each tu/fixture) -(def config +(def ^:private config (assoc - mem-node-config + api-stub/mem-node-config [:blaze.fhir/parsing-context :blaze.fhir.parsing-context/default] {:structure-definition-repo structure-definition-repo} :blaze.test/fixed-clock {} diff --git a/modules/rest-api/test/blaze/rest_api_test.clj b/modules/rest-api/test/blaze/rest_api_test.clj index f3c0a434f..29a1b30f9 100644 --- a/modules/rest-api/test/blaze/rest_api_test.clj +++ b/modules/rest-api/test/blaze/rest_api_test.clj @@ -2,7 +2,7 @@ (:require [blaze.async.comp :as ac] [blaze.db.api :as d] - [blaze.db.api-stub :refer [mem-node-config]] + [blaze.db.api-stub :as api-stub] [blaze.db.impl.search-param] [blaze.fhir.parsing-context] [blaze.fhir.spec.type.system :as system] @@ -18,7 +18,6 @@ [blaze.rest-api.capabilities-handler] [blaze.rest-api.routes-spec] [blaze.terminology-service :as-alias ts] - [blaze.terminology-service.local :as ts-local] [blaze.test-util :as tu] [buddy.auth.protocols :as ap] [clojure.spec.alpha :as s] @@ -94,7 +93,7 @@ (def ^:private config (assoc - mem-node-config + api-stub/mem-node-config :blaze/rest-api {:base-url "http://localhost:8080" :parsing-context (ig/ref :blaze.fhir.parsing-context/default) @@ -137,16 +136,7 @@ :structure-definition-repo structure-definition-repo :search-param-registry (ig/ref :blaze.db/search-param-registry) :terminology-service (ig/ref ::ts/local)} - :blaze.db/search-param-registry - {:structure-definition-repo structure-definition-repo} - ::ts/local - {:node (ig/ref :blaze.db/node) - :clock (ig/ref :blaze.test/fixed-clock) - :rng-fn (ig/ref :blaze.test/fixed-rng-fn) - :graph-cache (ig/ref ::ts-local/graph-cache)} - :blaze.test/fixed-rng-fn {} :blaze.test/page-id-cipher {} - ::ts-local/graph-cache {} :blaze.test/json-parser {:parsing-context (ig/ref :blaze.fhir.parsing-context/default)} :blaze.test/json-writer diff --git a/modules/rest-util/test/blaze/fhir/response/create_test.clj b/modules/rest-util/test/blaze/fhir/response/create_test.clj index d43815ecd..f1d94e641 100644 --- a/modules/rest-util/test/blaze/fhir/response/create_test.clj +++ b/modules/rest-util/test/blaze/fhir/response/create_test.clj @@ -1,7 +1,7 @@ (ns blaze.fhir.response.create-test (:require [blaze.db.api :as d] - [blaze.db.api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.fhir.response.create :refer [build-response]] [blaze.fhir.response.create-spec] [blaze.test-util :as tu] @@ -24,7 +24,7 @@ {:blaze/base-url "http://localhost:8080" ::reitit/router router}) (deftest build-response-test - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}]]] (let [db (d/db node) diff --git a/modules/rest-util/test/blaze/handler/fhir/util_test.clj b/modules/rest-util/test/blaze/handler/fhir/util_test.clj index 277e91855..9a8f36d69 100644 --- a/modules/rest-util/test/blaze/handler/fhir/util_test.clj +++ b/modules/rest-util/test/blaze/handler/fhir/util_test.clj @@ -3,7 +3,7 @@ [blaze.anomaly :as ba] [blaze.async.comp :as ac] [blaze.db.api :as d] - [blaze.db.api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.fhir.spec.generators :as fg] [blaze.fhir.spec.type :as type] [blaze.fhir.util :as fu] @@ -251,13 +251,13 @@ (deftest pull-test (testing "not-found" - (with-system [{:blaze.db/keys [node]} mem-node-config] + (with-system [{:blaze.db/keys [node]} api-stub/mem-node-config] (given-failed-future (fhir-util/pull (d/db node) "Patient" "0") ::anom/category := ::anom/not-found ::anom/message := "Resource `Patient/0` was not found."))) (testing "deleted" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}]] [[:delete "Patient" "0"]]] @@ -270,7 +270,7 @@ :fhir/issue := "deleted"))) (testing "found" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}]]] (given @(mtu/assoc-thread-name (fhir-util/pull (d/db node) "Patient" "0")) @@ -279,7 +279,7 @@ :id := "0")) (testing "summary variant" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/CodeSystem :id "0" :url #fhir/uri "system-115910" :version #fhir/string "version-170327" @@ -297,7 +297,7 @@ (testing "pull error" (with-redefs [d/pull (fn [_ _ _] (ac/completed-future (ba/fault)))] - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}]]] (given-failed-future (fhir-util/pull (d/db node) "Patient" "0") @@ -306,12 +306,12 @@ (deftest pull-historic-test (testing "not-found" - (with-system [{:blaze.db/keys [node]} mem-node-config] + (with-system [{:blaze.db/keys [node]} api-stub/mem-node-config] (given-failed-future (fhir-util/pull-historic (d/db node) "Patient" "0" 0) ::anom/category := ::anom/not-found ::anom/message := "Resource `Patient/0` with version `0` was not found.")) - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0" :active #fhir/boolean false}]] [[:put {:fhir/type :fhir/Patient :id "0" :active #fhir/boolean true}]] [[:delete-history "Patient" "0"]]] @@ -321,7 +321,7 @@ ::anom/message := "Resource `Patient/0` with version `1` was not found."))) (testing "found" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0" :active #fhir/boolean false}]] [[:put {:fhir/type :fhir/Patient :id "0" :active #fhir/boolean true}]]] @@ -340,7 +340,7 @@ :active := #fhir/boolean true))) (testing "deleted version" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:delete "Patient" "0"]]] (given-failed-future (fhir-util/pull-historic (d/db node) "Patient" "0" 1) @@ -354,7 +354,7 @@ (testing "pull error" (with-redefs [d/pull (fn [_ _ _] (ac/completed-future (ba/fault)))] - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}]]] (given-failed-future (fhir-util/pull-historic (d/db node) "Patient" "0" 1) diff --git a/modules/terminology-service/src/blaze/terminology_service.clj b/modules/terminology-service/src/blaze/terminology_service.clj index 9268b676e..99efdc930 100644 --- a/modules/terminology-service/src/blaze/terminology_service.clj +++ b/modules/terminology-service/src/blaze/terminology_service.clj @@ -2,6 +2,9 @@ (:require [blaze.terminology-service.protocols :as p])) +(defn post-init! [terminology-service node] + (p/-post-init terminology-service node)) + (defn code-systems "Returns a CompletableFuture that will complete with a list of TerminologyCapabilities codeSystem entries or will complete exceptionally with diff --git a/modules/terminology-service/src/blaze/terminology_service/local.clj b/modules/terminology-service/src/blaze/terminology_service/local.clj index 98c7ccc30..e7430fa34 100644 --- a/modules/terminology-service/src/blaze/terminology_service/local.clj +++ b/modules/terminology-service/src/blaze/terminology_service/local.clj @@ -251,19 +251,31 @@ "lenient-display-validation" {:action :copy} "activeOnly" {:action :copy}}) +(defn- db [vnode] + (if-some [node @vnode] + (d/db node) + (ba/unavailable "Terminology service is unavailable."))) + (defn- context-with-db [context db {:keys [tx-resources]}] (cond-> (assoc context :db db) tx-resources (assoc :tx-resources tx-resources))) -(defn- terminology-service [node context] +(defn- terminology-service [config context vnode] (reify p/TerminologyService + (-post-init [_ node] + (ensure-code-systems (assoc config :node node) context) + (load-all-code-systems node) + (vreset! vnode node)) + (-code-systems [_] - (c/code-systems (d/db node))) + (when-ok [db (db vnode)] + (c/code-systems db))) (-code-system-validate-code [_ params] (if-ok [params (fu/coerce-params cs-validate-code-param-specs params) - params (cs-validate-code-more params)] - (let [db (d/new-batch-db (d/db node))] + params (cs-validate-code-more params) + db (db vnode)] + (let [db (d/new-batch-db db)] (-> (find-code-system (context-with-db context db params) params) (ac/then-apply #(cs/validate-code % params)) (handle-close db))) @@ -271,8 +283,9 @@ (-expand-value-set [_ params] (if-ok [params (fu/coerce-params vs-expand-param-specs params) - params (expand-vs-more params)] - (let [db (d/new-batch-db (d/db node)) + params (expand-vs-more params) + db (db vnode)] + (let [db (d/new-batch-db db) context (context-with-db context db params) context (assoc context :params params)] (-> (find-value-set context params) @@ -284,8 +297,9 @@ (-value-set-validate-code [_ params] (let [validate-params (partial fu/coerce-params vs-validate-code-param-specs)] (if-ok [params (validate-params params) - params (vs-validate-code-more params)] - (let [db (d/new-batch-db (d/db node)) + params (vs-validate-code-more params) + db (db vnode)] + (let [db (d/new-batch-db db) context (context-with-db context db params)] (-> (find-value-set context params) (ac/then-compose @@ -303,16 +317,13 @@ ac/completed-future))))) (defmethod m/pre-init-spec ::ts/local [_] - (s/keys :req-un [:blaze.db/node :blaze/clock :blaze/rng-fn ::graph-cache] + (s/keys :req-un [:blaze/clock :blaze/rng-fn ::graph-cache] :opt-un [::enable-bcp-13 ::enable-bcp-47 ::enable-ucum ::loinc ::sct])) (defmethod ig/init-key ::ts/local - [_ {:keys [node] :as config}] + [_ config] (log/info "Init local terminology service") - (let [context (context config)] - (ensure-code-systems config context) - (load-all-code-systems node) - (terminology-service node context))) + (terminology-service config (context config) (volatile! nil))) (defmethod m/pre-init-spec ::graph-cache [_] (s/keys :opt-un [::num-concepts])) diff --git a/modules/terminology-service/src/blaze/terminology_service/local/code_system/filter/exists.clj b/modules/terminology-service/src/blaze/terminology_service/local/code_system/filter/exists.clj index 4d1004c74..0f3a579a0 100644 --- a/modules/terminology-service/src/blaze/terminology_service/local/code_system/filter/exists.clj +++ b/modules/terminology-service/src/blaze/terminology_service/local/code_system/filter/exists.clj @@ -12,8 +12,10 @@ (if-some [value (:value value)] (if-some [should-exist? (parse-boolean value)] ((if should-exist? identity complement) - (fn [{properties :property}] - (some #(-> % :code :value (= property)) properties))) + (if (= "concept" property) + (fn [_] true) + (fn [{properties :property}] + (some #(-> % :code :value (= property)) properties)))) (ba/incorrect (format "Invalid %s exists filter value `%s` in code system `%s`. Should be one of `true` or `false`." property value url))) (ba/incorrect (format "Missing %s exists filter value in code system `%s`." property url))) (ba/incorrect (format "Missing exists filter property in code system `%s`." url)))) diff --git a/modules/terminology-service/src/blaze/terminology_service/not_available.clj b/modules/terminology-service/src/blaze/terminology_service/not_available.clj index 6fc2eb417..9b33b8f04 100644 --- a/modules/terminology-service/src/blaze/terminology_service/not_available.clj +++ b/modules/terminology-service/src/blaze/terminology_service/not_available.clj @@ -14,6 +14,8 @@ [_ _] (log/info "Init not-available terminology service") (reify p/TerminologyService + (-post-init [_ _]) + (-code-systems [_] (ac/completed-future unsupported-anom)) diff --git a/modules/terminology-service/src/blaze/terminology_service/protocols.clj b/modules/terminology-service/src/blaze/terminology_service/protocols.clj index 1d880a1f4..e38e73e70 100644 --- a/modules/terminology-service/src/blaze/terminology_service/protocols.clj +++ b/modules/terminology-service/src/blaze/terminology_service/protocols.clj @@ -1,6 +1,7 @@ (ns blaze.terminology-service.protocols) (defprotocol TerminologyService + (-post-init [_ node]) (-code-systems [_]) (-code-system-validate-code [_ params]) (-expand-value-set [_ params]) diff --git a/modules/terminology-service/src/blaze/terminology_service_spec.clj b/modules/terminology-service/src/blaze/terminology_service_spec.clj index 0cf195719..0ef0c4b98 100644 --- a/modules/terminology-service/src/blaze/terminology_service_spec.clj +++ b/modules/terminology-service/src/blaze/terminology_service_spec.clj @@ -1,11 +1,16 @@ (ns blaze.terminology-service-spec (:require [blaze.async.comp :as ac] + [blaze.db.spec] [blaze.fhir.spec] [blaze.terminology-service :as ts] [blaze.terminology-service.spec] [clojure.spec.alpha :as s])) +(s/fdef ts/post-init! + :args (s/cat :terminology-service :blaze/terminology-service + :node :blaze.db/node)) + (s/fdef ts/code-systems :args (s/cat :terminology-service :blaze/terminology-service) :ret ac/completable-future?) diff --git a/modules/terminology-service/test/blaze/terminology_service/local/code_system/bcp_13_test.clj b/modules/terminology-service/test/blaze/terminology_service/local/code_system/bcp_13_test.clj index 38a5d6a8f..481c32454 100644 --- a/modules/terminology-service/test/blaze/terminology_service/local/code_system/bcp_13_test.clj +++ b/modules/terminology-service/test/blaze/terminology_service/local/code_system/bcp_13_test.clj @@ -1,7 +1,7 @@ (ns blaze.terminology-service.local.code-system.bcp-13-test (:require [blaze.db.api :as d] - [blaze.db.api-stub :refer [mem-node-config]] + [blaze.db.api-stub :as api-stub] [blaze.fhir.test-util] [blaze.module-spec] [blaze.module.test-util :refer [with-system]] @@ -14,10 +14,9 @@ (test/use-fixtures :each tu/fixture) -(def config +(def ^:private config (assoc - mem-node-config - :blaze.test/fixed-clock {} + api-stub/mem-node-config :blaze.test/incrementing-rng-fn {})) (deftest ensure-code-system-test diff --git a/modules/terminology-service/test/blaze/terminology_service/local/code_system/bcp_47_test.clj b/modules/terminology-service/test/blaze/terminology_service/local/code_system/bcp_47_test.clj index f965b81de..b8702dfdc 100644 --- a/modules/terminology-service/test/blaze/terminology_service/local/code_system/bcp_47_test.clj +++ b/modules/terminology-service/test/blaze/terminology_service/local/code_system/bcp_47_test.clj @@ -1,7 +1,7 @@ (ns blaze.terminology-service.local.code-system.bcp-47-test (:require [blaze.db.api :as d] - [blaze.db.api-stub :refer [mem-node-config]] + [blaze.db.api-stub :as api-stub] [blaze.fhir.test-util] [blaze.module-spec] [blaze.module.test-util :refer [with-system]] @@ -14,10 +14,9 @@ (test/use-fixtures :each tu/fixture) -(def config +(def ^:private config (assoc - mem-node-config - :blaze.test/fixed-clock {} + api-stub/mem-node-config :blaze.test/incrementing-rng-fn {})) (deftest ensure-code-system-test diff --git a/modules/terminology-service/test/blaze/terminology_service/local/code_system/loinc_test.clj b/modules/terminology-service/test/blaze/terminology_service/local/code_system/loinc_test.clj index fccbbe668..0749513ad 100644 --- a/modules/terminology-service/test/blaze/terminology_service/local/code_system/loinc_test.clj +++ b/modules/terminology-service/test/blaze/terminology_service/local/code_system/loinc_test.clj @@ -1,7 +1,7 @@ (ns blaze.terminology-service.local.code-system.loinc-test (:require [blaze.db.api :as d] - [blaze.db.api-stub :refer [mem-node-config]] + [blaze.db.api-stub :as api-stub] [blaze.fhir.test-util] [blaze.module.test-util :refer [with-system]] [blaze.terminology-service.local.code-system :as-alias cs] @@ -15,10 +15,9 @@ (test/use-fixtures :each tu/fixture) -(def config +(def ^:private config (assoc - mem-node-config - :blaze.test/fixed-clock {} + api-stub/mem-node-config :blaze.test/incrementing-rng-fn {} ::cs/loinc {})) diff --git a/modules/terminology-service/test/blaze/terminology_service/local/code_system/sct_test.clj b/modules/terminology-service/test/blaze/terminology_service/local/code_system/sct_test.clj index 4929ca0c8..4d90c7691 100644 --- a/modules/terminology-service/test/blaze/terminology_service/local/code_system/sct_test.clj +++ b/modules/terminology-service/test/blaze/terminology_service/local/code_system/sct_test.clj @@ -1,7 +1,7 @@ (ns blaze.terminology-service.local.code-system.sct-test (:require [blaze.db.api :as d] - [blaze.db.api-stub :refer [mem-node-config]] + [blaze.db.api-stub :as api-stub] [blaze.fhir.test-util] [blaze.module.test-util :refer [with-system]] [blaze.path :refer [path]] @@ -16,10 +16,9 @@ (test/use-fixtures :each tu/fixture) -(def config +(def ^:private config (assoc - mem-node-config - :blaze.test/fixed-clock {} + api-stub/mem-node-config :blaze.test/incrementing-rng-fn {} ::cs/sct {:release-path (path "sct-release")})) diff --git a/modules/terminology-service/test/blaze/terminology_service/local/code_system/ucum_test.clj b/modules/terminology-service/test/blaze/terminology_service/local/code_system/ucum_test.clj index 2fa00d716..a6815ae15 100644 --- a/modules/terminology-service/test/blaze/terminology_service/local/code_system/ucum_test.clj +++ b/modules/terminology-service/test/blaze/terminology_service/local/code_system/ucum_test.clj @@ -1,7 +1,7 @@ (ns blaze.terminology-service.local.code-system.ucum-test (:require [blaze.db.api :as d] - [blaze.db.api-stub :refer [mem-node-config]] + [blaze.db.api-stub :as api-stub] [blaze.fhir.test-util] [blaze.module-spec] [blaze.module.test-util :refer [with-system]] @@ -14,10 +14,9 @@ (test/use-fixtures :each tu/fixture) -(def config +(def ^:private config (assoc - mem-node-config - :blaze.test/fixed-clock {} + api-stub/mem-node-config :blaze.test/incrementing-rng-fn {})) (deftest ensure-code-system-test diff --git a/modules/terminology-service/test/blaze/terminology_service/local/code_system_test.clj b/modules/terminology-service/test/blaze/terminology_service/local/code_system_test.clj index d8be3abb4..718a0632e 100644 --- a/modules/terminology-service/test/blaze/terminology_service/local/code_system_test.clj +++ b/modules/terminology-service/test/blaze/terminology_service/local/code_system_test.clj @@ -1,7 +1,7 @@ (ns blaze.terminology-service.local.code-system-test (:require [blaze.db.api :as d] - [blaze.db.api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.terminology-service.local.code-system :as cs] [blaze.terminology-service.local.code-system-spec] [blaze.test-util :as tu] @@ -15,7 +15,7 @@ (deftest list-test (testing "with one code system" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/CodeSystem :id "id-160617" :url #fhir/uri "system-192435" :content #fhir/code "complete"}]]] @@ -30,7 +30,7 @@ (testing "with same URL" (testing "which are identical" (testing "created in the same transaction" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/CodeSystem :id "id-0" :url #fhir/uri "system-192435" :content #fhir/code "complete"}] @@ -47,7 +47,7 @@ [0 val 1 :id] := "id-0")))) (testing "created in different transactions" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/CodeSystem :id "id-1" :url #fhir/uri "system-192435" :content #fhir/code "complete"}]] @@ -65,7 +65,7 @@ (testing "with different versions" (testing "major only" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/CodeSystem :id "id-0" :url #fhir/uri "system-192435" :version #fhir/string "2" @@ -84,7 +84,7 @@ [0 val 1 :id] := "id-1")))) (testing "same major but different numeric minor" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/CodeSystem :id "id-0" :url #fhir/uri "system-192435" :version #fhir/string "1.10" @@ -103,7 +103,7 @@ [0 val 1 :id] := "id-1")))) (testing "same major but different mixed minor" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/CodeSystem :id "id-0" :url #fhir/uri "system-192435" :version #fhir/string "1.a" @@ -122,7 +122,7 @@ [0 val 1 :id] := "id-1")))) (testing "major and major.minor" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/CodeSystem :id "id-0" :url #fhir/uri "system-192435" :version #fhir/string "2" @@ -141,7 +141,7 @@ [0 val 1 :id] := "id-1")))) (testing "active version comes before no version" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/CodeSystem :id "id-0" :url #fhir/uri "system-192435" :status #fhir/code "active" @@ -161,7 +161,7 @@ [0 val 1 :id] := "id-1")))) (testing "active version comes before draft version" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/CodeSystem :id "id-0" :url #fhir/uri "system-192435" :version #fhir/string "1.1" @@ -182,7 +182,7 @@ [0 val 1 :id] := "id-1")))) (testing "draft version comes before retired version" - (with-system-data [{:blaze.db/keys [node]} mem-node-config] + (with-system-data [{:blaze.db/keys [node]} api-stub/mem-node-config] [[[:put {:fhir/type :fhir/CodeSystem :id "id-0" :url #fhir/uri "system-192435" :version #fhir/string "1.1" diff --git a/modules/terminology-service/test/blaze/terminology_service/local_test.clj b/modules/terminology-service/test/blaze/terminology_service/local_test.clj index e9880790c..e54c164b6 100644 --- a/modules/terminology-service/test/blaze/terminology_service/local_test.clj +++ b/modules/terminology-service/test/blaze/terminology_service/local_test.clj @@ -1,13 +1,13 @@ (ns blaze.terminology-service.local-test (:require [blaze.db.api :as d] - [blaze.db.api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system with-system-data]] [blaze.fhir.spec :as fhir-spec] [blaze.fhir.spec.type :as type] [blaze.fhir.test-util :refer [parameter structure-definition-repo]] [blaze.fhir.util :as fu] [blaze.fhir.util-spec] - [blaze.module.test-util :refer [given-failed-future given-failed-system with-system]] + [blaze.module.test-util :refer [given-failed-future given-failed-system]] [blaze.path :refer [path]] [blaze.spec] [blaze.terminology-service :as ts] @@ -38,17 +38,8 @@ (test/use-fixtures :each tu/fixture) -(def config - (assoc - mem-node-config - ::ts/local - {:node (ig/ref :blaze.db/node) - :clock (ig/ref :blaze.test/fixed-clock) - :rng-fn (ig/ref :blaze.test/fixed-rng-fn) - :graph-cache (ig/ref ::local/graph-cache)} - :blaze.test/fixed-clock {} - :blaze.test/fixed-rng-fn {} - ::local/graph-cache {})) +(def ^:private config + api-stub/mem-node-config) (deftest init-test (testing "nil config" @@ -61,17 +52,9 @@ (given-failed-system {::ts/local {}} :key := ::ts/local :reason := ::ig/build-failed-spec - [:cause-data ::s/problems 0 :pred] := `(fn ~'[%] (contains? ~'% :node)) - [:cause-data ::s/problems 1 :pred] := `(fn ~'[%] (contains? ~'% :clock)) - [:cause-data ::s/problems 2 :pred] := `(fn ~'[%] (contains? ~'% :rng-fn)) - [:cause-data ::s/problems 3 :pred] := `(fn ~'[%] (contains? ~'% :graph-cache)))) - - (testing "invalid node" - (given-failed-system (assoc-in config [::ts/local :node] ::invalid) - :key := ::ts/local - :reason := ::ig/build-failed-spec - [:cause-data ::s/problems 0 :via] := [:blaze.db/node] - [:cause-data ::s/problems 0 :val] := ::invalid)) + [:cause-data ::s/problems 0 :pred] := `(fn ~'[%] (contains? ~'% :clock)) + [:cause-data ::s/problems 1 :pred] := `(fn ~'[%] (contains? ~'% :rng-fn)) + [:cause-data ::s/problems 2 :pred] := `(fn ~'[%] (contains? ~'% :graph-cache)))) (testing "invalid clock" (given-failed-system (assoc-in config [::ts/local :clock] ::invalid) @@ -94,31 +77,11 @@ [:cause-data ::s/problems 0 :via] := [::local/graph-cache] [:cause-data ::s/problems 0 :val] := ::invalid))) -(def bcp-13-config - (assoc - mem-node-config - ::ts/local - {:node (ig/ref :blaze.db/node) - :clock (ig/ref :blaze.test/fixed-clock) - :rng-fn (ig/ref :blaze.test/fixed-rng-fn) - :graph-cache (ig/ref ::local/graph-cache) - :enable-bcp-13 true} - :blaze.test/fixed-clock {} - :blaze.test/fixed-rng-fn {} - ::local/graph-cache {})) - -(def bcp-47-config - (assoc - mem-node-config - ::ts/local - {:node (ig/ref :blaze.db/node) - :clock (ig/ref :blaze.test/fixed-clock) - :rng-fn (ig/ref :blaze.test/fixed-rng-fn) - :graph-cache (ig/ref ::local/graph-cache) - :enable-bcp-47 true} - :blaze.test/fixed-clock {} - :blaze.test/fixed-rng-fn {} - ::local/graph-cache {})) +(def ^:private bcp-13-config + (assoc-in api-stub/mem-node-config [::ts/local :enable-bcp-13] true)) + +(def ^:private bcp-47-config + (assoc-in api-stub/mem-node-config [::ts/local :enable-bcp-47] true)) ;; put LOINC data into an opaque function, so that it can't be introspected ;; by dev tooling, because it's just large @@ -131,65 +94,37 @@ [_ _] (loinc)) -(def loinc-config - (assoc - mem-node-config - ::ts/local - {:node (ig/ref :blaze.db/node) - :clock (ig/ref :blaze.test/fixed-clock) - :rng-fn (ig/ref :blaze.test/fixed-rng-fn) - :graph-cache (ig/ref ::local/graph-cache) - :loinc (ig/ref ::loinc)} - :blaze.test/fixed-clock {} - :blaze.test/fixed-rng-fn {} - ::local/graph-cache {} - ::loinc {})) - -(def sct-config - (assoc - mem-node-config - ::ts/local - {:node (ig/ref :blaze.db/node) - :clock (ig/ref :blaze.test/fixed-clock) - :rng-fn (ig/ref :blaze.test/incrementing-rng-fn) - :graph-cache (ig/ref ::local/graph-cache) - :sct (ig/ref ::cs/sct)} - :blaze.test/fixed-clock {} - :blaze.test/incrementing-rng-fn {} - ::local/graph-cache {} - ::cs/sct {:release-path (path "sct-release")})) - -(def ucum-config - (assoc - mem-node-config - ::ts/local - {:node (ig/ref :blaze.db/node) - :clock (ig/ref :blaze.test/fixed-clock) - :rng-fn (ig/ref :blaze.test/fixed-rng-fn) - :graph-cache (ig/ref ::local/graph-cache) - :enable-ucum true} - :blaze.test/fixed-clock {} - :blaze.test/fixed-rng-fn {} - ::local/graph-cache {})) - -(def complete-config - (assoc - mem-node-config - ::ts/local - {:node (ig/ref :blaze.db/node) - :clock (ig/ref :blaze.test/fixed-clock) - :rng-fn (ig/ref :blaze.test/incrementing-rng-fn) - :graph-cache (ig/ref ::local/graph-cache) - :enable-bcp-13 true - :enable-bcp-47 true - :enable-ucum true - :loinc (ig/ref ::loinc) - :sct (ig/ref ::cs/sct)} - :blaze.test/fixed-clock {} - :blaze.test/incrementing-rng-fn {} - ::local/graph-cache {} - ::loinc {} - ::cs/sct {:release-path (path "sct-release")})) +(def ^:private loinc-config + (-> (assoc-in api-stub/mem-node-config [::ts/local :loinc] (ig/ref ::loinc)) + (assoc ::loinc {}))) + +(def ^:private sct-config + (merge-with + merge + api-stub/mem-node-config + {::ts/local + {:rng-fn (ig/ref :blaze.test/incrementing-rng-fn) + :sct (ig/ref ::cs/sct)} + :blaze.test/incrementing-rng-fn {} + ::cs/sct {:release-path (path "sct-release")}})) + +(def ^:private ucum-config + (assoc-in api-stub/mem-node-config [::ts/local :enable-ucum] true)) + +(def ^:private complete-config + (merge-with + merge + api-stub/mem-node-config + {::ts/local + {:rng-fn (ig/ref :blaze.test/incrementing-rng-fn) + :enable-bcp-13 true + :enable-bcp-47 true + :enable-ucum true + :loinc (ig/ref ::loinc) + :sct (ig/ref ::cs/sct)} + :blaze.test/incrementing-rng-fn {} + ::loinc {} + ::cs/sct {:release-path (path "sct-release")}})) (defn- pull-type-list [node type] @(d/pull-many node (vec (d/type-list (d/db node) type)))) @@ -3220,9 +3155,29 @@ [:expansion :contains 1 :code] := #fhir/code "code-192308" [:expansion :contains 1 :display] := #fhir/string "display-192313")))) +(defn- vcl-uri [expr] + (type/uri (str "http://fhir.org/VCL?v1=" expr))) + (deftest expand-value-set-include-filter-exists-test (testing "with a single concept" (testing "without a property" + (testing "concept property" + (with-system-data [{ts ::ts/local} config] + [[[:put {:fhir/type :fhir/CodeSystem :id "0" + :url #fhir/uri "http://system-182822" + :content #fhir/code "complete" + :concept + [{:fhir/type :fhir.CodeSystem/concept + :code #fhir/code "code-182832" + :display #fhir/string "display-182717"}]}]]] + + (given @(expand-value-set ts "url" (vcl-uri "(http://system-182822)*")) + :fhir/type := :fhir/ValueSet + [:expansion :contains count] := 1 + [:expansion :contains 0 :system] := #fhir/uri "http://system-182822" + [:expansion :contains 0 :code] := #fhir/code "code-182832" + [:expansion :contains 0 :display] := #fhir/string "display-182717"))) + (testing "that shouldn't exist" (with-system-data [{ts ::ts/local} config] [[[:put {:fhir/type :fhir/CodeSystem :id "0" @@ -3747,9 +3702,6 @@ [:expansion :contains 0 :code] := #fhir/code "26465-5" [:expansion :contains 0 :display] := #fhir/string "Leukocytes [#/volume] in Cerebral spinal fluid")))))) -(defn- vcl-uri [expr] - (type/uri (str "http://fhir.org/VCL?v1=" expr))) - (deftest expand-value-set-loinc-include-filter-equals-test (testing "COMPONENT = LP14449-0/Hemoglobin" (with-system [{ts ::ts/local} loinc-config] diff --git a/resources/blaze.edn b/resources/blaze.edn index bfe3b8a80..704384bf6 100644 --- a/resources/blaze.edn +++ b/resources/blaze.edn @@ -429,6 +429,7 @@ ;; :blaze.db/search-param-registry {:structure-definition-repo #blaze/ref :blaze.fhir/structure-definition-repo + :terminology-service #blaze/ref :blaze.terminology-service/not-available :extra-bundle-file #blaze/cfg ["DB_SEARCH_PARAM_BUNDLE" string?]} ;; @@ -1456,8 +1457,7 @@ {:terminology-service #blaze/ref :blaze.terminology-service/local} :blaze.terminology-service/local - {:node #blaze/ref :blaze.db.main/node - :clock #blaze/ref :blaze/clock + {:clock #blaze/ref :blaze/clock :rng-fn #blaze/ref :blaze/rng-fn :graph-cache #blaze/ref :blaze.terminology-service.local/graph-cache :enable-bcp-13 true @@ -1472,6 +1472,9 @@ {"terminology-service-graph-cache" #blaze/ref :blaze.terminology-service.local/graph-cache}} :blaze.rest-api/capabilities-handler + {:terminology-service #blaze/ref :blaze.terminology-service/local} + + :blaze.db/search-param-registry {:terminology-service #blaze/ref :blaze.terminology-service/local}}} {:key :terminology-loinc @@ -1508,6 +1511,9 @@ :trust-store-pass #blaze/cfg ["EXTERN_TERMINOLOGY_SERVICE_CLIENT_TRUST_STORE_PASS" string?]} :blaze.fhir.operation.evaluate-measure/handler + {:terminology-service #blaze/ref :blaze.terminology-service/extern} + + :blaze.db/search-param-registry {:terminology-service #blaze/ref :blaze.terminology-service/extern}}} {:key :graph diff --git a/src/blaze/system.clj b/src/blaze/system.clj index c9cd73b0b..26ee16ccb 100644 --- a/src/blaze/system.clj +++ b/src/blaze/system.clj @@ -11,7 +11,9 @@ [blaze.fhir.spec.type.system :as system] [blaze.log] [blaze.path :refer [dir? path]] + [blaze.rest-api :as-alias rest-api] [blaze.spec] + [blaze.terminology-service :as ts] [blaze.util :as u :refer [str]] [clojure.java.io :as io] [clojure.spec.alpha :as s] @@ -133,10 +135,10 @@ :context-path (->Cfg "CONTEXT_PATH" string? "/fhir") :db-sync-timeout (->Cfg "DB_SYNC_TIMEOUT" pos-int? 10000)} - :blaze.rest-api/requests-total {} - :blaze.rest-api/request-duration-seconds {} - :blaze.rest-api/parse-duration-seconds {} - :blaze.rest-api/generate-duration-seconds {} + ::rest-api/requests-total {} + ::rest-api/request-duration-seconds {} + ::rest-api/parse-duration-seconds {} + ::rest-api/generate-duration-seconds {} :blaze.handler/app {:rest-api (ig/ref :blaze/rest-api) @@ -208,6 +210,12 @@ base-config features)) +(defn- post-init + [{terminology-service :blaze.terminology-service/local :as system}] + (when terminology-service + (let [node (system [:blaze.db/node :blaze.db.main/node])] + (ts/post-init! terminology-service node)))) + (defn init! [{level "LOG_LEVEL" :or {level "info"} :as env}] (log/info "Set log level to:" (str/lower-case level)) @@ -228,7 +236,8 @@ (load-namespaces config) (-> (ig/bind config bind-map) (ig/expand) - (ig/init))) + (ig/init) + (post-init))) ba/throw-anom)) diff --git a/test/blaze/system_test.clj b/test/blaze/system_test.clj index a1417449d..ba25e16aa 100644 --- a/test/blaze/system_test.clj +++ b/test/blaze/system_test.clj @@ -1,7 +1,7 @@ (ns blaze.system-test (:require [blaze.async.comp :as ac] - [blaze.db.api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.fhir.parsing-context] [blaze.fhir.spec.type.system :refer [parse-date-time]] [blaze.fhir.test-util :refer [structure-definition-repo]] @@ -30,7 +30,6 @@ [blaze.system :as system] [blaze.system-spec] [blaze.terminology-service :as-alias ts] - [blaze.terminology-service.local :as ts-local] [blaze.test-util :as tu] [buddy.auth.protocols :as ap] [clojure.spec.alpha :as s] @@ -136,9 +135,9 @@ :foo := {:default {:read {} :delete-history {}}}))) -(def config +(def ^:private config (assoc - mem-node-config + api-stub/mem-node-config :blaze/rest-api {:base-url "http://localhost:8080" :parsing-context (ig/ref :blaze.fhir.parsing-context/default) @@ -162,8 +161,6 @@ :job-scheduler (ig/ref :blaze/job-scheduler) :clock (ig/ref :blaze.test/fixed-clock) :rng-fn (ig/ref :blaze.test/fixed-rng-fn)} - :blaze.db/search-param-registry - {:structure-definition-repo structure-definition-repo} ::auth-backend {} :blaze.interaction/transaction {:node (ig/ref :blaze.db/node) @@ -246,18 +243,11 @@ :history-type #:blaze.rest-api.interaction {:handler (ig/ref :blaze.interaction.history/type)}}} - ::ts/local - {:node (ig/ref :blaze.db/node) - :clock (ig/ref :blaze.test/fixed-clock) - :rng-fn (ig/ref :blaze.test/fixed-rng-fn) - :graph-cache (ig/ref ::ts-local/graph-cache)} ::search-util/link {:fhir/version "4.0.1"} :blaze.test/executor {} :blaze.test/fixed-clock {} - :blaze.test/fixed-rng-fn {} ::page-store {} :blaze.test/page-id-cipher {} - ::ts-local/graph-cache {} :blaze.test/json-parser {:parsing-context (ig/ref :blaze.fhir.parsing-context/default)} :blaze.test/json-writer