diff --git a/api/src/main/java/org/openmrs/module/fhir2/api/translators/impl/RelatedPersonTranslatorImpl.java b/api/src/main/java/org/openmrs/module/fhir2/api/translators/impl/RelatedPersonTranslatorImpl.java index 0c1cd99b9..20c1c7fb9 100644 --- a/api/src/main/java/org/openmrs/module/fhir2/api/translators/impl/RelatedPersonTranslatorImpl.java +++ b/api/src/main/java/org/openmrs/module/fhir2/api/translators/impl/RelatedPersonTranslatorImpl.java @@ -15,8 +15,11 @@ import java.util.Date; +import ca.uhn.fhir.model.api.TemporalPrecisionEnum; import lombok.AccessLevel; import lombok.Setter; +import org.hl7.fhir.r4.model.Address; +import org.hl7.fhir.r4.model.HumanName; import org.hl7.fhir.r4.model.Identifier; import org.hl7.fhir.r4.model.Period; import org.hl7.fhir.r4.model.RelatedPerson; @@ -110,6 +113,42 @@ public RelatedPerson toFhirResource(@Nonnull Relationship relationship) { @Override public Relationship toOpenmrsType(@Nonnull RelatedPerson resource) { - throw new UnsupportedOperationException(); + Relationship relationship = new Relationship(); + relationship.setUuid(resource.getId()); + + Person personA = new Person(); + + if (resource.getBirthDateElement().getPrecision() == TemporalPrecisionEnum.DAY) { + personA.setBirthdate(resource.getBirthDate()); + } + + if (resource.getBirthDateElement().getPrecision() == TemporalPrecisionEnum.MONTH + || resource.getBirthDateElement().getPrecision() == TemporalPrecisionEnum.YEAR) { + personA.setBirthdate(resource.getBirthDate()); + personA.setBirthdateEstimated(true); + } + + if (resource.hasGender()) { + personA.setGender(genderTranslator.toOpenmrsType(resource.getGender())); + } + + for (HumanName name : resource.getName()) { + personA.addName(nameTranslator.toOpenmrsType(name)); + } + + for (Address address : resource.getAddress()) { + personA.addAddress(addressTranslator.toOpenmrsType(address)); + } + + relationship.setStartDate(resource.getPeriod().getStart()); + relationship.setEndDate(resource.getPeriod().getEnd()); + + if (resource.getPatient() != null) { + relationship.setPersonB(patientReferenceTranslator.toOpenmrsType(resource.getPatient())); + } + + relationship.setPersonA(personA); + + return relationship; } } diff --git a/api/src/main/java/org/openmrs/module/fhir2/providers/r3/RelatedPersonFhirResourceProvider.java b/api/src/main/java/org/openmrs/module/fhir2/providers/r3/RelatedPersonFhirResourceProvider.java index 8db63b28f..7c443c087 100644 --- a/api/src/main/java/org/openmrs/module/fhir2/providers/r3/RelatedPersonFhirResourceProvider.java +++ b/api/src/main/java/org/openmrs/module/fhir2/providers/r3/RelatedPersonFhirResourceProvider.java @@ -16,28 +16,36 @@ import java.util.HashSet; import ca.uhn.fhir.model.api.Include; +import ca.uhn.fhir.rest.annotation.Create; +import ca.uhn.fhir.rest.annotation.Delete; import ca.uhn.fhir.rest.annotation.IdParam; import ca.uhn.fhir.rest.annotation.IncludeParam; import ca.uhn.fhir.rest.annotation.OptionalParam; import ca.uhn.fhir.rest.annotation.Read; +import ca.uhn.fhir.rest.annotation.ResourceParam; import ca.uhn.fhir.rest.annotation.Search; import ca.uhn.fhir.rest.annotation.Sort; +import ca.uhn.fhir.rest.annotation.Update; +import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.rest.api.SortSpec; import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.param.DateRangeParam; import ca.uhn.fhir.rest.param.StringAndListParam; import ca.uhn.fhir.rest.param.TokenAndListParam; import ca.uhn.fhir.rest.server.IResourceProvider; +import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import lombok.Setter; import org.apache.commons.collections.CollectionUtils; import org.hl7.fhir.convertors.conv30_40.RelatedPerson30_40; import org.hl7.fhir.dstu3.model.IdType; +import org.hl7.fhir.dstu3.model.OperationOutcome; import org.hl7.fhir.dstu3.model.RelatedPerson; import org.hl7.fhir.instance.model.api.IBaseResource; import org.openmrs.module.fhir2.api.FhirRelatedPersonService; import org.openmrs.module.fhir2.api.annotations.R3Provider; import org.openmrs.module.fhir2.api.search.SearchQueryBundleProviderR3Wrapper; +import org.openmrs.module.fhir2.providers.util.FhirProviderUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -64,6 +72,34 @@ public RelatedPerson getRelatedPersonById(@IdParam @Nonnull IdType id) { return RelatedPerson30_40.convertRelatedPerson(relatedPerson); } + @Create + public MethodOutcome createRelatedPerson(@ResourceParam RelatedPerson relatedPerson) { + return FhirProviderUtils.buildCreate(RelatedPerson30_40 + .convertRelatedPerson(relatedPersonService.create(RelatedPerson30_40.convertRelatedPerson(relatedPerson)))); + } + + @Update + public MethodOutcome updateRelatedPerson(@IdParam IdType id, @ResourceParam RelatedPerson relatedPerson) { + if (id == null || id.getIdPart() == null) { + throw new InvalidRequestException("id must be specified to update"); + } + + relatedPerson.setId(id.getIdPart()); + + return FhirProviderUtils.buildUpdate(RelatedPerson30_40.convertRelatedPerson( + relatedPersonService.update(id.getIdPart(), RelatedPerson30_40.convertRelatedPerson(relatedPerson)))); + } + + @Delete + public OperationOutcome deleteRelatedPerson(@IdParam @Nonnull IdType id) { + org.hl7.fhir.r4.model.RelatedPerson relatedPerson = relatedPersonService.delete(id.getIdPart()); + if (relatedPerson == null) { + throw new ResourceNotFoundException("Could not find person to delete with id " + id.getIdPart()); + } + + return FhirProviderUtils.buildDelete(RelatedPerson30_40.convertRelatedPerson(relatedPerson)); + } + @Search @SuppressWarnings("unused") public IBundleProvider searchRelatedPerson(@OptionalParam(name = RelatedPerson.SP_NAME) StringAndListParam name, diff --git a/api/src/main/java/org/openmrs/module/fhir2/providers/r4/RelatedPersonFhirResourceProvider.java b/api/src/main/java/org/openmrs/module/fhir2/providers/r4/RelatedPersonFhirResourceProvider.java index 95b91cab5..2aae1b605 100644 --- a/api/src/main/java/org/openmrs/module/fhir2/providers/r4/RelatedPersonFhirResourceProvider.java +++ b/api/src/main/java/org/openmrs/module/fhir2/providers/r4/RelatedPersonFhirResourceProvider.java @@ -16,26 +16,34 @@ import java.util.HashSet; import ca.uhn.fhir.model.api.Include; +import ca.uhn.fhir.rest.annotation.Create; +import ca.uhn.fhir.rest.annotation.Delete; import ca.uhn.fhir.rest.annotation.IdParam; import ca.uhn.fhir.rest.annotation.IncludeParam; import ca.uhn.fhir.rest.annotation.OptionalParam; import ca.uhn.fhir.rest.annotation.Read; +import ca.uhn.fhir.rest.annotation.ResourceParam; import ca.uhn.fhir.rest.annotation.Search; import ca.uhn.fhir.rest.annotation.Sort; +import ca.uhn.fhir.rest.annotation.Update; +import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.rest.api.SortSpec; import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.param.DateRangeParam; import ca.uhn.fhir.rest.param.StringAndListParam; import ca.uhn.fhir.rest.param.TokenAndListParam; import ca.uhn.fhir.rest.server.IResourceProvider; +import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import lombok.Setter; import org.apache.commons.collections.CollectionUtils; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.r4.model.IdType; +import org.hl7.fhir.r4.model.OperationOutcome; import org.hl7.fhir.r4.model.RelatedPerson; import org.openmrs.module.fhir2.api.FhirRelatedPersonService; import org.openmrs.module.fhir2.api.annotations.R4Provider; +import org.openmrs.module.fhir2.providers.util.FhirProviderUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -61,6 +69,32 @@ public RelatedPerson getRelatedPersonById(@IdParam @Nonnull IdType id) { return relatedPerson; } + @Create + public MethodOutcome createRelatedPerson(@ResourceParam RelatedPerson relatedPerson) { + return FhirProviderUtils.buildCreate(relatedPersonService.create(relatedPerson)); + } + + @Update + public MethodOutcome updateRelatedPerson(@IdParam IdType id, @ResourceParam RelatedPerson relatedPerson) { + if (id == null || id.getIdPart() == null) { + throw new InvalidRequestException("id must be specified to update"); + } + + relatedPerson.setId(id.getIdPart()); + + return FhirProviderUtils.buildUpdate(relatedPersonService.update(id.getIdPart(), relatedPerson)); + } + + @Delete + public OperationOutcome deleteRelatedPerson(@IdParam @Nonnull IdType id) { + RelatedPerson relatedPerson = relatedPersonService.delete(id.getIdPart()); + if (relatedPerson == null) { + throw new ResourceNotFoundException("Could not find person to delete with id " + id.getIdPart()); + } + + return FhirProviderUtils.buildDelete(relatedPerson); + } + @Search @SuppressWarnings("unused") public IBundleProvider searchRelatedPerson(@OptionalParam(name = RelatedPerson.SP_NAME) StringAndListParam name, diff --git a/api/src/test/java/org/openmrs/module/fhir2/api/translators/impl/LocationTagTranslatorImplTest.java b/api/src/test/java/org/openmrs/module/fhir2/api/translators/impl/LocationTagTranslatorImplTest.java index d038168ae..8c2d1d3ca 100644 --- a/api/src/test/java/org/openmrs/module/fhir2/api/translators/impl/LocationTagTranslatorImplTest.java +++ b/api/src/test/java/org/openmrs/module/fhir2/api/translators/impl/LocationTagTranslatorImplTest.java @@ -70,4 +70,4 @@ public void toOpenmrsType_shouldReturnExistingTagIfTagExists() { assertThat(existingLocationTag, notNullValue()); assertThat(existingLocationTag.getName(), is(LAB_TAG_NAME)); } -} \ No newline at end of file +} diff --git a/api/src/test/java/org/openmrs/module/fhir2/api/translators/impl/RelatedPersonTranslatorImplTest.java b/api/src/test/java/org/openmrs/module/fhir2/api/translators/impl/RelatedPersonTranslatorImplTest.java index 2ae4f6aa5..5df640c0e 100644 --- a/api/src/test/java/org/openmrs/module/fhir2/api/translators/impl/RelatedPersonTranslatorImplTest.java +++ b/api/src/test/java/org/openmrs/module/fhir2/api/translators/impl/RelatedPersonTranslatorImplTest.java @@ -325,4 +325,150 @@ public void shouldTranslateToFhirBirthdate() { assertThat(result.getBirthDateElement().getYear(), equalTo(dateType.getYear())); assertThat(result.getBirthDateElement().getMonth(), equalTo(dateType.getMonth())); } + + @Test + public void shouldTranslateRelatedPersonToRelationship() { + RelatedPerson relatedPerson = new RelatedPerson(); + + Relationship result = relatedPersonTranslator.toOpenmrsType(relatedPerson); + + assertThat(result, notNullValue()); + } + + @Test + public void shouldTranslateRelatedPersonIdToRelationshipUuid() { + RelatedPerson relatedPerson = new RelatedPerson(); + relatedPerson.setId(RELATIONSHIP_UUID); + + Relationship result = relatedPersonTranslator.toOpenmrsType(relatedPerson); + + assertThat(result, notNullValue()); + assertThat(result.getUuid(), equalTo(RELATIONSHIP_UUID)); + } + + @Test + public void shouldTranslateFhirNameToOpenmrsName() { + PersonName personName = new PersonName(); + personName.setGivenName(PERSON_GIVEN_NAME); + personName.setFamilyName(PERSON_FAMILY_NAME); + + RelatedPerson relatedPerson = new RelatedPerson(); + HumanName name = relatedPerson.addName(); + name.addGiven(PERSON_GIVEN_NAME); + name.setFamily(PERSON_FAMILY_NAME); + when(nameTranslator.toOpenmrsType(name)).thenReturn(personName); + + Relationship result = relatedPersonTranslator.toOpenmrsType(relatedPerson); + + assertThat(result, notNullValue()); + assertThat(result.getPersonA().getGivenName(), equalTo(PERSON_GIVEN_NAME)); + assertThat(result.getPersonA().getFamilyName(), equalTo(PERSON_FAMILY_NAME)); + } + + @Test + public void shouldTranslateFhirAddressToOpenmrsAddress() { + PersonAddress personAddress = new PersonAddress(); + personAddress.setUuid(ADDRESS_UUID); + personAddress.setCityVillage(ADDRESS_CITY); + + RelatedPerson relatedPerson = new RelatedPerson(); + Address address = relatedPerson.addAddress(); + address.setId(ADDRESS_UUID); + address.setCity(ADDRESS_CITY); + when(addressTranslator.toOpenmrsType(address)).thenReturn(personAddress); + + Relationship result = relatedPersonTranslator.toOpenmrsType(relatedPerson); + + assertThat(result, notNullValue()); + assertThat(result.getPersonA().getPersonAddress(), notNullValue()); + assertThat(result.getPersonA().getPersonAddress().getUuid(), equalTo(ADDRESS_UUID)); + assertThat(result.getPersonA().getPersonAddress().getCityVillage(), equalTo(ADDRESS_CITY)); + + } + + @Test + public void shouldTranslateFhirGenderToOpenmrsGender() { + RelatedPerson relatedPerson = new RelatedPerson(); + relatedPerson.setGender(Enumerations.AdministrativeGender.MALE); + when(genderTranslator.toOpenmrsType(Enumerations.AdministrativeGender.MALE)).thenReturn("M"); + + Relationship result = relatedPersonTranslator.toOpenmrsType(relatedPerson); + + assertThat(result, notNullValue()); + assertThat(result.getPersonA().getGender(), equalTo("M")); + } + + @Test + public void shouldTranslateToOpenmrsBirthdate() { + RelatedPerson relatedPerson = new RelatedPerson(); + Date date = new Date(); + DateType dateType = new DateType(); + + // for TemporalPrecisionEnum.DAY + dateType.setValue(date, TemporalPrecisionEnum.DAY); + relatedPerson.setBirthDateElement(dateType); + + Relationship result = relatedPersonTranslator.toOpenmrsType(relatedPerson); + + assertThat(result, notNullValue()); + assertThat(result.getPersonA().getBirthdateEstimated(), equalTo(false)); + assertThat(result.getPersonA().getBirthdate(), equalTo(date)); + + // for TemporalPrecisionEnum.Month + dateType.setValue(date, TemporalPrecisionEnum.MONTH); + relatedPerson.setBirthDateElement(dateType); + + result = relatedPersonTranslator.toOpenmrsType(relatedPerson); + + assertThat(result, notNullValue()); + assertThat(result.getPersonA().getBirthdateEstimated(), equalTo(true)); + assertThat(result.getPersonA().getBirthdate(), equalTo(date)); + + // for TemporalPrecisionEnum.YEAR + dateType.setValue(date, TemporalPrecisionEnum.YEAR); + relatedPerson.setBirthDateElement(dateType); + + result = relatedPersonTranslator.toOpenmrsType(relatedPerson); + + assertThat(result, notNullValue()); + assertThat(result.getPersonA().getBirthdateEstimated(), equalTo(true)); + assertThat(result.getPersonA().getBirthdate(), equalTo(date)); + } + + @Test + public void shouldTranslateFhirStartDateAndEndDateToOpenmrsStartDateAndEndDate() { + RelatedPerson relatedPerson = new RelatedPerson(); + Calendar calendar = Calendar.getInstance(); + calendar.set(2000, Calendar.APRIL, 16); + relatedPerson.getPeriod().setStart(calendar.getTime()); + + Relationship result = relatedPersonTranslator.toOpenmrsType(relatedPerson); + + assertThat(result, notNullValue()); + assertThat(result.getStartDate().getTime(), equalTo(calendar.getTime().getTime())); + + calendar.set(2000, Calendar.SEPTEMBER, 29); + relatedPerson.getPeriod().setEnd(calendar.getTime()); + + result = relatedPersonTranslator.toOpenmrsType(relatedPerson); + + assertThat(result, notNullValue()); + assertThat(result.getEndDate().getTime(), equalTo(calendar.getTime().getTime())); + } + + @Test + public void shouldTranslateFhirPatientToOpenmrsPersonB() { + Patient patient = new Patient(); + patient.setUuid(PATIENT_UUID); + RelatedPerson relatedPerson = new RelatedPerson(); + Reference reference = new Reference(); + relatedPerson.setPatient(reference); + + when(patientReferenceTranslator.toOpenmrsType(relatedPerson.getPatient())).thenReturn(patient); + + Relationship result = relatedPersonTranslator.toOpenmrsType(relatedPerson); + + assertThat(result, notNullValue()); + assertThat(result.getPersonB().getUuid(), equalTo(PATIENT_UUID)); + } } diff --git a/api/src/test/java/org/openmrs/module/fhir2/providers/r3/RelatedPersonFhirResourceProviderTest.java b/api/src/test/java/org/openmrs/module/fhir2/providers/r3/RelatedPersonFhirResourceProviderTest.java index 7cbf16377..30e89db5c 100644 --- a/api/src/test/java/org/openmrs/module/fhir2/providers/r3/RelatedPersonFhirResourceProviderTest.java +++ b/api/src/test/java/org/openmrs/module/fhir2/providers/r3/RelatedPersonFhirResourceProviderTest.java @@ -16,6 +16,8 @@ import static org.hamcrest.Matchers.greaterThanOrEqualTo; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.when; import static org.mockito.hamcrest.MockitoHamcrest.argThat; @@ -26,6 +28,7 @@ import java.util.List; import ca.uhn.fhir.model.api.Include; +import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.param.DateRangeParam; import ca.uhn.fhir.rest.param.StringAndListParam; @@ -34,9 +37,12 @@ import ca.uhn.fhir.rest.param.TokenAndListParam; import ca.uhn.fhir.rest.param.TokenOrListParam; import ca.uhn.fhir.rest.param.TokenParam; +import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import org.hamcrest.Matchers; +import org.hl7.fhir.convertors.conv30_40.RelatedPerson30_40; import org.hl7.fhir.dstu3.model.IdType; +import org.hl7.fhir.dstu3.model.OperationOutcome; import org.hl7.fhir.dstu3.model.RelatedPerson; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.r4.model.Enumerations; @@ -333,4 +339,73 @@ public void searchForRelatedPeople_shouldNotAddRelatedResourcesForEmptyInclude() assertThat(resultList.size(), equalTo(1)); } + @Test + public void updateRelatedPerson_shouldUpdateRelatedPerson() { + when(relatedPersonService.update(eq(RELATED_PERSON_UUID), any(org.hl7.fhir.r4.model.RelatedPerson.class))) + .thenReturn(relatedPerson); + + MethodOutcome result = resourceProvider.updateRelatedPerson(new IdType().setValue(RELATED_PERSON_UUID), + RelatedPerson30_40.convertRelatedPerson(relatedPerson)); + + assertThat(result, notNullValue()); + assertThat(result.getResource(), notNullValue()); + assertThat(result.getResource().getIdElement().getIdPart(), equalTo(RELATED_PERSON_UUID)); + } + + @Test(expected = InvalidRequestException.class) + public void updateRelatedPerson_shouldThrowInvalidRequestForUuidMismatch() { + when(relatedPersonService.update(eq(WRONG_RELATED_PERSON_UUID), any(org.hl7.fhir.r4.model.RelatedPerson.class))) + .thenThrow(InvalidRequestException.class); + + resourceProvider.updateRelatedPerson(new IdType().setValue(WRONG_RELATED_PERSON_UUID), + RelatedPerson30_40.convertRelatedPerson(relatedPerson)); + } + + @Test(expected = InvalidRequestException.class) + public void updateRelatedPerson_shouldThrowInvalidRequestForMissingId() { + org.hl7.fhir.r4.model.RelatedPerson noIdRelatedPerson = new org.hl7.fhir.r4.model.RelatedPerson(); + + when(relatedPersonService.update(eq(RELATED_PERSON_UUID), any(org.hl7.fhir.r4.model.RelatedPerson.class))) + .thenThrow(InvalidRequestException.class); + + resourceProvider.updateRelatedPerson(new IdType().setValue(RELATED_PERSON_UUID), + RelatedPerson30_40.convertRelatedPerson(noIdRelatedPerson)); + } + + @Test(expected = InvalidRequestException.class) + public void updateRelatedPerson_shouldThrowInvalidRequestForMissingIdType() { + resourceProvider.updateRelatedPerson(null, RelatedPerson30_40.convertRelatedPerson(relatedPerson)); + } + + @Test + public void createRelatedPerson_shouldCreateNewRelatedPerson() { + when(relatedPersonService.create(any(org.hl7.fhir.r4.model.RelatedPerson.class))).thenReturn(relatedPerson); + + MethodOutcome result = resourceProvider.createRelatedPerson(RelatedPerson30_40.convertRelatedPerson(relatedPerson)); + + assertThat(result, Matchers.notNullValue()); + assertThat(result.getCreated(), is(true)); + assertThat(result.getResource(), Matchers.notNullValue()); + assertThat(result.getResource().getIdElement().getIdPart(), Matchers.equalTo(RELATED_PERSON_UUID)); + } + + @Test + public void deleteRelatedPerson_shouldDeleteRelatedPerson() { + when(relatedPersonService.delete(RELATED_PERSON_UUID)).thenReturn(relatedPerson); + + OperationOutcome result = resourceProvider.deleteRelatedPerson(new IdType().setValue(RELATED_PERSON_UUID)); + assertThat(result, Matchers.notNullValue()); + assertThat(result.getIssue(), Matchers.notNullValue()); + assertThat(result.getIssueFirstRep().getSeverity(), Matchers.equalTo(OperationOutcome.IssueSeverity.INFORMATION)); + assertThat(result.getIssueFirstRep().getDetails().getCodingFirstRep().getCode(), Matchers.equalTo("MSG_DELETED")); + assertThat(result.getIssueFirstRep().getDetails().getCodingFirstRep().getDisplay(), + Matchers.equalTo("This resource has been deleted")); + } + + @Test(expected = ResourceNotFoundException.class) + public void deleteRelatedPerson_shouldThrowResourceNotFoundException() { + when(relatedPersonService.delete(WRONG_RELATED_PERSON_UUID)).thenReturn(null); + + resourceProvider.deleteRelatedPerson(new IdType().setValue(WRONG_RELATED_PERSON_UUID)); + } } diff --git a/api/src/test/java/org/openmrs/module/fhir2/providers/r4/RelatedPersonFhirResourceProviderTest.java b/api/src/test/java/org/openmrs/module/fhir2/providers/r4/RelatedPersonFhirResourceProviderTest.java index 1a78c3f7c..1d8e0af3d 100644 --- a/api/src/test/java/org/openmrs/module/fhir2/providers/r4/RelatedPersonFhirResourceProviderTest.java +++ b/api/src/test/java/org/openmrs/module/fhir2/providers/r4/RelatedPersonFhirResourceProviderTest.java @@ -26,6 +26,7 @@ import java.util.List; import ca.uhn.fhir.model.api.Include; +import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.param.DateRangeParam; import ca.uhn.fhir.rest.param.StringAndListParam; @@ -34,12 +35,15 @@ import ca.uhn.fhir.rest.param.TokenAndListParam; import ca.uhn.fhir.rest.param.TokenOrListParam; import ca.uhn.fhir.rest.param.TokenParam; +import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; +import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import org.hamcrest.Matchers; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.r4.model.Enumerations; import org.hl7.fhir.r4.model.HumanName; import org.hl7.fhir.r4.model.IdType; +import org.hl7.fhir.r4.model.OperationOutcome; import org.hl7.fhir.r4.model.Patient; import org.hl7.fhir.r4.model.RelatedPerson; import org.junit.Before; @@ -333,4 +337,76 @@ public void searchForRelatedPeople_shouldNotAddRelatedResourcesForEmptyInclude() assertThat(resultList.size(), equalTo(1)); } + @Test + public void updateRelatedPerson_shouldUpdateRelatedPerson() { + when(relatedPersonService.update(RELATED_PERSON_UUID, relatedPerson)).thenReturn(relatedPerson); + + MethodOutcome result = resourceProvider.updateRelatedPerson(new IdType().setValue(RELATED_PERSON_UUID), + relatedPerson); + assertThat(result, notNullValue()); + assertThat(result.getResource(), equalTo(relatedPerson)); + } + + @Test(expected = InvalidRequestException.class) + public void updateRelatedPerson_shouldThrowInvalidRequestExceptionForUuidMismatch() { + when(relatedPersonService.update(WRONG_RELATED_PERSON_UUID, relatedPerson)).thenThrow(InvalidRequestException.class); + + resourceProvider.updateRelatedPerson(new IdType().setValue(WRONG_RELATED_PERSON_UUID), relatedPerson); + } + + @Test(expected = InvalidRequestException.class) + public void updateRelatedPerson_shouldThrowInvalidRequestForMissingId() { + RelatedPerson noIdRelatedPerson = new RelatedPerson(); + + when(relatedPersonService.update(RELATED_PERSON_UUID, noIdRelatedPerson)).thenThrow(InvalidRequestException.class); + + resourceProvider.updateRelatedPerson(new IdType().setValue(RELATED_PERSON_UUID), noIdRelatedPerson); + } + + @Test(expected = MethodNotAllowedException.class) + public void updateRelatedPerson_shouldThrowMethodeNotAllowedIfDoesNotExist() { + + relatedPerson.setId(WRONG_RELATED_PERSON_UUID); + + when(relatedPersonService.update(WRONG_RELATED_PERSON_UUID, relatedPerson)) + .thenThrow(MethodNotAllowedException.class); + + resourceProvider.updateRelatedPerson(new IdType().setValue(WRONG_RELATED_PERSON_UUID), relatedPerson); + } + + @Test(expected = InvalidRequestException.class) + public void updateRelatedPerson_shouldThrowInvalidRequestForMissingIdType() { + resourceProvider.updateRelatedPerson(null, relatedPerson); + } + + @Test + public void deleteRelatedPerson_shouldDeleteRelatedPerson() { + + when(relatedPersonService.delete(RELATED_PERSON_UUID)).thenReturn(relatedPerson); + + OperationOutcome result = resourceProvider.deleteRelatedPerson(new IdType().setValue(RELATED_PERSON_UUID)); + assertThat(result, notNullValue()); + assertThat(result.getIssueFirstRep().getSeverity(), equalTo(OperationOutcome.IssueSeverity.INFORMATION)); + assertThat(result.getIssueFirstRep().getDetails().getCodingFirstRep().getCode(), equalTo("MSG_DELETED")); + assertThat(result.getIssueFirstRep().getDetails().getCodingFirstRep().getDisplay(), + equalTo("This resource has been deleted")); + } + + @Test(expected = ResourceNotFoundException.class) + public void deleteRelatedPerson_shouldThrowResourceNotFoundException() { + + when(relatedPersonService.delete(WRONG_RELATED_PERSON_UUID)).thenReturn(null); + + resourceProvider.deleteRelatedPerson(new IdType().setValue(WRONG_RELATED_PERSON_UUID)); + } + + @Test + public void createRelatedPerson_shouldCreateNewRelatedPerson() { + when(relatedPersonService.create(relatedPerson)).thenReturn(relatedPerson); + + MethodOutcome result = resourceProvider.createRelatedPerson(relatedPerson); + + assertThat(result, notNullValue()); + assertThat(result.getResource(), equalTo(relatedPerson)); + } } diff --git a/omod/src/test/java/org/openmrs/module/fhir2/providers/r3/RelatedPersonFhirResourceProviderWebTest.java b/omod/src/test/java/org/openmrs/module/fhir2/providers/r3/RelatedPersonFhirResourceProviderWebTest.java index a13c49139..1a74dd109 100644 --- a/omod/src/test/java/org/openmrs/module/fhir2/providers/r3/RelatedPersonFhirResourceProviderWebTest.java +++ b/omod/src/test/java/org/openmrs/module/fhir2/providers/r3/RelatedPersonFhirResourceProviderWebTest.java @@ -10,6 +10,7 @@ package org.openmrs.module.fhir2.providers.r3; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsStringIgnoringCase; import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; @@ -17,24 +18,31 @@ import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import javax.servlet.ServletException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; import java.util.Calendar; import java.util.Collections; import java.util.HashSet; +import java.util.Objects; import ca.uhn.fhir.model.api.Include; import ca.uhn.fhir.rest.param.DateRangeParam; import ca.uhn.fhir.rest.param.StringAndListParam; import ca.uhn.fhir.rest.param.TokenAndListParam; +import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import lombok.AccessLevel; import lombok.Getter; +import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.time.DateUtils; import org.hl7.fhir.dstu3.model.Bundle; +import org.hl7.fhir.dstu3.model.IdType; import org.hl7.fhir.dstu3.model.RelatedPerson; import org.junit.Before; import org.junit.Test; @@ -51,6 +59,14 @@ @RunWith(MockitoJUnitRunner.class) public class RelatedPersonFhirResourceProviderWebTest extends BaseFhirR3ResourceProviderWebTest { + private static final String JSON_CREATE_RELATED_PERSON_PATH = "org/openmrs/module/fhir2/providers/RelatedPersonWebTest_create.json"; + + private static final String JSON_UPDATE_RELATED_PERSON_PATH = "org/openmrs/module/fhir2/providers/RelatedPersonWebTest_update.json"; + + private static final String JSON_UPDATE_RELATED_PERSON_NO_ID_PATH = "org/openmrs/module/fhir2/providers/RelatedPersonWebTest_updateWithoutId.json"; + + private static final String JSON_UPDATE_RELATED_PERSON_WRONG_ID_PATH = "org/openmrs/module/fhir2/providers/RelatedPersonWebTest_updateWrongId.json"; + private static final String RELATED_PERSON_UUID = "8a849d5e-6011-4279-a124-40ada5a687de"; private static final String WRONG_RELATED_PERSON_UUID = "9bf0d1ac-62a8-4440-a5a1-eb1015a7cc65"; @@ -384,4 +400,94 @@ private void verifyUri(String uri) throws Exception { assertThat(results.getEntry().get(0).getResource().getIdElement().getIdPart(), equalTo(RELATED_PERSON_UUID)); } + @Test + public void createRelatedPerson_shouldCreateRelatedPerson() throws Exception { + String jsonRelatedPerson; + try (InputStream is = this.getClass().getClassLoader().getResourceAsStream(JSON_CREATE_RELATED_PERSON_PATH)) { + Objects.requireNonNull(is); + jsonRelatedPerson = IOUtils.toString(is, StandardCharsets.UTF_8); + } + + org.hl7.fhir.r4.model.RelatedPerson relatedPerson = new org.hl7.fhir.r4.model.RelatedPerson(); + relatedPerson.setId(RELATED_PERSON_UUID); + + when(relatedPersonService.create(any(org.hl7.fhir.r4.model.RelatedPerson.class))).thenReturn(relatedPerson); + + MockHttpServletResponse response = post("/RelatedPerson").jsonContent(jsonRelatedPerson).accept(FhirMediaTypes.JSON) + .go(); + + assertThat(response, isCreated()); + } + + @Test + public void updateRelatedPerson_shouldUpdateExistingRelatedPerson() throws Exception { + String jsonRelatedPerson; + try (InputStream is = this.getClass().getClassLoader().getResourceAsStream(JSON_UPDATE_RELATED_PERSON_PATH)) { + Objects.requireNonNull(is); + jsonRelatedPerson = IOUtils.toString(is, StandardCharsets.UTF_8); + } + + org.hl7.fhir.r4.model.RelatedPerson relatedPerson = new org.hl7.fhir.r4.model.RelatedPerson(); + relatedPerson.setId(RELATED_PERSON_UUID); + + when(relatedPersonService.update(anyString(), any(org.hl7.fhir.r4.model.RelatedPerson.class))) + .thenReturn(relatedPerson); + + MockHttpServletResponse response = put("/RelatedPerson/" + RELATED_PERSON_UUID).jsonContent(jsonRelatedPerson) + .accept(FhirMediaTypes.JSON).go(); + + assertThat(response, isOk()); + } + + @Test + public void updateRelatedPerson_shouldThrowErrorForNoId() throws Exception { + String jsonRelatedPerson; + try (InputStream is = this.getClass().getClassLoader().getResourceAsStream(JSON_UPDATE_RELATED_PERSON_NO_ID_PATH)) { + Objects.requireNonNull(is); + jsonRelatedPerson = IOUtils.toString(is, StandardCharsets.UTF_8); + } + + MockHttpServletResponse response = put("/RelatedPerson/" + RELATED_PERSON_UUID).jsonContent(jsonRelatedPerson) + .accept(FhirMediaTypes.JSON).go(); + + assertThat(response, isBadRequest()); + assertThat(response.getContentAsString(), containsStringIgnoringCase("body must contain an ID element for update")); + } + + @Test + public void updateRelatedPerson_shouldThrowErrorForIdMissMatch() throws Exception { + String jsonRelatedPerson; + try (InputStream is = this.getClass().getClassLoader() + .getResourceAsStream(JSON_UPDATE_RELATED_PERSON_WRONG_ID_PATH)) { + Objects.requireNonNull(is); + jsonRelatedPerson = IOUtils.toString(is, StandardCharsets.UTF_8); + } + + MockHttpServletResponse response = put("/RelatedPerson/" + RELATED_PERSON_UUID).jsonContent(jsonRelatedPerson) + .accept(FhirMediaTypes.JSON).go(); + + assertThat(response, isBadRequest()); + assertThat(response.getContentAsString(), + containsStringIgnoringCase("body must contain an ID element which matches the request URL")); + } + + @Test + public void deleteRelatedPerson_shouldDeleteRelatedPerson() throws Exception { + org.hl7.fhir.r4.model.RelatedPerson relatedPerson = new org.hl7.fhir.r4.model.RelatedPerson(); + relatedPerson.setId(RELATED_PERSON_UUID); + + when(relatedPersonService.delete(RELATED_PERSON_UUID)).thenReturn(relatedPerson); + + MockHttpServletResponse response = delete("/RelatedPerson/" + RELATED_PERSON_UUID).accept(FhirMediaTypes.JSON).go(); + + assertThat(response, isOk()); + assertThat(response.getContentType(), equalTo(FhirMediaTypes.JSON.toString())); + } + + @Test(expected = ResourceNotFoundException.class) + public void deleteRelatedPerson_shouldThrowResourceNotFoundException() { + when(relatedPersonService.delete(WRONG_RELATED_PERSON_UUID)).thenReturn(null); + + resourceProvider.deleteRelatedPerson(new IdType().setValue(WRONG_RELATED_PERSON_UUID)); + } } diff --git a/omod/src/test/java/org/openmrs/module/fhir2/providers/r4/RelatedPersonFhirResourceProviderWebTest.java b/omod/src/test/java/org/openmrs/module/fhir2/providers/r4/RelatedPersonFhirResourceProviderWebTest.java index 4bf20b2ee..c814fc717 100644 --- a/omod/src/test/java/org/openmrs/module/fhir2/providers/r4/RelatedPersonFhirResourceProviderWebTest.java +++ b/omod/src/test/java/org/openmrs/module/fhir2/providers/r4/RelatedPersonFhirResourceProviderWebTest.java @@ -10,6 +10,7 @@ package org.openmrs.module.fhir2.providers.r4; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsStringIgnoringCase; import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; @@ -17,25 +18,32 @@ import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import javax.servlet.ServletException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; import java.util.Calendar; import java.util.Collections; import java.util.HashSet; +import java.util.Objects; import ca.uhn.fhir.model.api.Include; import ca.uhn.fhir.rest.param.DateRangeParam; import ca.uhn.fhir.rest.param.StringAndListParam; import ca.uhn.fhir.rest.param.TokenAndListParam; +import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import lombok.AccessLevel; import lombok.Getter; +import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.time.DateUtils; import org.hamcrest.MatcherAssert; import org.hl7.fhir.r4.model.Bundle; +import org.hl7.fhir.r4.model.IdType; import org.hl7.fhir.r4.model.RelatedPerson; import org.junit.Before; import org.junit.Test; @@ -51,6 +59,14 @@ @RunWith(MockitoJUnitRunner.class) public class RelatedPersonFhirResourceProviderWebTest extends BaseFhirR4ResourceProviderWebTest { + private static final String JSON_CREATE_RELATED_PERSON_PATH = "org/openmrs/module/fhir2/providers/RelatedPersonWebTest_create.json"; + + private static final String JSON_UPDATE_RELATED_PERSON_PATH = "org/openmrs/module/fhir2/providers/RelatedPersonWebTest_update.json"; + + private static final String JSON_UPDATE_RELATED_PERSON_NO_ID_PATH = "org/openmrs/module/fhir2/providers/RelatedPersonWebTest_updateWithoutId.json"; + + private static final String JSON_UPDATE_RELATED_PERSON_WRONG_ID_PATH = "org/openmrs/module/fhir2/providers/RelatedPersonWebTest_updateWrongId.json"; + private static final String RELATED_PERSON_UUID = "8a849d5e-6011-4279-a124-40ada5a687de"; private static final String WRONG_RELATED_PERSON_UUID = "9bf0d1ac-62a8-4440-a5a1-eb1015a7cc65"; @@ -383,4 +399,94 @@ private void verifyUri(String uri) throws Exception { assertThat(results.getEntry().get(0).getResource(), notNullValue()); assertThat(results.getEntry().get(0).getResource().getIdElement().getIdPart(), equalTo(RELATED_PERSON_UUID)); } + + @Test + public void createRelatedPerson_shouldCreateRelatedPerson() throws Exception { + String jsonRelatedPerson; + try (InputStream is = this.getClass().getClassLoader().getResourceAsStream(JSON_CREATE_RELATED_PERSON_PATH)) { + Objects.requireNonNull(is); + jsonRelatedPerson = IOUtils.toString(is, StandardCharsets.UTF_8); + } + + RelatedPerson relatedPerson = new RelatedPerson(); + relatedPerson.setId(RELATED_PERSON_UUID); + + when(relatedPersonService.create(any(RelatedPerson.class))).thenReturn(relatedPerson); + + MockHttpServletResponse response = post("RelatedPerson").jsonContent(jsonRelatedPerson).accept(FhirMediaTypes.JSON) + .go(); + + assertThat(response, isCreated()); + } + + @Test + public void updateRelatedPerson_shouldUpdateExistingRelatedPerson() throws Exception { + String jsonRelatedPerson; + try (InputStream is = this.getClass().getClassLoader().getResourceAsStream(JSON_UPDATE_RELATED_PERSON_PATH)) { + Objects.requireNonNull(is); + jsonRelatedPerson = IOUtils.toString(is, StandardCharsets.UTF_8); + } + + RelatedPerson relatedPerson = new RelatedPerson(); + relatedPerson.setId(RELATED_PERSON_UUID); + + when(relatedPersonService.update(anyString(), any(RelatedPerson.class))).thenReturn(relatedPerson); + + MockHttpServletResponse response = put("/RelatedPerson/" + RELATED_PERSON_UUID).jsonContent(jsonRelatedPerson) + .accept(FhirMediaTypes.JSON).go(); + + assertThat(response, isOk()); + } + + @Test + public void updateRelatedPerson_shouldThrowErrorForNoId() throws Exception { + String jsonRelatedPerson; + try (InputStream is = this.getClass().getClassLoader().getResourceAsStream(JSON_UPDATE_RELATED_PERSON_NO_ID_PATH)) { + Objects.requireNonNull(is); + jsonRelatedPerson = IOUtils.toString(is, StandardCharsets.UTF_8); + } + + MockHttpServletResponse response = put("/RelatedPerson/" + RELATED_PERSON_UUID).jsonContent(jsonRelatedPerson) + .accept(FhirMediaTypes.JSON).go(); + + assertThat(response, isBadRequest()); + assertThat(response.getContentAsString(), containsStringIgnoringCase("body must contain an ID element for update")); + } + + @Test + public void updateRelatedPerson_shouldThrowErrorForIdMissMatch() throws Exception { + String jsonRelatedPerson; + try (InputStream is = this.getClass().getClassLoader() + .getResourceAsStream(JSON_UPDATE_RELATED_PERSON_WRONG_ID_PATH)) { + Objects.requireNonNull(is); + jsonRelatedPerson = IOUtils.toString(is, StandardCharsets.UTF_8); + } + + MockHttpServletResponse response = put("/RelatedPerson/" + RELATED_PERSON_UUID).jsonContent(jsonRelatedPerson) + .accept(FhirMediaTypes.JSON).go(); + + assertThat(response, isBadRequest()); + assertThat(response.getContentAsString(), + containsStringIgnoringCase("body must contain an ID element which matches the request URL")); + } + + @Test + public void deleteRelatedPerson_shouldDeleteRelatedPerson() throws Exception { + RelatedPerson relatedPerson = new RelatedPerson(); + relatedPerson.setId(RELATED_PERSON_UUID); + + when(relatedPersonService.delete(RELATED_PERSON_UUID)).thenReturn(relatedPerson); + + MockHttpServletResponse response = delete("/RelatedPerson/" + RELATED_PERSON_UUID).accept(FhirMediaTypes.JSON).go(); + + assertThat(response, isOk()); + assertThat(response.getContentType(), equalTo(FhirMediaTypes.JSON.toString())); + } + + @Test(expected = ResourceNotFoundException.class) + public void deleteRelatedPerson_shouldThrowResourceNotFoundException() { + when(relatedPersonService.delete(WRONG_RELATED_PERSON_UUID)).thenReturn(null); + + resourceProvider.deleteRelatedPerson(new IdType().setValue(WRONG_RELATED_PERSON_UUID)); + } } diff --git a/test-data/src/test/resources/org/openmrs/module/fhir2/providers/RelatedPersonWebTest_create.json b/test-data/src/test/resources/org/openmrs/module/fhir2/providers/RelatedPersonWebTest_create.json new file mode 100644 index 000000000..1a5268cac --- /dev/null +++ b/test-data/src/test/resources/org/openmrs/module/fhir2/providers/RelatedPersonWebTest_create.json @@ -0,0 +1,49 @@ +{ + "resourceType": "RelatedPerson", + "identifier": { + "extension": [ + { + "url": "http://fhir.openmrs.org/ext/person/identifier#location", + "valueReference": { + "reference": "Location/92ab9667-4686-49af-8be8-65a4b58fc49c", + "type": "Location" + } + } + ], + "use": "official", + "type": { + "text": "Test Identifier Type" + }, + "value": "4444-6" + }, + "patient": { + "reference": "Patient/example" + }, + "relationship": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/v2-0131", + "code": "N" + } + ] + } + ], + "name": [ + { + "given": [ + "Adam" + ], + "family": "John" + } + ], + "gender": "male", + "birthDate": "2004-08-12", + "address": [ + { + "state": "Mukono", + "city": "Kampala", + "country": "Uganda" + } + ] +} diff --git a/test-data/src/test/resources/org/openmrs/module/fhir2/providers/RelatedPersonWebTest_update.json b/test-data/src/test/resources/org/openmrs/module/fhir2/providers/RelatedPersonWebTest_update.json new file mode 100644 index 000000000..a31342a57 --- /dev/null +++ b/test-data/src/test/resources/org/openmrs/module/fhir2/providers/RelatedPersonWebTest_update.json @@ -0,0 +1,10 @@ +{ + "resourceType": "RelatedPerson", + "id": "8a849d5e-6011-4279-a124-40ada5a687de", + "name": "adam", + "gender": "male", + "birthdate": "2004-08-12 00:00:00.0", + "state": "mukono", + "city": "kampala", + "country": "uganda" +} diff --git a/test-data/src/test/resources/org/openmrs/module/fhir2/providers/RelatedPersonWebTest_updateWithoutId.json b/test-data/src/test/resources/org/openmrs/module/fhir2/providers/RelatedPersonWebTest_updateWithoutId.json new file mode 100644 index 000000000..1314c38a6 --- /dev/null +++ b/test-data/src/test/resources/org/openmrs/module/fhir2/providers/RelatedPersonWebTest_updateWithoutId.json @@ -0,0 +1,9 @@ +{ + "resourceType": "RelatedPerson", + "name": "adam", + "gender": "male", + "birthdate": "2004-08-12 00:00:00.0", + "state": "mukono", + "city": "kampala", + "country": "uganda" +} diff --git a/test-data/src/test/resources/org/openmrs/module/fhir2/providers/RelatedPersonWebTest_updateWrongId.json b/test-data/src/test/resources/org/openmrs/module/fhir2/providers/RelatedPersonWebTest_updateWrongId.json new file mode 100644 index 000000000..c7e5c9da5 --- /dev/null +++ b/test-data/src/test/resources/org/openmrs/module/fhir2/providers/RelatedPersonWebTest_updateWrongId.json @@ -0,0 +1,10 @@ +{ + "resourceType": "RelatedPerson", + "id": "9bf0d1ac-62a8-4440-a5a1-eb1015a7cc65", + "name": "adam", + "gender": "male", + "birthdate": "2004-08-12 00:00:00.0", + "state": "mukono", + "city": "kampala", + "country": "uganda" +}