all updated resources to link to existing resources (#5152)

updating mdm resources will update all links to them as well as any links that it would match after update
This commit is contained in:
TipzCM 2023-08-02 12:29:17 -04:00 committed by GitHub
parent 5eda18f500
commit fd5c2c2862
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 387 additions and 35 deletions

View File

@ -0,0 +1,10 @@
---
issue: 5141
type: add
title: "Previously, updating an existing resource (resource A) to match a resource that
it didn't match to before (resource B) would update only the already
existing links on resource A.
This behaviour has been changed. Now such an update will also add additional links,
if necessary, from resource A to resource B, including adding a POSSIBLE_DUPLICATE
between golden resource A and golden resource B.
"

View File

@ -81,10 +81,10 @@ public class MdmMessageHandler implements MessageHandler {
ResourceModifiedMessage msg = ((ResourceModifiedJsonMessage) theMessage).getPayload();
try {
IBaseResource sourceResource = msg.getNewPayload(myFhirContext);
if (myMdmResourceFilteringSvc.shouldBeProcessed((IAnyResource) sourceResource)) {
boolean toProcess = myMdmResourceFilteringSvc.shouldBeProcessed((IAnyResource) sourceResource);
if (toProcess) {
matchMdmAndUpdateLinks(sourceResource, msg);
}
} catch (TooManyCandidatesException e) {

View File

@ -0,0 +1,30 @@
package ca.uhn.fhir.jpa.mdm.models;
import ca.uhn.fhir.mdm.model.MdmTransactionContext;
import org.hl7.fhir.instance.model.api.IAnyResource;
public class FindGoldenResourceCandidatesParams {
/**
* The resource to find matches for
*/
private final IAnyResource myResource;
/**
* The mdm context
*/
private final MdmTransactionContext myContext;
public FindGoldenResourceCandidatesParams(IAnyResource theResource, MdmTransactionContext theContext) {
myResource = theResource;
myContext = theContext;
}
public IAnyResource getResource() {
return myResource;
}
public MdmTransactionContext getContext() {
return myContext;
}
}

View File

@ -19,6 +19,7 @@
*/
package ca.uhn.fhir.jpa.mdm.svc;
import ca.uhn.fhir.jpa.mdm.models.FindGoldenResourceCandidatesParams;
import ca.uhn.fhir.jpa.mdm.svc.candidate.CandidateList;
import ca.uhn.fhir.jpa.mdm.svc.candidate.CandidateStrategyEnum;
import ca.uhn.fhir.jpa.mdm.svc.candidate.MatchedGoldenResourceCandidate;
@ -93,7 +94,7 @@ public class MdmMatchLinkSvc {
// we require a candidatestrategy, but it doesn't matter
// because empty lists are effectively no matches
// (and so the candidate strategy doesn't matter)
CandidateList candidateList = new CandidateList(CandidateStrategyEnum.LINK);
CandidateList candidateList = new CandidateList(CandidateStrategyEnum.ANY);
/*
* If a resource is blocked, we will not conduct
@ -103,7 +104,9 @@ public class MdmMatchLinkSvc {
boolean isResourceBlocked = myBlockRuleEvaluationSvc.isMdmMatchingBlocked(theResource);
if (!isResourceBlocked) {
candidateList = myMdmGoldenResourceFindingSvc.findGoldenResourceCandidates(theResource);
FindGoldenResourceCandidatesParams params =
new FindGoldenResourceCandidatesParams(theResource, theMdmTransactionContext);
candidateList = myMdmGoldenResourceFindingSvc.findGoldenResourceCandidates(params);
}
if (isResourceBlocked || candidateList.isEmpty()) {

View File

@ -35,7 +35,7 @@ public abstract class BaseCandidateFinder {
CandidateList findCandidates(IAnyResource theTarget) {
CandidateList candidateList = new CandidateList(getStrategy());
candidateList.addAll(findMatchGoldenResourceCandidates(theTarget));
candidateList.addAll(getStrategy(), findMatchGoldenResourceCandidates(theTarget));
return candidateList;
}

View File

@ -19,17 +19,29 @@
*/
package ca.uhn.fhir.jpa.mdm.svc.candidate;
import ca.uhn.fhir.i18n.Msg;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class CandidateList {
private final CandidateStrategyEnum myStrategy;
private final List<MatchedGoldenResourceCandidate> myList = new ArrayList<>();
// no multimap - ordering matters
private final Map<CandidateStrategyEnum, List<MatchedGoldenResourceCandidate>> myStrategyToCandidateList =
new HashMap<>();
public CandidateList(CandidateStrategyEnum theStrategy) {
myStrategy = theStrategy;
myStrategyToCandidateList.put(CandidateStrategyEnum.EID, new ArrayList<>());
myStrategyToCandidateList.put(CandidateStrategyEnum.LINK, new ArrayList<>());
myStrategyToCandidateList.put(CandidateStrategyEnum.SCORE, new ArrayList<>());
}
public CandidateStrategyEnum getStrategy() {
@ -37,32 +49,75 @@ public class CandidateList {
}
public boolean isEmpty() {
return myList.isEmpty();
return size() == 0;
}
public void addAll(List<MatchedGoldenResourceCandidate> theList) {
myList.addAll(theList);
public void addAll(CandidateStrategyEnum theStrategy, List<MatchedGoldenResourceCandidate> theList) {
switch (theStrategy) {
case EID:
case LINK:
case SCORE:
myStrategyToCandidateList.get(theStrategy).addAll(theList);
break;
default:
throw new InternalErrorException(
Msg.code(2424) + " Existing resources cannot be added for strategy " + theStrategy.name());
}
}
public MatchedGoldenResourceCandidate getOnlyMatch() {
assert myList.size() == 1;
return myList.get(0);
assert size() == 1;
return getCandidates().get(0);
}
public boolean exactlyOneMatch() {
return myList.size() == 1;
return size() == 1;
}
/**
* Returns a stream of all types.
* If multiple streams are present,
* they will be ordered by strategy type
*/
public Stream<MatchedGoldenResourceCandidate> stream() {
return myList.stream();
return Stream.concat(
myStrategyToCandidateList.get(CandidateStrategyEnum.EID).stream(),
Stream.concat(
myStrategyToCandidateList.get(CandidateStrategyEnum.LINK).stream(),
myStrategyToCandidateList.get(CandidateStrategyEnum.SCORE).stream()));
}
public Stream<MatchedGoldenResourceCandidate> stream(CandidateStrategyEnum theStrategy) {
return myStrategyToCandidateList.get(theStrategy).stream();
}
public List<MatchedGoldenResourceCandidate> getCandidates() {
return Collections.unmodifiableList(myList);
switch (myStrategy) {
case LINK:
case EID:
case SCORE:
return new ArrayList<>(myStrategyToCandidateList.get(myStrategy));
default:
return Stream.of(
myStrategyToCandidateList.get(CandidateStrategyEnum.EID),
myStrategyToCandidateList.get(CandidateStrategyEnum.LINK),
myStrategyToCandidateList.get(CandidateStrategyEnum.SCORE))
.flatMap(Collection::stream)
.collect(Collectors.toList());
}
}
public MatchedGoldenResourceCandidate getFirstMatch() {
return myList.get(0);
assert size() > 0;
switch (myStrategy) {
case EID:
case LINK:
case SCORE:
return myStrategyToCandidateList.get(myStrategy).get(0);
default:
return getCandidates().get(0);
}
}
public boolean isEidMatch() {
@ -70,6 +125,19 @@ public class CandidateList {
}
public int size() {
return myList.size();
switch (myStrategy) {
case EID:
case LINK:
case SCORE:
return myStrategyToCandidateList.get(myStrategy).size();
default:
return myStrategyToCandidateList.get(CandidateStrategyEnum.EID).size()
+ myStrategyToCandidateList
.get(CandidateStrategyEnum.LINK)
.size()
+ myStrategyToCandidateList
.get(CandidateStrategyEnum.SCORE)
.size();
}
}
}

View File

@ -25,7 +25,11 @@ public enum CandidateStrategyEnum {
/** Find Golden Resource candidates based on a link already existing for the source resource */
LINK,
/** Find Golden Resource candidates based on other sources that match the incoming source using the MDM Matching rules */
SCORE;
SCORE,
/**
* Find golden resource candidates that are EID, LINK, or SCORE.
*/
ANY;
public boolean isEidMatch() {
return this == EID;

View File

@ -19,8 +19,10 @@
*/
package ca.uhn.fhir.jpa.mdm.svc.candidate;
import ca.uhn.fhir.jpa.mdm.models.FindGoldenResourceCandidatesParams;
import ca.uhn.fhir.jpa.mdm.svc.MdmResourceDaoSvc;
import ca.uhn.fhir.mdm.log.Logs;
import ca.uhn.fhir.mdm.model.MdmTransactionContext;
import ca.uhn.fhir.rest.api.server.storage.IResourcePersistentId;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IBaseResource;
@ -56,23 +58,47 @@ public class MdmGoldenResourceFindingSvc {
* 4. If none are found, attempt to find Golden Resources that are linked to sources that are similar to our incoming resource based on the MDM rules and
* field matchers.
*
* @param theResource the {@link IBaseResource} we are attempting to find matching candidate Golden Resources for.
* @param theParams Params hold the {@link IBaseResource} for which we are attempting to find matching candidate Golden Resources,
* as well as the mdm context.
* @return A list of {@link MatchedGoldenResourceCandidate} indicating all potential Golden Resource matches.
*/
public CandidateList findGoldenResourceCandidates(IAnyResource theResource) {
CandidateList matchedGoldenResourceCandidates = myFindCandidateByEidSvc.findCandidates(theResource);
public CandidateList findGoldenResourceCandidates(FindGoldenResourceCandidatesParams theParams) {
IAnyResource resource = theParams.getResource();
if (matchedGoldenResourceCandidates.isEmpty()) {
matchedGoldenResourceCandidates = myFindCandidateByLinkSvc.findCandidates(theResource);
CandidateList eidGoldenResources = myFindCandidateByEidSvc.findCandidates(resource);
// if we have matches from eid, we'll return only these
if (!eidGoldenResources.isEmpty()) {
return eidGoldenResources;
}
if (matchedGoldenResourceCandidates.isEmpty()) {
// OK, so we have not found any links in the MdmLink table with us as a source. Next, let's find
// possible Golden Resources matches by following MDM rules.
matchedGoldenResourceCandidates = myFindCandidateByExampleSvc.findCandidates(theResource);
boolean isUpdate =
theParams.getContext().getRestOperation() == MdmTransactionContext.OperationType.UPDATE_RESOURCE;
// find MdmLinks that have theResource as the source
// (these are current golden resources matching this resource)
CandidateList linkGoldenResources = myFindCandidateByLinkSvc.findCandidates(resource);
if (!linkGoldenResources.isEmpty() && !isUpdate) {
return linkGoldenResources;
}
return matchedGoldenResourceCandidates;
// if we're updating, we might have existing resources that could *also* match
// find other golden resources that could be matching to this resource
// (we only need to do this for updates because otherwise they would already have matching resources
CandidateList anyGoldenResources = myFindCandidateByExampleSvc.findCandidates(resource);
if (linkGoldenResources.isEmpty()) {
// only other resources are available - we'll return this
return anyGoldenResources;
}
// else, we will combine the lists
CandidateList matches = new CandidateList(CandidateStrategyEnum.ANY);
matches.addAll(CandidateStrategyEnum.LINK, linkGoldenResources.getCandidates());
matches.addAll(CandidateStrategyEnum.SCORE, anyGoldenResources.getCandidates());
return matches;
}
public IAnyResource getGoldenResourceFromMatchedGoldenResourceCandidate(

View File

@ -208,7 +208,7 @@ public class MdmLinkHelper {
}
}
assertTrue(foundLink, String.format("State: %s - not found", stateExpression));
assertTrue(foundLink, String.format("State: %s - not found", stateExpression.getLinkExpression()));
}
}

View File

@ -7,7 +7,6 @@ import ca.uhn.fhir.jpa.entity.PartitionEntity;
import ca.uhn.fhir.jpa.interceptor.UserRequestRetryVersionConflictsInterceptor;
import ca.uhn.fhir.jpa.mdm.provider.BaseLinkR4Test;
import ca.uhn.fhir.jpa.partition.IRequestPartitionHelperSvc;
import ca.uhn.fhir.rest.api.server.SystemRequestDetails;
import ca.uhn.fhir.jpa.test.Batch2JobHelper;
import ca.uhn.fhir.mdm.api.IMdmControllerSvc;
import ca.uhn.fhir.mdm.api.MdmLinkJson;
@ -18,6 +17,7 @@ import ca.uhn.fhir.mdm.api.paging.MdmPageRequest;
import ca.uhn.fhir.mdm.batch2.clear.MdmClearStep;
import ca.uhn.fhir.mdm.model.MdmTransactionContext;
import ca.uhn.fhir.mdm.rules.config.MdmSettings;
import ca.uhn.fhir.rest.api.server.SystemRequestDetails;
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
import ca.uhn.fhir.rest.server.interceptor.partition.RequestTenantPartitionInterceptor;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;

View File

@ -3,7 +3,10 @@ package ca.uhn.fhir.jpa.mdm.svc;
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
import ca.uhn.fhir.jpa.entity.MdmLink;
import ca.uhn.fhir.jpa.mdm.BaseMdmR4Test;
import ca.uhn.fhir.jpa.mdm.config.BaseTestMdmConfig;
import ca.uhn.fhir.jpa.mdm.config.BlockListConfig;
import ca.uhn.fhir.jpa.mdm.helper.MdmLinkHelper;
import ca.uhn.fhir.jpa.mdm.helper.testmodels.MDMState;
import ca.uhn.fhir.jpa.model.dao.JpaPid;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.mdm.api.IMdmLink;
@ -31,14 +34,18 @@ import org.hl7.fhir.r4.model.Identifier;
import org.hl7.fhir.r4.model.Patient;
import org.hl7.fhir.r4.model.Practitioner;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
@ -61,8 +68,17 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.when;
import static org.slf4j.LoggerFactory.getLogger;
/**
* These tests use the rules defined in mdm-rules.json
* See {@link BaseTestMdmConfig}
*/
public class MdmMatchLinkSvcTest {
private static final Logger ourLog = getLogger(MdmMatchLinkSvcTest.class);
@Nested
public class NoBlockLinkTest extends BaseMdmR4Test {
@Autowired
@ -74,6 +90,9 @@ public class MdmMatchLinkSvcTest {
@Autowired
private IMdmLinkUpdaterSvc myMdmLinkUpdaterSvc;
@Autowired
private MdmLinkHelper myLinkHelper;
@Test
public void testAddPatientLinksToNewGoldenResourceIfNoneFound() {
createPatientAndUpdateLinks(buildJanePatient());
@ -98,6 +117,64 @@ public class MdmMatchLinkSvcTest {
assertLinksMatchVector((Long) null);
}
@Test
@RepeatedTest(20)
public void testUpdatingAResourceToMatchACurrentlyUnmatchedResource_resultsInUpdatedLinksForBoth() {
// setup
MDMState<Patient, JpaPid> state = new MDMState<>();
String startingState = """
GP1, AUTO, MATCH, P1
GP2, AUTO, MATCH, P2
""";
Map<String, Patient> idToResource = new HashMap<>();
// we're creating our patients manually,
// because we're testing mdm rules and how candidates are found
// so the patient info matters
Patient jane = buildJanePatient();
Long id;
{
Patient p = createPatient(jane);
idToResource.put("P1", p);
Long patientId = p.getIdElement().getIdPartAsLong();
state.addPID(patientId.toString(), JpaPid.fromIdAndResourceType(patientId, "Patient"));
}
{
Patient yui = buildJanePatient();
yui.setName(new ArrayList<>());
yui.addName()
.addGiven("Yui")
.setFamily("Hirasawa");
Patient retVal = createPatient(yui);
id = retVal.getIdElement().getIdPartAsLong();
idToResource.put("P2", retVal);
state.addPID(String.valueOf(id), JpaPid.fromIdAndResourceType(id, "Patient"));
}
// initialize our links
state.setInputState(startingState);
state.setParameterToValue(idToResource);
myLinkHelper.setup(state);
// test
Patient toUpdate = buildJanePatient();
toUpdate.setId("Patient/" + id.longValue());
updatePatientAndUpdateLinks(toUpdate);
// verify
String endState = """
GP1, AUTO, MATCH, P1
GP2, AUTO, POSSIBLE_MATCH, P2
GP1, AUTO, POSSIBLE_MATCH, P2
GP2, AUTO, POSSIBLE_DUPLICATE, GP1
""";
state.setParameterToValue(idToResource);
state.setOutputState(endState);
myLinkHelper.validateResults(state);
myLinkHelper.logMdmLinks();
}
@Test
public void testAddPatientLinksToNewlyCreatedResourceIfNoMatch() {
Patient patient1 = createPatientAndUpdateLinks(buildJanePatient());

View File

@ -4,8 +4,8 @@ import ca.uhn.fhir.interceptor.model.RequestPartitionId;
import ca.uhn.fhir.jpa.entity.PartitionEntity;
import ca.uhn.fhir.jpa.mdm.BaseMdmR4Test;
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
import ca.uhn.fhir.rest.api.server.SystemRequestDetails;
import ca.uhn.fhir.mdm.util.MdmResourceUtil;
import ca.uhn.fhir.rest.api.server.SystemRequestDetails;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.r4.model.Patient;
import org.junit.jupiter.api.AfterEach;

View File

@ -0,0 +1,121 @@
package ca.uhn.fhir.jpa.mdm.svc.candidate;
import ca.uhn.fhir.mdm.api.MdmMatchOutcome;
import ca.uhn.fhir.rest.api.server.storage.IResourcePersistentId;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import java.util.ArrayList;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock;
public class CandidateListTest {
private List<MatchedGoldenResourceCandidate> getCandidatesList(int theSize) {
List<MatchedGoldenResourceCandidate> candidatesToAdd = new ArrayList<>();
for (int i = 0; i < theSize; i++) {
MatchedGoldenResourceCandidate candidate = new MatchedGoldenResourceCandidate(
mock(IResourcePersistentId.class),
MdmMatchOutcome.POSSIBLE_MATCH
);
candidatesToAdd.add(candidate);
}
return candidatesToAdd;
}
@ParameterizedTest
@EnumSource(CandidateStrategyEnum.class)
public void addAll_withVariousStrategies_behaviourTest(CandidateStrategyEnum theStrategyEnum) {
// setup
int total = 3;
List<MatchedGoldenResourceCandidate> candidatesToAdd = getCandidatesList(total);
// test
CandidateList list = new CandidateList(theStrategyEnum);
// verify
if (theStrategyEnum == CandidateStrategyEnum.ANY) {
assertThrows(InternalErrorException.class, () -> {
list.addAll(theStrategyEnum, candidatesToAdd);
});
} else {
list.addAll(theStrategyEnum, candidatesToAdd);
assertEquals(total, list.size());
}
}
@ParameterizedTest
@EnumSource(CandidateStrategyEnum.class)
public void stream_forVariousStrategies_returnsJointStream(CandidateStrategyEnum theStrategy) {
// setup
int size = 3;
CandidateList candidateList = new CandidateList(theStrategy);
// we need some values first
size = populateCandidateList(theStrategy, size, candidateList);
// test
assertEquals(size, candidateList.stream().count());
}
private int populateCandidateList(CandidateStrategyEnum theStrategy, int theSize, CandidateList theCandidateList) {
if (theStrategy == CandidateStrategyEnum.ANY) {
int realTotal = 0;
for (CandidateStrategyEnum strat : CandidateStrategyEnum.values()) {
if (strat == theStrategy) {
continue;
}
theCandidateList.addAll(strat, getCandidatesList(theSize));
realTotal += theSize;
}
theSize = realTotal;
} else {
theCandidateList.addAll(theStrategy, getCandidatesList(theSize));
}
return theSize;
}
@ParameterizedTest
@EnumSource(CandidateStrategyEnum.class)
public void singleElement_CandidateList_Tests(CandidateStrategyEnum theStrategy) {
// setup
CandidateList candidate = new CandidateList(theStrategy);
if (theStrategy == CandidateStrategyEnum.ANY) {
candidate.addAll(CandidateStrategyEnum.LINK, getCandidatesList(1));
} else {
candidate.addAll(theStrategy, getCandidatesList(1));
}
// tests
assertFalse(candidate.isEmpty());
assertTrue(candidate.exactlyOneMatch());
assertEquals(1, candidate.size());
assertNotNull(candidate.getFirstMatch());
assertNotNull(candidate.getOnlyMatch());
}
@ParameterizedTest
@EnumSource(CandidateStrategyEnum.class)
public void getCandidates_variousStrategies_returnsExpectedResults(CandidateStrategyEnum theStrategy) {
// setup
CandidateList candidateList = new CandidateList(theStrategy);
int size = populateCandidateList(theStrategy, 10, candidateList);
// tests
assertEquals(size, candidateList.size());
List<MatchedGoldenResourceCandidate> candidates = candidateList.getCandidates();
assertEquals(size, candidates.size());
}
}

View File

@ -4,9 +4,12 @@ import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome;
import ca.uhn.fhir.jpa.entity.MdmLink;
import ca.uhn.fhir.jpa.mdm.BaseMdmR4Test;
import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc;
import ca.uhn.fhir.jpa.mdm.models.FindGoldenResourceCandidatesParams;
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
import ca.uhn.fhir.mdm.model.MdmTransactionContext;
import ca.uhn.fhir.rest.api.server.SystemRequestDetails;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.r4.model.Patient;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@ -49,7 +52,8 @@ class MdmGoldenResourceFindingSvcIT extends BaseMdmR4Test {
myMdmLinkDaoSvc.save(link);
// the NO_MATCH golden resource should not be a candidate
CandidateList candidateList = myMdmGoldenResourceFindingSvc.findGoldenResourceCandidates(jane);
CandidateList candidateList = myMdmGoldenResourceFindingSvc.findGoldenResourceCandidates(
createFindGoldenResourceCandidateParams(jane));
assertEquals(0, candidateList.size());
}
@ -131,7 +135,8 @@ class MdmGoldenResourceFindingSvcIT extends BaseMdmR4Test {
}
// test
CandidateList candidateList = myMdmGoldenResourceFindingSvc.findGoldenResourceCandidates(candidate);
CandidateList candidateList = myMdmGoldenResourceFindingSvc.findGoldenResourceCandidates(
createFindGoldenResourceCandidateParams(candidate));
// verify
assertNotNull(candidateList);
@ -154,4 +159,12 @@ class MdmGoldenResourceFindingSvcIT extends BaseMdmR4Test {
return (Patient) daoOutcome.getResource();
}
private FindGoldenResourceCandidatesParams createFindGoldenResourceCandidateParams(IAnyResource theResource) {
FindGoldenResourceCandidatesParams params = new FindGoldenResourceCandidatesParams(
theResource,
new MdmTransactionContext()
);
return params;
}
}

View File

@ -19,6 +19,7 @@
*/
package ca.uhn.fhir.jpa.test;
import ca.uhn.fhir.batch2.jobs.export.BulkDataExportProvider;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.support.IValidationSupport;
import ca.uhn.fhir.interceptor.api.IInterceptorService;
@ -37,7 +38,6 @@ import ca.uhn.fhir.jpa.api.svc.ISearchCoordinatorSvc;
import ca.uhn.fhir.jpa.binary.interceptor.BinaryStorageInterceptor;
import ca.uhn.fhir.jpa.binary.provider.BinaryAccessProvider;
import ca.uhn.fhir.jpa.bulk.export.api.IBulkDataExportJobSchedulingHelper;
import ca.uhn.fhir.batch2.jobs.export.BulkDataExportProvider;
import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
import ca.uhn.fhir.jpa.dao.data.IForcedIdDao;
import ca.uhn.fhir.jpa.dao.data.IMdmLinkJpaRepository;

View File

@ -260,7 +260,7 @@ public abstract class BaseJpaTest extends BaseTest {
private IForcedIdDao myForcedIdDao;
@Autowired
private DaoRegistry myDaoRegistry;
private List<Object> myRegisteredInterceptors = new ArrayList<>(1);
private final List<Object> myRegisteredInterceptors = new ArrayList<>(1);
@SuppressWarnings("BusyWait")
public static void waitForSize(int theTarget, List<?> theList) {