Added optional manual override to link update
This commit is contained in:
parent
8a5651093b
commit
759f06ce48
|
@ -240,7 +240,7 @@ Use the `$mdm-update-link` operation to change the `matchResult` update of an md
|
|||
<td>String</td>
|
||||
<td>1..1</td>
|
||||
<td>
|
||||
The id of the source resource.
|
||||
The id of the target resource.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -251,6 +251,15 @@ Use the `$mdm-update-link` operation to change the `matchResult` update of an md
|
|||
Must be either MATCH or NO_MATCH.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>resource</td>
|
||||
<td>Resource</td>
|
||||
<td>0.1</td>
|
||||
<td>
|
||||
Optional manually merged Golden Resource. All values except for the metadata, PID and identifiers will be copied from this resource, if it is present. If no value is specified, all fields from the resource pointed to by "resourceId" will be copied instead.
|
||||
.
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
|
|
@ -81,14 +81,14 @@ public class MdmControllerSvcImpl implements IMdmControllerSvc {
|
|||
}
|
||||
|
||||
@Override
|
||||
public IAnyResource updateLink(String theGoldenResourceId, String theSourceResourceId, String theMatchResult, MdmTransactionContext theMdmTransactionContext) {
|
||||
public IAnyResource updateLink(String theGoldenResourceId, String theSourceResourceId, IAnyResource theManuallyMergedGoldenResource, String theMatchResult, MdmTransactionContext theMdmTransactionContext) {
|
||||
MdmMatchResultEnum matchResult = MdmControllerUtil.extractMatchResultOrNull(theMatchResult);
|
||||
IAnyResource goldenResource = myMdmControllerHelper.getLatestGoldenResourceFromIdOrThrowException(ProviderConstants.MDM_UPDATE_LINK_GOLDEN_RESOURCE_ID, theGoldenResourceId);
|
||||
IAnyResource source = myMdmControllerHelper.getLatestSourceFromIdOrThrowException(ProviderConstants.MDM_UPDATE_LINK_RESOURCE_ID, theSourceResourceId);
|
||||
myMdmControllerHelper.validateSameVersion(goldenResource, theGoldenResourceId);
|
||||
myMdmControllerHelper.validateSameVersion(source, theSourceResourceId);
|
||||
|
||||
return myIMdmLinkUpdaterSvc.updateLink(goldenResource, source, matchResult, theMdmTransactionContext);
|
||||
return myIMdmLinkUpdaterSvc.updateLink(goldenResource, source, theManuallyMergedGoldenResource, matchResult, theMdmTransactionContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -69,7 +69,8 @@ public class MdmLinkUpdaterSvcImpl implements IMdmLinkUpdaterSvc {
|
|||
|
||||
@Transactional
|
||||
@Override
|
||||
public IAnyResource updateLink(IAnyResource theGoldenResource, IAnyResource theSourceResource, MdmMatchResultEnum theMatchResult, MdmTransactionContext theMdmContext) {
|
||||
public IAnyResource updateLink(IAnyResource theGoldenResource, IAnyResource theSourceResource, IAnyResource theManuallyMergedGoldenResource,
|
||||
MdmMatchResultEnum theMatchResult, MdmTransactionContext theMdmContext) {
|
||||
String sourceType = myFhirContext.getResourceType(theSourceResource);
|
||||
|
||||
validateUpdateLinkRequest(theGoldenResource, theSourceResource, theMatchResult, sourceType);
|
||||
|
@ -93,8 +94,8 @@ public class MdmLinkUpdaterSvcImpl implements IMdmLinkUpdaterSvc {
|
|||
mdmLink.setLinkSource(MdmLinkSourceEnum.MANUAL);
|
||||
myMdmLinkDaoSvc.save(mdmLink);
|
||||
|
||||
// TODO NG MDM Since it's a manual link update, we need to allow the caller to optionally override this behavior with what they thing should go into the golden resource
|
||||
myMdmSurvivorshipService.applySurvivorshipRulesToGoldenResource(theSourceResource, theGoldenResource, theMdmContext);
|
||||
IAnyResource resource = (theManuallyMergedGoldenResource == null) ? theSourceResource : theManuallyMergedGoldenResource;
|
||||
myMdmSurvivorshipService.applySurvivorshipRulesToGoldenResource(resource, theGoldenResource, theMdmContext);
|
||||
|
||||
myMdmResourceDaoSvc.upsertGoldenResource(theGoldenResource, theMdmContext.getResourceType());
|
||||
if (theMatchResult == MdmMatchResultEnum.NO_MATCH) {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package ca.uhn.fhir.jpa.mdm.provider;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.mdm.api.MdmConstants;
|
||||
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||
import ca.uhn.fhir.mdm.util.MessageHelper;
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
|
||||
import org.hl7.fhir.r4.model.Patient;
|
||||
|
@ -12,11 +12,17 @@ import org.hl7.fhir.r4.model.StringType;
|
|||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.hamcrest.Matchers.endsWith;
|
||||
import static org.hamcrest.Matchers.matchesPattern;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
public class MdmProviderUpdateLinkR4Test extends BaseLinkR4Test {
|
||||
|
||||
|
@ -26,7 +32,7 @@ public class MdmProviderUpdateLinkR4Test extends BaseLinkR4Test {
|
|||
@Test
|
||||
public void testUpdateLinkNoMatch() {
|
||||
assertLinkCount(1);
|
||||
myMdmProvider.updateLink(mySourcePatientId, myPatientId, NO_MATCH_RESULT, myRequestDetails);
|
||||
myMdmProvider.updateLink(mySourcePatientId, myPatientId, NO_MATCH_RESULT, null, myRequestDetails);
|
||||
assertLinkCount(2);
|
||||
|
||||
List<MdmLink> links = getPatientLinks();
|
||||
|
@ -40,7 +46,7 @@ public class MdmProviderUpdateLinkR4Test extends BaseLinkR4Test {
|
|||
@Test
|
||||
public void testUpdateLinkMatch() {
|
||||
assertLinkCount(1);
|
||||
myMdmProvider.updateLink(mySourcePatientId, myPatientId, MATCH_RESULT, myRequestDetails);
|
||||
myMdmProvider.updateLink(mySourcePatientId, myPatientId, MATCH_RESULT, null, myRequestDetails);
|
||||
assertLinkCount(1);
|
||||
|
||||
List<MdmLink> links = getPatientLinks();
|
||||
|
@ -48,14 +54,34 @@ public class MdmProviderUpdateLinkR4Test extends BaseLinkR4Test {
|
|||
assertEquals(MdmMatchResultEnum.MATCH, links.get(0).getMatchResult());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateLinkWithOverride() {
|
||||
assertLinkCount(1);
|
||||
Patient patient = new Patient();
|
||||
patient.addName().addGiven("Given");
|
||||
patient.addName().setFamily("Family");
|
||||
patient.setBirthDate(new Date());
|
||||
|
||||
Patient updatedPerson = (Patient) myMdmProvider
|
||||
.updateLink(mySourcePatientId, myPatientId, MATCH_RESULT, patient, myRequestDetails);
|
||||
assertLinkCount(1);
|
||||
|
||||
List<MdmLink> links = getPatientLinks();
|
||||
assertEquals(MdmLinkSourceEnum.MANUAL, links.get(0).getLinkSource());
|
||||
assertEquals(MdmMatchResultEnum.MATCH, links.get(0).getMatchResult());
|
||||
|
||||
assertEquals(patient.getNameFirstRep().getNameAsSingleString(), updatedPerson.getNameFirstRep().getNameAsSingleString());
|
||||
assertEquals(patient.getBirthDate(), updatedPerson.getBirthDate());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateLinkTwiceFailsDueToWrongVersion() {
|
||||
myMdmProvider.updateLink(mySourcePatientId, myPatientId, MATCH_RESULT, myRequestDetails);
|
||||
myMdmProvider.updateLink(mySourcePatientId, myPatientId, MATCH_RESULT, null, myRequestDetails);
|
||||
|
||||
materiallyChangeGoldenPatient();
|
||||
|
||||
try {
|
||||
myMdmProvider.updateLink(mySourcePatientId, myPatientId, NO_MATCH_RESULT, myRequestDetails);
|
||||
myMdmProvider.updateLink(mySourcePatientId, myPatientId, NO_MATCH_RESULT, null, myRequestDetails);
|
||||
fail();
|
||||
} catch (ResourceVersionConflictException e) {
|
||||
assertThat(e.getMessage(), matchesPattern("Requested resource Patient/\\d+/_history/1 is not the latest version. Latest version is Patient/\\d+/_history/2"));
|
||||
|
@ -70,19 +96,19 @@ public class MdmProviderUpdateLinkR4Test extends BaseLinkR4Test {
|
|||
|
||||
@Test
|
||||
public void testUpdateLinkTwiceDoesNotThrowValidationErrorWhenNoVersionIsProvided() {
|
||||
myMdmProvider.updateLink(mySourcePatientId, myPatientId, MATCH_RESULT, myRequestDetails);
|
||||
Patient patient = (Patient) myMdmProvider.updateLink(myVersionlessGodlenResourceId, myPatientId, NO_MATCH_RESULT, myRequestDetails);
|
||||
myMdmProvider.updateLink(mySourcePatientId, myPatientId, MATCH_RESULT, null, myRequestDetails);
|
||||
Patient patient = (Patient) myMdmProvider.updateLink(myVersionlessGodlenResourceId, myPatientId, NO_MATCH_RESULT, null, myRequestDetails);
|
||||
assertNotNull(patient); // if this wasn't allowed - a validation exception would be thrown
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnlinkLink() {
|
||||
myMdmProvider.updateLink(mySourcePatientId, myPatientId, NO_MATCH_RESULT, myRequestDetails);
|
||||
myMdmProvider.updateLink(mySourcePatientId, myPatientId, NO_MATCH_RESULT, null, myRequestDetails);
|
||||
|
||||
materiallyChangeGoldenPatient();
|
||||
|
||||
try {
|
||||
myMdmProvider.updateLink(mySourcePatientId, myPatientId, MATCH_RESULT, myRequestDetails);
|
||||
myMdmProvider.updateLink(mySourcePatientId, myPatientId, MATCH_RESULT, null, myRequestDetails);
|
||||
fail();
|
||||
} catch (ResourceVersionConflictException e) {
|
||||
assertThat(e.getMessage(), matchesPattern("Requested resource Patient/\\d+/_history/1 is not the latest version. Latest version is Patient/\\d+/_history/2"));
|
||||
|
@ -92,7 +118,7 @@ public class MdmProviderUpdateLinkR4Test extends BaseLinkR4Test {
|
|||
@Test
|
||||
public void testUpdateIllegalResultForPossibleMatch() {
|
||||
try {
|
||||
myMdmProvider.updateLink(mySourcePatientId, myPatientId, POSSIBLE_MATCH_RESULT, myRequestDetails);
|
||||
myMdmProvider.updateLink(mySourcePatientId, myPatientId, POSSIBLE_MATCH_RESULT, null, myRequestDetails);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals("$mdm-update-link illegal matchResult value 'POSSIBLE_MATCH'. Must be NO_MATCH or MATCH", e.getMessage());
|
||||
|
@ -102,7 +128,7 @@ public class MdmProviderUpdateLinkR4Test extends BaseLinkR4Test {
|
|||
@Test
|
||||
public void testUpdateIllegalResultPD() {
|
||||
try {
|
||||
myMdmProvider.updateLink(mySourcePatientId, myPatientId, POSSIBLE_DUPLICATE_RESULT, myRequestDetails);
|
||||
myMdmProvider.updateLink(mySourcePatientId, myPatientId, POSSIBLE_DUPLICATE_RESULT, null, myRequestDetails);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals("$mdm-update-link illegal matchResult value 'POSSIBLE_DUPLICATE'. Must be NO_MATCH or MATCH", e.getMessage());
|
||||
|
@ -112,7 +138,7 @@ public class MdmProviderUpdateLinkR4Test extends BaseLinkR4Test {
|
|||
@Test
|
||||
public void testUpdateIllegalSecondArg() {
|
||||
try {
|
||||
myMdmProvider.updateLink(myPatientId, new StringType(""), NO_MATCH_RESULT, myRequestDetails);
|
||||
myMdmProvider.updateLink(myPatientId, new StringType(""), NO_MATCH_RESULT, null, myRequestDetails);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), endsWith(" must have form <resourceType>/<id> where <id> is the id of the resource and <resourceType> is the type of the resource"));
|
||||
|
@ -122,7 +148,7 @@ public class MdmProviderUpdateLinkR4Test extends BaseLinkR4Test {
|
|||
@Test
|
||||
public void testUpdateIllegalFirstArg() {
|
||||
try {
|
||||
myMdmProvider.updateLink(new StringType(""), myPatientId, NO_MATCH_RESULT, myRequestDetails);
|
||||
myMdmProvider.updateLink(new StringType(""), myPatientId, NO_MATCH_RESULT, null, myRequestDetails);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), endsWith(" must have form <resourceType>/<id> where <id> is the id of the resource"));
|
||||
|
@ -132,7 +158,7 @@ public class MdmProviderUpdateLinkR4Test extends BaseLinkR4Test {
|
|||
@Test
|
||||
public void testAttemptingToModifyANonExistentLinkFails() {
|
||||
try {
|
||||
myMdmProvider.updateLink(mySourcePatientId, mySourcePatientId, NO_MATCH_RESULT, myRequestDetails);
|
||||
myMdmProvider.updateLink(mySourcePatientId, mySourcePatientId, NO_MATCH_RESULT, null, myRequestDetails);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), startsWith("No link"));
|
||||
|
@ -143,7 +169,7 @@ public class MdmProviderUpdateLinkR4Test extends BaseLinkR4Test {
|
|||
public void testUpdateStrangePatient() {
|
||||
Patient patient = createPatient();
|
||||
try {
|
||||
myMdmProvider.updateLink(new StringType(patient.getIdElement().getValue()), myPatientId, NO_MATCH_RESULT, myRequestDetails);
|
||||
myMdmProvider.updateLink(new StringType(patient.getIdElement().getValue()), myPatientId, NO_MATCH_RESULT, null, myRequestDetails);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
String expectedMessage = myMessageHelper.getMessageForUnmanagedResource();
|
||||
|
@ -157,7 +183,7 @@ public class MdmProviderUpdateLinkR4Test extends BaseLinkR4Test {
|
|||
patient.getMeta().addTag().setSystem(MdmConstants.SYSTEM_MDM_MANAGED).setCode(MdmConstants.CODE_NO_MDM_MANAGED);
|
||||
createPatient(patient);
|
||||
try {
|
||||
myMdmProvider.updateLink(mySourcePatientId, new StringType(patient.getIdElement().getValue()), NO_MATCH_RESULT, myRequestDetails);
|
||||
myMdmProvider.updateLink(mySourcePatientId, new StringType(patient.getIdElement().getValue()), NO_MATCH_RESULT, null, myRequestDetails);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals(myMessageHelper.getMessageForUnsupportedSourceResource(), e.getMessage());
|
||||
|
|
|
@ -36,5 +36,5 @@ public interface IMdmControllerSvc {
|
|||
|
||||
IAnyResource mergeGoldenResources(String theFromGoldenResourceId, String theToGoldenResourceId, IAnyResource theManuallyMergedGoldenResource, MdmTransactionContext theMdmTransactionContext);
|
||||
|
||||
IAnyResource updateLink(String theGoldenResourceId, String theSourceResourceId, String theMatchResult, MdmTransactionContext theMdmTransactionContext);
|
||||
IAnyResource updateLink(String theGoldenResourceId, String theSourceResourceId, IAnyResource theManuallyMergedGoldenResource, String theMatchResult, MdmTransactionContext theMdmTransactionContext);
|
||||
}
|
||||
|
|
|
@ -24,6 +24,6 @@ import ca.uhn.fhir.mdm.model.MdmTransactionContext;
|
|||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
|
||||
public interface IMdmLinkUpdaterSvc {
|
||||
IAnyResource updateLink(IAnyResource theGoldenResource, IAnyResource theSourceResource, MdmMatchResultEnum theMatchResult, MdmTransactionContext theMdmContext);
|
||||
IAnyResource updateLink(IAnyResource theGoldenResource, IAnyResource theSourceResource, IAnyResource theManuallyMergedGoldenResource, MdmMatchResultEnum theMatchResult, MdmTransactionContext theMdmContext);
|
||||
void notDuplicateGoldenResource(IAnyResource theGoldenResource, IAnyResource theTargetGoldenResource, MdmTransactionContext theMdmContext);
|
||||
}
|
||||
|
|
|
@ -159,10 +159,11 @@ public class MdmProviderDstu3Plus extends BaseMdmProvider {
|
|||
public IBaseResource updateLink(@OperationParam(name = ProviderConstants.MDM_UPDATE_LINK_GOLDEN_RESOURCE_ID, min = 1, max = 1) IPrimitiveType<String> theGoldenResourceId,
|
||||
@OperationParam(name = ProviderConstants.MDM_UPDATE_LINK_RESOURCE_ID, min = 1, max = 1) IPrimitiveType<String> theResourceId,
|
||||
@OperationParam(name = ProviderConstants.MDM_UPDATE_LINK_MATCH_RESULT, min = 1, max = 1) IPrimitiveType<String> theMatchResult,
|
||||
@OperationParam(name = ProviderConstants.MDM_UPDATE_LINK_RESOURCE, max = 1) IAnyResource theManuallyMergedResource,
|
||||
ServletRequestDetails theRequestDetails) {
|
||||
validateUpdateLinkParameters(theGoldenResourceId, theResourceId, theMatchResult);
|
||||
return myMdmControllerSvc.updateLink(theGoldenResourceId.getValueAsString(), theResourceId.getValue(), theMatchResult.getValue(),
|
||||
createMdmContext(theRequestDetails, MdmTransactionContext.OperationType.UPDATE_LINK,
|
||||
return myMdmControllerSvc.updateLink(theGoldenResourceId.getValueAsString(), theResourceId.getValue(), theManuallyMergedResource,
|
||||
theMatchResult.getValue(), createMdmContext(theRequestDetails, MdmTransactionContext.OperationType.UPDATE_LINK,
|
||||
getResourceType(ProviderConstants.MDM_UPDATE_LINK_GOLDEN_RESOURCE_ID, theGoldenResourceId))
|
||||
);
|
||||
}
|
||||
|
|
|
@ -75,6 +75,7 @@ public class ProviderConstants {
|
|||
public static final String MDM_UPDATE_LINK = "$mdm-update-link";
|
||||
public static final String MDM_UPDATE_LINK_GOLDEN_RESOURCE_ID = "goldenResourceId";
|
||||
public static final String MDM_UPDATE_LINK_RESOURCE_ID = "resourceId";
|
||||
public static final String MDM_UPDATE_LINK_RESOURCE = "resource";
|
||||
public static final String MDM_UPDATE_LINK_MATCH_RESULT = "matchResult";
|
||||
|
||||
public static final String MDM_QUERY_LINKS = "$mdm-query-links";
|
||||
|
|
Loading…
Reference in New Issue