[3040] finish implementation (#3049)
* [3040] finish implementation * Update hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_operations.md Co-authored-by: Tadgh <tadgh@cs.toronto.edu> * Update hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_operations.md Co-authored-by: Tadgh <tadgh@cs.toronto.edu> * Update hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_operations.md Co-authored-by: Tadgh <tadgh@cs.toronto.edu> * [3040] throw exception if link exists * [3040] add matchResult parameter/update documentation Co-authored-by: Tadgh <tadgh@cs.toronto.edu>
This commit is contained in:
parent
a474e88ed4
commit
3c80dba90e
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
type: add
|
||||
issue: 3020
|
||||
jira: SMILE-3192
|
||||
title: "Added `$mdm-create-link` operation and documentation."
|
|
@ -396,6 +396,78 @@ Any supported MDM type can be used. The following request body shows how to upda
|
|||
|
||||
The operation returns the updated Golden Resource. For the query above `Patient` resource will be returned. Note that this is the only way to modify MDM-managed Golden Resources.
|
||||
|
||||
## Create Link
|
||||
|
||||
Use the `$mdm-create-link` operation to create an MDM link from a Golden Resource to a Target Resource without the need for any pre-existing matching data within the two resources. This operation takes the following parameters:
|
||||
|
||||
<table class="table table-striped table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Type</th>
|
||||
<th>Cardinality</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>goldenResourceId</td>
|
||||
<td>String</td>
|
||||
<td>1..1</td>
|
||||
<td>
|
||||
The id of the Golden Resource.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>resourceId</td>
|
||||
<td>String</td>
|
||||
<td>1..1</td>
|
||||
<td>
|
||||
The id of the target resource.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>matchResult</td>
|
||||
<td>String</td>
|
||||
<td>0..1</td>
|
||||
<td>
|
||||
Optional matchResult. If omitted, it automatically set the default to MATCH, otherwise the value should be
|
||||
MATCH, POSSIBLE_MATCH or NO_MATCH.
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
MDM links created in this way will automatically have their `linkSource` set to `MANUAL`.
|
||||
|
||||
### Example
|
||||
|
||||
Use an HTTP POST to the following URL to invoke this operation:
|
||||
|
||||
```url
|
||||
http://example.com/$mdm-create-link
|
||||
```
|
||||
|
||||
Any supported MDM type can be used. The following request body shows how to update link on the Patient resource type:
|
||||
|
||||
```json
|
||||
{
|
||||
"resourceType": "Parameters",
|
||||
"parameter": [ {
|
||||
"name": "goldenResourceId",
|
||||
"valueString": "Patient/123"
|
||||
}, {
|
||||
"name": "resourceId",
|
||||
"valueString": "Patient/456"
|
||||
}, {
|
||||
"name": "matchResult",
|
||||
"valueString": "MATCH"
|
||||
} ]
|
||||
}
|
||||
```
|
||||
|
||||
The operation returns the Golden Resource. For the query above, `Patient` will be returned.
|
||||
|
||||
## Merge Golden Resources
|
||||
|
||||
The `$mdm-merge-golden-resources` operation can be used to merge one Golden Resource with another. When doing this, you will need to decide which resource to merge from and which one to merge to.
|
||||
|
|
|
@ -35,6 +35,7 @@ import ca.uhn.fhir.jpa.mdm.svc.GoldenResourceMergerSvcImpl;
|
|||
import ca.uhn.fhir.jpa.mdm.svc.IMdmModelConverterSvc;
|
||||
import ca.uhn.fhir.jpa.mdm.svc.MdmControllerSvcImpl;
|
||||
import ca.uhn.fhir.jpa.mdm.svc.MdmEidUpdateService;
|
||||
import ca.uhn.fhir.jpa.mdm.svc.MdmLinkCreateSvcImpl;
|
||||
import ca.uhn.fhir.jpa.mdm.svc.MdmLinkQuerySvcImplSvc;
|
||||
import ca.uhn.fhir.jpa.mdm.svc.MdmLinkSvcImpl;
|
||||
import ca.uhn.fhir.jpa.mdm.svc.MdmLinkUpdaterSvcImpl;
|
||||
|
@ -55,6 +56,7 @@ import ca.uhn.fhir.jpa.mdm.svc.candidate.MdmGoldenResourceFindingSvc;
|
|||
import ca.uhn.fhir.mdm.api.IGoldenResourceMergerSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmBatchJobSubmitterFactory;
|
||||
import ca.uhn.fhir.mdm.api.IMdmControllerSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLinkCreateSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLinkQuerySvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLinkSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLinkUpdaterSvc;
|
||||
|
@ -233,6 +235,12 @@ public class MdmConsumerConfig {
|
|||
return new MdmLinkUpdaterSvcImpl();
|
||||
}
|
||||
|
||||
@Bean
|
||||
IMdmLinkCreateSvc mdmLinkCreateSvc() {
|
||||
return new MdmLinkCreateSvcImpl();
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
MdmLoader mdmLoader() {
|
||||
return new MdmLoader();
|
||||
|
|
|
@ -24,6 +24,7 @@ import ca.uhn.fhir.context.FhirContext;
|
|||
import ca.uhn.fhir.mdm.api.IGoldenResourceMergerSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmBatchJobSubmitterFactory;
|
||||
import ca.uhn.fhir.mdm.api.IMdmControllerSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLinkCreateSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLinkQuerySvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLinkUpdaterSvc;
|
||||
import ca.uhn.fhir.mdm.api.MdmLinkJson;
|
||||
|
@ -65,6 +66,8 @@ public class MdmControllerSvcImpl implements IMdmControllerSvc {
|
|||
@Autowired
|
||||
IMdmLinkUpdaterSvc myIMdmLinkUpdaterSvc;
|
||||
@Autowired
|
||||
IMdmLinkCreateSvc myIMdmLinkCreateSvc;
|
||||
@Autowired
|
||||
IMdmBatchJobSubmitterFactory myMdmBatchJobSubmitterFactory;
|
||||
|
||||
public MdmControllerSvcImpl() {
|
||||
|
@ -106,6 +109,17 @@ public class MdmControllerSvcImpl implements IMdmControllerSvc {
|
|||
return myIMdmLinkUpdaterSvc.updateLink(goldenResource, source, matchResult, theMdmTransactionContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAnyResource createLink(String theGoldenResourceId, String theSourceResourceId, @Nullable String theMatchResult, MdmTransactionContext theMdmTransactionContext) {
|
||||
MdmMatchResultEnum matchResult = MdmControllerUtil.extractMatchResultOrNull(theMatchResult);
|
||||
IAnyResource goldenResource = myMdmControllerHelper.getLatestGoldenResourceFromIdOrThrowException(ProviderConstants.MDM_CREATE_LINK_GOLDEN_RESOURCE_ID, theGoldenResourceId);
|
||||
IAnyResource source = myMdmControllerHelper.getLatestSourceFromIdOrThrowException(ProviderConstants.MDM_CREATE_LINK_RESOURCE_ID, theSourceResourceId);
|
||||
myMdmControllerHelper.validateSameVersion(goldenResource, theGoldenResourceId);
|
||||
myMdmControllerHelper.validateSameVersion(source, theSourceResourceId);
|
||||
|
||||
return myIMdmLinkCreateSvc.createLink(goldenResource, source, matchResult, theMdmTransactionContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBaseParameters submitMdmClearJob(List<String> theUrls, IPrimitiveType<BigDecimal> theBatchSize, ServletRequestDetails theRequestDetails) {
|
||||
MultiUrlProcessor multiUrlProcessor = new MultiUrlProcessor(myFhirContext, myMdmBatchJobSubmitterFactory.getClearJobSubmitter());
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
package ca.uhn.fhir.jpa.mdm.svc;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.dao.index.IdHelperService;
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLinkCreateSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmSettings;
|
||||
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||
import ca.uhn.fhir.mdm.log.Logs;
|
||||
import ca.uhn.fhir.mdm.model.MdmTransactionContext;
|
||||
import ca.uhn.fhir.mdm.util.MdmResourceUtil;
|
||||
import ca.uhn.fhir.mdm.util.MessageHelper;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.slf4j.Logger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
public class MdmLinkCreateSvcImpl implements IMdmLinkCreateSvc {
|
||||
private static final Logger ourLog = Logs.getMdmTroubleshootingLog();
|
||||
|
||||
@Autowired
|
||||
FhirContext myFhirContext;
|
||||
@Autowired
|
||||
IdHelperService myIdHelperService;
|
||||
@Autowired
|
||||
MdmLinkDaoSvc myMdmLinkDaoSvc;
|
||||
@Autowired
|
||||
IMdmSettings myMdmSettings;
|
||||
@Autowired
|
||||
MessageHelper myMessageHelper;
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public IAnyResource createLink(IAnyResource theGoldenResource, IAnyResource theSourceResource, MdmMatchResultEnum theMatchResult, MdmTransactionContext theMdmContext) {
|
||||
String sourceType = myFhirContext.getResourceType(theSourceResource);
|
||||
|
||||
validateCreateLinkRequest(theGoldenResource, theSourceResource, sourceType);
|
||||
|
||||
Long goldenResourceId = myIdHelperService.getPidOrThrowException(theGoldenResource);
|
||||
Long targetId = myIdHelperService.getPidOrThrowException(theSourceResource);
|
||||
|
||||
Optional<MdmLink> optionalMdmLink = myMdmLinkDaoSvc.getLinkByGoldenResourcePidAndSourceResourcePid(goldenResourceId, targetId);
|
||||
if (optionalMdmLink.isPresent()) {
|
||||
throw new InvalidRequestException(myMessageHelper.getMessageForPresentLink(theGoldenResource, theSourceResource));
|
||||
}
|
||||
|
||||
List<MdmLink> mdmLinks = myMdmLinkDaoSvc.getMdmLinksBySourcePidAndMatchResult(targetId, MdmMatchResultEnum.MATCH);
|
||||
if (mdmLinks.size() > 0 && theMatchResult == MdmMatchResultEnum.MATCH) {
|
||||
throw new InvalidRequestException(myMessageHelper.getMessageForMultipleGoldenRecords(theSourceResource));
|
||||
}
|
||||
|
||||
MdmLink mdmLink = myMdmLinkDaoSvc.getOrCreateMdmLinkByGoldenResourcePidAndSourceResourcePid(goldenResourceId, targetId);
|
||||
mdmLink.setLinkSource(MdmLinkSourceEnum.MANUAL);
|
||||
if (theMatchResult == null) {
|
||||
mdmLink.setMatchResult(MdmMatchResultEnum.MATCH);
|
||||
} else {
|
||||
mdmLink.setMatchResult(theMatchResult);
|
||||
}
|
||||
ourLog.info("Manually creating a " + theGoldenResource.getIdElement().toVersionless() + " to " + theSourceResource.getIdElement().toVersionless() + " mdm link.");
|
||||
myMdmLinkDaoSvc.save(mdmLink);
|
||||
|
||||
return theGoldenResource;
|
||||
}
|
||||
|
||||
private void validateCreateLinkRequest(IAnyResource theGoldenRecord, IAnyResource theSourceResource, String theSourceType) {
|
||||
String goldenRecordType = myFhirContext.getResourceType(theGoldenRecord);
|
||||
|
||||
if (!myMdmSettings.isSupportedMdmType(goldenRecordType)) {
|
||||
throw new InvalidRequestException(myMessageHelper.getMessageForUnsupportedFirstArgumentTypeInUpdate(goldenRecordType));
|
||||
}
|
||||
|
||||
if (!myMdmSettings.isSupportedMdmType(theSourceType)) {
|
||||
throw new InvalidRequestException(myMessageHelper.getMessageForUnsupportedSecondArgumentTypeInUpdate(theSourceType));
|
||||
}
|
||||
|
||||
if (!Objects.equals(goldenRecordType, theSourceType)) {
|
||||
throw new InvalidRequestException(myMessageHelper.getMessageForArgumentTypeMismatchInUpdate(goldenRecordType, theSourceType));
|
||||
}
|
||||
|
||||
if (!MdmResourceUtil.isMdmManaged(theGoldenRecord)) {
|
||||
throw new InvalidRequestException(myMessageHelper.getMessageForUnmanagedResource());
|
||||
}
|
||||
|
||||
if (!MdmResourceUtil.isMdmAllowed(theSourceResource)) {
|
||||
throw new InvalidRequestException(myMessageHelper.getMessageForUnsupportedSourceResource());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,175 @@
|
|||
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.rest.server.exceptions.InvalidRequestException;
|
||||
import org.hl7.fhir.r4.model.Patient;
|
||||
import org.hl7.fhir.r4.model.StringType;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.endsWith;
|
||||
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.fail;
|
||||
|
||||
public class MdmProviderCreateLinkR4Test extends BaseLinkR4Test {
|
||||
|
||||
@Autowired
|
||||
private MessageHelper myMessageHelper;
|
||||
|
||||
@Test
|
||||
public void testCreateLinkWithMatchResult() {
|
||||
assertLinkCount(1);
|
||||
|
||||
Patient patient = createPatient(buildPatientWithNameAndId("PatientGiven", "ID.PatientGiven.123"), true, false);
|
||||
StringType patientId = new StringType(patient.getIdElement().getValue());
|
||||
|
||||
Patient sourcePatient = createPatient(buildPatientWithNameAndId("SourcePatientGiven", "ID.SourcePatientGiven.123"), true, false);
|
||||
StringType sourcePatientId = new StringType(sourcePatient.getIdElement().getValue());
|
||||
|
||||
myMdmProvider.createLink(sourcePatientId, patientId, MATCH_RESULT, myRequestDetails);
|
||||
assertLinkCount(2);
|
||||
|
||||
List<MdmLink> links = myMdmLinkDaoSvc.findMdmLinksBySourceResource(patient);
|
||||
assertEquals(MdmLinkSourceEnum.MANUAL, links.get(0).getLinkSource());
|
||||
assertEquals(MdmMatchResultEnum.MATCH, links.get(0).getMatchResult());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateLinkWithNullMatchResult() {
|
||||
assertLinkCount(1);
|
||||
|
||||
Patient patient = createPatient(buildPatientWithNameAndId("PatientGiven", "ID.PatientGiven.123"), true, false);
|
||||
StringType patientId = new StringType(patient.getIdElement().getValue());
|
||||
|
||||
Patient sourcePatient = createPatient(buildPatientWithNameAndId("SourcePatientGiven", "ID.SourcePatientGiven.123"), true, false);
|
||||
StringType sourcePatientId = new StringType(sourcePatient.getIdElement().getValue());
|
||||
|
||||
myMdmProvider.createLink(sourcePatientId, patientId, null, myRequestDetails);
|
||||
assertLinkCount(2);
|
||||
|
||||
List<MdmLink> links = myMdmLinkDaoSvc.findMdmLinksBySourceResource(patient);
|
||||
assertEquals(MdmLinkSourceEnum.MANUAL, links.get(0).getLinkSource());
|
||||
assertEquals(MdmMatchResultEnum.MATCH, links.get(0).getMatchResult());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateLinkTwiceWithDifferentGoldenResourceAndMatchResult() {
|
||||
assertLinkCount(1);
|
||||
|
||||
Patient patient = createPatient(buildPatientWithNameAndId("PatientGiven", "ID.PatientGiven.123"), true, false);
|
||||
StringType patientId = new StringType(patient.getIdElement().getValue());
|
||||
|
||||
Patient sourcePatient = createPatient(buildPatientWithNameAndId("SourcePatientGiven", "ID.SourcePatientGiven.123"), true, false);
|
||||
StringType sourcePatientId = new StringType(sourcePatient.getIdElement().getValue());
|
||||
|
||||
myMdmProvider.createLink(sourcePatientId, patientId, MATCH_RESULT, myRequestDetails);
|
||||
|
||||
Patient sourcePatient2 = createPatient(buildPatientWithNameAndId("SourcePatientGiven2", "ID.SourcePatientGiven.123.2"), true, false);
|
||||
StringType sourcePatientId2 = new StringType(sourcePatient2.getIdElement().getValue());
|
||||
|
||||
try {
|
||||
myMdmProvider.createLink(sourcePatientId2, patientId, MATCH_RESULT, myRequestDetails);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), endsWith("Use $mdm-query-links to see more details."));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateLinkTwiceWithDifferentGoldenResourceAndNoMatchResult() {
|
||||
assertLinkCount(1);
|
||||
|
||||
Patient patient = createPatient(buildPatientWithNameAndId("PatientGiven", "ID.PatientGiven.123"), true, false);
|
||||
StringType patientId = new StringType(patient.getIdElement().getValue());
|
||||
|
||||
Patient sourcePatient = createPatient(buildPatientWithNameAndId("SourcePatientGiven", "ID.SourcePatientGiven.123"), true, false);
|
||||
StringType sourcePatientId = new StringType(sourcePatient.getIdElement().getValue());
|
||||
|
||||
myMdmProvider.createLink(sourcePatientId, patientId, MATCH_RESULT, myRequestDetails);
|
||||
|
||||
Patient sourcePatient2 = createPatient(buildPatientWithNameAndId("SourcePatientGiven2", "ID.SourcePatientGiven.123.2"), true, false);
|
||||
StringType sourcePatientId2 = new StringType(sourcePatient2.getIdElement().getValue());
|
||||
|
||||
myMdmProvider.createLink(sourcePatientId2, patientId, NO_MATCH_RESULT, myRequestDetails);
|
||||
|
||||
assertLinkCount(3);
|
||||
List<MdmLink> links = myMdmLinkDaoSvc.findMdmLinksBySourceResource(patient);
|
||||
assertEquals(MdmLinkSourceEnum.MANUAL, links.get(1).getLinkSource());
|
||||
assertEquals(MdmMatchResultEnum.NO_MATCH, links.get(1).getMatchResult());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateExistentLink() {
|
||||
assertLinkCount(1);
|
||||
try {
|
||||
myMdmProvider.createLink(mySourcePatientId, myPatientId, MATCH_RESULT,myRequestDetails);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), startsWith("Link already exists"));
|
||||
}
|
||||
assertLinkCount(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateIllegalResultPD() {
|
||||
try {
|
||||
myMdmProvider.createLink(mySourcePatientId, myPatientId, POSSIBLE_DUPLICATE_RESULT, myRequestDetails);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals("$mdm-create-link illegal matchResult value 'POSSIBLE_DUPLICATE'. Must be NO_MATCH, MATCH or POSSIBLE_MATCH", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateIllegalFirstArg() {
|
||||
try {
|
||||
myMdmProvider.createLink(new StringType(""), myPatientId, MATCH_RESULT, myRequestDetails);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), endsWith(" must have form <resourceType>/<id> where <id> is the id of the resource"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateIllegalSecondArg() {
|
||||
try {
|
||||
myMdmProvider.createLink(myPatientId, new StringType(""), MATCH_RESULT, 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"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateStrangePatient() {
|
||||
Patient patient = createPatient();
|
||||
try {
|
||||
myMdmProvider.createLink(new StringType(patient.getIdElement().getValue()), myPatientId, MATCH_RESULT, myRequestDetails);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
String expectedMessage = myMessageHelper.getMessageForUnmanagedResource();
|
||||
assertEquals(expectedMessage, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExcludedGoldenResource() {
|
||||
Patient patient = new Patient();
|
||||
patient.getMeta().addTag().setSystem(MdmConstants.SYSTEM_MDM_MANAGED).setCode(MdmConstants.CODE_NO_MDM_MANAGED);
|
||||
createPatient(patient);
|
||||
try {
|
||||
myMdmProvider.createLink(mySourcePatientId, new StringType(patient.getIdElement().getValue()), MATCH_RESULT, myRequestDetails);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals(myMessageHelper.getMessageForUnsupportedSourceResource(), e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -44,5 +44,7 @@ public interface IMdmControllerSvc {
|
|||
|
||||
IAnyResource updateLink(String theGoldenResourceId, String theSourceResourceId, String theMatchResult, MdmTransactionContext theMdmTransactionContext);
|
||||
|
||||
IAnyResource createLink(String theGoldenResourceId, String theSourceResourceId, @Nullable String theMatchResult, MdmTransactionContext theMdmTransactionContext);
|
||||
|
||||
IBaseParameters submitMdmClearJob(List<String> theUrls, IPrimitiveType<BigDecimal> theBatchSize, ServletRequestDetails theRequestDetails);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
package ca.uhn.fhir.mdm.api;
|
||||
|
||||
import ca.uhn.fhir.mdm.model.MdmTransactionContext;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public interface IMdmLinkCreateSvc {
|
||||
IAnyResource createLink(IAnyResource theGoldenResource, IAnyResource theSourceResource, MdmMatchResultEnum theMatchResult, MdmTransactionContext theMdmContext);
|
||||
}
|
|
@ -35,6 +35,7 @@ public class MdmTransactionContext {
|
|||
SUBMIT_RESOURCE_TO_MDM,
|
||||
QUERY_LINKS,
|
||||
UPDATE_LINK,
|
||||
CREATE_LINK,
|
||||
DUPLICATE_GOLDEN_RESOURCES,
|
||||
NOT_DUPLICATE,
|
||||
MERGE_GOLDEN_RESOURCES,
|
||||
|
|
|
@ -38,6 +38,8 @@ import org.hl7.fhir.instance.model.api.IBaseParameters;
|
|||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.springframework.data.domain.Page;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
|
||||
public abstract class BaseMdmProvider {
|
||||
|
||||
|
@ -81,6 +83,22 @@ public abstract class BaseMdmProvider {
|
|||
validateNotNull(ProviderConstants.MDM_UPDATE_LINK_RESOURCE_ID, theResourceId);
|
||||
}
|
||||
|
||||
protected void validateCreateLinkParameters(IPrimitiveType<String> theGoldenResourceId, IPrimitiveType<String> theResourceId, @Nullable IPrimitiveType<String> theMatchResult) {
|
||||
validateNotNull(ProviderConstants.MDM_CREATE_LINK_GOLDEN_RESOURCE_ID, theGoldenResourceId);
|
||||
validateNotNull(ProviderConstants.MDM_CREATE_LINK_RESOURCE_ID, theResourceId);
|
||||
if (theMatchResult != null) {
|
||||
MdmMatchResultEnum matchResult = MdmMatchResultEnum.valueOf(theMatchResult.getValue());
|
||||
switch (matchResult) {
|
||||
case NO_MATCH:
|
||||
case POSSIBLE_MATCH:
|
||||
case MATCH:
|
||||
break;
|
||||
default:
|
||||
throw new InvalidRequestException(ProviderConstants.MDM_CREATE_LINK + " illegal " + ProviderConstants.MDM_CREATE_LINK_MATCH_RESULT +
|
||||
" value '" + matchResult + "'. Must be " + MdmMatchResultEnum.NO_MATCH + ", " + MdmMatchResultEnum.MATCH + " or " + MdmMatchResultEnum.POSSIBLE_MATCH);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected MdmTransactionContext createMdmContext(RequestDetails theRequestDetails, MdmTransactionContext.OperationType theOperationType, String theResourceType) {
|
||||
TransactionLogMessages transactionLogMessages = TransactionLogMessages.createFromTransactionGuid(theRequestDetails.getTransactionGuid());
|
||||
|
|
|
@ -53,6 +53,7 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
|
|||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.slf4j.Logger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
@ -180,6 +181,18 @@ public class MdmProviderDstu3Plus extends BaseMdmProvider {
|
|||
);
|
||||
}
|
||||
|
||||
@Operation(name = ProviderConstants.MDM_CREATE_LINK)
|
||||
public IBaseResource createLink(@OperationParam(name = ProviderConstants.MDM_CREATE_LINK_GOLDEN_RESOURCE_ID, min = 1, max = 1) IPrimitiveType<String> theGoldenResourceId,
|
||||
@OperationParam(name = ProviderConstants.MDM_CREATE_LINK_RESOURCE_ID, min = 1, max = 1) IPrimitiveType<String> theResourceId,
|
||||
@OperationParam(name = ProviderConstants.MDM_CREATE_LINK_MATCH_RESULT, min = 0, max = 1) IPrimitiveType<String> theMatchResult,
|
||||
ServletRequestDetails theRequestDetails) {
|
||||
validateCreateLinkParameters(theGoldenResourceId, theResourceId, theMatchResult);
|
||||
return myMdmControllerSvc.createLink(theGoldenResourceId.getValueAsString(), theResourceId.getValue(), extractStringOrNull(theMatchResult),
|
||||
createMdmContext(theRequestDetails, MdmTransactionContext.OperationType.CREATE_LINK,
|
||||
getResourceType(ProviderConstants.MDM_CREATE_LINK_GOLDEN_RESOURCE_ID, theGoldenResourceId))
|
||||
);
|
||||
}
|
||||
|
||||
@Operation(name = ProviderConstants.OPERATION_MDM_CLEAR, returnParameters = {
|
||||
@OperationParam(name = ProviderConstants.OPERATION_BATCH_RESPONSE_JOB_ID, typeName = "decimal")
|
||||
})
|
||||
|
|
|
@ -90,4 +90,21 @@ public class MessageHelper {
|
|||
public String getMessageForNoLink(String theGoldenRecord, String theSourceResource) {
|
||||
return "No link exists between " + theGoldenRecord + " and " + theSourceResource;
|
||||
}
|
||||
|
||||
public String getMessageForPresentLink(IAnyResource theGoldenRecord, IAnyResource theSourceResource) {
|
||||
return getMessageForPresentLink(theGoldenRecord.getIdElement().toVersionless().toString(),
|
||||
theSourceResource.getIdElement().toVersionless().toString());
|
||||
}
|
||||
|
||||
public String getMessageForPresentLink(String theGoldenRecord, String theSourceResource) {
|
||||
return "Link already exists between " + theGoldenRecord + " and " + theSourceResource + ". Use $mdm-update-link instead.";
|
||||
}
|
||||
|
||||
public String getMessageForMultipleGoldenRecords(IAnyResource theSourceResource) {
|
||||
return getMessageForMultipleGoldenRecords(theSourceResource.getIdElement().toVersionless().toString());
|
||||
}
|
||||
|
||||
public String getMessageForMultipleGoldenRecords(String theSourceResource) {
|
||||
return theSourceResource + " already has matched golden resource. Use $mdm-query-links to see more details.";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,6 +80,11 @@ public class ProviderConstants {
|
|||
public static final String MDM_UPDATE_LINK_RESOURCE_ID = "resourceId";
|
||||
public static final String MDM_UPDATE_LINK_MATCH_RESULT = "matchResult";
|
||||
|
||||
public static final String MDM_CREATE_LINK = "$mdm-create-link";
|
||||
public static final String MDM_CREATE_LINK_GOLDEN_RESOURCE_ID = "goldenResourceId";
|
||||
public static final String MDM_CREATE_LINK_RESOURCE_ID = "resourceId";
|
||||
public static final String MDM_CREATE_LINK_MATCH_RESULT = "matchResult";
|
||||
|
||||
public static final String MDM_QUERY_LINKS = "$mdm-query-links";
|
||||
public static final String MDM_QUERY_LINKS_GOLDEN_RESOURCE_ID = "goldenResourceId";
|
||||
public static final String MDM_QUERY_LINKS_RESOURCE_ID = "resourceId";
|
||||
|
|
Loading…
Reference in New Issue