From 7c4e75d1c7d64eb790bfdaa767fdaa9ece8289c2 Mon Sep 17 00:00:00 2001 From: Volker Schmidt Date: Wed, 22 May 2019 12:11:00 +0200 Subject: [PATCH] Added test for batch bundle processing. --- .../impl/TrackedEntityServiceImpl.java | 4 +- .../Dstu3BundleResourceProviderTest.java | 325 ++++++++ .../r4/R4BundleResourceProviderTest.java | 325 ++++++++ .../fhir/metadata/model/FhirClientSystem.java | 11 + .../adapter/fhir/metadata/model/System.java | 11 + .../fhir/repository/DhisFhirResourceId.java | 25 + .../fhir/repository/FhirOperationIssue.java | 6 + .../fhir/repository/FhirOperationResult.java | 10 + .../repository/FhirRepositoryOperation.java | 25 + .../AbstractBundleResourceProvider.java | 15 +- .../AbstractUntypedResourceProvider.java | 1 + .../AbstractBundleResourceProviderTest.java | 717 ++++++++++++++++++ 12 files changed, 1468 insertions(+), 7 deletions(-) create mode 100644 fhir-dstu3/src/test/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3BundleResourceProviderTest.java create mode 100644 fhir-r4/src/test/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4BundleResourceProviderTest.java create mode 100644 fhir/src/test/java/org/dhis2/fhir/adapter/fhir/server/provider/AbstractBundleResourceProviderTest.java diff --git a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/trackedentity/impl/TrackedEntityServiceImpl.java b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/trackedentity/impl/TrackedEntityServiceImpl.java index c982388c..61f5452d 100644 --- a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/trackedentity/impl/TrackedEntityServiceImpl.java +++ b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/trackedentity/impl/TrackedEntityServiceImpl.java @@ -235,12 +235,12 @@ public TrackedEntityInstance createOrUpdate( @Nonnull TrackedEntityInstance trac @HystrixCommand( ignoreExceptions = { DhisConflictException.class, UnauthorizedException.class } ) @Override - public boolean delete( @Nonnull String eventId ) + public boolean delete( @Nonnull String trackedEntityInstanceId ) { Event instance; try { - restTemplate.delete( "/trackedEntityInstances/{id}", eventId ); + restTemplate.delete( "/trackedEntityInstances/{id}", trackedEntityInstanceId ); } catch ( HttpClientErrorException e ) { diff --git a/fhir-dstu3/src/test/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3BundleResourceProviderTest.java b/fhir-dstu3/src/test/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3BundleResourceProviderTest.java new file mode 100644 index 00000000..ef4ed470 --- /dev/null +++ b/fhir-dstu3/src/test/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3BundleResourceProviderTest.java @@ -0,0 +1,325 @@ +package org.dhis2.fhir.adapter.fhir.server.provider.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 ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; +import org.dhis2.fhir.adapter.cache.RequestCacheService; +import org.dhis2.fhir.adapter.fhir.metadata.model.FhirClient; +import org.dhis2.fhir.adapter.fhir.metadata.model.FhirClientResource; +import org.dhis2.fhir.adapter.fhir.metadata.model.FhirResourceType; +import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientResourceRepository; +import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientSystemRepository; +import org.dhis2.fhir.adapter.fhir.model.FhirVersion; +import org.dhis2.fhir.adapter.fhir.repository.DhisRepository; +import org.dhis2.fhir.adapter.fhir.repository.FhirBatchRequest; +import org.dhis2.fhir.adapter.fhir.repository.FhirOperation; +import org.dhis2.fhir.adapter.fhir.repository.FhirOperationIssueSeverity; +import org.dhis2.fhir.adapter.fhir.repository.FhirOperationIssueType; +import org.dhis2.fhir.adapter.fhir.repository.FhirOperationType; +import org.dhis2.fhir.adapter.fhir.repository.FhirRepository; +import org.hl7.fhir.dstu3.model.Bundle; +import org.hl7.fhir.dstu3.model.OperationOutcome; +import org.hl7.fhir.dstu3.model.Patient; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Optional; + +/** + * Unit tests for {@link Dstu3BundleResourceProvider}. + * + * @author volsch + */ +public class Dstu3BundleResourceProviderTest +{ + @Mock + private FhirClientResourceRepository fhirClientResourceRepository; + + @Mock + private FhirClientSystemRepository fhirClientSystemRepository; + + @Mock + private FhirRepository fhirRepository; + + @Mock + private DhisRepository dhisRepository; + + @Mock + private RequestCacheService requestCacheService; + + @InjectMocks + private Dstu3BundleResourceProvider provider; + + private FhirClient fhirClient = new FhirClient(); + + private FhirClientResource patientClientResource = new FhirClientResource(); + + private FhirClientResource observationClientResource = new FhirClientResource(); + + @Rule + public MockitoRule rule = MockitoJUnit.rule(); + + @Before + public void setUp() + { + fhirClient.setId( FhirClient.getIdByFhirVersion( FhirVersion.DSTU3 ) ); + patientClientResource.setFhirClient( fhirClient ); + observationClientResource.setFhirClient( fhirClient ); + } + + @Test + public void getFhirVersion() + { + Assert.assertEquals( FhirVersion.DSTU3, provider.getFhirVersion() ); + } + + @Test( expected = InvalidRequestException.class ) + public void transactionBundle() + { + final Bundle bundle = new Bundle(); + bundle.setType( Bundle.BundleType.TRANSACTION ); + provider.createBatchRequest( bundle ); + } + + @Test + public void createBatchResponseCreated() + { + final List operations = new ArrayList<>(); + operations.add( new FhirOperation( FhirOperationType.POST, FhirResourceType.PATIENT, patientClientResource, null, new Patient(), null ) ); + operations.get( 0 ).getResult().created( new IdDt( "123" ) ); + final FhirBatchRequest batchRequest = new FhirBatchRequest( operations, false ); + + final Bundle bundle = provider.createBatchResponse( batchRequest ); + Assert.assertEquals( Bundle.BundleType.BATCHRESPONSE, bundle.getType() ); + Assert.assertEquals( 1, bundle.getEntry().size() ); + + Assert.assertEquals( "Patient/123", bundle.getEntry().get( 0 ).getResponse().getLocation() ); + Assert.assertEquals( "201 Created", bundle.getEntry().get( 0 ).getResponse().getStatus() ); + Assert.assertNull( bundle.getEntry().get( 0 ).getResponse().getOutcome() ); + } + + @Test + public void createBatchResponseOk() + { + final List operations = new ArrayList<>(); + operations.add( new FhirOperation( FhirOperationType.PUT, FhirResourceType.PATIENT, patientClientResource, "4711", new Patient(), null ) ); + operations.get( 0 ).getResult().ok(); + final FhirBatchRequest batchRequest = new FhirBatchRequest( operations, false ); + + final Bundle bundle = provider.createBatchResponse( batchRequest ); + Assert.assertEquals( Bundle.BundleType.BATCHRESPONSE, bundle.getType() ); + Assert.assertEquals( 1, bundle.getEntry().size() ); + + Assert.assertNull( bundle.getEntry().get( 0 ).getResponse().getLocation() ); + Assert.assertEquals( "200 OK", bundle.getEntry().get( 0 ).getResponse().getStatus() ); + Assert.assertNull( bundle.getEntry().get( 0 ).getResponse().getOutcome() ); + } + + @Test + public void createBatchResponseError() + { + final List operations = new ArrayList<>(); + operations.add( new FhirOperation( FhirOperationType.PUT, FhirResourceType.PATIENT, patientClientResource, "4711", new Patient(), null ) ); + operations.get( 0 ).getResult().unprocessableEntity( "Invalid data included" ); + final FhirBatchRequest batchRequest = new FhirBatchRequest( operations, false ); + + final Bundle bundle = provider.createBatchResponse( batchRequest ); + Assert.assertEquals( Bundle.BundleType.BATCHRESPONSE, bundle.getType() ); + Assert.assertEquals( 1, bundle.getEntry().size() ); + + Assert.assertNull( bundle.getEntry().get( 0 ).getResponse().getLocation() ); + Assert.assertEquals( "422 Unprocessable entity", bundle.getEntry().get( 0 ).getResponse().getStatus() ); + Assert.assertNotNull( bundle.getEntry().get( 0 ).getResponse().getOutcome() ); + Assert.assertNotNull( ( (OperationOutcome) bundle.getEntry().get( 0 ).getResponse().getOutcome() ).getIssue() ); + Assert.assertEquals( 1, ( (OperationOutcome) bundle.getEntry().get( 0 ).getResponse().getOutcome() ).getIssue().size() ); + Assert.assertEquals( "Invalid data included", ( (OperationOutcome) bundle.getEntry().get( 0 ).getResponse().getOutcome() ).getIssueFirstRep().getDiagnostics() ); + } + + @Test + public void createBatchResponseNotProcessed() + { + final List operations = new ArrayList<>(); + operations.add( new FhirOperation( FhirOperationType.PUT, FhirResourceType.PATIENT, patientClientResource, "4711", new Patient(), null ) ); + final FhirBatchRequest batchRequest = new FhirBatchRequest( operations, false ); + + final Bundle bundle = provider.createBatchResponse( batchRequest ); + Assert.assertEquals( Bundle.BundleType.BATCHRESPONSE, bundle.getType() ); + Assert.assertEquals( 1, bundle.getEntry().size() ); + + Assert.assertNull( bundle.getEntry().get( 0 ).getResponse().getLocation() ); + Assert.assertEquals( "500 Internal server error", bundle.getEntry().get( 0 ).getResponse().getStatus() ); + Assert.assertNotNull( bundle.getEntry().get( 0 ).getResponse().getOutcome() ); + Assert.assertNotNull( ( (OperationOutcome) bundle.getEntry().get( 0 ).getResponse().getOutcome() ).getIssue() ); + Assert.assertEquals( 1, ( (OperationOutcome) bundle.getEntry().get( 0 ).getResponse().getOutcome() ).getIssue().size() ); + Assert.assertEquals( "Operation has not been processed.", ( (OperationOutcome) bundle.getEntry().get( 0 ).getResponse().getOutcome() ).getIssueFirstRep().getDiagnostics() ); + } + + @Test + public void createBatchRequest() + { + Mockito.when( fhirClientResourceRepository.findFirstCached( Mockito.eq( fhirClient.getId() ), Mockito.eq( FhirResourceType.PATIENT ) ) ) + .thenReturn( Optional.of( patientClientResource ) ); + + final Bundle bundle = new Bundle(); + bundle.setType( Bundle.BundleType.BATCH ); + bundle.addEntry().setResource( new Patient() ).getRequest().setMethod( Bundle.HTTPVerb.POST ); + bundle.addEntry().setResource( new Patient() ).getRequest().setMethod( Bundle.HTTPVerb.POST ); + + final FhirBatchRequest batchRequest = provider.createBatchRequest( bundle ); + Assert.assertFalse( batchRequest.isTransactional() ); + Assert.assertEquals( 2, batchRequest.getOperations().size() ); + + Assert.assertFalse( batchRequest.getOperations().get( 0 ).isProcessed() ); + Assert.assertNotNull( batchRequest.getOperations().get( 0 ).getResource() ); + Assert.assertEquals( FhirOperationType.POST, batchRequest.getOperations().get( 0 ).getOperationType() ); + + Assert.assertFalse( batchRequest.getOperations().get( 1 ).isProcessed() ); + Assert.assertNotNull( batchRequest.getOperations().get( 1 ).getResource() ); + Assert.assertEquals( FhirOperationType.POST, batchRequest.getOperations().get( 1 ).getOperationType() ); + } + + @Test + public void createBatchRequestIfMatch() + { + final Bundle bundle = new Bundle(); + bundle.setType( Bundle.BundleType.BATCH ); + bundle.addEntry().setResource( new Patient() ).getRequest().setMethod( Bundle.HTTPVerb.POST ).setIfMatch( "xyz" ); + + final FhirBatchRequest batchRequest = provider.createBatchRequest( bundle ); + Assert.assertFalse( batchRequest.isTransactional() ); + Assert.assertEquals( 1, batchRequest.getOperations().size() ); + + Assert.assertTrue( batchRequest.getOperations().get( 0 ).isProcessed() ); + Assert.assertNotNull( batchRequest.getOperations().get( 0 ).getResult().getIssue() ); + } + + @Test + public void createBatchRequestIfModifiedSince() + { + final Bundle bundle = new Bundle(); + bundle.setType( Bundle.BundleType.BATCH ); + bundle.addEntry().setResource( new Patient() ).getRequest().setMethod( Bundle.HTTPVerb.POST ).setIfModifiedSince( new Date() ); + + final FhirBatchRequest batchRequest = provider.createBatchRequest( bundle ); + Assert.assertFalse( batchRequest.isTransactional() ); + Assert.assertEquals( 1, batchRequest.getOperations().size() ); + + Assert.assertTrue( batchRequest.getOperations().get( 0 ).isProcessed() ); + Assert.assertNotNull( batchRequest.getOperations().get( 0 ).getResult().getIssue() ); + } + + @Test + public void createBatchRequestIfNoneExist() + { + final Bundle bundle = new Bundle(); + bundle.setType( Bundle.BundleType.BATCH ); + bundle.addEntry().setResource( new Patient() ).getRequest().setMethod( Bundle.HTTPVerb.POST ).setIfNoneExist( "xyz" ); + + final FhirBatchRequest batchRequest = provider.createBatchRequest( bundle ); + Assert.assertFalse( batchRequest.isTransactional() ); + Assert.assertEquals( 1, batchRequest.getOperations().size() ); + + Assert.assertTrue( batchRequest.getOperations().get( 0 ).isProcessed() ); + Assert.assertNotNull( batchRequest.getOperations().get( 0 ).getResult().getIssue() ); + } + + @Test + public void createBatchRequestIfNoneMatch() + { + final Bundle bundle = new Bundle(); + bundle.setType( Bundle.BundleType.BATCH ); + bundle.addEntry().setResource( new Patient() ).getRequest().setMethod( Bundle.HTTPVerb.POST ).setIfNoneExist( "xyz" ); + + final FhirBatchRequest batchRequest = provider.createBatchRequest( bundle ); + Assert.assertFalse( batchRequest.isTransactional() ); + Assert.assertEquals( 1, batchRequest.getOperations().size() ); + + Assert.assertTrue( batchRequest.getOperations().get( 0 ).isProcessed() ); + Assert.assertNotNull( batchRequest.getOperations().get( 0 ).getResult().getIssue() ); + } + + @Test + public void testConvertInvalid() + { + Assert.assertEquals( OperationOutcome.IssueType.INVALID, provider.convert( FhirOperationIssueType.INVALID ) ); + } + + @Test + public void testConvertProcessing() + { + Assert.assertEquals( OperationOutcome.IssueType.PROCESSING, provider.convert( FhirOperationIssueType.PROCESSING ) ); + } + + @Test + public void testConvertTransient() + { + Assert.assertEquals( OperationOutcome.IssueType.TRANSIENT, provider.convert( FhirOperationIssueType.TRANSIENT ) ); + } + + @Test + public void testConvertInformational() + { + Assert.assertEquals( OperationOutcome.IssueType.INFORMATIONAL, provider.convert( FhirOperationIssueType.INFORMATIONAL ) ); + } + + @Test + public void testConvertInformation() + { + Assert.assertEquals( OperationOutcome.IssueSeverity.INFORMATION, provider.convert( FhirOperationIssueSeverity.INFO ) ); + } + + @Test + public void testConvertWarning() + { + Assert.assertEquals( OperationOutcome.IssueSeverity.WARNING, provider.convert( FhirOperationIssueSeverity.WARN ) ); + } + + @Test + public void testConvertError() + { + Assert.assertEquals( OperationOutcome.IssueSeverity.ERROR, provider.convert( FhirOperationIssueSeverity.ERROR ) ); + } + + @Test + public void testConvertFatal() + { + Assert.assertEquals( OperationOutcome.IssueSeverity.FATAL, provider.convert( FhirOperationIssueSeverity.FATAL ) ); + } +} \ No newline at end of file diff --git a/fhir-r4/src/test/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4BundleResourceProviderTest.java b/fhir-r4/src/test/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4BundleResourceProviderTest.java new file mode 100644 index 00000000..a48678f8 --- /dev/null +++ b/fhir-r4/src/test/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4BundleResourceProviderTest.java @@ -0,0 +1,325 @@ +package org.dhis2.fhir.adapter.fhir.server.provider.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 ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; +import org.dhis2.fhir.adapter.cache.RequestCacheService; +import org.dhis2.fhir.adapter.fhir.metadata.model.FhirClient; +import org.dhis2.fhir.adapter.fhir.metadata.model.FhirClientResource; +import org.dhis2.fhir.adapter.fhir.metadata.model.FhirResourceType; +import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientResourceRepository; +import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientSystemRepository; +import org.dhis2.fhir.adapter.fhir.model.FhirVersion; +import org.dhis2.fhir.adapter.fhir.repository.DhisRepository; +import org.dhis2.fhir.adapter.fhir.repository.FhirBatchRequest; +import org.dhis2.fhir.adapter.fhir.repository.FhirOperation; +import org.dhis2.fhir.adapter.fhir.repository.FhirOperationIssueSeverity; +import org.dhis2.fhir.adapter.fhir.repository.FhirOperationIssueType; +import org.dhis2.fhir.adapter.fhir.repository.FhirOperationType; +import org.dhis2.fhir.adapter.fhir.repository.FhirRepository; +import org.hl7.fhir.r4.model.Bundle; +import org.hl7.fhir.r4.model.OperationOutcome; +import org.hl7.fhir.r4.model.Patient; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Optional; + +/** + * Unit tests for {@link R4BundleResourceProvider}. + * + * @author volsch + */ +public class R4BundleResourceProviderTest +{ + @Mock + private FhirClientResourceRepository fhirClientResourceRepository; + + @Mock + private FhirClientSystemRepository fhirClientSystemRepository; + + @Mock + private FhirRepository fhirRepository; + + @Mock + private DhisRepository dhisRepository; + + @Mock + private RequestCacheService requestCacheService; + + @InjectMocks + private R4BundleResourceProvider provider; + + private FhirClient fhirClient = new FhirClient(); + + private FhirClientResource patientClientResource = new FhirClientResource(); + + private FhirClientResource observationClientResource = new FhirClientResource(); + + @Rule + public MockitoRule rule = MockitoJUnit.rule(); + + @Before + public void setUp() + { + fhirClient.setId( FhirClient.getIdByFhirVersion( FhirVersion.R4 ) ); + patientClientResource.setFhirClient( fhirClient ); + observationClientResource.setFhirClient( fhirClient ); + } + + @Test + public void getFhirVersion() + { + Assert.assertEquals( FhirVersion.R4, provider.getFhirVersion() ); + } + + @Test( expected = InvalidRequestException.class ) + public void transactionBundle() + { + final Bundle bundle = new Bundle(); + bundle.setType( Bundle.BundleType.TRANSACTION ); + provider.createBatchRequest( bundle ); + } + + @Test + public void createBatchResponseCreated() + { + final List operations = new ArrayList<>(); + operations.add( new FhirOperation( FhirOperationType.POST, FhirResourceType.PATIENT, patientClientResource, null, new Patient(), null ) ); + operations.get( 0 ).getResult().created( new IdDt( "123" ) ); + final FhirBatchRequest batchRequest = new FhirBatchRequest( operations, false ); + + final Bundle bundle = provider.createBatchResponse( batchRequest ); + Assert.assertEquals( Bundle.BundleType.BATCHRESPONSE, bundle.getType() ); + Assert.assertEquals( 1, bundle.getEntry().size() ); + + Assert.assertEquals( "Patient/123", bundle.getEntry().get( 0 ).getResponse().getLocation() ); + Assert.assertEquals( "201 Created", bundle.getEntry().get( 0 ).getResponse().getStatus() ); + Assert.assertNull( bundle.getEntry().get( 0 ).getResponse().getOutcome() ); + } + + @Test + public void createBatchResponseOk() + { + final List operations = new ArrayList<>(); + operations.add( new FhirOperation( FhirOperationType.PUT, FhirResourceType.PATIENT, patientClientResource, "4711", new Patient(), null ) ); + operations.get( 0 ).getResult().ok(); + final FhirBatchRequest batchRequest = new FhirBatchRequest( operations, false ); + + final Bundle bundle = provider.createBatchResponse( batchRequest ); + Assert.assertEquals( Bundle.BundleType.BATCHRESPONSE, bundle.getType() ); + Assert.assertEquals( 1, bundle.getEntry().size() ); + + Assert.assertNull( bundle.getEntry().get( 0 ).getResponse().getLocation() ); + Assert.assertEquals( "200 OK", bundle.getEntry().get( 0 ).getResponse().getStatus() ); + Assert.assertNull( bundle.getEntry().get( 0 ).getResponse().getOutcome() ); + } + + @Test + public void createBatchResponseError() + { + final List operations = new ArrayList<>(); + operations.add( new FhirOperation( FhirOperationType.PUT, FhirResourceType.PATIENT, patientClientResource, "4711", new Patient(), null ) ); + operations.get( 0 ).getResult().unprocessableEntity( "Invalid data included" ); + final FhirBatchRequest batchRequest = new FhirBatchRequest( operations, false ); + + final Bundle bundle = provider.createBatchResponse( batchRequest ); + Assert.assertEquals( Bundle.BundleType.BATCHRESPONSE, bundle.getType() ); + Assert.assertEquals( 1, bundle.getEntry().size() ); + + Assert.assertNull( bundle.getEntry().get( 0 ).getResponse().getLocation() ); + Assert.assertEquals( "422 Unprocessable entity", bundle.getEntry().get( 0 ).getResponse().getStatus() ); + Assert.assertNotNull( bundle.getEntry().get( 0 ).getResponse().getOutcome() ); + Assert.assertNotNull( ( (OperationOutcome) bundle.getEntry().get( 0 ).getResponse().getOutcome() ).getIssue() ); + Assert.assertEquals( 1, ( (OperationOutcome) bundle.getEntry().get( 0 ).getResponse().getOutcome() ).getIssue().size() ); + Assert.assertEquals( "Invalid data included", ( (OperationOutcome) bundle.getEntry().get( 0 ).getResponse().getOutcome() ).getIssueFirstRep().getDiagnostics() ); + } + + @Test + public void createBatchResponseNotProcessed() + { + final List operations = new ArrayList<>(); + operations.add( new FhirOperation( FhirOperationType.PUT, FhirResourceType.PATIENT, patientClientResource, "4711", new Patient(), null ) ); + final FhirBatchRequest batchRequest = new FhirBatchRequest( operations, false ); + + final Bundle bundle = provider.createBatchResponse( batchRequest ); + Assert.assertEquals( Bundle.BundleType.BATCHRESPONSE, bundle.getType() ); + Assert.assertEquals( 1, bundle.getEntry().size() ); + + Assert.assertNull( bundle.getEntry().get( 0 ).getResponse().getLocation() ); + Assert.assertEquals( "500 Internal server error", bundle.getEntry().get( 0 ).getResponse().getStatus() ); + Assert.assertNotNull( bundle.getEntry().get( 0 ).getResponse().getOutcome() ); + Assert.assertNotNull( ( (OperationOutcome) bundle.getEntry().get( 0 ).getResponse().getOutcome() ).getIssue() ); + Assert.assertEquals( 1, ( (OperationOutcome) bundle.getEntry().get( 0 ).getResponse().getOutcome() ).getIssue().size() ); + Assert.assertEquals( "Operation has not been processed.", ( (OperationOutcome) bundle.getEntry().get( 0 ).getResponse().getOutcome() ).getIssueFirstRep().getDiagnostics() ); + } + + @Test + public void createBatchRequest() + { + Mockito.when( fhirClientResourceRepository.findFirstCached( Mockito.eq( fhirClient.getId() ), Mockito.eq( FhirResourceType.PATIENT ) ) ) + .thenReturn( Optional.of( patientClientResource ) ); + + final Bundle bundle = new Bundle(); + bundle.setType( Bundle.BundleType.BATCH ); + bundle.addEntry().setResource( new Patient() ).getRequest().setMethod( Bundle.HTTPVerb.POST ); + bundle.addEntry().setResource( new Patient() ).getRequest().setMethod( Bundle.HTTPVerb.POST ); + + final FhirBatchRequest batchRequest = provider.createBatchRequest( bundle ); + Assert.assertFalse( batchRequest.isTransactional() ); + Assert.assertEquals( 2, batchRequest.getOperations().size() ); + + Assert.assertFalse( batchRequest.getOperations().get( 0 ).isProcessed() ); + Assert.assertNotNull( batchRequest.getOperations().get( 0 ).getResource() ); + Assert.assertEquals( FhirOperationType.POST, batchRequest.getOperations().get( 0 ).getOperationType() ); + + Assert.assertFalse( batchRequest.getOperations().get( 1 ).isProcessed() ); + Assert.assertNotNull( batchRequest.getOperations().get( 1 ).getResource() ); + Assert.assertEquals( FhirOperationType.POST, batchRequest.getOperations().get( 1 ).getOperationType() ); + } + + @Test + public void createBatchRequestIfMatch() + { + final Bundle bundle = new Bundle(); + bundle.setType( Bundle.BundleType.BATCH ); + bundle.addEntry().setResource( new Patient() ).getRequest().setMethod( Bundle.HTTPVerb.POST ).setIfMatch( "xyz" ); + + final FhirBatchRequest batchRequest = provider.createBatchRequest( bundle ); + Assert.assertFalse( batchRequest.isTransactional() ); + Assert.assertEquals( 1, batchRequest.getOperations().size() ); + + Assert.assertTrue( batchRequest.getOperations().get( 0 ).isProcessed() ); + Assert.assertNotNull( batchRequest.getOperations().get( 0 ).getResult().getIssue() ); + } + + @Test + public void createBatchRequestIfModifiedSince() + { + final Bundle bundle = new Bundle(); + bundle.setType( Bundle.BundleType.BATCH ); + bundle.addEntry().setResource( new Patient() ).getRequest().setMethod( Bundle.HTTPVerb.POST ).setIfModifiedSince( new Date() ); + + final FhirBatchRequest batchRequest = provider.createBatchRequest( bundle ); + Assert.assertFalse( batchRequest.isTransactional() ); + Assert.assertEquals( 1, batchRequest.getOperations().size() ); + + Assert.assertTrue( batchRequest.getOperations().get( 0 ).isProcessed() ); + Assert.assertNotNull( batchRequest.getOperations().get( 0 ).getResult().getIssue() ); + } + + @Test + public void createBatchRequestIfNoneExist() + { + final Bundle bundle = new Bundle(); + bundle.setType( Bundle.BundleType.BATCH ); + bundle.addEntry().setResource( new Patient() ).getRequest().setMethod( Bundle.HTTPVerb.POST ).setIfNoneExist( "xyz" ); + + final FhirBatchRequest batchRequest = provider.createBatchRequest( bundle ); + Assert.assertFalse( batchRequest.isTransactional() ); + Assert.assertEquals( 1, batchRequest.getOperations().size() ); + + Assert.assertTrue( batchRequest.getOperations().get( 0 ).isProcessed() ); + Assert.assertNotNull( batchRequest.getOperations().get( 0 ).getResult().getIssue() ); + } + + @Test + public void createBatchRequestIfNoneMatch() + { + final Bundle bundle = new Bundle(); + bundle.setType( Bundle.BundleType.BATCH ); + bundle.addEntry().setResource( new Patient() ).getRequest().setMethod( Bundle.HTTPVerb.POST ).setIfNoneExist( "xyz" ); + + final FhirBatchRequest batchRequest = provider.createBatchRequest( bundle ); + Assert.assertFalse( batchRequest.isTransactional() ); + Assert.assertEquals( 1, batchRequest.getOperations().size() ); + + Assert.assertTrue( batchRequest.getOperations().get( 0 ).isProcessed() ); + Assert.assertNotNull( batchRequest.getOperations().get( 0 ).getResult().getIssue() ); + } + + @Test + public void testConvertInvalid() + { + Assert.assertEquals( OperationOutcome.IssueType.INVALID, provider.convert( FhirOperationIssueType.INVALID ) ); + } + + @Test + public void testConvertProcessing() + { + Assert.assertEquals( OperationOutcome.IssueType.PROCESSING, provider.convert( FhirOperationIssueType.PROCESSING ) ); + } + + @Test + public void testConvertTransient() + { + Assert.assertEquals( OperationOutcome.IssueType.TRANSIENT, provider.convert( FhirOperationIssueType.TRANSIENT ) ); + } + + @Test + public void testConvertInformational() + { + Assert.assertEquals( OperationOutcome.IssueType.INFORMATIONAL, provider.convert( FhirOperationIssueType.INFORMATIONAL ) ); + } + + @Test + public void testConvertInformation() + { + Assert.assertEquals( OperationOutcome.IssueSeverity.INFORMATION, provider.convert( FhirOperationIssueSeverity.INFO ) ); + } + + @Test + public void testConvertWarning() + { + Assert.assertEquals( OperationOutcome.IssueSeverity.WARNING, provider.convert( FhirOperationIssueSeverity.WARN ) ); + } + + @Test + public void testConvertError() + { + Assert.assertEquals( OperationOutcome.IssueSeverity.ERROR, provider.convert( FhirOperationIssueSeverity.ERROR ) ); + } + + @Test + public void testConvertFatal() + { + Assert.assertEquals( OperationOutcome.IssueSeverity.FATAL, provider.convert( FhirOperationIssueSeverity.FATAL ) ); + } +} \ No newline at end of file diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/FhirClientSystem.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/FhirClientSystem.java index d7944d72..755d7338 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/FhirClientSystem.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/FhirClientSystem.java @@ -34,6 +34,7 @@ import org.dhis2.fhir.adapter.model.VersionedBaseMetadata; import org.dhis2.fhir.adapter.validator.EnumValue; +import javax.annotation.Nonnull; import javax.persistence.Basic; import javax.persistence.Column; import javax.persistence.Entity; @@ -78,6 +79,16 @@ public class FhirClientSystem extends VersionedBaseMetadata implements Serializa @Size( max = MAX_DEFAULT_VALUE_LENGTH ) private String defaultValue; + public FhirClientSystem() + { + super(); + } + + public FhirClientSystem( @Nonnull System system ) + { + this.system = system; + } + @Basic @Column( name = "fhir_resource_type", nullable = false, length = 30 ) @Enumerated( EnumType.STRING ) diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/System.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/System.java index 3b3d6b2a..9213e45d 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/System.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/System.java @@ -35,6 +35,7 @@ import org.hibernate.annotations.BatchSize; import org.springframework.data.rest.core.annotation.RestResource; +import javax.annotation.Nonnull; import javax.persistence.Basic; import javax.persistence.Column; import javax.persistence.Entity; @@ -93,6 +94,16 @@ public class System extends VersionedBaseMetadata implements SystemDependent, Se private Collection systemCodes; + public System() + { + super(); + } + + public System( @Nonnull String systemUri ) + { + this.systemUri = systemUri; + } + @Basic @Column( name = "name", nullable = false, length = 230 ) public String getName() diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/repository/DhisFhirResourceId.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/repository/DhisFhirResourceId.java index 6acb1b53..341a7936 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/repository/DhisFhirResourceId.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/repository/DhisFhirResourceId.java @@ -35,6 +35,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.io.Serializable; +import java.util.Objects; import java.util.UUID; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -87,6 +88,30 @@ public DhisResourceId getDhisResourceId() return new DhisResourceId( getType(), getId() ); } + @Override + public boolean equals( Object o ) + { + if ( this == o ) + { + return true; + } + + if ( o == null || getClass() != o.getClass() ) + { + return false; + } + + DhisFhirResourceId that = (DhisFhirResourceId) o; + + return getType() == that.getType() && getId().equals( that.getId() ) && getRuleId().equals( that.getRuleId() ); + } + + @Override + public int hashCode() + { + return Objects.hash( getType(), getId(), getRuleId() ); + } + @Override @Nonnull public String toString() diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/repository/FhirOperationIssue.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/repository/FhirOperationIssue.java index 762808a5..41020d93 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/repository/FhirOperationIssue.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/repository/FhirOperationIssue.java @@ -72,4 +72,10 @@ public String getDiagnostics() { return diagnostics; } + + @Override + public String toString() + { + return "FhirOperationIssue{severity=" + severity + ", type=" + type + ", diagnostics='" + diagnostics + "\'}"; + } } diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/repository/FhirOperationResult.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/repository/FhirOperationResult.java index 7ff6afdb..ccbc52de 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/repository/FhirOperationResult.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/repository/FhirOperationResult.java @@ -69,6 +69,16 @@ public class FhirOperationResult implements Serializable private FhirOperationIssue issue; + public FhirOperationResult() + { + super(); + } + + public FhirOperationResult( int statusCode ) + { + this.statusCode = statusCode; + } + public int getStatusCode() { return statusCode; diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/repository/FhirRepositoryOperation.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/repository/FhirRepositoryOperation.java index 45fadcce..b4168f73 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/repository/FhirRepositoryOperation.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/repository/FhirRepositoryOperation.java @@ -31,6 +31,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.io.Serializable; +import java.util.Objects; /** * Specifies the FHIR repository operation to be performed. @@ -67,4 +68,28 @@ public DhisFhirResourceId getDhisFhirResourceId() { return dhisFhirResourceId; } + + @Override + public boolean equals( Object o ) + { + if ( this == o ) + { + return true; + } + + if ( o == null || getClass() != o.getClass() ) + { + return false; + } + + FhirRepositoryOperation that = (FhirRepositoryOperation) o; + + return getOperationType() == that.getOperationType() && Objects.equals( getDhisFhirResourceId(), that.getDhisFhirResourceId() ); + } + + @Override + public int hashCode() + { + return Objects.hash( getOperationType(), getDhisFhirResourceId() ); + } } diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/AbstractBundleResourceProvider.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/AbstractBundleResourceProvider.java index 44684dc5..85e18215 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/AbstractBundleResourceProvider.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/AbstractBundleResourceProvider.java @@ -254,7 +254,7 @@ private void handleException( @Nonnull FhirOperation o, @Nonnull Exception e ) @Nullable private DhisFhirResourceId extractDhisResourceId( @Nonnull FhirOperation o, boolean ignoreNotFound ) { - DhisFhirResourceId dhisFhirResourceId; + DhisFhirResourceId dhisFhirResourceId = null; if ( hasConditionalReferenceUrl( o ) ) { @@ -272,7 +272,7 @@ private DhisFhirResourceId extractDhisResourceId( @Nonnull FhirOperation o, bool dhisFhirResourceId = DhisFhirResourceId.parse( resource.getIdElement().getIdPart() ); } - else + else if ( StringUtils.isNotBlank( o.getResourceId() ) ) { try { @@ -316,12 +316,14 @@ protected IBaseResource lookupConditionalReferenceUrl( @Nonnull FhirOperation op if ( identifiers == null ) { operation.getResult().badRequest( "Only identifiers are supported as conditional references in URLs." ); + return null; } if ( identifiers.size() > 1 ) { operation.getResult().badRequest( "Conditional reference in URL must not contain more than one identifier." ); + return null; } @@ -455,16 +457,16 @@ protected FhirOperationType getOperationType( @Nullable String httpVerb ) } @Nullable - protected URI parseUri( @Nullable String url ) + protected URI parseUri( @Nullable String uri ) { - if ( url == null ) + if ( uri == null ) { return null; } try { - return new URI( url ); + return new URI( uri ); } catch ( URISyntaxException e ) { @@ -521,6 +523,9 @@ protected String getStatus( @Nonnull FhirOperationResult result ) case FhirOperationResult.NOT_FOUND_STATUS_CODE: statusMessage = "Not found"; break; + case FhirOperationResult.UNPROCESSABLE_ENTITY_STATUS_CODE: + statusMessage = "Unprocessable entity"; + break; case FhirOperationResult.INTERNAL_SERVER_ERROR_STATUS_CODE: statusMessage = "Internal server error"; break; diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/AbstractUntypedResourceProvider.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/AbstractUntypedResourceProvider.java index f2ddaa76..f0cbf43b 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/AbstractUntypedResourceProvider.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/AbstractUntypedResourceProvider.java @@ -166,6 +166,7 @@ protected FhirClientSystem getFhirClientSystem( @Nonnull FhirResourceType fhirRe protected void validateUseCase( @Nonnull RequestDetails theRequestDetails ) { final String tenantId = theRequestDetails.getTenantId(); + if ( !DEFAULT_USE_CASE_TENANT.equals( tenantId ) ) { throw new InvalidRequestException( "Selected use case must be default (received " + tenantId + ")." ); diff --git a/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/server/provider/AbstractBundleResourceProviderTest.java b/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/server/provider/AbstractBundleResourceProviderTest.java new file mode 100644 index 00000000..e9601863 --- /dev/null +++ b/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/server/provider/AbstractBundleResourceProviderTest.java @@ -0,0 +1,717 @@ +package org.dhis2.fhir.adapter.fhir.server.provider; + +/* + * 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.context.FhirVersionEnum; +import ca.uhn.fhir.model.primitive.IdDt; +import ca.uhn.fhir.rest.api.server.RequestDetails; +import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; +import org.dhis2.fhir.adapter.cache.RequestCacheService; +import org.dhis2.fhir.adapter.fhir.metadata.model.FhirClient; +import org.dhis2.fhir.adapter.fhir.metadata.model.FhirClientResource; +import org.dhis2.fhir.adapter.fhir.metadata.model.FhirClientSystem; +import org.dhis2.fhir.adapter.fhir.metadata.model.FhirResourceType; +import org.dhis2.fhir.adapter.fhir.metadata.model.System; +import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientResourceRepository; +import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientSystemRepository; +import org.dhis2.fhir.adapter.fhir.model.FhirVersion; +import org.dhis2.fhir.adapter.fhir.repository.DhisFhirResourceId; +import org.dhis2.fhir.adapter.fhir.repository.DhisRepository; +import org.dhis2.fhir.adapter.fhir.repository.FhirBatchRequest; +import org.dhis2.fhir.adapter.fhir.repository.FhirOperation; +import org.dhis2.fhir.adapter.fhir.repository.FhirOperationResult; +import org.dhis2.fhir.adapter.fhir.repository.FhirOperationType; +import org.dhis2.fhir.adapter.fhir.repository.FhirRepository; +import org.dhis2.fhir.adapter.fhir.repository.FhirRepositoryOperation; +import org.dhis2.fhir.adapter.fhir.repository.FhirRepositoryOperationOutcome; +import org.dhis2.fhir.adapter.fhir.repository.FhirRepositoryOperationType; +import org.hamcrest.Matchers; +import org.hl7.fhir.instance.model.api.IBaseBundle; +import org.hl7.fhir.instance.model.api.IBaseMetaType; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IIdType; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +import static org.dhis2.fhir.adapter.fhir.metadata.model.FhirClient.FHIR_REST_INTERFACE_DSTU3_ID; + +/** + * Unit tests for {@link AbstractBundleResourceProviderTest}. + * + * @author volsch + */ +public class AbstractBundleResourceProviderTest +{ + private AbstractBundleResourceProvider bundleResourceProvider; + + @Mock + private IBaseBundle baseBundle; + + @Mock + private IBaseBundle resultBaseBundle; + + @Mock + private IBaseResource baseResource1; + + @Mock + private IBaseResource baseResource2; + + @Mock + private IBaseResource baseResource3; + + @Mock + private IBaseResource baseResource4; + + @Mock + private IBaseResource baseResource5; + + @Mock + private IBaseResource baseResource6; + + @Mock + private FhirClientResourceRepository fhirClientResourceRepository; + + @Mock + private FhirClientSystemRepository fhirClientSystemRepository; + + @Mock + private FhirRepository fhirRepository; + + @Mock + private DhisRepository dhisRepository; + + @Mock + private RequestCacheService requestCacheService; + + @Mock + private RequestDetails requestDetails; + + private FhirClient fhirClient = new FhirClient(); + + private FhirClientResource patientClientResource = new FhirClientResource(); + + private FhirClientResource observationClientResource = new FhirClientResource(); + + private FhirClientSystem patientClientSystem; + + @Rule + public MockitoRule mockitoRule = MockitoJUnit.rule(); + + @Before + @SuppressWarnings( { "unchecked" } ) + public void setUp() + { + bundleResourceProvider = Mockito.mock( AbstractBundleResourceProvider.class, Mockito.withSettings() + .useConstructor( fhirClientResourceRepository, fhirClientSystemRepository, fhirRepository, dhisRepository, requestCacheService ) + .defaultAnswer( Mockito.CALLS_REAL_METHODS ) ); + + fhirClient.setId( FhirClient.getIdByFhirVersion( FhirVersion.DSTU3 ) ); + patientClientResource.setFhirClient( fhirClient ); + observationClientResource.setFhirClient( fhirClient ); + + patientClientSystem = new FhirClientSystem(); + patientClientSystem.setSystem( new System( "http://test.com/patient" ) ); + } + + @Test( expected = InvalidRequestException.class ) + public void processInternalNull() + { + bundleResourceProvider.processInternal( requestDetails, null ); + } + + @Test + public void processInternal() throws Exception + { + Mockito.when( bundleResourceProvider.getFhirVersion() ).thenReturn( FhirVersion.DSTU3 ); + + final FhirOperation invalidDeleteOperation = new FhirOperation( FhirOperationType.DELETE, FhirResourceType.PATIENT, null, null, null, null ); + invalidDeleteOperation.getResult().badRequest( "Invalid data included" ); + + final FhirOperation invalidPostOperation = new FhirOperation( FhirOperationType.POST, FhirResourceType.PATIENT, null, null, null, null ); + invalidPostOperation.getResult().badRequest( "Invalid data included" ); + + final FhirOperation invalidPutOperation = new FhirOperation( FhirOperationType.PUT, FhirResourceType.PATIENT, null, null, null, null ); + invalidPutOperation.getResult().badRequest( "Invalid data included" ); + + final List operations = new ArrayList<>(); + operations.add( new FhirOperation( FhirOperationType.PUT, FhirResourceType.PATIENT, patientClientResource, "te-ldXIdLNUNE1-d0e1472a05e647c9b36bff1f06fec351", baseResource1, null ) ); + operations.add( new FhirOperation( FhirOperationType.DELETE, FhirResourceType.PATIENT, patientClientResource, "te-ldXIdLNUNE4-d0e1472a05e647c9b36bff1f06fec354", null, null ) ); + operations.add( new FhirOperation( FhirOperationType.POST, FhirResourceType.OBSERVATION, observationClientResource, null, baseResource2, null ) ); + operations.add( new FhirOperation( FhirOperationType.PUT, FhirResourceType.PATIENT, patientClientResource, "te-ldXIdLNUNE2-d0e1472a05e647c9b36bff1f06fec352", baseResource3, + new URI( "Patient?identifier=http%3A%2F%2Ftest.com%2Fpatient%7C8972" ) ) ); + operations.add( new FhirOperation( FhirOperationType.PUT, FhirResourceType.PATIENT, patientClientResource, null, baseResource4, + new URI( "Patient?identifier=http%3A%2F%2Ftest.com%2Fpatient%7C8973" ) ) ); + operations.add( new FhirOperation( FhirOperationType.DELETE, FhirResourceType.PATIENT, patientClientResource, "te-ldXIdLNUNE2-d0e1472a05e647c9b36bff1f06fec352", null, null ) ); + operations.add( new FhirOperation( FhirOperationType.POST, FhirResourceType.PATIENT, patientClientResource, "te-ldXIdLNUN12-d0e1472a05e647c9b36bff1f06fec312", baseResource5, null ) ); + operations.add( new FhirOperation( FhirOperationType.PUT, FhirResourceType.PATIENT, patientClientResource, "te-ldXIdLNUN22-d0e1472a05e647c9b36bff1f06fec322", baseResource6, null ) ); + + operations.add( invalidDeleteOperation ); + operations.add( invalidPostOperation ); + operations.add( invalidPutOperation ); + + final FhirBatchRequest batchRequest = new FhirBatchRequest( operations, false ); + + Mockito.when( requestDetails.getTenantId() ).thenReturn( "default" ); + Mockito.when( bundleResourceProvider.createBatchRequest( Mockito.same( baseBundle ) ) ).thenReturn( batchRequest ); + Mockito.when( fhirClientSystemRepository.findOneByFhirClientResourceType( Mockito.eq( FHIR_REST_INTERFACE_DSTU3_ID ), Mockito.eq( FhirResourceType.PATIENT ) ) ) + .thenReturn( Optional.of( patientClientSystem ) ); + Mockito.when( bundleResourceProvider.createBatchResponse( Mockito.same( batchRequest ) ) ).thenReturn( resultBaseBundle ); + + Mockito.when( fhirRepository.save( Mockito.same( patientClientResource ), Mockito.same( baseResource1 ), Mockito.eq( new FhirRepositoryOperation( FhirRepositoryOperationType.UPDATE ) ) ) ) + .thenReturn( new FhirRepositoryOperationOutcome( "te-ldXIdLNUNE1-d0e1472a05e647c9b36bff1f06fec351" ) ); + Mockito.when( fhirRepository.delete( Mockito.same( patientClientResource ), Mockito.eq( DhisFhirResourceId.parse( "te-ldXIdLNUNE4-d0e1472a05e647c9b36bff1f06fec354" ) ) ) ) + .thenReturn( true ); + Mockito.when( fhirRepository.save( Mockito.same( observationClientResource ), Mockito.same( baseResource2 ), Mockito.eq( new FhirRepositoryOperation( FhirRepositoryOperationType.CREATE ) ) ) ) + .thenReturn( new FhirRepositoryOperationOutcome( "te-ldXIdLNUNE9-d0e1472a05e647c9b36bff1f06fec359" ) ); + Mockito.when( dhisRepository.readByIdentifier( Mockito.same( patientClientResource.getFhirClient() ), Mockito.eq( FhirResourceType.PATIENT ), Mockito.eq( "8972" ) ) ) + .thenReturn( Optional.empty() ); + Mockito.when( fhirRepository.save( Mockito.same( patientClientResource ), Mockito.same( baseResource3 ), Mockito.eq( new FhirRepositoryOperation( FhirRepositoryOperationType.CREATE ) ) ) ) + .thenReturn( new FhirRepositoryOperationOutcome( "te-ldXIdLNUNE8-d0e1472a05e647c9b36bff1f06fec358" ) ); + Mockito.when( baseResource4.getIdElement() ).thenReturn( new IdDt( "te-ldXIdLNUNE7-d0e1472a05e647c9b36bff1f06fec357" ) ); + Mockito.when( dhisRepository.readByIdentifier( Mockito.same( patientClientResource.getFhirClient() ), Mockito.eq( FhirResourceType.PATIENT ), Mockito.eq( "8973" ) ) ) + .thenReturn( Optional.of( baseResource4 ) ); + Mockito.when( fhirRepository.save( Mockito.same( patientClientResource ), Mockito.same( baseResource4 ), Mockito.eq( new FhirRepositoryOperation( FhirRepositoryOperationType.UPDATE ) ) ) ) + .thenReturn( new FhirRepositoryOperationOutcome( "te-ldXIdLNUNE4-d0e1472a05e647c9b36bff1f06fec354" ) ); + Mockito.when( fhirRepository.delete( Mockito.same( patientClientResource ), Mockito.eq( DhisFhirResourceId.parse( "te-ldXIdLNUNE2-d0e1472a05e647c9b36bff1f06fec352" ) ) ) ) + .thenReturn( false ); + + Assert.assertSame( resultBaseBundle, bundleResourceProvider.processInternal( requestDetails, baseBundle ) ); + + Assert.assertNull( operations.get( 0 ).getResult().getIssue() ); + Assert.assertEquals( FhirOperationResult.OK_STATUS_CODE, operations.get( 0 ).getResult().getStatusCode() ); + Assert.assertNull( operations.get( 0 ).getResult().getId() ); + + Assert.assertNull( operations.get( 1 ).getResult().getIssue() ); + Assert.assertEquals( FhirOperationResult.NO_CONTENT_STATUS_CODE, operations.get( 1 ).getResult().getStatusCode() ); + Assert.assertNull( operations.get( 1 ).getResult().getId() ); + + Assert.assertNull( operations.get( 2 ).getResult().getIssue() ); + Assert.assertEquals( FhirOperationResult.CREATED_STATUS_CODE, operations.get( 2 ).getResult().getStatusCode() ); + Assert.assertEquals( new IdDt( "te-ldXIdLNUNE9-d0e1472a05e647c9b36bff1f06fec359" ), operations.get( 2 ).getResult().getId() ); + + Assert.assertNull( operations.get( 3 ).getResult().getIssue() ); + Assert.assertEquals( FhirOperationResult.CREATED_STATUS_CODE, operations.get( 3 ).getResult().getStatusCode() ); + Assert.assertEquals( new IdDt( "te-ldXIdLNUNE8-d0e1472a05e647c9b36bff1f06fec358" ), operations.get( 3 ).getResult().getId() ); + + Assert.assertNull( operations.get( 4 ).getResult().getIssue() ); + Assert.assertEquals( FhirOperationResult.OK_STATUS_CODE, operations.get( 4 ).getResult().getStatusCode() ); + Assert.assertNull( operations.get( 4 ).getResult().getId() ); + + Assert.assertNotNull( operations.get( 5 ).getResult().getIssue() ); + Assert.assertEquals( FhirOperationResult.NOT_FOUND_STATUS_CODE, operations.get( 5 ).getResult().getStatusCode() ); + Assert.assertNull( operations.get( 5 ).getResult().getId() ); + + Assert.assertNotNull( operations.get( 6 ).getResult().getIssue() ); + Assert.assertThat( operations.get( 6 ).getResult().getIssue().toString(), Matchers.containsString( "Could not find a rule that matches" ) ); + + Assert.assertNotNull( operations.get( 7 ).getResult().getIssue() ); + Assert.assertThat( operations.get( 7 ).getResult().getIssue().toString(), Matchers.containsString( "Could not find a rule that matches" ) ); + + Assert.assertNotNull( operations.get( 8 ).getResult().getIssue() ); + Assert.assertThat( operations.get( 8 ).getResult().getIssue().toString(), Matchers.containsString( "Invalid data included" ) ); + + Assert.assertNotNull( operations.get( 9 ).getResult().getIssue() ); + Assert.assertThat( operations.get( 9 ).getResult().getIssue().toString(), Matchers.containsString( "Invalid data included" ) ); + + Assert.assertNotNull( operations.get( 10 ).getResult().getIssue() ); + Assert.assertThat( operations.get( 10 ).getResult().getIssue().toString(), Matchers.containsString( "Invalid data included" ) ); + } + + @Test + public void processInternalReferenceNotFound() throws Exception + { + Mockito.when( bundleResourceProvider.getFhirVersion() ).thenReturn( FhirVersion.DSTU3 ); + + final List operations = new ArrayList<>(); + operations.add( new FhirOperation( FhirOperationType.DELETE, FhirResourceType.PATIENT, patientClientResource, null, null, + new URI( "Patient?identifier=http%3A%2F%2Ftest.com%2Fpatient%7C8972" ) ) ); + + final FhirBatchRequest batchRequest = new FhirBatchRequest( operations, false ); + + Mockito.when( requestDetails.getTenantId() ).thenReturn( "default" ); + Mockito.when( bundleResourceProvider.createBatchRequest( Mockito.same( baseBundle ) ) ).thenReturn( batchRequest ); + Mockito.when( fhirClientSystemRepository.findOneByFhirClientResourceType( Mockito.eq( FHIR_REST_INTERFACE_DSTU3_ID ), Mockito.eq( FhirResourceType.PATIENT ) ) ) + .thenReturn( Optional.of( patientClientSystem ) ); + Mockito.when( bundleResourceProvider.createBatchResponse( Mockito.same( batchRequest ) ) ).thenReturn( resultBaseBundle ); + + Assert.assertSame( resultBaseBundle, bundleResourceProvider.processInternal( requestDetails, baseBundle ) ); + + Assert.assertNotNull( operations.get( 0 ).getResult().getIssue() ); + Assert.assertEquals( FhirOperationResult.NOT_FOUND_STATUS_CODE, operations.get( 0 ).getResult().getStatusCode() ); + Assert.assertNull( operations.get( 0 ).getResult().getId() ); + } + + @Test + public void createOperationUrlWithoutResourceType() + { + Mockito.when( bundleResourceProvider.getFhirVersion() ).thenReturn( FhirVersion.DSTU3 ); + Mockito.when( fhirClientResourceRepository.findFirstCached( Mockito.eq( fhirClient.getId() ), Mockito.eq( FhirResourceType.PATIENT ) ) ) + .thenReturn( Optional.of( patientClientResource ) ); + + final FhirOperation fhirOperation = bundleResourceProvider.createOperation( "http://xyz.com/Patient/4811", null, "delete", "4711" ); + + Assert.assertFalse( fhirOperation.isProcessed() ); + Assert.assertEquals( FhirOperationType.DELETE, fhirOperation.getOperationType() ); + Assert.assertEquals( FhirResourceType.PATIENT, fhirOperation.getFhirResourceType() ); + Assert.assertEquals( "4711", fhirOperation.getResourceId() ); + } + + @Test + public void createOperationUrlWithResourceType() + { + Mockito.when( bundleResourceProvider.getFhirVersion() ).thenReturn( FhirVersion.DSTU3 ); + Mockito.when( fhirClientResourceRepository.findFirstCached( Mockito.eq( fhirClient.getId() ), Mockito.eq( FhirResourceType.PATIENT ) ) ) + .thenReturn( Optional.of( patientClientResource ) ); + + final FhirOperation fhirOperation = bundleResourceProvider.createOperation( "http://xyz.com/Observation/4811", null, "delete", "Patient/4711" ); + + Assert.assertFalse( fhirOperation.isProcessed() ); + Assert.assertEquals( FhirOperationType.DELETE, fhirOperation.getOperationType() ); + Assert.assertEquals( FhirResourceType.PATIENT, fhirOperation.getFhirResourceType() ); + Assert.assertEquals( "4711", fhirOperation.getResourceId() ); + } + + @Test + public void createOperationResourceOnly() + { + Mockito.when( bundleResourceProvider.getFhirVersion() ).thenReturn( FhirVersion.DSTU3 ); + Mockito.when( fhirClientResourceRepository.findFirstCached( Mockito.eq( fhirClient.getId() ), Mockito.eq( FhirResourceType.PATIENT ) ) ) + .thenReturn( Optional.of( patientClientResource ) ); + + final FhirOperation fhirOperation = bundleResourceProvider.createOperation( null, new Patient(), "POST", null ); + + Assert.assertFalse( fhirOperation.isProcessed() ); + Assert.assertEquals( FhirOperationType.POST, fhirOperation.getOperationType() ); + Assert.assertEquals( FhirResourceType.PATIENT, fhirOperation.getFhirResourceType() ); + Assert.assertNull( fhirOperation.getResourceId() ); + } + + @Test + public void createOperationUnhandledResource() + { + Mockito.when( bundleResourceProvider.getFhirVersion() ).thenReturn( FhirVersion.DSTU3 ); + + final FhirOperation fhirOperation = bundleResourceProvider.createOperation( null, new MeasureReport(), "POST", null ); + + Assert.assertTrue( fhirOperation.isProcessed() ); + Assert.assertEquals( FhirOperationType.POST, fhirOperation.getOperationType() ); + Assert.assertEquals( FhirResourceType.MEASURE_REPORT, fhirOperation.getFhirResourceType() ); + Assert.assertNull( fhirOperation.getResourceId() ); + } + + @Test + public void createOperationUnknownHttpVerb() + { + Mockito.when( bundleResourceProvider.getFhirVersion() ).thenReturn( FhirVersion.DSTU3 ); + Mockito.when( fhirClientResourceRepository.findFirstCached( Mockito.eq( fhirClient.getId() ), Mockito.eq( FhirResourceType.PATIENT ) ) ) + .thenReturn( Optional.of( patientClientResource ) ); + + final FhirOperation fhirOperation = bundleResourceProvider.createOperation( null, new Patient(), "xPOST", null ); + + Assert.assertTrue( fhirOperation.isProcessed() ); + Assert.assertEquals( FhirOperationResult.BAD_REQUEST_STATUS_CODE, fhirOperation.getResult().getStatusCode() ); + Assert.assertEquals( FhirOperationType.UNKNOWN, fhirOperation.getOperationType() ); + } + + @Test + public void createOperationUndefinedResourceType() + { + final FhirOperation fhirOperation = bundleResourceProvider.createOperation( null, null, "delete", "4711" ); + + Assert.assertTrue( fhirOperation.isProcessed() ); + Assert.assertEquals( FhirOperationResult.BAD_REQUEST_STATUS_CODE, fhirOperation.getResult().getStatusCode() ); + Assert.assertEquals( FhirOperationType.DELETE, fhirOperation.getOperationType() ); + } + + @Test + public void createOperationInvalidUri() + { + Mockito.when( bundleResourceProvider.getFhirVersion() ).thenReturn( FhirVersion.DSTU3 ); + Mockito.when( fhirClientResourceRepository.findFirstCached( Mockito.eq( fhirClient.getId() ), Mockito.eq( FhirResourceType.PATIENT ) ) ) + .thenReturn( Optional.of( patientClientResource ) ); + + final FhirOperation fhirOperation = bundleResourceProvider.createOperation( null, new Patient(), "post", ":%727" ); + + Assert.assertTrue( fhirOperation.isProcessed() ); + Assert.assertEquals( FhirOperationResult.BAD_REQUEST_STATUS_CODE, fhirOperation.getResult().getStatusCode() ); + Assert.assertEquals( FhirOperationType.POST, fhirOperation.getOperationType() ); + } + + @Test + public void createOperationPostWithoutResource() + { + final FhirOperation fhirOperation = bundleResourceProvider.createOperation( null, null, "post", null ); + + Assert.assertTrue( fhirOperation.isProcessed() ); + Assert.assertEquals( FhirOperationResult.BAD_REQUEST_STATUS_CODE, fhirOperation.getResult().getStatusCode() ); + Assert.assertEquals( FhirOperationType.POST, fhirOperation.getOperationType() ); + } + + @Test + public void createOperationPutWithoutResource() + { + Mockito.when( bundleResourceProvider.getFhirVersion() ).thenReturn( FhirVersion.DSTU3 ); + Mockito.when( fhirClientResourceRepository.findFirstCached( Mockito.eq( fhirClient.getId() ), Mockito.eq( FhirResourceType.PATIENT ) ) ) + .thenReturn( Optional.of( patientClientResource ) ); + + final FhirOperation fhirOperation = bundleResourceProvider.createOperation( null, null, "post", "Patient/4711" ); + + Assert.assertTrue( fhirOperation.isProcessed() ); + Assert.assertEquals( FhirOperationResult.BAD_REQUEST_STATUS_CODE, fhirOperation.getResult().getStatusCode() ); + Assert.assertEquals( FhirOperationType.POST, fhirOperation.getOperationType() ); + } + + @Test + public void createOperationPostWithConditionalReference() + { + Mockito.when( bundleResourceProvider.getFhirVersion() ).thenReturn( FhirVersion.DSTU3 ); + Mockito.when( fhirClientResourceRepository.findFirstCached( Mockito.eq( fhirClient.getId() ), Mockito.eq( FhirResourceType.PATIENT ) ) ) + .thenReturn( Optional.of( patientClientResource ) ); + + final FhirOperation fhirOperation = bundleResourceProvider.createOperation( null, new Patient(), "post", "Patient?identifier=832784" ); + + Assert.assertTrue( fhirOperation.isProcessed() ); + Assert.assertEquals( FhirOperationResult.BAD_REQUEST_STATUS_CODE, fhirOperation.getResult().getStatusCode() ); + Assert.assertEquals( FhirOperationType.POST, fhirOperation.getOperationType() ); + } + + @Test + public void createOperationPutWithoutIdReference() + { + Mockito.when( bundleResourceProvider.getFhirVersion() ).thenReturn( FhirVersion.DSTU3 ); + Mockito.when( fhirClientResourceRepository.findFirstCached( Mockito.eq( fhirClient.getId() ), Mockito.eq( FhirResourceType.PATIENT ) ) ) + .thenReturn( Optional.of( patientClientResource ) ); + + final FhirOperation fhirOperation = bundleResourceProvider.createOperation( null, new Patient(), "put", null ); + + Assert.assertTrue( fhirOperation.isProcessed() ); + Assert.assertEquals( FhirOperationResult.BAD_REQUEST_STATUS_CODE, fhirOperation.getResult().getStatusCode() ); + Assert.assertEquals( FhirOperationType.PUT, fhirOperation.getOperationType() ); + } + + @Test + public void lookupConditionalReferenceUrlUnsupportedSystem() throws Exception + { + Mockito.when( bundleResourceProvider.getFhirVersion() ).thenReturn( FhirVersion.DSTU3 ); + Mockito.when( fhirClientSystemRepository.findOneByFhirClientResourceType( Mockito.eq( FHIR_REST_INTERFACE_DSTU3_ID ), Mockito.eq( FhirResourceType.PATIENT ) ) ) + .thenReturn( Optional.of( patientClientSystem ) ); + + final FhirOperation fhirOperation = new FhirOperation( FhirOperationType.POST, FhirResourceType.PATIENT, patientClientResource, null, baseResource3, + new URI( "Patient?identifier=http%3A%2F%2Ftes.com%2Fpatient%7C8972" ) ); + Assert.assertNull( bundleResourceProvider.lookupConditionalReferenceUrl( fhirOperation ) ); + Assert.assertFalse( fhirOperation.isProcessed() ); + + Mockito.verifyZeroInteractions( dhisRepository ); + Mockito.verifyZeroInteractions( fhirRepository ); + } + + @Test + public void lookupConditionalReferenceUrlUnsupportedParameter() throws Exception + { + final FhirOperation fhirOperation = new FhirOperation( FhirOperationType.POST, FhirResourceType.PATIENT, patientClientResource, null, baseResource3, + new URI( "Patient?identifie=http%3A%2F%2Ftest.com%2Fpatient%7C8972" ) ); + Assert.assertNull( bundleResourceProvider.lookupConditionalReferenceUrl( fhirOperation ) ); + Assert.assertTrue( fhirOperation.isProcessed() ); + + Mockito.verifyZeroInteractions( dhisRepository ); + Mockito.verifyZeroInteractions( fhirRepository ); + } + + @Test + public void getOperationTypeNull() + { + Assert.assertEquals( FhirOperationType.UNKNOWN, bundleResourceProvider.getOperationType( null ) ); + } + + @Test + public void getOperationTypeOther() + { + Assert.assertEquals( FhirOperationType.UNKNOWN, bundleResourceProvider.getOperationType( "xpost" ) ); + } + + @Test + public void getOperationTypePost() + { + Assert.assertEquals( FhirOperationType.POST, bundleResourceProvider.getOperationType( "PoSt" ) ); + } + + @Test + public void getOperationTypePut() + { + Assert.assertEquals( FhirOperationType.PUT, bundleResourceProvider.getOperationType( "PuT" ) ); + } + + @Test + public void getOperationTypeDelete() + { + Assert.assertEquals( FhirOperationType.DELETE, bundleResourceProvider.getOperationType( "DELete" ) ); + } + + @Test + public void parseUriNull() + { + Assert.assertNull( bundleResourceProvider.parseUri( null ) ); + } + + @Test + public void parseUriInvalid() + { + Assert.assertNull( bundleResourceProvider.parseUri( ":%727" ) ); + } + + @Test + public void parseUri() throws Exception + { + Assert.assertEquals( new URI( "myTest" ), bundleResourceProvider.parseUri( "myTest" ) ); + } + + @Test + public void getIdFromFullUrlNull() + { + Assert.assertNull( bundleResourceProvider.getIdFromFullUrl( null ) ); + } + + @Test + public void getIdFromFullUrl() + { + final IIdType id = Objects.requireNonNull( bundleResourceProvider.getIdFromFullUrl( "Patient/471192" ) ); + + Assert.assertEquals( new IdDt( "Patient/471192" ), id ); + Assert.assertEquals( "Patient", id.getResourceType() ); + Assert.assertEquals( "471192", id.getIdPart() ); + } + + @Test + public void getIdFromFullUrlFull() + { + final IIdType id = Objects.requireNonNull( bundleResourceProvider.getIdFromFullUrl( "http://test.com/xyz/Patient/471192" ) ); + + Assert.assertEquals( new IdDt( "http://test.com/xyz/Patient/471192" ), id ); + Assert.assertEquals( "Patient", id.getResourceType() ); + Assert.assertEquals( "471192", id.getIdPart() ); + } + + @Test + public void getIdFromRequestUrl() + { + final IIdType id = bundleResourceProvider.getIdFromRequestUrl( "Patient/471192" ); + + Assert.assertEquals( new IdDt( "Patient/471192" ), id ); + Assert.assertEquals( "Patient", id.getResourceType() ); + Assert.assertEquals( "471192", id.getIdPart() ); + } + + @Test + public void getIdFromRequestUrlFull() + { + final IIdType id = bundleResourceProvider.getIdFromRequestUrl( "http://test.com/xyz/Patient/471192?identfier=827637" ); + + Assert.assertEquals( new IdDt( "http://test.com/xyz/Patient/471192" ), id ); + Assert.assertEquals( "Patient", id.getResourceType() ); + Assert.assertEquals( "471192", id.getIdPart() ); + } + + @Test + public void getStatusCodeOk() + { + Assert.assertEquals( "200 OK", bundleResourceProvider.getStatus( new FhirOperationResult( FhirOperationResult.OK_STATUS_CODE ) ) ); + } + + @Test + public void getStatusCodeCreated() + { + Assert.assertEquals( "201 Created", bundleResourceProvider.getStatus( new FhirOperationResult( FhirOperationResult.CREATED_STATUS_CODE ) ) ); + } + + @Test + public void getStatusCodeBadRequest() + { + Assert.assertEquals( "400 Bad request", bundleResourceProvider.getStatus( new FhirOperationResult( FhirOperationResult.BAD_REQUEST_STATUS_CODE ) ) ); + } + + @Test + public void getStatusCodeUnauthorized() + { + Assert.assertEquals( "401 Unauthorized", bundleResourceProvider.getStatus( new FhirOperationResult( FhirOperationResult.UNAUTHORIZED_STATUS_CODE ) ) ); + } + + @Test + public void getStatusCodeForbidden() + { + Assert.assertEquals( "403 Forbidden", bundleResourceProvider.getStatus( new FhirOperationResult( FhirOperationResult.FORBIDDEN_STATUS_CODE ) ) ); + } + + @Test + public void getStatusCodeNotFound() + { + Assert.assertEquals( "404 Not found", bundleResourceProvider.getStatus( new FhirOperationResult( FhirOperationResult.NOT_FOUND_STATUS_CODE ) ) ); + } + + @Test + public void getStatusCodeInternalServerError() + { + Assert.assertEquals( "500 Internal server error", bundleResourceProvider.getStatus( new FhirOperationResult( FhirOperationResult.INTERNAL_SERVER_ERROR_STATUS_CODE ) ) ); + } + + @Test + public void getStatusCodeUnknown() + { + Assert.assertEquals( "533 Unknown", bundleResourceProvider.getStatus( new FhirOperationResult( 533 ) ) ); + } + + public static class Patient implements IBaseResource + { + private static final long serialVersionUID = 6079331283234508350L; + + @Override + public IBaseMetaType getMeta() + { + return null; + } + + @Override + public IIdType getIdElement() + { + return null; + } + + @Override + public IBaseResource setId( String theId ) + { + return null; + } + + @Override + public IBaseResource setId( IIdType theId ) + { + return null; + } + + @Override + public FhirVersionEnum getStructureFhirVersionEnum() + { + return null; + } + + @Override + public boolean isEmpty() + { + return false; + } + + @Override + public boolean hasFormatComment() + { + return false; + } + + @Override + public List getFormatCommentsPre() + { + return null; + } + + @Override + public List getFormatCommentsPost() + { + return null; + } + } + + public static class MeasureReport implements IBaseResource + { + private static final long serialVersionUID = 6079331283234508350L; + + @Override + public IBaseMetaType getMeta() + { + return null; + } + + @Override + public IIdType getIdElement() + { + return null; + } + + @Override + public IBaseResource setId( String theId ) + { + return null; + } + + @Override + public IBaseResource setId( IIdType theId ) + { + return null; + } + + @Override + public FhirVersionEnum getStructureFhirVersionEnum() + { + return null; + } + + @Override + public boolean isEmpty() + { + return false; + } + + @Override + public boolean hasFormatComment() + { + return false; + } + + @Override + public List getFormatCommentsPre() + { + return null; + } + + @Override + public List getFormatCommentsPost() + { + return null; + } + } +} \ No newline at end of file