diff --git a/app/src/test/java/org/dhis2/fhir/adapter/fhir/server/r4/R4ProgramMetadataFhirRestAppTest.java b/app/src/test/java/org/dhis2/fhir/adapter/fhir/server/r4/R4ProgramMetadataFhirRestAppTest.java index e86e33b7..e828ae5b 100644 --- a/app/src/test/java/org/dhis2/fhir/adapter/fhir/server/r4/R4ProgramMetadataFhirRestAppTest.java +++ b/app/src/test/java/org/dhis2/fhir/adapter/fhir/server/r4/R4ProgramMetadataFhirRestAppTest.java @@ -34,6 +34,7 @@ import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import org.apache.commons.io.IOUtils; import org.dhis2.fhir.adapter.AbstractAppTest; +import org.dhis2.fhir.adapter.fhir.extension.ResourceTypeExtensionUtils; import org.dhis2.fhir.adapter.fhir.model.FhirVersion; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.PlanDefinition; @@ -124,6 +125,8 @@ private void getPlanDefinition() throws Exception client.registerInterceptor( new BasicAuthInterceptor( "fhir_client", "fhir_client_1" ) ); PlanDefinition planDefinition = client.read().resource( PlanDefinition.class ).withId( "EPDyQuoRnXk" ).execute(); Assert.assertEquals( "Child Programme", planDefinition.getTitle() ); + Assert.assertNotNull( planDefinition.getExtensionByUrl( ResourceTypeExtensionUtils.URL ) ); + Assert.assertEquals( "Patient", planDefinition.getExtensionByUrl( ResourceTypeExtensionUtils.URL ).getValue().primitiveValue() ); systemDhis2Server.verify(); userDhis2Server.verify(); diff --git a/docs/fhir/profiles/LocationExtension.StructureDefinition.xml b/docs/fhir/profiles/LocationExtension.StructureDefinition.xml index 4211ca46..51891d76 100644 --- a/docs/fhir/profiles/LocationExtension.StructureDefinition.xml +++ b/docs/fhir/profiles/LocationExtension.StructureDefinition.xml @@ -28,7 +28,7 @@ --> - + @@ -47,21 +47,6 @@ - - - - - - - - - - - - - - - diff --git a/docs/fhir/profiles/ResourceTypeExtension.StructureDefinition.xml b/docs/fhir/profiles/ResourceTypeExtension.StructureDefinition.xml new file mode 100644 index 00000000..76f90869 --- /dev/null +++ b/docs/fhir/profiles/ResourceTypeExtension.StructureDefinition.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/fhir/profiles/TrackerProgramPlanDefinition.StructureDefinition.xml b/docs/fhir/profiles/TrackerProgramPlanDefinition.StructureDefinition.xml index bf33d0bb..25e9ae28 100644 --- a/docs/fhir/profiles/TrackerProgramPlanDefinition.StructureDefinition.xml +++ b/docs/fhir/profiles/TrackerProgramPlanDefinition.StructureDefinition.xml @@ -50,6 +50,27 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/metadata/r4/R4ProgramMetadataToFhirPlanDefinitionTransformer.java b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/metadata/r4/R4ProgramMetadataToFhirPlanDefinitionTransformer.java index 44333c79..90f5a217 100644 --- a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/metadata/r4/R4ProgramMetadataToFhirPlanDefinitionTransformer.java +++ b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/metadata/r4/R4ProgramMetadataToFhirPlanDefinitionTransformer.java @@ -28,6 +28,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import ca.uhn.fhir.model.api.IElement; import org.dhis2.fhir.adapter.dhis.orgunit.OrganizationUnitService; import org.dhis2.fhir.adapter.dhis.tracker.program.Program; import org.dhis2.fhir.adapter.dhis.tracker.trackedentity.TrackedEntityMetadataService; @@ -50,11 +51,13 @@ import org.hl7.fhir.r4.model.Enumerations; import org.hl7.fhir.r4.model.PlanDefinition; import org.hl7.fhir.r4.model.PlanDefinition.PlanDefinitionActionComponent; +import org.hl7.fhir.r4.model.ResourceFactory; import org.springframework.stereotype.Component; import javax.annotation.Nonnull; import java.util.Map; import java.util.Set; +import java.util.function.Function; /** * R4 specific version of DHIS2 Program Metadata to FHIR Plan Definition transformer. @@ -86,7 +89,7 @@ protected boolean transformInternal( @Nonnull FhirClient fhirClient, @Nonnull Dh final Program dhisProgram = (Program) input.getDhisResource(); final PlanDefinition fhirPlanDefinition = (PlanDefinition) output; - if ( !isApplicableProgram( dhisProgram ) ) + if ( !addSubjectResourceType( dhisProgram, fhirPlanDefinition ) ) { return false; } @@ -111,4 +114,11 @@ protected boolean transformInternal( @Nonnull FhirClient fhirClient, @Nonnull Dh return true; } + + @Nonnull + @Override + protected Function getTypeFactory() + { + return ResourceFactory::createType; + } } diff --git a/fhir-r4/src/test/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/metadata/r4/R4ProgramMetadataToFhirPlanDefinitionTransformerTest.java b/fhir-r4/src/test/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/metadata/r4/R4ProgramMetadataToFhirPlanDefinitionTransformerTest.java index adccd703..a795ad71 100644 --- a/fhir-r4/src/test/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/metadata/r4/R4ProgramMetadataToFhirPlanDefinitionTransformerTest.java +++ b/fhir-r4/src/test/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/metadata/r4/R4ProgramMetadataToFhirPlanDefinitionTransformerTest.java @@ -36,9 +36,12 @@ import org.dhis2.fhir.adapter.dhis.tracker.trackedentity.TrackedEntityMetadataService; import org.dhis2.fhir.adapter.dhis.tracker.trackedentity.WritableTrackedEntityType; import org.dhis2.fhir.adapter.fhir.data.repository.FhirDhisAssignmentRepository; +import org.dhis2.fhir.adapter.fhir.extension.ResourceTypeExtensionUtils; 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.ProgramMetadataRule; import org.dhis2.fhir.adapter.fhir.metadata.model.RuleInfo; +import org.dhis2.fhir.adapter.fhir.metadata.model.TrackedEntityRule; 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; @@ -120,10 +123,13 @@ public void getFhirVersions() @Test public void transformInternal() { + final TrackedEntityRule rule2 = new TrackedEntityRule(); + rule2.setEvaluationOrder( 100 ); + rule2.setFhirResourceType( FhirResourceType.PATIENT ); + Mockito.doReturn( Optional.of( new WritableTrackedEntityType( "a1234567890", "Test", Collections.emptyList() ) ) ) .when( trackedEntityMetadataService ).findTypeByReference( Mockito.eq( new Reference( "a1234567890", ReferenceType.ID ) ) ); - Mockito.doReturn( Collections.singletonList( new RuleInfo<>( new ProgramMetadataRule(), Collections.emptyList() ) ) ) - .when( trackedEntityRuleRepository ).findByTypeRefs( Mockito.eq( new HashSet<>( + Mockito.doReturn( Collections.singletonList( rule2 ) ).when( trackedEntityRuleRepository ).findByTypeRefs( Mockito.eq( new HashSet<>( Arrays.asList( new Reference( "a1234567890", ReferenceType.ID ), new Reference( "Test", ReferenceType.NAME ) ) ) ) ); final WritableProgram program = new WritableProgram(); @@ -156,6 +162,10 @@ public void transformInternal() Assert.assertEquals( "Test Description", fhirPlanDefinition.getDescription() ); Assert.assertEquals( 2, fhirPlanDefinition.getAction().size() ); + Assert.assertEquals( 1, fhirPlanDefinition.getExtension().size() ); + Assert.assertEquals( ResourceTypeExtensionUtils.URL, fhirPlanDefinition.getExtension().get( 0 ).getUrl() ); + Assert.assertEquals( "Patient", fhirPlanDefinition.getExtension().get( 0 ).getValue().toString() ); + Assert.assertEquals( "b1234567890", fhirPlanDefinition.getAction().get( 0 ).getId() ); Assert.assertEquals( "Test Stage 1", fhirPlanDefinition.getAction().get( 0 ).getTitle() ); Assert.assertEquals( "Test Description 1", fhirPlanDefinition.getAction().get( 0 ).getDescription() ); diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/extension/ResourceTypeExtensionUtils.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/extension/ResourceTypeExtensionUtils.java new file mode 100644 index 00000000..595cc28f --- /dev/null +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/extension/ResourceTypeExtensionUtils.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.api.IElement; +import org.dhis2.fhir.adapter.fhir.metadata.model.FhirResourceType; +import org.hl7.fhir.instance.model.api.IBaseExtension; +import org.hl7.fhir.instance.model.api.IBaseHasExtensions; +import org.hl7.fhir.instance.model.api.IPrimitiveType; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.function.Function; + +/** + * Utility class to process FHIR resource type extension. + * + * @author volsch + */ +public abstract class ResourceTypeExtensionUtils +{ + public static final String URL = "http://www.dhis2.org/dhis2-fhir-adapter/fhir/extensions/resource-type"; + + @SuppressWarnings( "unchecked" ) + public static void setValue( @Nonnull IBaseHasExtensions resource, @Nullable FhirResourceType fhirResourceType, @Nonnull Function typeFactory ) + { + resource.getExtension().removeIf( e -> URL.equals( e.getUrl() ) ); + + if ( fhirResourceType != null ) + { + final IBaseExtension extension = resource.addExtension(); + + extension.setUrl( URL ); + extension.setValue( ( (IPrimitiveType) typeFactory.apply( "string" ) ).setValue( fhirResourceType.getResourceTypeName() ) ); + } + } + + private ResourceTypeExtensionUtils() + { + super(); + } +} diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/metadata/program/AbstractProgramMetadataToFhirPlanDefinitionTransformer.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/metadata/program/AbstractProgramMetadataToFhirPlanDefinitionTransformer.java index bb7aaefe..a2b48af7 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/metadata/program/AbstractProgramMetadataToFhirPlanDefinitionTransformer.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/metadata/program/AbstractProgramMetadataToFhirPlanDefinitionTransformer.java @@ -28,6 +28,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import ca.uhn.fhir.model.api.IElement; import org.dhis2.fhir.adapter.dhis.model.DhisResourceType; import org.dhis2.fhir.adapter.dhis.model.Reference; import org.dhis2.fhir.adapter.dhis.model.ReferenceType; @@ -36,6 +37,8 @@ import org.dhis2.fhir.adapter.dhis.tracker.trackedentity.TrackedEntityMetadataService; import org.dhis2.fhir.adapter.dhis.tracker.trackedentity.TrackedEntityType; import org.dhis2.fhir.adapter.fhir.data.repository.FhirDhisAssignmentRepository; +import org.dhis2.fhir.adapter.fhir.extension.ResourceTypeExtensionUtils; +import org.dhis2.fhir.adapter.fhir.metadata.model.AbstractRule; import org.dhis2.fhir.adapter.fhir.metadata.model.FhirResourceType; import org.dhis2.fhir.adapter.fhir.metadata.model.ProgramMetadataRule; import org.dhis2.fhir.adapter.fhir.metadata.repository.SystemRepository; @@ -46,11 +49,13 @@ import org.dhis2.fhir.adapter.fhir.transform.dhis.impl.metadata.AbstractReadOnlyDhisMetadataToTypedFhirTransformer; import org.dhis2.fhir.adapter.fhir.transform.scripted.AccessibleScriptedDhisMetadata; import org.dhis2.fhir.adapter.lock.LockManager; +import org.hl7.fhir.instance.model.api.IBaseHasExtensions; import org.hl7.fhir.instance.model.api.IBaseResource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.annotation.Nonnull; +import java.util.function.Function; /** * Implementation of {@link DhisToFhirTransformer} for transforming DHIS2 @@ -63,6 +68,8 @@ public abstract class AbstractProgramMetadataToFhirPlanDefinitionTransformer getRuleClass() return ProgramMetadataRule.class; } - protected boolean isApplicableProgram( @Nonnull Program program ) + protected boolean addSubjectResourceType( @Nonnull Program program, @Nonnull IBaseHasExtensions resource ) { - if ( program.isWithoutRegistration() || program.getTrackedEntityTypeId() == null ) + if ( program.getTrackedEntityTypeId() == null ) { - return false; + ResourceTypeExtensionUtils.setValue( resource, null, getTypeFactory() ); + + return true; } - final TrackedEntityType trackedEntityType = trackedEntityMetadataService.findTypeByReference( new Reference( program.getTrackedEntityTypeId(), ReferenceType.ID ) ).orElse( null ); + final TrackedEntityType trackedEntityType = trackedEntityMetadataService.findTypeByReference( + new Reference( program.getTrackedEntityTypeId(), ReferenceType.ID ) ).orElse( null ); if ( trackedEntityType == null ) { return false; } - return !trackedEntityRuleRepository.findByTypeRefs( trackedEntityType.getAllReferences() ).isEmpty(); + final FhirResourceType fhirResourceType = trackedEntityRuleRepository.findByTypeRefs( trackedEntityType.getAllReferences() ).stream() + .sorted( ( o1, o2 ) -> o2.getEvaluationOrder() - o1.getEvaluationOrder() ).map( AbstractRule::getFhirResourceType ).findFirst().orElse( null ); + + if ( fhirResourceType == null ) + { + return false; + } + + ResourceTypeExtensionUtils.setValue( resource, fhirResourceType, getTypeFactory() ); + + return true; } + + @Nonnull + protected abstract Function getTypeFactory(); } diff --git a/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/extension/ResourceTypeExtensionUtilsTest.java b/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/extension/ResourceTypeExtensionUtilsTest.java new file mode 100644 index 00000000..d245ec1d --- /dev/null +++ b/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/extension/ResourceTypeExtensionUtilsTest.java @@ -0,0 +1,107 @@ +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.ExtensionDt; +import ca.uhn.fhir.model.api.IElement; +import ca.uhn.fhir.model.primitive.StringDt; +import org.dhis2.fhir.adapter.fhir.metadata.model.FhirResourceType; +import org.hl7.fhir.instance.model.api.IBaseExtension; +import org.hl7.fhir.instance.model.api.IBaseHasExtensions; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +/** + * Unit tests for {@link ResourceTypeExtensionUtils}. + * + * @author volsch + */ +public class ResourceTypeExtensionUtilsTest +{ + @Test + public void resetValue() + { + PlanDefinition planDefinition = new PlanDefinition(); + + ResourceTypeExtensionUtils.setValue( planDefinition, FhirResourceType.PATIENT, TypeFactory::createType ); + ResourceTypeExtensionUtils.setValue( planDefinition, null, TypeFactory::createType ); + + Assert.assertTrue( planDefinition.getExtension().isEmpty() ); + } + + @Test + public void setValue() + { + PlanDefinition planDefinition = new PlanDefinition(); + + ResourceTypeExtensionUtils.setValue( planDefinition, FhirResourceType.PATIENT, TypeFactory::createType ); + + Assert.assertEquals( 1, planDefinition.getExtension().size() ); + Assert.assertEquals( ResourceTypeExtensionUtils.URL, planDefinition.getExtension().get( 0 ).getUrl() ); + Assert.assertEquals( "Patient", planDefinition.getExtension().get( 0 ).getValue().toString() ); + } + + public static class PlanDefinition implements IBaseHasExtensions + { + private final List> extensions = new ArrayList<>(); + + @Override + public IBaseExtension addExtension() + { + extensions.add( new ExtensionDt() ); + + return extensions.get( extensions.size() - 1 ); + } + + @Override + public List> getExtension() + { + return extensions; + } + + @Override + public boolean hasExtension() + { + return !extensions.isEmpty(); + } + } + + public static class TypeFactory + { + public static IElement createType( String name ) + { + Assert.assertEquals( "string", name ); + + return new StringDt(); + } + } +} \ No newline at end of file diff --git a/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/metadata/program/AbstractProgramMetadataToFhirPlanDefinitionTransformerTest.java b/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/metadata/program/AbstractProgramMetadataToFhirPlanDefinitionTransformerTest.java index 8ee2c709..5c473888 100644 --- a/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/metadata/program/AbstractProgramMetadataToFhirPlanDefinitionTransformerTest.java +++ b/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/metadata/program/AbstractProgramMetadataToFhirPlanDefinitionTransformerTest.java @@ -28,6 +28,8 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import ca.uhn.fhir.model.api.ExtensionDt; +import ca.uhn.fhir.model.primitive.StringDt; import org.dhis2.fhir.adapter.dhis.model.DhisResourceType; import org.dhis2.fhir.adapter.dhis.model.Reference; import org.dhis2.fhir.adapter.dhis.model.ReferenceType; @@ -36,15 +38,17 @@ import org.dhis2.fhir.adapter.dhis.tracker.trackedentity.TrackedEntityMetadataService; import org.dhis2.fhir.adapter.dhis.tracker.trackedentity.WritableTrackedEntityType; import org.dhis2.fhir.adapter.fhir.data.repository.FhirDhisAssignmentRepository; +import org.dhis2.fhir.adapter.fhir.extension.ResourceTypeExtensionUtils; import org.dhis2.fhir.adapter.fhir.metadata.model.FhirResourceType; -import org.dhis2.fhir.adapter.fhir.metadata.model.ProgramMetadataRule; -import org.dhis2.fhir.adapter.fhir.metadata.model.RuleInfo; +import org.dhis2.fhir.adapter.fhir.metadata.model.TrackedEntityRule; 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.script.ScriptExecutor; import org.dhis2.fhir.adapter.fhir.transform.scripted.AccessibleScriptedDhisMetadata; import org.dhis2.fhir.adapter.lock.LockManager; +import org.hl7.fhir.instance.model.api.IBaseExtension; +import org.hl7.fhir.instance.model.api.IBaseHasExtensions; import org.junit.Assert; import org.junit.Before; import org.junit.Rule; @@ -58,6 +62,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Optional; import static org.mockito.Mockito.CALLS_REAL_METHODS; @@ -97,7 +102,7 @@ public class AbstractProgramMetadataToFhirPlanDefinitionTransformerTest private AbstractProgramMetadataToFhirPlanDefinitionTransformer transformer; @Rule - public MockitoRule rule = MockitoJUnit.rule(); + public MockitoRule rule = MockitoJUnit.rule().silent(); @Before public void setUp() @@ -105,6 +110,8 @@ public void setUp() transformer = Mockito.mock( AbstractProgramMetadataToFhirPlanDefinitionTransformer.class, withSettings().useConstructor( scriptExecutor, lockManager, systemRepository, fhirResourceRepository, fhirDhisAssignmentRepository, organizationUnitService, trackedEntityMetadataService, trackedEntityRuleRepository ).defaultAnswer( CALLS_REAL_METHODS ) ); + + Mockito.when( transformer.getTypeFactory() ).thenReturn( name -> new StringDt() ); } @Test @@ -126,12 +133,19 @@ public void getDhisResourceClass() } @Test - public void isApplicableProgram() + public void addSubjectResourceType() { + final TrackedEntityRule rule1 = new TrackedEntityRule(); + rule1.setEvaluationOrder( 1 ); + rule1.setFhirResourceType( FhirResourceType.RELATED_PERSON ); + + final TrackedEntityRule rule2 = new TrackedEntityRule(); + rule2.setEvaluationOrder( 100 ); + rule2.setFhirResourceType( FhirResourceType.PATIENT ); + Mockito.doReturn( Optional.of( new WritableTrackedEntityType( "a1234567890", "Test", Collections.emptyList() ) ) ) .when( trackedEntityMetadataService ).findTypeByReference( Mockito.eq( new Reference( "a1234567890", ReferenceType.ID ) ) ); - Mockito.doReturn( Collections.singletonList( new RuleInfo<>( new ProgramMetadataRule(), Collections.emptyList() ) ) ) - .when( trackedEntityRuleRepository ).findByTypeRefs( Mockito.eq( new HashSet<>( + Mockito.doReturn( Arrays.asList( rule1, rule2 ) ).when( trackedEntityRuleRepository ).findByTypeRefs( Mockito.eq( new HashSet<>( Arrays.asList( new Reference( "a1234567890", ReferenceType.ID ), new Reference( "Test", ReferenceType.NAME ) ) ) ) ); final WritableProgram program = new WritableProgram(); @@ -141,24 +155,17 @@ public void isApplicableProgram() program.setTrackedEntityTypeId( "a1234567890" ); program.setStages( new ArrayList<>() ); - Assert.assertTrue( transformer.isApplicableProgram( program ) ); - } + final PlanDefinition planDefinition = new PlanDefinition(); - @Test - public void isApplicableProgramWithoutRegistration() - { - final WritableProgram program = new WritableProgram(); - program.setName( "Test Program" ); - program.setDescription( "Test Description" ); - program.setWithoutRegistration( true ); - program.setTrackedEntityTypeId( "a1234567890" ); - program.setStages( new ArrayList<>() ); + Assert.assertTrue( transformer.addSubjectResourceType( program, planDefinition ) ); - Assert.assertFalse( transformer.isApplicableProgram( program ) ); + Assert.assertEquals( 1, planDefinition.getExtension().size() ); + Assert.assertEquals( ResourceTypeExtensionUtils.URL, planDefinition.getExtension().get( 0 ).getUrl() ); + Assert.assertEquals( "Patient", planDefinition.getExtension().get( 0 ).getValue().toString() ); } @Test - public void isApplicableProgramWithoutTrackedEntityType() + public void addSubjectResourceTypeWithoutTrackedEntityType() { final WritableProgram program = new WritableProgram(); program.setName( "Test Program" ); @@ -166,11 +173,15 @@ public void isApplicableProgramWithoutTrackedEntityType() program.setWithoutRegistration( false ); program.setStages( new ArrayList<>() ); - Assert.assertFalse( transformer.isApplicableProgram( program ) ); + final PlanDefinition planDefinition = new PlanDefinition(); + + Assert.assertTrue( transformer.addSubjectResourceType( program, planDefinition ) ); + + Assert.assertEquals( 0, planDefinition.getExtension().size() ); } @Test - public void isApplicableProgramWithoutTrackedEntityMetadata() + public void addSubjectResourceTypeWithoutTrackedEntityMetadata() { Mockito.doReturn( Optional.empty() ) .when( trackedEntityMetadataService ).findTypeByReference( Mockito.eq( new Reference( "a1234567890", ReferenceType.ID ) ) ); @@ -182,11 +193,13 @@ public void isApplicableProgramWithoutTrackedEntityMetadata() program.setTrackedEntityTypeId( "a1234567890" ); program.setStages( new ArrayList<>() ); - Assert.assertFalse( transformer.isApplicableProgram( program ) ); + final PlanDefinition planDefinition = new PlanDefinition(); + + Assert.assertFalse( transformer.addSubjectResourceType( program, planDefinition ) ); } @Test - public void isApplicableProgramWithoutRules() + public void addSubjectResourceTypeWithoutRules() { Mockito.doReturn( Optional.of( new WritableTrackedEntityType( "a1234567890", "Test", Collections.emptyList() ) ) ) .when( trackedEntityMetadataService ).findTypeByReference( Mockito.eq( new Reference( "a1234567890", ReferenceType.ID ) ) ); @@ -201,6 +214,33 @@ public void isApplicableProgramWithoutRules() program.setTrackedEntityTypeId( "a1234567890" ); program.setStages( new ArrayList<>() ); - Assert.assertFalse( transformer.isApplicableProgram( program ) ); + final PlanDefinition planDefinition = new PlanDefinition(); + + Assert.assertFalse( transformer.addSubjectResourceType( program, planDefinition ) ); + } + + public static class PlanDefinition implements IBaseHasExtensions + { + private final List> extensions = new ArrayList<>(); + + @Override + public IBaseExtension addExtension() + { + extensions.add( new ExtensionDt() ); + + return extensions.get( extensions.size() - 1 ); + } + + @Override + public List> getExtension() + { + return extensions; + } + + @Override + public boolean hasExtension() + { + return !extensions.isEmpty(); + } } } \ No newline at end of file