diff --git a/.gitignore b/.gitignore
index f9f2c1c9..4ab88332 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,6 +11,7 @@ ctl/*
/test/tmp/
/test/version_tmp/
/test/unit/coverage
+/test/coverage
/tmp/
## Specific to RubyMotion:
diff --git a/Gemfile.lock b/Gemfile.lock
index 2d624164..22ac804f 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -7,6 +7,7 @@ PATH
fhir_client
fhir_dstu2_models
fhir_models
+ fhir_stu3_models
jsonpath
nokogiri (>= 1.8.2)
nokogiri-diff
@@ -16,7 +17,7 @@ PATH
GEM
remote: https://rubygems.org/
specs:
- activesupport (5.2.2.1)
+ activesupport (5.2.3)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
@@ -28,7 +29,9 @@ GEM
bcp47 (0.3.3)
i18n
coderay (1.1.2)
- concurrent-ruby (1.1.5)
+ concurrent-ruby (1.1.6)
+ coolline (0.5.0)
+ unicode_utils (~> 1.4)
crack (0.4.3)
safe_yaml (~> 1.0.0)
date_time_precision (0.8.1)
@@ -37,30 +40,36 @@ GEM
unf (>= 0.0.5, < 1.0.0)
faraday (0.15.4)
multipart-post (>= 1.2, < 3)
- fhir_client (3.1.2)
+ fhir_client (4.0.0)
activesupport (>= 3)
addressable (>= 2.3)
- fhir_dstu2_models (>= 1.0.4)
- fhir_models (>= 3.0.3)
+ fhir_dstu2_models (>= 1.0.9)
+ fhir_models (>= 4.0.0)
+ fhir_stu3_models (>= 3.0.0)
nokogiri (>= 1.8.2)
oauth2 (~> 1.1)
rack (>= 1.5)
rest-client (~> 2.0)
tilt (>= 1.1)
- fhir_dstu2_models (1.0.7)
+ fhir_dstu2_models (1.0.10)
bcp47 (>= 0.3)
date_time_precision (>= 0.8)
- mime-types (>= 1.16, < 3)
- nokogiri (>= 1.8.2)
- fhir_models (3.0.3)
+ mime-types (>= 3.0)
+ nokogiri (>= 1.10.4)
+ fhir_models (4.0.2)
bcp47 (>= 0.3)
date_time_precision (>= 0.8)
- mime-types (>= 1.16, < 3)
- nokogiri (>= 1.8.2)
+ mime-types (>= 3.0)
+ nokogiri (>= 1.10.4)
+ fhir_stu3_models (3.0.1)
+ bcp47 (>= 0.3)
+ date_time_precision (>= 0.8)
+ mime-types (>= 3.0)
+ nokogiri (>= 1.10.4)
hashdiff (0.3.8)
http-cookie (1.0.3)
domain_name (~> 0.5)
- i18n (1.6.0)
+ i18n (1.8.2)
concurrent-ruby (~> 1.0)
json (2.2.0)
jsonpath (1.0.1)
@@ -68,14 +77,16 @@ GEM
to_regexp (~> 0.2.1)
jwt (2.1.0)
method_source (0.9.2)
- mime-types (2.99.3)
+ mime-types (3.3.1)
+ mime-types-data (~> 3.2015)
+ mime-types-data (3.2019.1009)
mini_portile2 (2.4.0)
minitest (5.11.3)
multi_json (1.13.1)
multi_xml (0.6.0)
multipart-post (2.0.0)
netrc (0.11.0)
- nokogiri (1.10.8)
+ nokogiri (1.10.9)
mini_portile2 (~> 2.4.0)
nokogiri-diff (0.2.0)
nokogiri (~> 1.5)
@@ -90,6 +101,8 @@ GEM
pry (0.12.2)
coderay (~> 1.1.0)
method_source (~> 0.9.0)
+ pry-coolline (0.2.5)
+ coolline (~> 0.5)
public_suffix (3.0.3)
rack (2.0.8)
rake (12.3.3)
@@ -113,7 +126,8 @@ GEM
thread_safe (~> 0.1)
unf (0.1.4)
unf_ext
- unf_ext (0.0.7.5)
+ unf_ext (0.0.7.6)
+ unicode_utils (1.4.0)
webmock (3.5.1)
addressable (>= 2.3.6)
crack (>= 0.3.2)
@@ -127,6 +141,7 @@ DEPENDENCIES
awesome_print
plan_executor!
pry
+ pry-coolline
rake
simplecov
test-unit
diff --git a/README.md b/README.md
index 85c7d234..803e4105 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,8 @@
# Plan Executor [![Build Status](https://travis-ci.org/fhir-crucible/plan_executor.svg?branch=master)](https://travis-ci.org/fhir-crucible/plan_executor)
-Plan Executor runs test suites against a FHIR server.
-
-# STU3
-
-Updated to support the FHIR [STU3 Candidate branch](http://hl7.org/fhir/2016May/index.html).
+Plan Executor runs test suites against a FHIR server. It supports `DSTU2`, `STU3` and `R4` versions of FHIR.
+Tests can either be written in [Ruby](https://github.com/fhir-crucible/plan_executor#adding-a-new-test-suite),
+or using the [TestScript Resource](https://github.com/fhir-crucible/plan_executor/wiki/Using-Plan-Executor-with-TestScripts#testscript).
## Getting Started
@@ -15,7 +13,7 @@ $ bundle exec rake -T
## Listing Test Suites
-List all the available Test Suites, excluding supported `TestScripts`. Pass the version, which can currently either be `dstu2` or `stu3`.
+List all the available Test Suites, excluding supported `TestScripts`. Pass the version, which can currently be `dstu2`, `stu3` or `r4`.
```
$ bundle exec rake crucible:list_suites[dstu2]
@@ -26,18 +24,23 @@ $ bundle exec rake crucible:list_suites[dstu2]
Crucible tests can be executed by suite from the command-line by calling the `crucible-execute` rake task with the following parameters:
* `url` the FHIR endpoint
-* `version` the FHIR version (sequence). Currently `dstu2` and `stu3` are supported.
+* `version` the FHIR version (sequence). Currently `dstu2`, `stu3` and `r4` are supported.
* `test` the name of the test suite (see `crucible:list_suites`)
* `resource` (optional) limit the `test` (applicable to "ResourceTest" or "SearchTest" suites) to a given resource (e.g. "Patient")
-Run a DSTU2 Suite
+Run a R4 Suite limited by Resource
```
-$ bundle exec rake crucible:execute[http://fhirtest.uhn.ca/baseDstu2,dstu2,TransactionAndBatchTest]
+$ bundle exec rake crucible:execute[http://hapi.fhir.org/r4,r4,ResourceTest,Patient]
```
Run a STU3 Suite limited by Resource
```
-$ bundle exec rake crucible:execute[http://fhirtest.uhn.ca/baseDstu3,stu3,ResourceTest,Patient]
+$ bundle exec rake crucible:execute[http://hapi.fhir.org/baseDstu3,stu3,ResourceTest,Patient]
+```
+
+Run a DSTU2 Suite
+```
+$ bundle exec rake crucible:execute[http://hapi.fhir.org/baseDstu2,dstu2,TransactionAndBatchTest]
```
## Adding a New Test Suite
@@ -113,7 +116,7 @@ a trail of test data behind.
# License
-Copyright 2014-2016 The MITRE Corporation
+Copyright 2014-2020 The MITRE Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/fixtures/attachment/ccda_pdf.pdf b/fixtures/stu3/attachment/ccda_pdf.pdf
similarity index 100%
rename from fixtures/attachment/ccda_pdf.pdf
rename to fixtures/stu3/attachment/ccda_pdf.pdf
diff --git a/fixtures/attachment/ccda_pdf_base64.txt b/fixtures/stu3/attachment/ccda_pdf_base64.txt
similarity index 100%
rename from fixtures/attachment/ccda_pdf_base64.txt
rename to fixtures/stu3/attachment/ccda_pdf_base64.txt
diff --git a/fixtures/attachment/ccda_structured.xml b/fixtures/stu3/attachment/ccda_structured.xml
similarity index 100%
rename from fixtures/attachment/ccda_structured.xml
rename to fixtures/stu3/attachment/ccda_structured.xml
diff --git a/fixtures/attachment/ccda_unstructured.xml b/fixtures/stu3/attachment/ccda_unstructured.xml
similarity index 100%
rename from fixtures/attachment/ccda_unstructured.xml
rename to fixtures/stu3/attachment/ccda_unstructured.xml
diff --git a/fixtures/diagnostic_report/diagnosticreport-familyhistory-create.xml b/fixtures/stu3/diagnostic_report/diagnosticreport-familyhistory-create.xml
similarity index 100%
rename from fixtures/diagnostic_report/diagnosticreport-familyhistory-create.xml
rename to fixtures/stu3/diagnostic_report/diagnosticreport-familyhistory-create.xml
diff --git a/fixtures/diagnostic_report/diagnosticreport-hlatyping-create.xml b/fixtures/stu3/diagnostic_report/diagnosticreport-hlatyping-create.xml
similarity index 100%
rename from fixtures/diagnostic_report/diagnosticreport-hlatyping-create.xml
rename to fixtures/stu3/diagnostic_report/diagnosticreport-hlatyping-create.xml
diff --git a/fixtures/diagnostic_report/diagnosticreport-pathologyreport-create.xml b/fixtures/stu3/diagnostic_report/diagnosticreport-pathologyreport-create.xml
similarity index 100%
rename from fixtures/diagnostic_report/diagnosticreport-pathologyreport-create.xml
rename to fixtures/stu3/diagnostic_report/diagnosticreport-pathologyreport-create.xml
diff --git a/fixtures/diagnostic_report/dr-100.xml b/fixtures/stu3/diagnostic_report/dr-100.xml
similarity index 100%
rename from fixtures/diagnostic_report/dr-100.xml
rename to fixtures/stu3/diagnostic_report/dr-100.xml
diff --git a/fixtures/diagnostic_report/dr-200.xml b/fixtures/stu3/diagnostic_report/dr-200.xml
similarity index 100%
rename from fixtures/diagnostic_report/dr-200.xml
rename to fixtures/stu3/diagnostic_report/dr-200.xml
diff --git a/fixtures/diagnostic_report/dr-300.xml b/fixtures/stu3/diagnostic_report/dr-300.xml
similarity index 100%
rename from fixtures/diagnostic_report/dr-300.xml
rename to fixtures/stu3/diagnostic_report/dr-300.xml
diff --git a/fixtures/diagnostic_report/dr-400.xml b/fixtures/stu3/diagnostic_report/dr-400.xml
similarity index 100%
rename from fixtures/diagnostic_report/dr-400.xml
rename to fixtures/stu3/diagnostic_report/dr-400.xml
diff --git a/fixtures/diagnostic_request/do-100.xml b/fixtures/stu3/diagnostic_request/do-100.xml
similarity index 100%
rename from fixtures/diagnostic_request/do-100.xml
rename to fixtures/stu3/diagnostic_request/do-100.xml
diff --git a/fixtures/diagnostic_request/do-200.xml b/fixtures/stu3/diagnostic_request/do-200.xml
similarity index 100%
rename from fixtures/diagnostic_request/do-200.xml
rename to fixtures/stu3/diagnostic_request/do-200.xml
diff --git a/fixtures/diagnostic_request/do-300.xml b/fixtures/stu3/diagnostic_request/do-300.xml
similarity index 100%
rename from fixtures/diagnostic_request/do-300.xml
rename to fixtures/stu3/diagnostic_request/do-300.xml
diff --git a/fixtures/diagnostic_request/do-400.xml b/fixtures/stu3/diagnostic_request/do-400.xml
similarity index 100%
rename from fixtures/diagnostic_request/do-400.xml
rename to fixtures/stu3/diagnostic_request/do-400.xml
diff --git a/fixtures/family_member_history/familymemberhistory-familyhistory-create.xml b/fixtures/stu3/family_member_history/familymemberhistory-familyhistory-create.xml
similarity index 100%
rename from fixtures/family_member_history/familymemberhistory-familyhistory-create.xml
rename to fixtures/stu3/family_member_history/familymemberhistory-familyhistory-create.xml
diff --git a/fixtures/financial/claim-example-oral-average.xml b/fixtures/stu3/financial/claim-example-oral-average.xml
similarity index 100%
rename from fixtures/financial/claim-example-oral-average.xml
rename to fixtures/stu3/financial/claim-example-oral-average.xml
diff --git a/fixtures/financial/claim-example-oral-orthoplan.xml b/fixtures/stu3/financial/claim-example-oral-orthoplan.xml
similarity index 100%
rename from fixtures/financial/claim-example-oral-orthoplan.xml
rename to fixtures/stu3/financial/claim-example-oral-orthoplan.xml
diff --git a/fixtures/financial/claim-example.xml b/fixtures/stu3/financial/claim-example.xml
similarity index 100%
rename from fixtures/financial/claim-example.xml
rename to fixtures/stu3/financial/claim-example.xml
diff --git a/fixtures/financial/eligibilityrequest-example.xml b/fixtures/stu3/financial/eligibilityrequest-example.xml
similarity index 100%
rename from fixtures/financial/eligibilityrequest-example.xml
rename to fixtures/stu3/financial/eligibilityrequest-example.xml
diff --git a/fixtures/observation/obs-100.xml b/fixtures/stu3/observation/obs-100.xml
similarity index 100%
rename from fixtures/observation/obs-100.xml
rename to fixtures/stu3/observation/obs-100.xml
diff --git a/fixtures/observation/obs-101.xml b/fixtures/stu3/observation/obs-101.xml
similarity index 100%
rename from fixtures/observation/obs-101.xml
rename to fixtures/stu3/observation/obs-101.xml
diff --git a/fixtures/observation/obs-200.xml b/fixtures/stu3/observation/obs-200.xml
similarity index 100%
rename from fixtures/observation/obs-200.xml
rename to fixtures/stu3/observation/obs-200.xml
diff --git a/fixtures/observation/obs-300.xml b/fixtures/stu3/observation/obs-300.xml
similarity index 100%
rename from fixtures/observation/obs-300.xml
rename to fixtures/stu3/observation/obs-300.xml
diff --git a/fixtures/observation/obs-301.xml b/fixtures/stu3/observation/obs-301.xml
similarity index 100%
rename from fixtures/observation/obs-301.xml
rename to fixtures/stu3/observation/obs-301.xml
diff --git a/fixtures/observation/obs-302.xml b/fixtures/stu3/observation/obs-302.xml
similarity index 100%
rename from fixtures/observation/obs-302.xml
rename to fixtures/stu3/observation/obs-302.xml
diff --git a/fixtures/observation/obs-303.xml b/fixtures/stu3/observation/obs-303.xml
similarity index 100%
rename from fixtures/observation/obs-303.xml
rename to fixtures/stu3/observation/obs-303.xml
diff --git a/fixtures/observation/obs-304.xml b/fixtures/stu3/observation/obs-304.xml
similarity index 100%
rename from fixtures/observation/obs-304.xml
rename to fixtures/stu3/observation/obs-304.xml
diff --git a/fixtures/observation/obs-400.xml b/fixtures/stu3/observation/obs-400.xml
similarity index 100%
rename from fixtures/observation/obs-400.xml
rename to fixtures/stu3/observation/obs-400.xml
diff --git a/fixtures/observation/obs-401.xml b/fixtures/stu3/observation/obs-401.xml
similarity index 100%
rename from fixtures/observation/obs-401.xml
rename to fixtures/stu3/observation/obs-401.xml
diff --git a/fixtures/observation/obs-402.xml b/fixtures/stu3/observation/obs-402.xml
similarity index 100%
rename from fixtures/observation/obs-402.xml
rename to fixtures/stu3/observation/obs-402.xml
diff --git a/fixtures/observation/obs-403.xml b/fixtures/stu3/observation/obs-403.xml
similarity index 100%
rename from fixtures/observation/obs-403.xml
rename to fixtures/stu3/observation/obs-403.xml
diff --git a/fixtures/observation/obs-404.xml b/fixtures/stu3/observation/obs-404.xml
similarity index 100%
rename from fixtures/observation/obs-404.xml
rename to fixtures/stu3/observation/obs-404.xml
diff --git a/fixtures/observation/obs-405.xml b/fixtures/stu3/observation/obs-405.xml
similarity index 100%
rename from fixtures/observation/obs-405.xml
rename to fixtures/stu3/observation/obs-405.xml
diff --git a/fixtures/observation/obs-406.xml b/fixtures/stu3/observation/obs-406.xml
similarity index 100%
rename from fixtures/observation/obs-406.xml
rename to fixtures/stu3/observation/obs-406.xml
diff --git a/fixtures/observation/obs-407.xml b/fixtures/stu3/observation/obs-407.xml
similarity index 100%
rename from fixtures/observation/obs-407.xml
rename to fixtures/stu3/observation/obs-407.xml
diff --git a/fixtures/observation/obs-408.xml b/fixtures/stu3/observation/obs-408.xml
similarity index 100%
rename from fixtures/observation/obs-408.xml
rename to fixtures/stu3/observation/obs-408.xml
diff --git a/fixtures/observation/obs-uslab-example5.xml b/fixtures/stu3/observation/obs-uslab-example5.xml
similarity index 100%
rename from fixtures/observation/obs-uslab-example5.xml
rename to fixtures/stu3/observation/obs-uslab-example5.xml
diff --git a/fixtures/observation/observation-datawarehouse-create.xml b/fixtures/stu3/observation/observation-datawarehouse-create.xml
similarity index 100%
rename from fixtures/observation/observation-datawarehouse-create.xml
rename to fixtures/stu3/observation/observation-datawarehouse-create.xml
diff --git a/fixtures/observation/observation-familyhistory-create.xml b/fixtures/stu3/observation/observation-familyhistory-create.xml
similarity index 100%
rename from fixtures/observation/observation-familyhistory-create.xml
rename to fixtures/stu3/observation/observation-familyhistory-create.xml
diff --git a/fixtures/observation/observation-germline-create.xml b/fixtures/stu3/observation/observation-germline-create.xml
similarity index 100%
rename from fixtures/observation/observation-germline-create.xml
rename to fixtures/stu3/observation/observation-germline-create.xml
diff --git a/fixtures/observation/observation-register-create.xml b/fixtures/stu3/observation/observation-register-create.xml
similarity index 100%
rename from fixtures/observation/observation-register-create.xml
rename to fixtures/stu3/observation/observation-register-create.xml
diff --git a/fixtures/organization/org-uslab-example3.xml b/fixtures/stu3/organization/org-uslab-example3.xml
similarity index 100%
rename from fixtures/organization/org-uslab-example3.xml
rename to fixtures/stu3/organization/org-uslab-example3.xml
diff --git a/fixtures/patch/medicationrequest-simple.xml b/fixtures/stu3/patch/medicationrequest-simple.xml
similarity index 100%
rename from fixtures/patch/medicationrequest-simple.xml
rename to fixtures/stu3/patch/medicationrequest-simple.xml
diff --git a/fixtures/patient/patient-example-updated.xml b/fixtures/stu3/patient/patient-example-updated.xml
similarity index 100%
rename from fixtures/patient/patient-example-updated.xml
rename to fixtures/stu3/patient/patient-example-updated.xml
diff --git a/fixtures/patient/patient-example-us-extensions.xml b/fixtures/stu3/patient/patient-example-us-extensions.xml
similarity index 100%
rename from fixtures/patient/patient-example-us-extensions.xml
rename to fixtures/stu3/patient/patient-example-us-extensions.xml
diff --git a/fixtures/patient/patient-example.xml b/fixtures/stu3/patient/patient-example.xml
similarity index 100%
rename from fixtures/patient/patient-example.xml
rename to fixtures/stu3/patient/patient-example.xml
diff --git a/fixtures/patient/patient-familyhistory-create.xml b/fixtures/stu3/patient/patient-familyhistory-create.xml
similarity index 100%
rename from fixtures/patient/patient-familyhistory-create.xml
rename to fixtures/stu3/patient/patient-familyhistory-create.xml
diff --git a/fixtures/patient/patient-minimal.xml b/fixtures/stu3/patient/patient-minimal.xml
similarity index 100%
rename from fixtures/patient/patient-minimal.xml
rename to fixtures/stu3/patient/patient-minimal.xml
diff --git a/fixtures/patient/patient-register-create.xml b/fixtures/stu3/patient/patient-register-create.xml
similarity index 100%
rename from fixtures/patient/patient-register-create.xml
rename to fixtures/stu3/patient/patient-register-create.xml
diff --git a/fixtures/patient/patient-uslab-example1.xml b/fixtures/stu3/patient/patient-uslab-example1.xml
similarity index 100%
rename from fixtures/patient/patient-uslab-example1.xml
rename to fixtures/stu3/patient/patient-uslab-example1.xml
diff --git a/fixtures/practitioner/pract-uslab-example1.xml b/fixtures/stu3/practitioner/pract-uslab-example1.xml
similarity index 100%
rename from fixtures/practitioner/pract-uslab-example1.xml
rename to fixtures/stu3/practitioner/pract-uslab-example1.xml
diff --git a/fixtures/practitioner/pract-uslab-example3.xml b/fixtures/stu3/practitioner/pract-uslab-example3.xml
similarity index 100%
rename from fixtures/practitioner/pract-uslab-example3.xml
rename to fixtures/stu3/practitioner/pract-uslab-example3.xml
diff --git a/fixtures/practitioner/practitioner-register-create.xml b/fixtures/stu3/practitioner/practitioner-register-create.xml
similarity index 100%
rename from fixtures/practitioner/practitioner-register-create.xml
rename to fixtures/stu3/practitioner/practitioner-register-create.xml
diff --git a/fixtures/record/condition-example-f201-fever.xml b/fixtures/stu3/record/condition-example-f201-fever.xml
similarity index 100%
rename from fixtures/record/condition-example-f201-fever.xml
rename to fixtures/stu3/record/condition-example-f201-fever.xml
diff --git a/fixtures/record/condition-example-f205-infection.xml b/fixtures/stu3/record/condition-example-f205-infection.xml
similarity index 100%
rename from fixtures/record/condition-example-f205-infection.xml
rename to fixtures/stu3/record/condition-example-f205-infection.xml
diff --git a/fixtures/record/diagnosticreport-example-f201-brainct.xml b/fixtures/stu3/record/diagnosticreport-example-f201-brainct.xml
similarity index 100%
rename from fixtures/record/diagnosticreport-example-f201-brainct.xml
rename to fixtures/stu3/record/diagnosticreport-example-f201-brainct.xml
diff --git a/fixtures/record/encounter-example-f201-20130404.xml b/fixtures/stu3/record/encounter-example-f201-20130404.xml
similarity index 100%
rename from fixtures/record/encounter-example-f201-20130404.xml
rename to fixtures/stu3/record/encounter-example-f201-20130404.xml
diff --git a/fixtures/record/encounter-example-f202-20130128.xml b/fixtures/stu3/record/encounter-example-f202-20130128.xml
similarity index 100%
rename from fixtures/record/encounter-example-f202-20130128.xml
rename to fixtures/stu3/record/encounter-example-f202-20130128.xml
diff --git a/fixtures/record/observation-example-f202-temperature.xml b/fixtures/stu3/record/observation-example-f202-temperature.xml
similarity index 100%
rename from fixtures/record/observation-example-f202-temperature.xml
rename to fixtures/stu3/record/observation-example-f202-temperature.xml
diff --git a/fixtures/record/organization-example-f201-aumc.xml b/fixtures/stu3/record/organization-example-f201-aumc.xml
similarity index 100%
rename from fixtures/record/organization-example-f201-aumc.xml
rename to fixtures/stu3/record/organization-example-f201-aumc.xml
diff --git a/fixtures/record/organization-example-f203-bumc.xml b/fixtures/stu3/record/organization-example-f203-bumc.xml
similarity index 100%
rename from fixtures/record/organization-example-f203-bumc.xml
rename to fixtures/stu3/record/organization-example-f203-bumc.xml
diff --git a/fixtures/record/patient-example-f201-roel.xml b/fixtures/stu3/record/patient-example-f201-roel.xml
similarity index 100%
rename from fixtures/record/patient-example-f201-roel.xml
rename to fixtures/stu3/record/patient-example-f201-roel.xml
diff --git a/fixtures/record/practitioner-example-f201-ab.xml b/fixtures/stu3/record/practitioner-example-f201-ab.xml
similarity index 100%
rename from fixtures/record/practitioner-example-f201-ab.xml
rename to fixtures/stu3/record/practitioner-example-f201-ab.xml
diff --git a/fixtures/record/procedure-example-f201-tpf.xml b/fixtures/stu3/record/procedure-example-f201-tpf.xml
similarity index 100%
rename from fixtures/record/procedure-example-f201-tpf.xml
rename to fixtures/stu3/record/procedure-example-f201-tpf.xml
diff --git a/fixtures/scheduling/appointment-simple.xml b/fixtures/stu3/scheduling/appointment-simple.xml
similarity index 100%
rename from fixtures/scheduling/appointment-simple.xml
rename to fixtures/stu3/scheduling/appointment-simple.xml
diff --git a/fixtures/scheduling/appointmentresponse-patient-simple.xml b/fixtures/stu3/scheduling/appointmentresponse-patient-simple.xml
similarity index 100%
rename from fixtures/scheduling/appointmentresponse-patient-simple.xml
rename to fixtures/stu3/scheduling/appointmentresponse-patient-simple.xml
diff --git a/fixtures/scheduling/appointmentresponse-practitioner-simple.xml b/fixtures/stu3/scheduling/appointmentresponse-practitioner-simple.xml
similarity index 100%
rename from fixtures/scheduling/appointmentresponse-practitioner-simple.xml
rename to fixtures/stu3/scheduling/appointmentresponse-practitioner-simple.xml
diff --git a/fixtures/scheduling/practitioner-simple.xml b/fixtures/stu3/scheduling/practitioner-simple.xml
similarity index 100%
rename from fixtures/scheduling/practitioner-simple.xml
rename to fixtures/stu3/scheduling/practitioner-simple.xml
diff --git a/fixtures/scheduling/schedule-simple.xml b/fixtures/stu3/scheduling/schedule-simple.xml
similarity index 100%
rename from fixtures/scheduling/schedule-simple.xml
rename to fixtures/stu3/scheduling/schedule-simple.xml
diff --git a/fixtures/scheduling/slot-simple.xml b/fixtures/stu3/scheduling/slot-simple.xml
similarity index 100%
rename from fixtures/scheduling/slot-simple.xml
rename to fixtures/stu3/scheduling/slot-simple.xml
diff --git a/fixtures/sequence/sequence-register-create.xml b/fixtures/stu3/sequence/sequence-register-create.xml
similarity index 100%
rename from fixtures/sequence/sequence-register-create.xml
rename to fixtures/stu3/sequence/sequence-register-create.xml
diff --git a/fixtures/specimen/spec-100.xml b/fixtures/stu3/specimen/spec-100.xml
similarity index 100%
rename from fixtures/specimen/spec-100.xml
rename to fixtures/stu3/specimen/spec-100.xml
diff --git a/fixtures/specimen/spec-400.xml b/fixtures/stu3/specimen/spec-400.xml
similarity index 100%
rename from fixtures/specimen/spec-400.xml
rename to fixtures/stu3/specimen/spec-400.xml
diff --git a/fixtures/specimen/spec-uslab-example1.xml b/fixtures/stu3/specimen/spec-uslab-example1.xml
similarity index 100%
rename from fixtures/specimen/spec-uslab-example1.xml
rename to fixtures/stu3/specimen/spec-uslab-example1.xml
diff --git a/fixtures/specimen/specimen-familyhistory-create.xml b/fixtures/stu3/specimen/specimen-familyhistory-create.xml
similarity index 100%
rename from fixtures/specimen/specimen-familyhistory-create.xml
rename to fixtures/stu3/specimen/specimen-familyhistory-create.xml
diff --git a/fixtures/specimen/specimen-register-create.xml b/fixtures/stu3/specimen/specimen-register-create.xml
similarity index 100%
rename from fixtures/specimen/specimen-register-create.xml
rename to fixtures/stu3/specimen/specimen-register-create.xml
diff --git a/fixtures/terminology/codesystem-data-types.json b/fixtures/stu3/terminology/codesystem-data-types.json
similarity index 100%
rename from fixtures/terminology/codesystem-data-types.json
rename to fixtures/stu3/terminology/codesystem-data-types.json
diff --git a/fixtures/terminology/codesystem-resource-types.json b/fixtures/stu3/terminology/codesystem-resource-types.json
similarity index 100%
rename from fixtures/terminology/codesystem-resource-types.json
rename to fixtures/stu3/terminology/codesystem-resource-types.json
diff --git a/fixtures/terminology/codesystem-simple.xml b/fixtures/stu3/terminology/codesystem-simple.xml
similarity index 100%
rename from fixtures/terminology/codesystem-simple.xml
rename to fixtures/stu3/terminology/codesystem-simple.xml
diff --git a/fixtures/terminology/conceptmap-example.xml b/fixtures/stu3/terminology/conceptmap-example.xml
similarity index 100%
rename from fixtures/terminology/conceptmap-example.xml
rename to fixtures/stu3/terminology/conceptmap-example.xml
diff --git a/fixtures/terminology/v2-codesystem.json b/fixtures/stu3/terminology/v2-codesystem.json
similarity index 100%
rename from fixtures/terminology/v2-codesystem.json
rename to fixtures/stu3/terminology/v2-codesystem.json
diff --git a/fixtures/terminology/v2-valueset.json b/fixtures/stu3/terminology/v2-valueset.json
similarity index 100%
rename from fixtures/terminology/v2-valueset.json
rename to fixtures/stu3/terminology/v2-valueset.json
diff --git a/fixtures/terminology/valueset-defined-types.json b/fixtures/stu3/terminology/valueset-defined-types.json
similarity index 100%
rename from fixtures/terminology/valueset-defined-types.json
rename to fixtures/stu3/terminology/valueset-defined-types.json
diff --git a/fixtures/terminology/valueset-example.xml b/fixtures/stu3/terminology/valueset-example.xml
similarity index 100%
rename from fixtures/terminology/valueset-example.xml
rename to fixtures/stu3/terminology/valueset-example.xml
diff --git a/fixtures/uscore/CapabilityStatement-server.json b/fixtures/stu3/uscore/CapabilityStatement-server.json
similarity index 100%
rename from fixtures/uscore/CapabilityStatement-server.json
rename to fixtures/stu3/uscore/CapabilityStatement-server.json
diff --git a/fixtures/validation/observation.profile.xml b/fixtures/stu3/validation/observation.profile.xml
similarity index 100%
rename from fixtures/validation/observation.profile.xml
rename to fixtures/stu3/validation/observation.profile.xml
diff --git a/fixtures/validation/observations/observation-example.xml b/fixtures/stu3/validation/observations/observation-example.xml
similarity index 100%
rename from fixtures/validation/observations/observation-example.xml
rename to fixtures/stu3/validation/observations/observation-example.xml
diff --git a/lib/FHIR_structure.json b/lib/FHIR_structure.json
index 4a7ccd90..8cdf42b0 100644
--- a/lib/FHIR_structure.json
+++ b/lib/FHIR_structure.json
@@ -22,6 +22,8 @@
"name": "delete"
},{
"name": "history"
+ },{
+ "name": "patch"
}
]
},{
@@ -41,7 +43,7 @@
"name": "Whole System Interactions",
"children": [
{
- "name": "conformance-system"
+ "name": "capabilities-system"
},{
"name": "transaction-system"
},{
@@ -65,6 +67,46 @@
"name": "$meta-add"
},{
"name": "$meta-delete"
+ },{
+ "name": "$convert"
+ },{
+ "name": "$graph-ql"
+ },{
+ "name": "$graph"
+ },{
+ "name": "$apply"
+ },{
+ "name": "$data-requirements"
+ },{
+ "name": "$subset"
+ },{
+ "name": "$implements"
+ },{
+ "name": "$conforms"
+ },{
+ "name": "$versions"
+ },{
+ "name": "$submit"
+ },{
+ "name": "$submit-data"
+ },{
+ "name": "$collect-data"
+ },{
+ "name": "$care-gaps"
+ },{
+ "name": "$preferred-id"
+ },{
+ "name": "$stats"
+ },{
+ "name": "$lastn"
+ },{
+ "name": "$transform"
+ },{
+ "name": "$snapshot"
+ },{
+ "name": "$subsumes"
+ },{
+ "name": "$find-matches"
},{
"name": "$document"
},{
@@ -126,7 +168,7 @@
},{
"name": "graph definition"
},{
- "name": "data element"
+ "name": "example scenario"
}
]
},{
@@ -138,10 +180,10 @@
"name": "value set"
},{
"name": "concept map"
- },{
- "name": "expansion profile"
},{
"name": "naming system"
+ },{
+ "name": "terminology capabilities"
}
]
},{
@@ -166,6 +208,8 @@
"name": "document manifest"
},{
"name": "document reference"
+ },{
+ "name": "catalog entry"
}
]
},{
@@ -180,8 +224,6 @@
"name": "bundle"
},{
"name": "linkage"
- },{
- "name": "media"
},{
"name": "message header"
},{
@@ -220,6 +262,8 @@
"children": [
{
"name": "organization"
+ },{
+ "name": "organization affiliation"
},{
"name": "healthcare service"
},{
@@ -228,10 +272,10 @@
"name": "location"
},{
"name": "substance"
+ },{
+ "name": "biologically derived product"
}, {
"name": "device"
- },{
- "name": "device component"
},{
"name": "device metric"
}
@@ -251,9 +295,7 @@
},{
"name": "slot"
},{
- "name": "process request"
- },{
- "name": "process response"
+ "name": "verification result"
}
]
},{
@@ -302,21 +344,22 @@
"children": [
{
"name": "observation"
+ },{
+ "name": "media"
},{
"name": "diagnostic report"
},{
"name": "specimen"
},{
- "name": "body site"
+ "name": "body structure"
},{
"name": "imaging study"
- },{
- "name": "imaging manifest",
- "aka": ["imaging object selection"]
},{
"name": "questionnaire response"
},{
- "name": "sequence"
+ "name": "molecular sequence",
+ "aka": ["sequence"]
+
}
]
},{
@@ -336,6 +379,8 @@
"name": "medication"
},{
"name": "immunization"
+ },{
+ "name": "immunization evaluation"
},{
"name": "immunization recommendation"
}
@@ -350,10 +395,7 @@
},{
"name": "goal"
},{
- "name": "referral request"
- },{
- "name": "procedure request",
- "aka": ["diagnostic request", "diagnostic order"]
+ "name": "service request"
},{
"name": "nutrition order",
"aka": ["nutrition request"]
@@ -377,6 +419,8 @@
"aka": ["device use request"]
},{
"name": "device use statement"
+ },{
+ "name": "guidance response"
},{
"name": "supply request"
},{
@@ -394,9 +438,9 @@
{
"name": "coverage"
},{
- "name": "eligibility request"
+ "name": "coverage eligibility request"
},{
- "name": "eligibility response"
+ "name": "coverage eligibility response"
},{
"name": "enrollment request"
},{
@@ -410,6 +454,8 @@
"name": "claim"
},{
"name": "claim response"
+ },{
+ "name": "invoice"
}
]
},{
@@ -426,13 +472,17 @@
"aka": ["Other"],
"children": [
{
- "name": "explanation of benefit"
+ "name": "account"
+ },{
+ "name": "charge item"
+ },{
+ "name": "charge item definition"
},{
"name": "contract"
},{
- "name": "account"
+ "name": "explanation of benefit"
},{
- "name": "charge item"
+ "name": "insurance plan"
}
]
}
@@ -454,41 +504,79 @@
"name": "Definitional Artifacts",
"children": [
{
- "name": "questionnaire"
- },{
"name": "activity definition"
},{
- "name": "service definition",
- "aka": ["decision support service module"]
+ "name": "device definition"
+ },{
+ "name": "event definition"
+ },{
+ "name": "observation definition"
},{
"name": "plan definition"
+ },{
+ "name": "questionnaire"
+ },{
+ "name": "specimen definition"
}
]
},{
- "name": "Clinical Decision Support",
- "children": [
- {
- "name": "guidance response"
- }
- ]
- },{
- "name": "Quality Reporting",
- "aka": ["Clinical Reasoning"],
+ "name": "Quality Reporting & Testing",
+ "aka": ["Clinical Reasoning", "Quality Reporting"],
"children": [
{
"name": "measure"
},{
"name": "measure report"
+ },
+ {
+ "name": "test script"
+ },{
+ "name": "test report"
}
]
},{
- "name": "Testing",
- "aka": ["Implementation Support"],
+ "name": "Medication Definition",
"children": [
{
- "name": "test script"
- },{
- "name": "test report"
+ "name": "medicinal product"
+ }, {
+ "name": "medicinal product authorization"
+ },
+ {
+ "name": "medicinal product contraindication"
+ },
+ {
+ "name": "medicinal product indication"
+ },
+ {
+ "name": "medicinal product ingredient"
+ },
+ {
+ "name": "medicinal product interaction"
+ },
+ {
+ "name": "medicinal product manufactured"
+ },
+ {
+ "name": "medicinal product packaged"
+ },
+ {
+ "name": "medicinal product pharmaceutical"
+ },
+ {
+ "name": "medicinal product undesirable effect"
+ },
+ {
+ "name": "substance polymer"
+ },
+ {
+ "name": "substance reference information"
+ },
+ {
+ "name": "substance specification"
+ },
+ {
+ "name": "substance nucleic acid"
}
]
}
diff --git a/lib/FHIR_structure_r4.json b/lib/FHIR_structure_r4.json
new file mode 100644
index 00000000..1d918a5d
--- /dev/null
+++ b/lib/FHIR_structure_r4.json
@@ -0,0 +1,714 @@
+{
+ "name": "FHIR",
+ "children": [
+ {
+ "name": "OPERATIONS",
+ "children": [
+ {
+ "name": "RESTful API",
+ "children": [
+ {
+ "name": "Instance Level Interactions",
+ "children": [
+ {
+ "name": "read"
+ },{
+ "name": "vread"
+ },{
+ "name": "update"
+ },{
+ "name": "conditional-update"
+ },{
+ "name": "delete"
+ },{
+ "name": "history"
+ },{
+ "name": "patch"
+ }
+ ]
+ },{
+ "name": "Type Level Interactions",
+ "children": [
+ {
+ "name": "create"
+ },{
+ "name": "conditional-create"
+ },{
+ "name": "search"
+ },{
+ "name": "history-type"
+ }
+ ]
+ },{
+ "name": "Whole System Interactions",
+ "children": [
+ {
+ "name": "capabilities-system"
+ },{
+ "name": "transaction-system"
+ },{
+ "name": "history-system"
+ },{
+ "name": "search-system"
+ },{
+ "name": "batch-system"
+ }
+ ]
+ }
+ ]
+ },{
+ "name": "Extended Operations",
+ "children": [
+ {
+ "name": "$validate"
+ },{
+ "name": "$meta"
+ },{
+ "name": "$meta-add"
+ },{
+ "name": "$meta-delete"
+ },{
+ "name": "$convert"
+ },{
+ "name": "$graph-ql"
+ },{
+ "name": "$graph"
+ },{
+ "name": "$apply"
+ },{
+ "name": "$data-requirements"
+ },{
+ "name": "$subset"
+ },{
+ "name": "$implements"
+ },{
+ "name": "$conforms"
+ },{
+ "name": "$versions"
+ },{
+ "name": "$submit"
+ },{
+ "name": "$submit-data"
+ },{
+ "name": "$collect-data"
+ },{
+ "name": "$care-gaps"
+ },{
+ "name": "$preferred-id"
+ },{
+ "name": "$stats"
+ },{
+ "name": "$lastn"
+ },{
+ "name": "$transform"
+ },{
+ "name": "$snapshot"
+ },{
+ "name": "$subsumes"
+ },{
+ "name": "$find-matches"
+ },{
+ "name": "$document"
+ },{
+ "name": "$translate"
+ },{
+ "name": "$closure"
+ },{
+ "name": "$everything"
+ },{
+ "name": "$find"
+ },{
+ "name": "$process-message"
+ },{
+ "name": "$populate"
+ },{
+ "name": "$questionnaire"
+ },{
+ "name": "$expand"
+ },{
+ "name": "$lookup"
+ },{
+ "name": "$validate-code"
+ },{
+ "name": "$guidance"
+ },{
+ "name": "$guidance-requirements"
+ },{
+ "name": "$match"
+ }
+ ]
+ }
+ ]
+ },{
+ "name": "RESOURCES",
+ "children": [
+ {
+ "name": "Foundation",
+ "children": [
+ {
+ "name": "Conformance",
+ "children": [
+ {
+ "name": "capability statement",
+ "aka": ["conformance"]
+ },{
+ "name": "structure definition"
+ },{
+ "name": "implementation guide"
+ },{
+ "name": "search parameter"
+ },{
+ "name": "message definition"
+ },{
+ "name": "operation definition"
+ },{
+ "name": "compartment definition"
+ },{
+ "name": "structure map"
+ },{
+ "name": "graph definition"
+ },{
+ "name": "example scenario"
+ }
+ ]
+ },{
+ "name": "Terminology",
+ "children": [
+ {
+ "name": "code system"
+ },{
+ "name": "value set"
+ },{
+ "name": "concept map"
+ },{
+ "name": "naming system"
+ },{
+ "name": "terminology capabilities"
+ }
+ ]
+ },{
+ "name": "Security",
+ "aka": ["Security & Privacy"],
+ "children": [
+ {
+ "name": "provenance"
+ },{
+ "name": "audit event"
+ },{
+ "name": "consent"
+ }
+ ]
+ },{
+ "name": "Documents",
+ "aka": ["Documents & Questionnaires"],
+ "children": [
+ {
+ "name": "composition"
+ },{
+ "name": "document manifest"
+ },{
+ "name": "document reference"
+ },{
+ "name": "catalog entry"
+ }
+ ]
+ },{
+ "name": "Other",
+ "aka": ["Exchange", "Structure", "Structures"],
+ "children": [
+ {
+ "name": "basic"
+ },{
+ "name": "binary"
+ },{
+ "name": "bundle"
+ },{
+ "name": "linkage"
+ },{
+ "name": "message header"
+ },{
+ "name": "operation outcome"
+ },{
+ "name": "parameters"
+ },{
+ "name": "subscription"
+ }
+ ]
+ }
+ ]
+ },{
+ "name": "Base",
+ "aka": ["Administration", "Administrative", "Identification"],
+ "children": [
+ {
+ "name": "Individuals",
+ "children": [
+ {
+ "name": "patient"
+ },{
+ "name": "practitioner"
+ },{
+ "name": "practitioner role"
+ },{
+ "name": "related person"
+ },{
+ "name": "person"
+ },{
+ "name": "group"
+ }
+ ]
+ },{
+ "name": "Entities",
+ "children": [
+ {
+ "name": "organization"
+ },{
+ "name": "organization affiliation"
+ },{
+ "name": "healthcare service"
+ },{
+ "name": "endpoint"
+ },{
+ "name": "location"
+ },{
+ "name": "substance"
+ },{
+ "name": "biologically derived product"
+ }, {
+ "name": "device"
+ },{
+ "name": "device metric"
+ }
+ ]
+ },{
+ "name": "Workflow",
+ "aka": ["Scheduling", "Events", "Order Management"],
+ "children": [
+ {
+ "name": "task"
+ },{
+ "name": "appointment"
+ },{
+ "name": "appointment response"
+ },{
+ "name": "schedule"
+ },{
+ "name": "slot"
+ },{
+ "name": "verification result"
+ }
+ ]
+ },{
+ "name": "Management",
+ "aka": ["Patient Management"],
+ "children": [
+ {
+ "name": "encounter"
+ },{
+ "name": "episode of care"
+ },{
+ "name": "flag"
+ },{
+ "name": "list"
+ },{
+ "name": "library"
+ }
+ ]
+ }
+ ]
+ },{
+ "name": "Clinical",
+ "children": [
+ {
+ "name": "Summary",
+ "aka": ["General Clinical"],
+ "children": [
+ {
+ "name": "allergy intolerance"
+ },{
+ "name": "adverse event"
+ },{
+ "name": "condition"
+ },{
+ "name": "procedure"
+ },{
+ "name": "family member history"
+ },{
+ "name": "clinical impression"
+ },{
+ "name": "detected issue"
+ }
+ ]
+ },{
+ "name": "Diagnostics",
+ "children": [
+ {
+ "name": "observation"
+ },{
+ "name": "media"
+ },{
+ "name": "diagnostic report"
+ },{
+ "name": "specimen"
+ },{
+ "name": "body structure"
+ },{
+ "name": "imaging study"
+ },{
+ "name": "questionnaire response"
+ },{
+ "name": "molecular sequence",
+ "aka": ["sequence"]
+
+ }
+ ]
+ },{
+ "name": "Medications",
+ "aka": ["Medication & Immunization"],
+ "children": [
+ {
+ "name": "medication request",
+ "aka": ["medication order"]
+ },{
+ "name": "medication administration"
+ },{
+ "name": "medication dispense"
+ },{
+ "name": "medication statement"
+ },{
+ "name": "medication"
+ },{
+ "name": "medication knowledge"
+ },{
+ "name": "immunization"
+ },{
+ "name": "immunization evaluation"
+ },{
+ "name": "immunization recommendation"
+ }
+ ]
+ },{
+ "name": "Care Provision",
+ "children": [
+ {
+ "name": "care plan"
+ },{
+ "name": "care team"
+ },{
+ "name": "goal"
+ },{
+ "name": "service request"
+ },{
+ "name": "nutrition order",
+ "aka": ["nutrition request"]
+ },{
+ "name": "vision prescription"
+ },{
+ "name": "risk assessment"
+ },{
+ "name": "request group"
+ }
+ ]
+ },{
+ "name": "Request & Response",
+ "children": [
+ {
+ "name": "communication"
+ },{
+ "name": "communication request"
+ },{
+ "name": "device request",
+ "aka": ["device use request"]
+ },{
+ "name": "device use statement"
+ },{
+ "name": "guidance response"
+ },{
+ "name": "supply request"
+ },{
+ "name": "supply delivery"
+ }
+ ]
+ }
+ ]
+ },{
+ "name": "Financial",
+ "children": [
+ {
+ "name": "Support",
+ "children": [
+ {
+ "name": "coverage"
+ },{
+ "name": "coverage eligibility request"
+ },{
+ "name": "coverage eligibility response"
+ },{
+ "name": "enrollment request"
+ },{
+ "name": "enrollment response"
+ }
+ ]
+ },{
+ "name": "Billing",
+ "children": [
+ {
+ "name": "claim"
+ },{
+ "name": "claim response"
+ },{
+ "name": "invoice"
+ }
+ ]
+ },{
+ "name": "Payment",
+ "children": [
+ {
+ "name": "payment notice"
+ },{
+ "name": "payment reconciliation"
+ }
+ ]
+ },{
+ "name": "General",
+ "aka": ["Other"],
+ "children": [
+ {
+ "name": "account"
+ },{
+ "name": "charge item"
+ },{
+ "name": "charge item definition"
+ },{
+ "name": "contract"
+ },{
+ "name": "explanation of benefit"
+ },{
+ "name": "insurance plan"
+ }
+ ]
+ }
+ ]
+ },{
+ "name": "Specialized",
+ "children": [
+ {
+ "name": "Public Health & Research",
+ "aka": ["Research"],
+ "children": [
+ {
+ "name": "research study"
+ },{
+ "name": "research subject"
+ }
+ ]
+ },{
+ "name": "Definitional Artifacts",
+ "children": [
+ {
+ "name": "activity definition"
+ },{
+ "name": "device definition"
+ },{
+ "name": "event definition"
+ },{
+ "name": "observation definition"
+ },{
+ "name": "plan definition"
+ },{
+ "name": "questionnaire"
+ },{
+ "name": "specimen definition"
+ }
+ ]
+ },{
+ "name": "Evidence-Based Medicine",
+ "children": [
+ {
+ "name": "research definition"
+ },{
+ "name": "research element definition"
+ },{
+ "name": "evidence"
+ },{
+ "name": "evidence variable"
+ },{
+ "name": "effect evidence synthesis"
+ },{
+ "name": "risk evidence synthesis"
+ }
+ ]
+ },{
+ "name": "Quality Reporting & Testing",
+ "aka": ["Clinical Reasoning", "Quality Reporting"],
+ "children": [
+ {
+ "name": "measure"
+ },{
+ "name": "measure report"
+ },
+ {
+ "name": "test script"
+ },{
+ "name": "test report"
+ }
+ ]
+ },{
+ "name": "Medication Definition",
+ "children": [
+ {
+ "name": "medicinal product"
+ }, {
+ "name": "medicinal product authorization"
+ },
+ {
+ "name": "medicinal product contraindication"
+ },
+ {
+ "name": "medicinal product indication"
+ },
+ {
+ "name": "medicinal product ingredient"
+ },
+ {
+ "name": "medicinal product interaction"
+ },
+ {
+ "name": "medicinal product manufactured"
+ },
+ {
+ "name": "medicinal product packaged"
+ },
+ {
+ "name": "medicinal product pharmaceutical"
+ },
+ {
+ "name": "medicinal product undesirable effect"
+ },
+ {
+ "name": "substance polymer"
+ },
+ {
+ "name": "substance reference information"
+ },
+ {
+ "name": "substance specification"
+ },
+ {
+ "name": "substancenucleicacid"
+ },
+ {
+ "name": "substance protein"
+ },
+ {
+ "name": "substance source material"
+ },
+ {
+ "name": "substance nucleic acid"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },{
+ "name": "FORMAT",
+ "children": [
+ {
+ "name": "XML"
+ },{
+ "name": "JSON"
+ }
+ ]
+ },{
+ "name": "SECURITY",
+ "children": [
+ {
+ "name": "General Security",
+ "children": [
+ {
+ "name": "Authorization/Access Control"
+ },{
+ "name": "OAuth2"
+ },{
+ "name": "Audit Logging"
+ },{
+ "name": "Digital Signatures"
+ }
+ ]
+ },{
+ "name": "Security Labels",
+ "children": [
+ {
+ "name": "Confidentiality Codes"
+ },{
+ "name": "Celebrity / VIP"
+ },{
+ "name": "Staff"
+ },{
+ "name": "Keep information from patient"
+ },{
+ "name": "Contact/Employment Details Confidential"
+ },{
+ "name": "Diagnosis-related confidentiality"
+ },{
+ "name": "Author consent needed"
+ },{
+ "name": "Delete After Use"
+ },{
+ "name": "Do Not Reuse"
+ },{
+ "name": "Break The Glass"
+ },{
+ "name": "Confidentiality Classification"
+ },{
+ "name": "Sensitivity Category"
+ },{
+ "name": "Compartment Category"
+ },{
+ "name": "Integrity Category"
+ },{
+ "name": "Handling Caveat"
+ },{
+ "name": "US Privacy Law"
+ }
+ ]
+ }
+ ]
+ },{
+ "name": "MESSAGING",
+ "children": [
+ {
+ "name": "Consequence"
+ },{
+ "name": "Currency"
+ },{
+ "name": "Notification"
+ }
+ ]
+ },{
+ "name": "DOCUMENTS",
+ "children": []
+ },{
+ "name": "PROFILES",
+ "children": [
+ {
+ "name": "validate-profile"
+ }
+ ]
+ },{
+ "name": "EXTENSIONS",
+ "children": [
+ {
+ "name": "extensions"
+ },{
+ "name": "modifying extensions"
+ },{
+ "name": "complex extensions"
+ },{
+ "name": "primitive extensions"
+ }
+ ]
+ }
+ ]
+}
diff --git a/lib/data/fhir_structure.rb b/lib/data/fhir_structure.rb
index 7f7aca77..8e2f43bc 100644
--- a/lib/data/fhir_structure.rb
+++ b/lib/data/fhir_structure.rb
@@ -1,6 +1,6 @@
module Crucible
class FHIRStructure
- def self.get(fhir_version = :stu3)
+ def self.get(fhir_version = :r4)
root = File.expand_path File.join('..','..'), File.dirname(File.absolute_path(__FILE__))
JSON.parse(File.read(File.join(root, 'lib', "FHIR_structure_#{fhir_version.to_s}.json")))
end
diff --git a/lib/data/resources.rb b/lib/data/resources.rb
index 51ee9742..16ff86d1 100644
--- a/lib/data/resources.rb
+++ b/lib/data/resources.rb
@@ -11,63 +11,63 @@ def initialize(fhir_version = nil)
end
def example_patient
- load_fixture('patient/patient-example',:xml)
+ load_fixture('stu3/patient/patient-example',:xml)
end
def example_patient_us
- load_fixture('patient/patient-example-us-extensions',:xml)
+ load_fixture('stu3/patient/patient-example-us-extensions',:xml)
end
def minimal_patient
- load_fixture('patient/patient-minimal',:xml)
+ load_fixture('stu3/patient/patient-minimal',:xml)
end
def example_patient_record_201
- load_fixture('record/patient-example-f201-roel',:xml)
+ load_fixture('stu3/record/patient-example-f201-roel',:xml)
end
def example_patient_record_condition_201
- load_fixture('record/condition-example-f201-fever',:xml)
+ load_fixture('stu3/record/condition-example-f201-fever',:xml)
end
def example_patient_record_condition_205
- load_fixture('record/condition-example-f205-infection',:xml)
+ load_fixture('stu3/record/condition-example-f205-infection',:xml)
end
def example_patient_record_diagnosticreport_201
- load_fixture('record/diagnosticreport-example-f201-brainct',:xml)
+ load_fixture('stu3/record/diagnosticreport-example-f201-brainct',:xml)
end
def example_patient_record_encounter_201
- load_fixture('record/encounter-example-f201-20130404',:xml)
+ load_fixture('stu3/record/encounter-example-f201-20130404',:xml)
end
def example_patient_record_encounter_202
- load_fixture('record/encounter-example-f202-20130128',:xml)
+ load_fixture('stu3/record/encounter-example-f202-20130128',:xml)
end
def example_patient_record_observation_202
- load_fixture('record/observation-example-f202-temperature',:xml)
+ load_fixture('stu3/record/observation-example-f202-temperature',:xml)
end
def example_patient_record_organization_201
- load_fixture('record/organization-example-f201-aumc',:xml)
+ load_fixture('stu3/record/organization-example-f201-aumc',:xml)
end
def example_patient_record_organization_203
- load_fixture('record/organization-example-f203-bumc',:xml)
+ load_fixture('stu3/record/organization-example-f203-bumc',:xml)
end
def example_patient_record_practitioner_201
- load_fixture('record/practitioner-example-f201-ab',:xml)
+ load_fixture('stu3/record/practitioner-example-f201-ab',:xml)
end
def example_patient_record_procedure_201
- load_fixture('record/procedure-example-f201-tpf',:xml)
+ load_fixture('stu3/record/procedure-example-f201-tpf',:xml)
end
def track3_profile
- load_fixture('validation/observation.profile',:xml)
+ load_fixture('stu3/validation/observation.profile',:xml)
end
def track3_observations
@@ -83,148 +83,148 @@ def track3_observations
# ------------------------------ CLAIM TEST TRACK ------------------------------
def simple_claim
- load_fixture('financial/claim-example',:xml)
+ load_fixture('stu3/financial/claim-example',:xml)
end
def average_claim
- load_fixture('financial/claim-example-oral-average',:xml)
+ load_fixture('stu3/financial/claim-example-oral-average',:xml)
end
def complex_claim
- load_fixture('financial/claim-example-oral-orthoplan',:xml)
+ load_fixture('stu3/financial/claim-example-oral-orthoplan',:xml)
end
# ------------------------------ SCHEDULING TEST TRACK ------------------------------
def scheduling_appointment
- load_fixture('scheduling/appointment-simple',:xml)
+ load_fixture('stu3/scheduling/appointment-simple',:xml)
end
def scheduling_response_patient
- load_fixture('scheduling/appointmentresponse-patient-simple',:xml)
+ load_fixture('stu3/scheduling/appointmentresponse-patient-simple',:xml)
end
def scheduling_response_practitioner
- load_fixture('scheduling/appointmentresponse-practitioner-simple',:xml)
+ load_fixture('stu3/scheduling/appointmentresponse-practitioner-simple',:xml)
end
def scheduling_practitioner
- load_fixture('scheduling/practitioner-simple',:xml)
+ load_fixture('stu3/scheduling/practitioner-simple',:xml)
end
def scheduling_schedule
- load_fixture('scheduling/schedule-simple',:xml)
+ load_fixture('stu3/scheduling/schedule-simple',:xml)
end
def scheduling_slot
- load_fixture('scheduling/slot-simple',:xml)
+ load_fixture('stu3/scheduling/slot-simple',:xml)
end
# ------------------------------ US CORE TESTS ------------------------------
def uscore_conformance
- load_fixture('uscore/CapabilityStatement-server',:json)
+ load_fixture('stu3/uscore/CapabilityStatement-server',:json)
end
# ------------------------------ TERMINOLOGY TRACK TESTS ------------------------------
def codesystem_simple
- load_fixture('terminology/codesystem-simple',:xml)
+ load_fixture('stu3/terminology/codesystem-simple',:xml)
end
def valueset_simple
- load_fixture('terminology/valueset-example',:xml)
+ load_fixture('stu3/terminology/valueset-example',:xml)
end
def conceptmap_simple
- load_fixture('terminology/conceptmap-example',:xml)
+ load_fixture('stu3/terminology/conceptmap-example',:xml)
end
# ------------------------------ PATCH TRACK TESTS ------------------------------
def medicationorder_simple
- load_fixture('patch/medicationrequest-simple',:xml)
+ load_fixture('stu3/patch/medicationrequest-simple',:xml)
end
# ------------------------------ CONNECTATHONS -----------------------------
def patient_register
- load_fixture('patient/patient-register-create',:xml)
+ load_fixture('stu3/patient/patient-register-create',:xml)
end
def practitioner_register
- load_fixture('practitioner/practitioner-register-create', :xml)
+ load_fixture('stu3/practitioner/practitioner-register-create', :xml)
end
def eligibility_request
- load_fixture('financial/eligibilityrequest-example', :xml)
+ load_fixture('stu3/financial/eligibilityrequest-example', :xml)
end
def sequence_register
- load_fixture('sequence/sequence-register-create', :xml)
+ load_fixture('stu3/sequence/sequence-register-create', :xml)
end
def specimen_register
- load_fixture('specimen/specimen-register-create', :xml)
+ load_fixture('stu3/specimen/specimen-register-create', :xml)
end
def observation_register
- load_fixture('observation/observation-register-create', :xml)
+ load_fixture('stu3/observation/observation-register-create', :xml)
end
def patient_familyhistory
- load_fixture('patient/patient-familyhistory-create', :xml)
+ load_fixture('stu3/patient/patient-familyhistory-create', :xml)
end
def observation_familyhistory
- load_fixture('observation/observation-familyhistory-create', :xml)
+ load_fixture('stu3/observation/observation-familyhistory-create', :xml)
end
def family_member_history
- load_fixture('family_member_history/familymemberhistory-familyhistory-create', :xml)
+ load_fixture('stu3/family_member_history/familymemberhistory-familyhistory-create', :xml)
end
def specimen_familyhistory
- load_fixture('specimen/specimen-familyhistory-create', :xml)
+ load_fixture('stu3/specimen/specimen-familyhistory-create', :xml)
end
def diagnostic_familyhistory
- load_fixture('diagnostic_report/diagnosticreport-familyhistory-create', :xml)
+ load_fixture('stu3/diagnostic_report/diagnosticreport-familyhistory-create', :xml)
end
def observation_datawarehouse
- load_fixture('observation/observation-datawarehouse-create', :xml)
+ load_fixture('stu3/observation/observation-datawarehouse-create', :xml)
end
def diagnosticreport_hltyping
- load_fixture('diagnostic_report/diagnosticreport-hlatyping-create', :xml)
+ load_fixture('stu3/diagnostic_report/diagnosticreport-hlatyping-create', :xml)
end
def diagnosticreport_pathology
- load_fixture('diagnostic_report/diagnosticreport-pathologyreport-create', :xml)
+ load_fixture('stu3/diagnostic_report/diagnosticreport-pathologyreport-create', :xml)
end
def patient_uslab1
- load_fixture('patient/patient-uslab-example1', :xml)
+ load_fixture('stu3/patient/patient-uslab-example1', :xml)
end
def practitioner_uslab1
- load_fixture('practitioner/pract-uslab-example1', :xml)
+ load_fixture('stu3/practitioner/pract-uslab-example1', :xml)
end
def practitioner_uslab3
- load_fixture('practitioner/pract-uslab-example3', :xml)
+ load_fixture('stu3/practitioner/pract-uslab-example3', :xml)
end
def organization_uslab3
- load_fixture('organization/org-uslab-example3', :xml)
+ load_fixture('stu3/organization/org-uslab-example3', :xml)
end
def specimen_100
- load_fixture('specimen/spec-100', :xml)
+ load_fixture('stu3/specimen/spec-100', :xml)
end
def specimen_400
- load_fixture('specimen/spec-400', :xml)
+ load_fixture('stu3/specimen/spec-400', :xml)
end
def tag_metadata(resource)
diff --git a/lib/resource_generator.rb b/lib/resource_generator.rb
index e36fd4d4..eb6cac1f 100644
--- a/lib/resource_generator.rb
+++ b/lib/resource_generator.rb
@@ -8,13 +8,14 @@ class ResourceGenerator
EMBEDDED_LOOP_GUARD = 10
#
# Generate a FHIR resource for the given class `klass`
- # If `embedded` is greater than zero, all embedded children will also
+ # If `embedded` is greater than zero, alledded children will also
# be generated.
#
def self.generate(klass,embedded=0)
resource = klass.new
namespace = 'FHIR'
namespace = 'FHIR::DSTU2' if klass.name.starts_with? 'FHIR::DSTU2'
+ namespace = 'FHIR::STU3' if klass.name.starts_with? 'FHIR::STU3'
Time.zone = 'UTC'
set_fields!(resource, namespace, embedded)
resource.id=nil if resource.respond_to?(:id=)
@@ -65,9 +66,15 @@ def self.set_fields!(resource, namespace, embedded=0)
gen = SecureRandom.base64
end
elsif type == 'xhtml'
- gen = "
#{SecureRandom.base64}
"
+ gen = "#{SecureRandom.base64}
"
elsif type == 'uri'
gen = "http://projectcrucible.org/#{SecureRandom.base64}"
+ elsif type == 'uuid'
+ gen = "urn:uuid:#{SecureRandom.uuid}"
+ elsif type == 'url'
+ gen = "http://projectcrucible.org/#{SecureRandom.base64}"
+ elsif type == 'canonical'
+ gen = "http://projectcrucible.org/#{SecureRandom.base64}|1.0"
elsif type == 'dateTime' || type == 'instant'
gen = DateTime.now.strftime("%Y-%m-%dT%T.%LZ")
elsif type == 'date'
@@ -179,13 +186,13 @@ def self.minimal_patient(identifier='0',name='Name', namespace = FHIR)
def self.minimal_observation(system='http://loinc.org',code='8302-2',value=170,units='cm',patientId=nil, namespace = FHIR)
resource = namespace.const_get(:Observation).new
resource.status = 'final'
- resource.code = minimal_codeableconcept(system,code)
+ resource.code = minimal_codeableconcept(system,code, namespace)
if patientId
ref = namespace.const_get(:Reference).new
ref.reference = "Patient/#{patientId}"
resource.subject = ref
end
- resource.valueQuantity = minimal_quantity(value,units)
+ resource.valueQuantity = minimal_quantity(value,units, namespace)
tag_metadata(resource)
end
@@ -198,7 +205,7 @@ def self.minimal_condition(system='http://snomed.info/sct',code='414915002',pati
else
resource.subject.display = 'Patient'
end
- resource.code = minimal_codeableconcept(system,code)
+ resource.code = minimal_codeableconcept(system,code, namespace)
resource.verificationStatus = 'confirmed'
tag_metadata(resource)
end
@@ -263,9 +270,9 @@ def self.minimal_quantity(value=170,units='cm', namespace = FHIR)
def self.minimal_animal(namespace = FHIR)
animal = namespace.const_get(:Patient).const_get(:Animal).new
- animal.species = minimal_codeableconcept('http://hl7.org/fhir/animal-species','canislf') # dog
- animal.breed = minimal_codeableconcept('http://hl7.org/fhir/animal-breed','gret') # golden retriever
- animal.genderStatus = minimal_codeableconcept('http://hl7.org/fhir/animal-genderstatus','intact') # intact
+ animal.species = minimal_codeableconcept('http://hl7.org/fhir/animal-species','canislf', namespaec) # dog
+ animal.breed = minimal_codeableconcept('http://hl7.org/fhir/animal-breed','gret', namespaec) # golden retriever
+ animal.genderStatus = minimal_codeableconcept('http://hl7.org/fhir/animal-genderstatus','intact', namespaec) # intact
animal
end
@@ -282,7 +289,6 @@ def self.tag_metadata(resource, namespace = FHIR)
def self.apply_invariants!(resource)
case resource
- ## STU3
when FHIR::ActivityDefinition
resource.quantity.comparator = nil unless resource.quantity.nil?
when FHIR::Age
@@ -293,18 +299,15 @@ def self.apply_invariants!(resource)
resource.comparator = nil
when FHIR::AllergyIntolerance
resource.clinicalStatus = nil if resource.verificationStatus=='entered-in-error'
+ when FHIR::Binary
+ resource. contentType = MIME::Types.to_a.sample.content_type
when FHIR::Duration
resource.system = 'http://unitsofmeasure.org'
resource.code = 'mo'
resource.unit = nil
resource.comparator = nil
- when FHIR::Money
- resource.system = 'urn:iso:std:iso:4217'
- resource.code = 'USD'
- resource.unit = nil
- resource.comparator = nil
when FHIR::Appointment
- resource.reason = [ minimal_codeableconcept('http://snomed.info/sct','219006') ] # drinker of alcohol
+ resource.reasonCode = [ minimal_codeableconcept('http://snomed.info/sct','219006') ] # drinker of alcohol
resource.participant.each{|p| p.type=[ minimal_codeableconcept('http://hl7.org/fhir/participant-type','emergency') ] }
when FHIR::AppointmentResponse
resource.participantType = [ minimal_codeableconcept('http://hl7.org/fhir/participant-type','emergency') ]
@@ -347,40 +350,30 @@ def self.apply_invariants!(resource)
when FHIR::CodeSystem
resource.concept.each do |c|
c.concept.each do |d|
- d.property.each do |p|
- p.valueCode = nil
- p.valueCoding = nil
- p.valueString = SecureRandom.base64
- p.valueInteger = nil
- p.valueBoolean = nil
- p.valueDateTime = nil
- end
- end
- end
- when FHIR::CapabilityStatement
- resource.kind = 'instance'
- resource.rest.each do |r|
- r.resource.each do |res|
- res.interaction.each{|i|i.code = ['read', 'vread', 'update', 'delete', 'history-instance', 'history-type', 'create', 'search-type'].sample}
+ d.property = []
+ # d.property.each do |p|
+ # p.valueCode = nil
+ # p.valueCoding = nil
+ # p.valueString = SecureRandom.base64
+ # p.valueInteger = nil
+ # p.valueBoolean = nil
+ # p.valueDateTime = nil
+ # end
end
- r.interaction.each{|i|i.code = ['transaction', 'batch', 'search-system', 'history-system'].sample }
- end
- resource.messaging.each do |m|
- m.supportedMessage = [] if m.event.length > 0
end
when FHIR::Claim
resource.item.each do |item|
- item.category = minimal_codeableconcept('http://hl7.org/fhir/benefit-subcategory','35')
- item.quantity.comparator = nil unless item.quantity.nil?
- item.detail.each do |detail|
- detail.category = item.category
- detail.quantity.comparator = nil unless detail.quantity.nil?
- detail.subDetail.each do |sub|
- sub.category = item.category
- sub.quantity.comparator = nil unless sub.quantity.nil?
- sub.service = minimal_codeableconcept('http://hl7.org/fhir/ex-USCLS','1205')
- end
- end
+ # item.category = minimal_codeableconcept('http://hl7.org/fhir/benefit-subcategory','35')
+ # item.quantity.comparator = nil unless item.quantity.nil?
+ # item.detail.each do |detail|
+ # detail.category = item.category
+ # detail.quantity.comparator = nil unless detail.quantity.nil?
+ # detail.subDetail.each do |sub|
+ # sub.category = item.category
+ # sub.quantity.comparator = nil unless sub.quantity.nil?
+ # sub.service = minimal_codeableconcept('http://hl7.org/fhir/ex-USCLS','1205')
+ # end
+ # end
end
when FHIR::ClaimResponse
resource.item.each do |item|
@@ -402,7 +395,6 @@ def self.apply_invariants!(resource)
resource.payload = nil
when FHIR::CommunicationRequest
resource.payload = nil
- resource.requester.onBehalfOf = nil unless resource.requester.nil?
when FHIR::Composition
resource.attester.each {|a| a.mode = ['professional']}
resource.section.each do |section|
@@ -413,12 +405,12 @@ def self.apply_invariants!(resource)
end
end
when FHIR::ConceptMap
- if(resource.sourceUri.nil? && resource.sourceReference.nil?)
- resource.sourceReference = textonly_reference('ValueSet')
- end
- if(resource.targetUri.nil? && resource.targetReference.nil?)
- resource.targetReference = textonly_reference('ValueSet')
- end
+ # if(resource.sourceUri.nil? && resource.sourceReference.nil?)
+ # resource.sourceReference = textonly_reference('ValueSet')
+ # end
+ # if(resource.targetUri.nil? && resource.targetReference.nil?)
+ # resource.targetReference = textonly_reference('ValueSet')
+ # end
when FHIR::Condition
if resource.onsetAge
resource.onsetAge.system = 'http://unitsofmeasure.org'
@@ -426,7 +418,7 @@ def self.apply_invariants!(resource)
resource.onsetAge.unit = 'yr'
resource.onsetAge.comparator = nil
end
- resource.clinicalStatus = ['inactive', 'resolved','remission'].sample unless resource.abatement.nil?
+ # resource.clinicalStatus = ['inactive', 'resolved','remission'].sample unless resource.abatement.nil?
if resource.abatementAge
resource.abatementAge.system = 'http://unitsofmeasure.org'
resource.abatementAge.code = 'a'
@@ -441,80 +433,21 @@ def self.apply_invariants!(resource)
end
end
when FHIR::CapabilityStatement
- resource.fhirVersion = 'STU3'
+ resource.fhirVersion = '4.0.0'
resource.format = ['xml','json']
- if resource.kind == 'capability'
- resource.implementation = nil
- elsif resource.kind == 'requirements'
- resource.implementation = nil
- resource.software = nil
- end
- resource.messaging.each{|m| m.endpoint = nil} if resource.kind != 'instance'
- when FHIR::Contract
- resource.agent.each do |agent|
- agent.actor = textonly_reference('Patient')
- end
- resource.valuedItem.each do |item|
- if item.unitPrice
- item.unitPrice.system = 'urn:iso:std:iso:4217'
- item.unitPrice.code = 'USD'
- item.unitPrice.unit = nil
- item.unitPrice.comparator = nil
- end
- if item.net
- item.net.system = 'urn:iso:std:iso:4217'
- item.net.code = 'USD'
- item.net.unit = nil
- item.net.comparator = nil
- end
- item.quantity.comparator = nil unless item.quantity.nil?
- end
- resource.term.each do |term|
- term.agent.each do |agent|
- agent.actor = textonly_reference('Organization')
- end
- term.group.each do |group|
- group.agent.each do |agent|
- agent.actor = textonly_reference('Organization')
- end
- end
- term.valuedItem.each do |item|
- if item.unitPrice
- item.unitPrice.system = 'urn:iso:std:iso:4217'
- item.unitPrice.code = 'USD'
- item.unitPrice.unit = nil
- item.unitPrice.comparator = nil
- end
- if item.net
- item.net.system = 'urn:iso:std:iso:4217'
- item.net.code = 'USD'
- item.net.unit = nil
- item.net.comparator = nil
- end
- item.quantity.comparator = nil unless item.quantity.nil?
+ resource.patchFormat = []
+ resource.kind = 'instance'
+ resource.rest.each do |r|
+ r.resource.each do |res|
+ res.interaction.each{|i|i.code = ['read', 'vread', 'update', 'delete', 'history-instance', 'history-type', 'create', 'search-type'].sample}
end
+ r.interaction.each{|i|i.code = ['transaction', 'batch', 'search-system', 'history-system'].sample }
end
- resource.friendly.each do |f|
- f.contentAttachment = nil
- f.contentReference = textonly_reference('DocumentReference')
- end
- resource.legal.each do |f|
- f.contentAttachment = nil
- f.contentReference = textonly_reference('DocumentReference')
- end
- resource.rule.each do |f|
- f.contentAttachment = nil
- f.contentReference = textonly_reference('DocumentReference')
- end
- when FHIR::DataElement
- resource.mapping.each do |m|
- m.identity = SecureRandom.base64 if m.identity.nil?
- m.identity.gsub!(/[^0-9A-Za-z]/, '')
+ resource.messaging.each do |m|
end
- resource.jurisdiction = []
- when FHIR::DeviceComponent
- unless resource.languageCode.nil?
- resource.languageCode.coding.each do |c|
+ when FHIR::DeviceDefinition
+ resource.languageCode.each do |lc|
+ lc.coding.each do |c|
c.system = 'http://tools.ietf.org/html/bcp47'
c.code = 'en-US'
end
@@ -525,26 +458,23 @@ def self.apply_invariants!(resource)
date = DateTime.now
resource.effectiveDateTime = date.strftime("%Y-%m-%dT%T.%LZ")
resource.effectivePeriod = nil
- when FHIR::DocumentManifest
- resource.content.each do |c|
- c.pAttachment = nil
- c.pReference = textonly_reference('Any')
- end
when FHIR::DocumentReference
resource.docStatus = 'preliminary'
when FHIR::Dosage
- if !resource.doseRange.nil?
- resource.doseRange.low.comparator = nil unless resource.doseRange.low.nil?
- resource.doseRange.high.comparator = nil unless resource.doseRange.high.nil?
+ resource.doseAndRate.each do |dose|
+ if !dose.doseRange.nil?
+ dose.doseRange.low.comparator = nil unless dose.doseRange.low.nil?
+ dose.doseRange.high.comparator = nil unless dose.doseRange.high.nil?
+ end
+ dose.doseQuantity.comparator = nil unless dose.doseQuantity.nil?
+ if !dose.rateRange.nil?
+ dose.rateRange.low.comparator = nil unless dose.rateRange.low.nil?
+ dose.rateRange.high.comparator = nil unless dose.rateRange.high.nil?
+ end
+ dose.rateQuantity.comparator = nil unless dose.rateQuantity.nil?
end
- resource.doseQuantity.comparator = nil unless resource.doseQuantity.nil?
resource.maxDosePerAdministration.comparator = nil unless resource.maxDosePerAdministration.nil?
resource.maxDosePerLifetime.comparator = nil unless resource.maxDosePerLifetime.nil?
- if !resource.rateRange.nil?
- resource.rateRange.low.comparator = nil unless resource.rateRange.low.nil?
- resource.rateRange.high.comparator = nil unless resource.rateRange.high.nil?
- end
- resource.rateQuantity.comparator = nil unless resource.rateQuantity.nil?
when FHIR::ElementDefinition
keys = []
resource.constraint.each do |constraint|
@@ -575,14 +505,8 @@ def self.apply_invariants!(resource)
resource.instance_variable_set("@minValue#{type.capitalize}".to_sym, nil)
resource.instance_variable_set("@maxValue#{type.capitalize}".to_sym, nil)
end
- when FHIR::EligibilityResponse
- resource.insurance.each do |i|
- i.benefitBalance.each do |b|
- b.financial = []
- end
- end
- when FHIR::ExpansionProfile
- resource.designation.exclude = nil unless resource.designation.nil?
+ when FHIR::Endpoint
+ resource.payloadMimeType = [MIME::Types.to_a.sample.content_type]
when FHIR::ExplanationOfBenefit
resource.item.each do |item|
item.detail = []
@@ -623,64 +547,29 @@ def self.apply_invariants!(resource)
resource.outcomeReference.each do |reference|
reference = textonly_reference('Observation')
end
- if resource.target && resource.target.dueDuration
- resource.target.dueDuration.system = 'http://unitsofmeasure.org'
- resource.target.dueDuration.code = 'a'
- resource.target.dueDuration.unit = nil
- resource.target.dueDuration.comparator = nil
+ resource.target.each do |target|
+ unless target.dueDuration.nil?
+ target.dueDuration.system = 'http://unitsofmeasure.org'
+ target.dueDuration.code = 'a'
+ target.dueDuration.unit = nil
+ target.dueDuration.comparator = nil
+ end
end
when FHIR::Group
resource.member = [] if resource.actual==false
- resource.characteristic.each do |c|
- c.valueCodeableConcept = nil
- c.valueBoolean = true
- c.valueQuantity = nil
- c.valueRange = nil
- end
+ resource.characteristic = []
when FHIR::ImagingStudy
- resource.uid = random_oid
availability = ['ONLINE', 'OFFLINE', 'NEARLINE', 'UNAVAILABLE']
resource.series.each do |series|
series.uid=random_oid
- series.availability = availability.sample
series.instance.each do |instance|
instance.uid = random_oid
- instance.sopClass = random_oid
- end
- end
- resource.availability = availability.sample
- when FHIR::ImagingManifest
- resource.study.each do |study|
- study.series.each do |series|
- series.instance.each do |i|
- i.sopClass = random_oid
- i.uid = random_oid
- end
+ instance.sopClass = minimal_coding('urn:ietf:rfc:3986', random_oid)
end
end
when FHIR::Immunization
resource.doseQuantity.comparator = nil unless resource.doseQuantity.nil?
- if resource.notGiven
- unless resource.explanation.nil?
- resource.explanation.reasonNotGiven = [ textonly_codeableconcept("reasonNotGiven #{SecureRandom.base64}") ]
- resource.explanation.reason = nil
- end
- resource.reaction = nil
- else
- unless resource.explanation.nil?
- resource.explanation.reasonNotGiven = nil
- resource.explanation.reason = [ textonly_codeableconcept("reason #{SecureRandom.base64}") ]
- end
- end
resource.status = ['completed','entered-in-error'].sample
- when FHIR::ImplementationGuide
- resource.fhirVersion = "STU3"
- resource.package.each do |package|
- package.resource.each do |r|
- r.sourceUri = nil
- r.sourceReference = textonly_reference('Any')
- end
- end
when FHIR::Linkage
if resource.item.length == 1
resource.item << resource.item.first # must have 2
@@ -705,23 +594,14 @@ def self.apply_invariants!(resource)
resource.frames = nil
end
when FHIR::Medication
+ resource.amount = nil
resource.ingredient.each do |i|
- i.amount = nil
- end
- unless resource.package.nil?
- resource.package.content.each do |c|
- c.amount = nil
- end
+ i.strength = nil
end
when FHIR::MedicationAdministration
date = DateTime.now
resource.effectiveDateTime = date.strftime("%Y-%m-%dT%T.%LZ")
resource.effectivePeriod = nil
- if resource.notGiven
- resource.reasonCode = nil
- else
- resource.reasonNotGiven = nil
- end
resource.medicationReference = textonly_reference('Medication')
resource.medicationCodeableConcept = nil
unless resource.dosage.nil?
@@ -740,7 +620,6 @@ def self.apply_invariants!(resource)
resource.dosageInstruction.each {|d|d.timing = nil }
resource.dispenseRequest.quantity.comparator = nil if resource&.dispenseRequest&.quantity != nil
when FHIR::MedicationStatement
- resource.reasonNotTaken = nil unless resource.taken == 'n'
resource.medicationReference = textonly_reference('Medication')
resource.medicationCodeableConcept = nil
resource.dosage.each{|d|d.timing=nil}
@@ -751,7 +630,6 @@ def self.apply_invariants!(resource)
when FHIR::MessageHeader
resource.response.identifier.gsub!(/[^0-9A-Za-z]/, '') if resource.try(:response).try(:identifier)
when FHIR::NamingSystem
- resource.replacedBy = nil if resource.status!='retired'
if resource.kind == 'root'
resource.uniqueId.each do |uid|
uid.type='uuid'
@@ -808,14 +686,13 @@ def self.apply_invariants!(resource)
end
end
when FHIR::Procedure
- resource.notDoneReason = nil if resource.notDone != true
resource.focalDevice.each do |fd|
code = ['implanted', 'explanted', 'manipulated'].sample
fd.action = minimal_codeableconcept('http://hl7.org/fhir/device-action', code)
end
when FHIR::Provenance
resource.entity.each do |e|
- e.agent.each{|a| a.relatedAgentType = nil }
+ e.agent.each{|a| a.role = nil }
end
when FHIR::Practitioner
resource.communication.each do |comm|
@@ -825,33 +702,32 @@ def self.apply_invariants!(resource)
end
end
when FHIR::RelatedPerson
- resource.relationship = minimal_codeableconcept('http://hl7.org/fhir/patient-contact-relationship','family')
+ resource.relationship = [minimal_codeableconcept('http://hl7.org/fhir/patient-contact-relationship','family')]
when FHIR::Questionnaire
- resource.item.each do |i|
- i.required = true
- i.item = []
- i.options = nil
- i.option = []
- if ['choice','open-choice'].include?(i.type)
- choice_a = FHIR::Questionnaire::Item::Option.new({'valueString'=>'true'})
- choice_b = FHIR::Questionnaire::Item::Option.new({'valueString'=>'false'})
- i.option = [ choice_a, choice_b ]
- end
- if i.type=='display'
- i.required = nil
- i.repeats = nil
- i.readOnly = nil
- i.option = []
- FHIR::Questionnaire::Item::MULTIPLE_TYPES['initial'].each do |type|
- i.instance_variable_set("@initial#{type.capitalize}".to_sym, nil)
- end
- end
- i.enableWhen.each do |ew|
- ew.hasAnswer = false
- ew.hasAnswer = nil if ew.answer
- end
- i.maxLength = nil if !['boolean', 'decimal', 'integer', 'string', 'text', 'url'].include?(i.type)
- end
+ # resource.item.each do |i|
+ # i.required = true
+ # i.item = []
+ # i.answerOption = []
+ # if ['choice','open-choice'].include?(i.type)
+ # choice_a = FHIR::Questionnaire::Item::Option.new({'valueString'=>'true'})
+ # choice_b = FHIR::Questionnaire::Item::Option.new({'valueString'=>'false'})
+ # i.option = [ choice_a, choice_b ]
+ # end
+ # if i.type=='display'
+ # i.required = nil
+ # i.repeats = nil
+ # i.readOnly = nil
+ # i.option = []
+ # FHIR::Questionnaire::Item::MULTIPLE_TYPES['initial'].each do |type|
+ # i.instance_variable_set("@initial#{type.capitalize}".to_sym, nil)
+ # end
+ # end
+ # # i.enableWhen.each do |ew|
+ # # ew.hasAnswer = false
+ # # ew.hasAnswer = nil if ew.answer
+ # # end
+ # i.maxLength = nil if !['boolean', 'decimal', 'integer', 'string', 'text', 'url'].include?(i.type)
+ # end
when FHIR::QuestionnaireResponse
resource.item.each do |i|
i.item = nil
@@ -868,14 +744,12 @@ def self.apply_invariants!(resource)
# simple quantities do not have a comparator
resource.low.comparator = nil unless resource.low.nil?
resource.high.comparator = nil unless resource.high.nil?
- when FHIR::ReferralRequest
- resource.requester.onBehalfOf = nil unless resource.requester.nil?
- when FHIR::Sequence
+ when FHIR::MolecularSequence
resource.coordinateSystem = [0,1].sample
unless resource.referenceSeq.nil?
resource.referenceSeq.referenceSeqId = resource.referenceSeq.referenceSeqPointer = resource.referenceSeq.referenceSeqString = nil
- resource.referenceSeq.strand = [-1,1].sample unless resource.referenceSeq.strand.nil?
+ resource.referenceSeq.strand = ['watson','crick'].sample unless resource.referenceSeq.strand.nil?
end
when FHIR::SearchParameter
resource.type = 'reference'
@@ -884,8 +758,8 @@ def self.apply_invariants!(resource)
resource.origin.comparator = nil unless resource.origin.nil?
when FHIR::Signature
resource.type = [ minimal_coding('urn:iso-astm:E1762-95:2013','1.2.840.10065.1.12.1.18') ]
- resource.whoUri = 'http://projectcrucible.org'
- resource.whoReference = nil
+ resource.targetFormat = nil
+ resource.sigFormat = nil
when FHIR::Specimen
unless resource.collection.nil?
resource.collection.quantity.comparator = nil unless resource.collection.quantity.nil?
@@ -909,7 +783,7 @@ def self.apply_invariants!(resource)
resource.category = minimal_codeableconcept('http://hl7.org/fhir/supply-kind','central')
when FHIR::StructureDefinition
resource.derivation = 'constraint'
- resource.fhirVersion = 'STU3'
+ resource.fhirVersion = '4.0.0'
resource.baseDefinition = "http://hl7.org/fhir/StructureDefinition/#{resource.type}"
is_pattern = (SecureRandom.random_number(2)==0)
if resource.snapshot && resource.snapshot.element
@@ -919,6 +793,7 @@ def self.apply_invariants!(resource)
resource.snapshot.element.first.code = nil
resource.snapshot.element.first.requirements = nil
resource.snapshot.element.first.type = nil
+ resource.snapshot.element.first.mapping = []
if is_pattern
FHIR::ElementDefinition::MULTIPLE_TYPES['defaultValue'].each do |type|
resource.snapshot.element.first.instance_variable_set("@defaultValue#{type.capitalize}".to_sym, nil)
@@ -961,6 +836,13 @@ def self.apply_invariants!(resource)
instance.quantity.comparator = nil
end
end
+ when FHIR::Task
+ resource.input.each do |input|
+ input.valueString = SecureRandom.uuid if input.value.nil?
+ end
+ resource.output.each do |output|
+ output.valueString = SecureRandom.uuid if output.value.nil?
+ end
when FHIR::TestReport
if resource.setup
resource.setup.action.each do |a|
@@ -1019,6 +901,8 @@ def self.apply_invariants!(resource)
resource.sourceId.gsub!(/[^0-9A-Za-z]/, '') if resource.sourceId
resource.validateProfileId.gsub!(/[^0-9A-Za-z]/, '') if resource.validateProfileId
when FHIR::TestScript::Setup::Action::Operation
+ resource.accept = MIME::Types.to_a.sample.content_type
+ resource.contentType = MIME::Types.to_a.sample.content_type
resource.responseId.gsub!(/[^0-9A-Za-z]/, '') if resource.responseId
resource.sourceId.gsub!(/[^0-9A-Za-z]/, '') if resource.sourceId
resource.targetId.gsub!(/[^0-9A-Za-z]/, '') if resource.targetId
@@ -1044,7 +928,7 @@ def self.apply_invariants!(resource)
end
end
when FHIR::VisionPrescription
- resource.dispense.each do |d|
+ resource.lensSpecification.each do |d|
d.duration.comparator = nil unless d.duration.nil?
end
when FHIR::RequestGroup::Action
@@ -1055,6 +939,792 @@ def self.apply_invariants!(resource)
resource.action = []
end
end
+ ## STU3
+ when FHIR::STU3::ActivityDefinition
+ resource.quantity.comparator = nil unless resource.quantity.nil?
+ when FHIR::STU3::Age
+ resource.system = 'http://unitsofmeasure.org'
+ resource.code = 'a'
+ resource.value = (SecureRandom.random_number(100) + 1)
+ resource.unit = nil
+ resource.comparator = nil
+ when FHIR::STU3::AllergyIntolerance
+ resource.clinicalStatus = nil if resource.verificationStatus=='entered-in-error'
+ when FHIR::STU3::Duration
+ resource.system = 'http://unitsofmeasure.org'
+ resource.code = 'mo'
+ resource.unit = nil
+ resource.comparator = nil
+ when FHIR::STU3::Money
+ resource.system = 'urn:iso:std:iso:4217'
+ resource.code = 'USD'
+ resource.unit = nil
+ resource.comparator = nil
+ when FHIR::STU3::Appointment
+ resource.reason = [ minimal_codeableconcept('http://snomed.info/sct','219006', FHIR::STU3) ] # drinker of alcohol
+ resource.participant.each{|p| p.type=[ minimal_codeableconcept('http://hl7.org/fhir/participant-type','emergency', FHIR::STU3) ] }
+ when FHIR::STU3::AppointmentResponse
+ resource.participantType = [ minimal_codeableconcept('http://hl7.org/fhir/participant-type','emergency', FHIR::STU3) ]
+ when FHIR::STU3::AuditEvent
+ resource.entity.each do |o|
+ o.query=nil
+ o.name = "name #{SecureRandom.base64}" if o.name.nil?
+ end
+ when FHIR::STU3::Bundle
+ resource.type = ['document','message','collection'].sample
+ resource.total = nil if !['searchset','history'].include?(resource.type)
+ resource.entry.each {|e|e.search=nil} if resource.type!='searchset'
+ resource.entry.each {|e|e.request=nil} if !['batch','transaction','history'].include?(resource.type)
+ resource.entry.each {|e|e.response=nil} if !['batch-response','transaction-response'].include?(resource.type)
+ head = resource.entry.first
+ if !head.nil?
+ if resource.type == 'document'
+ head.resource = generate(FHIR::STU3::Composition,3)
+ elsif resource.type == 'message'
+ head.resource = generate(FHIR::STU3::MessageHeader,3)
+ else
+ head.resource = generate(FHIR::STU3::Basic,3)
+ end
+ rid = SecureRandom.random_number(100) + 1
+ head.fullUrl = "http://projectcrucible.org/fhir/#{head.resource.resourceType}/#{rid}"
+ head.resource.id = "#{rid}"
+ end
+ when FHIR::STU3::CarePlan
+ resource.activity.each do |a|
+ unless a.detail.nil?
+ a.reference = nil
+ a.detail.dailyAmount.comparator = nil unless a.detail.dailyAmount.nil?
+ a.detail.quantity.comparator = nil unless a.detail.quantity.nil?
+ end
+ end
+ when FHIR::STU3::CareTeam
+ resource.participant.each do |p|
+ p.onBehalfOf = nil
+ end
+ when FHIR::STU3::CodeSystem
+ resource.concept.each do |c|
+ c.concept.each do |d|
+ d.property.each do |p|
+ p.valueCode = nil
+ p.valueCoding = nil
+ p.valueString = SecureRandom.base64
+ p.valueInteger = nil
+ p.valueBoolean = nil
+ p.valueDateTime = nil
+ end
+ end
+ end
+ when FHIR::STU3::CapabilityStatement
+ resource.kind = 'instance'
+ resource.rest.each do |r|
+ r.resource.each do |res|
+ res.interaction.each{|i|i.code = ['read', 'vread', 'update', 'delete', 'history-instance', 'history-type', 'create', 'search-type'].sample}
+ end
+ r.interaction.each{|i|i.code = ['transaction', 'batch', 'search-system', 'history-system'].sample }
+ end
+ resource.messaging.each do |m|
+ m.supportedMessage = [] if m.event.length > 0
+ end
+ when FHIR::STU3::Claim
+ resource.item.each do |item|
+ item.category = minimal_codeableconcept('http://hl7.org/fhir/benefit-subcategory','35', FHIR::STU3)
+ item.quantity.comparator = nil unless item.quantity.nil?
+ item.detail.each do |detail|
+ detail.category = item.category
+ detail.quantity.comparator = nil unless detail.quantity.nil?
+ detail.subDetail.each do |sub|
+ sub.category = item.category
+ sub.quantity.comparator = nil unless sub.quantity.nil?
+ sub.service = minimal_codeableconcept('http://hl7.org/fhir/ex-USCLS','1205', FHIR::STU3)
+ end
+ end
+ end
+ when FHIR::STU3::ClaimResponse
+ resource.item.each do |item|
+ item.adjudication.each{|a|a.category = minimal_codeableconcept('http://hl7.org/fhir/adjudication','benefit', FHIR::STU3)}
+ item.detail.each do |detail|
+ detail.adjudication.each{|a|a.category = minimal_codeableconcept('http://hl7.org/fhir/adjudication','benefit', FHIR::STU3)}
+ detail.subDetail.each do |sub|
+ sub.adjudication.each{|a|a.category = minimal_codeableconcept('http://hl7.org/fhir/adjudication','benefit', FHIR::STU3)}
+ end
+ end
+ end
+ resource.addItem.each do |addItem|
+ addItem.adjudication.each{|a|a.category = minimal_codeableconcept('http://hl7.org/fhir/adjudication','benefit', FHIR::STU3)}
+ addItem.detail.each do |detail|
+ detail.adjudication.each{|a|a.category = minimal_codeableconcept('http://hl7.org/fhir/adjudication','benefit', FHIR::STU3)}
+ end
+ end
+ when FHIR::STU3::Communication
+ resource.payload = nil
+ when FHIR::STU3::CommunicationRequest
+ resource.payload = nil
+ resource.requester.onBehalfOf = nil unless resource.requester.nil?
+ when FHIR::STU3::Composition
+ resource.attester.each {|a| a.mode = ['professional']}
+ resource.section.each do |section|
+ section.emptyReason = nil
+ section.section.each do |sub|
+ sub.emptyReason = nil
+ sub.section = nil
+ end
+ end
+ when FHIR::STU3::ConceptMap
+ if(resource.sourceUri.nil? && resource.sourceReference.nil?)
+ resource.sourceReference = textonly_reference('ValueSet', FHIR::STU3)
+ end
+ if(resource.targetUri.nil? && resource.targetReference.nil?)
+ resource.targetReference = textonly_reference('ValueSet', FHIR::STU3)
+ end
+ when FHIR::STU3::Condition
+ if resource.onsetAge
+ resource.onsetAge.system = 'http://unitsofmeasure.org'
+ resource.onsetAge.code = 'a'
+ resource.onsetAge.unit = 'yr'
+ resource.onsetAge.comparator = nil
+ end
+ resource.clinicalStatus = ['inactive', 'resolved','remission'].sample unless resource.abatement.nil?
+ if resource.abatementAge
+ resource.abatementAge.system = 'http://unitsofmeasure.org'
+ resource.abatementAge.code = 'a'
+ resource.abatementAge.unit = 'yr'
+ resource.abatementAge.comparator = nil
+ end
+ # Make sure the onsetAge is before the abatementAge. If it's not (and both exist), flip them around
+ if resource.onsetAge && resource.abatementAge
+ if resource.onsetAge.value > resource.abatementAge.value
+ # This is the "Ruby Way" to swap two variables without using a temporary third variable
+ resource.onsetAge, resource.abatementAge = resource.abatementAge, resource.onsetAge
+ end
+ end
+ when FHIR::STU3::CapabilityStatement
+ resource.fhirVersion = 'STU3'
+ resource.format = ['xml','json']
+ if resource.kind == 'capability'
+ resource.implementation = nil
+ elsif resource.kind == 'requirements'
+ resource.implementation = nil
+ resource.software = nil
+ end
+ resource.messaging.each{|m| m.endpoint = nil} if resource.kind != 'instance'
+ when FHIR::STU3::Contract
+ resource.agent.each do |agent|
+ agent.actor = textonly_reference('Patient', FHIR::STU3)
+ end
+ resource.valuedItem.each do |item|
+ if item.unitPrice
+ item.unitPrice.system = 'urn:iso:std:iso:4217'
+ item.unitPrice.code = 'USD'
+ item.unitPrice.unit = nil
+ item.unitPrice.comparator = nil
+ end
+ if item.net
+ item.net.system = 'urn:iso:std:iso:4217'
+ item.net.code = 'USD'
+ item.net.unit = nil
+ item.net.comparator = nil
+ end
+ item.quantity.comparator = nil unless item.quantity.nil?
+ end
+ resource.term.each do |term|
+ term.agent.each do |agent|
+ agent.actor = textonly_reference('Organization', FHIR::STU3)
+ end
+ term.group.each do |group|
+ group.agent.each do |agent|
+ agent.actor = textonly_reference('Organization', FHIR::STU3)
+ end
+ end
+ term.valuedItem.each do |item|
+ if item.unitPrice
+ item.unitPrice.system = 'urn:iso:std:iso:4217'
+ item.unitPrice.code = 'USD'
+ item.unitPrice.unit = nil
+ item.unitPrice.comparator = nil
+ end
+ if item.net
+ item.net.system = 'urn:iso:std:iso:4217'
+ item.net.code = 'USD'
+ item.net.unit = nil
+ item.net.comparator = nil
+ end
+ item.quantity.comparator = nil unless item.quantity.nil?
+ end
+ end
+ resource.friendly.each do |f|
+ f.contentAttachment = nil
+ f.contentReference = textonly_reference('DocumentReference', FHIR::STU3)
+ end
+ resource.legal.each do |f|
+ f.contentAttachment = nil
+ f.contentReference = textonly_reference('DocumentReference', FHIR::STU3)
+ end
+ resource.rule.each do |f|
+ f.contentAttachment = nil
+ f.contentReference = textonly_reference('DocumentReference', FHIR::STU3)
+ end
+ when FHIR::STU3::DataElement
+ resource.element.each do |e|
+ e.example.each do |example|
+ example.valueString = SecureRandom.uuid if example.value.nil?
+ end
+ end
+ resource.mapping.each do |m|
+ m.identity = SecureRandom.base64 if m.identity.nil?
+ m.identity.gsub!(/[^0-9A-Za-z]/, '')
+ end
+ resource.jurisdiction = []
+ when FHIR::STU3::DeviceComponent
+ unless resource.languageCode.nil?
+ resource.languageCode.coding.each do |c|
+ c.system = 'http://tools.ietf.org/html/bcp47'
+ c.code = 'en-US'
+ end
+ end
+ when FHIR::STU3::DeviceMetric
+ resource.measurementPeriod = nil
+ when FHIR::STU3::DiagnosticReport
+ date = DateTime.now
+ resource.effectiveDateTime = date.strftime("%Y-%m-%dT%T.%LZ")
+ resource.effectivePeriod = nil
+ when FHIR::STU3::DocumentManifest
+ resource.content.each do |c|
+ c.pAttachment = nil
+ c.pReference = textonly_reference('Any', FHIR::STU3)
+ end
+ when FHIR::STU3::DocumentReference
+ resource.docStatus = 'preliminary'
+ when FHIR::STU3::Dosage
+ if !resource.doseRange.nil?
+ resource.doseRange.low.comparator = nil unless resource.doseRange.low.nil?
+ resource.doseRange.high.comparator = nil unless resource.doseRange.high.nil?
+ end
+ resource.doseQuantity.comparator = nil unless resource.doseQuantity.nil?
+ resource.maxDosePerAdministration.comparator = nil unless resource.maxDosePerAdministration.nil?
+ resource.maxDosePerLifetime.comparator = nil unless resource.maxDosePerLifetime.nil?
+ if !resource.rateRange.nil?
+ resource.rateRange.low.comparator = nil unless resource.rateRange.low.nil?
+ resource.rateRange.high.comparator = nil unless resource.rateRange.high.nil?
+ end
+ resource.rateQuantity.comparator = nil unless resource.rateQuantity.nil?
+ when FHIR::STU3::ElementDefinition
+ keys = []
+ resource.constraint.each do |constraint|
+ constraint.key = SecureRandom.base64 if constraint.key.nil?
+ constraint.key.gsub!(/[^0-9A-Za-z]/, '')
+ keys << constraint.key
+ constraint.xpath = "/"
+ end
+ resource.condition = keys
+ resource.mapping.each do |m|
+ m.identity = SecureRandom.base64 if m.identity.nil?
+ m.identity.gsub!(/[^0-9A-Za-z]/, '')
+ end
+ resource.max = "#{resource.min+1}"
+ # TODO remove bindings for things that can't be code, Coding, CodeableConcept
+ is_codeable = false
+ resource.type.each do |f|
+ is_codeable = (['code','Coding','CodeableConcept'].include?(f.code))
+ f.aggregation = []
+ end
+ resource.binding = nil unless is_codeable
+ resource.contentReference = nil
+ FHIR::STU3::ElementDefinition::MULTIPLE_TYPES['defaultValue'].each do |type|
+ resource.instance_variable_set("@defaultValue#{type.capitalize}".to_sym, nil)
+ resource.instance_variable_set("@fixed#{type.capitalize}".to_sym, nil)
+ resource.instance_variable_set("@pattern#{type.capitalize}".to_sym, nil)
+ resource.instance_variable_set("@example#{type.capitalize}".to_sym, nil)
+ resource.instance_variable_set("@minValue#{type.capitalize}".to_sym, nil)
+ resource.instance_variable_set("@maxValue#{type.capitalize}".to_sym, nil)
+ end
+ when FHIR::STU3::EligibilityResponse
+ resource.insurance.each do |i|
+ i.benefitBalance.each do |b|
+ b.financial = []
+ end
+ end
+ when FHIR::STU3::ExpansionProfile
+ resource.designation.exclude = nil unless resource.designation.nil?
+ resource.fixedVersion.each {|v| v.version = 'v1'}
+ when FHIR::STU3::ExplanationOfBenefit
+ resource.item.each do |item|
+ item.detail = []
+ item.quantity.comparator = nil unless item.quantity.nil?
+ end
+ resource.addItem.each do |item|
+ item.detail = []
+ end
+ when FHIR::STU3::FamilyMemberHistory
+ if resource.ageAge
+ resource.ageAge.system = 'http://unitsofmeasure.org'
+ resource.ageAge.code = 'a'
+ resource.ageAge.unit = nil
+ resource.ageAge.comparator = nil
+ end
+ if SecureRandom.random_number(2)==0
+ resource.bornPeriod = nil
+ resource.bornDate = nil
+ resource.bornString = nil
+ else
+ resource.ageAge = nil
+ resource.ageRange = nil
+ resource.ageString = nil
+ end
+ if resource.age.nil?
+ resource.estimatedAge = nil
+ end
+ if resource.deceasedAge
+ resource.deceasedAge.system = 'http://unitsofmeasure.org'
+ resource.deceasedAge.code = 'a'
+ resource.deceasedAge.unit = nil
+ resource.deceasedAge.comparator = nil
+ end
+ when FHIR::STU3::Goal
+ resource.outcomeCode.each do |code|
+ code = nil
+ end
+ resource.outcomeReference.each do |reference|
+ reference = textonly_reference('Observation', FHIR::STU3)
+ end
+ if resource.target && resource.target.dueDuration
+ resource.target.dueDuration.system = 'http://unitsofmeasure.org'
+ resource.target.dueDuration.code = 'a'
+ resource.target.dueDuration.unit = nil
+ resource.target.dueDuration.comparator = nil
+ end
+ when FHIR::STU3::Group
+ resource.member = [] if resource.actual==false
+ resource.characteristic.each do |c|
+ c.valueCodeableConcept = nil
+ c.valueBoolean = true
+ c.valueQuantity = nil
+ c.valueRange = nil
+ end
+ when FHIR::STU3::ImagingStudy
+ resource.uid = random_oid
+ availability = ['ONLINE', 'OFFLINE', 'NEARLINE', 'UNAVAILABLE']
+ resource.series.each do |series|
+ series.uid=random_oid
+ series.availability = availability.sample
+ series.instance.each do |instance|
+ instance.uid = random_oid
+ instance.sopClass = random_oid
+ end
+ end
+ resource.availability = availability.sample
+ when FHIR::STU3::ImagingManifest
+ resource.study.each do |study|
+ study.series.each do |series|
+ series.instance.each do |i|
+ i.sopClass = random_oid
+ i.uid = random_oid
+ end
+ end
+ end
+ when FHIR::STU3::Immunization
+ resource.doseQuantity.comparator = nil unless resource.doseQuantity.nil?
+ if resource.notGiven
+ unless resource.explanation.nil?
+ resource.explanation.reasonNotGiven = [ textonly_codeableconcept("reasonNotGiven #{SecureRandom.base64}", FHIR::STU3) ]
+ resource.explanation.reason = nil
+ end
+ resource.reaction = nil
+ else
+ unless resource.explanation.nil?
+ resource.explanation.reasonNotGiven = nil
+ resource.explanation.reason = [ textonly_codeableconcept("reason #{SecureRandom.base64}", FHIR::STU3) ]
+ end
+ end
+ resource.status = ['completed','entered-in-error'].sample
+ when FHIR::STU3::ImplementationGuide
+ resource.fhirVersion = "STU3"
+ resource.package.each do |package|
+ package.resource.each do |r|
+ r.sourceUri = nil
+ r.sourceReference = textonly_reference('Any', FHIR::STU3)
+ end
+ end
+ when FHIR::STU3::Linkage
+ if resource.item.length == 1
+ resource.item << resource.item.first # must have 2
+ end
+ when FHIR::STU3::List
+ resource.emptyReason = nil
+ resource.entry.each do |entry|
+ resource.mode = 'changes' if !entry.deleted.nil?
+ end
+ when FHIR::STU3::Media
+ if resource.type == 'video'
+ resource.frames = nil
+ elsif resource.type == 'photo'
+ resource.duration = nil
+ elsif resource.type == 'audio'
+ resource.height = nil
+ resource.width = nil
+ resource.frames = nil
+ else
+ resource.height = nil
+ resource.width = nil
+ resource.frames = nil
+ end
+ when FHIR::STU3::Medication
+ resource.ingredient.each do |i|
+ i.amount = nil
+ end
+ unless resource.package.nil?
+ resource.package.content.each do |c|
+ c.amount = nil
+ end
+ end
+ when FHIR::STU3::MedicationAdministration
+ date = DateTime.now
+ resource.effectiveDateTime = date.strftime("%Y-%m-%dT%T.%LZ")
+ resource.effectivePeriod = nil
+ if resource.notGiven
+ resource.reasonCode = nil
+ else
+ resource.reasonNotGiven = nil
+ end
+ resource.medicationReference = textonly_reference('Medication', FHIR::STU3)
+ resource.medicationCodeableConcept = nil
+ unless resource.dosage.nil?
+ resource.dosage.dose.comparator = nil unless resource.dosage.dose.nil?
+ resource.dosage.rateQuantity = nil
+ end
+ when FHIR::STU3::MedicationDispense
+ resource.medicationReference = textonly_reference('Medication', FHIR::STU3)
+ resource.medicationCodeableConcept = nil
+ resource.dosageInstruction.each {|d|d.timing = nil }
+ resource.quantity.comparator = nil unless resource.quantity.nil?
+ resource.daysSupply.comparator = nil unless resource.daysSupply.nil?
+ when FHIR::STU3::MedicationRequest
+ resource.medicationReference = textonly_reference('Medication', FHIR::STU3)
+ resource.medicationCodeableConcept = nil
+ resource.dosageInstruction.each {|d|d.timing = nil }
+ resource.dispenseRequest.quantity.comparator = nil if resource&.dispenseRequest&.quantity != nil
+ when FHIR::STU3::MedicationStatement
+ resource.reasonNotTaken = nil unless resource.taken == 'n'
+ resource.medicationReference = textonly_reference('Medication', FHIR::STU3)
+ resource.medicationCodeableConcept = nil
+ resource.dosage.each{|d|d.timing=nil}
+ when FHIR::STU3::MessageDefinition
+ resource.focus.each do |f|
+ f.max = '*' unless f.max.nil?
+ end
+ when FHIR::STU3::MessageHeader
+ resource.response.identifier.gsub!(/[^0-9A-Za-z]/, '') if resource.try(:response).try(:identifier)
+ when FHIR::STU3::NamingSystem
+ resource.replacedBy = nil if resource.status!='retired'
+ if resource.kind == 'root'
+ resource.uniqueId.each do |uid|
+ uid.type='uuid'
+ uid.value = SecureRandom.uuid
+ end
+ end
+ resource.uniqueId.each do |uid|
+ uid.preferred = nil
+ end
+ when FHIR::STU3::NutritionOrder
+ if resource.oralDiet
+ resource.oralDiet.schedule = nil
+ resource.oralDiet.nutrient.each { |n| n.amount.comparator = nil unless n.amount.nil? }
+ end
+ resource.supplement.each{|s|s.schedule=nil}
+ resource.supplement.each{|s|s.quantity=nil}
+ unless resource.enteralFormula.nil?
+ resource.enteralFormula.administration = nil
+ resource.enteralFormula.caloricDensity.comparator = nil unless resource.enteralFormula.caloricDensity.nil?
+ resource.enteralFormula.maxVolumeToDeliver.comparator = nil unless resource.enteralFormula.maxVolumeToDeliver.nil?
+ resource.enteralFormula.administration.each do |a|
+ a.rateQuantity = nil
+ end unless resource.enteralFormula.administration.nil?
+ end
+ resource.supplement.each { |s| s.quantity.comparator = nil unless s.quantity.nil? }
+ when FHIR::STU3::Observation
+ resource.referenceRange.each do |range|
+ range.low.comparator = nil unless range.low.nil?
+ range.high.comparator = nil unless range.high.nil?
+ end
+ resource.component.each do |component|
+ if !component.valueRange.nil?
+ component.valueRange.low.comparator = nil unless component.valueRange.low.nil?
+ component.valueRange.high.comparator = nil unless component.valueRange.high.nil?
+ end
+ component.referenceRange.each do |range|
+ range.low.comparator = nil unless range.low.nil?
+ range.high.comparator = nil unless range.high.nil?
+ end
+ end
+
+ when FHIR::STU3::OperationDefinition
+ resource.parameter.each do |p|
+ p.binding = nil
+ p.part = nil
+ p.searchType = nil unless p.type == 'string'
+ end
+ when FHIR::STU3::Patient
+ resource.maritalStatus = minimal_codeableconcept('http://hl7.org/fhir/v3/MaritalStatus','S', FHIR::STU3)
+ when FHIR::STU3::PlanDefinition
+ resource.action.each do |a|
+ a.action.each do |b|
+ b.relatedAction = []
+ end
+ end
+ when FHIR::STU3::Procedure
+ resource.notDoneReason = nil if resource.notDone != true
+ resource.focalDevice.each do |fd|
+ code = ['implanted', 'explanted', 'manipulated'].sample
+ fd.action = minimal_codeableconcept('http://hl7.org/fhir/device-action', code, FHIR::STU3)
+ end
+ when FHIR::STU3::Provenance
+ resource.entity.each do |e|
+ e.agent.each{|a| a.relatedAgentType = nil }
+ end
+ when FHIR::STU3::Practitioner
+ resource.communication.each do |comm|
+ comm.coding.each do |c|
+ c.system = 'http://tools.ietf.org/html/bcp47'
+ c.code = 'en-US'
+ end
+ end
+ when FHIR::STU3::RelatedPerson
+ resource.relationship = minimal_codeableconcept('http://hl7.org/fhir/patient-contact-relationship','family', FHIR::STU3)
+ when FHIR::STU3::Questionnaire
+ resource.item.each do |i|
+ i.required = true
+ i.item = []
+ i.options = nil
+ i.option = []
+ if ['choice','open-choice'].include?(i.type)
+ choice_a = FHIR::STU3::Questionnaire::Item::Option.new({'valueString'=>'true'})
+ choice_b = FHIR::STU3::Questionnaire::Item::Option.new({'valueString'=>'false'})
+ i.option = [ choice_a, choice_b ]
+ end
+ if i.type=='display'
+ i.required = nil
+ i.repeats = nil
+ i.readOnly = nil
+ i.option = []
+ FHIR::STU3::Questionnaire::Item::MULTIPLE_TYPES['initial'].each do |type|
+ i.instance_variable_set("@initial#{type.capitalize}".to_sym, nil)
+ end
+ end
+ i.enableWhen.each do |ew|
+ ew.hasAnswer = false
+ ew.hasAnswer = nil if ew.answer
+ end
+ i.maxLength = nil if !['boolean', 'decimal', 'integer', 'string', 'text', 'url'].include?(i.type)
+ end
+ when FHIR::STU3::QuestionnaireResponse
+ resource.item.each do |i|
+ i.item = nil
+ i.answer.each {|q|q.valueBoolean = true if !q.value }
+ end
+ when FHIR::STU3::Range
+ # validate that the low/high values in the range are correct (e.g. the low value is not higher than the high value)
+ if resource.low && resource.high
+ if resource.low.value > resource.high.value
+ # This is the "Ruby Way" to swap two variables without using a temporary third variable
+ resource.low.value,resource.high.value = resource.high.value,resource.low.value
+ end
+ end
+ # simple quantities do not have a comparator
+ resource.low.comparator = nil unless resource.low.nil?
+ resource.high.comparator = nil unless resource.high.nil?
+ when FHIR::STU3::ReferralRequest
+ resource.requester.onBehalfOf = nil unless resource.requester.nil?
+ when FHIR::STU3::Sequence
+ resource.coordinateSystem = [0,1].sample
+
+ unless resource.referenceSeq.nil?
+ resource.referenceSeq.referenceSeqId = resource.referenceSeq.referenceSeqPointer = resource.referenceSeq.referenceSeqString = nil
+ resource.referenceSeq.strand = [-1,1].sample unless resource.referenceSeq.strand.nil?
+ end
+ when FHIR::STU3::SearchParameter
+ resource.type = 'reference'
+
+ when FHIR::STU3::SampledData
+ resource.origin.comparator = nil unless resource.origin.nil?
+ when FHIR::STU3::Signature
+ resource.type = [ minimal_coding('urn:iso-astm:E1762-95:2013','1.2.840.10065.1.12.1.18', FHIR::STU3) ]
+ resource.whoUri = 'http://projectcrucible.org'
+ resource.whoReference = nil
+ when FHIR::STU3::Specimen
+ unless resource.collection.nil?
+ resource.collection.quantity.comparator = nil unless resource.collection.quantity.nil?
+ end
+ resource.container.each do |c|
+ c.capacity = c.specimenQuantity = nil
+ end
+ when FHIR::STU3::Subscription
+ resource.status = 'requested' if resource.id.nil?
+ resource.channel.payload = 'applicaton/json+fhir'
+ resource.end = nil
+ resource.criteria = 'Observation?code=http://loinc.org|1975-2'
+ when FHIR::STU3::Substance
+ resource.instance.each do |instance|
+ instance.quantity.comparator = nil unless instance.quantity.nil?
+ end
+ when FHIR::STU3::SupplyDelivery
+ resource.type = minimal_codeableconcept('http://hl7.org/fhir/supply-item-type','medication', FHIR::STU3)
+ resource.suppliedItem.quantity.comparator = nil if !resource.suppliedItem.nil? && !resource.suppliedItem.quantity.nil?
+ when FHIR::STU3::SupplyRequest
+ resource.category = minimal_codeableconcept('http://hl7.org/fhir/supply-kind','central', FHIR::STU3)
+ when FHIR::STU3::StructureDefinition
+ resource.derivation = 'constraint'
+ resource.fhirVersion = 'STU3'
+ resource.baseDefinition = "http://hl7.org/fhir/StructureDefinition/#{resource.type}"
+ is_pattern = (SecureRandom.random_number(2)==0)
+ if resource.snapshot && resource.snapshot.element
+ resource.snapshot.element.first.id = resource.type
+ resource.snapshot.element.first.path = resource.type
+ resource.snapshot.element.first.label = nil
+ resource.snapshot.element.first.code = nil
+ resource.snapshot.element.first.requirements = nil
+ resource.snapshot.element.first.type = nil
+ if is_pattern
+ FHIR::STU3::ElementDefinition::MULTIPLE_TYPES['defaultValue'].each do |type|
+ resource.snapshot.element.first.instance_variable_set("@defaultValue#{type.capitalize}".to_sym, nil)
+ resource.snapshot.element.first.instance_variable_set("@fixed#{type.capitalize}".to_sym, nil)
+ resource.snapshot.element.first.instance_variable_set("@example#{type.capitalize}".to_sym, nil)
+ resource.snapshot.element.first.instance_variable_set("@minValue#{type.capitalize}".to_sym, nil)
+ resource.snapshot.element.first.instance_variable_set("@maxValue#{type.capitalize}".to_sym, nil)
+ end
+ else
+ FHIR::STU3::ElementDefinition::MULTIPLE_TYPES['defaultValue'].each do |type|
+ resource.snapshot.element.first.instance_variable_set("@defaultValue#{type.capitalize}".to_sym, nil)
+ resource.snapshot.element.first.instance_variable_set("@pattern#{type.capitalize}".to_sym, nil)
+ resource.snapshot.element.first.instance_variable_set("@example#{type.capitalize}".to_sym, nil)
+ resource.snapshot.element.first.instance_variable_set("@minValue#{type.capitalize}".to_sym, nil)
+ resource.snapshot.element.first.instance_variable_set("@maxValue#{type.capitalize}".to_sym, nil)
+ end
+ end
+ end
+ if resource.differential && resource.differential.element
+ resource.differential.element[0] = resource.snapshot.element[0]
+ end
+ resource.mapping.each do |m|
+ m.identity.gsub!(/[^0-9A-Za-z]/, '') if m.identity
+ end
+ when FHIR::STU3::StructureMap
+ resource.group.each do |g|
+ g.rule.each{|r|r.rule = nil}
+ end
+ when FHIR::STU3::Substance
+ resource.ingredient.each do |ingredient|
+ unless ingredient.quantity.try(:denominator).try(:comparator).nil?
+ ingredient.quantity.denominator.comparator = nil
+ end
+ unless ingredient.quantity.try(:numerator).try(:comparator).nil?
+ ingredient.quantity.numerator.comparator = nil
+ end
+ end
+ resource.instance.each do |instance|
+ unless instance.quantity.nil?
+ instance.quantity.comparator = nil
+ end
+ end
+ when FHIR::STU3::Task
+ resource.input.each do |input|
+ input.valueString = SecureRandom.uuid if input.value.nil?
+ end
+ resource.output.each do |output|
+ output.valueString = SecureRandom.uuid if output.value.nil?
+ end
+ when FHIR::STU3::TestReport
+ if resource.setup
+ resource.setup.action.each do |a|
+ a.assert = nil if a.operation
+ apply_invariants!(a.operation) if a.operation
+ apply_invariants!(a.assert) if a.assert
+ end
+ end
+ resource.test.each do |test|
+ test.action.each do |a|
+ a.assert = nil if a.operation
+ apply_invariants!(a.operation) if a.operation
+ apply_invariants!(a.assert) if a.assert
+ end
+ end
+ if resource.teardown
+ resource.teardown.action.each do |a|
+ apply_invariants!(a.operation) if a.operation
+ end
+ end
+ when FHIR::STU3::TestScript
+ resource.variable.each do |v|
+ v.sourceId.gsub!(/[^0-9A-Za-z]/, '') if v.sourceId
+ v.path = nil if v.headerField
+ end
+ if resource.setup
+ resource.setup.action.each do |a|
+ a.assert = nil if a.operation
+ apply_invariants!(a.operation) if a.operation
+ apply_invariants!(a.assert) if a.assert
+ end
+ end
+ resource.test.each do |test|
+ test.action.each do |a|
+ a.assert = nil if a.operation
+ apply_invariants!(a.operation) if a.operation
+ apply_invariants!(a.assert) if a.assert
+ end
+ end
+ if resource.teardown
+ resource.teardown.action.each do |a|
+ apply_invariants!(a.operation) if a.operation
+ end
+ end
+ when FHIR::STU3::TestScript::Setup::Action::Assert
+ # an assertion can only contain one of these...
+ keys = ['contentType','headerField','minimumId','navigationLinks','path','resource','responseCode','response','validateProfileId']
+ has_keys = []
+ keys.each do |key|
+ has_keys << key if resource.try(key.to_sym)
+ end
+ # remove all assertions except the first
+ has_keys[1..-1].each do |key|
+ resource.send("#{key}=",nil)
+ end
+ resource.sourceId.gsub!(/[^0-9A-Za-z]/, '') if resource.sourceId
+ resource.validateProfileId.gsub!(/[^0-9A-Za-z]/, '') if resource.validateProfileId
+ when FHIR::STU3::TestScript::Setup::Action::Operation
+ resource.responseId.gsub!(/[^0-9A-Za-z]/, '') if resource.responseId
+ resource.sourceId.gsub!(/[^0-9A-Za-z]/, '') if resource.sourceId
+ resource.targetId.gsub!(/[^0-9A-Za-z]/, '') if resource.targetId
+ when FHIR::STU3::Timing
+ unless resource.repeat.nil?
+ resource.repeat.offset = nil if resource.repeat.when.nil?
+ resource.repeat.period = resource.repeat.period * -1 if resource.repeat.period < 0
+ resource.repeat.period = 1.0 if resource.repeat.period == 0
+ resource.repeat.periodMax = nil if resource.repeat.period.nil?
+ resource.repeat.durationMax = nil if resource.repeat.duration.nil?
+ resource.repeat.countMax = nil if resource.repeat.count.nil?
+ resource.repeat.duration = nil if resource.repeat.durationUnit.nil?
+ resource.repeat.timeOfDay = nil unless resource.repeat.when.nil?
+ resource.repeat.period = nil if resource.repeat.periodUnit.nil?
+ end
+ when FHIR::STU3::ValueSet
+ if resource.compose
+ resource.compose.include.each do |inc|
+ inc.filter = nil if inc.concept
+ end
+ resource.compose.exclude.each do |exc|
+ exc.filter = nil if exc.concept
+ end
+ end
+ when FHIR::STU3::VisionPrescription
+ resource.dispense.each do |d|
+ d.duration.comparator = nil unless d.duration.nil?
+ end
+ when FHIR::STU3::RequestGroup::Action
+ if !resource.resource.nil? && resource.action.count > 0
+ if SecureRandom.random_number(2)==0
+ resource.resource = nil
+ else
+ resource.action = []
+ end
+ end
# DSTU2
when FHIR::DSTU2::Appointment
diff --git a/lib/tasks/tasks.rake b/lib/tasks/tasks.rake
index c7eea615..2795fe52 100644
--- a/lib/tasks/tasks.rake
+++ b/lib/tasks/tasks.rake
@@ -96,6 +96,8 @@ namespace :crucible do
require 'benchmark'
b = Benchmark.measure {
client = FHIR::Client.new(args.url)
+ client.use_r4
+ client.use_stu3 if fhir_version == :stu3
client.use_dstu2 if fhir_version == :dstu2
options = client.get_oauth2_metadata_from_conformance
set_client_secrets(client,options) unless options.empty?
@@ -113,7 +115,8 @@ namespace :crucible do
end
def resolve_fhir_version(version_string)
- fhir_version = :stu3
+ fhir_version = :r4
+ fhir_version = :stu3 if version_string.downcase == 'stu3'
fhir_version = :dstu2 if version_string.downcase == 'dstu2'
fhir_version
end
@@ -303,6 +306,8 @@ namespace :crucible do
puts "```"
b = Benchmark.measure {
client = FHIR::Client.new(url)
+ client.use_r4
+ client.use_stu3 if fhir_version == :stu3
client.use_dstu2 if fhir_version == :dstu2
options = client.get_oauth2_metadata_from_conformance
set_client_secrets(client,options) unless options.empty?
@@ -334,6 +339,8 @@ namespace :crucible do
puts "```"
b = Benchmark.measure {
client = FHIR::Client.new(url)
+ client.use_r4
+ client.use_stu3 if fhir_version == :stu3
client.use_dstu2 if fhir_version == :dstu2
options = client.get_oauth2_metadata_from_conformance
set_client_secrets(client,options) unless options.empty?
@@ -414,6 +421,8 @@ namespace :crucible do
end
client = FHIR::Client.new(args.url)
+ client.use_r4
+ client.use_stu3 if fhir_version == :stu3
client.use_dstu2 if fhir_version == :dstu2
options = client.get_oauth2_metadata_from_conformance
set_client_secrets(client,options) unless options.empty?
diff --git a/lib/tests/base_test.rb b/lib/tests/base_test.rb
index 127575cd..a3372303 100644
--- a/lib/tests/base_test.rb
+++ b/lib/tests/base_test.rb
@@ -36,11 +36,13 @@ class BaseTest
def initialize(client, client2=nil)
@client = client
FHIR::Resource.new.client = client
+ FHIR::DSTU2::Resource.new.client = client
+ FHIR::STU3::Resource.new.client = client
@client2 = client2
@client.monitor_requests if @client
@client2.monitor_requests if @client2
@tags ||= []
- @supported_versions ||= [:dstu2, :stu3]
+ @supported_versions ||= [:dstu2, :stu3, :r4]
@warnings = []
@setup_failed = false
@setup_requests = []
diff --git a/lib/tests/suites/base_suite.rb b/lib/tests/suites/base_suite.rb
index b7ca9555..f83911fe 100644
--- a/lib/tests/suites/base_suite.rb
+++ b/lib/tests/suites/base_suite.rb
@@ -33,7 +33,7 @@ def build_messages(operation_outcome)
# also, this may be causing a problem on the fhir starburst structure
def fhir_version
if @client.nil?
- :stu3
+ :r4
else
@client.fhir_version
end
@@ -58,6 +58,8 @@ def resource_from_contents(body)
def version_namespace
if @client.fhir_version.to_s.upcase == 'DSTU2'
"FHIR::DSTU2".constantize
+ elsif @client.fhir_version.to_s.upcase == 'STU3'
+ "FHIR::STU3".constantize
else
"FHIR".constantize
end
@@ -66,6 +68,8 @@ def version_namespace
def self.get_resource(fhir_version, resource)
if fhir_version.to_s.upcase == 'DSTU2'
"FHIR::DSTU2::#{resource}".constantize
+ elsif fhir_version.to_s.upcase == 'STU3'
+ "FHIR::STU3::#{resource}".constantize
else
"FHIR::#{resource}".constantize
end
@@ -76,6 +80,8 @@ def self.get_resource(fhir_version, resource)
def self.valid_resource?(fhir_version, resource)
if fhir_version.to_s.upcase == 'DSTU2'
FHIR::DSTU2::RESOURCES.include?(resource)
+ elsif fhir_version.to_s.upcase == 'STU3'
+ FHIR::STU3::RESOURCES.include?(resource)
else
FHIR::RESOURCES.include?(resource)
end
@@ -167,6 +173,12 @@ def self.test(key, desc, &block)
def resource_category(resource)
unless @resource_category
@categories_by_resource = {}
+ fhir_version = :r4
+ if resource.name.start_with? 'FHIR::DSTU2'
+ fhir_version = :dstu2
+ elsif resource.name.start_with? 'FHIR::STU3'
+ fhir_version = :stu3
+ end
fhir_structure = Crucible::FHIRStructure.get(fhir_version)
categories = fhir_structure['children'].select {|n| n['name'] == 'RESOURCES'}.first['children']
pull_children = lambda {|n, chain| n['children'].nil? ? n['name'] : n['children'].map {|child| chain.call(child, chain)}}
@@ -176,7 +188,7 @@ def resource_category(resource)
end
end
end
- @categories_by_resource[resource.underscore.humanize.downcase] || 'Uncategorized'
+ @categories_by_resource[resource.name.demodulize.underscore.humanize.downcase] || 'Uncategorized'
end
end
diff --git a/lib/tests/suites/read_test.rb b/lib/tests/suites/read_test.rb
index c6f5f942..14ae644b 100644
--- a/lib/tests/suites/read_test.rb
+++ b/lib/tests/suites/read_test.rb
@@ -7,7 +7,7 @@ def id
end
def description
- 'Initial Sprinkler tests (R001, R002, R003, R004) for testing basic READ requests.'
+ 'Initial Sprinkler tests (R001, R002, R003, R004, R005) for testing basic READ requests.'
end
def initialize(client1, client2=nil)
@@ -16,6 +16,7 @@ def initialize(client1, client2=nil)
end
def setup
+ @resources = Crucible::Generator::Resources.new(fhir_version)
# try to find a patient
begin
response = @client.read_feed(get_resource(:Patient))
@@ -23,7 +24,7 @@ def setup
rescue
# try to create a patient
begin
- @patient = get_resource(:Patient).new(meta: { tag: [{ system: 'http://projectcrucible.org', code: 'testdata'}] }, name: { family: 'Emerald', given: 'Caro' })
+ @patient = @client.create(@resources.example_patient).resource
@patient_created = true
rescue
@patient = nil
diff --git a/lib/tests/suites/resource_test.rb b/lib/tests/suites/resource_test.rb
index c5efdc76..1fec315c 100644
--- a/lib/tests/suites/resource_test.rb
+++ b/lib/tests/suites/resource_test.rb
@@ -44,7 +44,7 @@ def description
end
def category
- resource = @resource_class.nil? ? "Uncategorized" : resource_category(@resource_class.name.demodulize)
+ resource = @resource_class.nil? ? "Uncategorized" : resource_category(@resource_class)
{id: "resources_#{resource.parameterize}", title: "#{resource} Resources"}
end
diff --git a/lib/tests/suites/search_test.rb b/lib/tests/suites/search_test.rb
index 11ff9838..17f9c431 100644
--- a/lib/tests/suites/search_test.rb
+++ b/lib/tests/suites/search_test.rb
@@ -32,7 +32,7 @@ def description
end
def category
- resource = @resource_class.nil? ? "Uncategorized" : resource_category(@resource_class.name.demodulize)
+ resource = @resource_class.nil? ? "Uncategorized" : resource_category(@resource_class)
{id: "search_#{resource.parameterize}", title: "#{resource} Search"}
end
diff --git a/lib/tests/suites/sprinkler_search_test.rb b/lib/tests/suites/sprinkler_search_test.rb
index c633bc9b..93ba13d8 100644
--- a/lib/tests/suites/sprinkler_search_test.rb
+++ b/lib/tests/suites/sprinkler_search_test.rb
@@ -73,7 +73,7 @@ def create_observation(value)
observation.code = get_resource(:CodeableConcept).new
observation.code.coding = [ code ]
observation.valueQuantity = get_resource(:Quantity).new
- observation.valueQuantity.system = 'http://unitofmeasure.org'
+ observation.valueQuantity.system = 'http://unitsofmeasure.org'
observation.valueQuantity.value = value
observation.valueQuantity.unit = 'mmol'
body = get_resource(:Coding).new
diff --git a/lib/tests/suites/suite_engine.rb b/lib/tests/suites/suite_engine.rb
index ab461513..66f0972b 100644
--- a/lib/tests/suites/suite_engine.rb
+++ b/lib/tests/suites/suite_engine.rb
@@ -27,7 +27,7 @@ def self.list_all(metadata=false)
test_class = test.class.name.demodulize
#if t can set class
if test.respond_to? 'resource_class='
- [:dstu2, :stu3].each do |fhir_version|
+ [:dstu2, :stu3, :r4].each do |fhir_version|
Crucible::Tests::BaseSuite.fhir_resources(fhir_version).each do |klass|
klass_name = klass.name.demodulize
test_name = "#{test_class}#{klass_name}"
diff --git a/lib/tests/suites/transaction_test.rb b/lib/tests/suites/transaction_test.rb
index f38e8202..149e0c7b 100644
--- a/lib/tests/suites/transaction_test.rb
+++ b/lib/tests/suites/transaction_test.rb
@@ -170,7 +170,7 @@ def teardown
@condition0.subject.reference = "Patient/#{@patient0.id}"
@condition0.clinicalStatus = 'resolved'
@condition0.verificationStatus = 'refuted'
- @condition0.abatementBoolean = true
+ @condition0.abatementString = 'Abated at unknown date'
@client.begin_transaction
@client.add_transaction_request('DELETE',"Observation/#{@obs0b.id}") if @obs0b && !@obs0b.id.nil? # delete first weight
diff --git a/lib/tests/testscripts/testscript_engine.rb b/lib/tests/testscripts/testscript_engine.rb
index 44d7879f..8476381f 100644
--- a/lib/tests/testscripts/testscript_engine.rb
+++ b/lib/tests/testscripts/testscript_engine.rb
@@ -74,15 +74,12 @@ def self.parse_testscripts
script_files.each do |f|
begin
- script = FHIR.from_contents( File.read(f) )
- if script.is_a?(FHIR::TestScript) && script.valid?
+ script = FHIR::STU3.from_contents( File.read(f) )
+ if script.is_a?(FHIR::STU3::TestScript) && script.valid?
script.url = f # replace the URL with the local file path so file system references can properly resolve
@@models << script
- FHIR.logger.info "TestScriptEngine.parse_testscripts: Loaded #{f}"
- elsif script.is_a?(FHIR::TestScript)
+ elsif script.is_a?(FHIR::STU3::TestScript)
FHIR.logger.error "TestScriptEngine.parse_testscripts: Skipping invalid TestScript #{f}"
- else # this is a fixture...
- FHIR.logger.warn "TestScriptEngine.parse_testscripts: Skipping fixture #{f}"
end
rescue
FHIR.logger.error "TestScriptEngine.parse_testscripts: Exception deserializing TestScript #{f}"
diff --git a/plan_executor.gemspec b/plan_executor.gemspec
index 0115151f..bdb6b77f 100644
--- a/plan_executor.gemspec
+++ b/plan_executor.gemspec
@@ -18,6 +18,7 @@ Gem::Specification.new do |s|
s.add_runtime_dependency('nokogiri-diff')
s.add_runtime_dependency('fhir_client')
s.add_runtime_dependency('fhir_models')
+ s.add_runtime_dependency('fhir_stu3_models')
s.add_runtime_dependency('fhir_dstu2_models')
s.add_runtime_dependency('oauth2')
s.add_runtime_dependency('rest-client')
@@ -28,6 +29,7 @@ Gem::Specification.new do |s|
s.add_development_dependency('ansi')
s.add_development_dependency('rake')
s.add_development_dependency('pry')
+ s.add_development_dependency('pry-coolline')
s.add_development_dependency('webmock')
s.add_development_dependency('simplecov')
s.add_development_dependency('test-unit')
diff --git a/test/unit/fhir_structure_test.rb b/test/unit/fhir_structure_test.rb
index 52910a15..65d453ab 100644
--- a/test/unit/fhir_structure_test.rb
+++ b/test/unit/fhir_structure_test.rb
@@ -3,6 +3,11 @@
class FHIRStructureTest < Test::Unit::TestCase
def test_fhir_starburst_root
+ structure = Crucible::FHIRStructure.get(:r4)
+ structure['name'] == 'FHIR'
+ end
+
+ def test_fhir_starburst_stu3
structure = Crucible::FHIRStructure.get(:stu3)
structure['name'] == 'FHIR'
end
@@ -21,13 +26,23 @@ def test_no_duplicate_names_in_starburst
end
end
+ def fhir_resources(fhir_version=nil)
+
+ resources = FHIR::RESOURCES
+ namespace = 'FHIR'
+ if !fhir_version.nil? && FHIR.constants.include?(fhir_version.upcase)
+ resources = FHIR.const_get(fhir_version.upcase)::RESOURCES
+ end
+ resources
+ end
+
def test_no_missing_resources_in_starburst
- [:stu3, :dstu2].each do |version|
- structure = Crucible::FHIRStructure.get
+ [:r4, :stu3, :dstu2].each do |version|
+ structure = Crucible::FHIRStructure.get(version)
resource_subset = structure['children'].select{|c| c['name'] == 'RESOURCES'}.first
structure_resources = all_names(resource_subset, true).map{|e| e.downcase.delete(' ')}
- model_resources = FHIR::RESOURCES.map(&:downcase).reject{|m| m == 'resource' || m == "domainresource"}
+ model_resources = fhir_resources(version).map(&:downcase).reject{|m| m == 'resource' || m == "domainresource"}
missing_resources = model_resources - structure_resources
extra_resources = structure_resources - model_resources
@@ -46,7 +61,7 @@ def test_no_unknown_requires_in_tests
names = []
- [:dstu2, :stu3].each do |version|
+ [:dstu2, :stu3, :r4].each do |version|
structure = Crucible::FHIRStructure.get(version)
names.concat(all_names(structure).map{|e| e.downcase.delete(' ')})
end
diff --git a/test/unit/fixtures_test.rb b/test/unit/fixtures_test.rb
index 4f7a29ea..54eb7045 100644
--- a/test/unit/fixtures_test.rb
+++ b/test/unit/fixtures_test.rb
@@ -15,57 +15,78 @@ class FixturesTest < Test::Unit::TestCase
Dir.glob(fixtures).each do | file |
basename = File.basename(file,'.xml')
next if basename.start_with?('ccda')
+
+ version = file.match(/fixtures\/([^\/]+)/)[1]
xml = File.open(file, 'r:bom|UTF-8', &:read)
- define_method("test_fixture_validation_#{basename}") do
- run_validate(basename,xml)
+ define_method("test_fixture_validation_#{basename}_#{version}") do
+ run_validate(basename, xml, version.to_sym)
end
end
Dir.glob(json_fixtures).each do | file |
basename = File.basename(file,'.json')
json = File.open(file, 'r:bom|UTF-8', &:read)
- define_method("test_json_fixture_validation_#{basename}") do
- run_json_validate(basename,json)
+ version = file.match(/fixtures\/([^\/]+)/)[1]
+ define_method("test_json_fixture_validation_#{basename}_#{version}") do
+ run_json_validate(basename, json, version.to_sym)
end
end
- def run_validate(fixture,xml)
+ def xml_namespace(fhir_version)
+ namespace = FHIR::Xml
+ if !fhir_version.nil? && FHIR.constants.include?(fhir_version.upcase)
+ namespace = FHIR.const_get(fhir_version.upcase)::Xml
+ end
+ namespace
+ end
+
+ def json_namespace(fhir_version)
+ namespace = FHIR::Json
+ if !fhir_version.nil? && FHIR.constants.include?(fhir_version.upcase)
+ namespace = FHIR.const_get(fhir_version.upcase)::Json
+ end
+ namespace
+ end
+
+ def run_validate(fixture, xml, version)
assert(fixture && xml)
+ xml_namespace = xml_namespace(version)
- r = FHIR::Xml.from_xml(xml)
+ r = xml_namespace.from_xml(xml)
assert(!r.nil?,"XML fixture does not deserialize.")
- errors = FHIR::Xml.validate(xml)
+ errors = xml_namespace.validate(xml)
if !errors.empty?
- File.open("#{ERROR_DIR}/#{fixture}.err", 'w:UTF-8') do |file|
- file.write "#{fixture}: #{errors.length} errors\n\n"
+ File.open("#{ERROR_DIR}/#{version}_#{fixture}.err", 'w:UTF-8') do |file|
+ file.write "#{version}_#{fixture}: #{errors.length} errors\n\n"
errors.each do |error|
file.write(sprintf("%-8d %s\n", error.line, error.message))
end
end
- File.open("#{ERROR_DIR}/#{fixture}.xml", 'w:UTF-8') { |file| file.write(xml) }
+ File.open("#{ERROR_DIR}/#{version}_#{fixture}.xml", 'w:UTF-8') { |file| file.write(xml) }
end
assert(errors.empty?,"XML fixture does not conform to schema.")
end
-
- def run_json_validate(fixture,json)
+ def run_json_validate(fixture,json,version)
assert(fixture && json)
- r = FHIR::Json.from_json(json)
+ json_namespace = json_namespace(version)
+
+ r = json_namespace.from_json(json)
assert(!r.nil?,"JSON fixture does not deserialize.")
errors = r.validate
if !errors.empty?
- File.open("#{ERROR_DIR}/#{fixture}.err", 'w:UTF-8') do |file|
- file.write "#{fixture}: #{errors.length} errors\n\n"
+ File.open("#{ERROR_DIR}/#{version}_#{fixture}.err", 'w:UTF-8') do |file|
+ file.write "#{version}_#{fixture}: #{errors.length} errors\n\n"
errors.each do |error|
file.write(sprintf("%-8d %s\n", error.line, error.message))
end
end
- File.open("#{ERROR_DIR}/#{fixture}.json", 'w:UTF-8') { |file| file.write(json) }
+ File.open("#{ERROR_DIR}/#{version}_#{fixture}.json", 'w:UTF-8') { |file| file.write(json) }
end
assert(errors.empty?,"JSON fixture does not conform to definition.")
diff --git a/test/unit/resource_generator_test.rb b/test/unit/resource_generator_test.rb
index 2d0f6ff4..b86b4231 100644
--- a/test/unit/resource_generator_test.rb
+++ b/test/unit/resource_generator_test.rb
@@ -2,12 +2,28 @@
class ResourceGeneratorTest < Test::Unit::TestCase
+ ERROR_DIR = File.join('tmp', 'errors', 'GeneratorTest')
+ # Create a blank folder for the errors
+ FileUtils.rm_rf(ERROR_DIR) if File.directory?(ERROR_DIR)
+ FileUtils.mkdir_p ERROR_DIR
+
# Define test methods for each resource type
FHIR::RESOURCES.each do | resource_type |
3.times do |index|
max_depth = index + 2
- define_method("test_resource_generator_#{resource_type}_#{max_depth}") do
- run_generator(resource_type, :stu3, max_depth )
+ define_method("test_resource_generator_r4_#{resource_type}_#{max_depth}") do
+ run_generator(resource_type, :r4, max_depth )
+ end
+ end
+ end
+
+ # Also check to make sure that everything in the resource is within the STU3 namespace
+ FHIR::STU3::RESOURCES.each do | resource_type |
+ 3.times do |index|
+ max_depth = index + 2
+ define_method("test_resource_generator_stu3_#{resource_type}_#{max_depth}") do
+ resource = run_generator(resource_type, :stu3, max_depth)
+ assert check_valid_namespaces(resource, 'FHIR::STU3'), "Resource Generator created a class of type FHIR::STU3::#{resource_type} that contained elements from the wrong version."
end
end
end
@@ -26,7 +42,7 @@ class ResourceGeneratorTest < Test::Unit::TestCase
def run_generator(resource_type, version, max_depth)
klass_namespace = "FHIR"
- if version != :stu3
+ if version != :r4
klass_namespace = "FHIR::#{version.to_s.upcase}"
end
klass = Module.const_get("#{klass_namespace}::#{resource_type}")
@@ -34,7 +50,15 @@ def run_generator(resource_type, version, max_depth)
r = Crucible::Tests::ResourceGenerator.generate(klass,max_depth)
assert !r.nil?, "Resource Generator could not generate #{resource_type} with max depth #{max_depth}"
errors = r.validate
- assert errors.empty?, "Resource Generator could not generate valid #{resource_type} with max depth #{max_depth}\n\n#{r.to_json}\n\nERRORS: #{errors}"
+
+ if !errors.empty?
+ File.open("#{ERROR_DIR}/#{version}_#{resource_type}_#{max_depth}.err", 'w:UTF-8') do |file|
+ file.write(JSON.pretty_generate(errors))
+ end
+ File.open("#{ERROR_DIR}/#{version}_#{resource_type}_#{max_depth}.json", 'w:UTF-8') { |file| file.write(r.to_json) }
+ end
+
+ assert errors.empty?, "Resource Generator could not generate valid #{resource_type} with max depth #{max_depth}"
r
end