diff --git a/app/src/test/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/enrollment/AbstractCarePlanToEnrollmentTransformationAppTest.java b/app/src/test/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/enrollment/AbstractCarePlanToEnrollmentTransformationAppTest.java index 8e241f39..6ca77815 100644 --- a/app/src/test/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/enrollment/AbstractCarePlanToEnrollmentTransformationAppTest.java +++ b/app/src/test/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/enrollment/AbstractCarePlanToEnrollmentTransformationAppTest.java @@ -74,9 +74,6 @@ public void createEnrollment() throws Exception .andExpect( requestTo( dhis2BaseUrl + "/api/" + dhis2ApiVersion + "/organisationUnits/ldXIdLNUNEn.json?fields=lastUpdated,id,code,name,shortName,displayName,level,openingDate,closedDate,coordinates,leaf,parent%5Bid%5D" ) ) .andRespond( withSuccess( IOUtils.resourceToString( "/org/dhis2/fhir/adapter/dhis/test/single-org-unit-OU_1234.json", StandardCharsets.UTF_8 ), MediaType.APPLICATION_JSON ) ); - userDhis2Server.expect( ExpectedCount.once(), requestTo( dhis2BaseUrl + "/api/" + dhis2ApiVersion + "/enrollments.json?program=EPDyQuoRnXk&programStatus=ACTIVE&trackedEntityInstance=JeR2Ul4mZfx&ouMode=ACCESSIBLE&fields=:all&" + - "order=lastUpdated:desc&pageSize=1" ) ).andExpect( method( HttpMethod.GET ) ).andExpect( header( "Authorization", testConfiguration.getDhis2UserAuthorization() ) ) - .andRespond( withSuccess( IOUtils.resourceToString( "/org/dhis2/fhir/adapter/dhis/test/default-enrollment-empty.json", StandardCharsets.UTF_8 ), MediaType.APPLICATION_JSON ) ); userDhis2Server.expect( ExpectedCount.once(), requestTo( dhis2BaseUrl + "/api/" + dhis2ApiVersion + "/enrollments.json?strategy=CREATE" ) ).andExpect( method( HttpMethod.POST ) ) .andExpect( header( "Authorization", testConfiguration.getDhis2UserAuthorization() ) ) .andExpect( content().contentTypeCompatibleWith( MediaType.APPLICATION_JSON ) ) @@ -115,9 +112,16 @@ public void updateEnrollment() throws Exception .andExpect( requestTo( dhis2BaseUrl + "/api/" + dhis2ApiVersion + "/organisationUnits/ldXIdLNUNEn.json?fields=lastUpdated,id,code,name,shortName,displayName,level,openingDate,closedDate,coordinates,leaf,parent%5Bid%5D" ) ) .andRespond( withSuccess( IOUtils.resourceToString( "/org/dhis2/fhir/adapter/dhis/test/single-org-unit-OU_1234.json", StandardCharsets.UTF_8 ), MediaType.APPLICATION_JSON ) ); - userDhis2Server.expect( ExpectedCount.between( 1, 3 ), requestTo( dhis2BaseUrl + "/api/" + dhis2ApiVersion + "/enrollments.json?program=EPDyQuoRnXk&programStatus=ACTIVE&trackedEntityInstance=JeR2Ul4mZfx&ouMode=ACCESSIBLE&fields=:all&" + - "order=lastUpdated:desc&pageSize=1" ) ).andExpect( method( HttpMethod.GET ) ).andExpect( header( "Authorization", testConfiguration.getDhis2UserAuthorization() ) ) - .andRespond( withSuccess( IOUtils.resourceToString( "/org/dhis2/fhir/adapter/dhis/test/default-enrollment-90-get.json", StandardCharsets.UTF_8 ), MediaType.APPLICATION_JSON ) ); + userDhis2Server.expect( ExpectedCount.once(), requestTo( dhis2BaseUrl + "/api/" + dhis2ApiVersion + "/enrollments.json?strategy=CREATE" ) ).andExpect( method( HttpMethod.POST ) ) + .andExpect( header( "Authorization", testConfiguration.getDhis2UserAuthorization() ) ) + .andExpect( content().contentTypeCompatibleWith( MediaType.APPLICATION_JSON ) ) + .andExpect( content().json( IOUtils.resourceToString( "/org/dhis2/fhir/adapter/dhis/test/default-enrollment-90-create.json", StandardCharsets.UTF_8 ) ) ) + .andRespond( withSuccess( IOUtils.resourceToString( "/org/dhis2/fhir/adapter/dhis/test/default-enrollment-90-create-response.json", StandardCharsets.UTF_8 ), MediaType.APPLICATION_JSON ) + .headers( createDefaultHeaders() ) ); + + userDhis2Server.expect( ExpectedCount.between( 1, 3 ), requestTo( dhis2BaseUrl + "/api/" + dhis2ApiVersion + "/enrollments/ieR4nl4muff.json" ) ).andExpect( method( HttpMethod.GET ) ).andExpect( header( "Authorization", + testConfiguration.getDhis2UserAuthorization() ) ) + .andRespond( withSuccess( IOUtils.resourceToString( "/org/dhis2/fhir/adapter/dhis/test/single-enrollment-90-get.json", StandardCharsets.UTF_8 ), MediaType.APPLICATION_JSON ) ); userDhis2Server.expect( ExpectedCount.once(), requestTo( dhis2BaseUrl + "/api/" + dhis2ApiVersion + "/enrollments/ieR4nl4muff.json?mergeMode=MERGE" ) ).andExpect( method( HttpMethod.PUT ) ) .andExpect( header( "Authorization", testConfiguration.getDhis2UserAuthorization() ) ) .andExpect( content().contentTypeCompatibleWith( MediaType.APPLICATION_JSON ) ) @@ -125,6 +129,11 @@ public void updateEnrollment() throws Exception .andRespond( withSuccess( IOUtils.resourceToString( "/org/dhis2/fhir/adapter/dhis/test/default-enrollment-90-update-response.json", StandardCharsets.UTF_8 ), MediaType.APPLICATION_JSON ) .headers( createDefaultHeaders() ) ); + notifyResource( FhirResourceType.CARE_PLAN, null, + "90", IOUtils.resourceToString( "/org/dhis2/fhir/adapter/fhir/test/" + getResourceDir() + "/get-care-plan-90.json", StandardCharsets.UTF_8 ), true ); + + waitForEmptyResourceQueue(); + notifyResource( FhirResourceType.CARE_PLAN, null, "90", IOUtils.resourceToString( "/org/dhis2/fhir/adapter/fhir/test/" + getResourceDir() + "/get-care-plan-90-update.json", StandardCharsets.UTF_8 ), true ); diff --git a/app/src/test/resources/data.sql b/app/src/test/resources/data.sql index a8fc4c49..855c3e92 100644 --- a/app/src/test/resources/data.sql +++ b/app/src/test/resources/data.sql @@ -1312,169 +1312,6 @@ if ((input.getDisplayName() != null) && !input.getDisplayName().equals(input.get } true' WHERE id='4bb9745e43c0455fbeee98e95c83df3d' AND version=0; -UPDATE fhir_script_source SET source_text= -'function getCodeFromHierarchy(hierarchy, resourceType, resourceRef) -{ - var mappedCode = null; - if (hierarchy != null) - { - for (var i = 0; (mappedCode == null) && (i < hierarchy.size()); i++) - { - var code = identifierUtils.getResourceIdentifier(hierarchy.get(i), resourceType); - if (code != null) - { - mappedCode = codeUtils.getMappedCode(code, resourceType); - if ((mappedCode == null) && args[''useIdentifierCode'']) - { - mappedCode = organizationUtils.existsWithPrefix(code); - } - } - } - } - return mappedCode; -} -function getOrganizationUnitMappedCode(organizationReference) -{ - var mappedCode = null; - if (organizationReference != null) - { - var hierarchy = organizationUtils.findHierarchy(organizationReference); - mappedCode = getCodeFromHierarchy(hierarchy, ''Organization'', organizationReference); - } - return mappedCode; -} -function getLocationMappedCode(locationReference) -{ - var mappedCode = null; - if (locationReference != null) - { - var hierarchy = locationUtils.findHierarchy(locationReference); - if (hierarchy != null) - { - getCodeFromHierarchy(hierarchy, ''Location'', locationReference); - for (var i = 0; (mappedCode == null) && (i < hierarchy.size()); i++) - { - var organizationReference = hierarchy.get(i).getManagingOrganization(); - if (organizationReference != null) - { - mappedCode = getOrganizationUnitMappedCode(organizationReference); - } - } - } - } - return mappedCode; -} -var fhirOrgUnitRef = null; -var fhirOrgUnitType = null; -if (input.managingOrganization) -{ - fhirOrgUnitRef = input.managingOrganization; - fhirOrgUnitType = ''Organization''; -} -else if ( (typeof input.locationFirstRep !== ''undefined'') && (typeof input.locationFirstRep.location !== ''undefined'') ) -{ - fhirOrgUnitRef = input.locationFirstRep.location; - fhirOrgUnitType = ''Location''; -} -else if (input.location) -{ - fhirOrgUnitRef = input.location; - fhirOrgUnitType = ''Location''; -} -else if (input.performer && !input.getPerformerFirstRep().isEmpty() && (input.getPerformerFirstRep().getReferenceElement().getResourceType() == null || input.getPerformerFirstRep().getReferenceElement().getResourceType() == ''Organization'')) -{ - fhirOrgUnitRef = input.getPerformerFirstRep(); - fhirOrgUnitType = input.getPerformerFirstRep().getReferenceElement().getResourceType(); - if (fhirOrgUnitType == null) - { - fhirOrgUnitType = ''Organization''; - } -} -else if (input.serviceProvider) -{ - fhirOrgUnitRef = input.serviceProvider; - fhirOrgUnitType = ''Organization''; -} -else if (input.author) -{ - fhirOrgUnitRef = input.author; - fhirOrgUnitType = ''Organization''; -} -else if (input.encounter) -{ - var encounter = referenceUtils.getResource(input.encounter, ''Encounter''); - if (encounter != null) - { - fhirOrgUnitRef = getLocationReference(encounter.location); - fhirOrgUnitType = ''Location''; - } -} -var ref = null; -if (fhirOrgUnitRef != null) -{ - ref = fhirResourceUtils.getAdapterReference(fhirOrgUnitRef, fhirOrgUnitType); -} -if (ref == null) -{ - if (context.getFhirRequest().isDhisFhirId()) - { - if (fhirOrgUnitRef == null) - { - if (args[''useTei''] && (typeof trackedEntityInstance !== ''undefined'')) - { - ref = context.createReference(trackedEntityInstance.organizationUnitId, ''ID''); - } - else if ((typeof enrollment !== ''undefined'') && (enrollment.organizationUnitId != null)) - { - ref = context.createReference(enrollment.organizationUnitId, ''ID''); - } - } - else - { - if (fhirOrgUnitRef != null && fhirOrgUnitRef.identifier !== ''undefined'' && fhirOrgUnitRef.hasIdentifier()) - { - ref = context.createReference(identifierUtils.getReferenceIdentifier(fhirOrgUnitRef, fhirOrgUnitType), ''code''); - } - if (ref == null) - { - ref = context.createReference(context.extractDhisId(fhirOrgUnitRef.getReferenceElement()), ''id''); - } - } - } - else - { - var mappedCode = null; - if (fhirOrgUnitRef != null) - { - if (fhirOrgUnitType == ''Location'') - { - mappedCode = getLocationMappedCode(fhirOrgUnitRef); - } - else - { - mappedCode = getOrganizationUnitMappedCode(fhirOrgUnitRef); - } - } - if (mappedCode == null) - { - mappedCode = args[''defaultCode'']; - } - if (mappedCode != null) - { - ref = context.createReference(mappedCode, ''CODE''); - } - if ((ref == null) && args[''useTei''] && (typeof trackedEntityInstance !== ''undefined'')) - { - ref = context.createReference(trackedEntityInstance.organizationUnitId, ''ID''); - } - else if ((ref == null) && (typeof enrollment !== ''undefined'') && (enrollment.organizationUnitId != null)) - { - ref = context.createReference(enrollment.organizationUnitId, ''ID''); - } - } -} -ref' WHERE id='7b94febabcf64635929a01311b25d975' AND version=0; - INSERT INTO fhir_code_category (id, version, name, code, description) VALUES ('1197b27e395643dda75cbfc6808dc49d', 0, 'Vital Sign', 'VITAL_SIGN', 'Vital signs.'); INSERT INTO fhir_code_set(id, version, code_category_id, name, code, description) @@ -2613,251 +2450,69 @@ if (!ok && (output.managingOrganization || output.performer || output.servicePro } ok' WHERE id = '78c2b73c469c4ab4824407e817b72d4a'; -UPDATE fhir_script_source SET source_text= -'function getCodeFromHierarchy(hierarchy, resourceType, resourceRef) +INSERT INTO fhir_script (id, version, name, code, description, script_type, return_type, input_type, output_type) +VALUES ('41d3bd48578847618274f8327f15fcbe', 0, 'Subject TEI Lookup', 'SUBJECT_TEI_LOOKUP', 'Lookup of the Tracked Entity Instance FHIR Resource from subject in FHIR Resource.', 'EVALUATE', 'FHIR_RESOURCE', NULL, NULL); +INSERT INTO fhir_script_variable (script_id, variable) VALUES ('41d3bd48578847618274f8327f15fcbe', 'CONTEXT'); +INSERT INTO fhir_script_variable (script_id, variable) VALUES ('41d3bd48578847618274f8327f15fcbe', 'INPUT'); +INSERT INTO fhir_script_source (id,version,script_id,source_text,source_type) +VALUES ('67249e7b4ba7466ca770a78923fbf1c3', 0, '41d3bd48578847618274f8327f15fcbe', 'referenceUtils.getResource(input.subject, ''PATIENT'')', 'JAVASCRIPT'); +INSERT INTO fhir_script_source_version (script_source_id,fhir_version) +VALUES ('67249e7b4ba7466ca770a78923fbf1c3', 'DSTU3'); +INSERT INTO fhir_script_source_version (script_source_id,fhir_version) +VALUES ('67249e7b4ba7466ca770a78923fbf1c3', 'R4'); +INSERT INTO fhir_executable_script (id, version, script_id, name, code, description) +VALUES ('762b4137a98b4b10a0f5629d93e23461', 0, '41d3bd48578847618274f8327f15fcbe', +'Subject TEI Lookup', 'SUBJECT_TEI_LOOKUP', 'Lookup of the Tracked Entity Instance FHIR Resource from subject in FHIR Resource.'); + +INSERT INTO fhir_script (id, version, code, name, description, script_type, return_type, input_type) +VALUES ('f638ba4c8b5311e989e4e70cb21cbc8c', 0, 'CARE_PLAN_DATE_LOOKUP', 'Care Plan Date Lookup', +'Lookup of the exact date of the FHIR Care Plan.', 'EVALUATE', 'DATE_TIME', 'FHIR_CARE_PLAN'); +INSERT INTO fhir_script_variable (script_id, variable) VALUES ('f638ba4c8b5311e989e4e70cb21cbc8c', 'CONTEXT'); +INSERT INTO fhir_script_variable (script_id, variable) VALUES ('f638ba4c8b5311e989e4e70cb21cbc8c', 'INPUT'); +INSERT INTO fhir_script_source (id, version, script_id, source_text, source_type) +VALUES ('224697268b5411e9b95a93563f739422', 0, 'f638ba4c8b5311e989e4e70cb21cbc8c', +'input.getPeriod().getStart()', 'JAVASCRIPT'); +INSERT INTO fhir_script_source_version (script_source_id, fhir_version) +VALUES ('224697268b5411e9b95a93563f739422', 'R4'); +INSERT INTO fhir_executable_script (id, version, script_id, name, code, description) +VALUES ('0f79f2c88b5411e981f7ebd621029975', 0, 'f638ba4c8b5311e989e4e70cb21cbc8c', 'Care Plan TEI Lookup', 'CARE_PLAN_DATE_LOOKUP', + 'Lookup of the exact date of the FHIR Care Plan'); + +INSERT INTO fhir_script (id, version, code, name, description, script_type, return_type, input_type) +VALUES ('44d6314675004db7b8bc666c4898523b', 0, 'CARE_PLAN_PROGRAM_REF_LOOKUP', 'Care Plan Tracker Program Lookup', +'Lookup of the Tracker Program of the FHIR Care Plan.', 'EVALUATE', 'PROGRAM_REF', 'FHIR_CARE_PLAN'); +INSERT INTO fhir_script_variable (script_id, variable) VALUES ('44d6314675004db7b8bc666c4898523b', 'CONTEXT'); +INSERT INTO fhir_script_variable (script_id, variable) VALUES ('44d6314675004db7b8bc666c4898523b', 'INPUT'); +INSERT INTO fhir_script_source (id, version, script_id, source_text, source_type) +VALUES ('e13eeaef7a6d4083a233190bc8c1c975', 0, '44d6314675004db7b8bc666c4898523b', +'var programRef = null; if (!input.getInstantiatesUri().isEmpty()) programRef = context.createReference(input.getInstantiatesUri().get(0).getValue(), ''id''); programRef', 'JAVASCRIPT'); +INSERT INTO fhir_script_source_version (script_source_id, fhir_version) +VALUES ('e13eeaef7a6d4083a233190bc8c1c975', 'R4'); +INSERT INTO fhir_executable_script (id, version, script_id, name, code, description) +VALUES ('79d297065c1c47c582456069036072f8', 0, '44d6314675004db7b8bc666c4898523b', 'Care Plan Tracker Program Lookup', 'CARE_PLAN_PROGRAM_REF_LOOKUP', + 'Lookup of the Tracker Program of the FHIR Care Plan.'); + +INSERT INTO fhir_script (id, version, code, name, description, script_type, return_type, input_type, output_type) +VALUES ('e885f646626940c5a8126c2aa081e239', 0, 'DEFAULT_CARE_PLAN_F2D', 'Default FHIR Care Plan to DHIS2 Enrollment Transformation', +'Transforms FHIR Care Plan to DHIS2 Enrollment.', 'TRANSFORM_TO_DHIS', 'BOOLEAN', 'FHIR_CARE_PLAN', 'DHIS_ENROLLMENT'); +INSERT INTO fhir_script_variable (script_id, variable) VALUES ('e885f646626940c5a8126c2aa081e239', 'CONTEXT'); +INSERT INTO fhir_script_variable (script_id, variable) VALUES ('e885f646626940c5a8126c2aa081e239', 'INPUT'); +INSERT INTO fhir_script_variable (script_id, variable) VALUES ('e885f646626940c5a8126c2aa081e239', 'OUTPUT'); +INSERT INTO fhir_script_source (id, version, script_id, source_text, source_type) +VALUES ('383a5fd3489041b593f36e00c14c2d43', 0, 'e885f646626940c5a8126c2aa081e239', +'function getOutputStatus(input) { - var mappedCode = null; - if (hierarchy != null) + var outputStatus = ''CANCELLED''; + var inputStatus = input.getStatus() == null ? null : input.getStatus().toCode(); + if (inputStatus === ''draft'') { - for (var i = 0; (mappedCode == null) && (i < hierarchy.size()); i++) - { - var code = identifierUtils.getResourceIdentifier(hierarchy.get(i), resourceType); - if (code != null) - { - mappedCode = codeUtils.getMappedCode(code, resourceType); - if ((mappedCode == null) && args[''useIdentifierCode'']) - { - mappedCode = organizationUtils.existsWithPrefix(code); - } - } - } + outputStatus = ''ACTIVE''; } - return mappedCode; -} -function getOrganizationUnitMappedCode(organizationReference) -{ - var mappedCode = null; - if (organizationReference != null) + else if (inputStatus === ''active'') { - var hierarchy = organizationUtils.findHierarchy(organizationReference); - mappedCode = getCodeFromHierarchy(hierarchy, ''Organization'', organizationReference); + outputStatus = ''ACTIVE''; } - return mappedCode; -} -function getLocationMappedCode(locationReference) -{ - var mappedCode = null; - if (locationReference != null) - { - var hierarchy = locationUtils.findHierarchy(locationReference); - if (hierarchy != null) - { - getCodeFromHierarchy(hierarchy, ''Location'', locationReference); - for (var i = 0; (mappedCode == null) && (i < hierarchy.size()); i++) - { - var organizationReference = hierarchy.get(i).getManagingOrganization(); - if (organizationReference != null) - { - mappedCode = getOrganizationUnitMappedCode(organizationReference); - } - } - } - } - return mappedCode; -} -var fhirOrgUnitRef = null; -var fhirOrgUnitType = null; -if (input.managingOrganization) -{ - fhirOrgUnitRef = input.managingOrganization; - fhirOrgUnitType = ''Organization''; -} -else if ( (typeof input.locationFirstRep !== ''undefined'') && (typeof input.locationFirstRep.location !== ''undefined'') ) -{ - fhirOrgUnitRef = input.locationFirstRep.location; - fhirOrgUnitType = ''Location''; -} -else if (input.location) -{ - fhirOrgUnitRef = input.location; - fhirOrgUnitType = ''Location''; -} -else if (input.performer && typeof input.getPerformerFirstRep() !== ''undefined'' && !input.getPerformerFirstRep().isEmpty() && (input.getPerformerFirstRep().getReferenceElement().getResourceType() == null || input.getPerformerFirstRep().getReferenceElement().getResourceType() == ''Organization'')) -{ - fhirOrgUnitRef = input.getPerformerFirstRep(); - fhirOrgUnitType = input.getPerformerFirstRep().getReferenceElement().getResourceType(); - if (fhirOrgUnitType == null) - { - fhirOrgUnitType = ''Organization''; - } -} -else if (input.performer && typeof input.getPerformerFirstRep === ''undefined'' && !input.getPerformer().isEmpty() && (input.getPerformer().getReferenceElement().getResourceType() == null || input.getPerformer().getReferenceElement().getResourceType() == ''Organization'')) -{ - fhirOrgUnitRef = input.getPerformer(); - fhirOrgUnitType = input.getPerformer().getReferenceElement().getResourceType(); - if (fhirOrgUnitType == null) - { - fhirOrgUnitType = ''Organization''; - } -} -else if (input.serviceProvider) -{ - fhirOrgUnitRef = input.serviceProvider; - fhirOrgUnitType = ''Organization''; -} -else if (input.author) -{ - fhirOrgUnitRef = input.author; - fhirOrgUnitType = ''Organization''; -} -else if (input.requester && input.requester.agent) -{ - fhirOrgUnitRef = input.getRequester().getAgent(); - fhirOrgUnitType = input.getRequester().getAgent().getReferenceElement().getResourceType(); - if (fhirOrgUnitType == null) - { - fhirOrgUnitType = ''Organization''; - } - ok = true; -} -else if (input.encounter) -{ - var encounter = referenceUtils.getResource(input.encounter, ''Encounter''); - if (encounter != null) - { - fhirOrgUnitRef = getLocationReference(encounter.location); - fhirOrgUnitType = ''Location''; - } -} -var ref = null; -if (fhirOrgUnitRef != null) -{ - ref = fhirResourceUtils.getAdapterReference(fhirOrgUnitRef, fhirOrgUnitType); -} -if (ref == null) -{ - if (context.getFhirRequest().isDhisFhirId()) - { - if (fhirOrgUnitRef == null) - { - if (args[''useTei''] && (typeof trackedEntityInstance !== ''undefined'')) - { - ref = context.createReference(trackedEntityInstance.organizationUnitId, ''ID''); - } - else if ((typeof enrollment !== ''undefined'') && (enrollment.organizationUnitId != null)) - { - ref = context.createReference(enrollment.organizationUnitId, ''ID''); - } - } - else - { - if (fhirOrgUnitRef != null && fhirOrgUnitRef.identifier !== ''undefined'' && fhirOrgUnitRef.hasIdentifier()) - { - ref = context.createReference(identifierUtils.getReferenceIdentifier(fhirOrgUnitRef, fhirOrgUnitType), ''code''); - } - if (ref == null) - { - ref = context.createReference(context.extractDhisId(fhirOrgUnitRef.getReferenceElement()), ''id''); - } - } - } - else - { - var mappedCode = null; - if (fhirOrgUnitRef != null) - { - if (fhirOrgUnitType == ''Location'') - { - mappedCode = getLocationMappedCode(fhirOrgUnitRef); - } - else - { - mappedCode = getOrganizationUnitMappedCode(fhirOrgUnitRef); - } - } - if (mappedCode == null) - { - mappedCode = args[''defaultCode'']; - } - if (mappedCode != null) - { - ref = context.createReference(mappedCode, ''CODE''); - } - if ((ref == null) && args[''useTei''] && (typeof trackedEntityInstance !== ''undefined'')) - { - ref = context.createReference(trackedEntityInstance.organizationUnitId, ''ID''); - } - else if ((ref == null) && (typeof enrollment !== ''undefined'') && (enrollment.organizationUnitId != null)) - { - ref = context.createReference(enrollment.organizationUnitId, ''ID''); - } - } -} -ref' WHERE id='7b94febabcf64635929a01311b25d975' AND version=0; - -INSERT INTO fhir_script (id, version, name, code, description, script_type, return_type, input_type, output_type) -VALUES ('41d3bd48578847618274f8327f15fcbe', 0, 'Subject TEI Lookup', 'SUBJECT_TEI_LOOKUP', 'Lookup of the Tracked Entity Instance FHIR Resource from subject in FHIR Resource.', 'EVALUATE', 'FHIR_RESOURCE', NULL, NULL); -INSERT INTO fhir_script_variable (script_id, variable) VALUES ('41d3bd48578847618274f8327f15fcbe', 'CONTEXT'); -INSERT INTO fhir_script_variable (script_id, variable) VALUES ('41d3bd48578847618274f8327f15fcbe', 'INPUT'); -INSERT INTO fhir_script_source (id,version,script_id,source_text,source_type) -VALUES ('67249e7b4ba7466ca770a78923fbf1c3', 0, '41d3bd48578847618274f8327f15fcbe', 'referenceUtils.getResource(input.subject, ''PATIENT'')', 'JAVASCRIPT'); -INSERT INTO fhir_script_source_version (script_source_id,fhir_version) -VALUES ('67249e7b4ba7466ca770a78923fbf1c3', 'DSTU3'); -INSERT INTO fhir_script_source_version (script_source_id,fhir_version) -VALUES ('67249e7b4ba7466ca770a78923fbf1c3', 'R4'); -INSERT INTO fhir_executable_script (id, version, script_id, name, code, description) -VALUES ('762b4137a98b4b10a0f5629d93e23461', 0, '41d3bd48578847618274f8327f15fcbe', -'Subject TEI Lookup', 'SUBJECT_TEI_LOOKUP', 'Lookup of the Tracked Entity Instance FHIR Resource from subject in FHIR Resource.'); - -INSERT INTO fhir_script (id, version, code, name, description, script_type, return_type, input_type) -VALUES ('f638ba4c8b5311e989e4e70cb21cbc8c', 0, 'CARE_PLAN_DATE_LOOKUP', 'Care Plan Date Lookup', -'Lookup of the exact date of the FHIR Care Plan.', 'EVALUATE', 'DATE_TIME', 'FHIR_CARE_PLAN'); -INSERT INTO fhir_script_variable (script_id, variable) VALUES ('f638ba4c8b5311e989e4e70cb21cbc8c', 'CONTEXT'); -INSERT INTO fhir_script_variable (script_id, variable) VALUES ('f638ba4c8b5311e989e4e70cb21cbc8c', 'INPUT'); -INSERT INTO fhir_script_source (id, version, script_id, source_text, source_type) -VALUES ('224697268b5411e9b95a93563f739422', 0, 'f638ba4c8b5311e989e4e70cb21cbc8c', -'input.getPeriod().getStart()', 'JAVASCRIPT'); -INSERT INTO fhir_script_source_version (script_source_id, fhir_version) -VALUES ('224697268b5411e9b95a93563f739422', 'R4'); -INSERT INTO fhir_executable_script (id, version, script_id, name, code, description) -VALUES ('0f79f2c88b5411e981f7ebd621029975', 0, 'f638ba4c8b5311e989e4e70cb21cbc8c', 'Care Plan TEI Lookup', 'CARE_PLAN_DATE_LOOKUP', - 'Lookup of the exact date of the FHIR Care Plan'); - -INSERT INTO fhir_script (id, version, code, name, description, script_type, return_type, input_type) -VALUES ('44d6314675004db7b8bc666c4898523b', 0, 'CARE_PLAN_PROGRAM_REF_LOOKUP', 'Care Plan Tracker Program Lookup', -'Lookup of the Tracker Program of the FHIR Care Plan.', 'EVALUATE', 'PROGRAM_REF', 'FHIR_CARE_PLAN'); -INSERT INTO fhir_script_variable (script_id, variable) VALUES ('44d6314675004db7b8bc666c4898523b', 'CONTEXT'); -INSERT INTO fhir_script_variable (script_id, variable) VALUES ('44d6314675004db7b8bc666c4898523b', 'INPUT'); -INSERT INTO fhir_script_source (id, version, script_id, source_text, source_type) -VALUES ('e13eeaef7a6d4083a233190bc8c1c975', 0, '44d6314675004db7b8bc666c4898523b', -'var programRef = null; if (!input.getInstantiatesUri().isEmpty()) programRef = context.createReference(input.getInstantiatesUri().get(0).getValue(), ''id''); programRef', 'JAVASCRIPT'); -INSERT INTO fhir_script_source_version (script_source_id, fhir_version) -VALUES ('e13eeaef7a6d4083a233190bc8c1c975', 'R4'); -INSERT INTO fhir_executable_script (id, version, script_id, name, code, description) -VALUES ('79d297065c1c47c582456069036072f8', 0, '44d6314675004db7b8bc666c4898523b', 'Care Plan Tracker Program Lookup', 'CARE_PLAN_PROGRAM_REF_LOOKUP', - 'Lookup of the Tracker Program of the FHIR Care Plan.'); - -INSERT INTO fhir_script (id, version, code, name, description, script_type, return_type, input_type, output_type) -VALUES ('e885f646626940c5a8126c2aa081e239', 0, 'DEFAULT_CARE_PLAN_F2D', 'Default FHIR Care Plan to DHIS2 Enrollment Transformation', -'Transforms FHIR Care Plan to DHIS2 Enrollment.', 'TRANSFORM_TO_DHIS', 'BOOLEAN', 'FHIR_CARE_PLAN', 'DHIS_ENROLLMENT'); -INSERT INTO fhir_script_variable (script_id, variable) VALUES ('e885f646626940c5a8126c2aa081e239', 'CONTEXT'); -INSERT INTO fhir_script_variable (script_id, variable) VALUES ('e885f646626940c5a8126c2aa081e239', 'INPUT'); -INSERT INTO fhir_script_variable (script_id, variable) VALUES ('e885f646626940c5a8126c2aa081e239', 'OUTPUT'); -INSERT INTO fhir_script_source (id, version, script_id, source_text, source_type) -VALUES ('383a5fd3489041b593f36e00c14c2d43', 0, 'e885f646626940c5a8126c2aa081e239', -'function getOutputStatus(input) -{ - var outputStatus = ''CANCELLED''; - var inputStatus = input.getStatus() == null ? null : input.getStatus().toCode(); - if (inputStatus === ''draft'') - { - outputStatus = ''ACTIVE''; - } - else if (inputStatus === ''active'') - { - outputStatus = ''ACTIVE''; - } - else if (inputStatus === ''on-hold'') + else if (inputStatus === ''on-hold'') { outputStatus = ''ACTIVE''; } @@ -3081,3 +2736,206 @@ INSERT INTO fhir_rule(id, version, fhir_resource_type, dhis_resource_type, name, VALUES('1f97f85ae4ea46f1bcde77ea178226f4', 0, 'QUESTIONNAIRE', 'PROGRAM_STAGE_METADATA', 'Default DHIS2 Program Stage Metadata to FHIR Questionnaire', 'Default rule that transforms a DHIS2 Program Stage Metadata to a FHIR Questionnaire.', true, false, true, false, true, true, true, false, -2147483648, TRUE); INSERT INTO fhir_program_stage_metadata_rule(id) VALUES ('1f97f85ae4ea46f1bcde77ea178226f4'); + +INSERT INTO fhir_rule(id, version, fhir_resource_type, dhis_resource_type, name, description, enabled, imp_enabled, exp_enabled, contained_allowed, fhir_create_enabled, fhir_update_enabled, fhir_delete_enabled, grouping, evaluation_order, simple_fhir_id) +VALUES('e54a6c5aef9a4bcfb91129b8b857f58c', 0, 'QUESTIONNAIRE_RESPONSE', 'PROGRAM_STAGE_EVENT', 'Default FHIR Questionnaire Response to DHIS2 Program Stage', 'Default rule that transforms a FHIR Questionnaire Response to a DHIS2 Program Stage.', +true, true, true, false, true, true, true, false, -2147483648, true); +INSERT INTO fhir_program_stage_rule(id) VALUES ('e54a6c5aef9a4bcfb91129b8b857f58c'); + +UPDATE fhir_rule SET exp_enabled=TRUE WHERE id='c4e17e7d880e45b59bc5568da8c79742'; +UPDATE fhir_rule SET transform_imp_script_id=NULL WHERE id='c4e17e7d880e45b59bc5568da8c79742' AND version=0; +UPDATE fhir_enrollment_rule SET program_ref_lookup_script_id=NULL WHERE id='c4e17e7d880e45b59bc5568da8c79742'; + +UPDATE fhir_script_source SET source_text= +'function getCodeFromHierarchy(hierarchy, resourceType, resourceRef) +{ + var mappedCode = null; + if (hierarchy != null) + { + for (var i = 0; (mappedCode == null) && (i < hierarchy.size()); i++) + { + var code = identifierUtils.getResourceIdentifier(hierarchy.get(i), resourceType); + if (code != null) + { + mappedCode = codeUtils.getMappedCode(code, resourceType); + if ((mappedCode == null) && args[''useIdentifierCode'']) + { + mappedCode = organizationUtils.existsWithPrefix(code); + } + } + } + } + return mappedCode; +} +function getOrganizationUnitMappedCode(organizationReference) +{ + var mappedCode = null; + if (organizationReference != null) + { + var hierarchy = organizationUtils.findHierarchy(organizationReference); + mappedCode = getCodeFromHierarchy(hierarchy, ''Organization'', organizationReference); + } + return mappedCode; +} +function getLocationMappedCode(locationReference) +{ + var mappedCode = null; + if (locationReference != null) + { + var hierarchy = locationUtils.findHierarchy(locationReference); + if (hierarchy != null) + { + getCodeFromHierarchy(hierarchy, ''Location'', locationReference); + for (var i = 0; (mappedCode == null) && (i < hierarchy.size()); i++) + { + var organizationReference = hierarchy.get(i).getManagingOrganization(); + if (organizationReference != null) + { + mappedCode = getOrganizationUnitMappedCode(organizationReference); + } + } + } + } + return mappedCode; +} +var fhirOrgUnitRef = null; +var fhirOrgUnitType = null; +if (fhirResourceUtils.hasExtension(input, ''http://www.dhis2.org/dhis2-fhir-adapter/fhir/extensions/location'')) +{ + fhirOrgUnitRef = fhirResourceUtils.getExtensionValue(input, ''http://www.dhis2.org/dhis2-fhir-adapter/fhir/extensions/location''); + if (fhirOrgUnitRef && fhirOrgUnitRef.fhirType() == ''Reference'') + { + fhirOrgUnitType = ''Location''; + } + else + { + fhirOrgUnitRef = null; + } +} +else if (input.managingOrganization) +{ + fhirOrgUnitRef = input.managingOrganization; + fhirOrgUnitType = ''Organization''; +} +else if ( (typeof input.locationFirstRep !== ''undefined'') && (typeof input.locationFirstRep.location !== ''undefined'') ) +{ + fhirOrgUnitRef = input.locationFirstRep.location; + fhirOrgUnitType = ''Location''; +} +else if (input.location) +{ + fhirOrgUnitRef = input.location; + fhirOrgUnitType = ''Location''; +} +else if (input.performer && typeof input.getPerformerFirstRep() !== ''undefined'' && !input.getPerformerFirstRep().isEmpty() && (input.getPerformerFirstRep().getReferenceElement().getResourceType() == null || input.getPerformerFirstRep().getReferenceElement().getResourceType() == ''Organization'')) +{ + fhirOrgUnitRef = input.getPerformerFirstRep(); + fhirOrgUnitType = input.getPerformerFirstRep().getReferenceElement().getResourceType(); + if (fhirOrgUnitType == null) + { + fhirOrgUnitType = ''Organization''; + } +} +else if (input.performer && typeof input.getPerformerFirstRep === ''undefined'' && !input.getPerformer().isEmpty() && (input.getPerformer().getReferenceElement().getResourceType() == null || input.getPerformer().getReferenceElement().getResourceType() == ''Organization'')) +{ + fhirOrgUnitRef = input.getPerformer(); + fhirOrgUnitType = input.getPerformer().getReferenceElement().getResourceType(); + if (fhirOrgUnitType == null) + { + fhirOrgUnitType = ''Organization''; + } +} +else if (input.serviceProvider) +{ + fhirOrgUnitRef = input.serviceProvider; + fhirOrgUnitType = ''Organization''; +} +else if (input.author) +{ + fhirOrgUnitRef = input.author; + fhirOrgUnitType = ''Organization''; +} +else if (input.requester && input.requester.agent) +{ + fhirOrgUnitRef = input.getRequester().getAgent(); + fhirOrgUnitType = input.getRequester().getAgent().getReferenceElement().getResourceType(); + if (fhirOrgUnitType == null) + { + fhirOrgUnitType = ''Organization''; + } + ok = true; +} +else if (input.encounter) +{ + var encounter = referenceUtils.getResource(input.encounter, ''Encounter''); + if (encounter != null) + { + fhirOrgUnitRef = getLocationReference(encounter.location); + fhirOrgUnitType = ''Location''; + } +} +var ref = null; +if (fhirOrgUnitRef != null) +{ + ref = fhirResourceUtils.getAdapterReference(fhirOrgUnitRef, fhirOrgUnitType); +} +if (ref == null) +{ + if (context.getFhirRequest().isDhisFhirId()) + { + if (fhirOrgUnitRef == null) + { + if (args[''useTei''] && (typeof trackedEntityInstance !== ''undefined'')) + { + ref = context.createReference(trackedEntityInstance.organizationUnitId, ''ID''); + } + else if ((typeof enrollment !== ''undefined'') && (enrollment.organizationUnitId != null)) + { + ref = context.createReference(enrollment.organizationUnitId, ''ID''); + } + } + else + { + if (fhirOrgUnitRef != null && fhirOrgUnitRef.identifier !== ''undefined'' && fhirOrgUnitRef.hasIdentifier()) + { + ref = context.createReference(identifierUtils.getReferenceIdentifier(fhirOrgUnitRef, fhirOrgUnitType), ''code''); + } + if (ref == null) + { + ref = context.createReference(context.extractDhisId(fhirOrgUnitRef.getReferenceElement()), ''id''); + } + } + } + else + { + var mappedCode = null; + if (fhirOrgUnitRef != null) + { + if (fhirOrgUnitType == ''Location'') + { + mappedCode = getLocationMappedCode(fhirOrgUnitRef); + } + else + { + mappedCode = getOrganizationUnitMappedCode(fhirOrgUnitRef); + } + } + if (mappedCode == null) + { + mappedCode = args[''defaultCode'']; + } + if (mappedCode != null) + { + ref = context.createReference(mappedCode, ''CODE''); + } + if ((ref == null) && args[''useTei''] && (typeof trackedEntityInstance !== ''undefined'')) + { + ref = context.createReference(trackedEntityInstance.organizationUnitId, ''ID''); + } + else if ((ref == null) && (typeof enrollment !== ''undefined'') && (enrollment.organizationUnitId != null)) + { + ref = context.createReference(enrollment.organizationUnitId, ''ID''); + } + } +} +ref' WHERE id='7b94febabcf64635929a01311b25d975' AND version=0; diff --git a/app/src/test/resources/org/dhis2/fhir/adapter/dhis/test/single-enrollment-90-get.json b/app/src/test/resources/org/dhis2/fhir/adapter/dhis/test/single-enrollment-90-get.json new file mode 100644 index 00000000..8f9c2a31 --- /dev/null +++ b/app/src/test/resources/org/dhis2/fhir/adapter/dhis/test/single-enrollment-90-get.json @@ -0,0 +1,10 @@ +{ + "enrollment": "ieR4nl4muff", + "status": "ACTIVE", + "enrollmentDate": "2018-11-11T00:00:00+01:00", + "incidentDate": "2018-11-10T00:00:00+01:00", + "coordinate": null, + "orgUnit": "ldXIdLNUNEn", + "program": "EPDyQuoRnXk", + "trackedEntityInstance": "JeR2Ul4mZfx" +} diff --git a/app/src/test/resources/org/dhis2/fhir/adapter/fhir/test/r4/get-care-plan-90-update.json b/app/src/test/resources/org/dhis2/fhir/adapter/fhir/test/r4/get-care-plan-90-update.json index 41eb83de..994ea0c1 100644 --- a/app/src/test/resources/org/dhis2/fhir/adapter/fhir/test/r4/get-care-plan-90-update.json +++ b/app/src/test/resources/org/dhis2/fhir/adapter/fhir/test/r4/get-care-plan-90-update.json @@ -16,11 +16,19 @@ "period": { "start": "2018-11-11" }, - "created": "2018-11-09", - "author": { - "identifier": { - "system": "http://www.dhis2.org/dhis2-fhir-adapter/systems/DHIS2-FHIR-Identifier", - "value": "ldXIdLNUNEn" + "extension": [ + { + "url": "http://www.dhis2.org/dhis2-fhir-adapter/fhir/extensions/location", + "valueReference": { + "identifier": { + "system": "http://www.dhis2.org/dhis2-fhir-adapter/systems/DHIS2-FHIR-Identifier", + "value": "ldXIdLNUNEn" + } + } + }, + { + "url": "http://www.dhis2.org/dhis2-fhir-adapter/fhir/extensions/incident-date", + "valueDate": "2018-11-09" } - } + ] } diff --git a/app/src/test/resources/org/dhis2/fhir/adapter/fhir/test/r4/get-care-plan-90.json b/app/src/test/resources/org/dhis2/fhir/adapter/fhir/test/r4/get-care-plan-90.json index a910ebd2..b8fa39dd 100644 --- a/app/src/test/resources/org/dhis2/fhir/adapter/fhir/test/r4/get-care-plan-90.json +++ b/app/src/test/resources/org/dhis2/fhir/adapter/fhir/test/r4/get-care-plan-90.json @@ -16,11 +16,19 @@ "period": { "start": "2018-11-11" }, - "created": "2018-11-10", - "author": { - "identifier": { - "system": "http://www.dhis2.org/dhis2-fhir-adapter/systems/DHIS2-FHIR-Identifier", - "value": "ldXIdLNUNEn" + "extension": [ + { + "url": "http://www.dhis2.org/dhis2-fhir-adapter/fhir/extensions/location", + "valueReference": { + "identifier": { + "system": "http://www.dhis2.org/dhis2-fhir-adapter/systems/DHIS2-FHIR-Identifier", + "value": "ldXIdLNUNEn" + } + } + }, + { + "url": "http://www.dhis2.org/dhis2-fhir-adapter/fhir/extensions/incident-date", + "valueDate": "2018-11-10" } - } + ] } diff --git a/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/program/dstu3/Dstu3ProgramStageToFhirDataProvider.java b/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/program/dstu3/Dstu3ProgramStageToFhirDataProvider.java new file mode 100644 index 00000000..d7158a9c --- /dev/null +++ b/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/program/dstu3/Dstu3ProgramStageToFhirDataProvider.java @@ -0,0 +1,60 @@ +package org.dhis2.fhir.adapter.fhir.transform.dhis.impl.program.dstu3; + +/* + * Copyright (c) 2004-2019, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import org.dhis2.fhir.adapter.dhis.tracker.program.EventService; +import org.dhis2.fhir.adapter.dhis.tracker.program.ProgramMetadataService; +import org.dhis2.fhir.adapter.fhir.model.FhirVersion; +import org.dhis2.fhir.adapter.fhir.script.ScriptExecutor; +import org.dhis2.fhir.adapter.fhir.transform.dhis.impl.program.AbstractProgramStageToFhirDataProvider; +import org.springframework.stereotype.Component; + +import javax.annotation.Nonnull; +import java.util.Set; + +/** + * DSTU3 specific implementation of {@link AbstractProgramStageToFhirDataProvider}. + * + * @author volsch + */ +@Component +public class Dstu3ProgramStageToFhirDataProvider extends AbstractProgramStageToFhirDataProvider +{ + public Dstu3ProgramStageToFhirDataProvider( @Nonnull ScriptExecutor scriptExecutor, @Nonnull ProgramMetadataService metadataService, @Nonnull EventService eventService ) + { + super( scriptExecutor, metadataService, eventService ); + } + + @Nonnull + @Override + public Set getFhirVersions() + { + return FhirVersion.DSTU3_ONLY; + } +} diff --git a/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/util/dstu3/Dstu3AssignmentDhisToFhirTransformerUtils.java b/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/util/dstu3/Dstu3AssignmentDhisToFhirTransformerUtils.java new file mode 100644 index 00000000..6a573bce --- /dev/null +++ b/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/util/dstu3/Dstu3AssignmentDhisToFhirTransformerUtils.java @@ -0,0 +1,71 @@ +package org.dhis2.fhir.adapter.fhir.transform.dhis.impl.util.dstu3; + +/* + * Copyright (c) 2004-2019, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import ca.uhn.fhir.model.primitive.IdDt; +import org.dhis2.fhir.adapter.fhir.data.repository.FhirDhisAssignmentRepository; +import org.dhis2.fhir.adapter.fhir.metadata.model.FhirResourceType; +import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientRepository; +import org.dhis2.fhir.adapter.fhir.model.FhirVersion; +import org.dhis2.fhir.adapter.fhir.script.ScriptExecutionContext; +import org.dhis2.fhir.adapter.fhir.transform.dhis.impl.util.AbstractAssignmentDhisToFhirTransformerUtils; +import org.hl7.fhir.dstu3.model.Reference; +import org.hl7.fhir.instance.model.api.IBaseReference; +import org.springframework.stereotype.Component; + +import javax.annotation.Nonnull; +import java.util.Set; + +/** + * DSTU3 implementation of {@link AbstractAssignmentDhisToFhirTransformerUtils}. + * + * @author volsch + */ +@Component +public class Dstu3AssignmentDhisToFhirTransformerUtils extends AbstractAssignmentDhisToFhirTransformerUtils +{ + public Dstu3AssignmentDhisToFhirTransformerUtils( @Nonnull ScriptExecutionContext scriptExecutionContext, @Nonnull FhirDhisAssignmentRepository assignmentRepository, @Nonnull FhirClientRepository fhirClientRepository ) + { + super( scriptExecutionContext, assignmentRepository, fhirClientRepository ); + } + + @Nonnull + @Override + public Set getFhirVersions() + { + return FhirVersion.DSTU3_ONLY; + } + + @Nonnull + @Override + protected IBaseReference createReference( @Nonnull FhirResourceType fhirResourceType, @Nonnull String fhirId ) + { + return new Reference( new IdDt( fhirResourceType.getResourceTypeName(), fhirId ) ); + } +} diff --git a/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/util/dstu3/Dstu3ValueTypeDhisToFhirTransformerUtils.java b/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/util/dstu3/Dstu3ValueTypeDhisToFhirTransformerUtils.java index d4f07a97..95ca7f4d 100644 --- a/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/util/dstu3/Dstu3ValueTypeDhisToFhirTransformerUtils.java +++ b/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/util/dstu3/Dstu3ValueTypeDhisToFhirTransformerUtils.java @@ -40,7 +40,6 @@ import org.dhis2.fhir.adapter.model.ValueType; import org.dhis2.fhir.adapter.scriptable.Scriptable; import org.hl7.fhir.dstu3.model.BooleanType; -import org.hl7.fhir.dstu3.model.CodeableConcept; import org.hl7.fhir.dstu3.model.Coding; import org.hl7.fhir.dstu3.model.DateTimeType; import org.hl7.fhir.dstu3.model.DecimalType; @@ -88,7 +87,7 @@ protected IBaseDatatype convert( @Nullable String dhisValue, @Nonnull ValueType { final Option option = optionSet.getOptionalOptionByCode( dhisValue ).orElseGet( () -> new WritableOption( dhisValue, dhisValue ) ); - return new CodeableConcept().addCoding( new Coding().setCode( option.getCode() ).setDisplay( option.getName() ) ); + return new Coding().setCode( option.getCode() ).setDisplay( option.getName() ); } try diff --git a/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/dstu3/Dstu3ValueTypeFhirToDhisTransformerUtils.java b/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/dstu3/Dstu3ValueTypeFhirToDhisTransformerUtils.java index a73d14e1..bd313d71 100644 --- a/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/dstu3/Dstu3ValueTypeFhirToDhisTransformerUtils.java +++ b/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/dstu3/Dstu3ValueTypeFhirToDhisTransformerUtils.java @@ -34,7 +34,6 @@ import org.dhis2.fhir.adapter.fhir.transform.fhir.impl.util.AbstractValueTypeFhirToDhisTransformerUtils; import org.dhis2.fhir.adapter.model.ValueType; import org.dhis2.fhir.adapter.scriptable.Scriptable; -import org.hl7.fhir.dstu3.model.CodeableConcept; import org.hl7.fhir.dstu3.model.Coding; import org.hl7.fhir.dstu3.model.DateTimeType; import org.hl7.fhir.dstu3.model.TimeType; @@ -94,9 +93,9 @@ protected Object convert( @Nullable IBaseDatatype fhirValue, @Nonnull ValueType return ( (IPrimitiveType) fhirValue ).getValueAsString(); } - if ( fhirValue instanceof CodeableConcept ) + if ( fhirValue instanceof Coding ) { - return getCode( (CodeableConcept) fhirValue ); + return getCode( (Coding) fhirValue ); } break; @@ -114,9 +113,9 @@ protected Object convert( @Nullable IBaseDatatype fhirValue, @Nonnull ValueType return ( (IPrimitiveType) fhirValue ).getValueAsString(); } - if ( fhirValue instanceof CodeableConcept ) + if ( fhirValue instanceof Coding ) { - return getCode( (CodeableConcept) fhirValue ); + return getCode( (Coding) fhirValue ); } break; @@ -177,9 +176,8 @@ protected Object convert( @Nullable IBaseDatatype fhirValue, @Nonnull ValueType } @Nullable - protected String getCode( @Nonnull CodeableConcept codeableConcept ) + protected String getCode( @Nonnull Coding coding ) { - return codeableConcept.getCoding().stream().filter( c -> c.getSystem() == null ).map( Coding::getCode ) - .findFirst().orElseThrow( () -> new TransformerDataException( "Codeable concept does not include a code (system must not be set)." ) ); + return coding.getCode(); } } diff --git a/fhir-dstu3/src/test/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/util/dstu3/Dstu3ValueTypeDhisToFhirTransformerUtilsTest.java b/fhir-dstu3/src/test/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/util/dstu3/Dstu3ValueTypeDhisToFhirTransformerUtilsTest.java index a0034da8..b42c2993 100644 --- a/fhir-dstu3/src/test/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/util/dstu3/Dstu3ValueTypeDhisToFhirTransformerUtilsTest.java +++ b/fhir-dstu3/src/test/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/util/dstu3/Dstu3ValueTypeDhisToFhirTransformerUtilsTest.java @@ -36,7 +36,6 @@ import org.dhis2.fhir.adapter.fhir.transform.TransformerDataException; import org.hl7.fhir.dstu3.model.Base; import org.hl7.fhir.dstu3.model.BooleanType; -import org.hl7.fhir.dstu3.model.CodeableConcept; import org.hl7.fhir.dstu3.model.Coding; import org.hl7.fhir.dstu3.model.DateTimeType; import org.hl7.fhir.dstu3.model.DecimalType; @@ -165,7 +164,7 @@ public void convertOption() final WritableOptionSet optionSet = new WritableOptionSet(); optionSet.setOptions( Collections.singletonList( new WritableOption( "test1", "Test 1" ) ) ); - Assert.assertTrue( new CodeableConcept().addCoding( new Coding().setCode( "test1" ).setDisplay( "Test 1" ) ) + Assert.assertTrue( new Coding().setCode( "test1" ).setDisplay( "Test 1" ) .equalsDeep( (Base) utils.convert( "test1", "text", optionSet ) ) ); Mockito.verify( valueConverter ).convert( Mockito.any(), Mockito.any(), Mockito.eq( String.class ) ); @@ -177,7 +176,7 @@ public void convertOptionNotFound() final WritableOptionSet optionSet = new WritableOptionSet(); optionSet.setOptions( Collections.singletonList( new WritableOption( "test1", "Test 1" ) ) ); - Assert.assertTrue( new CodeableConcept().addCoding( new Coding().setCode( "test2" ).setDisplay( "test2" ) ) + Assert.assertTrue( new Coding().setCode( "test2" ).setDisplay( "test2" ) .equalsDeep( (Base) utils.convert( "test2", "text", optionSet ) ) ); Mockito.verify( valueConverter ).convert( Mockito.any(), Mockito.any(), Mockito.eq( String.class ) ); diff --git a/fhir-dstu3/src/test/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/dstu3/Dstu3ProgramStageFhirToDhisTransformerUtilsTest.java b/fhir-dstu3/src/test/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/dstu3/Dstu3ProgramStageFhirToDhisTransformerUtilsTest.java index 9a08a7e4..b2b61c2f 100644 --- a/fhir-dstu3/src/test/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/dstu3/Dstu3ProgramStageFhirToDhisTransformerUtilsTest.java +++ b/fhir-dstu3/src/test/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/dstu3/Dstu3ProgramStageFhirToDhisTransformerUtilsTest.java @@ -28,6 +28,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import org.dhis2.fhir.adapter.dhis.model.DhisResource; import org.dhis2.fhir.adapter.dhis.model.DhisResourceId; import org.dhis2.fhir.adapter.dhis.model.DhisResourceType; import org.dhis2.fhir.adapter.dhis.model.Reference; @@ -123,6 +124,13 @@ public TestScriptedEvent( Event event ) this.event = event; } + @Nonnull + @Override + public DhisResource getDhisResource() + { + throw new UnsupportedOperationException(); + } + @SuppressWarnings( "ConstantConditions" ) @Nonnull @Override diff --git a/fhir-dstu3/src/test/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/dstu3/Dstu3ValueTypeFhirToDhisTransformerUtilsTest.java b/fhir-dstu3/src/test/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/dstu3/Dstu3ValueTypeFhirToDhisTransformerUtilsTest.java index 8218868b..14c70d11 100644 --- a/fhir-dstu3/src/test/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/dstu3/Dstu3ValueTypeFhirToDhisTransformerUtilsTest.java +++ b/fhir-dstu3/src/test/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/dstu3/Dstu3ValueTypeFhirToDhisTransformerUtilsTest.java @@ -92,7 +92,7 @@ public void convertText() @Test public void convertTextCode() { - Assert.assertEquals( "test1", utils.convert( new CodeableConcept().addCoding( new Coding().setCode( "test1" ) ), "Text" ) ); + Assert.assertEquals( "test1", utils.convert( new Coding().setCode( "test1" ), "Text" ) ); } @Test( expected = TransformerDataException.class ) @@ -110,7 +110,7 @@ public void convertInteger() @Test public void convertIntegerCode() { - Assert.assertEquals( "736384", utils.convert( new CodeableConcept().addCoding( new Coding().setCode( "736384" ) ), "integer" ) ); + Assert.assertEquals( "736384", utils.convert( new Coding().setCode( "736384" ), "integer" ) ); } @Test( expected = TransformerDataException.class ) diff --git a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/enrollment/r4/R4EnrollmentToCarePlanFhirTransformer.java b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/enrollment/r4/R4EnrollmentToFhirCarePlanTransformer.java similarity index 91% rename from fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/enrollment/r4/R4EnrollmentToCarePlanFhirTransformer.java rename to fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/enrollment/r4/R4EnrollmentToFhirCarePlanTransformer.java index 5c86e92a..1719645b 100644 --- a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/enrollment/r4/R4EnrollmentToCarePlanFhirTransformer.java +++ b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/enrollment/r4/R4EnrollmentToFhirCarePlanTransformer.java @@ -28,6 +28,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import org.dhis2.fhir.adapter.dhis.model.DhisResourceType; import org.dhis2.fhir.adapter.dhis.tracker.program.Enrollment; import org.dhis2.fhir.adapter.dhis.tracker.program.EnrollmentStatus; import org.dhis2.fhir.adapter.dhis.tracker.program.ProgramMetadataService; @@ -46,7 +47,7 @@ import org.dhis2.fhir.adapter.fhir.repository.FhirResourceRepository; import org.dhis2.fhir.adapter.fhir.script.ScriptExecutor; import org.dhis2.fhir.adapter.fhir.transform.dhis.DhisToFhirTransformerContext; -import org.dhis2.fhir.adapter.fhir.transform.dhis.impl.enrollment.AbstractEnrollmentToCarePlanFhirTransformer; +import org.dhis2.fhir.adapter.fhir.transform.dhis.impl.enrollment.AbstractEnrollmentToFhirCarePlanTransformer; import org.dhis2.fhir.adapter.fhir.transform.scripted.ScriptedEnrollment; import org.dhis2.fhir.adapter.lock.LockManager; import org.hl7.fhir.instance.model.api.IBaseResource; @@ -64,14 +65,14 @@ import java.util.Set; /** - * R4 specific implementation of {@link AbstractEnrollmentToCarePlanFhirTransformer}. + * R4 specific implementation of {@link AbstractEnrollmentToFhirCarePlanTransformer}. * * @author volsch */ @Component -public class R4EnrollmentToCarePlanFhirTransformer extends AbstractEnrollmentToCarePlanFhirTransformer +public class R4EnrollmentToFhirCarePlanTransformer extends AbstractEnrollmentToFhirCarePlanTransformer { - public R4EnrollmentToCarePlanFhirTransformer( @Nonnull ScriptExecutor scriptExecutor, @Nonnull LockManager lockManager, @Nonnull SystemRepository systemRepository, @Nonnull FhirResourceRepository fhirResourceRepository, + public R4EnrollmentToFhirCarePlanTransformer( @Nonnull ScriptExecutor scriptExecutor, @Nonnull LockManager lockManager, @Nonnull SystemRepository systemRepository, @Nonnull FhirResourceRepository fhirResourceRepository, @Nonnull FhirResourceMappingRepository resourceMappingRepository, @Nonnull FhirDhisAssignmentRepository fhirDhisAssignmentRepository, @Nonnull TrackedEntityMetadataService trackedEntityMetadataService, @Nonnull TrackedEntityRuleRepository trackedEntityRuleRepository, @Nonnull ProgramMetadataService programMetadataService ) { @@ -99,8 +100,8 @@ protected boolean transformInternal( @Nonnull FhirClient fhirClient, @Nonnull Dh fhirCarePlan.setIntent( CarePlan.CarePlanIntent.PLAN ); fhirCarePlan.setStatus( convertStatus( enrollment.getStatus() ) ); - LocationExtensionUtils.setValue( fhirCarePlan, - new Reference( FhirResourceType.LOCATION.withId( enrollment.getOrgUnitId() ) ) ); + LocationExtensionUtils.setValue( fhirCarePlan, createAssignedFhirReference( context, ruleInfo, scriptVariables, + DhisResourceType.ORGANIZATION_UNIT, enrollment.getOrgUnitId(), FhirResourceType.LOCATION ) ); fhirCarePlan.setSubject( new Reference( trackedEntityResource.getIdElement() ) ); fhirCarePlan.setPeriod( null ); diff --git a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/enrollment/r4/R4EnrollmentToFhirDataProvider.java b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/enrollment/r4/R4EnrollmentToFhirDataProvider.java index 9dfb0eff..7f08663d 100644 --- a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/enrollment/r4/R4EnrollmentToFhirDataProvider.java +++ b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/enrollment/r4/R4EnrollmentToFhirDataProvider.java @@ -28,15 +28,16 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import org.dhis2.fhir.adapter.dhis.model.DhisResourceType; import org.dhis2.fhir.adapter.dhis.tracker.program.EnrollmentService; import org.dhis2.fhir.adapter.fhir.extension.LocationExtensionUtils; import org.dhis2.fhir.adapter.fhir.metadata.model.EnrollmentRule; +import org.dhis2.fhir.adapter.fhir.metadata.model.FhirResourceType; import org.dhis2.fhir.adapter.fhir.metadata.model.RuleInfo; import org.dhis2.fhir.adapter.fhir.model.FhirVersion; import org.dhis2.fhir.adapter.fhir.script.ScriptExecutor; import org.dhis2.fhir.adapter.fhir.transform.dhis.impl.enrollment.AbstractEnrollmentToFhirDataProvider; import org.dhis2.fhir.adapter.fhir.transform.dhis.search.SearchFilter; -import org.dhis2.fhir.adapter.fhir.transform.dhis.search.SearchParamType; import org.hl7.fhir.r4.model.CarePlan; import org.springframework.stereotype.Component; @@ -66,10 +67,10 @@ public Set getFhirVersions() @Override protected void initSearchFilter( @Nonnull FhirVersion fhirVersion, @Nonnull RuleInfo ruleInfo, @Nonnull SearchFilter searchFilter ) { - searchFilter.add( CarePlan.SP_INSTANTIATES_CANONICAL, SearchParamType.REFERENCE, "program" ); - searchFilter.add( CarePlan.SP_INSTANTIATES_URI, SearchParamType.REFERENCE, "program" ); - searchFilter.add( CarePlan.SP_PATIENT, SearchParamType.REFERENCE, "trackedEntityInstance" ); - searchFilter.add( CarePlan.SP_SUBJECT, SearchParamType.REFERENCE, "trackedEntityInstance" ); - searchFilter.add( LocationExtensionUtils.LOCATION_SEARCH_PARAM, SearchParamType.REFERENCE, "ou" ); + searchFilter.addReference( CarePlan.SP_INSTANTIATES_CANONICAL, FhirResourceType.PLAN_DEFINITION, DhisResourceType.PROGRAM_METADATA, "program" ); + searchFilter.addReference( CarePlan.SP_INSTANTIATES_URI, FhirResourceType.PLAN_DEFINITION, DhisResourceType.PROGRAM_METADATA, "program" ); + searchFilter.addReference( CarePlan.SP_PATIENT, FhirResourceType.PATIENT, DhisResourceType.TRACKED_ENTITY, "trackedEntityInstance" ); + searchFilter.addReference( CarePlan.SP_SUBJECT, null, DhisResourceType.TRACKED_ENTITY, "trackedEntityInstance" ); + searchFilter.addReference( LocationExtensionUtils.LOCATION_SEARCH_PARAM, DhisResourceType.ORGANIZATION_UNIT, FhirResourceType.LOCATION, "ou" ); } } diff --git a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/program/r4/R4ProgramStageToFhirDataProvider.java b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/program/r4/R4ProgramStageToFhirDataProvider.java new file mode 100644 index 00000000..b608cf6a --- /dev/null +++ b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/program/r4/R4ProgramStageToFhirDataProvider.java @@ -0,0 +1,88 @@ +package org.dhis2.fhir.adapter.fhir.transform.dhis.impl.program.r4; + +/* + * Copyright (c) 2004-2019, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import org.dhis2.fhir.adapter.dhis.model.DhisResourceType; +import org.dhis2.fhir.adapter.dhis.tracker.program.EventService; +import org.dhis2.fhir.adapter.dhis.tracker.program.ProgramMetadataService; +import org.dhis2.fhir.adapter.fhir.extension.LocationExtensionUtils; +import org.dhis2.fhir.adapter.fhir.metadata.model.FhirResourceType; +import org.dhis2.fhir.adapter.fhir.metadata.model.ProgramStageRule; +import org.dhis2.fhir.adapter.fhir.metadata.model.RuleInfo; +import org.dhis2.fhir.adapter.fhir.model.FhirVersion; +import org.dhis2.fhir.adapter.fhir.script.ScriptExecutor; +import org.dhis2.fhir.adapter.fhir.transform.dhis.impl.program.AbstractProgramStageToFhirDataProvider; +import org.dhis2.fhir.adapter.fhir.transform.dhis.search.SearchFilter; +import org.hl7.fhir.r4.model.CarePlan; +import org.hl7.fhir.r4.model.QuestionnaireResponse; +import org.springframework.stereotype.Component; + +import javax.annotation.Nonnull; +import java.util.Set; + +/** + * R4 specific implementation of {@link AbstractProgramStageToFhirDataProvider}. + * + * @author volsch + */ +@Component +public class R4ProgramStageToFhirDataProvider extends AbstractProgramStageToFhirDataProvider +{ + public R4ProgramStageToFhirDataProvider( @Nonnull ScriptExecutor scriptExecutor, @Nonnull ProgramMetadataService metadataService, @Nonnull EventService eventService ) + { + super( scriptExecutor, metadataService, eventService ); + } + + @Nonnull + @Override + public Set getFhirVersions() + { + return FhirVersion.R4_ONLY; + } + + @Override + protected void initSearchFilter( @Nonnull FhirVersion fhirVersion, @Nonnull RuleInfo ruleInfo, @Nonnull SearchFilter searchFilter ) + { + super.initSearchFilter( fhirVersion, ruleInfo, searchFilter ); + + if ( ruleInfo.getRule().getFhirResourceType() == FhirResourceType.QUESTIONNAIRE_RESPONSE ) + { + searchFilter.addReference( QuestionnaireResponse.SP_BASED_ON + "." + CarePlan.SP_INSTANTIATES_CANONICAL, + FhirResourceType.PLAN_DEFINITION, DhisResourceType.PROGRAM_METADATA, "program" ); + searchFilter.addReference( QuestionnaireResponse.SP_BASED_ON + "." + CarePlan.SP_INSTANTIATES_URI, + FhirResourceType.PLAN_DEFINITION, DhisResourceType.PROGRAM_METADATA, "program" ); + + searchFilter.addReference( QuestionnaireResponse.SP_QUESTIONNAIRE, FhirResourceType.QUESTIONNAIRE, DhisResourceType.PROGRAM_STAGE_METADATA, "programStage" ); + searchFilter.addReference( QuestionnaireResponse.SP_BASED_ON, FhirResourceType.CARE_PLAN, DhisResourceType.ENROLLMENT, "enrollment" ); + searchFilter.addReference( QuestionnaireResponse.SP_PATIENT, FhirResourceType.PATIENT, DhisResourceType.TRACKED_ENTITY, "trackedEntityInstance" ); + searchFilter.addReference( QuestionnaireResponse.SP_SUBJECT, null, DhisResourceType.TRACKED_ENTITY, "trackedEntityInstance" ); + searchFilter.addReference( LocationExtensionUtils.LOCATION_SEARCH_PARAM, FhirResourceType.LOCATION, DhisResourceType.ORGANIZATION_UNIT, "orgUnit" ); + } + } +} diff --git a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/program/r4/R4ProgramStageToFhirQuestionnaireResponseTransformer.java b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/program/r4/R4ProgramStageToFhirQuestionnaireResponseTransformer.java new file mode 100644 index 00000000..468895dc --- /dev/null +++ b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/program/r4/R4ProgramStageToFhirQuestionnaireResponseTransformer.java @@ -0,0 +1,147 @@ +package org.dhis2.fhir.adapter.fhir.transform.dhis.impl.program.r4; + +/* + * Copyright (c) 2004-2019, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import org.dhis2.fhir.adapter.dhis.model.DataValue; +import org.dhis2.fhir.adapter.dhis.model.DhisResourceType; +import org.dhis2.fhir.adapter.dhis.tracker.program.Event; +import org.dhis2.fhir.adapter.dhis.tracker.program.EventStatus; +import org.dhis2.fhir.adapter.dhis.tracker.program.ProgramMetadataService; +import org.dhis2.fhir.adapter.dhis.tracker.program.ProgramStage; +import org.dhis2.fhir.adapter.dhis.tracker.trackedentity.TrackedEntityMetadataService; +import org.dhis2.fhir.adapter.fhir.data.repository.FhirDhisAssignmentRepository; +import org.dhis2.fhir.adapter.fhir.extension.DueDateExtensionUtils; +import org.dhis2.fhir.adapter.fhir.extension.EventStatusExtensionUtils; +import org.dhis2.fhir.adapter.fhir.extension.LocationExtensionUtils; +import org.dhis2.fhir.adapter.fhir.metadata.model.FhirClient; +import org.dhis2.fhir.adapter.fhir.metadata.model.FhirResourceType; +import org.dhis2.fhir.adapter.fhir.metadata.model.ProgramStageRule; +import org.dhis2.fhir.adapter.fhir.metadata.model.RuleInfo; +import org.dhis2.fhir.adapter.fhir.metadata.model.ScriptVariable; +import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirResourceMappingRepository; +import org.dhis2.fhir.adapter.fhir.metadata.repository.SystemRepository; +import org.dhis2.fhir.adapter.fhir.metadata.repository.TrackedEntityRuleRepository; +import org.dhis2.fhir.adapter.fhir.model.FhirVersion; +import org.dhis2.fhir.adapter.fhir.repository.FhirResourceRepository; +import org.dhis2.fhir.adapter.fhir.script.ScriptExecutor; +import org.dhis2.fhir.adapter.fhir.transform.dhis.DhisToFhirTransformerContext; +import org.dhis2.fhir.adapter.fhir.transform.dhis.impl.program.AbstractProgramStageToFhirQuestionnaireResponseTransformer; +import org.dhis2.fhir.adapter.fhir.transform.dhis.impl.util.AbstractValueTypeDhisToFhirTransformerUtils; +import org.dhis2.fhir.adapter.fhir.transform.scripted.ScriptedEvent; +import org.dhis2.fhir.adapter.fhir.transform.util.TransformerUtils; +import org.dhis2.fhir.adapter.lock.LockManager; +import org.hl7.fhir.instance.model.api.IBaseReference; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.r4.model.CanonicalType; +import org.hl7.fhir.r4.model.QuestionnaireResponse; +import org.hl7.fhir.r4.model.QuestionnaireResponse.QuestionnaireResponseItemComponent; +import org.hl7.fhir.r4.model.Reference; +import org.hl7.fhir.r4.model.ResourceFactory; +import org.hl7.fhir.r4.model.Type; +import org.springframework.stereotype.Component; + +import javax.annotation.Nonnull; +import java.util.Date; +import java.util.Map; +import java.util.Set; + +import static org.dhis2.fhir.adapter.dhis.model.Reference.createIdReference; + +/** + * R4 specific implementation of {@link AbstractProgramStageToFhirQuestionnaireResponseTransformer}. + * + * @author volsch + */ +@Component +public class R4ProgramStageToFhirQuestionnaireResponseTransformer extends AbstractProgramStageToFhirQuestionnaireResponseTransformer +{ + public R4ProgramStageToFhirQuestionnaireResponseTransformer( @Nonnull ScriptExecutor scriptExecutor, @Nonnull LockManager lockManager, @Nonnull SystemRepository systemRepository, @Nonnull FhirResourceRepository fhirResourceRepository, + @Nonnull FhirResourceMappingRepository resourceMappingRepository, @Nonnull FhirDhisAssignmentRepository fhirDhisAssignmentRepository, @Nonnull TrackedEntityMetadataService trackedEntityMetadataService, + @Nonnull TrackedEntityRuleRepository trackedEntityRuleRepository, @Nonnull ProgramMetadataService programMetadataService ) + { + super( scriptExecutor, lockManager, systemRepository, fhirResourceRepository, resourceMappingRepository, fhirDhisAssignmentRepository, trackedEntityMetadataService, trackedEntityRuleRepository, programMetadataService ); + } + + @Nonnull + @Override + public Set getFhirVersions() + { + return FhirVersion.R4_ONLY; + } + + @Override + protected boolean transformInternal( @Nonnull FhirClient fhirClient, @Nonnull DhisToFhirTransformerContext context, @Nonnull RuleInfo ruleInfo, @Nonnull Map scriptVariables, + @Nonnull ScriptedEvent input, @Nonnull IBaseResource output, @Nonnull IBaseResource trackedEntityResource ) + { + final Event event = (Event) input.getDhisResource(); + final ProgramStage programStage = input.getProgramStage(); + final QuestionnaireResponse fhirQuestionnaireResponse = (QuestionnaireResponse) output; + + final IBaseReference questionnaireReference = createAssignedFhirReference( context, ruleInfo, scriptVariables, + DhisResourceType.PROGRAM_STAGE_METADATA, event.getProgramStageId(), FhirResourceType.QUESTIONNAIRE ); + fhirQuestionnaireResponse.setQuestionnaireElement( questionnaireReference == null ? null : + new CanonicalType( questionnaireReference.getReferenceElement().getValue() ) ); + fhirQuestionnaireResponse.setItem( null ); + + fhirQuestionnaireResponse.setBasedOn( createAssignedFhirReferences( context, ruleInfo, scriptVariables, + DhisResourceType.ENROLLMENT, event.getEnrollmentId(), FhirResourceType.CARE_PLAN ) ); + EventStatusExtensionUtils.setValue( fhirQuestionnaireResponse, event.getStatus(), ResourceFactory::createType ); + fhirQuestionnaireResponse.setAuthored( Date.from( event.getEventDate().toInstant() ) ); + DueDateExtensionUtils.setValue( fhirQuestionnaireResponse, event.getDueDate() == null ? null : + Date.from( event.getDueDate().toInstant() ), ResourceFactory::createType ); + + LocationExtensionUtils.setValue( fhirQuestionnaireResponse, createAssignedFhirReference( context, ruleInfo, scriptVariables, + DhisResourceType.ORGANIZATION_UNIT, event.getOrgUnitId(), FhirResourceType.LOCATION ) ); + fhirQuestionnaireResponse.setSubject( new Reference( trackedEntityResource.getIdElement() ) ); + + if ( event.getStatus() == EventStatus.COMPLETED ) + { + fhirQuestionnaireResponse.setStatus( QuestionnaireResponse.QuestionnaireResponseStatus.COMPLETED ); + } + else + { + fhirQuestionnaireResponse.setStatus( QuestionnaireResponse.QuestionnaireResponseStatus.INPROGRESS ); + } + + final AbstractValueTypeDhisToFhirTransformerUtils valueTypeUtils = + TransformerUtils.getScriptVariable( scriptVariables, ScriptVariable.VALUE_TYPE_UTILS, AbstractValueTypeDhisToFhirTransformerUtils.class ); + + for ( final DataValue dataValue : event.getDataValues() ) + { + programStage.getOptionalDataElement( createIdReference( dataValue.getDataElementId() ) ).filter( dataElement -> valueTypeUtils.isSupportedValueType( dataElement.getElement().getValueType() ) ).ifPresent( dataElement -> { + final QuestionnaireResponseItemComponent item = fhirQuestionnaireResponse.addItem(); + item.setLinkId( dataValue.getDataElementId() ); + item.addAnswer().setValue( (Type) valueTypeUtils.convert( + dataValue.getValue(), dataElement.getElement().getValueType(), dataElement.getElement().getOptionSet() ) ); + } ); + } + + return true; + } +} diff --git a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/util/r4/R4ValueTypeFhirToDhisTransformerUtils.java b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/util/r4/R4ValueTypeFhirToDhisTransformerUtils.java index a2ccf377..e1b829d7 100644 --- a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/util/r4/R4ValueTypeFhirToDhisTransformerUtils.java +++ b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/util/r4/R4ValueTypeFhirToDhisTransformerUtils.java @@ -36,7 +36,6 @@ import org.dhis2.fhir.adapter.scriptable.Scriptable; import org.hl7.fhir.instance.model.api.IBaseDatatype; import org.hl7.fhir.instance.model.api.IPrimitiveType; -import org.hl7.fhir.r4.model.CodeableConcept; import org.hl7.fhir.r4.model.Coding; import org.hl7.fhir.r4.model.DateTimeType; import org.hl7.fhir.r4.model.TimeType; @@ -94,9 +93,9 @@ protected Object convert( @Nullable IBaseDatatype fhirValue, @Nonnull ValueType return ( (IPrimitiveType) fhirValue ).getValueAsString(); } - if ( fhirValue instanceof CodeableConcept ) + if ( fhirValue instanceof Coding ) { - return getCode( (CodeableConcept) fhirValue ); + return getCode( (Coding) fhirValue ); } break; @@ -109,9 +108,9 @@ protected Object convert( @Nullable IBaseDatatype fhirValue, @Nonnull ValueType return ( (IPrimitiveType) fhirValue ).getValueAsString(); } - if ( fhirValue instanceof CodeableConcept ) + if ( fhirValue instanceof Coding ) { - return getCode( (CodeableConcept) fhirValue ); + return getCode( (Coding) fhirValue ); } break; @@ -172,9 +171,8 @@ protected Object convert( @Nullable IBaseDatatype fhirValue, @Nonnull ValueType } @Nullable - protected String getCode( @Nonnull CodeableConcept codeableConcept ) + protected String getCode( @Nonnull Coding coding ) { - return codeableConcept.getCoding().stream().filter( c -> c.getSystem() == null ).map( Coding::getCode ) - .findFirst().orElseThrow( () -> new TransformerDataException( "Codeable concept does not include a code (system must not be set)." ) ); + return coding.getCode(); } } diff --git a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/enrollment/r4/R4FhirCarePlanToEnrollmentTransformer.java b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/enrollment/r4/R4FhirCarePlanToEnrollmentTransformer.java new file mode 100644 index 00000000..c366397a --- /dev/null +++ b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/enrollment/r4/R4FhirCarePlanToEnrollmentTransformer.java @@ -0,0 +1,181 @@ +package org.dhis2.fhir.adapter.fhir.transform.fhir.impl.enrollment.r4; + +/* + * Copyright (c) 2004-2019, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import org.dhis2.fhir.adapter.dhis.converter.ValueConverter; +import org.dhis2.fhir.adapter.dhis.model.Reference; +import org.dhis2.fhir.adapter.dhis.orgunit.OrganizationUnit; +import org.dhis2.fhir.adapter.dhis.orgunit.OrganizationUnitService; +import org.dhis2.fhir.adapter.dhis.tracker.program.Enrollment; +import org.dhis2.fhir.adapter.dhis.tracker.program.EnrollmentService; +import org.dhis2.fhir.adapter.dhis.tracker.program.EnrollmentStatus; +import org.dhis2.fhir.adapter.dhis.tracker.program.Program; +import org.dhis2.fhir.adapter.dhis.tracker.program.ProgramMetadataService; +import org.dhis2.fhir.adapter.dhis.tracker.trackedentity.TrackedEntityMetadataService; +import org.dhis2.fhir.adapter.dhis.tracker.trackedentity.TrackedEntityService; +import org.dhis2.fhir.adapter.fhir.data.repository.FhirDhisAssignmentRepository; +import org.dhis2.fhir.adapter.fhir.extension.IncidentDateExtensionUtils; +import org.dhis2.fhir.adapter.fhir.metadata.model.EnrollmentRule; +import org.dhis2.fhir.adapter.fhir.metadata.model.FhirResourceMapping; +import org.dhis2.fhir.adapter.fhir.metadata.model.FhirResourceType; +import org.dhis2.fhir.adapter.fhir.metadata.model.RuleInfo; +import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirResourceMappingRepository; +import org.dhis2.fhir.adapter.fhir.metadata.repository.TrackedEntityRuleRepository; +import org.dhis2.fhir.adapter.fhir.model.FhirVersion; +import org.dhis2.fhir.adapter.fhir.script.ScriptExecutionContext; +import org.dhis2.fhir.adapter.fhir.script.ScriptExecutor; +import org.dhis2.fhir.adapter.fhir.transform.TransformerDataException; +import org.dhis2.fhir.adapter.fhir.transform.TransformerException; +import org.dhis2.fhir.adapter.fhir.transform.TransformerMappingException; +import org.dhis2.fhir.adapter.fhir.transform.fhir.FhirToDhisTransformerContext; +import org.dhis2.fhir.adapter.fhir.transform.fhir.impl.program.AbstractFhirCarePlanToEnrollmentTransformer; +import org.dhis2.fhir.adapter.fhir.transform.scripted.ScriptedTrackedEntityInstance; +import org.dhis2.fhir.adapter.fhir.transform.scripted.WritableScriptedEnrollment; +import org.dhis2.fhir.adapter.fhir.util.FhirUriUtils; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IIdType; +import org.hl7.fhir.r4.model.CarePlan; +import org.springframework.stereotype.Component; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.Date; +import java.util.Map; +import java.util.Set; + +/** + * R4 specific implementation of {@link AbstractFhirCarePlanToEnrollmentTransformer}. + * + * @author volsch + */ +@Component +public class R4FhirCarePlanToEnrollmentTransformer extends AbstractFhirCarePlanToEnrollmentTransformer +{ + private final ZoneId zoneId = ZoneId.systemDefault(); + + public R4FhirCarePlanToEnrollmentTransformer( @Nonnull ScriptExecutor scriptExecutor, @Nonnull TrackedEntityMetadataService trackedEntityMetadataService, @Nonnull TrackedEntityService trackedEntityService, + @Nonnull TrackedEntityRuleRepository trackedEntityRuleRepository, @Nonnull OrganizationUnitService organizationUnitService, @Nonnull ProgramMetadataService programMetadataService, @Nonnull EnrollmentService enrollmentService, + @Nonnull FhirResourceMappingRepository resourceMappingRepository, @Nonnull FhirDhisAssignmentRepository fhirDhisAssignmentRepository, @Nonnull ScriptExecutionContext scriptExecutionContext, @Nonnull ValueConverter valueConverter ) + { + super( scriptExecutor, trackedEntityMetadataService, trackedEntityService, trackedEntityRuleRepository, organizationUnitService, programMetadataService, enrollmentService, resourceMappingRepository, fhirDhisAssignmentRepository, + scriptExecutionContext, valueConverter ); + } + + @Nonnull + @Override + public Set getFhirVersions() + { + return FhirVersion.R4_ONLY; + } + + @Override + protected void transformInternal( @Nonnull FhirToDhisTransformerContext context, @Nonnull RuleInfo ruleInfo, @Nonnull Map scriptVariables, @Nonnull FhirResourceMapping fhirResourceMapping, + @Nonnull Program program, @Nonnull IBaseResource carePlan, @Nonnull ScriptedTrackedEntityInstance scriptedTrackedEntityInstance, @Nonnull WritableScriptedEnrollment scriptedEnrollment ) throws TransformerException + { + final CarePlan fhirCarePlan = (CarePlan) carePlan; + final Enrollment enrollment = (Enrollment) scriptedEnrollment.getDhisResource(); + + enrollment.setProgramId( program.getId() ); + enrollment.setStatus( convertStatus( fhirCarePlan.getStatus() ) ); + enrollment.setOrgUnitId( getOrgUnit( context, ruleInfo, fhirResourceMapping.getImpEnrollmentOrgLookupScript(), scriptVariables ) + .map( OrganizationUnit::getId ).orElseThrow( () -> new TransformerMappingException( "Care plan contains location that cannot be mapped." ) ) ); + enrollment.setTrackedEntityInstanceId( scriptedTrackedEntityInstance.getId() ); + + if ( fhirCarePlan.getPeriod().hasStart() ) + { + enrollment.setEnrollmentDate( ZonedDateTime.ofInstant( + fhirCarePlan.getPeriod().getStart().toInstant(), zoneId ) ); + } + else + { + enrollment.setEnrollmentDate( null ); + } + + final Date incidentDate = IncidentDateExtensionUtils.getValue( fhirCarePlan ); + enrollment.setIncidentDate( incidentDate == null ? null : ZonedDateTime.ofInstant( incidentDate.toInstant(), zoneId ) ); + + enrollment.setModified(); + } + + @Nonnull + protected EnrollmentStatus convertStatus( @Nullable CarePlan.CarePlanStatus carePlanStatus ) + { + if ( carePlanStatus == null ) + { + throw new TransformerDataException( "Care plan status is mandatory." ); + } + + switch ( carePlanStatus ) + { + case ACTIVE: + return EnrollmentStatus.ACTIVE; + case COMPLETED: + return EnrollmentStatus.COMPLETED; + case REVOKED: + return EnrollmentStatus.CANCELLED; + default: + throw new TransformerDataException( "Care plan status is not allowed: " + carePlanStatus ); + } + } + + @Nonnull + @Override + protected Reference getProgramRef( @Nonnull FhirToDhisTransformerContext context, @Nonnull RuleInfo ruleInfo, @Nonnull Map scriptVariables, @Nonnull IBaseResource carePlan ) + { + final CarePlan fhirCarePlan = (CarePlan) carePlan; + final String uri; + + if ( !fhirCarePlan.getInstantiatesUri().isEmpty() ) + { + uri = fhirCarePlan.getInstantiatesUri().get( 0 ).getValueAsString(); + } + else if ( !fhirCarePlan.getInstantiatesCanonical().isEmpty() ) + { + uri = fhirCarePlan.getInstantiatesCanonical().get( 0 ).getValueAsString(); + } + else + { + throw new TransformerDataException( "No reference to a plan definition that is instantiated by this care plan has been given." ); + } + + final IIdType id; + try + { + id = FhirUriUtils.createIdFromUri( uri, FhirResourceType.CARE_PLAN ); + } + catch ( IllegalArgumentException e ) + { + throw new TransformerDataException( e.getMessage(), e ); + } + + return Reference.createIdReference( id.getIdPart() ); + } +} diff --git a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/r4/R4AssignmentDhisToFhirTransformerUtils.java b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/r4/R4AssignmentDhisToFhirTransformerUtils.java new file mode 100644 index 00000000..75dc4e35 --- /dev/null +++ b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/r4/R4AssignmentDhisToFhirTransformerUtils.java @@ -0,0 +1,71 @@ +package org.dhis2.fhir.adapter.fhir.transform.fhir.impl.util.r4; + +/* + * Copyright (c) 2004-2019, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import ca.uhn.fhir.model.primitive.IdDt; +import org.dhis2.fhir.adapter.fhir.data.repository.FhirDhisAssignmentRepository; +import org.dhis2.fhir.adapter.fhir.metadata.model.FhirResourceType; +import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientRepository; +import org.dhis2.fhir.adapter.fhir.model.FhirVersion; +import org.dhis2.fhir.adapter.fhir.script.ScriptExecutionContext; +import org.dhis2.fhir.adapter.fhir.transform.dhis.impl.util.AbstractAssignmentDhisToFhirTransformerUtils; +import org.hl7.fhir.instance.model.api.IBaseReference; +import org.hl7.fhir.r4.model.Reference; +import org.springframework.stereotype.Component; + +import javax.annotation.Nonnull; +import java.util.Set; + +/** + * DSTU3 implementation of {@link AbstractAssignmentDhisToFhirTransformerUtils}. + * + * @author volsch + */ +@Component +public class R4AssignmentDhisToFhirTransformerUtils extends AbstractAssignmentDhisToFhirTransformerUtils +{ + public R4AssignmentDhisToFhirTransformerUtils( @Nonnull ScriptExecutionContext scriptExecutionContext, @Nonnull FhirDhisAssignmentRepository assignmentRepository, @Nonnull FhirClientRepository fhirClientRepository ) + { + super( scriptExecutionContext, assignmentRepository, fhirClientRepository ); + } + + @Nonnull + @Override + public Set getFhirVersions() + { + return FhirVersion.R4_ONLY; + } + + @Nonnull + @Override + protected IBaseReference createReference( @Nonnull FhirResourceType fhirResourceType, @Nonnull String fhirId ) + { + return new Reference( new IdDt( fhirResourceType.getResourceTypeName(), fhirId ) ); + } +} diff --git a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/r4/R4ValueTypeDhisToFhirTransformerUtils.java b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/r4/R4ValueTypeDhisToFhirTransformerUtils.java index 586fc8e7..9c9f112b 100644 --- a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/r4/R4ValueTypeDhisToFhirTransformerUtils.java +++ b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/r4/R4ValueTypeDhisToFhirTransformerUtils.java @@ -41,7 +41,6 @@ import org.dhis2.fhir.adapter.scriptable.Scriptable; import org.hl7.fhir.instance.model.api.IBaseDatatype; import org.hl7.fhir.r4.model.BooleanType; -import org.hl7.fhir.r4.model.CodeableConcept; import org.hl7.fhir.r4.model.Coding; import org.hl7.fhir.r4.model.DateTimeType; import org.hl7.fhir.r4.model.DecimalType; @@ -88,7 +87,7 @@ protected IBaseDatatype convert( @Nullable String dhisValue, @Nonnull ValueType { final Option option = optionSet.getOptionalOptionByCode( dhisValue ).orElseGet( () -> new WritableOption( dhisValue, dhisValue ) ); - return new CodeableConcept().addCoding( new Coding().setCode( option.getCode() ).setDisplay( option.getName() ) ); + return new Coding().setCode( option.getCode() ).setDisplay( option.getName() ); } try diff --git a/fhir-r4/src/test/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/util/r4/R4ValueTypeDhisToFhirTransformerUtilsTest.java b/fhir-r4/src/test/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/util/r4/R4ValueTypeDhisToFhirTransformerUtilsTest.java index ab4bee0a..1aec2e02 100644 --- a/fhir-r4/src/test/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/util/r4/R4ValueTypeDhisToFhirTransformerUtilsTest.java +++ b/fhir-r4/src/test/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/util/r4/R4ValueTypeDhisToFhirTransformerUtilsTest.java @@ -37,7 +37,6 @@ import org.dhis2.fhir.adapter.fhir.transform.fhir.impl.util.r4.R4ValueTypeDhisToFhirTransformerUtils; import org.hl7.fhir.r4.model.Base; import org.hl7.fhir.r4.model.BooleanType; -import org.hl7.fhir.r4.model.CodeableConcept; import org.hl7.fhir.r4.model.Coding; import org.hl7.fhir.r4.model.DateTimeType; import org.hl7.fhir.r4.model.DecimalType; @@ -166,7 +165,7 @@ public void convertOption() final WritableOptionSet optionSet = new WritableOptionSet(); optionSet.setOptions( Collections.singletonList( new WritableOption( "test1", "Test 1" ) ) ); - Assert.assertTrue( new CodeableConcept().addCoding( new Coding().setCode( "test1" ).setDisplay( "Test 1" ) ) + Assert.assertTrue( new Coding().setCode( "test1" ).setDisplay( "Test 1" ) .equalsDeep( (Base) utils.convert( "test1", "text", optionSet ) ) ); Mockito.verify( valueConverter ).convert( Mockito.any(), Mockito.any(), Mockito.eq( String.class ) ); @@ -178,7 +177,7 @@ public void convertOptionNotFound() final WritableOptionSet optionSet = new WritableOptionSet(); optionSet.setOptions( Collections.singletonList( new WritableOption( "test1", "Test 1" ) ) ); - Assert.assertTrue( new CodeableConcept().addCoding( new Coding().setCode( "test2" ).setDisplay( "test2" ) ) + Assert.assertTrue( new Coding().setCode( "test2" ).setDisplay( "test2" ) .equalsDeep( (Base) utils.convert( "test2", "text", optionSet ) ) ); Mockito.verify( valueConverter ).convert( Mockito.any(), Mockito.any(), Mockito.eq( String.class ) ); diff --git a/fhir-r4/src/test/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/r4/R4ProgramStageFhirToDhisTransformerUtilsTest.java b/fhir-r4/src/test/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/r4/R4ProgramStageFhirToDhisTransformerUtilsTest.java index f3f989a1..fcbb08cb 100644 --- a/fhir-r4/src/test/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/r4/R4ProgramStageFhirToDhisTransformerUtilsTest.java +++ b/fhir-r4/src/test/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/r4/R4ProgramStageFhirToDhisTransformerUtilsTest.java @@ -28,6 +28,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import org.dhis2.fhir.adapter.dhis.model.DhisResource; import org.dhis2.fhir.adapter.dhis.model.DhisResourceId; import org.dhis2.fhir.adapter.dhis.model.DhisResourceType; import org.dhis2.fhir.adapter.dhis.model.Reference; @@ -123,6 +124,13 @@ public TestScriptedEvent( Event event ) this.event = event; } + @Nonnull + @Override + public DhisResource getDhisResource() + { + throw new UnsupportedOperationException(); + } + @SuppressWarnings( "ConstantConditions" ) @Nonnull @Override diff --git a/fhir-r4/src/test/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/r4/R4ValueTypeFhirToDhisTransformerUtilsTest.java b/fhir-r4/src/test/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/r4/R4ValueTypeFhirToDhisTransformerUtilsTest.java index a3048784..8ac176f9 100644 --- a/fhir-r4/src/test/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/r4/R4ValueTypeFhirToDhisTransformerUtilsTest.java +++ b/fhir-r4/src/test/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/r4/R4ValueTypeFhirToDhisTransformerUtilsTest.java @@ -93,7 +93,7 @@ public void convertText() @Test public void convertTextCode() { - Assert.assertEquals( "test1", utils.convert( new CodeableConcept().addCoding( new Coding().setCode( "test1" ) ), "Text" ) ); + Assert.assertEquals( "test1", utils.convert( new Coding().setCode( "test1" ), "Text" ) ); } @Test( expected = TransformerDataException.class ) @@ -111,7 +111,7 @@ public void convertInteger() @Test public void convertIntegerCode() { - Assert.assertEquals( "736384", utils.convert( new CodeableConcept().addCoding( new Coding().setCode( "736384" ) ), "integer" ) ); + Assert.assertEquals( "736384", utils.convert( new Coding().setCode( "736384" ), "integer" ) ); } @Test( expected = TransformerDataException.class ) diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/data/repository/CustomFhirDhisAssignmentRepository.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/data/repository/CustomFhirDhisAssignmentRepository.java index 8d60bd6b..7ced4964 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/data/repository/CustomFhirDhisAssignmentRepository.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/data/repository/CustomFhirDhisAssignmentRepository.java @@ -45,14 +45,14 @@ public interface CustomFhirDhisAssignmentRepository { @Nullable - String findFirstDhisResourceId( @Nonnull AbstractRule rule, @Nonnull FhirClient subscription, @Nonnull IIdType fhirResourceId ); + String findFirstDhisResourceId( @Nonnull AbstractRule rule, @Nonnull FhirClient fhirClient, @Nonnull IIdType fhirResourceId ); @Nullable - String findFirstFhirResourceId( @Nonnull AbstractRule rule, @Nonnull FhirClient subscription, @Nonnull DhisResourceId dhisResourceId ); + String findFirstFhirResourceId( @Nonnull AbstractRule rule, @Nonnull FhirClient fhirClient, @Nonnull DhisResourceId dhisResourceId ); - boolean saveDhisResourceId( @Nonnull AbstractRule rule, @Nonnull FhirClient subscription, @Nonnull IIdType fhirResourceId, @Nonnull DhisResourceId dhisResourceId ); + boolean saveDhisResourceId( @Nonnull AbstractRule rule, @Nonnull FhirClient fhirClient, @Nonnull IIdType fhirResourceId, @Nonnull DhisResourceId dhisResourceId ); - boolean saveFhirResourceId( @Nonnull AbstractRule rule, @Nonnull FhirClient subscription, @Nonnull DhisResourceId dhisResourceId, @Nonnull IIdType fhirResourceId ); + boolean saveFhirResourceId( @Nonnull AbstractRule rule, @Nonnull FhirClient fhirClient, @Nonnull DhisResourceId dhisResourceId, @Nonnull IIdType fhirResourceId ); - boolean deleteFhirResourceId( @Nonnull AbstractRule rule, @Nonnull FhirClient subscription, @Nonnull IIdType fhirResourceId ); + boolean deleteFhirResourceId( @Nonnull AbstractRule rule, @Nonnull FhirClient fhirClient, @Nonnull IIdType fhirResourceId ); } diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/extension/BaseExtensionUtils.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/extension/BaseExtensionUtils.java index c39be78a..025e9f70 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/extension/BaseExtensionUtils.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/extension/BaseExtensionUtils.java @@ -29,6 +29,7 @@ */ import ca.uhn.fhir.model.api.IElement; +import org.hl7.fhir.instance.model.api.IBaseDatatype; import org.hl7.fhir.instance.model.api.IBaseExtension; import org.hl7.fhir.instance.model.api.IBaseHasExtensions; import org.hl7.fhir.instance.model.api.IBaseReference; @@ -60,6 +61,24 @@ protected static void setStringValue( @Nonnull String url, @Nonnull IBaseHasExte } } + @Nullable + protected static Date getDateValue( @Nonnull String url, @Nonnull IBaseHasExtensions resource ) + { + final IBaseDatatype value = getValue( url, resource ); + + if ( value instanceof IPrimitiveType ) + { + final Object primitiveValue = ( (IPrimitiveType) value ).getValue(); + + if ( primitiveValue instanceof Date ) + { + return (Date) primitiveValue; + } + } + + return null; + } + @SuppressWarnings( "unchecked" ) protected static void setDateValue( @Nonnull String url, @Nonnull IBaseHasExtensions resource, @Nullable Date value, @Nonnull Function typeFactory ) { @@ -87,6 +106,13 @@ protected static void setReferenceValue( @Nonnull String url, @Nonnull IBaseHasE } } + @Nullable + protected static IBaseDatatype getValue( @Nonnull String url, @Nonnull IBaseHasExtensions resource ) + { + return resource.getExtension().stream().filter( e -> url.equals( e.getUrl() ) ).findFirst() + .map( IBaseExtension::getValue ).orElse( null ); + } + private BaseExtensionUtils() { super(); diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/extension/DueDateExtensionUtils.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/extension/DueDateExtensionUtils.java new file mode 100644 index 00000000..814238f9 --- /dev/null +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/extension/DueDateExtensionUtils.java @@ -0,0 +1,57 @@ +package org.dhis2.fhir.adapter.fhir.extension; + +/* + * Copyright (c) 2004-2019, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import ca.uhn.fhir.model.api.IElement; +import org.hl7.fhir.instance.model.api.IBaseHasExtensions; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Date; +import java.util.function.Function; + +/** + * Utility class to process FHIR due date extension. + * + * @author volsch + */ +public abstract class DueDateExtensionUtils +{ + public static final String URL = "http://www.dhis2.org/dhis2-fhir-adapter/fhir/extensions/due-date"; + + public static void setValue( @Nonnull IBaseHasExtensions resource, @Nullable Date date, @Nonnull Function typeFactory ) + { + BaseExtensionUtils.setDateValue( URL, resource, date, typeFactory ); + } + + private DueDateExtensionUtils() + { + super(); + } +} diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/extension/EventStatusExtensionUtils.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/extension/EventStatusExtensionUtils.java new file mode 100644 index 00000000..eae6b470 --- /dev/null +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/extension/EventStatusExtensionUtils.java @@ -0,0 +1,57 @@ +package org.dhis2.fhir.adapter.fhir.extension; + +/* + * Copyright (c) 2004-2019, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import ca.uhn.fhir.model.api.IElement; +import org.dhis2.fhir.adapter.dhis.tracker.program.EventStatus; +import org.hl7.fhir.instance.model.api.IBaseHasExtensions; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.function.Function; + +/** + * Utility class to process DHIS2 event status extension. + * + * @author volsch + */ +public abstract class EventStatusExtensionUtils +{ + public static final String URL = "http://www.dhis2.org/dhis2-fhir-adapter/fhir/extensions/event-status"; + + public static void setValue( @Nonnull IBaseHasExtensions resource, @Nullable EventStatus eventStatus, @Nonnull Function typeFactory ) + { + BaseExtensionUtils.setStringValue( URL, resource, eventStatus == null ? null : eventStatus.name(), typeFactory ); + } + + private EventStatusExtensionUtils() + { + super(); + } +} diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/extension/IncidentDateExtensionUtils.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/extension/IncidentDateExtensionUtils.java index 57cc724a..f513f72c 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/extension/IncidentDateExtensionUtils.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/extension/IncidentDateExtensionUtils.java @@ -50,6 +50,12 @@ public static void setValue( @Nonnull IBaseHasExtensions resource, @Nullable Dat BaseExtensionUtils.setDateValue( URL, resource, date, typeFactory ); } + @Nullable + public static Date getValue( @Nonnull IBaseHasExtensions resource ) + { + return BaseExtensionUtils.getDateValue( URL, resource ); + } + private IncidentDateExtensionUtils() { super(); diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/EnrollmentRule.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/EnrollmentRule.java index 9de6fe32..20a2e4f2 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/EnrollmentRule.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/EnrollmentRule.java @@ -58,8 +58,8 @@ public EnrollmentRule() } @JsonCacheId - @ManyToOne( optional = false ) - @JoinColumn( name = "program_ref_lookup_script_id", referencedColumnName = "id", nullable = false ) + @ManyToOne + @JoinColumn( name = "program_ref_lookup_script_id", referencedColumnName = "id" ) public ExecutableScript getProgramRefLookupScript() { return programRefLookupScript; diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/ScriptVariable.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/ScriptVariable.java index cce6d9df..28342d98 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/ScriptVariable.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/ScriptVariable.java @@ -58,7 +58,9 @@ public enum ScriptVariable ORGANIZATION_UNIT( "organizationUnit" ), ORGANIZATION_UNIT_RESOLVER( "organizationUnitResolver" ), TEI_FHIR_RESOURCE( "teiFhirResource" ), - SEARCH_FILTER( "searchFilter" ); + SEARCH_FILTER( "searchFilter" ), + ASSIGNMENT_UTILS( "assignmentUtils" ), + VALUE_TYPE_UTILS( "valueTypeUtils" ); private final String variableName; diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/AbstractDhisToFhirTransformer.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/AbstractDhisToFhirTransformer.java index 32653111..57529a70 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/AbstractDhisToFhirTransformer.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/AbstractDhisToFhirTransformer.java @@ -31,6 +31,7 @@ import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.model.primitive.IdDt; import org.apache.commons.lang3.StringUtils; +import org.dhis2.fhir.adapter.dhis.model.DhisResourceType; import org.dhis2.fhir.adapter.fhir.data.repository.FhirDhisAssignmentRepository; import org.dhis2.fhir.adapter.fhir.metadata.model.AbstractRule; import org.dhis2.fhir.adapter.fhir.metadata.model.ExecutableScript; @@ -52,6 +53,7 @@ import org.dhis2.fhir.adapter.fhir.transform.TransformerException; import org.dhis2.fhir.adapter.fhir.transform.dhis.DhisToFhirTransformOutcome; import org.dhis2.fhir.adapter.fhir.transform.dhis.DhisToFhirTransformerContext; +import org.dhis2.fhir.adapter.fhir.transform.dhis.impl.util.AbstractAssignmentDhisToFhirTransformerUtils; import org.dhis2.fhir.adapter.fhir.transform.dhis.impl.util.AbstractFhirResourceDhisToFhirTransformerUtils; import org.dhis2.fhir.adapter.fhir.transform.dhis.impl.util.AbstractIdentifierDhisToFhirTransformerUtils; import org.dhis2.fhir.adapter.fhir.transform.fhir.model.ResourceSystem; @@ -68,7 +70,9 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.Collections; import java.util.Date; +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -624,6 +628,25 @@ protected boolean transform( @Nonnull DhisToFhirTransformerContext context, @Non return Boolean.TRUE.equals( executeScript( context, ruleInfo, ruleInfo.getRule().getTransformExpScript(), scriptVariables, Boolean.class ) ); } + @Nonnull + protected List createAssignedFhirReferences( @Nonnull DhisToFhirTransformerContext context, @Nonnull RuleInfo ruleInfo, @Nonnull Map scriptVariables, + @Nonnull DhisResourceType dhisResourceType, @Nullable String dhisId, @Nonnull FhirResourceType fhirResourceType ) + { + @SuppressWarnings( "unchecked" ) final T reference = (T) createAssignedFhirReference( context, ruleInfo, scriptVariables, dhisResourceType, dhisId, fhirResourceType ); + + return reference == null ? Collections.emptyList() : Collections.singletonList( reference ); + } + + @Nullable + protected IBaseReference createAssignedFhirReference( @Nonnull DhisToFhirTransformerContext context, @Nonnull RuleInfo ruleInfo, @Nonnull Map scriptVariables, + @Nonnull DhisResourceType dhisResourceType, @Nullable String dhisId, @Nonnull FhirResourceType fhirResourceType ) + { + final AbstractAssignmentDhisToFhirTransformerUtils assignmentTransformerUtils = TransformerUtils.getScriptVariable( + scriptVariables, ScriptVariable.ASSIGNMENT_UTILS, AbstractAssignmentDhisToFhirTransformerUtils.class ); + + return assignmentTransformerUtils.getMappedFhirId( context, ruleInfo.getRule(), dhisResourceType, dhisId, fhirResourceType ); + } + /** * Executes an executable script with the specified variables . If the mandatory data for executing * the script has not been provided, the script will not be executed at all. diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/enrollment/AbstractEnrollmentToCarePlanFhirTransformer.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/enrollment/AbstractEnrollmentToFhirCarePlanTransformer.java similarity index 98% rename from fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/enrollment/AbstractEnrollmentToCarePlanFhirTransformer.java rename to fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/enrollment/AbstractEnrollmentToFhirCarePlanTransformer.java index 3d1908f9..e87ced9e 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/enrollment/AbstractEnrollmentToCarePlanFhirTransformer.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/enrollment/AbstractEnrollmentToFhirCarePlanTransformer.java @@ -77,7 +77,7 @@ * * @author volsch */ -public abstract class AbstractEnrollmentToCarePlanFhirTransformer extends AbstractDhisToFhirTransformer +public abstract class AbstractEnrollmentToFhirCarePlanTransformer extends AbstractDhisToFhirTransformer { private final Logger logger = LoggerFactory.getLogger( getClass() ); @@ -89,7 +89,7 @@ public abstract class AbstractEnrollmentToCarePlanFhirTransformer extends Abstra private final ProgramMetadataService programMetadataService; - public AbstractEnrollmentToCarePlanFhirTransformer( @Nonnull ScriptExecutor scriptExecutor, @Nonnull LockManager lockManager, @Nonnull SystemRepository systemRepository, @Nonnull FhirResourceRepository fhirResourceRepository, + public AbstractEnrollmentToFhirCarePlanTransformer( @Nonnull ScriptExecutor scriptExecutor, @Nonnull LockManager lockManager, @Nonnull SystemRepository systemRepository, @Nonnull FhirResourceRepository fhirResourceRepository, @Nonnull FhirResourceMappingRepository resourceMappingRepository, @Nonnull FhirDhisAssignmentRepository fhirDhisAssignmentRepository, @Nonnull TrackedEntityMetadataService trackedEntityMetadataService, @Nonnull TrackedEntityRuleRepository trackedEntityRuleRepository, @Nonnull ProgramMetadataService programMetadataService ) diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/program/ProgramStageToFhirDataProvider.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/program/AbstractProgramStageToFhirDataProvider.java similarity index 95% rename from fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/program/ProgramStageToFhirDataProvider.java rename to fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/program/AbstractProgramStageToFhirDataProvider.java index 148cdd34..4e6471cd 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/program/ProgramStageToFhirDataProvider.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/program/AbstractProgramStageToFhirDataProvider.java @@ -52,7 +52,6 @@ import org.dhis2.fhir.adapter.fhir.transform.dhis.DhisToFhirSearchState; import org.dhis2.fhir.adapter.fhir.transform.dhis.PreparedDhisToFhirSearch; import org.dhis2.fhir.adapter.fhir.transform.dhis.impl.AbstractDhisToFhirDataProvider; -import org.springframework.stereotype.Component; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -68,27 +67,20 @@ * * @author volsch */ -@Component -public class ProgramStageToFhirDataProvider extends AbstractDhisToFhirDataProvider +public abstract class AbstractProgramStageToFhirDataProvider extends AbstractDhisToFhirDataProvider { private final ProgramMetadataService metadataService; private final EventService eventService; - public ProgramStageToFhirDataProvider( @Nonnull ScriptExecutor scriptExecutor, @Nonnull ProgramMetadataService metadataService, @Nonnull EventService eventService ) + public AbstractProgramStageToFhirDataProvider( @Nonnull ScriptExecutor scriptExecutor, @Nonnull ProgramMetadataService metadataService, @Nonnull EventService eventService ) { super( scriptExecutor, false ); + this.metadataService = metadataService; this.eventService = eventService; } - @Nonnull - @Override - public Set getFhirVersions() - { - return FhirVersion.ALL; - } - @Nonnull @Override public DhisResourceType getDhisResourceType() diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/program/AbstractProgramStageToFhirQuestionnaireResponseTransformer.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/program/AbstractProgramStageToFhirQuestionnaireResponseTransformer.java new file mode 100644 index 00000000..662d62d7 --- /dev/null +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/program/AbstractProgramStageToFhirQuestionnaireResponseTransformer.java @@ -0,0 +1,262 @@ +package org.dhis2.fhir.adapter.fhir.transform.dhis.impl.program; + +/* + * Copyright (c) 2004-2019, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import org.dhis2.fhir.adapter.dhis.model.DhisResourceType; +import org.dhis2.fhir.adapter.dhis.model.Reference; +import org.dhis2.fhir.adapter.dhis.tracker.program.Program; +import org.dhis2.fhir.adapter.dhis.tracker.program.ProgramMetadataService; +import org.dhis2.fhir.adapter.dhis.tracker.trackedentity.TrackedEntityMetadataService; +import org.dhis2.fhir.adapter.fhir.data.repository.FhirDhisAssignmentRepository; +import org.dhis2.fhir.adapter.fhir.metadata.model.ExecutableScript; +import org.dhis2.fhir.adapter.fhir.metadata.model.FhirClient; +import org.dhis2.fhir.adapter.fhir.metadata.model.FhirResourceMapping; +import org.dhis2.fhir.adapter.fhir.metadata.model.FhirResourceType; +import org.dhis2.fhir.adapter.fhir.metadata.model.ProgramStageRule; +import org.dhis2.fhir.adapter.fhir.metadata.model.RuleInfo; +import org.dhis2.fhir.adapter.fhir.metadata.model.ScriptVariable; +import org.dhis2.fhir.adapter.fhir.metadata.model.TrackedEntityRule; +import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirResourceMappingRepository; +import org.dhis2.fhir.adapter.fhir.metadata.repository.SystemRepository; +import org.dhis2.fhir.adapter.fhir.metadata.repository.TrackedEntityRuleRepository; +import org.dhis2.fhir.adapter.fhir.repository.FhirResourceRepository; +import org.dhis2.fhir.adapter.fhir.repository.MissingDhisResourceException; +import org.dhis2.fhir.adapter.fhir.script.ScriptExecutor; +import org.dhis2.fhir.adapter.fhir.transform.FatalTransformerException; +import org.dhis2.fhir.adapter.fhir.transform.TransformerException; +import org.dhis2.fhir.adapter.fhir.transform.TransformerMappingException; +import org.dhis2.fhir.adapter.fhir.transform.dhis.DhisToFhirTransformOutcome; +import org.dhis2.fhir.adapter.fhir.transform.dhis.DhisToFhirTransformerContext; +import org.dhis2.fhir.adapter.fhir.transform.dhis.impl.AbstractDhisToFhirTransformer; +import org.dhis2.fhir.adapter.fhir.transform.dhis.impl.DhisToFhirTransformer; +import org.dhis2.fhir.adapter.fhir.transform.dhis.impl.metadata.program.ProgramTrackedEntityTypeUtils; +import org.dhis2.fhir.adapter.fhir.transform.scripted.ScriptedEvent; +import org.dhis2.fhir.adapter.fhir.transform.util.TransformerUtils; +import org.dhis2.fhir.adapter.lock.LockManager; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +/** + * Implementation of {@link DhisToFhirTransformer} for transforming DHIS2 + * Program Stage to FHIR Questionnaire Response. + * + * @author volsch + */ +public abstract class AbstractProgramStageToFhirQuestionnaireResponseTransformer extends AbstractDhisToFhirTransformer +{ + private final Logger logger = LoggerFactory.getLogger( getClass() ); + + private final FhirResourceMappingRepository resourceMappingRepository; + + private final TrackedEntityMetadataService trackedEntityMetadataService; + + private final TrackedEntityRuleRepository trackedEntityRuleRepository; + + private final ProgramMetadataService programMetadataService; + + public AbstractProgramStageToFhirQuestionnaireResponseTransformer( @Nonnull ScriptExecutor scriptExecutor, @Nonnull LockManager lockManager, @Nonnull SystemRepository systemRepository, @Nonnull FhirResourceRepository fhirResourceRepository, + @Nonnull FhirResourceMappingRepository resourceMappingRepository, @Nonnull FhirDhisAssignmentRepository fhirDhisAssignmentRepository, + @Nonnull TrackedEntityMetadataService trackedEntityMetadataService, @Nonnull TrackedEntityRuleRepository trackedEntityRuleRepository, + @Nonnull ProgramMetadataService programMetadataService ) + { + super( scriptExecutor, lockManager, systemRepository, fhirResourceRepository, fhirDhisAssignmentRepository ); + + this.resourceMappingRepository = resourceMappingRepository; + this.trackedEntityMetadataService = trackedEntityMetadataService; + this.trackedEntityRuleRepository = trackedEntityRuleRepository; + this.programMetadataService = programMetadataService; + } + + @Nonnull + @Override + public DhisResourceType getDhisResourceType() + { + return DhisResourceType.PROGRAM_STAGE_EVENT; + } + + @Nonnull + @Override + public Class getDhisResourceClass() + { + return ScriptedEvent.class; + } + + @Nonnull + @Override + public Class getRuleClass() + { + return ProgramStageRule.class; + } + + @Override + public int getPriority() + { + return 10; + } + + @Nullable + @Override + public DhisToFhirTransformOutcome transform( + @Nonnull FhirClient fhirClient, @Nonnull DhisToFhirTransformerContext context, @Nonnull ScriptedEvent input, + @Nonnull RuleInfo ruleInfo, @Nonnull Map scriptVariables ) throws TransformerException + { + if ( ruleInfo.getRule().getFhirResourceType() != FhirResourceType.QUESTIONNAIRE_RESPONSE || ruleInfo.getRule().getProgramStage() != null ) + { + return null; + } + + final Map variables = new HashMap<>( scriptVariables ); + + final Program program = programMetadataService.findMetadataByReference( Reference.createIdReference( input.getProgram().getId() ) ) + .orElseThrow( () -> new TransformerMappingException( "Program " + input.getProgram().getId() + " could not be found." ) ); + + final TrackedEntityRule trackedEntityRule = getTrackedEntityRule( program ); + + if ( trackedEntityRule == null ) + { + return null; + } + + final FhirResourceMapping resourceMapping = getResourceMapping( ruleInfo, trackedEntityRule.getFhirResourceType() ); + + final IBaseResource trackedEntityFhirResource = getTrackedEntityFhirResource( fhirClient, context, + new RuleInfo<>( trackedEntityRule, Collections.emptyList() ), trackedEntityRule.getFhirResourceType(), + Objects.requireNonNull( input.getTrackedEntityInstance() ), variables ).orElseThrow( + () -> new MissingDhisResourceException( Objects.requireNonNull( input.getTrackedEntityInstance().getResourceId() ) ) ); + variables.put( ScriptVariable.TEI_FHIR_RESOURCE.getVariableName(), trackedEntityFhirResource ); + + final IBaseResource resource = getResource( fhirClient, context, ruleInfo, variables ).orElse( null ); + + if ( resource == null ) + { + return null; + } + + final IBaseResource modifiedResource = cloneToModified( context, ruleInfo, resource, variables ); + + if ( modifiedResource == null ) + { + return null; + } + + variables.put( ScriptVariable.OUTPUT.getVariableName(), modifiedResource ); + + if ( !transformInternal( fhirClient, context, ruleInfo, scriptVariables, input, modifiedResource, trackedEntityFhirResource ) ) + { + return null; + } + + if ( !transformFhirResourceType( context, ruleInfo, variables, resourceMapping, input, modifiedResource ) ) + { + return null; + } + + if ( !transform( context, ruleInfo, variables ) ) + { + return null; + } + + return createResult( context, ruleInfo, variables, resource, modifiedResource ); + } + + @Nonnull + private DhisToFhirTransformOutcome createResult( @Nonnull DhisToFhirTransformerContext context, @Nonnull RuleInfo ruleInfo, @Nonnull Map variables, + @Nonnull IBaseResource resource, @Nonnull IBaseResource modifiedResource ) + { + if ( !context.getDhisRequest().isDhisFhirId() && evaluateNotModified( context, variables, resource, modifiedResource ) ) + { + // resource has not been changed and do not need to be updated + return new DhisToFhirTransformOutcome<>( ruleInfo.getRule(), null ); + } + + return new DhisToFhirTransformOutcome<>( ruleInfo.getRule(), modifiedResource ); + } + + protected boolean transformInternal( @Nonnull FhirClient fhirClient, @Nonnull DhisToFhirTransformerContext context, + @Nonnull RuleInfo ruleInfo, @Nonnull Map scriptVariables, + @Nonnull ScriptedEvent input, @Nonnull IBaseResource output, @Nonnull IBaseResource trackedEntityResource ) + { + // method can be overridden + return true; + } + + @Nonnull + @Override + protected Optional getActiveResource( @Nonnull FhirClient fhirClient, @Nonnull DhisToFhirTransformerContext context, @Nonnull RuleInfo ruleInfo, @Nonnull Map scriptVariables ) throws TransformerException + { + return Optional.empty(); + } + + @Override + protected void lockResource( @Nonnull FhirClient fhirClient, @Nonnull DhisToFhirTransformerContext context, @Nonnull RuleInfo ruleInfo, @Nonnull Map scriptVariables ) throws TransformerException + { + if ( !context.getDhisRequest().isDhisFhirId() ) + { + final ScriptedEvent scriptedEvent = TransformerUtils.getScriptVariable( + scriptVariables, ScriptVariable.INPUT, ScriptedEvent.class ); + + if ( scriptedEvent.getId() != null ) + { + final String lockKey = "out-ps:" + scriptedEvent.getId(); + getLockManager().getCurrentLockContext().orElseThrow( () -> new FatalTransformerException( "No lock context available." ) ).lock( lockKey ); + } + } + } + + @Nullable + @Override + protected String getIdentifierValue( @Nonnull DhisToFhirTransformerContext context, @Nonnull RuleInfo ruleInfo, @Nullable ExecutableScript identifierLookupScript, + @Nonnull ScriptedEvent scriptedDhisResource, @Nonnull Map scriptVariables ) + { + // for enrollments no identifier value can be created + return null; + } + + @Nonnull + protected FhirResourceMapping getResourceMapping( @Nonnull RuleInfo ruleInfo, @Nonnull FhirResourceType trackedEntityFhirResourceType ) + { + return resourceMappingRepository.findOneByFhirResourceType( ruleInfo.getRule().getFhirResourceType(), trackedEntityFhirResourceType ) + .orElseThrow( () -> new FatalTransformerException( "No FHIR resource mapping has been defined for " + ruleInfo.getRule().getFhirResourceType() + "." ) ); + } + + @Nullable + protected TrackedEntityRule getTrackedEntityRule( @Nonnull Program program ) + { + return ProgramTrackedEntityTypeUtils.getTrackedEntityRule( trackedEntityMetadataService, trackedEntityRuleRepository, program ).orElse( null ); + } +} diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/program/ProgramStageToFhirRequestResolver.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/program/ProgramStageToFhirRequestResolver.java index d6fe3ea1..58f75c02 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/program/ProgramStageToFhirRequestResolver.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/program/ProgramStageToFhirRequestResolver.java @@ -126,11 +126,13 @@ public List> resolveRules( @Nonnull ScriptedDhi final ScriptedEvent event = (ScriptedEvent) dhisResource; final Program program = event.getProgram(); final ProgramStage programStage = event.getProgramStage(); + return rules.stream().map( ri -> new RuleInfo<>( (ProgramStageRule) ri.getRule(), ri.getDhisDataReferences() ) ) - .filter( ri -> program.isReference( ri.getRule().getProgramStage().getProgram().getProgramReference() ) && + .filter( ri -> ri.getRule().getProgramStage() == null || ( + program.isReference( ri.getRule().getProgramStage().getProgram().getProgramReference() ) && programStage.isReference( ri.getRule().getProgramStage().getProgramStageReference() ) && ri.getRule().getProgramStage().isEnabled() && ri.getRule().getProgramStage().isExpEnabled() && - ri.getRule().getProgramStage().getProgram().isEnabled() && ri.getRule().getProgramStage().getProgram().isExpEnabled() ) + ri.getRule().getProgramStage().getProgram().isEnabled() && ri.getRule().getProgramStage().getProgram().isExpEnabled() ) ) .sorted().collect( Collectors.toList() ); } @@ -152,6 +154,6 @@ public ScriptedDhisResource convert( @Nonnull DhisResource dhisResource, @Nonnul final ScriptedTrackedEntityInstance scriptedTrackedEntityInstance = new ImmutableScriptedTrackedEntityInstance( new WritableScriptedTrackedEntityInstance( trackedEntityMetadataService, trackedEntityService, trackedEntityAttributes, trackedEntityType, event.getTrackedEntityInstanceId(), scriptExecutionContext, valueConverter ) ); - return new ImmutableScriptedEvent( new WritableScriptedEvent( program, programStage, event, scriptedTrackedEntityInstance, valueConverter ) ); + return new ImmutableScriptedEvent( new WritableScriptedEvent( program, programStage, event, scriptedTrackedEntityInstance, scriptExecutionContext, valueConverter ) ); } } diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/util/AbstractAssignmentDhisToFhirTransformerUtils.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/util/AbstractAssignmentDhisToFhirTransformerUtils.java new file mode 100644 index 00000000..0bbc6bae --- /dev/null +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/util/AbstractAssignmentDhisToFhirTransformerUtils.java @@ -0,0 +1,104 @@ +package org.dhis2.fhir.adapter.fhir.transform.dhis.impl.util; + +/* + * Copyright (c) 2004-2019, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import org.dhis2.fhir.adapter.dhis.model.DhisResourceId; +import org.dhis2.fhir.adapter.dhis.model.DhisResourceType; +import org.dhis2.fhir.adapter.fhir.data.repository.FhirDhisAssignmentRepository; +import org.dhis2.fhir.adapter.fhir.metadata.model.AbstractRule; +import org.dhis2.fhir.adapter.fhir.metadata.model.FhirClient; +import org.dhis2.fhir.adapter.fhir.metadata.model.FhirResourceType; +import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientRepository; +import org.dhis2.fhir.adapter.fhir.script.ScriptExecutionContext; +import org.dhis2.fhir.adapter.fhir.transform.FatalTransformerException; +import org.dhis2.fhir.adapter.fhir.transform.dhis.DhisToFhirTransformerContext; +import org.hl7.fhir.instance.model.api.IBaseReference; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * DHIS2 to FHIR transformer utility methods for assignment of IDs. + * + * @author volsch + */ +public abstract class AbstractAssignmentDhisToFhirTransformerUtils extends AbstractDhisToFhirTransformerUtils +{ + public static final String SCRIPT_ATTR_NAME = "assignmentUtils"; + + private final FhirDhisAssignmentRepository assignmentRepository; + + private final FhirClientRepository fhirClientRepository; + + protected AbstractAssignmentDhisToFhirTransformerUtils( @Nonnull ScriptExecutionContext scriptExecutionContext, + @Nonnull FhirDhisAssignmentRepository assignmentRepository, @Nonnull FhirClientRepository fhirClientRepository ) + { + super( scriptExecutionContext ); + + this.assignmentRepository = assignmentRepository; + this.fhirClientRepository = fhirClientRepository; + } + + @Nonnull + @Override + public final String getScriptAttrName() + { + return SCRIPT_ATTR_NAME; + } + + @Nullable + public IBaseReference getMappedFhirId( @Nonnull DhisToFhirTransformerContext context, @Nonnull AbstractRule rule, + @Nonnull DhisResourceType dhisResourceType, @Nullable String dhisId, @Nonnull FhirResourceType fhirResourceType ) + { + if ( dhisId == null ) + { + return null; + } + + if ( fhirResourceType.isSyncDhisId() || context.getDhisRequest().isDhisFhirId() ) + { + return createReference( fhirResourceType, dhisId ); + } + + final FhirClient fhirClient = fhirClientRepository.findOneByIdCached( context.getFhirClientId() ) + .orElseThrow( () -> new FatalTransformerException( "FHIR Client with ID " + context.getFhirClientId() + " could not be found." ) ); + + final String fhirId = assignmentRepository.findFirstFhirResourceId( rule, fhirClient, new DhisResourceId( dhisResourceType, dhisId ) ); + + if ( fhirId == null ) + { + return null; + } + + return createReference( fhirResourceType, fhirId ); + } + + @Nonnull + protected abstract IBaseReference createReference( @Nonnull FhirResourceType fhirResourceType, @Nonnull String fhirId ); +} diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/util/DataElementDhisToFhirTransformerUtils.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/util/DataElementDhisToFhirTransformerUtils.java index e548bd63..b2b06305 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/util/DataElementDhisToFhirTransformerUtils.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/util/DataElementDhisToFhirTransformerUtils.java @@ -1,7 +1,7 @@ package org.dhis2.fhir.adapter.fhir.transform.dhis.impl.util; /* - * Copyright (c) 2004-2018, University of Oslo + * Copyright (c) 2004-2019, University of Oslo * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -61,7 +61,7 @@ public class DataElementDhisToFhirTransformerUtils extends AbstractDhisToFhirTra { public static final String SCRIPT_ATTR_NAME = "dataElementUtils"; - protected DataElementDhisToFhirTransformerUtils( @Nonnull ScriptExecutionContext scriptExecutionContext ) + public DataElementDhisToFhirTransformerUtils( @Nonnull ScriptExecutionContext scriptExecutionContext ) { super( scriptExecutionContext ); } diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/search/SearchFilter.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/search/SearchFilter.java index feba74a4..822f3540 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/search/SearchFilter.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/search/SearchFilter.java @@ -99,7 +99,7 @@ public boolean addReference( @Nonnull String fhirSearchParamName, @Nullable Obje @Nullable private DhisFhirResourceId getSearchedDhisResourceId( @Nonnull String fhirSearchParamName, @Nullable Object defaultFhirResourceType, @Nonnull Object dhisResourceType ) { - final FhirResourceType fhirType = resolveFhirResourceType( defaultFhirResourceType ); + final FhirResourceType fhirType = defaultFhirResourceType == null ? null : resolveFhirResourceType( defaultFhirResourceType ); final DhisResourceType dhisType = resolveDhisResourceType( dhisResourceType ); final List searchParamValues = searchFilterCollector.getSearchParamValues( fhirSearchParamName ); diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/search/SearchFilterCollector.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/search/SearchFilterCollector.java index 9a57a55a..f766ee63 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/search/SearchFilterCollector.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/search/SearchFilterCollector.java @@ -56,7 +56,7 @@ public class SearchFilterCollector implements UriFilterApplier { public static final Set QUERY_PARAM_NAMES = Collections.unmodifiableSet( - new HashSet<>( Arrays.asList( "event", "orgUnit", "ou", "status", "trackedEntityInstance" ) ) ); + new HashSet<>( Arrays.asList( "event", "orgUnit", "ou", "status", "trackedEntityInstance", "program", "programStage" ) ) ); private final Function dhisPropertyRefResolver; diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/program/AbstractFhirCarePlanToEnrollmentTransformer.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/program/AbstractFhirCarePlanToEnrollmentTransformer.java new file mode 100644 index 00000000..66485f5e --- /dev/null +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/program/AbstractFhirCarePlanToEnrollmentTransformer.java @@ -0,0 +1,166 @@ +package org.dhis2.fhir.adapter.fhir.transform.fhir.impl.program; + +/* + * Copyright (c) 2004-2019, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import org.dhis2.fhir.adapter.dhis.converter.ValueConverter; +import org.dhis2.fhir.adapter.dhis.model.Reference; +import org.dhis2.fhir.adapter.dhis.orgunit.OrganizationUnitService; +import org.dhis2.fhir.adapter.dhis.tracker.program.Enrollment; +import org.dhis2.fhir.adapter.dhis.tracker.program.EnrollmentService; +import org.dhis2.fhir.adapter.dhis.tracker.program.EnrollmentStatus; +import org.dhis2.fhir.adapter.dhis.tracker.program.Program; +import org.dhis2.fhir.adapter.dhis.tracker.program.ProgramMetadataService; +import org.dhis2.fhir.adapter.dhis.tracker.trackedentity.IdentifiedTrackedEntityInstance; +import org.dhis2.fhir.adapter.dhis.tracker.trackedentity.TrackedEntityMetadataService; +import org.dhis2.fhir.adapter.dhis.tracker.trackedentity.TrackedEntityService; +import org.dhis2.fhir.adapter.dhis.tracker.trackedentity.TrackedEntityType; +import org.dhis2.fhir.adapter.fhir.data.repository.FhirDhisAssignmentRepository; +import org.dhis2.fhir.adapter.fhir.metadata.model.EnrollmentRule; +import org.dhis2.fhir.adapter.fhir.metadata.model.FhirClientResource; +import org.dhis2.fhir.adapter.fhir.metadata.model.FhirResourceMapping; +import org.dhis2.fhir.adapter.fhir.metadata.model.FhirResourceType; +import org.dhis2.fhir.adapter.fhir.metadata.model.RuleInfo; +import org.dhis2.fhir.adapter.fhir.metadata.model.ScriptVariable; +import org.dhis2.fhir.adapter.fhir.metadata.model.TrackedEntityRule; +import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirResourceMappingRepository; +import org.dhis2.fhir.adapter.fhir.metadata.repository.TrackedEntityRuleRepository; +import org.dhis2.fhir.adapter.fhir.script.ScriptExecutionContext; +import org.dhis2.fhir.adapter.fhir.script.ScriptExecutor; +import org.dhis2.fhir.adapter.fhir.transform.TransformerDataException; +import org.dhis2.fhir.adapter.fhir.transform.TransformerException; +import org.dhis2.fhir.adapter.fhir.transform.fhir.FhirToDhisTransformOutcome; +import org.dhis2.fhir.adapter.fhir.transform.fhir.FhirToDhisTransformerContext; +import org.dhis2.fhir.adapter.fhir.transform.scripted.ScriptedTrackedEntityInstance; +import org.dhis2.fhir.adapter.fhir.transform.scripted.WritableScriptedEnrollment; +import org.dhis2.fhir.adapter.fhir.transform.util.TransformerUtils; +import org.hl7.fhir.instance.model.api.IBaseResource; + +import javax.annotation.Nonnull; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +/** + * Specific transformer that transforms a FHIR care plan to a DHIS2 enrollment. + * + * @author volsch + */ +public abstract class AbstractFhirCarePlanToEnrollmentTransformer extends AbstractFhirToEnrollmentTransformer +{ + public AbstractFhirCarePlanToEnrollmentTransformer( @Nonnull ScriptExecutor scriptExecutor, @Nonnull TrackedEntityMetadataService trackedEntityMetadataService, @Nonnull TrackedEntityService trackedEntityService, + @Nonnull TrackedEntityRuleRepository trackedEntityRuleRepository, @Nonnull OrganizationUnitService organizationUnitService, @Nonnull ProgramMetadataService programMetadataService, @Nonnull EnrollmentService enrollmentService, + @Nonnull FhirResourceMappingRepository resourceMappingRepository, @Nonnull FhirDhisAssignmentRepository fhirDhisAssignmentRepository, @Nonnull ScriptExecutionContext scriptExecutionContext, @Nonnull ValueConverter valueConverter ) + { + super( scriptExecutor, trackedEntityMetadataService, trackedEntityService, trackedEntityRuleRepository, organizationUnitService, programMetadataService, enrollmentService, resourceMappingRepository, fhirDhisAssignmentRepository, + scriptExecutionContext, valueConverter ); + } + + @Override + public int getPriority() + { + return 10; + } + + @Override + protected boolean isSyncRequired( @Nonnull FhirToDhisTransformerContext context, @Nonnull RuleInfo ruleInfo, @Nonnull Map scriptVariables ) throws TransformerException + { + return context.getFhirRequest().isSync(); + } + + @Override + @Nonnull + protected Optional getActiveResource( @Nonnull FhirToDhisTransformerContext context, @Nonnull RuleInfo ruleInfo, @Nonnull Map scriptVariables, boolean sync, boolean refreshed ) throws TransformerException + { + return Optional.empty(); + } + + @Override + protected Enrollment createResource( @Nonnull FhirToDhisTransformerContext context, @Nonnull RuleInfo ruleInfo, String id, @Nonnull Map scriptVariables, boolean sync, boolean refreshed ) throws TransformerException + { + final Enrollment enrollment = new Enrollment( true ); + enrollment.setStatus( EnrollmentStatus.ACTIVE ); + + return enrollment; + } + + @Override + public FhirToDhisTransformOutcome transform( @Nonnull FhirClientResource fhirClientResource, @Nonnull FhirToDhisTransformerContext context, + @Nonnull IBaseResource input, @Nonnull RuleInfo ruleInfo, @Nonnull Map scriptVariables ) throws TransformerException + { + if ( ruleInfo.getRule().getFhirResourceType() != FhirResourceType.CARE_PLAN || ruleInfo.getRule().getProgramRefLookupScript() != null ) + { + return null; + } + + final Map variables = new HashMap<>( scriptVariables ); + + addBasicScriptVariables( context, ruleInfo, variables, input ); + + final RuleInfo trackedEntityRuleInfo = getTrackedEntityRuleInfo( context, ruleInfo, scriptVariables, + TransformerUtils.getScriptVariable( variables, ScriptVariable.PROGRAM, Program.class ), + TransformerUtils.getScriptVariable( variables, ScriptVariable.TRACKED_ENTITY_TYPE, TrackedEntityType.class ) ); + final FhirResourceMapping resourceMapping = getResourceMapping( ruleInfo, trackedEntityRuleInfo.getRule().getFhirResourceType() ); + final IdentifiedTrackedEntityInstance trackedEntityInstance = getTrackedEntityInstance( context, trackedEntityRuleInfo, resourceMapping, variables, false ) + .orElseThrow( () -> new TransformerDataException( "Tracked entity instance could not be found." ) ); + + addScriptVariables( context, variables, ruleInfo, trackedEntityRuleInfo, trackedEntityInstance ); + + final Enrollment enrollment = getResource( fhirClientResource, context, ruleInfo, variables ) + .orElseThrow( () -> new TransformerDataException( "Enrollment could not be determined." ) ); + final ScriptedTrackedEntityInstance scriptedTrackedEntityInstance = TransformerUtils.getScriptVariable( variables, ScriptVariable.TRACKED_ENTITY_INSTANCE, ScriptedTrackedEntityInstance.class ); + final Program program = TransformerUtils.getScriptVariable( variables, ScriptVariable.PROGRAM, Program.class ); + + final WritableScriptedEnrollment scriptedEnrollment = new WritableScriptedEnrollment( + program, enrollment, scriptedTrackedEntityInstance, scriptExecutionContext, valueConverter ); + variables.put( ScriptVariable.OUTPUT.getVariableName(), scriptedEnrollment ); + + transformInternal( context, ruleInfo, scriptVariables, resourceMapping, + program, input, scriptedTrackedEntityInstance, scriptedEnrollment ); + if ( !transform( context, ruleInfo, variables ) ) + { + throw new TransformerDataException( "Care plan data could not be transformed to enrollment." ); + } + + if ( enrollment.isModified() ) + { + scriptedEnrollment.validate(); + } + + return new FhirToDhisTransformOutcome<>( ruleInfo.getRule(), enrollment, enrollment.isNewResource() ); + } + + protected void transformInternal( @Nonnull FhirToDhisTransformerContext context, @Nonnull RuleInfo ruleInfo, @Nonnull Map scriptVariables, @Nonnull FhirResourceMapping fhirResourceMapping, + @Nonnull Program program, @Nonnull IBaseResource carePlan, @Nonnull ScriptedTrackedEntityInstance scriptedTrackedEntityInstance, @Nonnull WritableScriptedEnrollment scriptedEnrollment ) throws TransformerException + { + // method can be overridden + } + + @Nonnull + protected abstract Reference getProgramRef( @Nonnull FhirToDhisTransformerContext context, @Nonnull RuleInfo ruleInfo, @Nonnull Map scriptVariables, @Nonnull IBaseResource carePlan ); +} diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/program/AbstractFhirToEnrollmentTransformer.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/program/AbstractFhirToEnrollmentTransformer.java new file mode 100644 index 00000000..03f8f73e --- /dev/null +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/program/AbstractFhirToEnrollmentTransformer.java @@ -0,0 +1,220 @@ +package org.dhis2.fhir.adapter.fhir.transform.fhir.impl.program; + +/* + * Copyright (c) 2004-2019, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import org.dhis2.fhir.adapter.dhis.converter.ValueConverter; +import org.dhis2.fhir.adapter.dhis.model.DhisResourceType; +import org.dhis2.fhir.adapter.dhis.model.Reference; +import org.dhis2.fhir.adapter.dhis.orgunit.OrganizationUnitService; +import org.dhis2.fhir.adapter.dhis.tracker.program.Enrollment; +import org.dhis2.fhir.adapter.dhis.tracker.program.EnrollmentService; +import org.dhis2.fhir.adapter.dhis.tracker.program.Program; +import org.dhis2.fhir.adapter.dhis.tracker.program.ProgramMetadataService; +import org.dhis2.fhir.adapter.dhis.tracker.trackedentity.IdentifiedTrackedEntityInstance; +import org.dhis2.fhir.adapter.dhis.tracker.trackedentity.TrackedEntityAttributes; +import org.dhis2.fhir.adapter.dhis.tracker.trackedentity.TrackedEntityMetadataService; +import org.dhis2.fhir.adapter.dhis.tracker.trackedentity.TrackedEntityService; +import org.dhis2.fhir.adapter.dhis.tracker.trackedentity.TrackedEntityType; +import org.dhis2.fhir.adapter.fhir.data.repository.FhirDhisAssignmentRepository; +import org.dhis2.fhir.adapter.fhir.metadata.model.EnrollmentRule; +import org.dhis2.fhir.adapter.fhir.metadata.model.FhirClientResource; +import org.dhis2.fhir.adapter.fhir.metadata.model.FhirResourceMapping; +import org.dhis2.fhir.adapter.fhir.metadata.model.FhirResourceType; +import org.dhis2.fhir.adapter.fhir.metadata.model.RuleInfo; +import org.dhis2.fhir.adapter.fhir.metadata.model.ScriptVariable; +import org.dhis2.fhir.adapter.fhir.metadata.model.TrackedEntityRule; +import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirResourceMappingRepository; +import org.dhis2.fhir.adapter.fhir.metadata.repository.TrackedEntityRuleRepository; +import org.dhis2.fhir.adapter.fhir.repository.DhisFhirResourceId; +import org.dhis2.fhir.adapter.fhir.script.ScriptExecutionContext; +import org.dhis2.fhir.adapter.fhir.script.ScriptExecutor; +import org.dhis2.fhir.adapter.fhir.transform.TransformerDataException; +import org.dhis2.fhir.adapter.fhir.transform.TransformerException; +import org.dhis2.fhir.adapter.fhir.transform.TransformerMappingException; +import org.dhis2.fhir.adapter.fhir.transform.fhir.FhirToDhisDeleteTransformOutcome; +import org.dhis2.fhir.adapter.fhir.transform.fhir.FhirToDhisTransformerContext; +import org.dhis2.fhir.adapter.fhir.transform.fhir.impl.AbstractFhirToDhisTransformer; +import org.dhis2.fhir.adapter.spring.StaticObjectProvider; +import org.hl7.fhir.instance.model.api.IBaseResource; + +import javax.annotation.Nonnull; +import java.util.Collections; +import java.util.Map; +import java.util.Optional; + +/** + * Abstract implementation of a transformer that transforms from FHIR to a DHIS2 enrollment. + * + * @author volsch + */ +public abstract class AbstractFhirToEnrollmentTransformer extends AbstractFhirToDhisTransformer +{ + protected final EnrollmentService enrollmentService; + + protected final TrackedEntityMetadataService trackedEntityMetadataService; + + protected final TrackedEntityRuleRepository trackedEntityRuleRepository; + + protected final ScriptExecutionContext scriptExecutionContext; + + protected final ValueConverter valueConverter; + + protected final ProgramMetadataService programMetadataService; + + protected final FhirResourceMappingRepository resourceMappingRepository; + + public AbstractFhirToEnrollmentTransformer( @Nonnull ScriptExecutor scriptExecutor, @Nonnull TrackedEntityMetadataService trackedEntityMetadataService, @Nonnull TrackedEntityService trackedEntityService, + @Nonnull TrackedEntityRuleRepository trackedEntityRuleRepository, + @Nonnull OrganizationUnitService organizationUnitService, @Nonnull ProgramMetadataService programMetadataService, @Nonnull EnrollmentService enrollmentService, + @Nonnull FhirResourceMappingRepository resourceMappingRepository, @Nonnull FhirDhisAssignmentRepository fhirDhisAssignmentRepository, @Nonnull ScriptExecutionContext scriptExecutionContext, @Nonnull ValueConverter valueConverter ) + { + super( scriptExecutor, organizationUnitService, new StaticObjectProvider<>( trackedEntityMetadataService ), new StaticObjectProvider<>( trackedEntityService ), + fhirDhisAssignmentRepository, scriptExecutionContext, valueConverter ); + + this.programMetadataService = programMetadataService; + this.enrollmentService = enrollmentService; + this.trackedEntityMetadataService = trackedEntityMetadataService; + this.trackedEntityRuleRepository = trackedEntityRuleRepository; + this.resourceMappingRepository = resourceMappingRepository; + this.scriptExecutionContext = scriptExecutionContext; + this.valueConverter = valueConverter; + } + + @Override + @Nonnull + public DhisResourceType getDhisResourceType() + { + return DhisResourceType.ENROLLMENT; + } + + @Override + @Nonnull + public Class getDhisResourceClass() + { + return Enrollment.class; + } + + @Override + @Nonnull + public Class getRuleClass() + { + return EnrollmentRule.class; + } + + @Override + @Nonnull + protected Optional getResourceById( String id ) throws TransformerException + { + return id == null ? Optional.empty() : enrollmentService.findOneById( id ); + } + + @Override + @Nonnull + protected Optional findResourceById( @Nonnull FhirToDhisTransformerContext context, @Nonnull RuleInfo ruleInfo, @Nonnull String id, @Nonnull Map scriptVariables ) + { + return enrollmentService.findOneById( id ); + } + + @Override + public FhirToDhisDeleteTransformOutcome transformDeletion( @Nonnull FhirClientResource fhirClientResource, @Nonnull RuleInfo ruleInfo, @Nonnull DhisFhirResourceId dhisFhirResourceId ) throws TransformerException + { + final Enrollment enrollment = new Enrollment(); + enrollment.setId( dhisFhirResourceId.getId() ); + + return new FhirToDhisDeleteTransformOutcome<>( ruleInfo.getRule(), enrollment, true ); + } + + protected void addBasicScriptVariables( @Nonnull FhirToDhisTransformerContext context, @Nonnull RuleInfo ruleInfo, @Nonnull Map scriptVariables, @Nonnull IBaseResource carePlan ) throws TransformerException + { + final Program program = getProgram( context, ruleInfo, scriptVariables, carePlan ); + scriptVariables.put( ScriptVariable.PROGRAM.getVariableName(), program ); + + final TrackedEntityAttributes attributes = trackedEntityMetadataService.getAttributes(); + scriptVariables.put( ScriptVariable.TRACKED_ENTITY_ATTRIBUTES.getVariableName(), attributes ); + + final TrackedEntityType trackedEntityType = getTrackedEntityType( context, ruleInfo, scriptVariables, program ); + scriptVariables.put( ScriptVariable.TRACKED_ENTITY_TYPE.getVariableName(), trackedEntityType ); + } + + protected void addScriptVariables( @Nonnull FhirToDhisTransformerContext context, @Nonnull Map variables, @Nonnull RuleInfo ruleInfo, + @Nonnull RuleInfo trackedEntityRuleRuleInfo, @Nonnull IdentifiedTrackedEntityInstance trackedEntityInstance ) throws TransformerException + { + variables.put( ScriptVariable.TRACKED_ENTITY_RESOURCE_TYPE.getVariableName(), trackedEntityRuleRuleInfo.getRule().getFhirResourceType() ); + addTrackedEntityScriptVariables( context, ruleInfo, trackedEntityInstance, variables ); + } + + @Nonnull + protected FhirResourceMapping getResourceMapping( @Nonnull RuleInfo ruleInfo, @Nonnull FhirResourceType trackedEntityFhirResourceType ) + { + return resourceMappingRepository.findOneByFhirResourceType( ruleInfo.getRule().getFhirResourceType(), trackedEntityFhirResourceType ) + .orElseThrow( () -> new TransformerMappingException( "No FHIR resource mapping has been defined for " + ruleInfo.getRule().getFhirResourceType() + + " and tracked entity FHIR resource " + trackedEntityFhirResourceType + "." ) ); + } + + @Override + protected boolean isAlwaysActiveResource( @Nonnull RuleInfo ruleInfo ) + { + return false; + } + + @Nonnull + protected TrackedEntityType getTrackedEntityType( @Nonnull FhirToDhisTransformerContext context, @Nonnull RuleInfo ruleInfo, @Nonnull Map scriptVariables, + @Nonnull Program program ) + { + return trackedEntityMetadataService.findTypeByReference( Reference.createIdReference( program.getTrackedEntityTypeId() ) ) + .orElseThrow( () -> new TransformerMappingException( "Tracked entity type " + program.getTrackedEntityTypeId() + " of tracker program " + program.getId() + " does not exist." ) ); + } + + @Nonnull + protected RuleInfo getTrackedEntityRuleInfo( @Nonnull FhirToDhisTransformerContext context, @Nonnull RuleInfo ruleInfo, @Nonnull Map scriptVariables, + @Nonnull Program program, @Nonnull TrackedEntityType trackedEntityType ) + { + return trackedEntityRuleRepository.findByTypeRefs( trackedEntityType.getAllReferences() ) + .stream().findFirst().map( r -> new RuleInfo<>( r, Collections.emptyList() ) ) + .orElseThrow( () -> new TransformerMappingException( "Tracked entity type " + program.getTrackedEntityTypeId() + " is not associated with a tracked entity rule." ) ); + } + + @Nonnull + protected abstract Reference getProgramRef( @Nonnull FhirToDhisTransformerContext context, @Nonnull RuleInfo ruleInfo, @Nonnull Map scriptVariables, @Nonnull IBaseResource carePlan ); + + @Nonnull + protected Program getProgram( @Nonnull FhirToDhisTransformerContext context, @Nonnull RuleInfo ruleInfo, @Nonnull Map scriptVariables, @Nonnull IBaseResource carePlan ) + { + final Reference programRef = getProgramRef( context, ruleInfo, scriptVariables, carePlan ); + final Program program = programMetadataService.findMetadataByReference( programRef ) + .orElseThrow( () -> new TransformerDataException( "Tracker program \"" + programRef + "\" does not exist." ) ); + + if ( !program.isRegistration() ) + { + throw new TransformerDataException( "Tracker program \"" + programRef + "\" does not require registration." ); + } + + return program; + } +} diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/program/FhirToEnrollmentTransformer.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/program/FhirToEnrollmentTransformer.java index 584b19b0..84727692 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/program/FhirToEnrollmentTransformer.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/program/FhirToEnrollmentTransformer.java @@ -29,7 +29,6 @@ */ import org.dhis2.fhir.adapter.dhis.converter.ValueConverter; -import org.dhis2.fhir.adapter.dhis.model.DhisResourceType; import org.dhis2.fhir.adapter.dhis.model.Reference; import org.dhis2.fhir.adapter.dhis.orgunit.OrganizationUnit; import org.dhis2.fhir.adapter.dhis.orgunit.OrganizationUnitService; @@ -39,7 +38,6 @@ import org.dhis2.fhir.adapter.dhis.tracker.program.Program; import org.dhis2.fhir.adapter.dhis.tracker.program.ProgramMetadataService; import org.dhis2.fhir.adapter.dhis.tracker.trackedentity.IdentifiedTrackedEntityInstance; -import org.dhis2.fhir.adapter.dhis.tracker.trackedentity.TrackedEntityAttributes; import org.dhis2.fhir.adapter.dhis.tracker.trackedentity.TrackedEntityMetadataService; import org.dhis2.fhir.adapter.dhis.tracker.trackedentity.TrackedEntityService; import org.dhis2.fhir.adapter.dhis.tracker.trackedentity.TrackedEntityType; @@ -54,21 +52,16 @@ import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirResourceMappingRepository; import org.dhis2.fhir.adapter.fhir.metadata.repository.TrackedEntityRuleRepository; import org.dhis2.fhir.adapter.fhir.model.FhirVersion; -import org.dhis2.fhir.adapter.fhir.repository.DhisFhirResourceId; import org.dhis2.fhir.adapter.fhir.script.ScriptExecutionContext; import org.dhis2.fhir.adapter.fhir.script.ScriptExecutor; import org.dhis2.fhir.adapter.fhir.transform.TransformerDataException; import org.dhis2.fhir.adapter.fhir.transform.TransformerException; -import org.dhis2.fhir.adapter.fhir.transform.TransformerMappingException; -import org.dhis2.fhir.adapter.fhir.transform.fhir.FhirToDhisDeleteTransformOutcome; import org.dhis2.fhir.adapter.fhir.transform.fhir.FhirToDhisTransformOutcome; import org.dhis2.fhir.adapter.fhir.transform.fhir.FhirToDhisTransformerContext; -import org.dhis2.fhir.adapter.fhir.transform.fhir.impl.AbstractFhirToDhisTransformer; import org.dhis2.fhir.adapter.fhir.transform.scripted.ScriptedTrackedEntityInstance; import org.dhis2.fhir.adapter.fhir.transform.scripted.WritableScriptedEnrollment; import org.dhis2.fhir.adapter.fhir.transform.util.TransformerUtils; import org.dhis2.fhir.adapter.model.ValueType; -import org.dhis2.fhir.adapter.spring.StaticObjectProvider; import org.dhis2.fhir.adapter.util.DateTimeUtils; import org.hl7.fhir.instance.model.api.IAnyResource; import org.hl7.fhir.instance.model.api.IBaseResource; @@ -78,7 +71,6 @@ import javax.annotation.Nullable; import java.time.ZoneId; import java.time.ZonedDateTime; -import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Objects; @@ -90,39 +82,16 @@ * @author volsch */ @Component -public class FhirToEnrollmentTransformer extends AbstractFhirToDhisTransformer +public class FhirToEnrollmentTransformer extends AbstractFhirToEnrollmentTransformer { - private final EnrollmentService enrollmentService; - - private final TrackedEntityMetadataService trackedEntityMetadataService; - - private final TrackedEntityRuleRepository trackedEntityRuleRepository; - - private final ScriptExecutionContext scriptExecutionContext; - - private final ValueConverter valueConverter; - - private final ProgramMetadataService programMetadataService; - - private final FhirResourceMappingRepository resourceMappingRepository; - private final ZoneId zoneId = ZoneId.systemDefault(); public FhirToEnrollmentTransformer( @Nonnull ScriptExecutor scriptExecutor, @Nonnull TrackedEntityMetadataService trackedEntityMetadataService, @Nonnull TrackedEntityService trackedEntityService, - @Nonnull TrackedEntityRuleRepository trackedEntityRuleRepository, - @Nonnull OrganizationUnitService organizationUnitService, @Nonnull ProgramMetadataService programMetadataService, @Nonnull EnrollmentService enrollmentService, + @Nonnull TrackedEntityRuleRepository trackedEntityRuleRepository, @Nonnull OrganizationUnitService organizationUnitService, @Nonnull ProgramMetadataService programMetadataService, @Nonnull EnrollmentService enrollmentService, @Nonnull FhirResourceMappingRepository resourceMappingRepository, @Nonnull FhirDhisAssignmentRepository fhirDhisAssignmentRepository, @Nonnull ScriptExecutionContext scriptExecutionContext, @Nonnull ValueConverter valueConverter ) { - super( scriptExecutor, organizationUnitService, new StaticObjectProvider<>( trackedEntityMetadataService ), new StaticObjectProvider<>( trackedEntityService ), - fhirDhisAssignmentRepository, scriptExecutionContext, valueConverter ); - - this.programMetadataService = programMetadataService; - this.enrollmentService = enrollmentService; - this.trackedEntityMetadataService = trackedEntityMetadataService; - this.trackedEntityRuleRepository = trackedEntityRuleRepository; - this.resourceMappingRepository = resourceMappingRepository; - this.scriptExecutionContext = scriptExecutionContext; - this.valueConverter = valueConverter; + super( scriptExecutor, trackedEntityMetadataService, trackedEntityService, trackedEntityRuleRepository, organizationUnitService, programMetadataService, enrollmentService, resourceMappingRepository, fhirDhisAssignmentRepository, + scriptExecutionContext, valueConverter ); } @Nonnull @@ -139,13 +108,6 @@ protected boolean isSyncRequired( @Nonnull FhirToDhisTransformerContext context, return false; } - @Override - @Nonnull - protected Optional getResourceById( String id ) throws TransformerException - { - return ( id == null ) ? Optional.empty() : enrollmentService.findOneById( id ); - } - @Override @Nonnull protected Optional getActiveResource( @Nonnull FhirToDhisTransformerContext context, @Nonnull RuleInfo ruleInfo, @Nonnull Map scriptVariables, boolean sync, boolean refreshed ) throws TransformerException @@ -156,13 +118,6 @@ protected Optional getActiveResource( @Nonnull FhirToDhisTransformer return enrollmentService.findLatestActive( program.getId(), Objects.requireNonNull( trackedEntityInstance.getId() ), trackedEntityInstance.isLocal() ); } - @Override - @Nonnull - protected Optional findResourceById( @Nonnull FhirToDhisTransformerContext context, @Nonnull RuleInfo ruleInfo, @Nonnull String id, @Nonnull Map scriptVariables ) - { - return enrollmentService.findOneById( id ); - } - @Override protected Enrollment createResource( @Nonnull FhirToDhisTransformerContext context, @Nonnull RuleInfo ruleInfo, String id, @Nonnull Map scriptVariables, boolean sync, boolean refreshed ) throws TransformerException { @@ -196,38 +151,19 @@ protected Enrollment createResource( @Nonnull FhirToDhisTransformerContext conte return enrollment; } - @Override - @Nonnull - public DhisResourceType getDhisResourceType() - { - return DhisResourceType.ENROLLMENT; - } - - @Override - @Nonnull - public Class getDhisResourceClass() - { - return Enrollment.class; - } - - @Override - @Nonnull - public Class getRuleClass() - { - return EnrollmentRule.class; - } - @Override public FhirToDhisTransformOutcome transform( @Nonnull FhirClientResource fhirClientResource, @Nonnull FhirToDhisTransformerContext context, @Nonnull IBaseResource input, @Nonnull RuleInfo ruleInfo, @Nonnull Map scriptVariables ) throws TransformerException { - final Map variables = new HashMap<>( scriptVariables ); - - if ( !addBasicScriptVariables( context, ruleInfo, variables ) ) + if ( ruleInfo.getRule().getProgramRefLookupScript() == null ) { return null; } + final Map variables = new HashMap<>( scriptVariables ); + + addBasicScriptVariables( context, ruleInfo, variables, input ); + final RuleInfo trackedEntityRuleInfo = getTrackedEntityRuleInfo( context, ruleInfo, scriptVariables, TransformerUtils.getScriptVariable( variables, ScriptVariable.PROGRAM, Program.class ), TransformerUtils.getScriptVariable( variables, ScriptVariable.TRACKED_ENTITY_TYPE, TrackedEntityType.class ) ); @@ -267,51 +203,6 @@ public FhirToDhisTransformOutcome transform( @Nonnull FhirClientReso return new FhirToDhisTransformOutcome<>( ruleInfo.getRule(), enrollment, enrollment.isNewResource() ); } - @Override - public FhirToDhisDeleteTransformOutcome transformDeletion( @Nonnull FhirClientResource fhirClientResource, @Nonnull RuleInfo ruleInfo, @Nonnull DhisFhirResourceId dhisFhirResourceId ) throws TransformerException - { - final Enrollment enrollment = new Enrollment(); - enrollment.setId( dhisFhirResourceId.getId() ); - - return new FhirToDhisDeleteTransformOutcome<>( ruleInfo.getRule(), enrollment, true ); - } - - protected boolean addBasicScriptVariables( @Nonnull FhirToDhisTransformerContext context, @Nonnull RuleInfo ruleInfo, @Nonnull Map scriptVariables ) throws TransformerException - { - final Program program = getProgram( context, ruleInfo, scriptVariables ); - scriptVariables.put( ScriptVariable.PROGRAM.getVariableName(), program ); - - final TrackedEntityAttributes attributes = trackedEntityMetadataService.getAttributes(); - scriptVariables.put( ScriptVariable.TRACKED_ENTITY_ATTRIBUTES.getVariableName(), attributes ); - - final TrackedEntityType trackedEntityType = getTrackedEntityType( context, ruleInfo, scriptVariables, program ); - scriptVariables.put( ScriptVariable.TRACKED_ENTITY_TYPE.getVariableName(), trackedEntityType ); - - return true; - } - - protected void addScriptVariables( @Nonnull FhirToDhisTransformerContext context, @Nonnull Map variables, @Nonnull RuleInfo ruleInfo, - @Nonnull RuleInfo trackedEntityRuleRuleInfo, @Nonnull IdentifiedTrackedEntityInstance trackedEntityInstance ) throws TransformerException - { - variables.put( ScriptVariable.TRACKED_ENTITY_RESOURCE_TYPE.getVariableName(), trackedEntityRuleRuleInfo.getRule().getFhirResourceType() ); - addTrackedEntityScriptVariables( context, ruleInfo, trackedEntityInstance, variables ); - } - - @Nonnull - protected FhirResourceMapping getResourceMapping( @Nonnull RuleInfo ruleInfo, @Nonnull FhirResourceType trackedEntityFhirResourceType ) - { - return resourceMappingRepository.findOneByFhirResourceType( ruleInfo.getRule().getFhirResourceType(), trackedEntityFhirResourceType ) - .orElseThrow( () -> new TransformerMappingException( "No FHIR resource mapping has been defined for " + ruleInfo.getRule().getFhirResourceType() + - " and tracked entity FHIR resource " + trackedEntityFhirResourceType + "." ) ); - } - - @Override - protected boolean isAlwaysActiveResource( @Nonnull RuleInfo ruleInfo ) - { - // not use for currently supported use case (method is not invoked) - return false; - } - @Nullable protected ZonedDateTime getEnrollmentDate( @Nonnull FhirToDhisTransformerContext context, @Nonnull RuleInfo ruleInfo, @Nonnull FhirResourceMapping resourceMapping, @Nonnull Program program, @Nonnull Map scriptVariables ) { @@ -347,7 +238,8 @@ protected ZonedDateTime getEnrollmentDate( @Nonnull FhirToDhisTransformerContext } @Nonnull - protected Program getProgram( @Nonnull FhirToDhisTransformerContext context, @Nonnull RuleInfo ruleInfo, @Nonnull Map scriptVariables ) + @Override + protected Reference getProgramRef( @Nonnull FhirToDhisTransformerContext context, @Nonnull RuleInfo ruleInfo, @Nonnull Map scriptVariables, @Nonnull IBaseResource carePlan ) { final Reference programRef = executeScript( context, ruleInfo, ruleInfo.getRule().getProgramRefLookupScript(), scriptVariables, Reference.class ); @@ -356,47 +248,6 @@ protected Program getProgram( @Nonnull FhirToDhisTransformerContext context, @No throw new TransformerDataException( "FHIR resource does not contain a a reference to a tracker program." ); } - final Program program = programMetadataService.findMetadataByReference( programRef ).orElse( null ); - - if ( program == null ) - { - throw new TransformerDataException( "Tracker program \"" + programRef + "\" does not exist." ); - } - - if ( !program.isRegistration() ) - { - throw new TransformerDataException( "Tracker program \"" + programRef + "\" does not require registration." ); - } - - return program; - } - - @Nonnull - protected TrackedEntityType getTrackedEntityType( @Nonnull FhirToDhisTransformerContext context, @Nonnull RuleInfo ruleInfo, @Nonnull Map scriptVariables, - @Nonnull Program program ) - { - final TrackedEntityType trackedEntityType = trackedEntityMetadataService.findTypeByReference( Reference.createIdReference( program.getTrackedEntityTypeId() ) ).orElse( null ); - - if ( trackedEntityType == null ) - { - throw new TransformerMappingException( "Tracked entity type " + program.getTrackedEntityTypeId() + " of tracker program " + program.getId() + " does not exist." ); - } - - return trackedEntityType; - } - - @Nonnull - protected RuleInfo getTrackedEntityRuleInfo( @Nonnull FhirToDhisTransformerContext context, @Nonnull RuleInfo ruleInfo, @Nonnull Map scriptVariables, - @Nonnull Program program, @Nonnull TrackedEntityType trackedEntityType ) - { - final TrackedEntityRule trackedEntityRule = trackedEntityRuleRepository.findByTypeRefs( trackedEntityType.getAllReferences() ) - .stream().findFirst().orElse( null ); - - if ( trackedEntityRule == null ) - { - throw new TransformerMappingException( "Tracked entity type " + program.getTrackedEntityTypeId() + " is not associated with a tracked entity rule." ); - } - - return new RuleInfo<>( trackedEntityRule, Collections.emptyList() ); + return programRef; } } diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/program/FhirToProgramStageTransformer.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/program/FhirToProgramStageTransformer.java index 28850c15..d1ee066c 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/program/FhirToProgramStageTransformer.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/program/FhirToProgramStageTransformer.java @@ -253,7 +253,7 @@ public FhirToDhisTransformOutcome transform( @Nonnull FhirClientResource } final WritableScriptedEvent scriptedEvent = new WritableScriptedEvent( - context, program, programStage, event, scriptedTrackedEntityInstance, valueConverter ); + context, program, programStage, event, scriptedTrackedEntityInstance, scriptExecutionContext, valueConverter ); variables.put( ScriptVariable.OUTPUT.getVariableName(), scriptedEvent ); updateEventDate( context, ruleInfo, resourceMapping, event.getEnrollment(), programStage, event, variables ); @@ -484,7 +484,7 @@ private Optional getExistingResource( @Nonnull FhirToDhisTransformerConte if ( ruleInfo.getRule().getProgramStage().getBeforeScript() != null ) { variables.get().put( ScriptVariable.EVENT.getVariableName(), new WritableScriptedEvent( - context, eventInfo.getProgram(), eventInfo.getProgramStage(), event, scriptedTrackedEntityInstance, valueConverter ) ); + context, eventInfo.getProgram(), eventInfo.getProgramStage(), event, scriptedTrackedEntityInstance, scriptExecutionContext, valueConverter ) ); variables.get().put( ScriptVariable.DATE_TIME.getVariableName(), getEffectiveDate( context, ruleInfo, resourceMapping.get(), variables.get() ) ); final Optional orgUnit = getEventOrgUnit( context, ruleInfo, resourceMapping.get(), enrollment, variables.get() ); variables.get().put( ScriptVariable.ORGANIZATION_UNIT_ID.getVariableName(), orgUnit.map( OrganizationUnit::getId ).orElse( null ) ); @@ -585,7 +585,7 @@ protected Event createResource( @Nonnull FhirToDhisTransformerContext context, @ final ScriptedTrackedEntityInstance scriptedTrackedEntityInstance = TransformerUtils.getScriptVariable( scriptVariables, ScriptVariable.TRACKED_ENTITY_INSTANCE, ScriptedTrackedEntityInstance.class ); final WritableScriptedEvent scriptedEvent = new WritableScriptedEvent( - context, eventInfo.getProgram(), eventInfo.getProgramStage(), event, scriptedTrackedEntityInstance, valueConverter ); + context, eventInfo.getProgram(), eventInfo.getProgramStage(), event, scriptedTrackedEntityInstance, scriptExecutionContext, valueConverter ); variables.put( ScriptVariable.EVENT.getVariableName(), scriptedEvent ); final ZonedDateTime eventDate; @@ -840,7 +840,8 @@ protected List createScriptedProgramStageEvents( @Nonnull } return events.stream().filter( e -> programStage.getId().equals( e.getProgramStageId() ) ).sorted( new EventComparator() ) - .map( e -> new WritableScriptedEvent( transformerContext, program, programStage, e, scriptedTrackedEntityInstance, valueConverter ) ).collect( Collectors.toList() ); + .map( e -> new WritableScriptedEvent( transformerContext, program, programStage, e, scriptedTrackedEntityInstance, scriptExecutionContext, valueConverter ) ) + .collect( Collectors.toList() ); } protected boolean initAndValidateTrackedEntity( @Nonnull Program program, @Nonnull Map variables ) diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/AbstractFhirResourceFhirToDhisTransformerUtils.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/AbstractFhirResourceFhirToDhisTransformerUtils.java index 747fd709..daba5b3f 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/AbstractFhirResourceFhirToDhisTransformerUtils.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/AbstractFhirResourceFhirToDhisTransformerUtils.java @@ -43,6 +43,7 @@ import org.dhis2.fhir.adapter.fhir.transform.fhir.FhirToDhisTransformerContext; import org.dhis2.fhir.adapter.fhir.transform.fhir.model.ResourceSystem; import org.dhis2.fhir.adapter.fhir.transform.scripted.TransformerScriptException; +import org.dhis2.fhir.adapter.fhir.util.FhirUriUtils; import org.dhis2.fhir.adapter.scriptable.ScriptMethod; import org.dhis2.fhir.adapter.scriptable.ScriptMethodArg; import org.dhis2.fhir.adapter.scriptable.ScriptTransformType; @@ -51,6 +52,8 @@ import org.dhis2.fhir.adapter.util.EnumValueUtils; import org.dhis2.fhir.adapter.util.NameUtils; import org.hl7.fhir.instance.model.api.IBaseDatatype; +import org.hl7.fhir.instance.model.api.IBaseExtension; +import org.hl7.fhir.instance.model.api.IBaseHasExtensions; import org.hl7.fhir.instance.model.api.IBaseReference; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IIdType; @@ -60,8 +63,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import java.util.stream.Collectors; /** @@ -78,8 +79,6 @@ public abstract class AbstractFhirResourceFhirToDhisTransformerUtils extends Abs protected static final String INTERNAL_REFERENCE_BEGIN = "urn:"; - protected final Pattern CANONICAL_PATTERN = Pattern.compile( "([^/]+)/([^/]+)" ); - private final ReferenceFhirToDhisTransformerUtils referenceUtils; private final SystemCodeRepository systemCodeRepository; @@ -277,24 +276,17 @@ public Reference getCanonicalAdapterReference( @Nonnull FhirToDhisTransformerCon return null; } - final Matcher canonicalMatcher = CANONICAL_PATTERN.matcher( canonicalUri ); - - if ( !canonicalMatcher.matches() ) + final IIdType canonicalId; + try { - throw new TransformerDataException( "Unhandled canonical URI: " + canonicalUri ); + canonicalId = FhirUriUtils.createIdFromUri( canonicalUri, null ); } - - final String type = canonicalMatcher.group( 1 ); - final String id = canonicalMatcher.group( 2 ); - - final FhirResourceType canonicalResourceType = FhirResourceType.getByResourceTypeName( type ); - - if ( canonicalResourceType == null ) + catch ( IllegalArgumentException e ) { - throw new TransformerDataException( "Unknown FHIR resource type in canonical URI: " + type ); + throw new TransformerDataException( e.getMessage(), e ); } - return getAdapterReference( context, createReference( canonicalResourceType.getResourceTypeName(), id ), fhirResourceType ); + return getAdapterReference( context, createReference( canonicalId.getResourceType(), canonicalId.getIdPart() ), fhirResourceType ); } @Nullable @@ -428,6 +420,27 @@ public > T resolveEnumValue( @Nonnull Object object, @Nonnull return EnumValueUtils.resolveEnumValue( object, propertyPath, enumValueName ); } + @ScriptMethod( description = "Returns if the specified resource contains the extension with the specified URL.", returnDescription = "If the specified resource contains the extension with the specified URL.", + args = { + @ScriptMethodArg( value = "resource", description = "The resource that should be checked." ), + @ScriptMethodArg( value = "url", description = "The URL that should be checked." ) + } ) + public boolean hasExtension( @Nonnull IBaseHasExtensions resource, @Nonnull String url ) + { + return resource.getExtension().stream().anyMatch( e -> url.equals( e.getUrl() ) ); + } + + @Nullable + @ScriptMethod( description = "Returns the value of the extension with the specified URL from the specified resource.", returnDescription = "Returns the value of the extension or null if the resource has no such extension.", + args = { + @ScriptMethodArg( value = "resource", description = "The resource from which the value should be returned." ), + @ScriptMethodArg( value = "url", description = "The URL for which the extension value should be returned." ) + } ) + public IBaseDatatype getExtensionValue( @Nonnull IBaseHasExtensions resource, @Nonnull String url ) + { + return resource.getExtension().stream().filter( e -> url.equals( e.getUrl() ) ).findFirst().map( IBaseExtension::getValue ).orElse( null ); + } + @Nonnull protected abstract IBaseReference createReference( @Nullable IIdType id ); diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/ReferenceFhirToDhisTransformerUtils.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/ReferenceFhirToDhisTransformerUtils.java index 42c8fa0f..5d737a49 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/ReferenceFhirToDhisTransformerUtils.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/ReferenceFhirToDhisTransformerUtils.java @@ -85,6 +85,7 @@ public ReferenceFhirToDhisTransformerUtils( @Nonnull ScriptExecutionContext scri @Nonnull FhirResourceRepository fhirResourceRepository ) { super( scriptExecutionContext ); + this.fhirClientResourceRepository = fhirClientResourceRepository; this.fhirResourceRepository = fhirResourceRepository; } @@ -143,6 +144,7 @@ public IBaseResource getResource( @Nullable IBaseReference reference, @Nullable } final FhirResourceType fhirResourceType; + if ( resourceType == null ) { fhirResourceType = null; @@ -165,8 +167,10 @@ public IBaseResource getResource( @Nullable IBaseReference reference, @Nullable { logger.debug( "The referenced resource ID contains resource type {}, but requested resource type is {}.", FhirResourceType.getByResource( reference.getResource() ), fhirResourceType ); + return null; } + // also handles the case of a local reference return reference.getResource(); } diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/ImmutableScriptedEnrollment.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/ImmutableScriptedEnrollment.java index eed9e055..84a3a85f 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/ImmutableScriptedEnrollment.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/ImmutableScriptedEnrollment.java @@ -28,7 +28,6 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -import com.fasterxml.jackson.annotation.JsonIgnore; import org.dhis2.fhir.adapter.dhis.model.ImmutableDhisObject; import org.dhis2.fhir.adapter.geo.Location; import org.dhis2.fhir.adapter.scriptable.Scriptable; @@ -53,14 +52,12 @@ public ImmutableScriptedEnrollment( @Nonnull WritableScriptedEnrollment delegate super( delegate ); } - @JsonIgnore @Nonnull protected ScriptedEnrollment getInternalDelegate() { return (ScriptedEnrollment) super.getDelegate(); } - @JsonIgnore @Override @Nullable public ZonedDateTime getEnrollmentDate() @@ -68,7 +65,6 @@ public ZonedDateTime getEnrollmentDate() return getInternalDelegate().getEnrollmentDate(); } - @JsonIgnore @Override @Nullable public ZonedDateTime getIncidentDate() @@ -76,7 +72,6 @@ public ZonedDateTime getIncidentDate() return getInternalDelegate().getIncidentDate(); } - @JsonIgnore @Override @Nullable public Location getCoordinate() @@ -84,7 +79,6 @@ public Location getCoordinate() return getInternalDelegate().getCoordinate(); } - @JsonIgnore @Nullable @Override public String getProgramId() diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/ImmutableScriptedEvent.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/ImmutableScriptedEvent.java index fac1c7c0..b6f767a3 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/ImmutableScriptedEvent.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/ImmutableScriptedEvent.java @@ -29,8 +29,6 @@ */ -import org.dhis2.fhir.adapter.dhis.model.DhisResourceId; -import org.dhis2.fhir.adapter.dhis.model.DhisResourceType; import org.dhis2.fhir.adapter.dhis.model.ImmutableDhisObject; import org.dhis2.fhir.adapter.dhis.model.Reference; import org.dhis2.fhir.adapter.dhis.tracker.program.EventStatus; @@ -55,195 +53,147 @@ * @author volsch */ @Scriptable -public class ImmutableScriptedEvent implements ScriptedEvent, ImmutableDhisObject, Serializable +public class ImmutableScriptedEvent extends ImmutableScriptedDhisResource implements ScriptedEvent, ImmutableDhisObject, Serializable { private static final long serialVersionUID = -3248712035742910069L; - private final ScriptedEvent delegate; - - public ImmutableScriptedEvent( @Nonnull ScriptedEvent delegate ) - { - this.delegate = delegate; - } - - @Override - public boolean isNewResource() - { - return delegate.isNewResource(); - } - - @Override - public boolean isLocal() - { - return delegate.isLocal(); - } - - @Override - public boolean isDeleted() - { - return delegate.isDeleted(); - } - - @Nullable - @Override - public String getId() + public ImmutableScriptedEvent( @Nonnull WritableScriptedEvent delegate ) { - return delegate.getId(); + super( delegate ); } - @Override @Nonnull - public DhisResourceType getResourceType() + protected ScriptedEvent getInternalDelegate() { - return delegate.getResourceType(); - } - - @Nullable - @Override - public DhisResourceId getResourceId() - { - return delegate.getResourceId(); - } - - @Nullable - @Override - public ZonedDateTime getLastUpdated() - { - return delegate.getLastUpdated(); - } - - @Nullable - @Override - public String getOrganizationUnitId() - { - return delegate.getOrganizationUnitId(); + return (ScriptedEvent) super.getDelegate(); } @Nullable @Override public String getEnrollmentId() { - return delegate.getEnrollmentId(); + return getInternalDelegate().getEnrollmentId(); } @Override @Nonnull public Program getProgram() { - return delegate.getProgram(); + return getInternalDelegate().getProgram(); } @Nonnull @Override public ProgramStage getProgramStage() { - return delegate.getProgramStage(); + return getInternalDelegate().getProgramStage(); } @Nullable @Override public ScriptedTrackedEntityInstance getTrackedEntityInstance() { - if ( delegate.getTrackedEntityInstance() instanceof ImmutableDhisObject ) + if ( getInternalDelegate().getTrackedEntityInstance() instanceof ImmutableDhisObject ) { - return delegate.getTrackedEntityInstance(); + return getInternalDelegate().getTrackedEntityInstance(); } - return new ImmutableScriptedTrackedEntityInstance( Objects.requireNonNull( delegate.getTrackedEntityInstance() ) ); + + return new ImmutableScriptedTrackedEntityInstance( Objects.requireNonNull( getInternalDelegate().getTrackedEntityInstance() ) ); } @Nullable @Override public ZonedDateTime getEventDate() { - return delegate.getEventDate(); + return getInternalDelegate().getEventDate(); } @Override @Nullable public ZonedDateTime getDueDate() { - return delegate.getDueDate(); + return getInternalDelegate().getDueDate(); } @Nullable @Override public EventStatus getStatus() { - return delegate.getStatus(); + return getInternalDelegate().getStatus(); } @Override @Nullable public Location getCoordinate() { - return delegate.getCoordinate(); + return getInternalDelegate().getCoordinate(); } @Nullable @Override public Object getValue( @Nonnull Reference dataElementReference ) { - return delegate.getValue( dataElementReference ); + return getInternalDelegate().getValue( dataElementReference ); } @Nullable @Override public Boolean getBooleanValue( @Nonnull Reference dataElementReference ) { - return delegate.getBooleanValue( dataElementReference ); + return getInternalDelegate().getBooleanValue( dataElementReference ); } @Nullable @Override public Integer getIntegerValue( @Nonnull Reference dataElementReference ) { - return delegate.getIntegerValue( dataElementReference ); + return getInternalDelegate().getIntegerValue( dataElementReference ); } @Nullable @Override public BigDecimal getBigDecimalValue( @Nonnull Reference dataElementReference ) { - return delegate.getBigDecimalValue( dataElementReference ); + return getInternalDelegate().getBigDecimalValue( dataElementReference ); } @Nullable @Override public ZonedDateTime getDateTimeValue( @Nonnull Reference dataElementReference ) { - return delegate.getDateTimeValue( dataElementReference ); + return getInternalDelegate().getDateTimeValue( dataElementReference ); } @Nullable @Override public LocalDate getDateValue( @Nonnull Reference dataElementReference ) { - return delegate.getDateValue( dataElementReference ); + return getInternalDelegate().getDateValue( dataElementReference ); } @Nullable @Override public String getStringValue( @Nonnull Reference dataElementReference ) { - return delegate.getStringValue( dataElementReference ); + return getInternalDelegate().getStringValue( dataElementReference ); } @Nullable @Override public Integer getIntegerOptionValue( @Nonnull Reference dataElementReference, int valueBase, @Nullable Pattern optionValuePattern ) { - return delegate.getIntegerOptionValue( dataElementReference, valueBase, optionValuePattern ); + return getInternalDelegate().getIntegerOptionValue( dataElementReference, valueBase, optionValuePattern ); } @Override public boolean isProvidedElsewhere( @Nonnull Reference dataElementReference ) { - return delegate.isProvidedElsewhere( dataElementReference ); + return getInternalDelegate().isProvidedElsewhere( dataElementReference ); } @Override public void validate() throws TransformerException { - delegate.validate(); + getInternalDelegate().validate(); } } diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/ScriptedEvent.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/ScriptedEvent.java index bb65c24d..edaef2ba 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/ScriptedEvent.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/ScriptedEvent.java @@ -48,7 +48,7 @@ * @author volsch */ @Scriptable -public interface ScriptedEvent extends ScriptedDhisResource +public interface ScriptedEvent extends AccessibleScriptedDhisResource { @Nonnull Program getProgram(); diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/WritableScriptedEvent.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/WritableScriptedEvent.java index 1123fd08..20bdb088 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/WritableScriptedEvent.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/WritableScriptedEvent.java @@ -32,8 +32,6 @@ import org.apache.commons.lang3.StringUtils; import org.dhis2.fhir.adapter.converter.ConversionException; import org.dhis2.fhir.adapter.dhis.converter.ValueConverter; -import org.dhis2.fhir.adapter.dhis.model.DhisResourceId; -import org.dhis2.fhir.adapter.dhis.model.DhisResourceType; import org.dhis2.fhir.adapter.dhis.model.Reference; import org.dhis2.fhir.adapter.dhis.model.WritableDataValue; import org.dhis2.fhir.adapter.dhis.tracker.program.Event; @@ -41,6 +39,7 @@ import org.dhis2.fhir.adapter.dhis.tracker.program.Program; import org.dhis2.fhir.adapter.dhis.tracker.program.ProgramStage; import org.dhis2.fhir.adapter.dhis.tracker.program.ProgramStageDataElement; +import org.dhis2.fhir.adapter.fhir.script.ScriptExecutionContext; import org.dhis2.fhir.adapter.fhir.transform.TransformerContext; import org.dhis2.fhir.adapter.fhir.transform.TransformerException; import org.dhis2.fhir.adapter.fhir.transform.TransformerMappingException; @@ -72,7 +71,7 @@ @Scriptable @ScriptType( value = "Event", var = "event", transformDataType = "DHIS_EVENT", description = "Program stage instance (aka event). If event is not new and will be modified, it will be persisted." ) -public class WritableScriptedEvent implements ScriptedEvent, Serializable +public class WritableScriptedEvent extends WritableScriptedDhisResource implements AccessibleScriptedDhisResource, ScriptedEvent, Serializable { private static final long serialVersionUID = 3407593545422372222L; @@ -88,14 +87,17 @@ public class WritableScriptedEvent implements ScriptedEvent, Serializable private final ValueConverter valueConverter; - public WritableScriptedEvent( @Nonnull Program program, @Nonnull ProgramStage programStage, @Nonnull Event event, @Nullable ScriptedTrackedEntityInstance trackedEntityInstance, @Nonnull ValueConverter valueConverter ) + public WritableScriptedEvent( @Nonnull Program program, @Nonnull ProgramStage programStage, @Nonnull Event event, @Nullable ScriptedTrackedEntityInstance trackedEntityInstance, + @Nonnull ScriptExecutionContext scriptExecutionContext, @Nonnull ValueConverter valueConverter ) { - this( null, program, programStage, event, trackedEntityInstance, valueConverter ); + this( null, program, programStage, event, trackedEntityInstance, scriptExecutionContext, valueConverter ); } public WritableScriptedEvent( @Nullable TransformerContext transformerContext, @Nonnull Program program, @Nonnull ProgramStage programStage, @Nonnull Event event, @Nullable ScriptedTrackedEntityInstance trackedEntityInstance, - @Nonnull ValueConverter valueConverter ) + @Nonnull ScriptExecutionContext scriptExecutionContext, @Nonnull ValueConverter valueConverter ) { + super( event, scriptExecutionContext ); + this.transformerContext = transformerContext; this.program = program; this.programStage = programStage; @@ -104,63 +106,6 @@ public WritableScriptedEvent( @Nullable TransformerContext transformerContext, @ this.valueConverter = valueConverter; } - @Override - @ScriptMethod( description = "Returns if the event is new ans has not yet been saved on DHIS2." ) - public boolean isNewResource() - { - return event.isNewResource(); - } - - @Override - public boolean isLocal() - { - return event.isLocal(); - } - - @Override - public boolean isDeleted() - { - return event.isDeleted(); - } - - @Nullable - @Override - @ScriptMethod( description = "Returns the ID of the event on DHIS2. Return null if the instance is new." ) - public String getId() - { - return event.getId(); - } - - @Nonnull - @Override - public DhisResourceType getResourceType() - { - return event.getResourceType(); - } - - @Nullable - @Override - public DhisResourceId getResourceId() - { - return event.getResourceId(); - } - - @Nullable - @Override - @ScriptMethod( description = "Returns the date and time when the resource has been updated the last time or null if this is a new resource." ) - public ZonedDateTime getLastUpdated() - { - return event.getLastUpdated(); - } - - @Nullable - @Override - @ScriptMethod( description = "Returns the ID of the organisation unit on DHIS2 where this event has been registered." ) - public String getOrganizationUnitId() - { - return event.getOrgUnitId(); - } - @Nullable @Override @ScriptMethod( description = "Returns the ID of the enrollment on DHIS2 to which this event belongs to." ) @@ -227,11 +172,14 @@ public ZonedDateTime getDueDate() public boolean setDueDate( @Nullable Object dueDate ) { final ZonedDateTime zonedDateTime = ScriptedDateTimeUtils.toZonedDateTime( dueDate, valueConverter ); + if ( !Objects.equals( event.getDueDate(), zonedDateTime ) ) { event.setModified( true ); } + event.setDueDate( zonedDateTime ); + return (dueDate != null); } @@ -257,11 +205,14 @@ public boolean setStatus( @Nullable Object status ) { throw new TransformerScriptException( "Event status has not been defined: " + status, e ); } + if ( !Objects.equals( event.getStatus(), convertedStatus ) ) { event.setModified( true ); } + event.setStatus( convertedStatus ); + return true; } @@ -279,11 +230,14 @@ public Location getCoordinate() public boolean setCoordinate( @Nullable Object coordinate ) { final Location convertedCoordinate = valueConverter.convert( coordinate, ValueType.COORDINATE, Location.class ); + if ( !Objects.equals( event.getCoordinate(), convertedCoordinate ) ) { event.setModified( true ); } + event.setCoordinate( convertedCoordinate ); + return true; } @@ -294,6 +248,7 @@ public boolean isProvidedElsewhere( @Nonnull Reference dataElementReference ) { final ProgramStageDataElement dataElement = getProgramStageDataElement( dataElementReference ); final WritableDataValue dataValue = getDataValue( dataElement ); + return dataValue.isProvidedElsewhere(); } @@ -305,6 +260,7 @@ public Object getValue( @Nonnull Reference dataElementReference ) { final ProgramStageDataElement dataElement = getProgramStageDataElement( dataElementReference ); final WritableDataValue dataValue = getDataValue( dataElement ); + return dataValue.getValue(); } diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/util/FhirUriUtils.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/util/FhirUriUtils.java new file mode 100644 index 00000000..663645bb --- /dev/null +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/util/FhirUriUtils.java @@ -0,0 +1,84 @@ +package org.dhis2.fhir.adapter.fhir.util; + +/* + * Copyright (c) 2004-2019, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import ca.uhn.fhir.model.primitive.IdDt; +import org.dhis2.fhir.adapter.fhir.metadata.model.FhirResourceType; +import org.hl7.fhir.instance.model.api.IIdType; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Utility class that handles FHIR URIs. + * + * @author volsch + */ +public abstract class FhirUriUtils +{ + protected static final Pattern CANONICAL_PATTERN = Pattern.compile( "(?:([^/]+)/)?([^/]+)" ); + + @Nonnull + public static IIdType createIdFromUri( @Nonnull String uri, @Nullable FhirResourceType fhirResourceType ) throws IllegalArgumentException + { + final Matcher matcher = CANONICAL_PATTERN.matcher( uri ); + + if ( !matcher.matches() ) + { + throw new IllegalArgumentException( "URI is invalid: " + uri ); + } + + String resourceTypeName = matcher.group( 1 ); + final String id = matcher.group( 2 ); + + if ( resourceTypeName == null && fhirResourceType != null ) + { + resourceTypeName = fhirResourceType.getResourceTypeName(); + } + + if ( resourceTypeName == null ) + { + throw new IllegalArgumentException( "URI must include a valid FHIR resource type: " + uri ); + } + + if ( fhirResourceType != null && !fhirResourceType.getResourceTypeName().equals( resourceTypeName ) ) + { + throw new IllegalArgumentException( "Resource type in URI differs from expected resource type " + fhirResourceType + ": " + uri ); + } + + return new IdDt( resourceTypeName, id ); + } + + private FhirUriUtils() + { + super(); + } +} diff --git a/fhir/src/main/resources/db/migration/production/V1.1.0.45_0_0__Care_Resources_Read.sql b/fhir/src/main/resources/db/migration/production/V1.1.0.45_0_0__Care_Resources_Read.sql index 4c62666f..7a5a22c8 100644 --- a/fhir/src/main/resources/db/migration/production/V1.1.0.45_0_0__Care_Resources_Read.sql +++ b/fhir/src/main/resources/db/migration/production/V1.1.0.45_0_0__Care_Resources_Read.sql @@ -30,3 +30,209 @@ UPDATE fhir_rule SET exp_enabled=TRUE WHERE id='c4e17e7d-880e-45b5-9bc5-568da8c79742'; ALTER TABLE fhir_program_stage_rule ALTER COLUMN program_stage_id DROP NOT NULL; + +INSERT INTO fhir_rule(id, version, fhir_resource_type, dhis_resource_type, name, description, enabled, imp_enabled, exp_enabled, contained_allowed, fhir_create_enabled, fhir_update_enabled, fhir_delete_enabled, grouping, evaluation_order, simple_fhir_id) +VALUES('e54a6c5a-ef9a-4bcf-b911-29b8b857f58c', 0, 'QUESTIONNAIRE_RESPONSE', 'PROGRAM_STAGE_EVENT', 'Default FHIR Questionnaire Response to DHIS2 Program Stage', 'Default rule that transforms a FHIR Questionnaire Response to a DHIS2 Program Stage.', +true, true, true, false, true, true, true, false, -2147483648, true); +INSERT INTO fhir_program_stage_rule(id) VALUES ('e54a6c5a-ef9a-4bcf-b911-29b8b857f58c'); + +ALTER TABLE fhir_enrollment_rule ALTER COLUMN program_ref_lookup_script_id DROP NOT NULL; + +UPDATE fhir_enrollment_rule SET program_ref_lookup_script_id=NULL WHERE id='c4e17e7d-880e-45b5-9bc5-568da8c79742' AND EXISTS +(SELECT 1 from fhir_rule WHERE id='c4e17e7d-880e-45b5-9bc5-568da8c79742' AND version=0); +UPDATE fhir_rule SET transform_imp_script_id=NULL WHERE id='c4e17e7d-880e-45b5-9bc5-568da8c79742' AND version=0; + +UPDATE fhir_script_source SET source_text= +'function getCodeFromHierarchy(hierarchy, resourceType, resourceRef) +{ + var mappedCode = null; + if (hierarchy != null) + { + for (var i = 0; (mappedCode == null) && (i < hierarchy.size()); i++) + { + var code = identifierUtils.getResourceIdentifier(hierarchy.get(i), resourceType); + if (code != null) + { + mappedCode = codeUtils.getMappedCode(code, resourceType); + if ((mappedCode == null) && args[''useIdentifierCode'']) + { + mappedCode = organizationUtils.existsWithPrefix(code); + } + } + } + } + return mappedCode; +} +function getOrganizationUnitMappedCode(organizationReference) +{ + var mappedCode = null; + if (organizationReference != null) + { + var hierarchy = organizationUtils.findHierarchy(organizationReference); + mappedCode = getCodeFromHierarchy(hierarchy, ''Organization'', organizationReference); + } + return mappedCode; +} +function getLocationMappedCode(locationReference) +{ + var mappedCode = null; + if (locationReference != null) + { + var hierarchy = locationUtils.findHierarchy(locationReference); + if (hierarchy != null) + { + getCodeFromHierarchy(hierarchy, ''Location'', locationReference); + for (var i = 0; (mappedCode == null) && (i < hierarchy.size()); i++) + { + var organizationReference = hierarchy.get(i).getManagingOrganization(); + if (organizationReference != null) + { + mappedCode = getOrganizationUnitMappedCode(organizationReference); + } + } + } + } + return mappedCode; +} +var fhirOrgUnitRef = null; +var fhirOrgUnitType = null; +if (fhirResourceUtils.hasExtension(input, ''http://www.dhis2.org/dhis2-fhir-adapter/fhir/extensions/location'')) +{ + fhirOrgUnitRef = fhirResourceUtils.getExtensionValue(input, ''http://www.dhis2.org/dhis2-fhir-adapter/fhir/extensions/location''); +if (fhirOrgUnitRef && fhirOrgUnitRef.fhirType() == ''Reference'') + { + fhirOrgUnitType = ''Location''; + } + else + { + fhirOrgUnitRef = null; + } +} +else if (input.managingOrganization) +{ + fhirOrgUnitRef = input.managingOrganization; + fhirOrgUnitType = ''Organization''; +} +else if ( (typeof input.locationFirstRep !== ''undefined'') && (typeof input.locationFirstRep.location !== ''undefined'') ) +{ + fhirOrgUnitRef = input.locationFirstRep.location; + fhirOrgUnitType = ''Location''; +} +else if (input.location) +{ + fhirOrgUnitRef = input.location; + fhirOrgUnitType = ''Location''; +} +else if (input.performer && typeof input.getPerformerFirstRep() !== ''undefined'' && !input.getPerformerFirstRep().isEmpty() && (input.getPerformerFirstRep().getReferenceElement().getResourceType() == null || input.getPerformerFirstRep().getReferenceElement().getResourceType() == ''Organization'')) +{ + fhirOrgUnitRef = input.getPerformerFirstRep(); + fhirOrgUnitType = input.getPerformerFirstRep().getReferenceElement().getResourceType(); + if (fhirOrgUnitType == null) + { + fhirOrgUnitType = ''Organization''; + } +} +else if (input.performer && typeof input.getPerformerFirstRep === ''undefined'' && !input.getPerformer().isEmpty() && (input.getPerformer().getReferenceElement().getResourceType() == null || input.getPerformer().getReferenceElement().getResourceType() == ''Organization'')) +{ + fhirOrgUnitRef = input.getPerformer(); + fhirOrgUnitType = input.getPerformer().getReferenceElement().getResourceType(); + if (fhirOrgUnitType == null) + { + fhirOrgUnitType = ''Organization''; + } +} +else if (input.serviceProvider) +{ + fhirOrgUnitRef = input.serviceProvider; + fhirOrgUnitType = ''Organization''; +} +else if (input.author) +{ + fhirOrgUnitRef = input.author; + fhirOrgUnitType = ''Organization''; +} +else if (input.requester && input.requester.agent) +{ + fhirOrgUnitRef = input.getRequester().getAgent(); + fhirOrgUnitType = input.getRequester().getAgent().getReferenceElement().getResourceType(); + if (fhirOrgUnitType == null) + { + fhirOrgUnitType = ''Organization''; + } + ok = true; +} +else if (input.encounter) +{ + var encounter = referenceUtils.getResource(input.encounter, ''Encounter''); + if (encounter != null) + { + fhirOrgUnitRef = getLocationReference(encounter.location); + fhirOrgUnitType = ''Location''; + } +} +var ref = null; +if (fhirOrgUnitRef != null) +{ + ref = fhirResourceUtils.getAdapterReference(fhirOrgUnitRef, fhirOrgUnitType); +} +if (ref == null) +{ + if (context.getFhirRequest().isDhisFhirId()) + { + if (fhirOrgUnitRef == null) + { + if (args[''useTei''] && (typeof trackedEntityInstance !== ''undefined'')) + { + ref = context.createReference(trackedEntityInstance.organizationUnitId, ''ID''); + } + else if ((typeof enrollment !== ''undefined'') && (enrollment.organizationUnitId != null)) + { + ref = context.createReference(enrollment.organizationUnitId, ''ID''); + } + } + else + { + if (fhirOrgUnitRef != null && fhirOrgUnitRef.identifier !== ''undefined'' && fhirOrgUnitRef.hasIdentifier()) + { + ref = context.createReference(identifierUtils.getReferenceIdentifier(fhirOrgUnitRef, fhirOrgUnitType), ''code''); + } + if (ref == null) + { + ref = context.createReference(context.extractDhisId(fhirOrgUnitRef.getReferenceElement()), ''id''); + } + } + } + else + { + var mappedCode = null; + if (fhirOrgUnitRef != null) + { + if (fhirOrgUnitType == ''Location'') + { + mappedCode = getLocationMappedCode(fhirOrgUnitRef); + } + else + { + mappedCode = getOrganizationUnitMappedCode(fhirOrgUnitRef); + } + } + if (mappedCode == null) + { + mappedCode = args[''defaultCode'']; + } + if (mappedCode != null) + { + ref = context.createReference(mappedCode, ''CODE''); + } + if ((ref == null) && args[''useTei''] && (typeof trackedEntityInstance !== ''undefined'')) + { + ref = context.createReference(trackedEntityInstance.organizationUnitId, ''ID''); + } + else if ((ref == null) && (typeof enrollment !== ''undefined'') && (enrollment.organizationUnitId != null)) + { + ref = context.createReference(enrollment.organizationUnitId, ''ID''); + } + } +} +ref' WHERE id='7b94feba-bcf6-4635-929a-01311b25d975' AND version=0; + diff --git a/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/extension/BaseExtensionUtilsTest.java b/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/extension/BaseExtensionUtilsTest.java index 73a6d1a4..23f6ffc0 100644 --- a/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/extension/BaseExtensionUtilsTest.java +++ b/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/extension/BaseExtensionUtilsTest.java @@ -90,6 +90,17 @@ public void setDateValue() Assert.assertEquals( date, ( (DateDt) planDefinition.getExtension().get( 0 ).getValue() ).getValue() ); } + @Test + public void getDateValue() + { + TestPlanDefinition planDefinition = new TestPlanDefinition(); + + final Date date = new Date(); + + BaseExtensionUtils.setDateValue( "testUrl", planDefinition, new Date(), TypeFactory::createType ); + Assert.assertEquals( date, BaseExtensionUtils.getDateValue( "testUrl", planDefinition ) ); + } + @Test public void resetReferenceValue() { diff --git a/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/extension/DueDateExtensionUtilsTest.java b/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/extension/DueDateExtensionUtilsTest.java new file mode 100644 index 00000000..31acdef5 --- /dev/null +++ b/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/extension/DueDateExtensionUtilsTest.java @@ -0,0 +1,68 @@ +package org.dhis2.fhir.adapter.fhir.extension; + +/* + * Copyright (c) 2004-2019, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import ca.uhn.fhir.model.primitive.DateDt; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Date; + +/** + * Unit tests for {@link DueDateExtensionUtils}. + * + * @author volsch + */ +public class DueDateExtensionUtilsTest +{ + @Test + public void resetValue() + { + TestPlanDefinition planDefinition = new TestPlanDefinition(); + + DueDateExtensionUtils.setValue( planDefinition, new Date(), TypeFactory::createType ); + DueDateExtensionUtils.setValue( planDefinition, null, TypeFactory::createType ); + + Assert.assertTrue( planDefinition.getExtension().isEmpty() ); + } + + @Test + public void setValue() + { + TestPlanDefinition planDefinition = new TestPlanDefinition(); + + final Date date = new Date(); + + DueDateExtensionUtils.setValue( planDefinition, date, TypeFactory::createType ); + + Assert.assertEquals( 1, planDefinition.getExtension().size() ); + Assert.assertEquals( DueDateExtensionUtils.URL, planDefinition.getExtension().get( 0 ).getUrl() ); + Assert.assertSame( date, ( (DateDt) planDefinition.getExtension().get( 0 ).getValue() ).getValue() ); + } +} \ No newline at end of file diff --git a/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/extension/EventStatusExtensionUtilsTest.java b/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/extension/EventStatusExtensionUtilsTest.java new file mode 100644 index 00000000..23b5be4d --- /dev/null +++ b/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/extension/EventStatusExtensionUtilsTest.java @@ -0,0 +1,53 @@ +package org.dhis2.fhir.adapter.fhir.extension; + +/* + * Copyright (c) 2004-2019, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import org.dhis2.fhir.adapter.dhis.tracker.program.EventStatus; +import org.junit.Assert; +import org.junit.Test; + +/** + * Unit tests for {@link EventStatusExtensionUtils}. + * + * @author volsch + */ +public class EventStatusExtensionUtilsTest +{ + @Test + public void setValue() + { + TestPlanDefinition planDefinition = new TestPlanDefinition(); + + EventStatusExtensionUtils.setValue( planDefinition, EventStatus.OVERDUE, TypeFactory::createType ); + + Assert.assertEquals( 1, planDefinition.getExtension().size() ); + Assert.assertEquals( EventStatusExtensionUtils.URL, planDefinition.getExtension().get( 0 ).getUrl() ); + Assert.assertEquals( "OVERDUE", planDefinition.getExtension().get( 0 ).getValue().toString() ); + } +} \ No newline at end of file diff --git a/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/extension/IncidentDateExtensionUtilsTest.java b/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/extension/IncidentDateExtensionUtilsTest.java index 2bacc7c8..97edca03 100644 --- a/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/extension/IncidentDateExtensionUtilsTest.java +++ b/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/extension/IncidentDateExtensionUtilsTest.java @@ -65,4 +65,15 @@ public void setValue() Assert.assertEquals( IncidentDateExtensionUtils.URL, planDefinition.getExtension().get( 0 ).getUrl() ); Assert.assertSame( date, ( (DateDt) planDefinition.getExtension().get( 0 ).getValue() ).getValue() ); } + + @Test + public void getDateValue() + { + TestPlanDefinition planDefinition = new TestPlanDefinition(); + + final Date date = new Date(); + + IncidentDateExtensionUtils.setValue( planDefinition, date, TypeFactory::createType ); + Assert.assertEquals( date, IncidentDateExtensionUtils.getValue( planDefinition ) ); + } } \ No newline at end of file diff --git a/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/util/FhirUriUtilsTest.java b/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/util/FhirUriUtilsTest.java new file mode 100644 index 00000000..49a7cc16 --- /dev/null +++ b/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/util/FhirUriUtilsTest.java @@ -0,0 +1,81 @@ +package org.dhis2.fhir.adapter.fhir.util; + +/* + * Copyright (c) 2004-2019, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import org.dhis2.fhir.adapter.fhir.metadata.model.FhirResourceType; +import org.hl7.fhir.instance.model.api.IIdType; +import org.junit.Assert; +import org.junit.Test; + +/** + * Unit tests for {@link FhirUriUtils}. + * + * @author volsch + */ +public class FhirUriUtilsTest +{ + @Test + public void createIdFromUri() + { + final IIdType id = FhirUriUtils.createIdFromUri( "Location/4711", null ); + Assert.assertEquals( "Location/4711", id.getValue() ); + } + + @Test + public void createIdFromUriWithType() + { + final IIdType id = FhirUriUtils.createIdFromUri( "Location/4711", FhirResourceType.LOCATION ); + Assert.assertEquals( "Location/4711", id.getValue() ); + } + + @Test + public void createIdFromUriWithUnspecifiedType() + { + final IIdType id = FhirUriUtils.createIdFromUri( "4711", FhirResourceType.LOCATION ); + Assert.assertEquals( "Location/4711", id.getValue() ); + } + + @Test( expected = IllegalArgumentException.class ) + public void createIdFromUriWithNonMatchingType() + { + FhirUriUtils.createIdFromUri( "Location/4711", FhirResourceType.ORGANIZATION ); + } + + @Test( expected = IllegalArgumentException.class ) + public void createIdFromUriWithMissingType() + { + FhirUriUtils.createIdFromUri( "4711", null ); + } + + @Test( expected = IllegalArgumentException.class ) + public void createIdFromUriInvalid() + { + FhirUriUtils.createIdFromUri( "No/Location/4711", FhirResourceType.LOCATION ); + } +} \ No newline at end of file