From f962589e191bbb368f77cb90ce8a8ce021ce2019 Mon Sep 17 00:00:00 2001 From: Rob Scanlon Date: Sat, 4 May 2019 00:15:01 -0400 Subject: [PATCH 01/15] Move all STU3 references to FHIR::STU3 --- .gitignore | 1 + Gemfile.lock | 33 +- fixtures/{ => stu3}/attachment/ccda_pdf.pdf | Bin .../{ => stu3}/attachment/ccda_pdf_base64.txt | 0 .../{ => stu3}/attachment/ccda_structured.xml | 0 .../attachment/ccda_unstructured.xml | 0 .../diagnosticreport-familyhistory-create.xml | 0 .../diagnosticreport-hlatyping-create.xml | 0 ...iagnosticreport-pathologyreport-create.xml | 0 .../{ => stu3}/diagnostic_report/dr-100.xml | 0 .../{ => stu3}/diagnostic_report/dr-200.xml | 0 .../{ => stu3}/diagnostic_report/dr-300.xml | 0 .../{ => stu3}/diagnostic_report/dr-400.xml | 0 .../{ => stu3}/diagnostic_request/do-100.xml | 0 .../{ => stu3}/diagnostic_request/do-200.xml | 0 .../{ => stu3}/diagnostic_request/do-300.xml | 0 .../{ => stu3}/diagnostic_request/do-400.xml | 0 ...milymemberhistory-familyhistory-create.xml | 0 .../financial/claim-example-oral-average.xml | 0 .../claim-example-oral-orthoplan.xml | 0 .../{ => stu3}/financial/claim-example.xml | 0 .../financial/eligibilityrequest-example.xml | 0 fixtures/{ => stu3}/observation/obs-100.xml | 0 fixtures/{ => stu3}/observation/obs-101.xml | 0 fixtures/{ => stu3}/observation/obs-200.xml | 0 fixtures/{ => stu3}/observation/obs-300.xml | 0 fixtures/{ => stu3}/observation/obs-301.xml | 0 fixtures/{ => stu3}/observation/obs-302.xml | 0 fixtures/{ => stu3}/observation/obs-303.xml | 0 fixtures/{ => stu3}/observation/obs-304.xml | 0 fixtures/{ => stu3}/observation/obs-400.xml | 0 fixtures/{ => stu3}/observation/obs-401.xml | 0 fixtures/{ => stu3}/observation/obs-402.xml | 0 fixtures/{ => stu3}/observation/obs-403.xml | 0 fixtures/{ => stu3}/observation/obs-404.xml | 0 fixtures/{ => stu3}/observation/obs-405.xml | 0 fixtures/{ => stu3}/observation/obs-406.xml | 0 fixtures/{ => stu3}/observation/obs-407.xml | 0 fixtures/{ => stu3}/observation/obs-408.xml | 0 .../observation/obs-uslab-example5.xml | 0 .../observation-datawarehouse-create.xml | 0 .../observation-familyhistory-create.xml | 0 .../observation-germline-create.xml | 0 .../observation-register-create.xml | 0 .../organization/org-uslab-example3.xml | 0 .../patch/medicationrequest-simple.xml | 0 .../patient/patient-example-updated.xml | 0 .../patient/patient-example-us-extensions.xml | 0 .../{ => stu3}/patient/patient-example.xml | 0 .../patient/patient-familyhistory-create.xml | 0 .../{ => stu3}/patient/patient-minimal.xml | 0 .../patient/patient-register-create.xml | 0 .../patient/patient-uslab-example1.xml | 0 .../practitioner/pract-uslab-example1.xml | 0 .../practitioner/pract-uslab-example3.xml | 0 .../practitioner-register-create.xml | 0 .../record/condition-example-f201-fever.xml | 0 .../condition-example-f205-infection.xml | 0 .../diagnosticreport-example-f201-brainct.xml | 0 .../encounter-example-f201-20130404.xml | 0 .../encounter-example-f202-20130128.xml | 0 .../observation-example-f202-temperature.xml | 0 .../record/organization-example-f201-aumc.xml | 0 .../record/organization-example-f203-bumc.xml | 0 .../record/patient-example-f201-roel.xml | 0 .../record/practitioner-example-f201-ab.xml | 0 .../record/procedure-example-f201-tpf.xml | 0 .../scheduling/appointment-simple.xml | 0 .../appointmentresponse-patient-simple.xml | 0 ...ppointmentresponse-practitioner-simple.xml | 0 .../scheduling/practitioner-simple.xml | 0 .../{ => stu3}/scheduling/schedule-simple.xml | 0 .../{ => stu3}/scheduling/slot-simple.xml | 0 .../sequence/sequence-register-create.xml | 0 fixtures/{ => stu3}/specimen/spec-100.xml | 0 fixtures/{ => stu3}/specimen/spec-400.xml | 0 .../specimen/spec-uslab-example1.xml | 0 .../specimen-familyhistory-create.xml | 0 .../specimen/specimen-register-create.xml | 0 .../terminology/codesystem-data-types.json | 0 .../codesystem-resource-types.json | 0 .../terminology/codesystem-simple.xml | 0 .../terminology/conceptmap-example.xml | 0 .../{ => stu3}/terminology/v2-codesystem.json | 0 .../{ => stu3}/terminology/v2-valueset.json | 0 .../terminology/valueset-defined-types.json | 0 .../terminology/valueset-example.xml | 0 .../uscore/CapabilityStatement-server.json | 0 .../validation/observation.profile.xml | 0 .../observations/observation-example.xml | 0 lib/FHIR_structure.json | 173 +++-- lib/FHIR_structure_r4.json | 713 ++++++++++++++++++ lib/data/fhir_structure.rb | 2 +- lib/data/resources.rb | 98 +-- lib/resource_generator.rb | 268 +++---- lib/tests/base_test.rb | 2 + lib/tests/suites/base_suite.rb | 4 + lib/tests/testscripts/testscript_engine.rb | 6 +- plan_executor.gemspec | 1 + test/unit/fhir_structure_test.rb | 16 +- test/unit/fixtures_test.rb | 53 +- test/unit/resource_generator_test.rb | 34 +- 102 files changed, 1139 insertions(+), 265 deletions(-) rename fixtures/{ => stu3}/attachment/ccda_pdf.pdf (100%) rename fixtures/{ => stu3}/attachment/ccda_pdf_base64.txt (100%) rename fixtures/{ => stu3}/attachment/ccda_structured.xml (100%) rename fixtures/{ => stu3}/attachment/ccda_unstructured.xml (100%) rename fixtures/{ => stu3}/diagnostic_report/diagnosticreport-familyhistory-create.xml (100%) rename fixtures/{ => stu3}/diagnostic_report/diagnosticreport-hlatyping-create.xml (100%) rename fixtures/{ => stu3}/diagnostic_report/diagnosticreport-pathologyreport-create.xml (100%) rename fixtures/{ => stu3}/diagnostic_report/dr-100.xml (100%) rename fixtures/{ => stu3}/diagnostic_report/dr-200.xml (100%) rename fixtures/{ => stu3}/diagnostic_report/dr-300.xml (100%) rename fixtures/{ => stu3}/diagnostic_report/dr-400.xml (100%) rename fixtures/{ => stu3}/diagnostic_request/do-100.xml (100%) rename fixtures/{ => stu3}/diagnostic_request/do-200.xml (100%) rename fixtures/{ => stu3}/diagnostic_request/do-300.xml (100%) rename fixtures/{ => stu3}/diagnostic_request/do-400.xml (100%) rename fixtures/{ => stu3}/family_member_history/familymemberhistory-familyhistory-create.xml (100%) rename fixtures/{ => stu3}/financial/claim-example-oral-average.xml (100%) rename fixtures/{ => stu3}/financial/claim-example-oral-orthoplan.xml (100%) rename fixtures/{ => stu3}/financial/claim-example.xml (100%) rename fixtures/{ => stu3}/financial/eligibilityrequest-example.xml (100%) rename fixtures/{ => stu3}/observation/obs-100.xml (100%) rename fixtures/{ => stu3}/observation/obs-101.xml (100%) rename fixtures/{ => stu3}/observation/obs-200.xml (100%) rename fixtures/{ => stu3}/observation/obs-300.xml (100%) rename fixtures/{ => stu3}/observation/obs-301.xml (100%) rename fixtures/{ => stu3}/observation/obs-302.xml (100%) rename fixtures/{ => stu3}/observation/obs-303.xml (100%) rename fixtures/{ => stu3}/observation/obs-304.xml (100%) rename fixtures/{ => stu3}/observation/obs-400.xml (100%) rename fixtures/{ => stu3}/observation/obs-401.xml (100%) rename fixtures/{ => stu3}/observation/obs-402.xml (100%) rename fixtures/{ => stu3}/observation/obs-403.xml (100%) rename fixtures/{ => stu3}/observation/obs-404.xml (100%) rename fixtures/{ => stu3}/observation/obs-405.xml (100%) rename fixtures/{ => stu3}/observation/obs-406.xml (100%) rename fixtures/{ => stu3}/observation/obs-407.xml (100%) rename fixtures/{ => stu3}/observation/obs-408.xml (100%) rename fixtures/{ => stu3}/observation/obs-uslab-example5.xml (100%) rename fixtures/{ => stu3}/observation/observation-datawarehouse-create.xml (100%) rename fixtures/{ => stu3}/observation/observation-familyhistory-create.xml (100%) rename fixtures/{ => stu3}/observation/observation-germline-create.xml (100%) rename fixtures/{ => stu3}/observation/observation-register-create.xml (100%) rename fixtures/{ => stu3}/organization/org-uslab-example3.xml (100%) rename fixtures/{ => stu3}/patch/medicationrequest-simple.xml (100%) rename fixtures/{ => stu3}/patient/patient-example-updated.xml (100%) rename fixtures/{ => stu3}/patient/patient-example-us-extensions.xml (100%) rename fixtures/{ => stu3}/patient/patient-example.xml (100%) rename fixtures/{ => stu3}/patient/patient-familyhistory-create.xml (100%) rename fixtures/{ => stu3}/patient/patient-minimal.xml (100%) rename fixtures/{ => stu3}/patient/patient-register-create.xml (100%) rename fixtures/{ => stu3}/patient/patient-uslab-example1.xml (100%) rename fixtures/{ => stu3}/practitioner/pract-uslab-example1.xml (100%) rename fixtures/{ => stu3}/practitioner/pract-uslab-example3.xml (100%) rename fixtures/{ => stu3}/practitioner/practitioner-register-create.xml (100%) rename fixtures/{ => stu3}/record/condition-example-f201-fever.xml (100%) rename fixtures/{ => stu3}/record/condition-example-f205-infection.xml (100%) rename fixtures/{ => stu3}/record/diagnosticreport-example-f201-brainct.xml (100%) rename fixtures/{ => stu3}/record/encounter-example-f201-20130404.xml (100%) rename fixtures/{ => stu3}/record/encounter-example-f202-20130128.xml (100%) rename fixtures/{ => stu3}/record/observation-example-f202-temperature.xml (100%) rename fixtures/{ => stu3}/record/organization-example-f201-aumc.xml (100%) rename fixtures/{ => stu3}/record/organization-example-f203-bumc.xml (100%) rename fixtures/{ => stu3}/record/patient-example-f201-roel.xml (100%) rename fixtures/{ => stu3}/record/practitioner-example-f201-ab.xml (100%) rename fixtures/{ => stu3}/record/procedure-example-f201-tpf.xml (100%) rename fixtures/{ => stu3}/scheduling/appointment-simple.xml (100%) rename fixtures/{ => stu3}/scheduling/appointmentresponse-patient-simple.xml (100%) rename fixtures/{ => stu3}/scheduling/appointmentresponse-practitioner-simple.xml (100%) rename fixtures/{ => stu3}/scheduling/practitioner-simple.xml (100%) rename fixtures/{ => stu3}/scheduling/schedule-simple.xml (100%) rename fixtures/{ => stu3}/scheduling/slot-simple.xml (100%) rename fixtures/{ => stu3}/sequence/sequence-register-create.xml (100%) rename fixtures/{ => stu3}/specimen/spec-100.xml (100%) rename fixtures/{ => stu3}/specimen/spec-400.xml (100%) rename fixtures/{ => stu3}/specimen/spec-uslab-example1.xml (100%) rename fixtures/{ => stu3}/specimen/specimen-familyhistory-create.xml (100%) rename fixtures/{ => stu3}/specimen/specimen-register-create.xml (100%) rename fixtures/{ => stu3}/terminology/codesystem-data-types.json (100%) rename fixtures/{ => stu3}/terminology/codesystem-resource-types.json (100%) rename fixtures/{ => stu3}/terminology/codesystem-simple.xml (100%) rename fixtures/{ => stu3}/terminology/conceptmap-example.xml (100%) rename fixtures/{ => stu3}/terminology/v2-codesystem.json (100%) rename fixtures/{ => stu3}/terminology/v2-valueset.json (100%) rename fixtures/{ => stu3}/terminology/valueset-defined-types.json (100%) rename fixtures/{ => stu3}/terminology/valueset-example.xml (100%) rename fixtures/{ => stu3}/uscore/CapabilityStatement-server.json (100%) rename fixtures/{ => stu3}/validation/observation.profile.xml (100%) rename fixtures/{ => stu3}/validation/observations/observation-example.xml (100%) create mode 100644 lib/FHIR_structure_r4.json 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 99ae0bcc..986135b2 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) @@ -37,25 +38,31 @@ 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.9) bcp47 (>= 0.3) date_time_precision (>= 0.8) - mime-types (>= 1.16, < 3) + mime-types (>= 3.0) + nokogiri (>= 1.8.5) + fhir_models (4.0.0) + bcp47 (>= 0.3) + date_time_precision (>= 0.8) + mime-types (>= 3.0) nokogiri (>= 1.8.2) - fhir_models (3.0.3) + fhir_stu3_models (3.0.0) bcp47 (>= 0.3) date_time_precision (>= 0.8) - mime-types (>= 1.16, < 3) + mime-types (>= 3.0) nokogiri (>= 1.8.2) hashdiff (0.3.8) http-cookie (1.0.3) @@ -68,14 +75,16 @@ GEM to_regexp (~> 0.2.1) jwt (2.1.0) method_source (0.9.2) - mime-types (2.99.3) + mime-types (3.2.2) + mime-types-data (~> 3.2015) + mime-types-data (3.2019.0331) 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.1) + nokogiri (1.10.3) mini_portile2 (~> 2.4.0) nokogiri-diff (0.2.0) nokogiri (~> 1.5) @@ -91,7 +100,7 @@ GEM coderay (~> 1.1.0) method_source (~> 0.9.0) public_suffix (3.0.3) - rack (2.0.6) + rack (2.0.7) rake (12.3.2) rest-client (2.0.2) http-cookie (>= 1.0.2, < 2.0) @@ -113,7 +122,7 @@ GEM thread_safe (~> 0.1) unf (0.1.4) unf_ext - unf_ext (0.0.7.5) + unf_ext (0.0.7.6) webmock (3.5.1) addressable (>= 2.3.6) crack (>= 0.3.2) 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..020343c7 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,48 @@ "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": "$lookup" + },{ + "name": "$subsumes" + },{ + "name": "$find-matches" },{ "name": "$document" },{ @@ -126,7 +170,7 @@ },{ "name": "graph definition" },{ - "name": "data element" + "name": "example scenario" } ] },{ @@ -138,10 +182,10 @@ "name": "value set" },{ "name": "concept map" - },{ - "name": "expansion profile" },{ "name": "naming system" + },{ + "name": "terminology capabilities" } ] },{ @@ -166,6 +210,8 @@ "name": "document manifest" },{ "name": "document reference" + },{ + "name": "catalog entry" } ] },{ @@ -180,8 +226,6 @@ "name": "bundle" },{ "name": "linkage" - },{ - "name": "media" },{ "name": "message header" },{ @@ -220,6 +264,8 @@ "children": [ { "name": "organization" + },{ + "name": "organization affiliation" },{ "name": "healthcare service" },{ @@ -228,10 +274,10 @@ "name": "location" },{ "name": "substance" + },{ + "name": "biologically derived product" }, { "name": "device" - },{ - "name": "device component" },{ "name": "device metric" } @@ -251,9 +297,7 @@ },{ "name": "slot" },{ - "name": "process request" - },{ - "name": "process response" + "name": "verification result" } ] },{ @@ -302,21 +346,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 +381,8 @@ "name": "medication" },{ "name": "immunization" + },{ + "name": "immunization evaluation" },{ "name": "immunization recommendation" } @@ -350,10 +397,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 +421,8 @@ "aka": ["device use request"] },{ "name": "device use statement" + },{ + "name": "guidance response" },{ "name": "supply request" },{ @@ -394,9 +440,9 @@ { "name": "coverage" },{ - "name": "eligibility request" + "name": "coverage eligibility request" },{ - "name": "eligibility response" + "name": "coverage eligibility response" },{ "name": "enrollment request" },{ @@ -410,6 +456,8 @@ "name": "claim" },{ "name": "claim response" + },{ + "name": "invoice" } ] },{ @@ -426,13 +474,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 +506,76 @@ "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" } ] } diff --git a/lib/FHIR_structure_r4.json b/lib/FHIR_structure_r4.json new file mode 100644 index 00000000..6a5cd540 --- /dev/null +++ b/lib/FHIR_structure_r4.json @@ -0,0 +1,713 @@ +{ + "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": "$lookup" + },{ + "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": "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..bc735840 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=) @@ -179,13 +180,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 +199,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 +264,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 @@ -283,37 +284,37 @@ def self.tag_metadata(resource, namespace = FHIR) def self.apply_invariants!(resource) case resource ## STU3 - when FHIR::ActivityDefinition + when FHIR::STU3::ActivityDefinition resource.quantity.comparator = nil unless resource.quantity.nil? - when FHIR::Age + 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::AllergyIntolerance + when FHIR::STU3::AllergyIntolerance resource.clinicalStatus = nil if resource.verificationStatus=='entered-in-error' - when FHIR::Duration + when FHIR::STU3::Duration resource.system = 'http://unitsofmeasure.org' resource.code = 'mo' resource.unit = nil resource.comparator = nil - when FHIR::Money + when FHIR::STU3::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.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') ] - when FHIR::AuditEvent + 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::Bundle + 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' @@ -322,17 +323,17 @@ def self.apply_invariants!(resource) head = resource.entry.first if !head.nil? if resource.type == 'document' - head.resource = generate(FHIR::Composition,3) + head.resource = generate(FHIR::STU3::Composition,3) elsif resource.type == 'message' - head.resource = generate(FHIR::MessageHeader,3) + head.resource = generate(FHIR::STU3::MessageHeader,3) else - head.resource = generate(FHIR::Basic,3) + 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::CarePlan + when FHIR::STU3::CarePlan resource.activity.each do |a| unless a.detail.nil? a.reference = nil @@ -340,11 +341,11 @@ def self.apply_invariants!(resource) a.detail.quantity.comparator = nil unless a.detail.quantity.nil? end end - when FHIR::CareTeam + when FHIR::STU3::CareTeam resource.participant.each do |p| p.onBehalfOf = nil end - when FHIR::CodeSystem + when FHIR::STU3::CodeSystem resource.concept.each do |c| c.concept.each do |d| d.property.each do |p| @@ -357,7 +358,7 @@ def self.apply_invariants!(resource) end end end - when FHIR::CapabilityStatement + when FHIR::STU3::CapabilityStatement resource.kind = 'instance' resource.rest.each do |r| r.resource.each do |res| @@ -368,9 +369,9 @@ def self.apply_invariants!(resource) resource.messaging.each do |m| m.supportedMessage = [] if m.event.length > 0 end - when FHIR::Claim + when FHIR::STU3::Claim resource.item.each do |item| - item.category = minimal_codeableconcept('http://hl7.org/fhir/benefit-subcategory','35') + 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 @@ -378,32 +379,32 @@ def self.apply_invariants!(resource) 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') + sub.service = minimal_codeableconcept('http://hl7.org/fhir/ex-USCLS','1205', FHIR::STU3) end end end - when FHIR::ClaimResponse + when FHIR::STU3::ClaimResponse resource.item.each do |item| - item.adjudication.each{|a|a.category = minimal_codeableconcept('http://hl7.org/fhir/adjudication','benefit')} + 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')} + 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')} + 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')} + 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')} + detail.adjudication.each{|a|a.category = minimal_codeableconcept('http://hl7.org/fhir/adjudication','benefit', FHIR::STU3)} end end - when FHIR::Communication + when FHIR::STU3::Communication resource.payload = nil - when FHIR::CommunicationRequest + when FHIR::STU3::CommunicationRequest resource.payload = nil resource.requester.onBehalfOf = nil unless resource.requester.nil? - when FHIR::Composition + when FHIR::STU3::Composition resource.attester.each {|a| a.mode = ['professional']} resource.section.each do |section| section.emptyReason = nil @@ -412,14 +413,14 @@ def self.apply_invariants!(resource) sub.section = nil end end - when FHIR::ConceptMap + when FHIR::STU3::ConceptMap if(resource.sourceUri.nil? && resource.sourceReference.nil?) - resource.sourceReference = textonly_reference('ValueSet') + resource.sourceReference = textonly_reference('ValueSet', FHIR::STU3) end if(resource.targetUri.nil? && resource.targetReference.nil?) - resource.targetReference = textonly_reference('ValueSet') + resource.targetReference = textonly_reference('ValueSet', FHIR::STU3) end - when FHIR::Condition + when FHIR::STU3::Condition if resource.onsetAge resource.onsetAge.system = 'http://unitsofmeasure.org' resource.onsetAge.code = 'a' @@ -440,7 +441,7 @@ def self.apply_invariants!(resource) resource.onsetAge, resource.abatementAge = resource.abatementAge, resource.onsetAge end end - when FHIR::CapabilityStatement + when FHIR::STU3::CapabilityStatement resource.fhirVersion = 'STU3' resource.format = ['xml','json'] if resource.kind == 'capability' @@ -450,9 +451,9 @@ def self.apply_invariants!(resource) resource.software = nil end resource.messaging.each{|m| m.endpoint = nil} if resource.kind != 'instance' - when FHIR::Contract + when FHIR::STU3::Contract resource.agent.each do |agent| - agent.actor = textonly_reference('Patient') + agent.actor = textonly_reference('Patient', FHIR::STU3) end resource.valuedItem.each do |item| if item.unitPrice @@ -471,11 +472,11 @@ def self.apply_invariants!(resource) end resource.term.each do |term| term.agent.each do |agent| - agent.actor = textonly_reference('Organization') + agent.actor = textonly_reference('Organization', FHIR::STU3) end term.group.each do |group| group.agent.each do |agent| - agent.actor = textonly_reference('Organization') + agent.actor = textonly_reference('Organization', FHIR::STU3) end end term.valuedItem.each do |item| @@ -496,43 +497,43 @@ def self.apply_invariants!(resource) end resource.friendly.each do |f| f.contentAttachment = nil - f.contentReference = textonly_reference('DocumentReference') + f.contentReference = textonly_reference('DocumentReference', FHIR::STU3) end resource.legal.each do |f| f.contentAttachment = nil - f.contentReference = textonly_reference('DocumentReference') + f.contentReference = textonly_reference('DocumentReference', FHIR::STU3) end resource.rule.each do |f| f.contentAttachment = nil - f.contentReference = textonly_reference('DocumentReference') + f.contentReference = textonly_reference('DocumentReference', FHIR::STU3) end - when FHIR::DataElement + when FHIR::STU3::DataElement 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::DeviceComponent + 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::DeviceMetric + when FHIR::STU3::DeviceMetric resource.measurementPeriod = nil - when FHIR::DiagnosticReport + when FHIR::STU3::DiagnosticReport date = DateTime.now resource.effectiveDateTime = date.strftime("%Y-%m-%dT%T.%LZ") resource.effectivePeriod = nil - when FHIR::DocumentManifest + when FHIR::STU3::DocumentManifest resource.content.each do |c| c.pAttachment = nil - c.pReference = textonly_reference('Any') + c.pReference = textonly_reference('Any', FHIR::STU3) end - when FHIR::DocumentReference + when FHIR::STU3::DocumentReference resource.docStatus = 'preliminary' - when FHIR::Dosage + 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? @@ -545,7 +546,7 @@ def self.apply_invariants!(resource) resource.rateRange.high.comparator = nil unless resource.rateRange.high.nil? end resource.rateQuantity.comparator = nil unless resource.rateQuantity.nil? - when FHIR::ElementDefinition + when FHIR::STU3::ElementDefinition keys = [] resource.constraint.each do |constraint| constraint.key = SecureRandom.base64 if constraint.key.nil? @@ -567,7 +568,7 @@ def self.apply_invariants!(resource) end resource.binding = nil unless is_codeable resource.contentReference = nil - FHIR::ElementDefinition::MULTIPLE_TYPES['defaultValue'].each do |type| + 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) @@ -575,15 +576,16 @@ 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 + when FHIR::STU3::EligibilityResponse resource.insurance.each do |i| i.benefitBalance.each do |b| b.financial = [] end end - when FHIR::ExpansionProfile + when FHIR::STU3::ExpansionProfile resource.designation.exclude = nil unless resource.designation.nil? - when FHIR::ExplanationOfBenefit + 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? @@ -591,7 +593,7 @@ def self.apply_invariants!(resource) resource.addItem.each do |item| item.detail = [] end - when FHIR::FamilyMemberHistory + when FHIR::STU3::FamilyMemberHistory if resource.ageAge resource.ageAge.system = 'http://unitsofmeasure.org' resource.ageAge.code = 'a' @@ -616,12 +618,12 @@ def self.apply_invariants!(resource) resource.deceasedAge.unit = nil resource.deceasedAge.comparator = nil end - when FHIR::Goal + when FHIR::STU3::Goal resource.outcomeCode.each do |code| code = nil end resource.outcomeReference.each do |reference| - reference = textonly_reference('Observation') + reference = textonly_reference('Observation', FHIR::STU3) end if resource.target && resource.target.dueDuration resource.target.dueDuration.system = 'http://unitsofmeasure.org' @@ -629,7 +631,7 @@ def self.apply_invariants!(resource) resource.target.dueDuration.unit = nil resource.target.dueDuration.comparator = nil end - when FHIR::Group + when FHIR::STU3::Group resource.member = [] if resource.actual==false resource.characteristic.each do |c| c.valueCodeableConcept = nil @@ -637,7 +639,7 @@ def self.apply_invariants!(resource) c.valueQuantity = nil c.valueRange = nil end - when FHIR::ImagingStudy + when FHIR::STU3::ImagingStudy resource.uid = random_oid availability = ['ONLINE', 'OFFLINE', 'NEARLINE', 'UNAVAILABLE'] resource.series.each do |series| @@ -649,7 +651,7 @@ def self.apply_invariants!(resource) end end resource.availability = availability.sample - when FHIR::ImagingManifest + when FHIR::STU3::ImagingManifest resource.study.each do |study| study.series.each do |series| series.instance.each do |i| @@ -658,39 +660,39 @@ def self.apply_invariants!(resource) end end end - when FHIR::Immunization + 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}") ] + 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}") ] + resource.explanation.reason = [ textonly_codeableconcept("reason #{SecureRandom.base64}", FHIR::STU3) ] end end resource.status = ['completed','entered-in-error'].sample - when FHIR::ImplementationGuide + 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') + r.sourceReference = textonly_reference('Any', FHIR::STU3) end end - when FHIR::Linkage + when FHIR::STU3::Linkage if resource.item.length == 1 resource.item << resource.item.first # must have 2 end - when FHIR::List + when FHIR::STU3::List resource.emptyReason = nil resource.entry.each do |entry| resource.mode = 'changes' if !entry.deleted.nil? end - when FHIR::Media + when FHIR::STU3::Media if resource.type == 'video' resource.frames = nil elsif resource.type == 'photo' @@ -704,7 +706,7 @@ def self.apply_invariants!(resource) resource.width = nil resource.frames = nil end - when FHIR::Medication + when FHIR::STU3::Medication resource.ingredient.each do |i| i.amount = nil end @@ -713,7 +715,7 @@ def self.apply_invariants!(resource) c.amount = nil end end - when FHIR::MedicationAdministration + when FHIR::STU3::MedicationAdministration date = DateTime.now resource.effectiveDateTime = date.strftime("%Y-%m-%dT%T.%LZ") resource.effectivePeriod = nil @@ -722,35 +724,35 @@ def self.apply_invariants!(resource) else resource.reasonNotGiven = nil end - resource.medicationReference = textonly_reference('Medication') + 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::MedicationDispense - resource.medicationReference = textonly_reference('Medication') + 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::MedicationRequest - resource.medicationReference = textonly_reference('Medication') + 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::MedicationStatement + when FHIR::STU3::MedicationStatement resource.reasonNotTaken = nil unless resource.taken == 'n' - resource.medicationReference = textonly_reference('Medication') + resource.medicationReference = textonly_reference('Medication', FHIR::STU3) resource.medicationCodeableConcept = nil resource.dosage.each{|d|d.timing=nil} - when FHIR::MessageDefinition + when FHIR::STU3::MessageDefinition resource.focus.each do |f| f.max = '*' unless f.max.nil? end - when FHIR::MessageHeader + when FHIR::STU3::MessageHeader resource.response.identifier.gsub!(/[^0-9A-Za-z]/, '') if resource.try(:response).try(:identifier) - when FHIR::NamingSystem + when FHIR::STU3::NamingSystem resource.replacedBy = nil if resource.status!='retired' if resource.kind == 'root' resource.uniqueId.each do |uid| @@ -761,7 +763,7 @@ def self.apply_invariants!(resource) resource.uniqueId.each do |uid| uid.preferred = nil end - when FHIR::NutritionOrder + when FHIR::STU3::NutritionOrder if resource.oralDiet resource.oralDiet.schedule = nil resource.oralDiet.nutrient.each { |n| n.amount.comparator = nil unless n.amount.nil? } @@ -777,7 +779,7 @@ def self.apply_invariants!(resource) end unless resource.enteralFormula.administration.nil? end resource.supplement.each { |s| s.quantity.comparator = nil unless s.quantity.nil? } - when FHIR::Observation + 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? @@ -793,48 +795,48 @@ def self.apply_invariants!(resource) end end - when FHIR::OperationDefinition + 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::Patient - resource.maritalStatus = minimal_codeableconcept('http://hl7.org/fhir/v3/MaritalStatus','S') - when FHIR::PlanDefinition + 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::Procedure + 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) + fd.action = minimal_codeableconcept('http://hl7.org/fhir/device-action', code, FHIR::STU3) end - when FHIR::Provenance + when FHIR::STU3::Provenance resource.entity.each do |e| e.agent.each{|a| a.relatedAgentType = nil } end - when FHIR::Practitioner + 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::RelatedPerson - resource.relationship = minimal_codeableconcept('http://hl7.org/fhir/patient-contact-relationship','family') - when FHIR::Questionnaire + 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::Questionnaire::Item::Option.new({'valueString'=>'true'}) - choice_b = FHIR::Questionnaire::Item::Option.new({'valueString'=>'false'}) + 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' @@ -842,7 +844,7 @@ def self.apply_invariants!(resource) i.repeats = nil i.readOnly = nil i.option = [] - FHIR::Questionnaire::Item::MULTIPLE_TYPES['initial'].each do |type| + FHIR::STU3::Questionnaire::Item::MULTIPLE_TYPES['initial'].each do |type| i.instance_variable_set("@initial#{type.capitalize}".to_sym, nil) end end @@ -852,12 +854,12 @@ def self.apply_invariants!(resource) end i.maxLength = nil if !['boolean', 'decimal', 'integer', 'string', 'text', 'url'].include?(i.type) end - when FHIR::QuestionnaireResponse + 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::Range + 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 @@ -868,46 +870,46 @@ 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 + when FHIR::STU3::ReferralRequest resource.requester.onBehalfOf = nil unless resource.requester.nil? - when FHIR::Sequence + 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::SearchParameter + when FHIR::STU3::SearchParameter resource.type = 'reference' - when FHIR::SampledData + when FHIR::STU3::SampledData 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') ] + 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::Specimen + 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::Subscription + 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::Substance + when FHIR::STU3::Substance resource.instance.each do |instance| instance.quantity.comparator = nil unless instance.quantity.nil? end - when FHIR::SupplyDelivery - resource.type = minimal_codeableconcept('http://hl7.org/fhir/supply-item-type','medication') + 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::SupplyRequest - resource.category = minimal_codeableconcept('http://hl7.org/fhir/supply-kind','central') - when FHIR::StructureDefinition + 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}" @@ -920,7 +922,7 @@ def self.apply_invariants!(resource) resource.snapshot.element.first.requirements = nil resource.snapshot.element.first.type = nil if is_pattern - FHIR::ElementDefinition::MULTIPLE_TYPES['defaultValue'].each do |type| + 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) @@ -928,7 +930,7 @@ def self.apply_invariants!(resource) resource.snapshot.element.first.instance_variable_set("@maxValue#{type.capitalize}".to_sym, nil) end else - FHIR::ElementDefinition::MULTIPLE_TYPES['defaultValue'].each do |type| + 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) @@ -943,11 +945,11 @@ def self.apply_invariants!(resource) resource.mapping.each do |m| m.identity.gsub!(/[^0-9A-Za-z]/, '') if m.identity end - when FHIR::StructureMap + when FHIR::STU3::StructureMap resource.group.each do |g| g.rule.each{|r|r.rule = nil} end - when FHIR::Substance + when FHIR::STU3::Substance resource.ingredient.each do |ingredient| unless ingredient.quantity.try(:denominator).try(:comparator).nil? ingredient.quantity.denominator.comparator = nil @@ -961,7 +963,7 @@ def self.apply_invariants!(resource) instance.quantity.comparator = nil end end - when FHIR::TestReport + when FHIR::STU3::TestReport if resource.setup resource.setup.action.each do |a| a.assert = nil if a.operation @@ -981,7 +983,7 @@ def self.apply_invariants!(resource) apply_invariants!(a.operation) if a.operation end end - when FHIR::TestScript + 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 @@ -1005,7 +1007,7 @@ def self.apply_invariants!(resource) apply_invariants!(a.operation) if a.operation end end - when FHIR::TestScript::Setup::Action::Assert + 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 = [] @@ -1018,11 +1020,11 @@ def self.apply_invariants!(resource) end 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 + 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::Timing + 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 @@ -1034,7 +1036,7 @@ def self.apply_invariants!(resource) resource.repeat.timeOfDay = nil unless resource.repeat.when.nil? resource.repeat.period = nil if resource.repeat.periodUnit.nil? end - when FHIR::ValueSet + when FHIR::STU3::ValueSet if resource.compose resource.compose.include.each do |inc| inc.filter = nil if inc.concept @@ -1043,11 +1045,11 @@ def self.apply_invariants!(resource) exc.filter = nil if exc.concept end end - when FHIR::VisionPrescription + when FHIR::STU3::VisionPrescription resource.dispense.each do |d| d.duration.comparator = nil unless d.duration.nil? end - when FHIR::RequestGroup::Action + when FHIR::STU3::RequestGroup::Action if !resource.resource.nil? && resource.action.count > 0 if SecureRandom.random_number(2)==0 resource.resource = nil diff --git a/lib/tests/base_test.rb b/lib/tests/base_test.rb index 127575cd..12d7403d 100644 --- a/lib/tests/base_test.rb +++ b/lib/tests/base_test.rb @@ -36,6 +36,8 @@ 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 diff --git a/lib/tests/suites/base_suite.rb b/lib/tests/suites/base_suite.rb index b7ca9555..693f2f70 100644 --- a/lib/tests/suites/base_suite.rb +++ b/lib/tests/suites/base_suite.rb @@ -66,6 +66,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 +78,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 diff --git a/lib/tests/testscripts/testscript_engine.rb b/lib/tests/testscripts/testscript_engine.rb index 44d7879f..e6806794 100644 --- a/lib/tests/testscripts/testscript_engine.rb +++ b/lib/tests/testscripts/testscript_engine.rb @@ -74,12 +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}" diff --git a/plan_executor.gemspec b/plan_executor.gemspec index 0115151f..796861ed 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') diff --git a/test/unit/fhir_structure_test.rb b/test/unit/fhir_structure_test.rb index 52910a15..237b07d7 100644 --- a/test/unit/fhir_structure_test.rb +++ b/test/unit/fhir_structure_test.rb @@ -21,13 +21,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 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..a0cabb99 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 | + # FHIR::RESOURCES.each do | resource_type | + # 3.times do |index| + # max_depth = index + 2 + # 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_#{resource_type}_#{max_depth}") do - run_generator(resource_type, :stu3, max_depth ) + 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 From 9853d357c35af7f02185742f11a1334e99dda69c Mon Sep 17 00:00:00 2001 From: Rob Scanlon Date: Sat, 4 May 2019 02:24:26 -0400 Subject: [PATCH 02/15] Make resource generator tests pass. --- lib/resource_generator.rb | 651 +++++++++++++++++++++++++++ test/unit/resource_generator_test.rb | 16 +- 2 files changed, 659 insertions(+), 8 deletions(-) diff --git a/lib/resource_generator.rb b/lib/resource_generator.rb index bc735840..5aae6a4a 100644 --- a/lib/resource_generator.rb +++ b/lib/resource_generator.rb @@ -69,6 +69,12 @@ def self.set_fields!(resource, namespace, embedded=0) gen = "
#{SecureRandom.base64}
" elsif type == 'uri' gen = "http://projectcrucible.org/#{SecureRandom.base64}" + elsif type == 'uuid' + gen = 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' @@ -283,6 +289,651 @@ def self.tag_metadata(resource, namespace = FHIR) def self.apply_invariants!(resource) case resource + when FHIR::ActivityDefinition + resource.quantity.comparator = nil unless resource.quantity.nil? + when FHIR::Age + resource.system = 'http://unitsofmeasure.org' + resource.code = 'a' + resource.value = (SecureRandom.random_number(100) + 1) + resource.unit = nil + 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::Appointment + 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') ] + when FHIR::AuditEvent + resource.entity.each do |o| + o.query=nil + o.name = "name #{SecureRandom.base64}" if o.name.nil? + end + when FHIR::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::Composition,3) + elsif resource.type == 'message' + head.resource = generate(FHIR::MessageHeader,3) + else + head.resource = generate(FHIR::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::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::CareTeam + resource.participant.each do |p| + p.onBehalfOf = nil + end + when FHIR::CodeSystem + resource.concept.each do |c| + c.concept.each do |d| + 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 + 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 + end + when FHIR::ClaimResponse + resource.item.each do |item| + item.adjudication.each{|a|a.category = minimal_codeableconcept('http://hl7.org/fhir/adjudication','benefit')} + item.detail.each do |detail| + detail.adjudication.each{|a|a.category = minimal_codeableconcept('http://hl7.org/fhir/adjudication','benefit')} + detail.subDetail.each do |sub| + sub.adjudication.each{|a|a.category = minimal_codeableconcept('http://hl7.org/fhir/adjudication','benefit')} + end + end + end + resource.addItem.each do |addItem| + addItem.adjudication.each{|a|a.category = minimal_codeableconcept('http://hl7.org/fhir/adjudication','benefit')} + addItem.detail.each do |detail| + detail.adjudication.each{|a|a.category = minimal_codeableconcept('http://hl7.org/fhir/adjudication','benefit')} + end + end + when FHIR::Communication + resource.payload = nil + when FHIR::CommunicationRequest + resource.payload = nil + when FHIR::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::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 + when FHIR::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::CapabilityStatement + resource.fhirVersion = '4.0.0' + resource.format = ['xml','json'] + 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.messaging.each do |m| + end + 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 + end + when FHIR::DeviceMetric + resource.measurementPeriod = nil + when FHIR::DiagnosticReport + date = DateTime.now + resource.effectiveDateTime = date.strftime("%Y-%m-%dT%T.%LZ") + resource.effectivePeriod = nil + when FHIR::DocumentReference + resource.docStatus = 'preliminary' + when FHIR::Dosage + 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.maxDosePerAdministration.comparator = nil unless resource.maxDosePerAdministration.nil? + resource.maxDosePerLifetime.comparator = nil unless resource.maxDosePerLifetime.nil? + when FHIR::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::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::Endpoint + resource.payloadMimeType = [MIME::Types.to_a.sample.content_type] + when FHIR::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::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::Goal + resource.outcomeCode.each do |code| + code = nil + end + resource.outcomeReference.each do |reference| + reference = textonly_reference('Observation') + end + 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 = [] + when FHIR::ImagingStudy + availability = ['ONLINE', 'OFFLINE', 'NEARLINE', 'UNAVAILABLE'] + resource.series.each do |series| + series.uid=random_oid + series.instance.each do |instance| + instance.uid = random_oid + instance.sopClass = minimal_coding('urn:ietf:rfc:3986', random_oid) + end + end + when FHIR::Immunization + resource.doseQuantity.comparator = nil unless resource.doseQuantity.nil? + resource.status = ['completed','entered-in-error'].sample + when FHIR::ImplementationGuide + resource.fhirVersion = "4.0.0" + when FHIR::Linkage + if resource.item.length == 1 + resource.item << resource.item.first # must have 2 + end + when FHIR::List + resource.emptyReason = nil + resource.entry.each do |entry| + resource.mode = 'changes' if !entry.deleted.nil? + end + when FHIR::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::Medication + resource.amount = nil + resource.ingredient.each do |i| + i.strength = nil + end + when FHIR::MedicationAdministration + date = DateTime.now + resource.effectiveDateTime = date.strftime("%Y-%m-%dT%T.%LZ") + resource.effectivePeriod = nil + resource.medicationReference = textonly_reference('Medication') + resource.medicationCodeableConcept = nil + unless resource.dosage.nil? + resource.dosage.dose.comparator = nil unless resource.dosage.dose.nil? + resource.dosage.rateQuantity = nil + end + when FHIR::MedicationDispense + resource.medicationReference = textonly_reference('Medication') + 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::MedicationRequest + resource.medicationReference = textonly_reference('Medication') + resource.medicationCodeableConcept = nil + resource.dosageInstruction.each {|d|d.timing = nil } + resource.dispenseRequest.quantity.comparator = nil if resource&.dispenseRequest&.quantity != nil + when FHIR::MedicationStatement + resource.medicationReference = textonly_reference('Medication') + resource.medicationCodeableConcept = nil + resource.dosage.each{|d|d.timing=nil} + when FHIR::MessageDefinition + resource.focus.each do |f| + f.max = '*' unless f.max.nil? + end + when FHIR::MessageHeader + resource.response.identifier.gsub!(/[^0-9A-Za-z]/, '') if resource.try(:response).try(:identifier) + when FHIR::NamingSystem + 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::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::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::OperationDefinition + resource.parameter.each do |p| + p.binding = nil + p.part = nil + p.searchType = nil unless p.type == 'string' + end + when FHIR::Patient + resource.maritalStatus = minimal_codeableconcept('http://hl7.org/fhir/v3/MaritalStatus','S') + when FHIR::PlanDefinition + resource.action.each do |a| + a.action.each do |b| + b.relatedAction = [] + end + end + when FHIR::Procedure + 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.role = nil } + end + when FHIR::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::RelatedPerson + 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.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 + i.answer.each {|q|q.valueBoolean = true if !q.value } + end + when FHIR::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::MolecularSequence + resource.coordinateSystem = [0,1].sample + + unless resource.referenceSeq.nil? + resource.referenceSeq.referenceSeqId = resource.referenceSeq.referenceSeqPointer = resource.referenceSeq.referenceSeqString = nil + resource.referenceSeq.strand = ['watson','crick'].sample unless resource.referenceSeq.strand.nil? + end + when FHIR::SearchParameter + resource.type = 'reference' + + when FHIR::SampledData + 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.targetFormat = nil + resource.sigFormat = nil + when FHIR::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::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::Substance + resource.instance.each do |instance| + instance.quantity.comparator = nil unless instance.quantity.nil? + end + when FHIR::SupplyDelivery + resource.type = minimal_codeableconcept('http://hl7.org/fhir/supply-item-type','medication') + resource.suppliedItem.quantity.comparator = nil if !resource.suppliedItem.nil? && !resource.suppliedItem.quantity.nil? + when FHIR::SupplyRequest + resource.category = minimal_codeableconcept('http://hl7.org/fhir/supply-kind','central') + when FHIR::StructureDefinition + resource.derivation = 'constraint' + 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 + 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 + 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) + 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::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::StructureMap + resource.group.each do |g| + g.rule.each{|r|r.rule = nil} + end + when FHIR::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::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::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::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::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 + when FHIR::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::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::VisionPrescription + resource.lensSpecification.each do |d| + d.duration.comparator = nil unless d.duration.nil? + end + when FHIR::RequestGroup::Action + if !resource.resource.nil? && resource.action.count > 0 + if SecureRandom.random_number(2)==0 + resource.resource = nil + else + resource.action = [] + end + end ## STU3 when FHIR::STU3::ActivityDefinition resource.quantity.comparator = nil unless resource.quantity.nil? diff --git a/test/unit/resource_generator_test.rb b/test/unit/resource_generator_test.rb index a0cabb99..b86b4231 100644 --- a/test/unit/resource_generator_test.rb +++ b/test/unit/resource_generator_test.rb @@ -8,14 +8,14 @@ class ResourceGeneratorTest < Test::Unit::TestCase 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_r4_#{resource_type}_#{max_depth}") do - # run_generator(resource_type, :r4, max_depth ) - # end - # end - # end + FHIR::RESOURCES.each do | resource_type | + 3.times do |index| + max_depth = index + 2 + 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 | From e591b5d963bf80958afdb9383d36b39091e8003e Mon Sep 17 00:00:00 2001 From: Rob Scanlon Date: Sat, 4 May 2019 02:42:53 -0400 Subject: [PATCH 03/15] More r4 updates. --- lib/tasks/tasks.rake | 3 ++- lib/tests/base_test.rb | 2 +- lib/tests/suites/suite_engine.rb | 2 +- test/unit/fhir_structure_test.rb | 7 ++++++- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/tasks/tasks.rake b/lib/tasks/tasks.rake index c7eea615..1f46a2bf 100644 --- a/lib/tasks/tasks.rake +++ b/lib/tasks/tasks.rake @@ -113,7 +113,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 diff --git a/lib/tests/base_test.rb b/lib/tests/base_test.rb index 12d7403d..a3372303 100644 --- a/lib/tests/base_test.rb +++ b/lib/tests/base_test.rb @@ -42,7 +42,7 @@ def initialize(client, client2=nil) @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/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/test/unit/fhir_structure_test.rb b/test/unit/fhir_structure_test.rb index 237b07d7..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 @@ -56,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 From 3f4e6a8323c82d9e1afe8846e249fbd352d6c4e6 Mon Sep 17 00:00:00 2001 From: Jason Walonoski Date: Sun, 5 May 2019 14:39:56 -0400 Subject: [PATCH 04/15] Fix broken resource generator unit tests. --- Gemfile.lock | 6 ++++++ lib/resource_generator.rb | 16 +++++++++++++++- plan_executor.gemspec | 1 + 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 986135b2..ecb02302 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -30,6 +30,8 @@ GEM i18n coderay (1.1.2) concurrent-ruby (1.1.5) + coolline (0.5.0) + unicode_utils (~> 1.4) crack (0.4.3) safe_yaml (~> 1.0.0) date_time_precision (0.8.1) @@ -99,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.7) rake (12.3.2) @@ -123,6 +127,7 @@ GEM unf (0.1.4) unf_ext unf_ext (0.0.7.6) + unicode_utils (1.4.0) webmock (3.5.1) addressable (>= 2.3.6) crack (>= 0.3.2) @@ -136,6 +141,7 @@ DEPENDENCIES awesome_print plan_executor! pry + pry-coolline rake simplecov test-unit diff --git a/lib/resource_generator.rb b/lib/resource_generator.rb index 5aae6a4a..306882ee 100644 --- a/lib/resource_generator.rb +++ b/lib/resource_generator.rb @@ -70,7 +70,7 @@ def self.set_fields!(resource, namespace, embedded=0) elsif type == 'uri' gen = "http://projectcrucible.org/#{SecureRandom.base64}" elsif type == 'uuid' - gen = SecureRandom.uuid + gen = "urn:uuid:#{SecureRandom.uuid}" elsif type == 'url' gen = "http://projectcrucible.org/#{SecureRandom.base64}" elsif type == 'canonical' @@ -838,6 +838,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| @@ -1614,6 +1621,13 @@ def self.apply_invariants!(resource) 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| diff --git a/plan_executor.gemspec b/plan_executor.gemspec index 796861ed..bdb6b77f 100644 --- a/plan_executor.gemspec +++ b/plan_executor.gemspec @@ -29,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') From 91ef44ec801abf3f524b1336cca48a69e205410e Mon Sep 17 00:00:00 2001 From: Jason Walonoski Date: Sun, 5 May 2019 14:59:42 -0400 Subject: [PATCH 05/15] Fix resource generator for STU3 DataElement. --- lib/resource_generator.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/resource_generator.rb b/lib/resource_generator.rb index 306882ee..27a6060c 100644 --- a/lib/resource_generator.rb +++ b/lib/resource_generator.rb @@ -1166,6 +1166,11 @@ def self.apply_invariants!(resource) 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]/, '') From d878bfd4fbd31eedc290ea0dd8795c4a2559cd41 Mon Sep 17 00:00:00 2001 From: Rob Scanlon Date: Sat, 8 Jun 2019 02:13:22 -0400 Subject: [PATCH 06/15] Fix FHIR structure in R4. --- lib/FHIR_structure.json | 2 -- lib/FHIR_structure_r4.json | 2 -- 2 files changed, 4 deletions(-) diff --git a/lib/FHIR_structure.json b/lib/FHIR_structure.json index 020343c7..49ee92b0 100644 --- a/lib/FHIR_structure.json +++ b/lib/FHIR_structure.json @@ -103,8 +103,6 @@ "name": "$transform" },{ "name": "$snapshot" - },{ - "name": "$lookup" },{ "name": "$subsumes" },{ diff --git a/lib/FHIR_structure_r4.json b/lib/FHIR_structure_r4.json index 6a5cd540..d172e1bf 100644 --- a/lib/FHIR_structure_r4.json +++ b/lib/FHIR_structure_r4.json @@ -103,8 +103,6 @@ "name": "$transform" },{ "name": "$snapshot" - },{ - "name": "$lookup" },{ "name": "$subsumes" },{ From 6bf47a43de1f9df8582bf39f4474b2d9c61a8a0d Mon Sep 17 00:00:00 2001 From: Rob Scanlon Date: Sat, 8 Jun 2019 03:52:05 -0400 Subject: [PATCH 07/15] Various r4 fixes. --- lib/FHIR_structure.json | 3 +++ lib/FHIR_structure_r4.json | 3 +++ lib/tests/suites/base_suite.rb | 12 ++++++++++-- lib/tests/suites/resource_test.rb | 2 +- lib/tests/suites/search_test.rb | 2 +- lib/tests/suites/transaction_test.rb | 2 +- 6 files changed, 19 insertions(+), 5 deletions(-) diff --git a/lib/FHIR_structure.json b/lib/FHIR_structure.json index 49ee92b0..8cdf42b0 100644 --- a/lib/FHIR_structure.json +++ b/lib/FHIR_structure.json @@ -574,6 +574,9 @@ }, { "name": "substance specification" + }, + { + "name": "substance nucleic acid" } ] } diff --git a/lib/FHIR_structure_r4.json b/lib/FHIR_structure_r4.json index d172e1bf..1d918a5d 100644 --- a/lib/FHIR_structure_r4.json +++ b/lib/FHIR_structure_r4.json @@ -602,6 +602,9 @@ }, { "name": "substance source material" + }, + { + "name": "substance nucleic acid" } ] } diff --git a/lib/tests/suites/base_suite.rb b/lib/tests/suites/base_suite.rb index 693f2f70..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 @@ -171,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)}} @@ -180,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/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/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 From 2bd7047e1f35bc701995d512e45f890b81edd5d7 Mon Sep 17 00:00:00 2001 From: Rob Scanlon Date: Sat, 8 Jun 2019 20:39:30 -0400 Subject: [PATCH 08/15] Update README. --- README.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 85c7d234..6eab7177 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 From 726f149ad40c70d18de547994d320be0d553a067 Mon Sep 17 00:00:00 2001 From: Rob Scanlon Date: Mon, 24 Jun 2019 12:35:41 -0400 Subject: [PATCH 09/15] R4 ImplementationGuide generator incorrect fhirVersion cardinality --- lib/resource_generator.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/resource_generator.rb b/lib/resource_generator.rb index 27a6060c..e5d19476 100644 --- a/lib/resource_generator.rb +++ b/lib/resource_generator.rb @@ -570,8 +570,6 @@ def self.apply_invariants!(resource) when FHIR::Immunization resource.doseQuantity.comparator = nil unless resource.doseQuantity.nil? resource.status = ['completed','entered-in-error'].sample - when FHIR::ImplementationGuide - resource.fhirVersion = "4.0.0" when FHIR::Linkage if resource.item.length == 1 resource.item << resource.item.first # must have 2 From 8bd3817c66bddb281a0f15b69289da70846e58df Mon Sep 17 00:00:00 2001 From: Rob Scanlon Date: Mon, 24 Jun 2019 12:48:46 -0400 Subject: [PATCH 10/15] RelatedPerson generates invalid R4 resource. --- lib/resource_generator.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/resource_generator.rb b/lib/resource_generator.rb index 27a6060c..d0915640 100644 --- a/lib/resource_generator.rb +++ b/lib/resource_generator.rb @@ -704,7 +704,7 @@ 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 From 474ba92a86b250bd7bbed8eaeee466ffb354e9ad Mon Sep 17 00:00:00 2001 From: Eero Kelly Date: Fri, 2 Aug 2019 09:41:35 -0700 Subject: [PATCH 11/15] Fix a typo in Sprinkler Search Test The UCUM url is unitsofmeasure.org not unitofmeasure.org. --- lib/tests/suites/sprinkler_search_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From 981f0e8f90462b1af64297df7fc2328369fc99e8 Mon Sep 17 00:00:00 2001 From: Rob Scanlon Date: Fri, 27 Mar 2020 00:39:36 -0400 Subject: [PATCH 12/15] Fix some language and narrative generation. --- README.md | 17 +++++++++++------ lib/resource_generator.rb | 2 +- lib/tasks/tasks.rake | 8 ++++++++ lib/tests/testscripts/testscript_engine.rb | 3 --- 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 6eab7177..803e4105 100644 --- a/README.md +++ b/README.md @@ -13,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] @@ -24,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 @@ -111,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/lib/resource_generator.rb b/lib/resource_generator.rb index af359a97..eb6cac1f 100644 --- a/lib/resource_generator.rb +++ b/lib/resource_generator.rb @@ -66,7 +66,7 @@ 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' diff --git a/lib/tasks/tasks.rake b/lib/tasks/tasks.rake index 1f46a2bf..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? @@ -304,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? @@ -335,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? @@ -415,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/testscripts/testscript_engine.rb b/lib/tests/testscripts/testscript_engine.rb index e6806794..8476381f 100644 --- a/lib/tests/testscripts/testscript_engine.rb +++ b/lib/tests/testscripts/testscript_engine.rb @@ -78,11 +78,8 @@ def self.parse_testscripts 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::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}" From d0515366d74160a3a2a1cbe4de9e6f1b80ad943d Mon Sep 17 00:00:00 2001 From: Rob Scanlon Date: Fri, 27 Mar 2020 00:44:40 -0400 Subject: [PATCH 13/15] Update gemfile.lock --- Gemfile.lock | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 841b1249..22ac804f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -29,7 +29,7 @@ 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) @@ -51,25 +51,25 @@ GEM rack (>= 1.5) rest-client (~> 2.0) tilt (>= 1.1) - fhir_dstu2_models (1.0.9) + fhir_dstu2_models (1.0.10) bcp47 (>= 0.3) date_time_precision (>= 0.8) mime-types (>= 3.0) - nokogiri (>= 1.8.5) - fhir_models (4.0.0) + nokogiri (>= 1.10.4) + fhir_models (4.0.2) bcp47 (>= 0.3) date_time_precision (>= 0.8) mime-types (>= 3.0) - nokogiri (>= 1.8.2) - fhir_stu3_models (3.0.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.8.2) + 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) @@ -77,16 +77,16 @@ GEM to_regexp (~> 0.2.1) jwt (2.1.0) method_source (0.9.2) - mime-types (3.2.2) + mime-types (3.3.1) mime-types-data (~> 3.2015) - mime-types-data (3.2019.0331) + 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) From c38f64aa553acfc7340f692516309571d3295d90 Mon Sep 17 00:00:00 2001 From: Peter Hull Date: Wed, 29 Jul 2020 08:49:55 +0000 Subject: [PATCH 14/15] Create a patient on the client, if needed Also use the standard 'minimal_patient' resource instead of an ad-hoc definition --- lib/tests/suites/read_test.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/tests/suites/read_test.rb b/lib/tests/suites/read_test.rb index c6f5f942..b408b369 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.minimal_patient).resource @patient_created = true rescue @patient = nil From bd5743828ba05c805cb5f80411806c83b046e6db Mon Sep 17 00:00:00 2001 From: Peter Hull Date: Wed, 29 Jul 2020 15:03:59 +0100 Subject: [PATCH 15/15] Use a patient resource fixture with text in it. --- lib/tests/suites/read_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tests/suites/read_test.rb b/lib/tests/suites/read_test.rb index b408b369..14ae644b 100644 --- a/lib/tests/suites/read_test.rb +++ b/lib/tests/suites/read_test.rb @@ -24,7 +24,7 @@ def setup rescue # try to create a patient begin - @patient = @client.create(@resources.minimal_patient).resource + @patient = @client.create(@resources.example_patient).resource @patient_created = true rescue @patient = nil