davinci_pas_test_kit 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (168) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +201 -0
  3. data/lib/davinci_pas_test_kit/client_suite.rb +289 -0
  4. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/claim_status/pas_claim_status_test.rb +109 -0
  5. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_approval_submit_response_attest.rb +39 -0
  6. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_approval_submit_test.rb +38 -0
  7. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_denial_submit_response_attest.rb +38 -0
  8. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_denial_submit_test.rb +43 -0
  9. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_inquire_must_support_test.rb +51 -0
  10. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_pended_inquire_response_attest.rb +39 -0
  11. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_pended_inquire_test.rb +35 -0
  12. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_pended_submit_response_attest.rb +39 -0
  13. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_pended_submit_test.rb +43 -0
  14. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_submit_must_support_test.rb +57 -0
  15. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_token_request_test.rb +31 -0
  16. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_token_validation_test.rb +18 -0
  17. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/error_tests/nonconformant_pas_bundle.json +16 -0
  18. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/error_tests/pas_inquiry_error_test.rb +38 -0
  19. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/error_tests/pas_submission_error_test.rb +56 -0
  20. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/must_support/device_request_metadata.yml +112 -0
  21. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/must_support/medication_request_metadata.yml +183 -0
  22. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/must_support/nutrition_order_metadata.yml +109 -0
  23. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/must_support/pas_client_must_support_requirement_test.rb +117 -0
  24. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/must_support/pas_server_must_support_requirement_test.rb +116 -0
  25. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/must_support/service_request_metadata.yml +148 -0
  26. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_client_approval_group.rb +26 -0
  27. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_client_authentication_group.rb +49 -0
  28. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_client_denial_group.rb +41 -0
  29. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_client_pended_group.rb +56 -0
  30. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_error_group.rb +20 -0
  31. data/lib/davinci_pas_test_kit/ext/inferno_core/record_response_route.rb +98 -0
  32. data/lib/davinci_pas_test_kit/ext/inferno_core/request.rb +19 -0
  33. data/lib/davinci_pas_test_kit/ext/inferno_core/runnable.rb +18 -0
  34. data/lib/davinci_pas_test_kit/fhir_resource_navigation.rb +72 -0
  35. data/lib/davinci_pas_test_kit/generated/v2.0.1/beneficiary/client_inquiry_request_beneficiary_must_support_test.rb +75 -0
  36. data/lib/davinci_pas_test_kit/generated/v2.0.1/beneficiary/client_submit_request_beneficiary_must_support_test.rb +75 -0
  37. data/lib/davinci_pas_test_kit/generated/v2.0.1/beneficiary/metadata.yml +162 -0
  38. data/lib/davinci_pas_test_kit/generated/v2.0.1/beneficiary/server_inquiry_request_beneficiary_must_support_test.rb +75 -0
  39. data/lib/davinci_pas_test_kit/generated/v2.0.1/beneficiary/server_inquiry_response_beneficiary_must_support_test.rb +75 -0
  40. data/lib/davinci_pas_test_kit/generated/v2.0.1/beneficiary/server_submit_request_beneficiary_must_support_test.rb +75 -0
  41. data/lib/davinci_pas_test_kit/generated/v2.0.1/beneficiary/server_submit_response_beneficiary_must_support_test.rb +75 -0
  42. data/lib/davinci_pas_test_kit/generated/v2.0.1/claim/claim_operation_test.rb +67 -0
  43. data/lib/davinci_pas_test_kit/generated/v2.0.1/claim/metadata.yml +577 -0
  44. data/lib/davinci_pas_test_kit/generated/v2.0.1/claim_inquiry/claim_inquiry_operation_test.rb +57 -0
  45. data/lib/davinci_pas_test_kit/generated/v2.0.1/claim_inquiry/client_inquiry_request_claim_inquiry_must_support_test.rb +95 -0
  46. data/lib/davinci_pas_test_kit/generated/v2.0.1/claim_inquiry/metadata.yml +516 -0
  47. data/lib/davinci_pas_test_kit/generated/v2.0.1/claim_inquiry/server_inquiry_request_claim_inquiry_must_support_test.rb +95 -0
  48. data/lib/davinci_pas_test_kit/generated/v2.0.1/claim_update/client_submit_request_claim_update_must_support_test.rb +102 -0
  49. data/lib/davinci_pas_test_kit/generated/v2.0.1/claim_update/metadata.yml +591 -0
  50. data/lib/davinci_pas_test_kit/generated/v2.0.1/claim_update/server_submit_request_claim_update_must_support_test.rb +102 -0
  51. data/lib/davinci_pas_test_kit/generated/v2.0.1/claiminquiryresponse/metadata.yml +311 -0
  52. data/lib/davinci_pas_test_kit/generated/v2.0.1/claiminquiryresponse/server_inquiry_response_claiminquiryresponse_must_support_test.rb +73 -0
  53. data/lib/davinci_pas_test_kit/generated/v2.0.1/claimresponse/metadata.yml +318 -0
  54. data/lib/davinci_pas_test_kit/generated/v2.0.1/claimresponse/server_submit_response_claimresponse_must_support_test.rb +75 -0
  55. data/lib/davinci_pas_test_kit/generated/v2.0.1/client_tests/client_denial_pas_response_bundle_validation_test.rb +53 -0
  56. data/lib/davinci_pas_test_kit/generated/v2.0.1/client_tests/client_pas_request_bundle_validation_test.rb +55 -0
  57. data/lib/davinci_pas_test_kit/generated/v2.0.1/client_tests/client_pended_pas_inquiry_request_bundle_validation_test.rb +55 -0
  58. data/lib/davinci_pas_test_kit/generated/v2.0.1/client_tests/client_pended_pas_response_bundle_validation_test.rb +53 -0
  59. data/lib/davinci_pas_test_kit/generated/v2.0.1/communication_request/metadata.yml +130 -0
  60. data/lib/davinci_pas_test_kit/generated/v2.0.1/communication_request/server_submit_response_communication_request_must_support_test.rb +58 -0
  61. data/lib/davinci_pas_test_kit/generated/v2.0.1/coverage/client_inquiry_request_coverage_must_support_test.rb +55 -0
  62. data/lib/davinci_pas_test_kit/generated/v2.0.1/coverage/client_submit_request_coverage_must_support_test.rb +55 -0
  63. data/lib/davinci_pas_test_kit/generated/v2.0.1/coverage/metadata.yml +111 -0
  64. data/lib/davinci_pas_test_kit/generated/v2.0.1/coverage/server_inquiry_request_coverage_must_support_test.rb +55 -0
  65. data/lib/davinci_pas_test_kit/generated/v2.0.1/coverage/server_submit_request_coverage_must_support_test.rb +55 -0
  66. data/lib/davinci_pas_test_kit/generated/v2.0.1/device_request/client_submit_request_device_request_must_support_test.rb +51 -0
  67. data/lib/davinci_pas_test_kit/generated/v2.0.1/device_request/metadata.yml +112 -0
  68. data/lib/davinci_pas_test_kit/generated/v2.0.1/device_request/server_submit_request_device_request_must_support_test.rb +51 -0
  69. data/lib/davinci_pas_test_kit/generated/v2.0.1/encounter/client_submit_request_encounter_must_support_test.rb +67 -0
  70. data/lib/davinci_pas_test_kit/generated/v2.0.1/encounter/metadata.yml +213 -0
  71. data/lib/davinci_pas_test_kit/generated/v2.0.1/encounter/server_submit_request_encounter_must_support_test.rb +67 -0
  72. data/lib/davinci_pas_test_kit/generated/v2.0.1/insurer/client_inquiry_request_insurer_must_support_test.rb +60 -0
  73. data/lib/davinci_pas_test_kit/generated/v2.0.1/insurer/client_submit_request_insurer_must_support_test.rb +60 -0
  74. data/lib/davinci_pas_test_kit/generated/v2.0.1/insurer/metadata.yml +104 -0
  75. data/lib/davinci_pas_test_kit/generated/v2.0.1/insurer/server_inquiry_request_insurer_must_support_test.rb +60 -0
  76. data/lib/davinci_pas_test_kit/generated/v2.0.1/insurer/server_inquiry_response_insurer_must_support_test.rb +60 -0
  77. data/lib/davinci_pas_test_kit/generated/v2.0.1/insurer/server_submit_request_insurer_must_support_test.rb +60 -0
  78. data/lib/davinci_pas_test_kit/generated/v2.0.1/insurer/server_submit_response_insurer_must_support_test.rb +60 -0
  79. data/lib/davinci_pas_test_kit/generated/v2.0.1/medication_request/client_submit_request_medication_request_must_support_test.rb +61 -0
  80. data/lib/davinci_pas_test_kit/generated/v2.0.1/medication_request/metadata.yml +183 -0
  81. data/lib/davinci_pas_test_kit/generated/v2.0.1/medication_request/server_submit_request_medication_request_must_support_test.rb +61 -0
  82. data/lib/davinci_pas_test_kit/generated/v2.0.1/metadata.yml +5253 -0
  83. data/lib/davinci_pas_test_kit/generated/v2.0.1/nutrition_order/client_submit_request_nutrition_order_must_support_test.rb +53 -0
  84. data/lib/davinci_pas_test_kit/generated/v2.0.1/nutrition_order/metadata.yml +109 -0
  85. data/lib/davinci_pas_test_kit/generated/v2.0.1/nutrition_order/server_submit_request_nutrition_order_must_support_test.rb +53 -0
  86. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_client_inquiry_must_support_use_case_group.rb +51 -0
  87. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_client_submit_must_support_use_case_group.rb +61 -0
  88. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_inquiry_request_bundle/client_inquiry_request_pas_inquiry_request_bundle_must_support_test.rb +53 -0
  89. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_inquiry_request_bundle/metadata.yml +77 -0
  90. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_inquiry_request_bundle/server_inquiry_request_pas_inquiry_request_bundle_must_support_test.rb +53 -0
  91. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_inquiry_request_bundle/server_pas_inquiry_request_bundle_validation_test.rb +83 -0
  92. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_inquiry_response_bundle/metadata.yml +67 -0
  93. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_inquiry_response_bundle/server_inquiry_response_pas_inquiry_response_bundle_must_support_test.rb +52 -0
  94. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_inquiry_response_bundle/server_pas_inquiry_response_bundle_validation_test.rb +80 -0
  95. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_request_bundle/client_submit_request_pas_request_bundle_must_support_test.rb +53 -0
  96. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_request_bundle/metadata.yml +77 -0
  97. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_request_bundle/server_pas_request_bundle_validation_test.rb +83 -0
  98. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_request_bundle/server_submit_request_pas_request_bundle_must_support_test.rb +53 -0
  99. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_response_bundle/metadata.yml +71 -0
  100. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_response_bundle/server_pas_response_bundle_validation_test.rb +80 -0
  101. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_response_bundle/server_submit_response_pas_response_bundle_must_support_test.rb +52 -0
  102. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_server_approval_use_case_group.rb +59 -0
  103. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_server_denial_use_case_group.rb +59 -0
  104. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_server_must_support_use_case_group.rb +265 -0
  105. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_server_pended_use_case_group.rb +84 -0
  106. data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner/client_inquiry_request_practitioner_must_support_test.rb +53 -0
  107. data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner/client_submit_request_practitioner_must_support_test.rb +53 -0
  108. data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner/metadata.yml +74 -0
  109. data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner/server_inquiry_request_practitioner_must_support_test.rb +53 -0
  110. data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner/server_inquiry_response_practitioner_must_support_test.rb +53 -0
  111. data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner/server_submit_request_practitioner_must_support_test.rb +53 -0
  112. data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner/server_submit_response_practitioner_must_support_test.rb +53 -0
  113. data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner_role/client_inquiry_request_practitioner_role_must_support_test.rb +49 -0
  114. data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner_role/client_submit_request_practitioner_role_must_support_test.rb +49 -0
  115. data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner_role/metadata.yml +81 -0
  116. data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner_role/server_inquiry_request_practitioner_role_must_support_test.rb +49 -0
  117. data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner_role/server_inquiry_response_practitioner_role_must_support_test.rb +49 -0
  118. data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner_role/server_submit_request_practitioner_role_must_support_test.rb +49 -0
  119. data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner_role/server_submit_response_practitioner_role_must_support_test.rb +49 -0
  120. data/lib/davinci_pas_test_kit/generated/v2.0.1/requestor/client_inquiry_request_requestor_must_support_test.rb +63 -0
  121. data/lib/davinci_pas_test_kit/generated/v2.0.1/requestor/client_submit_request_requestor_must_support_test.rb +63 -0
  122. data/lib/davinci_pas_test_kit/generated/v2.0.1/requestor/metadata.yml +107 -0
  123. data/lib/davinci_pas_test_kit/generated/v2.0.1/requestor/server_inquiry_request_requestor_must_support_test.rb +63 -0
  124. data/lib/davinci_pas_test_kit/generated/v2.0.1/requestor/server_inquiry_response_requestor_must_support_test.rb +63 -0
  125. data/lib/davinci_pas_test_kit/generated/v2.0.1/requestor/server_submit_request_requestor_must_support_test.rb +63 -0
  126. data/lib/davinci_pas_test_kit/generated/v2.0.1/requestor/server_submit_response_requestor_must_support_test.rb +63 -0
  127. data/lib/davinci_pas_test_kit/generated/v2.0.1/resource_list.rb +54 -0
  128. data/lib/davinci_pas_test_kit/generated/v2.0.1/server_suite.rb +236 -0
  129. data/lib/davinci_pas_test_kit/generated/v2.0.1/service_request/client_submit_request_service_request_must_support_test.rb +53 -0
  130. data/lib/davinci_pas_test_kit/generated/v2.0.1/service_request/metadata.yml +148 -0
  131. data/lib/davinci_pas_test_kit/generated/v2.0.1/service_request/server_submit_request_service_request_must_support_test.rb +53 -0
  132. data/lib/davinci_pas_test_kit/generated/v2.0.1/subscriber/client_inquiry_request_subscriber_must_support_test.rb +74 -0
  133. data/lib/davinci_pas_test_kit/generated/v2.0.1/subscriber/client_submit_request_subscriber_must_support_test.rb +74 -0
  134. data/lib/davinci_pas_test_kit/generated/v2.0.1/subscriber/metadata.yml +159 -0
  135. data/lib/davinci_pas_test_kit/generated/v2.0.1/subscriber/server_inquiry_request_subscriber_must_support_test.rb +74 -0
  136. data/lib/davinci_pas_test_kit/generated/v2.0.1/subscriber/server_submit_request_subscriber_must_support_test.rb +74 -0
  137. data/lib/davinci_pas_test_kit/generated/v2.0.1/task/metadata.yml +192 -0
  138. data/lib/davinci_pas_test_kit/generated/v2.0.1/task/server_inquiry_response_task_must_support_test.rb +61 -0
  139. data/lib/davinci_pas_test_kit/generated/v2.0.1/task/server_submit_response_task_must_support_test.rb +61 -0
  140. data/lib/davinci_pas_test_kit/generator/group_generator.rb +440 -0
  141. data/lib/davinci_pas_test_kit/generator/group_metadata.rb +73 -0
  142. data/lib/davinci_pas_test_kit/generator/group_metadata_extractor.rb +244 -0
  143. data/lib/davinci_pas_test_kit/generator/ig_loader.rb +78 -0
  144. data/lib/davinci_pas_test_kit/generator/ig_metadata.rb +66 -0
  145. data/lib/davinci_pas_test_kit/generator/ig_metadata_extractor.rb +54 -0
  146. data/lib/davinci_pas_test_kit/generator/ig_resources.rb +74 -0
  147. data/lib/davinci_pas_test_kit/generator/must_support_check_profiles.rb +86 -0
  148. data/lib/davinci_pas_test_kit/generator/must_support_metadata_extractor.rb +327 -0
  149. data/lib/davinci_pas_test_kit/generator/must_support_test_generator.rb +155 -0
  150. data/lib/davinci_pas_test_kit/generator/naming.rb +50 -0
  151. data/lib/davinci_pas_test_kit/generator/operation_test_generator.rb +136 -0
  152. data/lib/davinci_pas_test_kit/generator/resource_list_generator.rb +59 -0
  153. data/lib/davinci_pas_test_kit/generator/suite_generator.rb +94 -0
  154. data/lib/davinci_pas_test_kit/generator/terminology_binding_metadata_extractor.rb +108 -0
  155. data/lib/davinci_pas_test_kit/generator/validation_test_generator.rb +181 -0
  156. data/lib/davinci_pas_test_kit/generator/value_extractor.rb +48 -0
  157. data/lib/davinci_pas_test_kit/generator.rb +80 -0
  158. data/lib/davinci_pas_test_kit/mock_server.rb +189 -0
  159. data/lib/davinci_pas_test_kit/must_support_test.rb +267 -0
  160. data/lib/davinci_pas_test_kit/pas_bundle_validation.rb +568 -0
  161. data/lib/davinci_pas_test_kit/tags.rb +7 -0
  162. data/lib/davinci_pas_test_kit/urls.rb +39 -0
  163. data/lib/davinci_pas_test_kit/user_input_response.rb +32 -0
  164. data/lib/davinci_pas_test_kit/validation_test.rb +58 -0
  165. data/lib/davinci_pas_test_kit/validator_suppressions.rb +143 -0
  166. data/lib/davinci_pas_test_kit/version.rb +5 -0
  167. data/lib/davinci_pas_test_kit.rb +2 -0
  168. metadata +281 -0
@@ -0,0 +1,244 @@
1
+ require_relative 'group_metadata'
2
+ require_relative 'ig_metadata'
3
+ require_relative 'must_support_metadata_extractor'
4
+ require_relative 'terminology_binding_metadata_extractor'
5
+
6
+ module DaVinciPASTestKit
7
+ class Generator
8
+ class GroupMetadataExtractor
9
+ attr_accessor :resource_capabilities, :profile_url, :ig_metadata, :ig_resources
10
+
11
+ def initialize(resource_capabilities, profile_url, ig_metadata, ig_resources)
12
+ self.resource_capabilities = resource_capabilities
13
+ self.profile_url = profile_url
14
+ self.ig_metadata = ig_metadata
15
+ self.ig_resources = ig_resources
16
+ end
17
+
18
+ def group_metadata
19
+ @group_metadata ||=
20
+ GroupMetadata.new(group_metadata_hash)
21
+ end
22
+
23
+ def group_metadata_hash
24
+ @group_metadata_hash ||=
25
+ {
26
+ name:,
27
+ class_name:,
28
+ version:,
29
+ reformatted_version:,
30
+ resource:,
31
+ conformance_expectation:,
32
+ profile_url:,
33
+ profile_name:,
34
+ profile_version:,
35
+ title:,
36
+ short_description:,
37
+ interactions:,
38
+ operations:,
39
+ # searches:,
40
+ # search_definitions:,
41
+ # include_params:,
42
+ # revincludes:,
43
+ required_concepts:,
44
+ must_supports:,
45
+ mandatory_elements:,
46
+ bindings:,
47
+ references:
48
+ }
49
+
50
+ # mark_mandatory_and_must_support_searches
51
+
52
+ @group_metadata_hash
53
+ end
54
+
55
+ # def mark_mandatory_and_must_support_searches
56
+ # searches.each do |search|
57
+ # search[:names_not_must_support_or_mandatory] = search[:names].reject do |name|
58
+ # full_paths = search_definitions[name.to_sym][:full_paths]
59
+ # any_must_support_elements = must_supports[:elements].any? do |element|
60
+ # full_must_support_paths = ["#{resource}.#{element[:original_path]}", "#{resource}.#{element[:path]}"]
61
+
62
+ # full_paths.any? do |path|
63
+ # # allow for non-choice, choice types, and _id
64
+ # name == '_id' ||
65
+ # full_must_support_paths.include?(path) ||
66
+ # full_must_support_paths.include?("#{path}[x]")
67
+ # end
68
+ # end
69
+
70
+ # any_must_support_slices = must_supports[:slices].any? do |slice|
71
+ # # only handle type slices because that is all we need for now
72
+ # # for a slice like Observation.effective[x]:effectiveDateTime, the search parameter's expression could
73
+ # # be either Observation.effective or Observation.effectiveDateTime.
74
+ # if slice[:discriminator] && slice[:discriminator][:type] == 'type'
75
+ # full_must_support_path = "#{resource}.#{slice[:path].sub('[x]', slice[:discriminator][:code])}"
76
+ # base_must_support_path = "#{resource}.#{slice[:path].sub('[x]', '')}"
77
+
78
+ # full_paths.intersection([full_must_support_path, base_must_support_path]).present?
79
+ # else
80
+ # false
81
+ # end
82
+ # end
83
+
84
+ # any_mandatory_elements = mandatory_elements.any? do |element|
85
+ # full_paths.include?(element)
86
+ # end
87
+
88
+ # any_must_support_elements || any_must_support_slices || any_mandatory_elements
89
+ # end
90
+
91
+ # search[:must_support_or_mandatory] = search[:names_not_must_support_or_mandatory].empty?
92
+ # end
93
+ # end
94
+
95
+ def profile
96
+ @profile ||= ig_resources.profile_by_url(profile_url)
97
+ end
98
+
99
+ def profile_elements
100
+ @profile_elements ||= profile.snapshot.element
101
+ end
102
+
103
+ def base_name
104
+ profile_url.split('StructureDefinition/').last
105
+ end
106
+
107
+ def name
108
+ base_name.tr('-', '_')
109
+ end
110
+
111
+ def class_name
112
+ base_name
113
+ .split('-')
114
+ .map(&:capitalize)
115
+ .join
116
+ .gsub('PAS', "PAS#{ig_metadata.reformatted_version}")
117
+ .concat('Sequence')
118
+ end
119
+
120
+ def version
121
+ ig_metadata.ig_version
122
+ end
123
+
124
+ def reformatted_version
125
+ ig_metadata.reformatted_version
126
+ end
127
+
128
+ def resource
129
+ profile.type
130
+ end
131
+
132
+ def conformance_expectation
133
+ resource_capabilities&.extension&.first&.valueCode
134
+ end
135
+
136
+ def profile_name
137
+ profile.title.gsub(' ', ' ')
138
+ end
139
+
140
+ def profile_version
141
+ profile.version
142
+ end
143
+
144
+ def title
145
+ puts profile.title
146
+ profile.title.gsub(/PAS\s*/, '').gsub(/\s*Profile/, '').strip
147
+ end
148
+
149
+ def short_description
150
+ "Verify support for the server capabilities required by the #{profile_name}."
151
+ end
152
+
153
+ def interactions
154
+ @interactions ||=
155
+ resource_capabilities.interaction.map do |interaction|
156
+ {
157
+ code: interaction.code,
158
+ expectation: interaction&.extension&.first&.valueCode # TODO: fix expectation extension finding
159
+ }
160
+ end
161
+ end
162
+
163
+ def operations
164
+ @operations ||=
165
+ resource_capabilities.operation.map do |operation|
166
+ {
167
+ code: operation.name,
168
+ expectation: operation&.extension&.first&.valueCode # TODO: fix expectation extension finding
169
+ }
170
+ end
171
+ end
172
+
173
+ # def search_metadata_extractor
174
+ # @search_metadata_extractor ||=
175
+ # SearchMetadataExtractor.new(resource_capabilities, ig_resources, resource, profile_elements)
176
+ # end
177
+
178
+ # def searches
179
+ # @searches ||= search_metadata_extractor.searches
180
+ # end
181
+
182
+ # def search_definitions
183
+ # @search_definitions ||= search_metadata_extractor.search_definitions
184
+ # end
185
+
186
+ # def include_params
187
+ # resource_capabilities.searchInclude || []
188
+ # end
189
+
190
+ # def revincludes
191
+ # resource_capabilities.searchRevInclude || []
192
+ # end
193
+
194
+ def required_concepts
195
+ return [] if resource == 'Observation'
196
+
197
+ profile_elements
198
+ .select { |element| element.type&.any? { |type| type.code == 'CodeableConcept' } }
199
+ .select { |element| element.binding&.strength == 'required' }
200
+ .map { |element| element.path.gsub("#{resource}.", '').gsub('[x]', 'CodeableConcept') }
201
+ end
202
+
203
+ def terminology_binding_metadata_extractor
204
+ @terminology_binding_metadata_extractor ||=
205
+ TerminologyBindingMetadataExtractor.new(profile_elements, ig_resources, resource)
206
+ end
207
+
208
+ def bindings
209
+ @bindings ||=
210
+ terminology_binding_metadata_extractor.terminology_bindings
211
+ end
212
+
213
+ def must_support_metadata_extractor
214
+ @must_support_metadata_extractor ||=
215
+ MustSupportMetadataExtractor.new(profile_elements, profile, resource, ig_resources)
216
+ end
217
+
218
+ def must_supports
219
+ @must_supports ||=
220
+ must_support_metadata_extractor.must_supports
221
+ end
222
+
223
+ def mandatory_elements
224
+ @mandatory_elements ||=
225
+ profile_elements
226
+ .select { |element| element.min.positive? }
227
+ .map(&:path)
228
+ .uniq
229
+ end
230
+
231
+ def references
232
+ @references ||=
233
+ profile_elements
234
+ .select { |element| element.type&.first&.code == 'Reference' }
235
+ .map do |reference_definition|
236
+ {
237
+ path: reference_definition.path,
238
+ profiles: reference_definition.type.first.targetProfile
239
+ }
240
+ end
241
+ end
242
+ end
243
+ end
244
+ end
@@ -0,0 +1,78 @@
1
+ require 'active_support/all'
2
+ require 'fhir_models'
3
+ require 'pathname'
4
+ require 'rubygems/package'
5
+ require 'zlib'
6
+ require 'pry'
7
+ require_relative 'ig_resources'
8
+
9
+ module DaVinciPASTestKit
10
+ class Generator
11
+ class IGLoader
12
+ attr_accessor :ig_file_name
13
+
14
+ def initialize(ig_file_name)
15
+ self.ig_file_name = ig_file_name
16
+ end
17
+
18
+ def ig_resources
19
+ @ig_resources ||= IGResources.new
20
+ end
21
+
22
+ def load
23
+ load_ig
24
+ load_standalone_resources
25
+ end
26
+
27
+ def load_ig
28
+ tar = Gem::Package::TarReader.new(
29
+ Zlib::GzipReader.open(ig_file_name)
30
+ )
31
+
32
+ tar.each do |entry|
33
+ next if entry.directory?
34
+
35
+ file_name = entry.full_name.split('/').last
36
+
37
+ next unless file_name.end_with? '.json'
38
+
39
+ next unless entry.full_name.start_with? 'package/'
40
+
41
+ begin
42
+ resource = FHIR.from_contents(entry.read)
43
+ next if resource.nil?
44
+ rescue StandardError
45
+ puts "#{file_name} does not appear to be a FHIR resource."
46
+ next
47
+ end
48
+
49
+ ig_resources.add(resource)
50
+ end
51
+
52
+ ig_resources
53
+ end
54
+
55
+ def load_standalone_resources
56
+ ig_directory = ig_file_name.chomp('.tgz')
57
+
58
+ return ig_resources unless File.exist? ig_directory
59
+
60
+ Dir.glob(File.join(ig_directory, '*.json')).each do |file_path|
61
+ begin
62
+ resource = FHIR.from_contents(File.read(file_path))
63
+
64
+ next if resource.nil?
65
+ rescue StandardError
66
+ file_name = file_path.split('/').last
67
+ puts "#{file_name} does not appear to be a FHIR resource."
68
+ next
69
+ end
70
+
71
+ ig_resources.add(resource)
72
+ end
73
+
74
+ ig_resources
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,66 @@
1
+ module DaVinciPASTestKit
2
+ class Generator
3
+ class IGMetadata
4
+ attr_accessor :ig_version, :groups, :use_case_groups
5
+
6
+ def reformatted_version
7
+ @reformatted_version ||= ig_version.delete('.-')
8
+ end
9
+
10
+ def ordered_groups
11
+ @ordered_groups ||=
12
+ [patient_group] + non_delayed_groups + delayed_groups
13
+ end
14
+
15
+ def patient_group
16
+ @patient_group ||=
17
+ groups.find { |group| group.resource == 'Patient' }
18
+ end
19
+
20
+ def delayed_groups
21
+ @delayed_groups ||=
22
+ groups.select(&:delayed?)
23
+ end
24
+
25
+ def non_delayed_groups
26
+ @non_delayed_groups ||=
27
+ groups.reject(&:delayed?) - [patient_group]
28
+ end
29
+
30
+ def delayed_profiles
31
+ @delayed_profiles ||=
32
+ delayed_groups.map(&:profile_url)
33
+ end
34
+
35
+ def add_use_case_groups(id, file_name)
36
+ @use_case_groups ||= []
37
+ @use_case_groups << { id:, file_name: }
38
+ end
39
+
40
+ def bundle_groups
41
+ @bundle_groups ||=
42
+ groups.select { |group| group.resource == 'Bundle' }
43
+ .reject { |group| group.profile_name.include?('Base') }
44
+ end
45
+
46
+ def claim_groups
47
+ @claim_groups ||=
48
+ groups.select { |group| group.resource == 'Claim' }
49
+ .reject { |group| group.profile_name.include?('Base') }
50
+ end
51
+
52
+ def postprocess_groups(ig_resources)
53
+ groups.each do |group|
54
+ group.add_delayed_references(delayed_profiles, ig_resources)
55
+ end
56
+ end
57
+
58
+ def to_hash
59
+ {
60
+ ig_version:,
61
+ groups: groups.map(&:to_hash)
62
+ }
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,54 @@
1
+ require_relative 'ig_metadata'
2
+ require_relative 'group_metadata_extractor'
3
+ require 'pry'
4
+ module DaVinciPASTestKit
5
+ class Generator
6
+ class IGMetadataExtractor
7
+ attr_accessor :ig_resources, :metadata
8
+
9
+ def initialize(ig_resources)
10
+ self.ig_resources = ig_resources
11
+ self.metadata = IGMetadata.new
12
+ end
13
+
14
+ def extract
15
+ add_metadata_from_ig
16
+ add_metadata_from_resources
17
+ metadata
18
+ end
19
+
20
+ def add_metadata_from_ig
21
+ metadata.ig_version = "v#{ig_resources.ig.version}"
22
+ end
23
+
24
+ def resources_in_capability_statement
25
+ # TODO: uncomment bellow when PAS IG will have a solid capability statement.
26
+ # ig_resources.capability_statement.rest.first.resource
27
+
28
+ # Work around for the code above to extract the IG supported profiles/resources
29
+ resources = []
30
+ ig_resources.base_resources_and_supported_profiles.each do |k, v|
31
+ resource = FHIR::CapabilityStatement::Rest::Resource.new(
32
+ type: k,
33
+ supportedProfile: v,
34
+ operation: k == 'Claim' ? [{ name: '$submit' }, { name: '$inquire' }] : []
35
+ )
36
+ resources << resource
37
+ end
38
+
39
+ resources
40
+ end
41
+
42
+ def add_metadata_from_resources
43
+ metadata.groups =
44
+ resources_in_capability_statement.flat_map do |resource|
45
+ resource.supportedProfile&.map do |supported_profile|
46
+ GroupMetadataExtractor.new(resource, supported_profile, metadata, ig_resources).group_metadata
47
+ end
48
+ end
49
+
50
+ metadata.postprocess_groups(ig_resources)
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,74 @@
1
+ module DaVinciPASTestKit
2
+ class Generator
3
+ class IGResources
4
+ def add(resource)
5
+ resources_by_type[resource.resourceType] << resource
6
+ end
7
+
8
+ def capability_statement(mode = 'server')
9
+ resources_by_type['CapabilityStatement'].find do |capability_statement_resource|
10
+ capability_statement_resource.rest.any? { |r| r.mode == mode }
11
+ end
12
+ end
13
+
14
+ def base_resources_and_supported_profiles
15
+ definitions = [
16
+ 'ImplementationGuide',
17
+ 'CapabilityStatement',
18
+ 'CodeSystem',
19
+ 'OperationDefinition',
20
+ 'StructureDefinition',
21
+ 'ValueSet'
22
+ ]
23
+ base_resources = resources_by_type.keys.reject { |k| definitions.include?(k) }
24
+ resource_profiles = {}
25
+ base_resources.each do |res|
26
+ profile_urls = resources_by_type['StructureDefinition'].find_all { |p| p.type == res }.map(&:url)
27
+ resource_profiles[res] = profile_urls
28
+ end
29
+ resource_profiles
30
+ end
31
+
32
+ def ig
33
+ resources_by_type['ImplementationGuide'].first
34
+ end
35
+
36
+ def inspect
37
+ 'IGResources'
38
+ end
39
+
40
+ def profile_by_url(url)
41
+ resources_by_type['StructureDefinition'].find { |profile| profile.url == url }
42
+ end
43
+
44
+ def resource_type_for_profile(url)
45
+ profile_by_url(url).type
46
+ end
47
+
48
+ def value_set_by_url(url)
49
+ resources_by_type['ValueSet'].find { |profile| profile.url == url }
50
+ end
51
+
52
+ # def search_param_by_resource_and_name(resource, name)
53
+ # # remove '_' from search parameter name, such as _id or _tag
54
+ # normalized_name = normalized_name = name.to_s.delete_prefix('_')
55
+
56
+ # param = resources_by_type['SearchParameter']
57
+ # .find { |param| param.id == "#{resource.downcase}-#{normalized_name}" }
58
+
59
+ # if param.nil?
60
+ # param = resources_by_type['SearchParameter']
61
+ # .find { |param| param.id == "Resource-#{normalized_name}" }
62
+ # end
63
+
64
+ # return param
65
+ # end
66
+
67
+ private
68
+
69
+ def resources_by_type
70
+ @resources_by_type ||= Hash.new { |hash, key| hash[key] = [] }
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,86 @@
1
+ module DaVinciPASTestKit
2
+ class Generator
3
+ module MustSupportCheckProfiles
4
+ SUBMIT_REQUEST_REQUIRED_PROFILES = [
5
+ 'PAS Request Bundle',
6
+ 'PAS Beneficiary Patient',
7
+ 'PAS Claim Update',
8
+ 'PAS Coverage',
9
+ 'PAS Device Request',
10
+ 'PAS Encounter',
11
+ 'PAS Insurer Organization',
12
+ 'PAS Medication Request',
13
+ 'PAS Nutrition Order',
14
+ 'PAS Practitioner',
15
+ 'PAS PractitionerRole',
16
+ 'PAS Requestor Organization',
17
+ 'PAS Service Request',
18
+ 'PAS Subscriber Patient'
19
+ ].freeze
20
+
21
+ SUBMIT_RESPONSE_REQUIRED_PROFILES = [
22
+ 'PAS Beneficiary Patient',
23
+ 'PAS Claim Response',
24
+ 'PAS CommunicationRequest',
25
+ 'PAS Insurer Organization',
26
+ 'PAS Practitioner',
27
+ 'PAS PractitionerRole',
28
+ 'PAS Requestor Organization',
29
+ 'PAS Response Bundle',
30
+ 'PAS Task'
31
+ ].freeze
32
+
33
+ INQUIRY_REQUEST_REQUIRED_PROFILES = [
34
+ 'PAS Beneficiary Patient',
35
+ 'PAS Claim Inquiry',
36
+ 'PAS Coverage',
37
+ 'PAS Inquiry Request Bundle',
38
+ 'PAS Insurer Organization',
39
+ 'PAS Practitioner',
40
+ 'PAS PractitionerRole',
41
+ 'PAS Requestor Organization',
42
+ 'PAS Subscriber Patient'
43
+ ].freeze
44
+
45
+ INQUIRY_RESPONSE_REQUIRED_PROFILES = [
46
+ 'PAS Beneficiary Patient',
47
+ 'PAS Claim Inquiry Response',
48
+ 'PAS Inquiry Response Bundle',
49
+ 'PAS Insurer Organization',
50
+ 'PAS Practitioner',
51
+ 'PAS PractitionerRole',
52
+ 'PAS Requestor Organization',
53
+ 'PAS Task'
54
+ ].freeze
55
+
56
+ OPTIONAL_PROFILES = [
57
+ 'PAS Medication Request',
58
+ 'PAS Service Request',
59
+ 'PAS Device Request',
60
+ 'PAS Nutrition Order'
61
+ ].freeze
62
+
63
+ class << self
64
+ def submit_request_group?(group)
65
+ SUBMIT_REQUEST_REQUIRED_PROFILES.include?(group.profile_name)
66
+ end
67
+
68
+ def submit_response_group?(group)
69
+ SUBMIT_RESPONSE_REQUIRED_PROFILES.include?(group.profile_name)
70
+ end
71
+
72
+ def inquiry_request_group?(group)
73
+ INQUIRY_REQUEST_REQUIRED_PROFILES.include?(group.profile_name)
74
+ end
75
+
76
+ def inquiry_response_group?(group)
77
+ INQUIRY_RESPONSE_REQUIRED_PROFILES.include?(group.profile_name)
78
+ end
79
+
80
+ def optional_group?(group)
81
+ OPTIONAL_PROFILES.include?(group.profile_name)
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end