diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..13f820c43 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,283 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true +tab_width = 3 +indent_size = 3 +charset = utf-8 + +[*.xml] +charset = utf-8 +indent_style = tab +tab_width = 3 +indent_size = 3 + +[*.json] +charset = utf-8 +indent_style = tab +tab_width = 3 +indent_size = 3 + +[*.vm] +charset = utf-8 +indent_style = tab +tab_width = 3 +indent_size = 3 + + +[*.java] +charset = utf-8 +indent_style = tab +tab_width = 3 +indent_size = 3 +continuation_indent_size=3 +ij_java_align_consecutive_assignments = false +ij_java_align_consecutive_variable_declarations = false +ij_java_align_group_field_declarations = false +ij_java_align_multiline_annotation_parameters = false +ij_java_align_multiline_array_initializer_expression = false +ij_java_align_multiline_assignment = false +ij_java_align_multiline_binary_operation = false +ij_java_align_multiline_chained_methods = false +ij_java_align_multiline_extends_list = false +ij_java_align_multiline_for = true +ij_java_align_multiline_method_parentheses = false +ij_java_align_multiline_parameters = true +ij_java_align_multiline_parameters_in_calls = false +ij_java_align_multiline_parenthesized_expression = false +ij_java_align_multiline_records = true +ij_java_align_multiline_resources = true +ij_java_align_multiline_ternary_operation = false +ij_java_align_multiline_text_blocks = false +ij_java_align_multiline_throws_list = false +ij_java_align_subsequent_simple_methods = false +ij_java_align_throws_keyword = false +ij_java_annotation_parameter_wrap = off +ij_java_array_initializer_new_line_after_left_brace = false +ij_java_array_initializer_right_brace_on_new_line = false +ij_java_array_initializer_wrap = off +ij_java_assert_statement_colon_on_next_line = false +ij_java_assert_statement_wrap = off +ij_java_assignment_wrap = off +ij_java_binary_operation_sign_on_next_line = false +ij_java_binary_operation_wrap = off +ij_java_blank_lines_after_anonymous_class_header = 0 +ij_java_blank_lines_after_class_header = 0 +ij_java_blank_lines_after_imports = 1 +ij_java_blank_lines_after_package = 1 +ij_java_blank_lines_around_class = 1 +ij_java_blank_lines_around_field = 0 +ij_java_blank_lines_around_field_in_interface = 0 +ij_java_blank_lines_around_initializer = 1 +ij_java_blank_lines_around_method = 1 +ij_java_blank_lines_around_method_in_interface = 1 +ij_java_blank_lines_before_class_end = 0 +ij_java_blank_lines_before_imports = 1 +ij_java_blank_lines_before_method_body = 0 +ij_java_blank_lines_before_package = 0 +ij_java_block_brace_style = end_of_line +ij_java_block_comment_at_first_column = true +ij_java_call_parameters_new_line_after_left_paren = false +ij_java_call_parameters_right_paren_on_new_line = false +ij_java_call_parameters_wrap = off +ij_java_case_statement_on_separate_line = true +ij_java_catch_on_new_line = false +ij_java_class_annotation_wrap = split_into_lines +ij_java_class_brace_style = end_of_line +ij_java_class_count_to_use_import_on_demand = 999 +ij_java_class_names_in_javadoc = 1 +ij_java_do_not_indent_top_level_class_members = false +ij_java_do_not_wrap_after_single_annotation = false +ij_java_do_while_brace_force = never +ij_java_doc_add_blank_line_after_description = true +ij_java_doc_add_blank_line_after_param_comments = false +ij_java_doc_add_blank_line_after_return = false +ij_java_doc_add_p_tag_on_empty_lines = true +ij_java_doc_align_exception_comments = true +ij_java_doc_align_param_comments = true +ij_java_doc_do_not_wrap_if_one_line = false +ij_java_doc_enable_formatting = true +ij_java_doc_enable_leading_asterisks = true +ij_java_doc_indent_on_continuation = false +ij_java_doc_keep_empty_lines = true +ij_java_doc_keep_empty_parameter_tag = true +ij_java_doc_keep_empty_return_tag = true +ij_java_doc_keep_empty_throws_tag = true +ij_java_doc_keep_invalid_tags = true +ij_java_doc_param_description_on_new_line = false +ij_java_doc_preserve_line_breaks = false +ij_java_doc_use_throws_not_exception_tag = true +ij_java_else_on_new_line = false +ij_java_entity_dd_suffix = EJB +ij_java_entity_eb_suffix = Bean +ij_java_entity_hi_suffix = Home +ij_java_entity_lhi_prefix = Local +ij_java_entity_lhi_suffix = Home +ij_java_entity_li_prefix = Local +ij_java_entity_pk_class = java.lang.String +ij_java_entity_vo_suffix = VO +ij_java_enum_constants_wrap = off +ij_java_extends_keyword_wrap = off +ij_java_extends_list_wrap = off +ij_java_field_annotation_wrap = split_into_lines +ij_java_field_name_prefix = my +ij_java_finally_on_new_line = false +ij_java_for_brace_force = never +ij_java_for_statement_new_line_after_left_paren = false +ij_java_for_statement_right_paren_on_new_line = false +ij_java_for_statement_wrap = off +ij_java_generate_final_locals = false +ij_java_generate_final_parameters = false +ij_java_if_brace_force = never +ij_java_imports_layout = *,|,javax.**,java.**,|,$* +ij_java_indent_case_from_switch = true +ij_java_insert_inner_class_imports = false +ij_java_insert_override_annotation = true +ij_java_keep_blank_lines_before_right_brace = 2 +ij_java_keep_blank_lines_between_package_declaration_and_header = 2 +ij_java_keep_blank_lines_in_code = 2 +ij_java_keep_blank_lines_in_declarations = 2 +ij_java_keep_control_statement_in_one_line = true +ij_java_keep_first_column_comment = true +ij_java_keep_indents_on_empty_lines = false +ij_java_keep_line_breaks = true +ij_java_keep_multiple_expressions_in_one_line = false +ij_java_keep_simple_blocks_in_one_line = false +ij_java_keep_simple_classes_in_one_line = false +ij_java_keep_simple_lambdas_in_one_line = false +ij_java_keep_simple_methods_in_one_line = false +ij_java_label_indent_absolute = false +ij_java_label_indent_size = 0 +ij_java_lambda_brace_style = end_of_line +ij_java_layout_static_imports_separately = true +ij_java_line_comment_add_space = false +ij_java_line_comment_at_first_column = true +ij_java_message_dd_suffix = EJB +ij_java_message_eb_suffix = Bean +ij_java_method_annotation_wrap = split_into_lines +ij_java_method_brace_style = end_of_line +ij_java_method_call_chain_wrap = off +ij_java_method_parameters_new_line_after_left_paren = false +ij_java_method_parameters_right_paren_on_new_line = false +ij_java_method_parameters_wrap = off +ij_java_modifier_list_wrap = false +ij_java_names_count_to_use_import_on_demand = 999 +ij_java_new_line_after_lparen_in_record_header = false +ij_java_packages_to_use_import_on_demand = java.awt.*,javax.swing.* +ij_java_parameter_annotation_wrap = off +ij_java_parameter_name_prefix = the +ij_java_parentheses_expression_new_line_after_left_paren = false +ij_java_parentheses_expression_right_paren_on_new_line = false +ij_java_place_assignment_sign_on_next_line = false +ij_java_prefer_longer_names = true +ij_java_prefer_parameters_wrap = false +ij_java_record_components_wrap = normal +ij_java_repeat_synchronized = true +ij_java_replace_instanceof_and_cast = false +ij_java_replace_null_check = true +ij_java_replace_sum_lambda_with_method_ref = true +ij_java_resource_list_new_line_after_left_paren = false +ij_java_resource_list_right_paren_on_new_line = false +ij_java_resource_list_wrap = off +ij_java_rparen_on_new_line_in_record_header = false +ij_java_session_dd_suffix = EJB +ij_java_session_eb_suffix = Bean +ij_java_session_hi_suffix = Home +ij_java_session_lhi_prefix = Local +ij_java_session_lhi_suffix = Home +ij_java_session_li_prefix = Local +ij_java_session_si_suffix = Service +ij_java_space_after_closing_angle_bracket_in_type_argument = false +ij_java_space_after_colon = true +ij_java_space_after_comma = true +ij_java_space_after_comma_in_type_arguments = true +ij_java_space_after_for_semicolon = true +ij_java_space_after_quest = true +ij_java_space_after_type_cast = true +ij_java_space_before_annotation_array_initializer_left_brace = false +ij_java_space_before_annotation_parameter_list = false +ij_java_space_before_array_initializer_left_brace = false +ij_java_space_before_catch_keyword = true +ij_java_space_before_catch_left_brace = true +ij_java_space_before_catch_parentheses = true +ij_java_space_before_class_left_brace = true +ij_java_space_before_colon = true +ij_java_space_before_colon_in_foreach = true +ij_java_space_before_comma = false +ij_java_space_before_do_left_brace = true +ij_java_space_before_else_keyword = true +ij_java_space_before_else_left_brace = true +ij_java_space_before_finally_keyword = true +ij_java_space_before_finally_left_brace = true +ij_java_space_before_for_left_brace = true +ij_java_space_before_for_parentheses = true +ij_java_space_before_for_semicolon = false +ij_java_space_before_if_left_brace = true +ij_java_space_before_if_parentheses = true +ij_java_space_before_method_call_parentheses = false +ij_java_space_before_method_left_brace = true +ij_java_space_before_method_parentheses = false +ij_java_space_before_opening_angle_bracket_in_type_parameter = false +ij_java_space_before_quest = true +ij_java_space_before_switch_left_brace = true +ij_java_space_before_switch_parentheses = true +ij_java_space_before_synchronized_left_brace = true +ij_java_space_before_synchronized_parentheses = true +ij_java_space_before_try_left_brace = true +ij_java_space_before_try_parentheses = true +ij_java_space_before_type_parameter_list = false +ij_java_space_before_while_keyword = true +ij_java_space_before_while_left_brace = true +ij_java_space_before_while_parentheses = true +ij_java_space_inside_one_line_enum_braces = false +ij_java_space_within_empty_array_initializer_braces = false +ij_java_space_within_empty_method_call_parentheses = false +ij_java_space_within_empty_method_parentheses = false +ij_java_spaces_around_additive_operators = true +ij_java_spaces_around_assignment_operators = true +ij_java_spaces_around_bitwise_operators = true +ij_java_spaces_around_equality_operators = true +ij_java_spaces_around_lambda_arrow = true +ij_java_spaces_around_logical_operators = true +ij_java_spaces_around_method_ref_dbl_colon = false +ij_java_spaces_around_multiplicative_operators = true +ij_java_spaces_around_relational_operators = true +ij_java_spaces_around_shift_operators = true +ij_java_spaces_around_type_bounds_in_type_parameters = true +ij_java_spaces_around_unary_operator = false +ij_java_spaces_within_angle_brackets = false +ij_java_spaces_within_annotation_parentheses = false +ij_java_spaces_within_array_initializer_braces = false +ij_java_spaces_within_braces = false +ij_java_spaces_within_brackets = false +ij_java_spaces_within_cast_parentheses = false +ij_java_spaces_within_catch_parentheses = false +ij_java_spaces_within_for_parentheses = false +ij_java_spaces_within_if_parentheses = false +ij_java_spaces_within_method_call_parentheses = false +ij_java_spaces_within_method_parentheses = false +ij_java_spaces_within_parentheses = false +ij_java_spaces_within_switch_parentheses = false +ij_java_spaces_within_synchronized_parentheses = false +ij_java_spaces_within_try_parentheses = false +ij_java_spaces_within_while_parentheses = false +ij_java_special_else_if_treatment = true +ij_java_static_field_name_prefix = our +ij_java_subclass_name_suffix = Impl +ij_java_ternary_operation_signs_on_next_line = false +ij_java_ternary_operation_wrap = off +ij_java_test_name_suffix = Test +ij_java_throws_keyword_wrap = off +ij_java_throws_list_wrap = off +ij_java_use_external_annotations = false +ij_java_use_fq_class_names = false +ij_java_use_relative_indents = false +ij_java_use_single_class_imports = true +ij_java_variable_annotation_wrap = off +ij_java_visibility = public +ij_java_while_brace_force = never +ij_java_while_on_new_line = false +ij_java_wrap_comments = false +ij_java_wrap_first_method_in_call_chain = false +ij_java_wrap_long_lines = false diff --git a/.idea/compiler.xml b/.idea/compiler.xml index b0c8e512b..88ddaa2bd 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -9,7 +9,9 @@ - + + + @@ -17,7 +19,9 @@ diff --git a/.idea/encodings.xml b/.idea/encodings.xml index 4a43f0d20..18f04cc77 100644 --- a/.idea/encodings.xml +++ b/.idea/encodings.xml @@ -3,8 +3,12 @@ + + + + diff --git a/.vscode/launch.json b/.vscode/launch.json index ae2a4261b..665fa9c47 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,7 +10,12 @@ "request": "launch", "mainClass": "org.opencds.cqf.ruler.Application", "projectName": "cqf-ruler-server", - "vmArgs": ["-XX:TieredStopAtLevel=1", "-Xverify:none", "-Dspring.main.lazy-initialization=true"], + "vmArgs": [ + "-XX:TieredStopAtLevel=1", + "-Xverify:none", + "-Dspring.main.lazy-initialization=true", + "-Dloader.debug=true" + ], "stepFilters": { "classNameFilters": [ "java.*", @@ -24,6 +29,7 @@ "classPaths": [ "$Auto", "${workspaceFolder}/plugin/hello-world/target/classes", + "${workspaceFolder}/plugin/ra/target/classes", "${workspaceFolder}/plugin/sdc/target/classes", "${workspaceFolder}/plugin/utility/target/classes" ] @@ -81,4 +87,4 @@ } } ] -} \ No newline at end of file +} diff --git a/.vscode/settings.json b/.vscode/settings.json index 6b7faefb3..ceb50694e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -16,5 +16,6 @@ "jpaserver", "springframework", "Versionless" - ] -} \ No newline at end of file + ], + "java.saveActions.organizeImports": true +} diff --git a/README.md b/README.md index d98e2bf59..ec930aef3 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ Visit the [wiki](https://github.com/DBCG/cqf-ruler/wiki) for more documentation. To run the cqf-ruler directory from this project use: -`java -jar server/target/cqf-ruler-server-*.jar` +`java -jar server/target/cqf-ruler-server-*.war` ### Plugins diff --git a/external/hapi-fhir-jpaserver-starter b/external/hapi-fhir-jpaserver-starter index ea3f10ec8..79fddf830 160000 --- a/external/hapi-fhir-jpaserver-starter +++ b/external/hapi-fhir-jpaserver-starter @@ -1 +1 @@ -Subproject commit ea3f10ec86774abfaedf220f46a7b515f9751d26 +Subproject commit 79fddf8309db91795fafaf3c877d96833f3b5dff diff --git a/external/pom.xml b/external/pom.xml index 2d9f73223..f466e1afc 100644 --- a/external/pom.xml +++ b/external/pom.xml @@ -94,7 +94,7 @@ maven-antrun-plugin - + generate-sources @@ -160,7 +160,7 @@ 1.4.1 - + generate-sources replace diff --git a/plugin/hello-world/src/test/java/org/opencds/cqf/ruler/plugin/hello/HelloWorldProviderIT.java b/plugin/hello-world/src/test/java/org/opencds/cqf/ruler/plugin/hello/HelloWorldProviderIT.java index eb470d975..8c7375ccb 100644 --- a/plugin/hello-world/src/test/java/org/opencds/cqf/ruler/plugin/hello/HelloWorldProviderIT.java +++ b/plugin/hello-world/src/test/java/org/opencds/cqf/ruler/plugin/hello/HelloWorldProviderIT.java @@ -16,7 +16,6 @@ import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.rest.client.api.IGenericClient; import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum; - @ExtendWith(SpringExtension.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = { Application.class, HelloWorldConfig.class }, properties = { diff --git a/plugin/ra/pom.xml b/plugin/ra/pom.xml new file mode 100644 index 000000000..6c8494ffb --- /dev/null +++ b/plugin/ra/pom.xml @@ -0,0 +1,60 @@ + + 4.0.0 + + org.opencds.cqf.ruler + cqf-ruler + 0.5.0-SNAPSHOT + ../.. + + + cqf-ruler-plugin-ra + + + org.opencds.cqf.ruler + cqf-ruler-external + 0.5.0-SNAPSHOT + provided + + + org.opencds.cqf.ruler + cqf-ruler-server + 0.5.0-SNAPSHOT + classes + provided + + + org.opencds.cqf.ruler + cqf-ruler-plugin-utility + 0.5.0-SNAPSHOT + provided + + + org.opencds.cqf.ruler + cqf-ruler-plugin-test-utility + 0.5.0-SNAPSHOT + provided + + + org.springframework.boot + spring-boot-autoconfigure + provided + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + + org.springframework.boot + spring-boot-starter-test + test + + + diff --git a/plugin/ra/src/main/java/org/opencds/cqf/ruler/plugin/ra/RAConfig.java b/plugin/ra/src/main/java/org/opencds/cqf/ruler/plugin/ra/RAConfig.java new file mode 100644 index 000000000..f4e8ff0c9 --- /dev/null +++ b/plugin/ra/src/main/java/org/opencds/cqf/ruler/plugin/ra/RAConfig.java @@ -0,0 +1,25 @@ +package org.opencds.cqf.ruler.plugin.ra; + +import ca.uhn.fhir.jpa.starter.annotations.OnR4Condition; + +import org.opencds.cqf.ruler.api.OperationProvider; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ConditionalOnProperty(prefix = "hapi.fhir.ra", name = "enabled", havingValue = "true") +public class RAConfig { + + @Bean + public RAProperties RAProperties() { + return new RAProperties(); + } + + @Bean + @Conditional(OnR4Condition.class) + public OperationProvider r4ReportProvider() { + return new org.opencds.cqf.ruler.plugin.ra.r4.ReportProvider(); + } +} diff --git a/plugin/ra/src/main/java/org/opencds/cqf/ruler/plugin/ra/RAProperties.java b/plugin/ra/src/main/java/org/opencds/cqf/ruler/plugin/ra/RAProperties.java new file mode 100644 index 000000000..f9aa9cce8 --- /dev/null +++ b/plugin/ra/src/main/java/org/opencds/cqf/ruler/plugin/ra/RAProperties.java @@ -0,0 +1,44 @@ +package org.opencds.cqf.ruler.plugin.ra; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@ConfigurationProperties(prefix = "hapi.fhir.ra") +@Configuration +@EnableConfigurationProperties +public class RAProperties { + + private Boolean enabled = true; + + public Boolean getEnabled() { + return this.enabled; + } + + public void setEnabled(Boolean enabled) { + this.enabled = enabled; + } + + private Report report = new Report(); + + public Report getReport() { + return report; + } + + public void setReport(Report report) { + this.report = report; + } + + public static class Report { + + private String endpoint; + + public String getEndpoint() { + return endpoint; + } + + public void setEndpoint(String endpoint) { + this.endpoint = endpoint; + } + } +} diff --git a/plugin/ra/src/main/java/org/opencds/cqf/ruler/plugin/ra/r4/ReportProvider.java b/plugin/ra/src/main/java/org/opencds/cqf/ruler/plugin/ra/r4/ReportProvider.java new file mode 100644 index 000000000..91dfc2172 --- /dev/null +++ b/plugin/ra/src/main/java/org/opencds/cqf/ruler/plugin/ra/r4/ReportProvider.java @@ -0,0 +1,234 @@ +package org.opencds.cqf.ruler.plugin.ra.r4; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.instance.model.api.IAnyResource; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IIdType; +import org.hl7.fhir.r4.model.Bundle; +import org.hl7.fhir.r4.model.Group; +import org.hl7.fhir.r4.model.Identifier; +import org.hl7.fhir.r4.model.MeasureReport; +import org.hl7.fhir.r4.model.Meta; +import org.hl7.fhir.r4.model.Parameters; +import org.hl7.fhir.r4.model.Patient; +import org.hl7.fhir.r4.model.Period; +import org.hl7.fhir.r4.model.Reference; +import org.hl7.fhir.r4.model.Resource; +import org.opencds.cqf.ruler.api.OperationProvider; +import org.opencds.cqf.ruler.plugin.utility.OperatorUtilities; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; + +import ca.uhn.fhir.jpa.api.dao.DaoRegistry; +import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao; +import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; +import ca.uhn.fhir.jpa.starter.AppProperties; +import ca.uhn.fhir.model.api.annotation.Description; +import ca.uhn.fhir.rest.annotation.Operation; +import ca.uhn.fhir.rest.annotation.OperationParam; +import ca.uhn.fhir.rest.param.ReferenceParam; +public class ReportProvider implements OperationProvider, OperatorUtilities { + + @Autowired + private DaoRegistry myDaoRegistry; + + @Autowired + private AppProperties myAppProperties; + + private static final Logger ourLog = LoggerFactory.getLogger(ReportProvider.class); + + /** + * Implements the $report + * operation found in the + * Da Vinci Risk + * Adjustment IG. + * + * @param periodStart the start of the clinical evaluation period + * @param periodEnd the end of the clinical evaluation period + * @param subject a Patient or Patient Group + * @return a Parameters with Bundles of MeasureReports and evaluatedResource + * Resources + */ + @Description(shortDefinition = "$report", value = "Implements the $report operation found in the Da Vinci Risk Adjustment IG.") + + @Operation(name = "$report", idempotent = true, type = MeasureReport.class) + public Parameters report( + @OperationParam(name = "periodStart", min = 1, max = 1) String periodStart, + @OperationParam(name = "periodEnd", min = 1, max = 1) String periodEnd, + @OperationParam(name = "subject", min = 1, max = 1) String subject) throws FHIRException { + + Period period = validateParamaters(periodStart, periodEnd, subject); + Parameters result = initializeParametersResult(subject); + List patients = getPatientListFromSubject(subject); + + (patients) + .forEach( + patient -> { + Parameters.ParametersParameterComponent patientParameter = patientReport(patient, period, + myAppProperties.getServer_address()); + result.addParameter(patientParameter); + }); + + return result; + } + + private Period validateParamaters(String periodStart, String periodEnd, String subject) { + if (periodStart == null) { + throw new IllegalArgumentException("Parameter 'periodStart' is required."); + } + if (periodEnd == null) { + throw new IllegalArgumentException("Parameter 'periodEnd' is required."); + } + Date periodStartDate = resolveRequestDate(periodStart, true); + Date periodEndDate = resolveRequestDate(periodEnd, false); + if (periodStartDate.after(periodEndDate)) { + throw new IllegalArgumentException("Parameter 'periodStart' must be before 'periodEnd'."); + } + + if (subject == null) { + throw new IllegalArgumentException("Parameter 'subject' is required."); + } + if (!subject.startsWith("Patient/") && !subject.startsWith("Group/")) { + throw new IllegalArgumentException( + "Parameter 'subject' must be in the format 'Patient/[id]' or 'Group/[id]'."); + } + + return new Period().setStart(periodStartDate).setEnd(periodEndDate); + } + + private Parameters initializeParametersResult(String subject) { + Parameters result = new Parameters(); + result.setId(subject.replace("/", "-") + "-report"); + + return result; + } + + private static String PATIENT_REPORT_PROFILE_URL = "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-measurereport-bundle"; + + private Parameters.ParametersParameterComponent patientReport(Patient thePatient, Period thePeriod, + String serverBase) { + + String patientId = thePatient.getIdElement().getIdPart(); + final Map bundleEntries = new HashMap<>(); + bundleEntries.put(thePatient.getIdElement(), thePatient); + + SearchParameterMap theParams = SearchParameterMap.newSynchronous(); + ReferenceParam subjectParam = new ReferenceParam(patientId); + theParams.add("subject", subjectParam); + IFhirResourceDao measureReportDao = myDaoRegistry.getResourceDao(MeasureReport.class); + measureReportDao.search(theParams).getAllResources().forEach(baseResource -> { + MeasureReport measureReport = (MeasureReport) baseResource; + + if (measureReport.getPeriod().getEnd().before(thePeriod.getStart()) + || measureReport.getPeriod().getStart().after(thePeriod.getEnd())) { + return; + } + + bundleEntries.putIfAbsent(measureReport.getIdElement(), measureReport); + + getEvaluatedResources(measureReport).forEach(resource -> { + bundleEntries.putIfAbsent(resource.getIdElement(), resource); + }); + }); + + Bundle patientReportBundle = new Bundle(); + patientReportBundle.setMeta(new Meta().addProfile(PATIENT_REPORT_PROFILE_URL)); + patientReportBundle.setType(Bundle.BundleType.COLLECTION); + patientReportBundle.setTimestamp(new Date()); + patientReportBundle.setId(patientId + "-report"); + patientReportBundle.setIdentifier( + new Identifier().setSystem("urn:ietf:rfc:3986").setValue("urn:uuid:" + UUID.randomUUID().toString())); + + bundleEntries.entrySet().forEach(resource -> { + patientReportBundle.addEntry( + new Bundle.BundleEntryComponent() + .setResource((Resource) resource.getValue()) + .setFullUrl(getFullUrl(serverBase, resource.getValue().fhirType(), + resource.getValue().getIdElement().getIdPart()))); + }); + + Parameters.ParametersParameterComponent patientParameter = new Parameters.ParametersParameterComponent(); + patientParameter.setResource(patientReportBundle); + patientParameter.setId(thePatient.getIdElement().getIdPart() + "-report"); + patientParameter.setName("return"); + + return patientParameter; + } + + // TODO: this might be useful to make a utility + private List getEvaluatedResources(MeasureReport report) { + List resources = new ArrayList<>(); + for (Reference evaluatedResource : report.getEvaluatedResource()) { + IIdType theEvaluatedId = evaluatedResource.getReferenceElement(); + IBaseResource resourceBase = this.resolveById(myDaoRegistry, theEvaluatedId); + if (resourceBase != null && resourceBase instanceof Resource) { + Resource resource = (Resource) resourceBase; + resources.add(resource); + } + } + return resources; + + } + + // TODO: replace this with version from the evaluator? + private Patient ensurePatient(String patientRef) { + IBaseResource patient = resolveById(myDaoRegistry, Patient.class, patientRef); + if (patient == null) { + throw new RuntimeException("Could not find Patient: " + patientRef); + } + return (Patient) patient; + } + + // TODO: replace this with version from the evaluator? + private List getPatientListFromSubject(String subject) { + List patientList = null; + + if (subject.startsWith("Patient/")) { + Patient patient = ensurePatient(subject); + patientList = new ArrayList(); + patientList.add(patient); + } else if (subject.startsWith("Group/")) { + patientList = getPatientListFromGroup(subject); + } else { + ourLog.info(String.format("Subject member was not a Patient or a Group, so skipping. \n%s", subject)); + } + + return patientList; + } + + // TODO: replace this with version from the evaluator? + private List getPatientListFromGroup(String subjectGroupId) { + List patientList = new ArrayList<>(); + + IBaseResource baseGroup = resolveById(myDaoRegistry, Group.class, subjectGroupId); + if (baseGroup == null) { + throw new RuntimeException("Could not find Group: " + subjectGroupId); + } + + Group group = (Group) baseGroup; + group.getMember().forEach(member -> { + Reference reference = member.getEntity(); + if (reference.getReferenceElement().getResourceType().equals("Patient")) { + Patient patient = ensurePatient(reference.getReference()); + patientList.add(patient); + } else if (reference.getReferenceElement().getResourceType().equals("Group")) { + patientList.addAll(getPatientListFromGroup(reference.getReference())); + } else { + ourLog.info( + String.format("Group member was not a Patient or a Group, so skipping. \n%s", + reference.getReference())); + } + }); + + return patientList; + } +} diff --git a/plugin/ra/src/main/resources/META-INF/spring.factories b/plugin/ra/src/main/resources/META-INF/spring.factories new file mode 100644 index 000000000..c7f2c02f9 --- /dev/null +++ b/plugin/ra/src/main/resources/META-INF/spring.factories @@ -0,0 +1,2 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ +org.opencds.cqf.ruler.plugin.ra.RAConfig \ No newline at end of file diff --git a/plugin/ra/src/main/resources/application.yaml b/plugin/ra/src/main/resources/application.yaml new file mode 100644 index 000000000..b064ee800 --- /dev/null +++ b/plugin/ra/src/main/resources/application.yaml @@ -0,0 +1,6 @@ +hapi: + fhir: + ra: + enabled: true + report: + endpoint: '' \ No newline at end of file diff --git a/plugin/ra/src/test/java/org/opencds/cqf/ruler/plugin/ra/r4/ReportProviderIT.java b/plugin/ra/src/test/java/org/opencds/cqf/ruler/plugin/ra/r4/ReportProviderIT.java new file mode 100644 index 000000000..5e9c8e5d6 --- /dev/null +++ b/plugin/ra/src/test/java/org/opencds/cqf/ruler/plugin/ra/r4/ReportProviderIT.java @@ -0,0 +1,340 @@ +package org.opencds.cqf.ruler.plugin.ra.r4; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.io.IOException; + +import org.hl7.fhir.r4.model.Bundle; +import org.hl7.fhir.r4.model.Group; +import org.hl7.fhir.r4.model.MeasureReport; +import org.hl7.fhir.r4.model.Parameters; +import org.hl7.fhir.r4.model.StringType; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.opencds.cqf.ruler.Application; +import org.opencds.cqf.ruler.plugin.ra.RAConfig; +import org.opencds.cqf.ruler.plugin.ra.RAProperties; +import org.opencds.cqf.ruler.plugin.testutility.ResolutionUtilities; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.context.FhirVersionEnum; +import ca.uhn.fhir.jpa.api.dao.DaoRegistry; +import ca.uhn.fhir.rest.client.api.IGenericClient; +import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum; +import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; +import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; + +@ExtendWith(SpringExtension.class) +@ActiveProfiles("test") +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = { Application.class, + RAConfig.class }, properties = { "hapi.fhir.fhir_version=r4", "hapi.fhir.ra.enabled=true" }) +public class ReportProviderIT implements org.opencds.cqf.ruler.plugin.testutility.ClientUtilities, ResolutionUtilities, + org.opencds.cqf.ruler.plugin.utility.ClientUtilities { + + private IGenericClient ourClient; + private FhirContext ourCtx; + + @Autowired + private DaoRegistry ourRegistry; + + @Autowired + private RAProperties myRaProperties; + + @LocalServerPort + private int port; + + @BeforeEach + void beforeEach() { + + ourCtx = FhirContext.forCached(FhirVersionEnum.R4); + ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER); + ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000); + String ourServerBase = getClientUrl(myRaProperties.getReport().getEndpoint(), port); + ourClient = createClient(ourCtx, ourServerBase); + myRaProperties.getReport().setEndpoint(ourServerBase); + } + + @Test + public void testMissingPeriodStartParam() throws IOException { + + Parameters params = new Parameters(); + params.addParameter().setName("periodEnd").setValue(new StringType("2021-12-31")); + params.addParameter().setName("subject").setValue(new StringType("Patient/testReport01")); + + assertThrows(InternalErrorException.class, () -> { + ourClient.operation().onType(MeasureReport.class).named("$report") + .withParameters(params) + .returnResourceType(Parameters.class) + .execute(); + }); + } + + @Test + public void testMissingPeriodEndParam() throws IOException { + + Parameters params = new Parameters(); + params.addParameter().setName("periodStart").setValue(new StringType("2021-01-01")); + params.addParameter().setName("subject").setValue(new StringType("Patient/testReport01")); + + assertThrows(InternalErrorException.class, () -> { + ourClient.operation().onType(MeasureReport.class).named("$report") + .withParameters(params) + .returnResourceType(Parameters.class) + .execute(); + }); + } + + @Test + public void testMissingSubjectParam() throws IOException { + + Parameters params = new Parameters(); + params.addParameter().setName("periodStart").setValue(new StringType("2021-01-01")); + params.addParameter().setName("periodEnd").setValue(new StringType("2021-12-31")); + + assertThrows(InternalErrorException.class, () -> { + ourClient.operation().onType(MeasureReport.class).named("$report") + .withParameters(params) + .returnResourceType(Parameters.class) + .execute(); + }); + } + + @Test + public void testStartPeriodBeforeEndPeriod() throws IOException { + + Parameters params = new Parameters(); + params.addParameter().setName("periodStart").setValue(new StringType("2021-01-01")); + params.addParameter().setName("periodEnd").setValue(new StringType("2020-12-31")); + + assertThrows(InternalErrorException.class, () -> { + ourClient.operation().onType(MeasureReport.class).named("$report") + .withParameters(params) + .returnResourceType(Parameters.class) + .execute(); + }); + } + + // TODO: add the count of patients returned + @Test + public void testSubjectPatient() throws IOException { + + Parameters params = new Parameters(); + params.addParameter().setName("periodStart").setValue(new StringType("2021-01-01")); + params.addParameter().setName("periodEnd").setValue(new StringType("2021-12-31")); + params.addParameter().setName("subject").setValue(new StringType("Patient/ra-patient01")); + resolveByLocation(ourRegistry, "Patient-ra-patient01.json", ourCtx); + + assertDoesNotThrow(() -> { + ourClient.operation().onType(MeasureReport.class).named("$report") + .withParameters(params) + .returnResourceType(Parameters.class) + .execute(); + }); + } + + // TODO: add the count of patients returned + @Test + public void testSubjectGroup() throws IOException { + + Parameters params = new Parameters(); + params.addParameter().setName("periodStart").setValue(new StringType("2021-01-01")); + params.addParameter().setName("periodEnd").setValue(new StringType("2021-12-31")); + params.addParameter().setName("subject").setValue(new StringType("Group/ra-group01")); + resolveByLocation(ourRegistry, "Patient-ra-patient01.json", ourCtx); + resolveByLocation(ourRegistry, "Group-ra-group01.json", ourCtx); + + assertDoesNotThrow(() -> { + ourClient.operation().onType(MeasureReport.class).named("$report") + .withParameters(params) + .returnResourceType(Parameters.class) + .execute(); + }); + } + + @Test + public void testSubjectIsNotPatientOrGroup() throws IOException { + + Parameters params = new Parameters(); + params.addParameter().setName("periodStart").setValue(new StringType("2021-01-01")); + params.addParameter().setName("periodEnd").setValue(new StringType("2021-12-31")); + params.addParameter().setName("subject").setValue(new StringType("ra-patient01")); + + assertThrows(InternalErrorException.class, () -> { + ourClient.operation().onType(MeasureReport.class).named("$report") + .withParameters(params) + .returnResourceType(Parameters.class) + .execute(); + }); + } + + @Test + public void testPatientSubjectNotFound() throws IOException { + + Parameters params = new Parameters(); + params.addParameter().setName("periodStart").setValue(new StringType("2021-01-01")); + params.addParameter().setName("periodEnd").setValue(new StringType("2021-12-31")); + params.addParameter().setName("subject").setValue(new StringType("Patient/bad-patient")); + + assertThrows(ResourceNotFoundException.class, () -> { + ourClient.operation().onType(MeasureReport.class).named("$report") + .withParameters(params) + .returnResourceType(Parameters.class) + .execute(); + }); + } + + @Test + public void testGroupSubjectNotFound() throws IOException { + + Parameters params = new Parameters(); + params.addParameter().setName("periodStart").setValue(new StringType("2021-01-01")); + params.addParameter().setName("periodEnd").setValue(new StringType("2021-12-31")); + params.addParameter().setName("subject").setValue(new StringType("Group/bad-group")); + + assertThrows(ResourceNotFoundException.class, () -> { + ourClient.operation().onType(MeasureReport.class).named("$report") + .withParameters(params) + .returnResourceType(Parameters.class) + .execute(); + }); + } + + // This test requires the following application setting: + // enforce_referential_integrity_on_write: false + @Test + public void testSubjectPatientNotFoundInGroup() throws IOException { + + Parameters params = new Parameters(); + params.addParameter().setName("periodStart").setValue(new StringType("2021-01-01")); + params.addParameter().setName("periodEnd").setValue(new StringType("2021-12-31")); + params.addParameter().setName("subject").setValue(new StringType("Group/ra-group00")); + resolveByLocation(ourRegistry, "Group-ra-group00.json", ourCtx); + Group group = ourClient.read().resource(Group.class).withId("ra-group00").execute(); + assertNotNull(group); + + assertThrows(ResourceNotFoundException.class, () -> { + ourClient.operation().onType(MeasureReport.class).named("$report") + .withParameters(params) + .returnResourceType(Parameters.class) + .execute(); + }); + } + + // TODO: add the count of patients returned + @Test + public void testSubjectMultiplePatientGroup() throws IOException { + + Parameters params = new Parameters(); + params.addParameter().setName("periodStart").setValue(new StringType("2021-01-01")); + params.addParameter().setName("periodEnd").setValue(new StringType("2021-12-31")); + params.addParameter().setName("subject").setValue(new StringType("Group/ra-group02")); + resolveByLocation(ourRegistry, "Patient-ra-patient02.json", ourCtx); + resolveByLocation(ourRegistry, "Patient-ra-patient03.json", ourCtx); + resolveByLocation(ourRegistry, "Group-ra-group02.json", ourCtx); + + assertDoesNotThrow(() -> { + ourClient.operation().onType(MeasureReport.class).named("$report") + .withParameters(params) + .returnResourceType(Parameters.class) + .execute(); + }); + } + + @Test + public void testSingleSubjectSingleReport() throws IOException { + + Parameters params = new Parameters(); + params.addParameter().setName("periodStart").setValue(new StringType("2021-01-01")); + params.addParameter().setName("periodEnd").setValue(new StringType("2021-12-31")); + params.addParameter().setName("subject").setValue(new StringType("Patient/ra-patient01")); + resolveByLocation(ourRegistry, "Patient-ra-patient01.json", ourCtx); + resolveByLocation(ourRegistry, "Condition-ra-condition02pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Condition-ra-condition03pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Condition-ra-condition08pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Condition-ra-condition09pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Condition-ra-condition10pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Condition-ra-condition11pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Condition-ra-condition17pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Condition-ra-condition18pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Condition-ra-condition33pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Condition-ra-condition43pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Condition-ra-condition44pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Observation-ra-obs21pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Encounter-ra-encounter02pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Encounter-ra-encounter03pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Encounter-ra-encounter08pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Encounter-ra-encounter09pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Encounter-ra-encounter11pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Encounter-ra-encounter43pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Encounter-ra-encounter44pat01.json", ourCtx); + resolveByLocation(ourRegistry, "MeasureReport-ra-measurereport01.json", ourCtx); + + Parameters actual = ourClient.operation().onType(MeasureReport.class).named("$report") + .withParameters(params) + .returnResourceType(Parameters.class) + .execute(); + + assertNotNull(actual); + assertEquals(1, actual.getParameter().size()); + + Bundle bundle = (Bundle) actual.getParameter().get(0).getResource(); + assertNotNull(bundle); + // all the resources inserted above are in the bundle entry + assertEquals(21, bundle.getEntry().size()); + } + + @Test + public void testReportDoesNotIncludeNonEvaluatedResources() throws IOException { + + Parameters params = new Parameters(); + params.addParameter().setName("periodStart").setValue(new StringType("2021-01-01")); + params.addParameter().setName("periodEnd").setValue(new StringType("2021-12-31")); + params.addParameter().setName("subject").setValue(new StringType("Patient/ra-patient01")); + resolveByLocation(ourRegistry, "Patient-ra-patient01.json", ourCtx); + resolveByLocation(ourRegistry, "Condition-ra-condition02pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Condition-ra-condition03pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Condition-ra-condition08pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Condition-ra-condition09pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Condition-ra-condition10pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Condition-ra-condition11pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Condition-ra-condition17pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Condition-ra-condition18pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Condition-ra-condition33pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Condition-ra-condition43pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Condition-ra-condition44pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Observation-ra-obs21pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Encounter-ra-encounter02pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Encounter-ra-encounter03pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Encounter-ra-encounter08pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Encounter-ra-encounter09pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Encounter-ra-encounter11pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Encounter-ra-encounter43pat01.json", ourCtx); + resolveByLocation(ourRegistry, "Encounter-ra-encounter44pat01.json", ourCtx); + resolveByLocation(ourRegistry, "MeasureReport-ra-measurereport01.json", ourCtx); + // this is not an evaluatedResource of the report + resolveByLocation(ourRegistry, "Encounter-ra-encounter45pat01.json", ourCtx); + + Parameters actual = ourClient.operation().onType(MeasureReport.class).named("$report") + .withParameters(params) + .returnResourceType(Parameters.class) + .execute(); + + Bundle bundle = (Bundle) actual.getParameter().get(0).getResource(); + // all the resources inserted above are in the bundle entry except the one that + // was not evaluated + assertEquals(21, bundle.getEntry().size()); + } + + // TODO: create test for single patient, multiple reports + // TODO: create test for multiple patients, multiple reports + // TODO: create tests of overlap of MeasureReport date and period +} diff --git a/plugin/ra/src/test/resources/Condition-ra-condition02pat01.json b/plugin/ra/src/test/resources/Condition-ra-condition02pat01.json new file mode 100644 index 000000000..178f30357 --- /dev/null +++ b/plugin/ra/src/test/resources/Condition-ra-condition02pat01.json @@ -0,0 +1,55 @@ +{ + "resourceType": "Condition", + "id": "ra-condition02pat01", + "meta": { + "profile": [ + "http://hl7.org/fhir/us/core/StructureDefinition/us-core-condition" + ] + }, + "clinicalStatus": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/condition-clinical", + "code": "active", + "display": "Active" + } + ], + "text": "Active" + }, + "verificationStatus": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/condition-ver-status", + "code": "confirmed", + "display": "Confirmed" + } + ], + "text": "Confirmed" + }, + "category": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/condition-category", + "code": "encounter-diagnosis", + "display": "Encounter Diagnosis" + } + ], + "text": "Encounter Diagnosis" + } + ], + "code": { + "coding": [ + { + "system": "http://hl7.org/fhir/sid/icd-10-cm", + "code": "E08.29", + "display": "Diabetes mellitus due to underlying condition with other diabetic kidney complication" + } + ], + "text": "E08.29: Diabetes mellitus due to underlying condition with other diabetic kidney complication" + }, + "subject": { + "reference": "Patient/ra-patient01" + }, + "onsetDateTime": "2021-01-31" +} diff --git a/plugin/ra/src/test/resources/Condition-ra-condition03pat01.json b/plugin/ra/src/test/resources/Condition-ra-condition03pat01.json new file mode 100644 index 000000000..d3f03d4eb --- /dev/null +++ b/plugin/ra/src/test/resources/Condition-ra-condition03pat01.json @@ -0,0 +1,55 @@ +{ + "resourceType": "Condition", + "id": "ra-condition03pat01", + "meta": { + "profile": [ + "http://hl7.org/fhir/us/core/StructureDefinition/us-core-condition" + ] + }, + "clinicalStatus": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/condition-clinical", + "code": "active", + "display": "Active" + } + ], + "text": "Active" + }, + "verificationStatus": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/condition-ver-status", + "code": "confirmed", + "display": "Confirmed" + } + ], + "text": "Confirmed" + }, + "category": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/condition-category", + "code": "encounter-diagnosis", + "display": "Encounter Diagnosis" + } + ], + "text": "Encounter Diagnosis" + } + ], + "code": { + "coding": [ + { + "system": "http://hl7.org/fhir/sid/icd-10-cm", + "code": "J45.31", + "display": "Mild persistent asthma with (acute) exacerbation" + } + ], + "text": "J45.31: Mild persistent asthma with (acute) exacerbation" + }, + "subject": { + "reference": "Patient/ra-patient01" + }, + "onsetDateTime": "2021-09-26" +} diff --git a/plugin/ra/src/test/resources/Condition-ra-condition08pat01.json b/plugin/ra/src/test/resources/Condition-ra-condition08pat01.json new file mode 100644 index 000000000..479a2f40a --- /dev/null +++ b/plugin/ra/src/test/resources/Condition-ra-condition08pat01.json @@ -0,0 +1,55 @@ +{ + "resourceType": "Condition", + "id": "ra-condition08pat01", + "meta": { + "profile": [ + "http://hl7.org/fhir/us/core/StructureDefinition/us-core-condition" + ] + }, + "clinicalStatus": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/condition-clinical", + "code": "active", + "display": "Active" + } + ], + "text": "Active" + }, + "verificationStatus": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/condition-ver-status", + "code": "confirmed", + "display": "Confirmed" + } + ], + "text": "Confirmed" + }, + "category": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/condition-category", + "code": "encounter-diagnosis", + "display": "Encounter Diagnosis" + } + ], + "text": "Encounter Diagnosis" + } + ], + "code": { + "coding": [ + { + "system": "http://hl7.org/fhir/sid/icd-10-cm", + "code": "F31.61", + "display": "Bipolar disorder, current episode mixed, mild" + } + ], + "text": "Bipolar disorder, current episode mixed, mild" + }, + "subject": { + "reference": "Patient/ra-patient01" + }, + "onsetDateTime": "2017-02-03" +} diff --git a/plugin/ra/src/test/resources/Condition-ra-condition09pat01.json b/plugin/ra/src/test/resources/Condition-ra-condition09pat01.json new file mode 100644 index 000000000..044a20d7e --- /dev/null +++ b/plugin/ra/src/test/resources/Condition-ra-condition09pat01.json @@ -0,0 +1,55 @@ +{ + "resourceType": "Condition", + "id": "ra-condition09pat01", + "meta": { + "profile": [ + "http://hl7.org/fhir/us/core/StructureDefinition/us-core-condition" + ] + }, + "clinicalStatus": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/condition-clinical", + "code": "active", + "display": "Active" + } + ], + "text": "Active" + }, + "verificationStatus": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/condition-ver-status", + "code": "confirmed", + "display": "Confirmed" + } + ], + "text": "Confirmed" + }, + "category": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/condition-category", + "code": "encounter-diagnosis", + "display": "Encounter Diagnosis" + } + ], + "text": "Encounter Diagnosis" + } + ], + "code": { + "coding": [ + { + "system": "http://hl7.org/fhir/sid/icd-10-cm", + "code": "B44.81", + "display": "Allergic bronchopulmonary aspergillosis" + } + ], + "text": "B44.81: Allergic bronchopulmonary aspergillosis" + }, + "subject": { + "reference": "Patient/ra-patient01" + }, + "onsetDateTime": "2021-03-27" +} diff --git a/plugin/ra/src/test/resources/Condition-ra-condition10pat01.json b/plugin/ra/src/test/resources/Condition-ra-condition10pat01.json new file mode 100644 index 000000000..2010d7910 --- /dev/null +++ b/plugin/ra/src/test/resources/Condition-ra-condition10pat01.json @@ -0,0 +1,55 @@ +{ + "resourceType": "Condition", + "id": "ra-condition10pat01", + "meta": { + "profile": [ + "http://hl7.org/fhir/us/core/StructureDefinition/us-core-condition" + ] + }, + "clinicalStatus": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/condition-clinical", + "code": "active", + "display": "Active" + } + ], + "text": "Active" + }, + "verificationStatus": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/condition-ver-status", + "code": "confirmed", + "display": "Confirmed" + } + ], + "text": "Confirmed" + }, + "category": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/condition-category", + "code": "encounter-diagnosis", + "display": "Encounter Diagnosis" + } + ], + "text": "Encounter Diagnosis" + } + ], + "code": { + "coding": [ + { + "system": "http://hl7.org/fhir/sid/icd-10-cm", + "code": "J45.31", + "display": "Mild persistent asthma with (acute) exacerbation" + } + ], + "text": "J45.31: Mild persistent asthma with (acute) exacerbation" + }, + "subject": { + "reference": "Patient/ra-patient01" + }, + "onsetDateTime": "2021-09-26" +} diff --git a/plugin/ra/src/test/resources/Condition-ra-condition11pat01.json b/plugin/ra/src/test/resources/Condition-ra-condition11pat01.json new file mode 100644 index 000000000..aaed40233 --- /dev/null +++ b/plugin/ra/src/test/resources/Condition-ra-condition11pat01.json @@ -0,0 +1,55 @@ +{ + "resourceType": "Condition", + "id": "ra-condition11pat01", + "meta": { + "profile": [ + "http://hl7.org/fhir/us/core/StructureDefinition/us-core-condition" + ] + }, + "clinicalStatus": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/condition-clinical", + "code": "active", + "display": "Active" + } + ], + "text": "Active" + }, + "verificationStatus": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/condition-ver-status", + "code": "confirmed", + "display": "Confirmed" + } + ], + "text": "Confirmed" + }, + "category": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/condition-category", + "code": "encounter-diagnosis", + "display": "Encounter Diagnosis" + } + ], + "text": "Encounter Diagnosis" + } + ], + "code": { + "coding": [ + { + "system": "http://hl7.org/fhir/sid/icd-10-cm", + "code": "J81.0", + "display": "Acute pulmonary edema" + } + ], + "text": "J81.0: Acute pulmonary edema" + }, + "subject": { + "reference": "Patient/ra-patient01" + }, + "onsetDateTime": "2020-11-02" +} diff --git a/plugin/ra/src/test/resources/Condition-ra-condition17pat01.json b/plugin/ra/src/test/resources/Condition-ra-condition17pat01.json new file mode 100644 index 000000000..8f233ad99 --- /dev/null +++ b/plugin/ra/src/test/resources/Condition-ra-condition17pat01.json @@ -0,0 +1,55 @@ +{ + "resourceType": "Condition", + "id": "ra-condition17pat01", + "meta": { + "profile": [ + "http://hl7.org/fhir/us/core/StructureDefinition/us-core-condition" + ] + }, + "clinicalStatus": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/condition-clinical", + "code": "active", + "display": "Active" + } + ], + "text": "Active" + }, + "verificationStatus": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/condition-ver-status", + "code": "confirmed", + "display": "Confirmed" + } + ], + "text": "Confirmed" + }, + "category": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/condition-category", + "code": "encounter-diagnosis", + "display": "Encounter Diagnosis" + } + ], + "text": "Encounter Diagnosis" + } + ], + "code": { + "coding": [ + { + "system": "http://hl7.org/fhir/sid/icd-10-cm", + "code": "Z68.42", + "display": "Body mass index [BMI] 45.0-49.9, adult" + } + ], + "text": "Z68.42: Body mass index [BMI] 45.0-49.9, adult" + }, + "subject": { + "reference": "Patient/ra-patient01" + }, + "onsetDateTime": "2021-01-31" +} diff --git a/plugin/ra/src/test/resources/Condition-ra-condition18pat01.json b/plugin/ra/src/test/resources/Condition-ra-condition18pat01.json new file mode 100644 index 000000000..9647dbf20 --- /dev/null +++ b/plugin/ra/src/test/resources/Condition-ra-condition18pat01.json @@ -0,0 +1,55 @@ +{ + "resourceType": "Condition", + "id": "ra-condition18pat01", + "meta": { + "profile": [ + "http://hl7.org/fhir/us/core/StructureDefinition/us-core-condition" + ] + }, + "clinicalStatus": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/condition-clinical", + "code": "active", + "display": "Active" + } + ], + "text": "Active" + }, + "verificationStatus": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/condition-ver-status", + "code": "confirmed", + "display": "Confirmed" + } + ], + "text": "Confirmed" + }, + "category": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/condition-category", + "code": "encounter-diagnosis", + "display": "Encounter Diagnosis" + } + ], + "text": "Encounter Diagnosis" + } + ], + "code": { + "coding": [ + { + "system": "http://hl7.org/fhir/sid/icd-10-cm", + "code": "I48.11", + "display": "Longstanding persistent atrial fibrillation" + } + ], + "text": "I48.11: Longstanding persistent atrial fibrillation" + }, + "subject": { + "reference": "Patient/ra-patient01" + }, + "onsetDateTime": "2021-09-26" +} diff --git a/plugin/ra/src/test/resources/Condition-ra-condition33pat01.json b/plugin/ra/src/test/resources/Condition-ra-condition33pat01.json new file mode 100644 index 000000000..1df5577c6 --- /dev/null +++ b/plugin/ra/src/test/resources/Condition-ra-condition33pat01.json @@ -0,0 +1,55 @@ +{ + "resourceType": "Condition", + "id": "ra-condition33pat01", + "meta": { + "profile": [ + "http://hl7.org/fhir/us/core/StructureDefinition/us-core-condition" + ] + }, + "clinicalStatus": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/condition-clinical", + "code": "active", + "display": "Active" + } + ], + "text": "Active" + }, + "verificationStatus": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/condition-ver-status", + "code": "confirmed", + "display": "Confirmed" + } + ], + "text": "Confirmed" + }, + "category": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/condition-category", + "code": "encounter-diagnosis", + "display": "Encounter Diagnosis" + } + ], + "text": "Encounter Diagnosis" + } + ], + "code": { + "coding": [ + { + "system": "http://hl7.org/fhir/sid/icd-10-cm", + "code": "R09.2", + "display": "Respiratory arrest" + } + ], + "text": "R09.2: Respiratory arrest" + }, + "subject": { + "reference": "Patient/ra-patient01" + }, + "onsetDateTime": "2021-09-26" +} diff --git a/plugin/ra/src/test/resources/Condition-ra-condition43pat01.json b/plugin/ra/src/test/resources/Condition-ra-condition43pat01.json new file mode 100644 index 000000000..2a4ea9b9a --- /dev/null +++ b/plugin/ra/src/test/resources/Condition-ra-condition43pat01.json @@ -0,0 +1,55 @@ +{ + "resourceType": "Condition", + "id": "ra-condition43pat01", + "meta": { + "profile": [ + "http://hl7.org/fhir/us/core/StructureDefinition/us-core-condition" + ] + }, + "clinicalStatus": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/condition-clinical", + "code": "active", + "display": "Active" + } + ], + "text": "Active" + }, + "verificationStatus": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/condition-ver-status", + "code": "confirmed", + "display": "Confirmed" + } + ], + "text": "Confirmed" + }, + "category": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/condition-category", + "code": "encounter-diagnosis", + "display": "Encounter Diagnosis" + } + ], + "text": "Encounter Diagnosis" + } + ], + "code": { + "coding": [ + { + "system": "http://hl7.org/fhir/sid/icd-10-cm", + "code": "E08.29", + "display": "Diabetes mellitus due to underlying condition with other diabetic kidney complication" + } + ], + "text": "E08.29: Diabetes mellitus due to underlying condition with other diabetic kidney complication" + }, + "subject": { + "reference": "Patient/ra-patient01" + }, + "onsetDateTime": "2019-02-10" +} diff --git a/plugin/ra/src/test/resources/Condition-ra-condition44pat01.json b/plugin/ra/src/test/resources/Condition-ra-condition44pat01.json new file mode 100644 index 000000000..ec73b41c8 --- /dev/null +++ b/plugin/ra/src/test/resources/Condition-ra-condition44pat01.json @@ -0,0 +1,55 @@ +{ + "resourceType": "Condition", + "id": "ra-condition44pat01", + "meta": { + "profile": [ + "http://hl7.org/fhir/us/core/StructureDefinition/us-core-condition" + ] + }, + "clinicalStatus": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/condition-clinical", + "code": "active", + "display": "Active" + } + ], + "text": "Active" + }, + "verificationStatus": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/condition-ver-status", + "code": "confirmed", + "display": "Confirmed" + } + ], + "text": "Confirmed" + }, + "category": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/condition-category", + "code": "encounter-diagnosis", + "display": "Encounter Diagnosis" + } + ], + "text": "Encounter Diagnosis" + } + ], + "code": { + "coding": [ + { + "system": "http://hl7.org/fhir/sid/icd-10-cm", + "code": "B44.81", + "display": "Allergic bronchopulmonary aspergillosis" + } + ], + "text": "B44.81: Allergic bronchopulmonary aspergillosis" + }, + "subject": { + "reference": "Patient/ra-patient01" + }, + "onsetDateTime": "2017-01-18" +} diff --git a/plugin/ra/src/test/resources/Encounter-ra-encounter02pat01.json b/plugin/ra/src/test/resources/Encounter-ra-encounter02pat01.json new file mode 100644 index 000000000..054a8d434 --- /dev/null +++ b/plugin/ra/src/test/resources/Encounter-ra-encounter02pat01.json @@ -0,0 +1,59 @@ +{ + "resourceType": "Encounter", + "id": "ra-encounter02pat01", + "meta": { + "extension": [{ + "url": "http://hl7.org/fhir/StructureDefinition/instance-name", + "valueString": "Encounter with Dr Howell on 20210714 for Patient 03" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/instance-description", + "valueMarkdown": "This is Encounter with Dr Howell on 20210714 for Patient 03." + } + ], + "lastUpdated": "2021-07-14T11:56:57.250-04:00", + "profile": [ + "http://hl7.org/fhir/us/core/StructureDefinition/us-core-encounter" + ] + }, + "status": "finished", + "class": { + "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", + "code": "AMB", + "display": "ambulatory" + }, + "type": [{ + "coding": [{ + "system": "http://www.ama-assn.org/go/cpt", + "code": "99215" + }], + "text": "Office Visit, High Complexity" + }], + "subject": { + "reference": "Patient/ra-patient01" + }, + + "participant": [{ + "individual": { + "reference": "Practitioner/ra-prac01pat01" + } + }], + "diagnosis": [{ + "condition": { + "reference": "Condition/ra-condition02pat01" + } + }, + { + "condition": { + "reference": "Condition/ra-condition17pat01" + } + } + ], + "period": { + "start": "2021-01-31", + "end": "2021-01-31" + }, + "serviceProvider": { + "reference": "Organization/ra-org01pat01" + } +} diff --git a/plugin/ra/src/test/resources/Encounter-ra-encounter03pat01.json b/plugin/ra/src/test/resources/Encounter-ra-encounter03pat01.json new file mode 100644 index 000000000..62bb5bbb8 --- /dev/null +++ b/plugin/ra/src/test/resources/Encounter-ra-encounter03pat01.json @@ -0,0 +1,68 @@ +{ + "resourceType": "Encounter", + "id": "ra-encounter03pat01", + "meta": { + "extension": [{ + "url": "http://hl7.org/fhir/StructureDefinition/instance-name", + "valueString": "Encounter with Dr Howell on 20210714 for Patient 03" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/instance-description", + "valueMarkdown": "This is Encounter with Dr Howell on 20210714 for Patient 03." + } + ], + "profile": [ + "http://hl7.org/fhir/us/core/StructureDefinition/us-core-encounter" + ] + }, + "status": "finished", + "class": { + "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", + "code": "AMB", + "display": "ambulatory" + }, + "type": [{ + "coding": [{ + "system": "http://www.ama-assn.org/go/cpt", + "code": "99215" + }], + "text": "Office Visit, High Complexity" + }], + "subject": { + "reference": "Patient/ra-patient01" + }, + + "participant": [{ + "individual": { + "reference": "Practitioner/ra-prac01pat01" + } + }], + "diagnosis": [{ + "condition": { + "reference": "Condition/ra-condition03pat01" + } + }, + { + "condition": { + "reference": "Condition/ra-condition10pat01" + } + }, + { + "condition": { + "reference": "Condition/ra-condition18pat01" + } + }, + { + "condition": { + "reference": "Condition/ra-condition33pat01" + } + } + ], + "period": { + "start": "2021-09-26", + "end": "2021-09-26" + }, + "serviceProvider": { + "reference": "Organization/ra-org01pat01" + } +} diff --git a/plugin/ra/src/test/resources/Encounter-ra-encounter08pat01.json b/plugin/ra/src/test/resources/Encounter-ra-encounter08pat01.json new file mode 100644 index 000000000..a79439d39 --- /dev/null +++ b/plugin/ra/src/test/resources/Encounter-ra-encounter08pat01.json @@ -0,0 +1,53 @@ +{ + "resourceType": "Encounter", + "id": "ra-encounter08pat01", + "meta": { + "extension": [{ + "url": "http://hl7.org/fhir/StructureDefinition/instance-name", + "valueString": "Encounter with Dr Howell on 20210714 for Patient 03" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/instance-description", + "valueMarkdown": "This is Encounter with Dr Howell on 20210714 for Patient 03." + } + ], + "profile": [ + "http://hl7.org/fhir/us/core/StructureDefinition/us-core-encounter" + ] + }, + "status": "finished", + "class": { + "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", + "code": "AMB", + "display": "ambulatory" + }, + "type": [{ + "coding": [{ + "system": "http://www.ama-assn.org/go/cpt", + "code": "99215" + }], + "text": "Office Visit, High Complexity" + }], + "subject": { + "reference": "Patient/ra-patient01" + }, + + "participant": [{ + "individual": { + "reference": "Practitioner/ra-prac01pat01" + } + }], + "diagnosis": [{ + "condition": { + "reference": "Condition/ra-condition08pat01" + } + } + ], + "period": { + "start": "2017-02-03", + "end": "2017-02-03" + }, + "serviceProvider": { + "reference": "Organization/ra-org01pat01" + } +} diff --git a/plugin/ra/src/test/resources/Encounter-ra-encounter09pat01.json b/plugin/ra/src/test/resources/Encounter-ra-encounter09pat01.json new file mode 100644 index 000000000..3476375fe --- /dev/null +++ b/plugin/ra/src/test/resources/Encounter-ra-encounter09pat01.json @@ -0,0 +1,53 @@ +{ + "resourceType": "Encounter", + "id": "ra-encounter09pat01", + "meta": { + "extension": [{ + "url": "http://hl7.org/fhir/StructureDefinition/instance-name", + "valueString": "Encounter with Dr Howell on 20210714 for Patient 03" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/instance-description", + "valueMarkdown": "This is Encounter with Dr Howell on 20210714 for Patient 03." + } + ], + "profile": [ + "http://hl7.org/fhir/us/core/StructureDefinition/us-core-encounter" + ] + }, + "status": "finished", + "class": { + "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", + "code": "AMB", + "display": "ambulatory" + }, + "type": [{ + "coding": [{ + "system": "http://www.ama-assn.org/go/cpt", + "code": "99215" + }], + "text": "Office Visit, High Complexity" + }], + "subject": { + "reference": "Patient/ra-patient01" + }, + + "participant": [{ + "individual": { + "reference": "Practitioner/ra-prac01pat01" + } + }], + "diagnosis": [{ + "condition": { + "reference": "Condition/ra-condition09pat01" + } + } + ], + "period": { + "start": "2021-03-27", + "end": "2021-03-27" + }, + "serviceProvider": { + "reference": "Organization/ra-org01pat01" + } +} diff --git a/plugin/ra/src/test/resources/Encounter-ra-encounter11pat01.json b/plugin/ra/src/test/resources/Encounter-ra-encounter11pat01.json new file mode 100644 index 000000000..d0d017829 --- /dev/null +++ b/plugin/ra/src/test/resources/Encounter-ra-encounter11pat01.json @@ -0,0 +1,53 @@ +{ + "resourceType": "Encounter", + "id": "ra-encounter11pat01", + "meta": { + "extension": [{ + "url": "http://hl7.org/fhir/StructureDefinition/instance-name", + "valueString": "Encounter with Dr Howell on 20210714 for Patient 03" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/instance-description", + "valueMarkdown": "This is Encounter with Dr Howell on 20210714 for Patient 03." + } + ], + "profile": [ + "http://hl7.org/fhir/us/core/StructureDefinition/us-core-encounter" + ] + }, + "status": "finished", + "class": { + "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", + "code": "AMB", + "display": "ambulatory" + }, + "type": [{ + "coding": [{ + "system": "http://www.ama-assn.org/go/cpt", + "code": "99215" + }], + "text": "Office Visit, High Complexity" + }], + "subject": { + "reference": "Patient/ra-patient01" + }, + + "participant": [{ + "individual": { + "reference": "Practitioner/ra-prac01pat01" + } + }], + "diagnosis": [{ + "condition": { + "reference": "Condition/ra-condition11pat01" + } + } + ], + "period": { + "start": "2020-11-02", + "end": "2020-11-02" + }, + "serviceProvider": { + "reference": "Organization/ra-org01pat01" + } +} diff --git a/plugin/ra/src/test/resources/Encounter-ra-encounter43pat01.json b/plugin/ra/src/test/resources/Encounter-ra-encounter43pat01.json new file mode 100644 index 000000000..3e3d8d789 --- /dev/null +++ b/plugin/ra/src/test/resources/Encounter-ra-encounter43pat01.json @@ -0,0 +1,53 @@ +{ + "resourceType": "Encounter", + "id": "ra-encounter43pat01", + "meta": { + "extension": [{ + "url": "http://hl7.org/fhir/StructureDefinition/instance-name", + "valueString": "Encounter with Dr Howell on 20210714 for Patient 03" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/instance-description", + "valueMarkdown": "This is Encounter with Dr Howell on 20210714 for Patient 03." + } + ], + "profile": [ + "http://hl7.org/fhir/us/core/StructureDefinition/us-core-encounter" + ] + }, + "status": "finished", + "class": { + "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", + "code": "AMB", + "display": "ambulatory" + }, + "type": [{ + "coding": [{ + "system": "http://www.ama-assn.org/go/cpt", + "code": "99215" + }], + "text": "Office Visit, High Complexity" + }], + "subject": { + "reference": "Patient/ra-patient01" + }, + + "participant": [{ + "individual": { + "reference": "Practitioner/ra-prac01pat01" + } + }], + "diagnosis": [{ + "condition": { + "reference": "Condition/ra-condition43pat01" + } + } + ], + "period": { + "start": "2019-02-10", + "end": "2019-02-10" + }, + "serviceProvider": { + "reference": "Organization/ra-org01pat01" + } +} diff --git a/plugin/ra/src/test/resources/Encounter-ra-encounter44pat01.json b/plugin/ra/src/test/resources/Encounter-ra-encounter44pat01.json new file mode 100644 index 000000000..71611842d --- /dev/null +++ b/plugin/ra/src/test/resources/Encounter-ra-encounter44pat01.json @@ -0,0 +1,53 @@ +{ + "resourceType": "Encounter", + "id": "ra-encounter44pat01", + "meta": { + "extension": [{ + "url": "http://hl7.org/fhir/StructureDefinition/instance-name", + "valueString": "Encounter with Dr Howell on 20210714 for Patient 03" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/instance-description", + "valueMarkdown": "This is Encounter with Dr Howell on 20210714 for Patient 03." + } + ], + "profile": [ + "http://hl7.org/fhir/us/core/StructureDefinition/us-core-encounter" + ] + }, + "status": "finished", + "class": { + "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", + "code": "AMB", + "display": "ambulatory" + }, + "type": [{ + "coding": [{ + "system": "http://www.ama-assn.org/go/cpt", + "code": "99215" + }], + "text": "Office Visit, High Complexity" + }], + "subject": { + "reference": "Patient/ra-patient01" + }, + + "participant": [{ + "individual": { + "reference": "Practitioner/ra-prac01pat01" + } + }], + "diagnosis": [{ + "condition": { + "reference": "Condition/ra-condition44pat01" + } + } + ], + "period": { + "start": "2017-01-18", + "end": "2017-01-18" + }, + "serviceProvider": { + "reference": "Organization/ra-org01pat01" + } +} diff --git a/plugin/ra/src/test/resources/Encounter-ra-encounter45pat01.json b/plugin/ra/src/test/resources/Encounter-ra-encounter45pat01.json new file mode 100644 index 000000000..bb726de44 --- /dev/null +++ b/plugin/ra/src/test/resources/Encounter-ra-encounter45pat01.json @@ -0,0 +1,53 @@ +{ + "resourceType": "Encounter", + "id": "ra-encounter45pat01", + "meta": { + "extension": [{ + "url": "http://hl7.org/fhir/StructureDefinition/instance-name", + "valueString": "Encounter with Dr Howell on 20210714 for Patient 03" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/instance-description", + "valueMarkdown": "This is Encounter with Dr Howell on 20210714 for Patient 03." + } + ], + "profile": [ + "http://hl7.org/fhir/us/core/StructureDefinition/us-core-encounter" + ] + }, + "status": "finished", + "class": { + "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", + "code": "AMB", + "display": "ambulatory" + }, + "type": [{ + "coding": [{ + "system": "http://www.ama-assn.org/go/cpt", + "code": "99215" + }], + "text": "Office Visit, High Complexity" + }], + "subject": { + "reference": "Patient/ra-patient01" + }, + + "participant": [{ + "individual": { + "reference": "Practitioner/ra-prac01pat01" + } + }], + "diagnosis": [{ + "condition": { + "reference": "Condition/ra-condition44pat01" + } + } + ], + "period": { + "start": "2018-07-21", + "end": "2018-07-21" + }, + "serviceProvider": { + "reference": "Organization/ra-org01pat01" + } +} diff --git a/plugin/ra/src/test/resources/Group-ra-group00.json b/plugin/ra/src/test/resources/Group-ra-group00.json new file mode 100644 index 000000000..10c1e7e0b --- /dev/null +++ b/plugin/ra/src/test/resources/Group-ra-group00.json @@ -0,0 +1,18 @@ +{ + "resourceType": "Group", + "id": "ra-group00", + "meta": { + "profile": [ + "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-patient-group" + ] + }, + "type": "person", + "actual": true, + "member": [ + { + "entity": { + "reference": "Patient/ra-patient00" + } + } + ] +} \ No newline at end of file diff --git a/plugin/ra/src/test/resources/Group-ra-group01.json b/plugin/ra/src/test/resources/Group-ra-group01.json new file mode 100644 index 000000000..d0982f5ef --- /dev/null +++ b/plugin/ra/src/test/resources/Group-ra-group01.json @@ -0,0 +1,18 @@ +{ + "resourceType": "Group", + "id": "ra-group01", + "meta": { + "profile": [ + "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-patient-group" + ] + }, + "type": "person", + "actual": true, + "member": [ + { + "entity": { + "reference": "Patient/ra-patient01" + } + } + ] +} \ No newline at end of file diff --git a/plugin/ra/src/test/resources/Group-ra-group02.json b/plugin/ra/src/test/resources/Group-ra-group02.json new file mode 100644 index 000000000..a386565f6 --- /dev/null +++ b/plugin/ra/src/test/resources/Group-ra-group02.json @@ -0,0 +1,23 @@ +{ + "resourceType": "Group", + "id": "ra-group02", + "meta": { + "profile": [ + "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-patient-group" + ] + }, + "type": "person", + "actual": true, + "member": [ + { + "entity": { + "reference": "Patient/ra-patient02" + } + }, + { + "entity": { + "reference": "Patient/ra-patient03" + } + } + ] +} \ No newline at end of file diff --git a/plugin/ra/src/test/resources/MeasureReport-ra-measurereport01.json b/plugin/ra/src/test/resources/MeasureReport-ra-measurereport01.json new file mode 100644 index 000000000..6360e034c --- /dev/null +++ b/plugin/ra/src/test/resources/MeasureReport-ra-measurereport01.json @@ -0,0 +1,750 @@ +{ + "resourceType": "MeasureReport", + "id": "ra-measurereport01", + "meta": { + "profile": [ + "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-measurereport" + ] + }, + "extension": [ + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-clinicalDataCollectionDeadline", + "valueDate": "2022-03-31" + } + ], + "status": "complete", + "type": "individual", + "measure": "https://build.fhir.org/ig/HL7/davinci-ra/Measure-RAModelExample01", + "subject": { + "reference": "Patient/ra-patient01" + }, + "date": "2021-10-18", + "reporter": { + "reference": "Organization/ra-payer01" + }, + "period": { + "start": "2021-01-01", + "end": "2021-09-30" + }, + "group": [ + { + "id": "group-001", + "code": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/cmshcc", + "version": "24", + "code": "18", + "display": "Diabetes with Chronic Complications" + } + ], + "text": "HCC 18: Diabetes with Chronic Complications" + }, + "extension": [ + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-suspectType", + "valueCodeableConcept": { + "coding": [ + { + "code": "historic", + "system": "http://hl7.org/fhir/us/davinci-ra/CodeSystem/suspect-type" + } + ] + } + }, + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-evidenceStatus", + "valueCodeableConcept": { + "coding": [ + { + "code": "closed-gap", + "system": "http://hl7.org/fhir/us/davinci-ra/CodeSystem/evidence-status" + } + ] + } + }, + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-evidenceStatusDate", + "valueDate": "2021-04-01" + }, + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-hierarchicalStatus", + "valueCodeableConcept": { + "coding": [ + { + "code": "applied-not-superseded", + "system": "http://hl7.org/fhir/us/davinci-ra/CodeSystem/hierarchical-status" + } + ] + } + } + ] + }, + { + "id": "group-002", + "code": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/cmshcc", + "version": "24", + "code": "111", + "display": "Chronic Obstructive Pulmonary Disease" + } + ], + "text": "HCC 111: Chronic Obstructive Pulmonary Disease" + }, + "extension": [ + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-suspectType", + "valueCodeableConcept": { + "coding": [ + { + "code": "historic", + "system": "http://hl7.org/fhir/us/davinci-ra/CodeSystem/suspect-type" + } + ] + } + }, + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-evidenceStatus", + "valueCodeableConcept": { + "coding": [ + { + "code": "pending", + "system": "http://hl7.org/fhir/us/davinci-ra/CodeSystem/evidence-status" + } + ] + } + }, + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-evidenceStatusDate", + "valueDate": "2021-09-29" + }, + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-hierarchicalStatus", + "valueCodeableConcept": { + "coding": [ + { + "code": "applied-not-superseded", + "system": "http://hl7.org/fhir/us/davinci-ra/CodeSystem/hierarchical-status" + } + ] + } + } + ] + }, + { + "id": "group-003", + "code": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/cmshcc", + "version": "24", + "code": "53", + "display": "Major Depressive, Bipolar, and Paranoid Disorders" + } + ], + "text": "HCC 59: Major Depressive, Bipolar, and Paranoid Disorders" + }, + "extension": [ + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-suspectType", + "valueCodeableConcept": { + "coding": [ + { + "code": "historic", + "system": "http://hl7.org/fhir/us/davinci-ra/CodeSystem/suspect-type" + } + ] + } + }, + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-evidenceStatus", + "valueCodeableConcept": { + "coding": [ + { + "code": "open-gap", + "system": "http://hl7.org/fhir/us/davinci-ra/CodeSystem/evidence-status" + } + ] + } + }, + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-evidenceStatusDate", + "valueDate": "2020-07-15" + }, + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-hierarchicalStatus", + "valueCodeableConcept": { + "coding": [ + { + "code": "applied-not-superseded", + "system": "http://hl7.org/fhir/us/davinci-ra/CodeSystem/hierarchical-status" + } + ] + } + } + ] + }, + { + "id": "group-004", + "code": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/cmshcc", + "version": "24", + "code": "112", + "display": "Fibrosis of lung and other chronic lung disorders" + } + ], + "text": "HCC 112: Fibrosis of lung and other chronic lung disorders" + }, + "extension": [ + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-suspectType", + "valueCodeableConcept": { + "coding": [ + { + "code": "historic", + "system": "http://hl7.org/fhir/us/davinci-ra/CodeSystem/suspect-type" + } + ] + } + }, + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-evidenceStatus", + "valueCodeableConcept": { + "coding": [ + { + "code": "closed-gap", + "system": "http://hl7.org/fhir/us/davinci-ra/CodeSystem/evidence-status" + } + ] + } + }, + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-evidenceStatusDate", + "valueDate": "2021-04-27" + }, + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-hierarchicalStatus", + "valueCodeableConcept": { + "coding": [ + { + "code": "applied-superseded", + "system": "http://hl7.org/fhir/us/davinci-ra/CodeSystem/hierarchical-status" + } + ] + } + } + ] + }, + { + "id": "group-005", + "code": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/cmshcc", + "version": "24", + "code": "19", + "display": "Diabetes without Complications" + } + ], + "text": "HCC 19: Diabetes without Complications" + }, + "extension": [ + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-suspectType", + "valueCodeableConcept": { + "coding": [ + { + "code": "historic", + "system": "http://hl7.org/fhir/us/davinci-ra/CodeSystem/suspect-type" + } + ] + } + }, + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-evidenceStatus", + "valueCodeableConcept": { + "coding": [ + { + "code": "pending", + "system": "http://hl7.org/fhir/us/davinci-ra/CodeSystem/evidence-status" + } + ] + } + }, + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-evidenceStatusDate", + "valueDate": "2021-09-27" + }, + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-hierarchicalStatus", + "valueCodeableConcept": { + "coding": [ + { + "code": "applied-superseded", + "system": "http://hl7.org/fhir/us/davinci-ra/CodeSystem/hierarchical-status" + } + ] + } + } + ] + }, + { + "id": "group-006", + "code": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/cmshcc", + "version": "24", + "code": "84", + "display": "Cardio-Respiratory Failure and Shock" + } + ], + "text": "HCC 84: Cardio-Respiratory Failure and Shock" + }, + "extension": [ + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-suspectType", + "valueCodeableConcept": { + "coding": [ + { + "code": "historic", + "system": "http://hl7.org/fhir/us/davinci-ra/CodeSystem/suspect-type" + } + ] + } + }, + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-evidenceStatus", + "valueCodeableConcept": { + "coding": [ + { + "code": "open-gap", + "system": "http://hl7.org/fhir/us/davinci-ra/CodeSystem/evidence-status" + } + ] + } + }, + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-evidenceStatusDate", + "valueDate": "2020-12-15" + }, + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-hierarchicalStatus", + "valueCodeableConcept": { + "coding": [ + { + "code": "applied-superseded", + "system": "http://hl7.org/fhir/us/davinci-ra/CodeSystem/hierarchical-status" + } + ] + } + } + ] + }, + { + "id": "group-007", + "code": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/cmshcc", + "version": "24", + "code": "22", + "display": "Morbid Obesity" + } + ], + "text": "HCC 22: Morbid Obesity" + }, + "extension": [ + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-suspectType", + "valueCodeableConcept": { + "coding": [ + { + "code": "suspected", + "system": "http://hl7.org/fhir/us/davinci-ra/CodeSystem/suspect-type" + } + ] + } + }, + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-evidenceStatus", + "valueCodeableConcept": { + "coding": [ + { + "code": "closed-gap", + "system": "http://hl7.org/fhir/us/davinci-ra/CodeSystem/evidence-status" + } + ] + } + }, + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-evidenceStatusDate", + "valueDate": "2021-03-15" + }, + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-hierarchicalStatus", + "valueCodeableConcept": { + "coding": [ + { + "code": "applied-not-superseded", + "system": "http://hl7.org/fhir/us/davinci-ra/CodeSystem/hierarchical-status" + } + ] + } + } + ] + }, + { + "id": "group-008", + "code": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/cmshcc", + "version": "24", + "code": "96", + "display": "Specified Heart Arrhythmias" + } + ], + "text": "HCC 96: Specified Heart Arrhythmias" + }, + "extension": [ + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-suspectType", + "valueCodeableConcept": { + "coding": [ + { + "code": "suspected", + "system": "http://hl7.org/fhir/us/davinci-ra/CodeSystem/suspect-type" + } + ] + } + }, + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-evidenceStatus", + "valueCodeableConcept": { + "coding": [ + { + "code": "pending", + "system": "http://hl7.org/fhir/us/davinci-ra/CodeSystem/evidence-status" + } + ] + } + }, + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-evidenceStatusDate", + "valueDate": "2021-09-27" + }, + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-hierarchicalStatus", + "valueCodeableConcept": { + "coding": [ + { + "code": "applied-not-superseded", + "system": "http://hl7.org/fhir/us/davinci-ra/CodeSystem/hierarchical-status" + } + ] + } + } + ] + }, + { + "id": "group-009", + "code": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/cmshcc", + "version": "24", + "code": "110", + "display": "Cystic Fibrosis" + } + ], + "text": "HCC 110: Cystic Fibrosis" + }, + "extension": [ + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-suspectType", + "valueCodeableConcept": { + "coding": [ + { + "code": "suspected", + "system": "http://hl7.org/fhir/us/davinci-ra/CodeSystem/suspect-type" + } + ] + } + }, + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-evidenceStatus", + "valueCodeableConcept": { + "coding": [ + { + "code": "open-gap", + "system": "http://hl7.org/fhir/us/davinci-ra/CodeSystem/evidence-status" + } + ] + } + }, + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-evidenceStatusDate", + "valueDate": "2020-07-15" + }, + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-hierarchicalStatus", + "valueCodeableConcept": { + "coding": [ + { + "code": "applied-not-superseded", + "system": "http://hl7.org/fhir/us/davinci-ra/CodeSystem/hierarchical-status" + } + ] + } + } + ] + }, + { + "id": "group-010", + "code": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/cmshcc", + "version": "24", + "code": "83", + "display": "Respiratory Arrest" + } + ], + "text": "HCC 110: Cystic Fibrosis" + }, + "extension": [ + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-suspectType", + "valueCodeableConcept": { + "coding": [ + { + "code": "net-new", + "system": "http://hl7.org/fhir/us/davinci-ra/CodeSystem/suspect-type" + } + ] + } + }, + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-evidenceStatus", + "valueCodeableConcept": { + "coding": [ + { + "code": "pending", + "system": "http://hl7.org/fhir/us/davinci-ra/CodeSystem/evidence-status" + } + ] + } + }, + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-evidenceStatusDate", + "valueDate": "2021-09-28" + }, + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-hierarchicalStatus", + "valueCodeableConcept": { + "coding": [ + { + "code": "applied-not-superseded", + "system": "http://hl7.org/fhir/us/davinci-ra/CodeSystem/hierarchical-status" + } + ] + } + } + ] + } + ], + "evaluatedResource": [ + { + "extension": [ + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-groupReference", + "valueString": "group-001" + } + ], + "reference": "Condition/ra-condition02pat01" + }, + { + "extension": [ + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-groupReference", + "valueString": "group-002" + } + ], + "reference": "Condition/ra-condition03pat01" + }, + { + "extension": [ + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-groupReference", + "valueString": "group-003" + } + ], + "reference": "Condition/ra-condition08pat01" + }, + { + "extension": [ + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-groupReference", + "valueString": "group-004" + } + ], + "reference": "Condition/ra-condition09pat01" + }, + { + "extension": [ + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-groupReference", + "valueString": "group-005" + } + ], + "reference": "Condition/ra-condition10pat01" + }, + { + "extension": [ + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-groupReference", + "valueString": "group-006" + } + ], + "reference": "Condition/ra-condition11pat01" + }, + { + "extension": [ + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-groupReference", + "valueString": "group-007" + } + ], + "reference": "Condition/ra-condition17pat01" + }, + { + "extension": [ + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-groupReference", + "valueString": "group-008" + } + ], + "reference": "Condition/ra-condition18pat01" + }, + { + "extension": [ + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-groupReference", + "valueString": "group-010" + } + ], + "reference": "Condition/ra-condition33pat01" + }, + { + "extension": [ + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-groupReference", + "valueString": "group-001" + } + ], + "reference": "Condition/ra-condition43pat01" + }, + { + "extension": [ + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-groupReference", + "valueString": "group-004" + } + ], + "reference": "Condition/ra-condition44pat01" + }, + { + "extension": [ + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-groupReference", + "valueString": "group-001" + }, + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-groupReference", + "valueString": "group-007" + } + ], + "reference": "Encounter/ra-encounter02pat01" + }, + { + "extension": [ + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-groupReference", + "valueString": "group-002" + }, + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-groupReference", + "valueString": "group-005" + }, + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-groupReference", + "valueString": "group-008" + }, + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-groupReference", + "valueString": "group-010" + } + ], + "reference": "Encounter/ra-encounter03pat01" + }, + { + "extension": [ + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-groupReference", + "valueString": "group-003" + } + ], + "reference": "Encounter/ra-encounter08pat01" + }, + { + "extension": [ + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-groupReference", + "valueString": "group-004" + } + ], + "reference": "Encounter/ra-encounter09pat01" + }, + { + "extension": [ + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-groupReference", + "valueString": "group-006" + } + ], + "reference": "Encounter/ra-encounter11pat01" + }, + { + "extension": [ + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-groupReference", + "valueString": "group-001" + } + ], + "reference": "Encounter/ra-encounter43pat01" + }, + { + "extension": [ + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-groupReference", + "valueString": "group-004" + } + ], + "reference": "Encounter/ra-encounter44pat01" + }, + { + "extension": [ + { + "url": "http://hl7.org/fhir/us/davinci-ra/StructureDefinition/ra-groupReference", + "valueString": "group-009" + } + ], + "reference": "Observation/ra-obs21pat01" + } + ] +} diff --git a/plugin/ra/src/test/resources/Observation-ra-obs21pat01.json b/plugin/ra/src/test/resources/Observation-ra-obs21pat01.json new file mode 100644 index 000000000..fc7053f0d --- /dev/null +++ b/plugin/ra/src/test/resources/Observation-ra-obs21pat01.json @@ -0,0 +1,79 @@ +{ + "resourceType" : "Observation", + "id" : "ra-obs21pat01", + "meta" : { + "extension" : [ + { + "url" : "http://hl7.org/fhir/StructureDefinition/instance-name", + "valueString" : "Trypsin [Mass/volume] in Serum or Plasma for Pat01" + }, + { + "url" : "http://hl7.org/fhir/StructureDefinition/instance-description", + "valueMarkdown" : "Trypsin [Mass/volume] in Serum or Plasma for Pat01*." + } + ], + "profile" : [ + "http://hl7.org/fhir/us/core/StructureDefinition/us-core-observation-lab" + ] + }, + "status" : "final", + "category" : [ + { + "coding" : [ + { + "system" : "http://terminology.hl7.org/CodeSystem/observation-category", + "code" : "laboratory", + "display" : "Laboratory" + } + ], + "text" : "Laboratory" + } + ], + "code" : { + "coding" : [ + { + "system" : "http://loinc.org", + "code" : "33325-2", + "display" : "Trypsin [Mass/volume] in Serum or Plasma" + } + ], + "text" : "Trypsin [Mass/volume] in Serum or Plasma" + }, + "subject" : { + "reference" : "Patient/ra-patient01", + "display" : "Eve Everywoman" + }, + "effectiveDateTime" : "2019-06-17", + "valueQuantity" : { + "value" : 770, + "unit" : "ng/mL", + "system" : "http://unitsofmeasure.org" + }, + "referenceRange" : [ + { + "low" : { + "value" : 169, + "unit" : "ng/mL", + "system" : "http://unitsofmeasure.org", + "code" : "ng/mL" + }, + "high" : { + "value" : 773, + "unit" : "ng/mL", + "system" : "http://unitsofmeasure.org", + "code" : "mg/dL" + }, + "type" : + { + "coding" : [ + { + "system" : "http://terminology.hl7.org/CodeSystem/referencerange-meaning", + "code" : "normal", + "display" : "Normal Range" + } + ], + "text" : "Normal Range" + } + } + ] +} diff --git a/plugin/ra/src/test/resources/Patient-ra-patient01.json b/plugin/ra/src/test/resources/Patient-ra-patient01.json new file mode 100644 index 000000000..f1a1b86b8 --- /dev/null +++ b/plugin/ra/src/test/resources/Patient-ra-patient01.json @@ -0,0 +1,113 @@ +{ + "resourceType": "Patient", + "id": "ra-patient01", + "meta": { + "profile": [ + "http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient" + ] + }, + "extension": [ + { + "url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex", + "valueCode": "F" + }, + { + "url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-race", + "extension": [ + { + "url": "ombCategory", + "valueCoding": { + "system": "urn:oid:2.16.840.1.113883.6.238", + "code": "2106-3", + "display": "White" + } + }, + { + "url": "text", + "valueString": "White" + } + ] + }, + { + "url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity", + "extension": [ + { + "url": "ombCategory", + "valueCoding": { + "system": "urn:oid:2.16.840.1.113883.6.238", + "code": "2186-5", + "display": "Not Hispanic or Latino" + } + }, + { + "url": "text", + "valueString": "Not Hispanic or Latino" + } + ] + } + ], + "identifier": [ + { + "use": "usual", + "type": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/v2-0203", + "code": "MR", + "display": "Medical record number" + } + ] + }, + "system": "http://hospital.davinci.org", + "value": "12345" + } + ], + "active": true, + "name": [ + { + "use": "official", + "family": "Everywoman", + "given": [ + "Eve" + ] + } + ], + "gender": "female", + "birthDate": "1975-01-16", + "deceasedBoolean": false, + "address": [ + { + "use": "home", + "line": [ + "2222 Home Street" + ], + "city": "Ann Arbor", + "state": "MI", + "postalCode": "99999", + "country": "USA" + } + ], + "maritalStatus": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/v3-MaritalStatus", + "code": "M", + "display": "Married" + } + ] + }, + "communication": [ + { + "language": { + "coding": [ + { + "system": "urn:ietf:bcp:47", + "code": "en-US", + "display": "English (Region=United States)" + } + ] + }, + "preferred": true + } + ] +} diff --git a/plugin/ra/src/test/resources/Patient-ra-patient02.json b/plugin/ra/src/test/resources/Patient-ra-patient02.json new file mode 100644 index 000000000..5256799b2 --- /dev/null +++ b/plugin/ra/src/test/resources/Patient-ra-patient02.json @@ -0,0 +1,113 @@ +{ + "resourceType": "Patient", + "id": "ra-patient02", + "meta": { + "profile": [ + "http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient" + ] + }, + "extension": [ + { + "url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex", + "valueCode": "M" + }, + { + "url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-race", + "extension": [ + { + "url": "ombCategory", + "valueCoding": { + "system": "urn:oid:2.16.840.1.113883.6.238", + "code": "2106-3", + "display": "White" + } + }, + { + "url": "text", + "valueString": "White" + } + ] + }, + { + "url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity", + "extension": [ + { + "url": "ombCategory", + "valueCoding": { + "system": "urn:oid:2.16.840.1.113883.6.238", + "code": "2186-5", + "display": "Not Hispanic or Latino" + } + }, + { + "url": "text", + "valueString": "Not Hispanic or Latino" + } + ] + } + ], + "identifier": [ + { + "use": "usual", + "type": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/v2-0203", + "code": "MR", + "display": "Medical record number" + } + ] + }, + "system": "http://hospital.davinci.org", + "value": "23456" + } + ], + "active": true, + "name": [ + { + "use": "official", + "family": "Everyman", + "given": [ + "Adam" + ] + } + ], + "gender": "female", + "birthDate": "1950-12-16", + "deceasedBoolean": false, + "address": [ + { + "use": "home", + "line": [ + "2222 Home Street" + ], + "city": "Ann Arbor", + "state": "MI", + "postalCode": "99999", + "country": "USA" + } + ], + "maritalStatus": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/v3-MaritalStatus", + "code": "M", + "display": "Married" + } + ] + }, + "communication": [ + { + "language": { + "coding": [ + { + "system": "urn:ietf:bcp:47", + "code": "en-US", + "display": "English (Region=United States)" + } + ] + }, + "preferred": true + } + ] +} diff --git a/plugin/ra/src/test/resources/Patient-ra-patient03.json b/plugin/ra/src/test/resources/Patient-ra-patient03.json new file mode 100644 index 000000000..1b45ef856 --- /dev/null +++ b/plugin/ra/src/test/resources/Patient-ra-patient03.json @@ -0,0 +1,113 @@ +{ + "resourceType": "Patient", + "id": "ra-patient03", + "meta": { + "profile": [ + "http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient" + ] + }, + "extension": [ + { + "url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex", + "valueCode": "F" + }, + { + "url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-race", + "extension": [ + { + "url": "ombCategory", + "valueCoding": { + "system": "urn:oid:2.16.840.1.113883.6.238", + "code": "2054-5", + "display": "Black or African American" + } + }, + { + "url": "text", + "valueString": "Black or African American" + } + ] + }, + { + "url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity", + "extension": [ + { + "url": "ombCategory", + "valueCoding": { + "system": "urn:oid:2.16.840.1.113883.6.238", + "code": "2186-5", + "display": "Not Hispanic or Latino" + } + }, + { + "url": "text", + "valueString": "Not Hispanic or Latino" + } + ] + } + ], + "identifier": [ + { + "use": "usual", + "type": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/v2-0203", + "code": "MR", + "display": "Medical record number" + } + ] + }, + "system": "http://hospital.davinci.org", + "value": "34567" + } + ], + "active": true, + "name": [ + { + "use": "official", + "family": "Nuclear", + "given": [ + "Nelda" + ] + } + ], + "gender": "female", + "birthDate": "1965-07-26", + "deceasedBoolean": false, + "address": [ + { + "use": "home", + "line": [ + "6666 Home Street" + ], + "city": "Ann Arbor", + "state": "MI", + "postalCode": "99999", + "country": "USA" + } + ], + "maritalStatus": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/v3-MaritalStatus", + "code": "M", + "display": "Married" + } + ] + }, + "communication": [ + { + "language": { + "coding": [ + { + "system": "urn:ietf:bcp:47", + "code": "en-US", + "display": "English (Region=United States)" + } + ] + }, + "preferred": true + } + ] +} diff --git a/plugin/ra/src/test/resources/application-test.yaml b/plugin/ra/src/test/resources/application-test.yaml new file mode 100644 index 000000000..ad73d33c4 --- /dev/null +++ b/plugin/ra/src/test/resources/application-test.yaml @@ -0,0 +1,18 @@ +spring: + config: + import: application.yaml + main: + allow-bean-definition-overriding: true + batch: + job: + enabled: false" + datasource: + url: jdbc:h2:mem:dbr4-mt + +hapi: + fhir: + tester_enabled: false; + enforce_referential_integrity_on_write: false + ra: + report: + endpoint: http://localhost:%d/fhir diff --git a/plugin/sdc/pom.xml b/plugin/sdc/pom.xml index 46fa2f6f8..4c694123e 100644 --- a/plugin/sdc/pom.xml +++ b/plugin/sdc/pom.xml @@ -34,6 +34,12 @@ spring-boot-autoconfigure provided + + org.opencds.cqf.ruler + cqf-ruler-plugin-test-utility + 0.5.0-SNAPSHOT + test + org.junit.jupiter junit-jupiter-api diff --git a/plugin/sdc/src/test/java/org/opencds/cqf/ruler/plugin/sdc/r4/ExtractProviderIT.java b/plugin/sdc/src/test/java/org/opencds/cqf/ruler/plugin/sdc/r4/ExtractProviderIT.java index c3966e2b3..f18324175 100644 --- a/plugin/sdc/src/test/java/org/opencds/cqf/ruler/plugin/sdc/r4/ExtractProviderIT.java +++ b/plugin/sdc/src/test/java/org/opencds/cqf/ruler/plugin/sdc/r4/ExtractProviderIT.java @@ -15,9 +15,8 @@ import org.opencds.cqf.ruler.Application; import org.opencds.cqf.ruler.plugin.sdc.SDCConfig; import org.opencds.cqf.ruler.plugin.sdc.SDCProperties; -import org.opencds.cqf.ruler.plugin.utility.ResolutionUtilities; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.opencds.cqf.ruler.plugin.testutility.ResolutionUtilities; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.web.server.LocalServerPort; @@ -37,8 +36,6 @@ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = { Application.class, SDCConfig.class }, properties = {"hapi.fhir.fhir_version=r4", "hapi.fhir.sdc.enabled=true" }) public class ExtractProviderIT implements ResolutionUtilities { - private Logger log = LoggerFactory.getLogger(ExtractProviderIT.class); - private IGenericClient ourClient; private FhirContext ourCtx; diff --git a/plugin/test-utility/README.md b/plugin/test-utility/README.md new file mode 100644 index 000000000..e195d10e9 --- /dev/null +++ b/plugin/test-utility/README.md @@ -0,0 +1,3 @@ +# test utility Plugin + +This plugin provides cross-cutting test utility functions for other plugins diff --git a/plugin/test-utility/pom.xml b/plugin/test-utility/pom.xml new file mode 100644 index 000000000..d47c25928 --- /dev/null +++ b/plugin/test-utility/pom.xml @@ -0,0 +1,55 @@ + + 4.0.0 + + org.opencds.cqf.ruler + cqf-ruler + 0.5.0-SNAPSHOT + ../.. + + + cqf-ruler-plugin-test-utility + + + org.opencds.cqf.ruler + cqf-ruler-external + 0.5.0-SNAPSHOT + provided + + + org.opencds.cqf.ruler + cqf-ruler-server + 0.5.0-SNAPSHOT + classes + provided + + + org.springframework.boot + spring-boot-autoconfigure + provided + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.springframework.boot + spring-boot-starter-test + test + + + commons-io + commons-io + + + commons-validator + commons-validator + + + diff --git a/plugin/test-utility/src/main/java/org/opencds/cqf/ruler/plugin/testutility/ClientUtilities.java b/plugin/test-utility/src/main/java/org/opencds/cqf/ruler/plugin/testutility/ClientUtilities.java new file mode 100644 index 000000000..7a2809337 --- /dev/null +++ b/plugin/test-utility/src/main/java/org/opencds/cqf/ruler/plugin/testutility/ClientUtilities.java @@ -0,0 +1,30 @@ +package org.opencds.cqf.ruler.plugin.testutility; + +/** + * This interface provides test utility functions for creating IGenericClients and + * setting up authentication + */ +public interface ClientUtilities { + public static String SERVER_URL = "http://localhost:%d/fhir"; + + /** + * Creates an client url given a url template and port + * + * @param theUrlTemplate the url template to use + * @param thePort the port to use + * @return String for the client url + */ + public default String getClientUrl(String theUrlTemplate, Integer thePort) { + return String.format(theUrlTemplate, thePort); + } + + /** + * Creates an client url using the default url and port + * + * @param thePort the port to use + * @return String for the client url + */ + public default String getClientUrl(Integer thePort) { + return getClientUrl(SERVER_URL, thePort); + } +} diff --git a/plugin/test-utility/src/main/java/org/opencds/cqf/ruler/plugin/testutility/ResolutionUtilities.java b/plugin/test-utility/src/main/java/org/opencds/cqf/ruler/plugin/testutility/ResolutionUtilities.java new file mode 100644 index 000000000..8f76ee35c --- /dev/null +++ b/plugin/test-utility/src/main/java/org/opencds/cqf/ruler/plugin/testutility/ResolutionUtilities.java @@ -0,0 +1,68 @@ +package org.opencds.cqf.ruler.plugin.testutility; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +import com.google.common.base.Charsets; +import org.apache.commons.io.IOUtils; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.jpa.api.dao.DaoRegistry; +import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao; + +/** + * This interface provides test utility functions for resolving FHIR resources from a location. + * + */ +public interface ResolutionUtilities { + + /** + * Returns the Resource at the specified location. + * + * @param an IBaseResource type + * @param theResourceDao the DaoRegistry to use for resolution + * @param theLocation the location of the Resource to resolve + * @param theFhirContext the FhirContext to use to parse the resource + * @return the Resource at the specified location + * @throws IOException if the location does not exist or is unaccessible + */ + @SuppressWarnings("unchecked") + public default ResourceType resolveByLocation( + DaoRegistry theResourceDao, String theLocation, FhirContext theFhirContext) + throws IOException { + String json = stringFromResource(theLocation); + IBaseResource resource = theFhirContext.newJsonParser().parseResource(json); + IFhirResourceDao dao = theResourceDao.getResourceDao(resource.getIdElement().getResourceType()); + if (dao == null) { + return null; + } else { + dao.update(resource); + return (ResourceType) resource; + } + } + + /** + * Returns a String representation of the Resource + * at the specified location. + * + * @param theLocation the location of the Resource to resolve + * @return the string representation of the Resource + * @throws IOException if the location does not exist or is unaccessible + */ + public default String stringFromResource(String theLocation) throws IOException { + InputStream is = null; + if (theLocation.startsWith(File.separator)) { + is = new FileInputStream(theLocation); + } else { + DefaultResourceLoader resourceLoader = new DefaultResourceLoader(); + Resource resource = resourceLoader.getResource(theLocation); + is = resource.getInputStream(); + } + return IOUtils.toString(is, Charsets.UTF_8); + } +} diff --git a/plugin/test-utility/src/main/resources/META-INF/spring.factories b/plugin/test-utility/src/main/resources/META-INF/spring.factories new file mode 100644 index 000000000..e69de29bb diff --git a/plugin/test-utility/src/test/java/org/opencds/cqf/ruler/plugin/testutility/ClientUtilitiesTest.java b/plugin/test-utility/src/test/java/org/opencds/cqf/ruler/plugin/testutility/ClientUtilitiesTest.java new file mode 100644 index 000000000..c76a48062 --- /dev/null +++ b/plugin/test-utility/src/test/java/org/opencds/cqf/ruler/plugin/testutility/ClientUtilitiesTest.java @@ -0,0 +1,36 @@ +package org.opencds.cqf.ruler.plugin.testutility; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.apache.commons.validator.routines.UrlValidator; +import org.junit.jupiter.api.Test; + +public class ClientUtilitiesTest implements ClientUtilities { + @Test + public void testClientUrlWithTemplate() { + + String template = "http://localhost:%d/fhir"; + Integer port = 8084; + String url = getClientUrl(template, port); + + String[] schemes = {"http","https"}; + UrlValidator urlValidator = new UrlValidator(schemes, UrlValidator.ALLOW_LOCAL_URLS); + + assertTrue(urlValidator.isValid(url)); + + assertEquals("http://localhost:8084/fhir", url); + } + + @Test + public void testClientUrlWithoutTemplate() { + + Integer port = 8084; + String url = getClientUrl(port); + + String[] schemes = {"http","https"}; + UrlValidator urlValidator = new UrlValidator(schemes, UrlValidator.ALLOW_LOCAL_URLS); + + assertTrue(urlValidator.isValid(url)); + } +} diff --git a/plugin/utility/pom.xml b/plugin/utility/pom.xml index 50d10f69b..884eb8740 100644 --- a/plugin/utility/pom.xml +++ b/plugin/utility/pom.xml @@ -14,19 +14,19 @@ org.opencds.cqf.ruler cqf-ruler-external 0.5.0-SNAPSHOT - + provided org.opencds.cqf.ruler cqf-ruler-server 0.5.0-SNAPSHOT classes - + provided org.springframework.boot spring-boot-autoconfigure - + provided org.junit.jupiter @@ -43,11 +43,9 @@ spring-boot-starter-test test - - - commons-io - commons-io - 2.6 - + + commons-io + commons-io + diff --git a/plugin/utility/src/main/java/org/opencds/cqf/ruler/plugin/utility/ClientUtilities.java b/plugin/utility/src/main/java/org/opencds/cqf/ruler/plugin/utility/ClientUtilities.java index 05b06ba16..5f76425b4 100644 --- a/plugin/utility/src/main/java/org/opencds/cqf/ruler/plugin/utility/ClientUtilities.java +++ b/plugin/utility/src/main/java/org/opencds/cqf/ruler/plugin/utility/ClientUtilities.java @@ -19,7 +19,7 @@ * setting up authentication */ public interface ClientUtilities { - + /** * Creates an IGenericClient for the given url. Defaults to NEVER * ServerValidationMode diff --git a/plugin/utility/src/main/java/org/opencds/cqf/ruler/plugin/utility/OperatorUtilities.java b/plugin/utility/src/main/java/org/opencds/cqf/ruler/plugin/utility/OperatorUtilities.java new file mode 100644 index 000000000..54468d97c --- /dev/null +++ b/plugin/utility/src/main/java/org/opencds/cqf/ruler/plugin/utility/OperatorUtilities.java @@ -0,0 +1,139 @@ +package org.opencds.cqf.ruler.plugin.utility; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.TimeZone; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This interface provides utilities for implementing FHIR operators. + */ +public interface OperatorUtilities extends ResolutionUtilities { + + public static final Logger ourLog = LoggerFactory.getLogger(OperatorUtilities.class); + + /** + * This function converts a string representation of a FHIR period date to a + * java.util.Date. + * + * @param date the date to convert + * @param start whether the date is the start of a period + * @return the FHIR period date as a java.util.Date type + */ + public default Date resolveRequestDate(String date, boolean start) { + // split it up - support dashes or slashes + String[] dissect = date.contains("-") ? date.split("-") : date.split("/"); + List dateVals = new ArrayList<>(); + for (String dateElement : dissect) { + dateVals.add(Integer.parseInt(dateElement)); + } + + if (dateVals.isEmpty()) { + throw new IllegalArgumentException("Invalid date"); + } + + // for now support dates up to day precision + Calendar calendar = Calendar.getInstance(); + calendar.clear(); + calendar.setTimeZone(TimeZone.getDefault()); + calendar.set(Calendar.YEAR, dateVals.get(0)); + if (dateVals.size() > 1) { + // java.util.Date months are zero based, hence the negative 1 -- 2014-01 == + // February 2014 + calendar.set(Calendar.MONTH, dateVals.get(1) - 1); + } + if (dateVals.size() > 2) + calendar.set(Calendar.DAY_OF_MONTH, dateVals.get(2)); + else { + if (start) { + calendar.set(Calendar.DAY_OF_MONTH, 1); + } else { + // get last day of month for end period + calendar.add(Calendar.MONTH, 1); + calendar.set(Calendar.DAY_OF_MONTH, 1); + calendar.add(Calendar.DATE, -1); + } + } + return calendar.getTime(); + } + + /** + * This function returns a fullUrl for a resource. + * + * @param serverAddress the address of the server + * @param fhirType the type of the resource + * @param elementId the id of the resource + * @return the FHIR period date as a java.util.Date type + */ + public default String getFullUrl(String serverAddress, String fhirType, String elementId) { + String fullUrl = String.format("%s%s/%s", serverAddress, fhirType, elementId); + return fullUrl; + } + + // This has some issues + // public default void ensurePatient(String + // patientRef, DaoRegistry theRegistry, Class theResourceType) { + // IBaseResource patient = resolveById(theRegistry, theResourceType, + // patientRef); + // if (patient == null) { + // throw new RuntimeException("Could not find Patient: " + patientRef); + // } + // } + + // //TODO: replace this with version from base structures + // public default List + // getPatientListFromSubject(String theSubject, DaoRegistry theRegistry, + // Class thePatientType, Class theGroupType) { + // List patientList = null; + + // if (theSubject.startsWith("Patient/")) { + // ensurePatient(theSubject, theRegistry, thePatientType); + // patientList = new ArrayList(); + // Reference patientReference = new Reference().setReference(theSubject); + // patientList.add(patientReference); + // } else if (theSubject.startsWith("Group/")) { + // patientList = getPatientListFromGroup(theSubject, theRegistry, + // thePatientType, theGroupType); + // } else { + // ourLog.info(String.format("Subject member was not a Patient or a Group, so + // skipping. \n%s", theSubject)); + // } + + // return patientList; + // } + + // //TODO: replace this with version from base structures + // public default List + // getPatientListFromGroup(String subjectGroupId, DaoRegistry theRegistry, + // Class thePatientType, Class theGroupType){ + // List patientList = new ArrayList<>(); + + // IBaseResource baseGroup = resolveById(theRegistry, theGroupType, + // subjectGroupId); + // if (baseGroup == null) { + // throw new RuntimeException("Could not find Group: " + subjectGroupId); + // } + + // Group group = (Group)baseGroup; + // group.getMember().forEach(member -> { + // Reference reference = member.getEntity(); + // if (reference.getReference().getValue().startsWith("/Patient")) { + // ensurePatient(reference.getReference().getValue(), theRegistry, + // thePatientType); + // patientList.add(reference); + // } else if (reference.getReference().getValue().startsWith("/Group")) { + // patientList.addAll(getPatientListFromGroup(reference.getReference().getValue(), + // theRegistry, thePatientType, theGroupType)); + // } else { + // ourLog.info(String.format("Group member was not a Patient or a Group, so + // skipping. \n%s", reference.getReference())); + // } + // }); + + // return patientList; + // } +} diff --git a/plugin/utility/src/main/java/org/opencds/cqf/ruler/plugin/utility/ResolutionUtilities.java b/plugin/utility/src/main/java/org/opencds/cqf/ruler/plugin/utility/ResolutionUtilities.java index b813775dc..1add20388 100644 --- a/plugin/utility/src/main/java/org/opencds/cqf/ruler/plugin/utility/ResolutionUtilities.java +++ b/plugin/utility/src/main/java/org/opencds/cqf/ruler/plugin/utility/ResolutionUtilities.java @@ -1,20 +1,11 @@ package org.opencds.cqf.ruler.plugin.utility; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; import java.util.List; -import com.google.common.base.Charsets; -import org.apache.commons.io.IOUtils; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IPrimitiveType; -import org.springframework.core.io.DefaultResourceLoader; -import org.springframework.core.io.Resource; -import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.jpa.api.dao.DaoRegistry; import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; @@ -33,9 +24,9 @@ public interface ResolutionUtilities extends IdUtilities, VersionUtilities { /** * Returns the Resource with a matching Id * - * @param an IBaseResource type - * @param theDaoRegistry the DaoRegistry to use for resolution - * @param theId the Id of the Resource to resolve + * @param an IBaseResource type + * @param theDaoRegistry the DaoRegistry to use for resolution + * @param theId the Id of the Resource to resolve * @return the Resource matching the criteria */ public default ResourceType resolveById(DaoRegistry theDaoRegistry, @@ -467,45 +458,4 @@ public default ResourceType resolveByCanoni RequestDetails theRequestDetails) { return this.resolveByCanonicalUrl(theResourceDao, theUrl.getValue(), theRequestDetails); } - - /** - * Returns the Resource at the specified location. - * @param an IBaseResource type - * @param theResourceDao the DaoRegistry to use for resolution - * @param theLocation the location of the Resource to resolve - * @param theFhirContext the FhirContext to use to parse the resource - * @return the Resource at the specified location - */ - @SuppressWarnings("unchecked") - public default ResourceType resolveByLocation( - DaoRegistry theResourceDao, String theLocation, FhirContext theFhirContext) - throws IOException { - String json = stringFromResource(theLocation); - IBaseResource resource = theFhirContext.newJsonParser().parseResource(json); - IFhirResourceDao dao = theResourceDao.getResourceDao(resource.getIdElement().getResourceType()); - if (dao == null) { - return null; - } else { - dao.update(resource); - return (ResourceType) resource; - } - } - - /** - * Returns a String representation of the Resource - * at the specified location. - * @param theLocation the location of the Resource to resolve - * @return the string representation of the Resource - */ - public default String stringFromResource(String theLocation) throws IOException { - InputStream is = null; - if (theLocation.startsWith(File.separator)) { - is = new FileInputStream(theLocation); - } else { - DefaultResourceLoader resourceLoader = new DefaultResourceLoader(); - Resource resource = resourceLoader.getResource(theLocation); - is = resource.getInputStream(); - } - return IOUtils.toString(is, Charsets.UTF_8); - } } diff --git a/plugin/utility/src/test/java/org/opencds/cqf/ruler/plugin/utility/ResolutionUtilitiesIT.java b/plugin/utility/src/test/java/org/opencds/cqf/ruler/plugin/utility/ResolutionUtilitiesIT.java index c02c370f5..2cb829318 100644 --- a/plugin/utility/src/test/java/org/opencds/cqf/ruler/plugin/utility/ResolutionUtilitiesIT.java +++ b/plugin/utility/src/test/java/org/opencds/cqf/ruler/plugin/utility/ResolutionUtilitiesIT.java @@ -17,135 +17,143 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import ca.uhn.fhir.jpa.api.dao.DaoRegistry; +import ca.uhn.fhir.jpa.model.config.PartitionSettings; + @ExtendWith(SpringExtension.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = { - Application.class }, properties = { - // Override is currently required when using MDM as the construction of the MDM - // beans are ambiguous as they are constructed multiple places. This is evident - // when running in a spring boot environment - "spring.main.allow-bean-definition-overriding=true", - "spring.batch.job.enabled=false", - "spring.datasource.url=jdbc:h2:mem:dbr4-mt", - "hapi.fhir.fhir_version=r4", - "hapi.fhir.tester_enabled=false", + Application.class }, properties = { + // Override is currently required when using MDM as the construction of the MDM + // beans are ambiguous as they are constructed multiple places. This is evident + // when running in a spring boot environment + "spring.main.allow-bean-definition-overriding=true", + "spring.batch.job.enabled=false", + "spring.datasource.url=jdbc:h2:mem:dbr4-mt", + "hapi.fhir.fhir_version=r4", + "hapi.fhir.tester_enabled=false", }) @TestInstance(Lifecycle.PER_CLASS) public class ResolutionUtilitiesIT implements ResolutionUtilities { - @Autowired - private DaoRegistry ourRegistry; - - @LocalServerPort - private int port; - - @BeforeAll - void beforeAll() { - Library library1 = new Library().setName("TestLibrary").setVersion("1.0.0") - .setUrl("http://test.com/Library/TestLibrary"); - library1.setId("libraryone"); - ourRegistry.getResourceDao(Library.class).update(library1); - - Library library2 = new Library().setName("TestLibrary").setVersion("2.0.0") - .setUrl("http://test.com/Library/TestLibrary"); - library2.setId("librarytwo"); - ourRegistry.getResourceDao(Library.class).update(library2); - - Patient patient = new Patient(); - patient.setId("patientone"); - ourRegistry.getResourceDao(Patient.class).update(patient); - - Observation obs = new Observation(); - patient.setId("observationone"); - ourRegistry.getResourceDao(Observation.class).create(obs); - } - - @Test - public void testResolveByCanonicalUrl() { - // Versionless resolves latest version - Library lib = this.resolveByCanonicalUrl(ourRegistry, Library.class, "http://test.com/Library/TestLibrary"); - assertNotNull(lib); - assertEquals("2.0.0", lib.getVersion()); - - // Versioned resolves correct version - lib = this.resolveByCanonicalUrl(ourRegistry, Library.class, "http://test.com/Library/TestLibrary|1.0.0"); - assertNotNull(lib); - assertEquals("1.0.0", lib.getVersion()); - - // Non-url Resource type explodes - assertThrows(RuntimeException.class, () -> { - this.resolveByCanonicalUrl(ourRegistry, Patient.class, "http://test.com/Patient"); - }); - } - - @Test - @SuppressWarnings("unchecked") - public void testResolveByName() { - // Name only resolves latest version - Library lib = this.resolveByName(ourRegistry, Library.class, "TestLibrary"); - assertNotNull(lib); - assertEquals("2.0.0", lib.getVersion()); - - // Name only on resource dao resolves latest version - lib = (Library) this.resolveByName(ourRegistry.getResourceDao("Library"), "TestLibrary"); - assertNotNull(lib); - assertEquals("2.0.0", lib.getVersion()); - - // Non-name Resource type explodes - assertThrows(RuntimeException.class, () -> { - this.resolveByName(ourRegistry, Observation.class, "NotAName"); - }); - } - - @Test - public void testResolveByNameAndVersion() { - // Name only resolves latest version - Library lib = this.resolveByNameAndVersion(ourRegistry, Library.class, "TestLibrary", null); - assertNotNull(lib); - assertEquals("2.0.0", lib.getVersion()); - - // Version resolves correct version - lib = this.resolveByNameAndVersion(ourRegistry, Library.class, "TestLibrary", "1.0.0"); - assertNotNull(lib); - assertEquals("1.0.0", lib.getVersion()); - - // Non-name Resource type explodes - assertThrows(RuntimeException.class, () -> { - this.resolveByNameAndVersion(ourRegistry, Observation.class, "NotAName", null); - }); - } - - @Test - @SuppressWarnings("unchecked") - public void testResolveById() { - // Full Id resolves - Library lib = this.resolveById(ourRegistry, Library.class, "Library/librarytwo"); - assertNotNull(lib); - assertEquals("librarytwo", lib.getIdElement().getIdPart()); - - // Partial Id resolves - lib = this.resolveById(ourRegistry, Library.class, "libraryone"); - assertNotNull(lib); - assertEquals("libraryone", lib.getIdElement().getIdPart()); - - // FhirDao resolves - lib = (Library) this.resolveById(ourRegistry.getResourceDao("Library"), "Library/librarytwo"); - assertNotNull(lib); - assertEquals("librarytwo", lib.getIdElement().getIdPart()); - - // Doesn't exist explodes - assertThrows(RuntimeException.class, () -> { - this.resolveById(ourRegistry, Library.class, "librarythree"); - }); - - // Doesn't exist on partition explodes - assertThrows(RuntimeException.class, () -> { - this.resolveById(ourRegistry, Patient.class, "patienttwo"); - }); - - // Mismatched Id types explodes - assertThrows(RuntimeException.class, () -> { - this.resolveById(ourRegistry, Library.class, "Patient/patientone"); - }); - } + @Autowired + private DaoRegistry ourRegistry; + + @LocalServerPort + private int port; + + @Autowired + protected PartitionSettings myPartitionSettings; + + @BeforeAll + void beforeAll() { + // Spring reusues application context, so need to set this because there are multi-tenant tests + myPartitionSettings.setPartitioningEnabled(false); + + Library library1 = new Library().setName("TestLibrary").setVersion("1.0.0") + .setUrl("http://test.com/Library/TestLibrary"); + library1.setId("libraryone"); + ourRegistry.getResourceDao(Library.class).update(library1); + + Library library2 = new Library().setName("TestLibrary").setVersion("2.0.0") + .setUrl("http://test.com/Library/TestLibrary"); + library2.setId("librarytwo"); + ourRegistry.getResourceDao(Library.class).update(library2); + + Patient patient = new Patient(); + patient.setId("patientone"); + ourRegistry.getResourceDao(Patient.class).update(patient); + + Observation obs = new Observation(); + patient.setId("observationone"); + ourRegistry.getResourceDao(Observation.class).create(obs); + } + + @Test + public void testResolveByCanonicalUrl() { + // Versionless resolves latest version + Library lib = this.resolveByCanonicalUrl(ourRegistry, Library.class, "http://test.com/Library/TestLibrary"); + assertNotNull(lib); + assertEquals("2.0.0", lib.getVersion()); + + // Versioned resolves correct version + lib = this.resolveByCanonicalUrl(ourRegistry, Library.class, "http://test.com/Library/TestLibrary|1.0.0"); + assertNotNull(lib); + assertEquals("1.0.0", lib.getVersion()); + + // Non-url Resource type explodes + assertThrows(RuntimeException.class, () -> { + this.resolveByCanonicalUrl(ourRegistry, Patient.class, "http://test.com/Patient"); + }); + } + + @Test + @SuppressWarnings("unchecked") + public void testResolveByName() { + // Name only resolves latest version + Library lib = this.resolveByName(ourRegistry, Library.class, "TestLibrary"); + assertNotNull(lib); + assertEquals("2.0.0", lib.getVersion()); + + // Name only on resource dao resolves latest version + lib = (Library) this.resolveByName(ourRegistry.getResourceDao("Library"), "TestLibrary"); + assertNotNull(lib); + assertEquals("2.0.0", lib.getVersion()); + + // Non-name Resource type explodes + assertThrows(RuntimeException.class, () -> { + this.resolveByName(ourRegistry, Observation.class, "NotAName"); + }); + } + + @Test + public void testResolveByNameAndVersion() { + // Name only resolves latest version + Library lib = this.resolveByNameAndVersion(ourRegistry, Library.class, "TestLibrary", null); + assertNotNull(lib); + assertEquals("2.0.0", lib.getVersion()); + + // Version resolves correct version + lib = this.resolveByNameAndVersion(ourRegistry, Library.class, "TestLibrary", "1.0.0"); + assertNotNull(lib); + assertEquals("1.0.0", lib.getVersion()); + + // Non-name Resource type explodes + assertThrows(RuntimeException.class, () -> { + this.resolveByNameAndVersion(ourRegistry, Observation.class, "NotAName", null); + }); + } + + @Test + @SuppressWarnings("unchecked") + public void testResolveById() { + // Full Id resolves + Library lib = this.resolveById(ourRegistry, Library.class, "Library/librarytwo"); + assertNotNull(lib); + assertEquals("librarytwo", lib.getIdElement().getIdPart()); + + // Partial Id resolves + lib = this.resolveById(ourRegistry, Library.class, "libraryone"); + assertNotNull(lib); + assertEquals("libraryone", lib.getIdElement().getIdPart()); + + // FhirDao resolves + lib = (Library) this.resolveById(ourRegistry.getResourceDao("Library"), "Library/librarytwo"); + assertNotNull(lib); + assertEquals("librarytwo", lib.getIdElement().getIdPart()); + + // Doesn't exist explodes + assertThrows(RuntimeException.class, () -> { + this.resolveById(ourRegistry, Library.class, "librarythree"); + }); + + // Doesn't exist on partition explodes + assertThrows(RuntimeException.class, () -> { + this.resolveById(ourRegistry, Patient.class, "patientblahblah"); + }); + + // Mismatched Id types explodes + assertThrows(RuntimeException.class, () -> { + this.resolveById(ourRegistry, Library.class, "Patient/patientone"); + }); + } } diff --git a/pom.xml b/pom.xml index e9c264b1f..a600014f3 100644 --- a/pom.xml +++ b/pom.xml @@ -1,113 +1,115 @@ - 4.0.0 - - org.opencds.cqf.ruler - cqf-ruler - 0.5.0-SNAPSHOT - pom - - - external - server - plugin/utility - plugin/hello-world - plugin/sdc - - + - - - - cqf-ruler - CQL Ruler - https://github.com/DBCG/cqf-ruler/tree/master - - - - The Apache Software License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt - - - - - - Bryn Rhodes - - - Chris Schuler - - - Jonathan Percival - Alphora - - - - - scm:git:git://github.com/DBCG/cqf-ruler.git - scm:git:ssh://github.com:DBCG/cqf-ruler.git - https://github.com/DBCG/cqf-ruler/tree/master - - - - - UTF-8 - UTF-8 - - - 5.3.11 - 5.5.3 - image/v5.5.1 - 8.0.1 - 0.62.2 - 2.5.6 - 5.3.12 - - - 1.5.3-SNAPSHOT - 1.3.1-SNAPSHOT - 1.5.4 - 1.3.1-SNAPSHOT - 1.3.1-SNAPSHOT - - - - ossrh - https://oss.sonatype.org/content/repositories/snapshots - - - - ossrh - https://oss.sonatype.org/service/local/staging/deploy/maven2/ - - - - - oss-sonatype - https://oss.sonatype.org/content/repositories/snapshots - - true - - - - oss-sonatype-public - https://oss.sonatype.org/content/groups/public/ - - - - - - - - org.springframework.boot - spring-boot-dependencies - ${spring_boot_version} - pom - import - - - + + + cqf-ruler + CQL Ruler + https://github.com/DBCG/cqf-ruler/tree/master + + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + + + + + + Bryn Rhodes + + + Chris Schuler + + + Jonathan Percival + Alphora + + + + + scm:git:git://github.com/DBCG/cqf-ruler.git + scm:git:ssh://github.com:DBCG/cqf-ruler.git + https://github.com/DBCG/cqf-ruler/tree/master + + + + + UTF-8 + UTF-8 + + + 5.3.11 + 5.5.3 + image/v5.5.1 + 8.0.1 + 0.62.2 + 2.5.6 + 5.3.12 + + + 1.5.3-SNAPSHOT + 1.3.1-SNAPSHOT + 1.5.4 + 1.3.1-SNAPSHOT + 1.3.1-SNAPSHOT + + + + ossrh + https://oss.sonatype.org/content/repositories/snapshots + + + + ossrh + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + + oss-sonatype + https://oss.sonatype.org/content/repositories/snapshots + + true + + + + oss-sonatype-public + https://oss.sonatype.org/content/groups/public/ + + + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring_boot_version} + pom + import + + + - - ca.uhn.hapi.fhir - hapi-fhir-bom - ${hapi_version} - pom - import - - - - org.junit - junit-bom - 5.8.1 - pom - import - - - - - ca.uhn.hapi.fhir - hapi-fhir-test-utilities - ${hapi_version} - test - - - - ca.uhn.hapi.fhir - hapi-fhir-testpage-overlay - ${hapi_version} - classes - - - - ca.uhn.hapi.fhir - hapi-fhir-testpage-overlay - ${hapi_version} - war - - - - ca.uhn.hapi.fhir - hapi-fhir-jpaserver-cql - ${hapi_version} - - - org.opencds.cqf.cql - evaluator.engine - ${cql-evaluator.version} - - - org.opencds.cqf.cql - evaluator.fhir - ${cql-evaluator.version} - - - - org.opencds.cqf.cql - evaluator.activitydefinition - ${cql-evaluator.version} - - - org.opencds.cqf.cql - evaluator.expression - ${cql-evaluator.version} - - - org.opencds.cqf.cql - evaluator.plandefinition - ${cql-evaluator.version} - - - org.opencds.cqf.cql - evaluator.spring - ${cql-evaluator.version} - - - org.opencds.cqf.cql - evaluator.library - ${cql-evaluator.version} - - - org.opencds.cqf - tooling - ${cqf-tooling.version} - - - - org.opencds.cqf.cql - engine - ${cql-engine.version} - - - - org.opencds.cqf.cql - engine.fhir - ${cql-engine.version} - - - - info.cqframework - cql-to-elm - ${cqframework.version} - - - - info.cqframework - cql-formatter - ${cqframework.version} - - - - info.cqframework - qdm - ${cqframework.version} - - - - info.cqframework - quick - ${cqframework.version} - - - - info.cqframework - cql - ${cqframework.version} - - - - info.cqframework - model - ${cqframework.version} - - - - info.cqframework - elm - ${cqframework.version} - - - - org.opencds.cqf - cds - ${cds-hooks.version} - - - - com.vladsch.flexmark - flexmark - ${flexmark_version} - - - com.vladsch.flexmark - flexmark-ext-tables - ${flexmark_version} - - - com.vladsch.flexmark - flexmark-ext-gfm-strikethrough - ${flexmark_version} - - - com.vladsch.flexmark - flexmark-profile-pegdown - ${flexmark_version} - - - - com.vladsch.flexmark - flexmark-ext-autolink - ${flexmark_version} - - - com.vladsch.flexmark - flexmark-ext-gfm-tasklist - ${flexmark_version} - - - - javax - javaee-api - ${javax.version} - - - - - commons-io - commons-io - 2.11.0 - - - - org.yaml - snakeyaml - 1.28 - - - - org.webjars - bootstrap - 5.0.1 - - - - org.springframework - spring-context - ${spring_version} - - - - org.springframework.boot - spring-boot-autoconfigure - ${spring_boot_version} - - - - org.springframework.boot - spring-boot-starter - ${spring_boot_version} - - - - org.springframework.boot - spring-boot-starter-web - ${spring_boot_version} - - - - org.springframework.boot - spring-boot-devtools - ${spring_boot_version} - true - - - - org.springframework.boot - spring-boot-starter-test - ${spring_boot_version} - test - - - - - - - - org.apache.maven.plugins - maven-antrun-plugin - 3.0.0 - - + + commons-io + commons-io + 2.11.0 + + + + commons-validator + commons-validator + 1.7 + + + + org.yaml + snakeyaml + 1.28 + + + + org.webjars + bootstrap + 5.0.1 + + + + org.springframework + spring-context + ${spring_version} + + + + org.springframework.boot + spring-boot-autoconfigure + ${spring_boot_version} + + + + org.springframework.boot + spring-boot-starter + ${spring_boot_version} + + + + org.springframework.boot + spring-boot-starter-web + ${spring_boot_version} + + + + org.springframework.boot + spring-boot-devtools + ${spring_boot_version} + true + + + + org.springframework.boot + spring-boot-starter-test + ${spring_boot_version} + test + + + + + + + + org.apache.maven.plugins + maven-antrun-plugin + 3.0.0 + + - - org.apache.maven.plugins - maven-dependency-plugin - 3.2.0 - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 1.8 - 1.8 - true - true - - -Xlint:all - - -Xlint:-options - -Xlint:-processing - -Werror - - - - - org.apache.maven.plugins - maven-jar-plugin - 3.2.0 - - - - true - true - - - - - - org.apache.maven.plugins - maven-war-plugin - 3.3.2 - - - - true - true - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 3.3.1 - - 8 - - - - attach-javadocs - - jar - - - - - - org.apache.maven.plugins - maven-source-plugin - 3.2.1 - - - attach-sources - - jar - - - - - - org.apache.maven.plugins - maven-gpg-plugin - 3.0.1 - - - sign-artifacts - deploy - - sign - - - - - - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.8 - true - - ossrh - https://oss.sonatype.org/ - true - - - - org.apache.maven.plugins - maven-enforcer-plugin - 3.0.0 - - - enforce-no-snapshots - - enforce - - - - - No Snapshot Versions Allowed! - - - No Snapshot Dependencies Allowed! - - - true - - - - - - org.basepom.maven - duplicate-finder-maven-plugin - 1.5.0 - - - org.apache.maven.plugins - maven-failsafe-plugin - 3.0.0-M5 - - true - - - - - integration-test - verify - - - - - - org.apache.maven.plugins - maven-surefire-plugin - 3.0.0-M5 - - - org.apache.maven.plugins - maven-deploy-plugin - 3.0.0-M1 - - - org.codehaus.mojo - build-helper-maven-plugin - 3.2.0 - - - - - - org.apache.maven.plugins - maven-surefire-plugin - - - org.apache.maven.plugins - maven-failsafe-plugin - - - - - - java-9 - - [9,) - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - 8 - - - - - - - - ci - - - - org.apache.maven.plugins - maven-source-plugin - - - org.apache.maven.plugins - maven-javadoc-plugin - - - org.apache.maven.plugins - maven-deploy-plugin - - - - - - release - - - - org.apache.maven.plugins - maven-enforcer-plugin - - - org.apache.maven.plugins - maven-gpg-plugin - - - org.sonatype.plugins - nexus-staging-maven-plugin - - - - - + + org.apache.maven.plugins + maven-dependency-plugin + 3.2.0 + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + true + true + + -Xlint:all + + -Xlint:-options + -Xlint:-processing + -Werror + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.2.0 + + + + true + true + + + + + + org.apache.maven.plugins + maven-war-plugin + 3.3.2 + + + + true + true + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.3.1 + + 8 + + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.1 + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 3.0.1 + + + sign-artifacts + deploy + + sign + + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.8 + true + + ossrh + https://oss.sonatype.org/ + true + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0 + + + enforce-no-snapshots + + enforce + + + + + No Snapshot Versions Allowed! + + + No Snapshot Dependencies Allowed! + + + true + + + + + + org.basepom.maven + duplicate-finder-maven-plugin + 1.5.0 + + + org.apache.maven.plugins + maven-failsafe-plugin + 3.0.0-M5 + + true + + + + + integration-test + verify + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M5 + + + org.apache.maven.plugins + maven-deploy-plugin + 3.0.0-M1 + + + org.codehaus.mojo + build-helper-maven-plugin + 3.2.0 + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + org.apache.maven.plugins + maven-failsafe-plugin + + + + + + java-9 + + [9,) + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 8 + + + + + + + + ci + + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-javadoc-plugin + + + org.apache.maven.plugins + maven-deploy-plugin + + + + + + release + + + + org.apache.maven.plugins + maven-enforcer-plugin + + + org.apache.maven.plugins + maven-gpg-plugin + + + org.sonatype.plugins + nexus-staging-maven-plugin + + + + + diff --git a/server/src/main/resources/application.yaml b/server/src/main/resources/application.yaml index 0f16434df..26ee8793e 100644 --- a/server/src/main/resources/application.yaml +++ b/server/src/main/resources/application.yaml @@ -138,6 +138,14 @@ hapi: ### 1: NORMALIZED_QUANTITY_STORAGE_SUPPORTED ### 2: NORMALIZED_QUANTITY_SEARCH_SUPPORTED # normalized_quantity_search_level: 2 + +## RA Settings + ra: + enabled: true + report: + endpoint: '' + + #elasticsearch: # debug: # pretty_print_json_log: false