2878 mdm mongo support (#3748)
* small refactor * refactored MDM module to use iterface IMDMLink, refactored MDMLink to use ResourcePersistenceId wrapper rather than pid as long * removing IJpaIdHelperService and refactor IIdHelperService * fixed bugs for GoldenResourceMergerSvcImpl and FindCandidateByExampleSvc * changes to IIdHelperService * move MdmSearchParamSvc and MdmSubmitSvcImpl out of jpaserver-mdm * moved JpaResourceLoader to hapi-fhir-storage, renamed to ResourceLoaderImpl * added error Msg code, removed Fixme * fixed error code, update last used code in Msg.java to 2083 * fixed accidentally throwing unprocessableentityException * added MdmLinkExpandSvc interface * build adding license to files * MdmLinkdao refactor * fix build * mdm config refactoring * MdmStorageInterceptor and IExpungeEverythingService changes * fix bug where a pid is converted to ResourcePersistenceId twice * minor refactor to IMdmLink, change id from long to ResourcePersistenceId * changed PageImpl to Page interface * refactor MdmSearchExpandingInterceptor to use interface * fixed missed refactor where the resourcePersistenceId is still assumed to be long * resolve test failures resulting from merging master * changed conflicting exception code * fixed issue with bulk export wrapping resourcePid inside resourcePersistenceId * added IMdmLinkImpl to MdmSettings * fixed missing import in IdHelperService from merging master * fixed MdmLinkDaoSvcTest importing wrong MdmLinkTuple * restored JpaIdHelperService and added changelog * modified msg.code to non-duplicate * code review changes * refactored some bulk export batch 2 files to accomodate change in beans being exported * fixed jpa bulk export failing tests * removed duplicate bean declaration of MdmLinkImplFactory in BaseMdmR4Test * merged master and bump version to pre25 * extracted expungeEverythingByType to IExpungeEverythingService * fixed wiring issue * messed up merging pom with master * fixed broken changelog Co-authored-by: Long Ma <long@smilecdr.com> Co-authored-by: Samuel Lee <samuel.lee@smilecdr.com> Co-authored-by: Ken Stevens <ken@smilecdr.com>
This commit is contained in:
parent
8346c0263b
commit
f933ff3d9c
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>6.1.0-PRE24-SNAPSHOT</version>
|
||||
<version>6.1.0-PRE25-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.1.0-PRE24-SNAPSHOT</version>
|
||||
<version>6.1.0-PRE25-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.1.0-PRE24-SNAPSHOT</version>
|
||||
<version>6.1.0-PRE25-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ public final class Msg {
|
|||
|
||||
/**
|
||||
* IMPORTANT: Please update the following comment after you add a new code
|
||||
* Last code value: 2106
|
||||
* Last code value: 2109
|
||||
*/
|
||||
|
||||
private Msg() {}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.1.0-PRE24-SNAPSHOT</version>
|
||||
<version>6.1.0-PRE25-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-bom</artifactId>
|
||||
<version>6.1.0-PRE24-SNAPSHOT</version>
|
||||
<version>6.1.0-PRE25-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>HAPI FHIR BOM</name>
|
||||
|
||||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.1.0-PRE24-SNAPSHOT</version>
|
||||
<version>6.1.0-PRE25-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>6.1.0-PRE24-SNAPSHOT</version>
|
||||
<version>6.1.0-PRE25-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.1.0-PRE24-SNAPSHOT</version>
|
||||
<version>6.1.0-PRE25-SNAPSHOT</version>
|
||||
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-cli</artifactId>
|
||||
<version>6.1.0-PRE24-SNAPSHOT</version>
|
||||
<version>6.1.0-PRE25-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.1.0-PRE24-SNAPSHOT</version>
|
||||
<version>6.1.0-PRE25-SNAPSHOT</version>
|
||||
<relativePath>../../hapi-deployable-pom</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>6.1.0-PRE24-SNAPSHOT</version>
|
||||
<version>6.1.0-PRE25-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.1.0-PRE24-SNAPSHOT</version>
|
||||
<version>6.1.0-PRE25-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.1.0-PRE24-SNAPSHOT</version>
|
||||
<version>6.1.0-PRE25-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.1.0-PRE24-SNAPSHOT</version>
|
||||
<version>6.1.0-PRE25-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>6.1.0-PRE24-SNAPSHOT</version>
|
||||
<version>6.1.0-PRE25-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.1.0-PRE24-SNAPSHOT</version>
|
||||
<version>6.1.0-PRE25-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
type: add
|
||||
issue: 2878
|
||||
title: "Refactored mdm classes to use ResourcePersistenceId rather than prematurely converting to longs"
|
|
@ -11,7 +11,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.1.0-PRE24-SNAPSHOT</version>
|
||||
<version>6.1.0-PRE25-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.1.0-PRE24-SNAPSHOT</version>
|
||||
<version>6.1.0-PRE25-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.1.0-PRE24-SNAPSHOT</version>
|
||||
<version>6.1.0-PRE25-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.1.0-PRE24-SNAPSHOT</version>
|
||||
<version>6.1.0-PRE25-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -29,13 +29,13 @@ import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
|||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.api.model.PersistentIdToForcedIdMap;
|
||||
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
||||
import ca.uhn.fhir.jpa.bulk.export.api.IBulkExportProcessor;
|
||||
import ca.uhn.fhir.jpa.bulk.export.model.ExportPIDIteratorParameters;
|
||||
import ca.uhn.fhir.jpa.dao.IResultIterator;
|
||||
import ca.uhn.fhir.jpa.dao.ISearchBuilder;
|
||||
import ca.uhn.fhir.jpa.dao.SearchBuilderFactory;
|
||||
import ca.uhn.fhir.jpa.dao.data.IMdmLinkDao;
|
||||
import ca.uhn.fhir.jpa.dao.index.IJpaIdHelperService;
|
||||
import ca.uhn.fhir.jpa.dao.mdm.MdmExpansionCacheSvc;
|
||||
import ca.uhn.fhir.jpa.model.search.SearchRuntimeDetails;
|
||||
|
@ -43,6 +43,8 @@ import ca.uhn.fhir.jpa.partition.SystemRequestDetails;
|
|||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.util.QueryChunker;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||
import ca.uhn.fhir.mdm.dao.IMdmLinkDao;
|
||||
import ca.uhn.fhir.mdm.model.MdmPidTuple;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.api.server.bulk.BulkDataExportOptions;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
|
@ -101,9 +103,6 @@ public class JpaBulkExportProcessor implements IBulkExportProcessor {
|
|||
@Autowired
|
||||
private IMdmLinkDao myMdmLinkDao;
|
||||
|
||||
@Autowired
|
||||
private IJpaIdHelperService myJpaIdHelperService;
|
||||
|
||||
@Autowired
|
||||
private MdmExpansionCacheSvc myMdmExpansionCacheSvc;
|
||||
|
||||
|
@ -259,25 +258,23 @@ public class JpaBulkExportProcessor implements IBulkExportProcessor {
|
|||
private Iterator<ResourcePersistentId> getExpandedPatientIterator(ExportPIDIteratorParameters theParameters) {
|
||||
List<String> members = getMembers(theParameters.getGroupId());
|
||||
List<IIdType> ids = members.stream().map(member -> new IdDt("Patient/" + member)).collect(Collectors.toList());
|
||||
List<Long> pidsOrThrowException = myJpaIdHelperService.getPidsOrThrowException(ids);
|
||||
Set<Long> patientPidsToExport = new HashSet<>(pidsOrThrowException);
|
||||
|
||||
// Are bulk exports partition aware or care about partition at all? This does
|
||||
List<ResourcePersistentId> pidsOrThrowException = myIdHelperService.getPidsOrThrowException(RequestPartitionId.allPartitions(), ids);
|
||||
Set<ResourcePersistentId> patientPidsToExport = new HashSet<>(pidsOrThrowException);
|
||||
|
||||
if (theParameters.isExpandMdm()) {
|
||||
SystemRequestDetails srd = SystemRequestDetails.newSystemRequestAllPartitions();
|
||||
IBaseResource group = myDaoRegistry.getResourceDao("Group").read(new IdDt(theParameters.getGroupId()), srd);
|
||||
Long pidOrNull = myJpaIdHelperService.getPidOrNull(group);
|
||||
List<IMdmLinkDao.MdmPidTuple> goldenPidSourcePidTuple = myMdmLinkDao.expandPidsFromGroupPidGivenMatchResult(pidOrNull, MdmMatchResultEnum.MATCH);
|
||||
ResourcePersistentId pidOrNull = myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), group);
|
||||
List<MdmPidTuple> goldenPidSourcePidTuple = myMdmLinkDao.expandPidsFromGroupPidGivenMatchResult(pidOrNull, MdmMatchResultEnum.MATCH);
|
||||
goldenPidSourcePidTuple.forEach(tuple -> {
|
||||
patientPidsToExport.add(tuple.getGoldenPid());
|
||||
patientPidsToExport.add(tuple.getSourcePid());
|
||||
});
|
||||
populateMdmResourceCache(goldenPidSourcePidTuple);
|
||||
}
|
||||
List<ResourcePersistentId> resourcePersistentIds = patientPidsToExport
|
||||
.stream()
|
||||
.map(ResourcePersistentId::new)
|
||||
.collect(Collectors.toList());
|
||||
return resourcePersistentIds.iterator();
|
||||
return patientPidsToExport.iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -295,7 +292,7 @@ public class JpaBulkExportProcessor implements IBulkExportProcessor {
|
|||
/**
|
||||
* @param thePidTuples
|
||||
*/
|
||||
private void populateMdmResourceCache(List<IMdmLinkDao.MdmPidTuple> thePidTuples) {
|
||||
private void populateMdmResourceCache(List<MdmPidTuple> thePidTuples) {
|
||||
if (myMdmExpansionCacheSvc.hasBeenPopulated()) {
|
||||
return;
|
||||
}
|
||||
|
@ -304,7 +301,7 @@ public class JpaBulkExportProcessor implements IBulkExportProcessor {
|
|||
// patient/gold-1 -> [patient/1, patient/2]
|
||||
// patient/gold-2 -> [patient/3, patient/4]
|
||||
//}
|
||||
Map<Long, Set<Long>> goldenResourceToSourcePidMap = new HashMap<>();
|
||||
Map<ResourcePersistentId, Set<ResourcePersistentId>> goldenResourceToSourcePidMap = new HashMap<>();
|
||||
extract(thePidTuples, goldenResourceToSourcePidMap);
|
||||
|
||||
//Next, lets convert it to an inverted index for fast lookup
|
||||
|
@ -317,11 +314,9 @@ public class JpaBulkExportProcessor implements IBulkExportProcessor {
|
|||
Map<String, String> sourceResourceIdToGoldenResourceIdMap = new HashMap<>();
|
||||
goldenResourceToSourcePidMap.forEach((key, value) -> {
|
||||
String goldenResourceId = myIdHelperService.translatePidIdToForcedIdWithCache(new ResourcePersistentId(key)).orElse(key.toString());
|
||||
Map<Long, Optional<String>> pidsToForcedIds = myIdHelperService.translatePidsToForcedIds(value);
|
||||
PersistentIdToForcedIdMap pidsToForcedIds = myIdHelperService.translatePidsToForcedIds(value);
|
||||
|
||||
Set<String> sourceResourceIds = pidsToForcedIds.entrySet().stream()
|
||||
.map(ent -> ent.getValue().isPresent() ? ent.getValue().get() : ent.getKey().toString())
|
||||
.collect(Collectors.toSet());
|
||||
Set<String> sourceResourceIds = pidsToForcedIds.getResolvedResourceIds();
|
||||
|
||||
sourceResourceIds
|
||||
.forEach(sourceResourceId -> sourceResourceIdToGoldenResourceIdMap.put(sourceResourceId, goldenResourceId));
|
||||
|
@ -331,10 +326,10 @@ public class JpaBulkExportProcessor implements IBulkExportProcessor {
|
|||
myMdmExpansionCacheSvc.setCacheContents(sourceResourceIdToGoldenResourceIdMap);
|
||||
}
|
||||
|
||||
private void extract(List<IMdmLinkDao.MdmPidTuple> theGoldenPidTargetPidTuples, Map<Long, Set<Long>> theGoldenResourceToSourcePidMap) {
|
||||
for (IMdmLinkDao.MdmPidTuple goldenPidTargetPidTuple : theGoldenPidTargetPidTuples) {
|
||||
Long goldenPid = goldenPidTargetPidTuple.getGoldenPid();
|
||||
Long sourcePid = goldenPidTargetPidTuple.getSourcePid();
|
||||
private void extract(List<MdmPidTuple> theGoldenPidTargetPidTuples, Map<ResourcePersistentId, Set<ResourcePersistentId>> theGoldenResourceToSourcePidMap) {
|
||||
for (MdmPidTuple goldenPidTargetPidTuple : theGoldenPidTargetPidTuples) {
|
||||
ResourcePersistentId goldenPid = goldenPidTargetPidTuple.getGoldenPid();
|
||||
ResourcePersistentId sourcePid = goldenPidTargetPidTuple.getSourcePid();
|
||||
theGoldenResourceToSourcePidMap.computeIfAbsent(goldenPid, key -> new HashSet<>()).add(sourcePid);
|
||||
}
|
||||
}
|
||||
|
@ -416,28 +411,25 @@ public class JpaBulkExportProcessor implements IBulkExportProcessor {
|
|||
Set<String> expandedIds = new HashSet<>();
|
||||
SystemRequestDetails requestDetails = SystemRequestDetails.newSystemRequestAllPartitions();
|
||||
IBaseResource group = myDaoRegistry.getResourceDao("Group").read(new IdDt(theParams.getGroupId()), requestDetails);
|
||||
Long pidOrNull = myJpaIdHelperService.getPidOrNull(group);
|
||||
ResourcePersistentId pidOrNull = myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), group);
|
||||
|
||||
//Attempt to perform MDM Expansion of membership
|
||||
if (theParams.isExpandMdm()) {
|
||||
List<IMdmLinkDao.MdmPidTuple> goldenPidTargetPidTuples = myMdmLinkDao.expandPidsFromGroupPidGivenMatchResult(pidOrNull, MdmMatchResultEnum.MATCH);
|
||||
List<MdmPidTuple> goldenPidTargetPidTuples = myMdmLinkDao.expandPidsFromGroupPidGivenMatchResult(pidOrNull, MdmMatchResultEnum.MATCH);
|
||||
//Now lets translate these pids into resource IDs
|
||||
Set<Long> uniquePids = new HashSet<>();
|
||||
Set<ResourcePersistentId> uniquePids = new HashSet<>();
|
||||
goldenPidTargetPidTuples.forEach(tuple -> {
|
||||
uniquePids.add(tuple.getGoldenPid());
|
||||
uniquePids.add(tuple.getSourcePid());
|
||||
});
|
||||
Map<Long, Optional<String>> pidToForcedIdMap = myIdHelperService.translatePidsToForcedIds(uniquePids);
|
||||
PersistentIdToForcedIdMap pidToForcedIdMap = myIdHelperService.translatePidsToForcedIds(uniquePids);
|
||||
|
||||
Map<Long, Set<Long>> goldenResourceToSourcePidMap = new HashMap<>();
|
||||
Map<ResourcePersistentId, Set<ResourcePersistentId>> goldenResourceToSourcePidMap = new HashMap<>();
|
||||
extract(goldenPidTargetPidTuples, goldenResourceToSourcePidMap);
|
||||
populateMdmResourceCache(goldenPidTargetPidTuples);
|
||||
|
||||
//If the result of the translation is an empty optional, it means there is no forced id, and we can use the PID as the resource ID.
|
||||
Set<String> resolvedResourceIds = pidToForcedIdMap.entrySet().stream()
|
||||
.map(entry -> entry.getValue().isPresent() ? entry.getValue().get() : entry.getKey().toString())
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
Set<String> resolvedResourceIds = pidToForcedIdMap.getResolvedResourceIds();
|
||||
expandedIds.addAll(resolvedResourceIds);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ package ca.uhn.fhir.jpa.config;
|
|||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.api.svc.IBatch2DaoSvc;
|
||||
import ca.uhn.fhir.jpa.api.svc.IDeleteExpungeSvc;
|
||||
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceLinkDao;
|
||||
import ca.uhn.fhir.jpa.dao.expunge.ResourceTableFKProvider;
|
||||
import ca.uhn.fhir.jpa.dao.index.IJpaIdHelperService;
|
||||
|
@ -46,7 +47,7 @@ public class Batch2SupportConfig {
|
|||
}
|
||||
|
||||
@Bean
|
||||
DeleteExpungeSqlBuilder deleteExpungeSqlBuilder(ResourceTableFKProvider theResourceTableFKProvider, DaoConfig theDaoConfig, IJpaIdHelperService theIdHelper, IResourceLinkDao theResourceLinkDao) {
|
||||
DeleteExpungeSqlBuilder deleteExpungeSqlBuilder(ResourceTableFKProvider theResourceTableFKProvider, DaoConfig theDaoConfig, IIdHelperService theIdHelper, IResourceLinkDao theResourceLinkDao) {
|
||||
return new DeleteExpungeSqlBuilder(theResourceTableFKProvider, theDaoConfig, theIdHelper, theResourceLinkDao);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ import ca.uhn.fhir.jpa.config.util.ResourceCountCacheUtil;
|
|||
import ca.uhn.fhir.jpa.config.util.ValidationSupportConfigUtil;
|
||||
import ca.uhn.fhir.jpa.dao.FulltextSearchSvcImpl;
|
||||
import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
|
||||
import ca.uhn.fhir.jpa.dao.mdm.MdmLinkDaoJpaImpl;
|
||||
import ca.uhn.fhir.jpa.dao.search.HSearchSortHelperImpl;
|
||||
import ca.uhn.fhir.jpa.dao.search.IHSearchSortHelper;
|
||||
import ca.uhn.fhir.jpa.provider.DaoRegistryResourceSupportedSvc;
|
||||
|
@ -35,6 +36,7 @@ import ca.uhn.fhir.jpa.search.IStaleSearchDeletingSvc;
|
|||
import ca.uhn.fhir.jpa.search.StaleSearchDeletingSvcImpl;
|
||||
import ca.uhn.fhir.jpa.util.ResourceCountCache;
|
||||
import ca.uhn.fhir.jpa.validation.JpaValidationSupportChain;
|
||||
import ca.uhn.fhir.mdm.dao.IMdmLinkDao;
|
||||
import ca.uhn.fhir.rest.api.IResourceSupportedSvc;
|
||||
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
|
||||
import org.hl7.fhir.common.hapi.validation.support.CachingValidationSupport;
|
||||
|
@ -92,4 +94,9 @@ public class HapiJpaConfig {
|
|||
public ResourceCountCache resourceCountsCache(IFhirSystemDao<?, ?> theSystemDao) {
|
||||
return ResourceCountCacheUtil.newResourceCountCache(theSystemDao);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public static IMdmLinkDao mdmLinkDao(){
|
||||
return new MdmLinkDaoJpaImpl();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
|||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.jpa.api.dao.IDao;
|
||||
import ca.uhn.fhir.jpa.api.model.ExpungeOptions;
|
||||
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
||||
import ca.uhn.fhir.jpa.api.svc.ISearchCoordinatorSvc;
|
||||
import ca.uhn.fhir.jpa.batch.BatchJobsConfig;
|
||||
import ca.uhn.fhir.jpa.batch.config.BatchConstants;
|
||||
|
@ -39,10 +40,8 @@ import ca.uhn.fhir.jpa.dao.expunge.ResourceExpungeService;
|
|||
import ca.uhn.fhir.jpa.dao.expunge.ResourceTableFKProvider;
|
||||
import ca.uhn.fhir.jpa.dao.index.DaoResourceLinkResolver;
|
||||
import ca.uhn.fhir.jpa.dao.index.DaoSearchParamSynchronizer;
|
||||
import ca.uhn.fhir.jpa.dao.index.IJpaIdHelperService;
|
||||
import ca.uhn.fhir.jpa.dao.index.JpaIdHelperService;
|
||||
import ca.uhn.fhir.jpa.dao.index.IdHelperService;
|
||||
import ca.uhn.fhir.jpa.dao.index.SearchParamWithInlineReferencesExtractor;
|
||||
import ca.uhn.fhir.jpa.dao.mdm.MdmLinkExpandSvc;
|
||||
import ca.uhn.fhir.jpa.dao.tx.HapiTransactionService;
|
||||
import ca.uhn.fhir.jpa.delete.DeleteConflictFinderService;
|
||||
import ca.uhn.fhir.jpa.delete.DeleteConflictService;
|
||||
|
@ -122,8 +121,9 @@ import ca.uhn.fhir.jpa.term.api.ITermConceptMappingSvc;
|
|||
import ca.uhn.fhir.jpa.term.api.ITermDeferredStorageSvc;
|
||||
import ca.uhn.fhir.jpa.term.config.TermCodeSystemConfig;
|
||||
import ca.uhn.fhir.jpa.util.MemoryCacheService;
|
||||
import ca.uhn.fhir.jpa.validation.JpaResourceLoader;
|
||||
import ca.uhn.fhir.jpa.validation.ResourceLoaderImpl;
|
||||
import ca.uhn.fhir.jpa.validation.ValidationSettings;
|
||||
import ca.uhn.fhir.mdm.svc.MdmLinkExpandSvc;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.api.server.storage.IDeleteExpungeJobSubmitter;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
|
@ -137,6 +137,7 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
|
|||
import org.hl7.fhir.utilities.graphql.IGraphQLStorageServices;
|
||||
import org.hl7.fhir.utilities.npm.PackageClient;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
@ -617,7 +618,7 @@ public class JpaConfig {
|
|||
return new SearchQueryExecutor(theGeneratedSql, theMaxResultsToFetch);
|
||||
}
|
||||
|
||||
@Bean(name = SEARCH_BUILDER)
|
||||
@Bean(name = ISearchBuilder.SEARCH_BUILDER_BEAN_NAME)
|
||||
@Scope("prototype")
|
||||
public ISearchBuilder newSearchBuilder(IDao theDao, String theResourceName, Class<? extends IBaseResource> theResourceType, DaoConfig theDaoConfig) {
|
||||
return new SearchBuilder(theDao, theResourceName, theResourceType);
|
||||
|
@ -636,8 +637,8 @@ public class JpaConfig {
|
|||
}
|
||||
|
||||
@Bean
|
||||
public IJpaIdHelperService jpaIdHelperService() {
|
||||
return new JpaIdHelperService();
|
||||
public IIdHelperService idHelperService () {
|
||||
return new IdHelperService();
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
@ -717,8 +718,8 @@ public class JpaConfig {
|
|||
}
|
||||
|
||||
@Bean
|
||||
public JpaResourceLoader jpaResourceLoader() {
|
||||
return new JpaResourceLoader();
|
||||
public ResourceLoaderImpl jpaResourceLoader() {
|
||||
return new ResourceLoaderImpl();
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
|
|
@ -24,9 +24,11 @@ import ca.uhn.fhir.context.FhirContext;
|
|||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.api.model.PersistentIdToForcedIdMap;
|
||||
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import com.google.common.collect.ImmutableListMultimap;
|
||||
import com.google.common.collect.Multimaps;
|
||||
|
@ -47,8 +49,9 @@ import javax.persistence.criteria.Root;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static ca.uhn.fhir.jpa.search.builder.SearchBuilder.toPredicateArray;
|
||||
|
||||
|
@ -121,15 +124,16 @@ public class HistoryBuilder {
|
|||
List<ResourceHistoryTable> tables = query.getResultList();
|
||||
if (tables.size() > 0) {
|
||||
ImmutableListMultimap<Long, ResourceHistoryTable> resourceIdToHistoryEntries = Multimaps.index(tables, ResourceHistoryTable::getResourceId);
|
||||
|
||||
Map<Long, Optional<String>> pidToForcedId = myIdHelperService.translatePidsToForcedIds(resourceIdToHistoryEntries.keySet());
|
||||
ourLog.trace("Translated IDs: {}", pidToForcedId);
|
||||
Set<ResourcePersistentId> pids = resourceIdToHistoryEntries.keySet().stream().map(t-> new ResourcePersistentId(t)).collect(Collectors.toSet());
|
||||
PersistentIdToForcedIdMap pidToForcedId = myIdHelperService.translatePidsToForcedIds(pids);
|
||||
ourLog.trace("Translated IDs: {}", pidToForcedId.getResourcePersistentIdOptionalMap());
|
||||
|
||||
for (Long nextResourceId : resourceIdToHistoryEntries.keySet()) {
|
||||
List<ResourceHistoryTable> historyTables = resourceIdToHistoryEntries.get(nextResourceId);
|
||||
|
||||
String resourceId;
|
||||
Optional<String> forcedId = pidToForcedId.get(nextResourceId);
|
||||
|
||||
Optional<String> forcedId = pidToForcedId.get(new ResourcePersistentId(nextResourceId));
|
||||
if (forcedId.isPresent()) {
|
||||
resourceId = forcedId.get();
|
||||
} else {
|
||||
|
|
|
@ -34,7 +34,7 @@ import java.util.List;
|
|||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public interface IMdmLinkDao extends JpaRepository<MdmLink, Long>, IHapiFhirJpaRepository {
|
||||
public interface IMdmLinkJpaRepository extends JpaRepository<MdmLink, Long>, IHapiFhirJpaRepository {
|
||||
@Modifying
|
||||
@Query("DELETE FROM MdmLink f WHERE myGoldenResourcePid = :pid OR mySourcePid = :pid")
|
||||
int deleteWithAnyReferenceToPid(@Param("pid") Long thePid);
|
|
@ -51,11 +51,11 @@ public class FhirResourceDaoQuestionnaireResponseDstu3 extends BaseHapiFhirResou
|
|||
// }
|
||||
// }
|
||||
//
|
||||
// public class JpaResourceLoader implements IResourceLoader {
|
||||
// public class ResourceLoaderImpl implements IResourceLoader {
|
||||
//
|
||||
// private RequestDetails myRequestDetails;
|
||||
//
|
||||
// public JpaResourceLoader(RequestDetails theRequestDetails) {
|
||||
// public ResourceLoaderImpl(RequestDetails theRequestDetails) {
|
||||
// super();
|
||||
// myRequestDetails = theRequestDetails;
|
||||
// }
|
||||
|
|
|
@ -27,6 +27,7 @@ import ca.uhn.fhir.jpa.entity.Batch2JobInstanceEntity;
|
|||
import ca.uhn.fhir.jpa.entity.Batch2WorkChunkEntity;
|
||||
import ca.uhn.fhir.jpa.entity.BulkImportJobEntity;
|
||||
import ca.uhn.fhir.jpa.entity.BulkImportJobFileEntity;
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.jpa.entity.PartitionEntity;
|
||||
import ca.uhn.fhir.jpa.entity.Search;
|
||||
import ca.uhn.fhir.jpa.entity.SearchInclude;
|
||||
|
@ -236,12 +237,18 @@ public class ExpungeEverythingService implements IExpungeEverythingService {
|
|||
return outcome;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int expungeEverythingByType(Class<?> theEntityType) {
|
||||
int result = expungeEverythingByTypeWithoutPurging(theEntityType);
|
||||
purgeAllCaches();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int expungeEverythingMdmLinks() {
|
||||
return expungeEverythingByType(MdmLink.class);
|
||||
}
|
||||
|
||||
private int doExpungeEverythingQuery(String theQuery) {
|
||||
StopWatch sw = new StopWatch();
|
||||
int outcome = myEntityManager.createQuery(theQuery).executeUpdate();
|
||||
|
|
|
@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.dao.index;
|
|||
*/
|
||||
|
||||
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
|
@ -76,7 +77,7 @@ public interface IJpaIdHelperService extends IIdHelperService {
|
|||
Long getPidOrThrowException(IIdType theId);
|
||||
|
||||
@Nonnull
|
||||
Long getPidOrThrowException(@Nonnull IAnyResource theResource);
|
||||
ResourcePersistentId getPidOrThrowException(@Nonnull IAnyResource theResource);
|
||||
|
||||
IIdType resourceIdFromPidOrThrowException(Long thePid);
|
||||
|
||||
|
@ -91,6 +92,6 @@ public interface IJpaIdHelperService extends IIdHelperService {
|
|||
* @param thePids The Set of pids you would like to resolve to external FHIR Resource IDs.
|
||||
* @return A Set of strings representing the FHIR IDs of the pids.
|
||||
*/
|
||||
Set<String> translatePidsToFhirResourceIds(Set<Long> thePids);
|
||||
Set<String> translatePidsToFhirResourceIds(Set<ResourcePersistentId> thePids);
|
||||
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import ca.uhn.fhir.context.FhirContext;
|
|||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.api.model.PersistentIdToForcedIdMap;
|
||||
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
||||
import ca.uhn.fhir.jpa.dao.data.IForcedIdDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceTableDao;
|
||||
|
@ -31,6 +32,7 @@ import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
|||
import ca.uhn.fhir.jpa.model.cross.IResourceLookup;
|
||||
import ca.uhn.fhir.jpa.model.cross.ResourceLookup;
|
||||
import ca.uhn.fhir.jpa.model.entity.ForcedId;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.search.builder.SearchBuilder;
|
||||
import ca.uhn.fhir.jpa.util.MemoryCacheService;
|
||||
import ca.uhn.fhir.jpa.util.QueryChunker;
|
||||
|
@ -44,6 +46,8 @@ import com.google.common.collect.ListMultimap;
|
|||
import com.google.common.collect.MultimapBuilder;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.r4.model.IdType;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -589,9 +593,9 @@ public class IdHelperService implements IIdHelperService {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Map<Long, Optional<String>> translatePidsToForcedIds(Set<Long> thePids) {
|
||||
public PersistentIdToForcedIdMap translatePidsToForcedIds(Set<ResourcePersistentId> theResourceIds) {
|
||||
assert myDontCheckActiveTransactionForUnitTest || TransactionSynchronizationManager.isSynchronizationActive();
|
||||
|
||||
Set<Long> thePids = theResourceIds.stream().map(t -> t.getIdAsLong()).collect(Collectors.toSet());
|
||||
Map<Long, Optional<String>> retVal = new HashMap<>(myMemoryCacheService.getAllPresent(MemoryCacheService.CacheEnum.PID_TO_FORCED_ID, thePids));
|
||||
|
||||
List<Long> remainingPids = thePids
|
||||
|
@ -618,8 +622,13 @@ public class IdHelperService implements IIdHelperService {
|
|||
retVal.put(nextResourcePid, Optional.empty());
|
||||
myMemoryCacheService.putAfterCommit(MemoryCacheService.CacheEnum.PID_TO_FORCED_ID, nextResourcePid, Optional.empty());
|
||||
}
|
||||
|
||||
return retVal;
|
||||
Map<ResourcePersistentId, Optional<String>> convertRetVal = new HashMap<>();
|
||||
retVal.forEach(
|
||||
(k, v) -> {
|
||||
convertRetVal.put(new ResourcePersistentId(k), v);
|
||||
}
|
||||
);
|
||||
return new PersistentIdToForcedIdMap(convertRetVal);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -664,4 +673,73 @@ public class IdHelperService implements IIdHelperService {
|
|||
public static boolean isValidPid(String theIdPart) {
|
||||
return StringUtils.isNumeric(theIdPart);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public List<ResourcePersistentId> getPidsOrThrowException(@Nonnull RequestPartitionId theRequestPartitionId, List<IIdType> theIds) {
|
||||
List<ResourcePersistentId> resourcePersistentIds = resolveResourcePersistentIdsWithCache(theRequestPartitionId, theIds);
|
||||
return resourcePersistentIds;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ResourcePersistentId getPidOrNull(@Nonnull RequestPartitionId theRequestPartitionId, IBaseResource theResource) {
|
||||
ResourcePersistentId retVal = new ResourcePersistentId(theResource.getUserData(RESOURCE_PID));
|
||||
if (retVal.getId() == null) {
|
||||
IIdType id = theResource.getIdElement();
|
||||
try {
|
||||
retVal = resolveResourcePersistentIds(theRequestPartitionId, id.getResourceType(), id.getIdPart());
|
||||
} catch (ResourceNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public ResourcePersistentId getPidOrThrowException(@Nonnull RequestPartitionId theRequestPartitionId, IIdType theId) {
|
||||
List<IIdType> ids = Collections.singletonList(theId);
|
||||
List<ResourcePersistentId> resourcePersistentIds = resolveResourcePersistentIdsWithCache(theRequestPartitionId, ids);
|
||||
return resourcePersistentIds.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public ResourcePersistentId getPidOrThrowException(@Nonnull IAnyResource theResource) {
|
||||
Object theResourcePID = theResource.getUserData(RESOURCE_PID);
|
||||
if (theResourcePID == null) {
|
||||
throw new IllegalStateException(Msg.code(2108) + String.format("Unable to find %s in the user data for %s with ID %s", RESOURCE_PID, theResource, theResource.getId()));
|
||||
}
|
||||
return new ResourcePersistentId(theResourcePID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IIdType resourceIdFromPidOrThrowException(ResourcePersistentId thePid, String theResourceType) {
|
||||
Optional<ResourceTable> optionalResource = myResourceTableDao.findById(thePid.getIdAsLong());
|
||||
if (!optionalResource.isPresent()) {
|
||||
throw new ResourceNotFoundException(Msg.code(2107) + "Requested resource not found");
|
||||
}
|
||||
return optionalResource.get().getIdDt().toVersionless();
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a set of PIDs, return a set of public FHIR Resource IDs.
|
||||
* This function will resolve a forced ID if it resolves, and if it fails to resolve to a forced it, will just return the pid
|
||||
* Example:
|
||||
* Let's say we have Patient/1(pid == 1), Patient/pat1 (pid == 2), Patient/3 (pid == 3), their pids would resolve as follows:
|
||||
* <p>
|
||||
* [1,2,3] -> ["1","pat1","3"]
|
||||
*
|
||||
* @param thePids The Set of pids you would like to resolve to external FHIR Resource IDs.
|
||||
* @return A Set of strings representing the FHIR IDs of the pids.
|
||||
*/
|
||||
@Override
|
||||
public Set<String> translatePidsToFhirResourceIds(Set<ResourcePersistentId> thePids) {
|
||||
assert TransactionSynchronizationManager.isSynchronizationActive();
|
||||
|
||||
PersistentIdToForcedIdMap pidToForcedIdMap = translatePidsToForcedIds(thePids);
|
||||
|
||||
return pidToForcedIdMap.getResolvedResourceIds();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ package ca.uhn.fhir.jpa.dao.index;
|
|||
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.api.model.PersistentIdToForcedIdMap;
|
||||
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceTableDao;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
|
@ -37,13 +38,10 @@ import javax.annotation.Nonnull;
|
|||
import javax.annotation.Nullable;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static ca.uhn.fhir.jpa.dao.index.IdHelperService.RESOURCE_PID;
|
||||
|
||||
/**
|
||||
* See {@link IJpaIdHelperService} for an explanation of this class.
|
||||
*/
|
||||
|
@ -104,13 +102,13 @@ public class JpaIdHelperService extends IdHelperService implements IJpaIdHelperS
|
|||
|
||||
@Override
|
||||
@Nonnull
|
||||
public Long getPidOrThrowException(@Nonnull IAnyResource theResource) {
|
||||
public ResourcePersistentId getPidOrThrowException(@Nonnull IAnyResource theResource) {
|
||||
Long retVal = (Long) theResource.getUserData(RESOURCE_PID);
|
||||
if (retVal == null) {
|
||||
throw new IllegalStateException(Msg.code(1102) + String.format("Unable to find %s in the user data for %s with ID %s", RESOURCE_PID, theResource, theResource.getId())
|
||||
);
|
||||
}
|
||||
return retVal;
|
||||
return new ResourcePersistentId(retVal);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -134,18 +132,12 @@ public class JpaIdHelperService extends IdHelperService implements IJpaIdHelperS
|
|||
* @return A Set of strings representing the FHIR IDs of the pids.
|
||||
*/
|
||||
@Override
|
||||
public Set<String> translatePidsToFhirResourceIds(Set<Long> thePids) {
|
||||
public Set<String> translatePidsToFhirResourceIds(Set<ResourcePersistentId> thePids) {
|
||||
assert TransactionSynchronizationManager.isSynchronizationActive();
|
||||
|
||||
Map<Long, Optional<String>> pidToForcedIdMap = super.translatePidsToForcedIds(thePids);
|
||||
|
||||
//If the result of the translation is an empty optional, it means there is no forced id, and we can use the PID as the resource ID.
|
||||
Set<String> resolvedResourceIds = pidToForcedIdMap.entrySet().stream()
|
||||
.map(entry -> entry.getValue().isPresent() ? entry.getValue().get() : entry.getKey().toString())
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
return resolvedResourceIds;
|
||||
PersistentIdToForcedIdMap pidToForcedIdMap = super.translatePidsToForcedIds(thePids);
|
||||
|
||||
return pidToForcedIdMap.getResolvedResourceIds();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,243 @@
|
|||
package ca.uhn.fhir.jpa.dao.mdm;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
||||
import ca.uhn.fhir.jpa.dao.data.IMdmLinkJpaRepository;
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLink;
|
||||
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||
import ca.uhn.fhir.mdm.api.paging.MdmPageRequest;
|
||||
import ca.uhn.fhir.mdm.dao.IMdmLinkDao;
|
||||
import ca.uhn.fhir.mdm.model.MdmPidTuple;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.collections4.ListUtils;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Example;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.TypedQuery;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Expression;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class MdmLinkDaoJpaImpl implements IMdmLinkDao<MdmLink> {
|
||||
@Autowired
|
||||
IMdmLinkJpaRepository myMdmLinkDao;
|
||||
@Autowired
|
||||
protected EntityManager myEntityManager;
|
||||
@Autowired
|
||||
private IIdHelperService myIdHelperService;
|
||||
|
||||
@Override
|
||||
public int deleteWithAnyReferenceToPid(ResourcePersistentId thePid) {
|
||||
return myMdmLinkDao.deleteWithAnyReferenceToPid(thePid.getIdAsLong());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteWithAnyReferenceToPidAndMatchResultNot(ResourcePersistentId thePid, MdmMatchResultEnum theMatchResult) {
|
||||
return myMdmLinkDao.deleteWithAnyReferenceToPidAndMatchResultNot(thePid.getIdAsLong(), theMatchResult);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MdmPidTuple> expandPidsFromGroupPidGivenMatchResult(ResourcePersistentId theGroupPid, MdmMatchResultEnum theMdmMatchResultEnum) {
|
||||
return myMdmLinkDao.expandPidsFromGroupPidGivenMatchResult(theGroupPid.getIdAsLong(), theMdmMatchResultEnum)
|
||||
.stream()
|
||||
.map( theMdmPidTuple -> new MdmPidTuple()
|
||||
.setSourcePid(new ResourcePersistentId(theMdmPidTuple.getSourcePid()))
|
||||
.setGoldenPid(new ResourcePersistentId(theMdmPidTuple.getGoldenPid())))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MdmPidTuple> expandPidsBySourcePidAndMatchResult(ResourcePersistentId theSourcePid, MdmMatchResultEnum theMdmMatchResultEnum) {
|
||||
return myMdmLinkDao.expandPidsBySourcePidAndMatchResult(theSourcePid.getIdAsLong(), theMdmMatchResultEnum)
|
||||
.stream()
|
||||
.map( theMdmPidTuple -> new MdmPidTuple()
|
||||
.setSourcePid(new ResourcePersistentId(theMdmPidTuple.getSourcePid()))
|
||||
.setGoldenPid(new ResourcePersistentId(theMdmPidTuple.getGoldenPid())))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MdmPidTuple> expandPidsByGoldenResourcePidAndMatchResult(ResourcePersistentId theSourcePid, MdmMatchResultEnum theMdmMatchResultEnum) {
|
||||
return myMdmLinkDao.expandPidsByGoldenResourcePidAndMatchResult(theSourcePid.getIdAsLong(), theMdmMatchResultEnum)
|
||||
.stream()
|
||||
.map( theMdmPidTuple -> new MdmPidTuple()
|
||||
.setSourcePid(new ResourcePersistentId(theMdmPidTuple.getSourcePid()))
|
||||
.setGoldenPid(new ResourcePersistentId(theMdmPidTuple.getGoldenPid())))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ResourcePersistentId> findPidByResourceNameAndThreshold(String theResourceName, Date theHighThreshold, Pageable thePageable) {
|
||||
return myMdmLinkDao.findPidByResourceNameAndThreshold(theResourceName,theHighThreshold, thePageable)
|
||||
.stream()
|
||||
.map( theResourcePids -> new ResourcePersistentId(theResourcePids))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ResourcePersistentId> findPidByResourceNameAndThresholdAndPartitionId(String theResourceName, Date theHighThreshold, List<Integer> thePartitionIds, Pageable thePageable) {
|
||||
return myMdmLinkDao.findPidByResourceNameAndThresholdAndPartitionId(theResourceName,theHighThreshold, thePartitionIds, thePageable)
|
||||
.stream()
|
||||
.map( theResourcePids -> new ResourcePersistentId(theResourcePids))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MdmLink> findAllById(List<ResourcePersistentId> thePids) {
|
||||
List<Long> theLongPids = thePids.stream().map(theResourcePersistentId -> theResourcePersistentId.getIdAsLong()).collect(Collectors.toList());
|
||||
return myMdmLinkDao.findAllById(theLongPids);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<MdmLink> findById(ResourcePersistentId thePid) {
|
||||
return myMdmLinkDao.findById(thePid.getIdAsLong());
|
||||
}
|
||||
|
||||
public void deleteAll(List<MdmLink> theLinks) {
|
||||
myMdmLinkDao.deleteAll(theLinks);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<MdmLink> findAll(Example<MdmLink> theExample) {
|
||||
return myMdmLinkDao.findAll(theExample);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MdmLink> findAll() {
|
||||
return myMdmLinkDao.findAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long count() {
|
||||
return myMdmLinkDao.count();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteAll() {
|
||||
myMdmLinkDao.deleteAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MdmLink save(MdmLink theMdmLink) {
|
||||
return myMdmLinkDao.save(theMdmLink);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<MdmLink> findOne(Example<MdmLink> theExample) {
|
||||
return myMdmLinkDao.findOne(theExample);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(MdmLink theMdmLink) {
|
||||
myMdmLinkDao.delete(theMdmLink);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MdmLink validateMdmLink(IMdmLink theMdmLink) throws UnprocessableEntityException {
|
||||
if (theMdmLink instanceof MdmLink){
|
||||
return (MdmLink) theMdmLink;
|
||||
}
|
||||
else {
|
||||
throw new UnprocessableEntityException(Msg.code(2109) + "Unprocessable MdmLink implementation");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<MdmLink> search(IIdType theGoldenResourceId, IIdType theSourceId, MdmMatchResultEnum theMatchResult, MdmLinkSourceEnum theLinkSource, MdmPageRequest thePageRequest, List<Integer> thePartitionId) {
|
||||
CriteriaBuilder criteriaBuilder = myEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<MdmLink> criteriaQuery = criteriaBuilder.createQuery(MdmLink.class);
|
||||
Root<MdmLink> from = criteriaQuery.from(MdmLink.class);
|
||||
|
||||
List<Predicate> andPredicates = new ArrayList<>();
|
||||
|
||||
if (theGoldenResourceId != null) {
|
||||
Predicate goldenResourcePredicate = criteriaBuilder.equal(from.get("myGoldenResourcePid").as(Long.class), myIdHelperService.getPidOrThrowException(RequestPartitionId.allPartitions(), theGoldenResourceId).getIdAsLong());
|
||||
andPredicates.add(goldenResourcePredicate);
|
||||
}
|
||||
if (theSourceId != null) {
|
||||
Predicate sourceIdPredicate = criteriaBuilder.equal(from.get("mySourcePid").as(Long.class), myIdHelperService.getPidOrThrowException(RequestPartitionId.allPartitions(), theSourceId).getIdAsLong());
|
||||
andPredicates.add(sourceIdPredicate);
|
||||
}
|
||||
if (theMatchResult != null) {
|
||||
Predicate matchResultPredicate = criteriaBuilder.equal(from.get("myMatchResult").as(MdmMatchResultEnum.class), theMatchResult);
|
||||
andPredicates.add(matchResultPredicate);
|
||||
}
|
||||
if (theLinkSource != null) {
|
||||
Predicate linkSourcePredicate = criteriaBuilder.equal(from.get("myLinkSource").as(MdmLinkSourceEnum.class), theLinkSource);
|
||||
andPredicates.add(linkSourcePredicate);
|
||||
}
|
||||
if (!CollectionUtils.isEmpty(thePartitionId)) {
|
||||
Expression<Integer> exp = from.get("myPartitionId").get("myPartitionId").as(Integer.class);
|
||||
Predicate linkSourcePredicate = exp.in(thePartitionId);
|
||||
andPredicates.add(linkSourcePredicate);
|
||||
}
|
||||
|
||||
Predicate finalQuery = criteriaBuilder.and(andPredicates.toArray(new Predicate[0]));
|
||||
TypedQuery<MdmLink> typedQuery = myEntityManager.createQuery(criteriaQuery.where(finalQuery));
|
||||
|
||||
CriteriaQuery<Long> countQuery = criteriaBuilder.createQuery(Long.class);
|
||||
countQuery.select(criteriaBuilder.count(countQuery.from(MdmLink.class)))
|
||||
.where(finalQuery);
|
||||
|
||||
Long totalResults = myEntityManager.createQuery(countQuery).getSingleResult();
|
||||
|
||||
return new PageImpl<>(typedQuery.setFirstResult(thePageRequest.getOffset()).setMaxResults(thePageRequest.getCount()).getResultList(),
|
||||
PageRequest.of(thePageRequest.getPage(), thePageRequest.getCount()),
|
||||
totalResults);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<? extends IMdmLink> findBySourcePidAndMatchResult(ResourcePersistentId theSourcePid, MdmMatchResultEnum theMatch) {
|
||||
return myMdmLinkDao.findBySourcePidAndMatchResult(theSourcePid.getIdAsLong(), theMatch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteLinksWithAnyReferenceToPids(List<ResourcePersistentId> theResourcePersistentIds) {
|
||||
List<Long> goldenResourcePids = theResourcePersistentIds.stream().map(ResourcePersistentId::getIdAsLong).collect(Collectors.toList());
|
||||
// Split into chunks of 500 so older versions of Oracle don't run into issues (500 = 1000 / 2 since the dao
|
||||
// method uses the list twice in the sql predicate)
|
||||
List<List<Long>> chunks = ListUtils.partition(goldenResourcePids, 500);
|
||||
for (List<Long> chunk : chunks) {
|
||||
myMdmLinkDao.deleteLinksWithAnyReferenceToPids(chunk);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -51,11 +51,11 @@ public class FhirResourceDaoQuestionnaireResponseR4 extends BaseHapiFhirResource
|
|||
// }
|
||||
// }
|
||||
//
|
||||
// public class JpaResourceLoader implements IResourceLoader {
|
||||
// public class ResourceLoaderImpl implements IResourceLoader {
|
||||
//
|
||||
// private RequestDetails myRequestDetails;
|
||||
//
|
||||
// public JpaResourceLoader(RequestDetails theRequestDetails) {
|
||||
// public ResourceLoaderImpl(RequestDetails theRequestDetails) {
|
||||
// super();
|
||||
// myRequestDetails = theRequestDetails;
|
||||
// }
|
||||
|
|
|
@ -51,11 +51,11 @@ public class FhirResourceDaoQuestionnaireResponseR5 extends BaseHapiFhirResource
|
|||
// }
|
||||
// }
|
||||
//
|
||||
// public class JpaResourceLoader implements IResourceLoader {
|
||||
// public class ResourceLoaderImpl implements IResourceLoader {
|
||||
//
|
||||
// private RequestDetails myRequestDetails;
|
||||
//
|
||||
// public JpaResourceLoader(RequestDetails theRequestDetails) {
|
||||
// public ResourceLoaderImpl(RequestDetails theRequestDetails) {
|
||||
// super();
|
||||
// myRequestDetails = theRequestDetails;
|
||||
// }
|
||||
|
|
|
@ -22,6 +22,7 @@ package ca.uhn.fhir.jpa.delete.batch2;
|
|||
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceLinkDao;
|
||||
import ca.uhn.fhir.jpa.dao.expunge.ResourceForeignKey;
|
||||
import ca.uhn.fhir.jpa.dao.expunge.ResourceTableFKProvider;
|
||||
|
@ -45,10 +46,10 @@ public class DeleteExpungeSqlBuilder {
|
|||
|
||||
private final ResourceTableFKProvider myResourceTableFKProvider;
|
||||
private final DaoConfig myDaoConfig;
|
||||
private final IJpaIdHelperService myIdHelper;
|
||||
private final IIdHelperService myIdHelper;
|
||||
private final IResourceLinkDao myResourceLinkDao;
|
||||
|
||||
public DeleteExpungeSqlBuilder(ResourceTableFKProvider theResourceTableFKProvider, DaoConfig theDaoConfig, IJpaIdHelperService theIdHelper, IResourceLinkDao theResourceLinkDao) {
|
||||
public DeleteExpungeSqlBuilder(ResourceTableFKProvider theResourceTableFKProvider, DaoConfig theDaoConfig, IIdHelperService theIdHelper, IResourceLinkDao theResourceLinkDao) {
|
||||
myResourceTableFKProvider = theResourceTableFKProvider;
|
||||
myDaoConfig = theDaoConfig;
|
||||
myIdHelper = theIdHelper;
|
||||
|
@ -96,8 +97,8 @@ public class DeleteExpungeSqlBuilder {
|
|||
//NB-GGG: We previously instantiated these ID values from firstConflict.getSourceResource().getIdDt(), but in a situation where we
|
||||
//actually had to run delete conflict checks in multiple partitions, the executor service starts its own sessions on a per thread basis, and by the time
|
||||
//we arrive here, those sessions are closed. So instead, we resolve them from PIDs, which are eagerly loaded.
|
||||
String sourceResourceId = myIdHelper.resourceIdFromPidOrThrowException(firstConflict.getSourceResourcePid()).toVersionless().getValue();
|
||||
String targetResourceId = myIdHelper.resourceIdFromPidOrThrowException(firstConflict.getTargetResourcePid()).toVersionless().getValue();
|
||||
String sourceResourceId = myIdHelper.resourceIdFromPidOrThrowException(new ResourcePersistentId(firstConflict.getSourceResourcePid()), firstConflict.getSourceResourceType()).toVersionless().getValue();
|
||||
String targetResourceId = myIdHelper.resourceIdFromPidOrThrowException(new ResourcePersistentId(firstConflict.getTargetResourcePid()), firstConflict.getTargetResourceType()).toVersionless().getValue();
|
||||
|
||||
throw new InvalidRequestException(Msg.code(822) + "DELETE with _expunge=true failed. Unable to delete " +
|
||||
targetResourceId + " because " + sourceResourceId + " refers to it via the path " + firstConflict.getSourcePath());
|
||||
|
|
|
@ -25,6 +25,7 @@ import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
|||
import ca.uhn.fhir.mdm.api.IMdmLink;
|
||||
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
|
||||
import javax.persistence.Column;
|
||||
|
@ -137,12 +138,38 @@ public class MdmLink extends BasePartitionable implements IMdmLink {
|
|||
@Column(name = "TARGET_TYPE", nullable = true, length = SOURCE_TYPE_LENGTH)
|
||||
private String myMdmSourceType;
|
||||
|
||||
public Long getId() {
|
||||
return myId;
|
||||
@Override
|
||||
public ResourcePersistentId getId() {
|
||||
return new ResourcePersistentId(myId);
|
||||
}
|
||||
|
||||
public MdmLink setId(Long theId) {
|
||||
myId = theId;
|
||||
@Override
|
||||
public MdmLink setId(ResourcePersistentId theId) {
|
||||
myId = theId.getIdAsLong();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourcePersistentId getGoldenResourcePersistenceId() {
|
||||
return new ResourcePersistentId(myGoldenResourcePid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMdmLink setGoldenResourcePersistenceId(ResourcePersistentId theGoldenResourcePid) {
|
||||
setPersonPid(theGoldenResourcePid.getIdAsLong());
|
||||
|
||||
myGoldenResourcePid = theGoldenResourcePid.getIdAsLong();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourcePersistentId getSourcePersistenceId() {
|
||||
return new ResourcePersistentId(mySourcePid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMdmLink setSourcePersistenceId(ResourcePersistentId theSourcePid) {
|
||||
mySourcePid = theSourcePid.getIdAsLong();
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -160,6 +187,7 @@ public class MdmLink extends BasePartitionable implements IMdmLink {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public Long getGoldenResourcePid() {
|
||||
return myGoldenResourcePid;
|
||||
}
|
||||
|
@ -173,6 +201,10 @@ public class MdmLink extends BasePartitionable implements IMdmLink {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #setGoldenResourcePersistenceId(ResourcePersistentId)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public MdmLink setGoldenResourcePid(Long theGoldenResourcePid) {
|
||||
setPersonPid(theGoldenResourcePid);
|
||||
|
||||
|
@ -190,101 +222,92 @@ public class MdmLink extends BasePartitionable implements IMdmLink {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public Long getSourcePid() {
|
||||
return mySourcePid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #setSourcePersistenceId(ResourcePersistentId)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public MdmLink setSourcePid(Long theSourcePid) {
|
||||
mySourcePid = theSourcePid;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MdmMatchResultEnum getMatchResult() {
|
||||
return myMatchResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MdmLink setMatchResult(MdmMatchResultEnum theMatchResult) {
|
||||
myMatchResult = theMatchResult;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isNoMatch() {
|
||||
return myMatchResult == MdmMatchResultEnum.NO_MATCH;
|
||||
}
|
||||
|
||||
public boolean isMatch() {
|
||||
return myMatchResult == MdmMatchResultEnum.MATCH;
|
||||
}
|
||||
|
||||
public boolean isPossibleMatch() {
|
||||
return myMatchResult == MdmMatchResultEnum.POSSIBLE_MATCH;
|
||||
}
|
||||
|
||||
public boolean isRedirect() {
|
||||
return myMatchResult == MdmMatchResultEnum.REDIRECT;
|
||||
}
|
||||
|
||||
public boolean isPossibleDuplicate() {
|
||||
return myMatchResult == MdmMatchResultEnum.POSSIBLE_DUPLICATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MdmLinkSourceEnum getLinkSource() {
|
||||
return myLinkSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MdmLink setLinkSource(MdmLinkSourceEnum theLinkSource) {
|
||||
myLinkSource = theLinkSource;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isAuto() {
|
||||
return myLinkSource == MdmLinkSourceEnum.AUTO;
|
||||
}
|
||||
|
||||
public boolean isManual() {
|
||||
return myLinkSource == MdmLinkSourceEnum.MANUAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getCreated() {
|
||||
return myCreated;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MdmLink setCreated(Date theCreated) {
|
||||
myCreated = theCreated;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getUpdated() {
|
||||
return myUpdated;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MdmLink setUpdated(Date theUpdated) {
|
||||
myUpdated = theUpdated;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return myVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MdmLink setVersion(String theVersion) {
|
||||
myVersion = theVersion;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getVector() {
|
||||
return myVector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MdmLink setVector(Long theVector) {
|
||||
myVector = theVector;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getScore() {
|
||||
return myScore;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MdmLink setScore(Double theScore) {
|
||||
myScore = theScore;
|
||||
return this;
|
||||
|
@ -299,19 +322,23 @@ public class MdmLink extends BasePartitionable implements IMdmLink {
|
|||
* <code>isEidMatch</code> because Hibernate Search complains about having
|
||||
* 2 accessors for this property
|
||||
*/
|
||||
public boolean isEidMatchPresent() {
|
||||
@Override
|
||||
public Boolean isEidMatchPresent() {
|
||||
return myEidMatch != null && myEidMatch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MdmLink setEidMatch(Boolean theEidMatch) {
|
||||
myEidMatch = theEidMatch;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean getHadToCreateNewGoldenResource() {
|
||||
@Override
|
||||
public Boolean getHadToCreateNewGoldenResource() {
|
||||
return myHadToCreateNewGoldenResource != null && myHadToCreateNewGoldenResource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MdmLink setHadToCreateNewGoldenResource(Boolean theHadToCreateNewResource) {
|
||||
myHadToCreateNewGoldenResource = theHadToCreateNewResource;
|
||||
return this;
|
||||
|
@ -347,8 +374,9 @@ public class MdmLink extends BasePartitionable implements IMdmLink {
|
|||
return myRuleCount;
|
||||
}
|
||||
|
||||
public void setRuleCount(Long theRuleCount) {
|
||||
public MdmLink setRuleCount(Long theRuleCount) {
|
||||
myRuleCount = theRuleCount;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ package ca.uhn.fhir.jpa.term;
|
|||
*/
|
||||
|
||||
import ca.uhn.fhir.context.support.ConceptValidationOptions;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
import ca.uhn.fhir.context.support.ValueSetExpansionOptions;
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
|
@ -35,7 +34,6 @@ import org.hl7.fhir.r4.model.CodeSystem;
|
|||
import org.hl7.fhir.r4.model.CodeableConcept;
|
||||
import org.hl7.fhir.r4.model.Coding;
|
||||
import org.hl7.fhir.r4.model.ValueSet;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
|
|
|
@ -7,18 +7,20 @@ import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
|||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.api.model.PersistentIdToForcedIdMap;
|
||||
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
||||
import ca.uhn.fhir.jpa.bulk.export.model.ExportPIDIteratorParameters;
|
||||
import ca.uhn.fhir.jpa.dao.IResultIterator;
|
||||
import ca.uhn.fhir.jpa.dao.ISearchBuilder;
|
||||
import ca.uhn.fhir.jpa.dao.SearchBuilderFactory;
|
||||
import ca.uhn.fhir.jpa.dao.data.IMdmLinkDao;
|
||||
import ca.uhn.fhir.jpa.dao.index.IJpaIdHelperService;
|
||||
import ca.uhn.fhir.jpa.dao.mdm.MdmExpansionCacheSvc;
|
||||
import ca.uhn.fhir.jpa.model.search.SearchRuntimeDetails;
|
||||
import ca.uhn.fhir.jpa.partition.SystemRequestDetails;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||
import ca.uhn.fhir.mdm.dao.IMdmLinkDao;
|
||||
import ca.uhn.fhir.mdm.model.MdmPidTuple;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.api.server.bulk.BulkDataExportOptions;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
|
@ -126,9 +128,6 @@ public class JpaBulkExportProcessorTest {
|
|||
@Mock
|
||||
private IMdmLinkDao myMdmLinkDao;
|
||||
|
||||
@Mock
|
||||
private IJpaIdHelperService myJpaIdHelperService;
|
||||
|
||||
@Mock
|
||||
private MdmExpansionCacheSvc myMdmExpansionCacheSvc;
|
||||
|
||||
|
@ -159,16 +158,16 @@ public class JpaBulkExportProcessorTest {
|
|||
return patientTypes;
|
||||
}
|
||||
|
||||
private IMdmLinkDao.MdmPidTuple createTuple(long theGroupId, long theGoldenId) {
|
||||
return new IMdmLinkDao.MdmPidTuple() {
|
||||
private MdmPidTuple createTuple(long theGroupId, long theGoldenId) {
|
||||
return new MdmPidTuple() {
|
||||
@Override
|
||||
public Long getGoldenPid() {
|
||||
return theGoldenId;
|
||||
public ResourcePersistentId getGoldenPid() {
|
||||
return new ResourcePersistentId(theGoldenId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getSourcePid() {
|
||||
return theGroupId;
|
||||
public ResourcePersistentId getSourcePid() {
|
||||
return new ResourcePersistentId(theGroupId);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -251,19 +250,19 @@ public class JpaBulkExportProcessorTest {
|
|||
ExportPIDIteratorParameters parameters = createExportParameters(BulkDataExportOptions.ExportStyle.GROUP);
|
||||
parameters.setResourceType("Patient");
|
||||
|
||||
long groupId = Long.parseLong(parameters.getGroupId());
|
||||
ResourcePersistentId groupId = new ResourcePersistentId(Long.parseLong(parameters.getGroupId()));
|
||||
long groupGoldenPid = 4567l;
|
||||
|
||||
Group groupResource = new Group();
|
||||
groupResource.setId(parameters.getGroupId());
|
||||
|
||||
List<IPrimitiveType> patientTypes = createPatientTypes();
|
||||
List<Long> pids = new ArrayList<>();
|
||||
List<ResourcePersistentId> pids = new ArrayList<>();
|
||||
for (IPrimitiveType type : patientTypes) {
|
||||
pids.add(((IdDt) type).getIdPartAsLong());
|
||||
pids.add(new ResourcePersistentId(((IdDt) type).getIdPartAsLong()));
|
||||
}
|
||||
|
||||
IMdmLinkDao.MdmPidTuple tuple = createTuple(groupId, groupGoldenPid);
|
||||
MdmPidTuple tuple = createTuple(groupId.getIdAsLong(), groupGoldenPid);
|
||||
|
||||
IFhirResourceDao<Group> groupDao = mock(IFhirResourceDao.class);
|
||||
IFhirPath path = mock(IFhirPath.class);
|
||||
|
@ -279,13 +278,22 @@ public class JpaBulkExportProcessorTest {
|
|||
.thenReturn(path);
|
||||
when(path.evaluate(eq(groupResource), anyString(), any(Class.class)))
|
||||
.thenReturn(patientTypes);
|
||||
when(myJpaIdHelperService.getPidsOrThrowException(anyList()))
|
||||
when(myIdHelperService.getPidsOrThrowException(any(), anyList()))
|
||||
.thenReturn(pids);
|
||||
// mdm expansion stuff
|
||||
if (theMdm) {
|
||||
when(myJpaIdHelperService.getPidOrNull(any(Group.class)))
|
||||
when(myIdHelperService.translatePidsToForcedIds(any(Set.class)))
|
||||
.thenAnswer(params -> {
|
||||
Set<ResourcePersistentId> uniqPids = params.getArgument(0);
|
||||
HashMap<ResourcePersistentId, Optional<String>> answer = new HashMap<>();
|
||||
for (ResourcePersistentId l : uniqPids) {
|
||||
answer.put(l, Optional.empty());
|
||||
}
|
||||
return new PersistentIdToForcedIdMap(answer);
|
||||
});
|
||||
when(myIdHelperService.getPidOrNull(any(), any(Group.class)))
|
||||
.thenReturn(groupId);
|
||||
when(myMdmLinkDao.expandPidsFromGroupPidGivenMatchResult(anyLong(), eq(MdmMatchResultEnum.MATCH)))
|
||||
when(myMdmLinkDao.expandPidsFromGroupPidGivenMatchResult(any(ResourcePersistentId.class), eq(MdmMatchResultEnum.MATCH)))
|
||||
.thenReturn(Collections.singletonList(tuple));
|
||||
when(myMdmExpansionCacheSvc.hasBeenPopulated())
|
||||
.thenReturn(false); // does not matter, since if false, it then goes and populates
|
||||
|
@ -301,7 +309,7 @@ public class JpaBulkExportProcessorTest {
|
|||
while (pidIterator.hasNext()) {
|
||||
ResourcePersistentId pid = pidIterator.next();
|
||||
long idAsLong = pid.getIdAsLong();
|
||||
boolean existing = pids.contains(idAsLong);
|
||||
boolean existing = pids.contains(new ResourcePersistentId(idAsLong));
|
||||
if (!existing) {
|
||||
assertTrue(theMdm);
|
||||
assertEquals(groupGoldenPid, idAsLong);
|
||||
|
@ -320,7 +328,7 @@ public class JpaBulkExportProcessorTest {
|
|||
ExportPIDIteratorParameters parameters = createExportParameters(BulkDataExportOptions.ExportStyle.GROUP);
|
||||
parameters.setResourceType("Observation");
|
||||
|
||||
long groupId = Long.parseLong(parameters.getGroupId());
|
||||
ResourcePersistentId groupId = new ResourcePersistentId(Long.parseLong(parameters.getGroupId()));
|
||||
Group groupResource = new Group();
|
||||
groupResource.setId(parameters.getGroupId());
|
||||
long groupGoldenPid = 4567l;
|
||||
|
@ -331,7 +339,7 @@ public class JpaBulkExportProcessorTest {
|
|||
Arrays.asList(pid, pid2)
|
||||
);
|
||||
|
||||
IMdmLinkDao.MdmPidTuple tuple = createTuple(groupId, groupGoldenPid);
|
||||
MdmPidTuple tuple = createTuple(groupId.getIdAsLong(), groupGoldenPid);
|
||||
List<IPrimitiveType> patientTypes = createPatientTypes();
|
||||
|
||||
IFhirResourceDao<Group> groupDao = mock(IFhirResourceDao.class);
|
||||
|
@ -346,20 +354,20 @@ public class JpaBulkExportProcessorTest {
|
|||
.thenReturn(groupDao);
|
||||
when(groupDao.read(any(IIdType.class), any(SystemRequestDetails.class)))
|
||||
.thenReturn(groupResource);
|
||||
when(myJpaIdHelperService.getPidOrNull(eq(groupResource)))
|
||||
when(myIdHelperService.getPidOrNull(any(), eq(groupResource)))
|
||||
.thenReturn(groupId);
|
||||
|
||||
if (theMdm) {
|
||||
when(myMdmLinkDao.expandPidsFromGroupPidGivenMatchResult(anyLong(), eq(MdmMatchResultEnum.MATCH)))
|
||||
when(myMdmLinkDao.expandPidsFromGroupPidGivenMatchResult(any(ResourcePersistentId.class), eq(MdmMatchResultEnum.MATCH)))
|
||||
.thenReturn(Collections.singletonList(tuple));
|
||||
when(myIdHelperService.translatePidsToForcedIds(any(Set.class)))
|
||||
.thenAnswer(params -> {
|
||||
Set<Long> uniqPids = params.getArgument(0);
|
||||
HashMap<Long, Optional<String>> answer = new HashMap<>();
|
||||
for (long l : uniqPids) {
|
||||
Set<ResourcePersistentId> uniqPids = params.getArgument(0);
|
||||
HashMap<ResourcePersistentId, Optional<String>> answer = new HashMap<>();
|
||||
for (ResourcePersistentId l : uniqPids) {
|
||||
answer.put(l, Optional.empty());
|
||||
}
|
||||
return answer;
|
||||
return new PersistentIdToForcedIdMap(answer);
|
||||
});
|
||||
}
|
||||
when(myFhirContext.newFhirPath())
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.1.0-PRE24-SNAPSHOT</version>
|
||||
<version>6.1.0-PRE25-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.1.0-PRE24-SNAPSHOT</version>
|
||||
<version>6.1.0-PRE25-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -20,13 +20,11 @@ package ca.uhn.fhir.jpa.mdm.broker;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.interceptor.api.HookParams;
|
||||
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
|
||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc;
|
||||
import ca.uhn.fhir.jpa.mdm.svc.IMdmModelConverterSvc;
|
||||
import ca.uhn.fhir.jpa.mdm.svc.MdmMatchLinkSvc;
|
||||
import ca.uhn.fhir.jpa.mdm.svc.MdmResourceFilteringSvc;
|
||||
|
@ -55,8 +53,6 @@ public class MdmMessageHandler implements MessageHandler {
|
|||
|
||||
private static final Logger ourLog = Logs.getMdmTroubleshootingLog();
|
||||
|
||||
@Autowired
|
||||
private MdmLinkDaoSvc myMdmLinkDaoSvc;
|
||||
@Autowired
|
||||
private MdmMatchLinkSvc myMdmMatchLinkSvc;
|
||||
@Autowired
|
||||
|
@ -181,7 +177,7 @@ public class MdmMessageHandler implements MessageHandler {
|
|||
theMdmContext.getMdmLinks()
|
||||
.stream()
|
||||
.forEach(l -> {
|
||||
linkChangeEvent.addMdmLink(myModelConverter.toJson((MdmLink) l));
|
||||
linkChangeEvent.addMdmLink(myModelConverter.toJson(l));
|
||||
});
|
||||
|
||||
return linkChangeEvent;
|
||||
|
|
|
@ -21,9 +21,9 @@ package ca.uhn.fhir.jpa.mdm.config;
|
|||
*/
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.dao.mdm.MdmLinkDeleteSvc;
|
||||
import ca.uhn.fhir.jpa.interceptor.MdmSearchExpandingInterceptor;
|
||||
import ca.uhn.fhir.mdm.interceptor.MdmSearchExpandingInterceptor;
|
||||
import ca.uhn.fhir.mdm.rules.config.MdmRuleValidator;
|
||||
import ca.uhn.fhir.mdm.svc.MdmLinkDeleteSvc;
|
||||
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
@ -41,7 +41,6 @@ public class MdmCommonConfig {
|
|||
return new MdmSearchExpandingInterceptor();
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
MdmLinkDeleteSvc mdmLinkDeleteSvc() {
|
||||
return new MdmLinkDeleteSvc();
|
||||
|
|
|
@ -27,9 +27,7 @@ import ca.uhn.fhir.jpa.mdm.broker.MdmMessageHandler;
|
|||
import ca.uhn.fhir.jpa.mdm.broker.MdmMessageKeySvc;
|
||||
import ca.uhn.fhir.jpa.mdm.broker.MdmQueueConsumerLoader;
|
||||
import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc;
|
||||
import ca.uhn.fhir.jpa.mdm.dao.MdmLinkFactory;
|
||||
import ca.uhn.fhir.jpa.mdm.interceptor.IMdmStorageInterceptor;
|
||||
import ca.uhn.fhir.jpa.mdm.interceptor.MdmStorageInterceptor;
|
||||
import ca.uhn.fhir.mdm.dao.MdmLinkFactory;
|
||||
import ca.uhn.fhir.jpa.mdm.svc.GoldenResourceMergerSvcImpl;
|
||||
import ca.uhn.fhir.jpa.mdm.svc.GoldenResourceSearchSvcImpl;
|
||||
import ca.uhn.fhir.jpa.mdm.svc.IMdmModelConverterSvc;
|
||||
|
@ -44,7 +42,6 @@ import ca.uhn.fhir.jpa.mdm.svc.MdmMatchLinkSvc;
|
|||
import ca.uhn.fhir.jpa.mdm.svc.MdmModelConverterSvcImpl;
|
||||
import ca.uhn.fhir.jpa.mdm.svc.MdmResourceDaoSvc;
|
||||
import ca.uhn.fhir.jpa.mdm.svc.MdmResourceFilteringSvc;
|
||||
import ca.uhn.fhir.jpa.mdm.svc.MdmSearchParamSvc;
|
||||
import ca.uhn.fhir.jpa.mdm.svc.MdmSurvivorshipSvcImpl;
|
||||
import ca.uhn.fhir.jpa.mdm.svc.candidate.CandidateSearcher;
|
||||
import ca.uhn.fhir.jpa.mdm.svc.candidate.FindCandidateByEidSvc;
|
||||
|
@ -65,10 +62,14 @@ import ca.uhn.fhir.mdm.api.IMdmMatchFinderSvc;
|
|||
import ca.uhn.fhir.mdm.api.IMdmSettings;
|
||||
import ca.uhn.fhir.mdm.api.IMdmSurvivorshipService;
|
||||
import ca.uhn.fhir.mdm.batch2.MdmBatch2Config;
|
||||
import ca.uhn.fhir.mdm.dao.IMdmLinkImplFactory;
|
||||
import ca.uhn.fhir.mdm.interceptor.IMdmStorageInterceptor;
|
||||
import ca.uhn.fhir.mdm.interceptor.MdmStorageInterceptor;
|
||||
import ca.uhn.fhir.mdm.log.Logs;
|
||||
import ca.uhn.fhir.mdm.provider.MdmControllerHelper;
|
||||
import ca.uhn.fhir.mdm.provider.MdmProviderLoader;
|
||||
import ca.uhn.fhir.mdm.rules.svc.MdmResourceMatcherSvc;
|
||||
import ca.uhn.fhir.mdm.svc.MdmSearchParamSvc;
|
||||
import ca.uhn.fhir.mdm.util.EIDHelper;
|
||||
import ca.uhn.fhir.mdm.util.GoldenResourceHelper;
|
||||
import ca.uhn.fhir.mdm.util.MessageHelper;
|
||||
|
@ -219,8 +220,8 @@ public class MdmConsumerConfig {
|
|||
}
|
||||
|
||||
@Bean
|
||||
MdmLinkFactory mdmLinkFactory(IMdmSettings theMdmSettings) {
|
||||
return new MdmLinkFactory(theMdmSettings);
|
||||
MdmLinkFactory mdmLinkFactory(IMdmSettings theMdmSettings, IMdmLinkImplFactory theMdmLinkImplFactory) {
|
||||
return new MdmLinkFactory(theMdmSettings, theMdmLinkImplFactory);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
|
|
@ -21,16 +21,17 @@ package ca.uhn.fhir.jpa.mdm.config;
|
|||
*/
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.dao.mdm.MdmLinkDeleteSvc;
|
||||
import ca.uhn.fhir.jpa.dao.mdm.MdmLinkDaoJpaImpl;
|
||||
import ca.uhn.fhir.jpa.mdm.dao.JpaMdmLinkImplFactory;
|
||||
import ca.uhn.fhir.jpa.mdm.interceptor.MdmSubmitterInterceptorLoader;
|
||||
import ca.uhn.fhir.jpa.mdm.svc.MdmChannelSubmitterSvcImpl;
|
||||
import ca.uhn.fhir.jpa.mdm.svc.MdmSearchParamSvc;
|
||||
import ca.uhn.fhir.jpa.mdm.svc.MdmSubmitSvcImpl;
|
||||
import ca.uhn.fhir.mdm.dao.IMdmLinkImplFactory;
|
||||
import ca.uhn.fhir.mdm.svc.MdmChannelSubmitterSvcImpl;
|
||||
import ca.uhn.fhir.mdm.dao.IMdmLinkDao;
|
||||
import ca.uhn.fhir.mdm.svc.MdmSearchParamSvc;
|
||||
import ca.uhn.fhir.mdm.svc.MdmSubmitSvcImpl;
|
||||
import ca.uhn.fhir.jpa.subscription.channel.api.IChannelFactory;
|
||||
import ca.uhn.fhir.mdm.api.IMdmChannelSubmitterSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmSubmitSvc;
|
||||
import ca.uhn.fhir.mdm.rules.config.MdmRuleValidator;
|
||||
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
@ -60,4 +61,12 @@ public class MdmSubmitterConfig {
|
|||
IMdmSubmitSvc mdmSubmitService() {
|
||||
return new MdmSubmitSvcImpl();
|
||||
}
|
||||
|
||||
@Bean
|
||||
IMdmLinkDao mdmLinkDao(){
|
||||
return new MdmLinkDaoJpaImpl();
|
||||
}
|
||||
|
||||
@Bean
|
||||
IMdmLinkImplFactory mdmLinkImplFactory() {return new JpaMdmLinkImplFactory();}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@ import ca.uhn.fhir.i18n.Msg;
|
|||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.partition.SystemRequestDetails;
|
||||
import ca.uhn.fhir.jpa.dao.index.IJpaIdHelperService;
|
||||
import ca.uhn.fhir.jpa.subscription.channel.api.ChannelProducerSettings;
|
||||
import ca.uhn.fhir.jpa.subscription.channel.subscription.IChannelNamer;
|
||||
import ca.uhn.fhir.jpa.subscription.match.registry.SubscriptionLoader;
|
||||
|
@ -56,8 +55,6 @@ public class MdmSubscriptionLoader {
|
|||
@Autowired
|
||||
public DaoRegistry myDaoRegistry;
|
||||
@Autowired
|
||||
public IJpaIdHelperService myIdHelperService;
|
||||
@Autowired
|
||||
IChannelNamer myChannelNamer;
|
||||
@Autowired
|
||||
private SubscriptionLoader mySubscriptionLoader;
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
package ca.uhn.fhir.jpa.mdm.dao;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server - Master Data Management
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLink;
|
||||
import ca.uhn.fhir.mdm.dao.IMdmLinkImplFactory;
|
||||
|
||||
public class JpaMdmLinkImplFactory implements IMdmLinkImplFactory {
|
||||
@Override
|
||||
public IMdmLink newMdmLinkImpl() {
|
||||
return new MdmLink();
|
||||
}
|
||||
}
|
|
@ -22,40 +22,31 @@ package ca.uhn.fhir.jpa.mdm.dao;
|
|||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.dao.data.IMdmLinkDao;
|
||||
import ca.uhn.fhir.jpa.dao.index.IJpaIdHelperService;
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
||||
import ca.uhn.fhir.jpa.model.entity.PartitionablePartitionId;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLink;
|
||||
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchOutcome;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||
import ca.uhn.fhir.mdm.api.paging.MdmPageRequest;
|
||||
import ca.uhn.fhir.mdm.dao.IMdmLinkDao;
|
||||
import ca.uhn.fhir.mdm.dao.MdmLinkFactory;
|
||||
import ca.uhn.fhir.mdm.log.Logs;
|
||||
import ca.uhn.fhir.mdm.model.MdmTransactionContext;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.collections4.ListUtils;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.slf4j.Logger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Example;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.TypedQuery;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Expression;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
@ -70,18 +61,13 @@ public class MdmLinkDaoSvc {
|
|||
@Autowired
|
||||
private MdmLinkFactory myMdmLinkFactory;
|
||||
@Autowired
|
||||
private IJpaIdHelperService myJpaIdHelperService;
|
||||
private IIdHelperService myIdHelperService;
|
||||
@Autowired
|
||||
private FhirContext myFhirContext;
|
||||
@Autowired
|
||||
protected EntityManager myEntityManager;
|
||||
|
||||
@Transactional
|
||||
public MdmLink createOrUpdateLinkEntity(IBaseResource theGoldenResource, IBaseResource theSourceResource, MdmMatchOutcome theMatchOutcome, MdmLinkSourceEnum theLinkSource, @Nullable MdmTransactionContext theMdmTransactionContext) {
|
||||
Long goldenResourcePid = myJpaIdHelperService.getPidOrNull(theGoldenResource);
|
||||
Long sourceResourcePid = myJpaIdHelperService.getPidOrNull(theSourceResource);
|
||||
|
||||
MdmLink mdmLink = getOrCreateMdmLinkByGoldenResourcePidAndSourceResourcePid(goldenResourcePid, sourceResourcePid);
|
||||
public IMdmLink createOrUpdateLinkEntity(IAnyResource theGoldenResource, IAnyResource theSourceResource, MdmMatchOutcome theMatchOutcome, MdmLinkSourceEnum theLinkSource, @Nullable MdmTransactionContext theMdmTransactionContext) {
|
||||
IMdmLink mdmLink = getOrCreateMdmLinkByGoldenResourceAndSourceResource(theGoldenResource, theSourceResource);
|
||||
mdmLink.setLinkSource(theLinkSource);
|
||||
mdmLink.setMatchResult(theMatchOutcome.getMatchResultEnum());
|
||||
// Preserve these flags for link updates
|
||||
|
@ -107,26 +93,46 @@ public class MdmLinkDaoSvc {
|
|||
}
|
||||
|
||||
@Nonnull
|
||||
public MdmLink getOrCreateMdmLinkByGoldenResourcePidAndSourceResourcePid(Long theGoldenResourcePid, Long theSourceResourcePid) {
|
||||
Optional<MdmLink> oExisting = getLinkByGoldenResourcePidAndSourceResourcePid(theGoldenResourcePid, theSourceResourcePid);
|
||||
public IMdmLink getOrCreateMdmLinkByGoldenResourceAndSourceResource(IAnyResource theGoldenResource, IAnyResource theSourceResource) {
|
||||
ResourcePersistentId goldenResourcePid = myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), theGoldenResource);
|
||||
ResourcePersistentId sourceResourcePid = myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), theSourceResource);
|
||||
Optional<? extends IMdmLink> oExisting = getLinkByGoldenResourcePidAndSourceResourcePid(goldenResourcePid, sourceResourcePid);
|
||||
if (oExisting.isPresent()) {
|
||||
return oExisting.get();
|
||||
} else {
|
||||
MdmLink newLink = myMdmLinkFactory.newMdmLink();
|
||||
newLink.setGoldenResourcePid(theGoldenResourcePid);
|
||||
newLink.setSourcePid(theSourceResourcePid);
|
||||
IMdmLink newLink = myMdmLinkFactory.newMdmLink();
|
||||
newLink.setGoldenResourcePersistenceId(goldenResourcePid);
|
||||
newLink.setSourcePersistenceId(sourceResourcePid);
|
||||
return newLink;
|
||||
}
|
||||
}
|
||||
|
||||
public Optional<MdmLink> getLinkByGoldenResourcePidAndSourceResourcePid(Long theGoldenResourcePid, Long theSourceResourcePid) {
|
||||
/**
|
||||
* Given a golden resource Pid and source Pid, return the mdm link that matches these criterias if exists
|
||||
* @deprecated This was deprecated in favour of using ResourcePersistenceId rather than longs
|
||||
* @param theGoldenResourcePid
|
||||
* @param theSourceResourcePid
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
public Optional<? extends IMdmLink> getLinkByGoldenResourcePidAndSourceResourcePid(Long theGoldenResourcePid, Long theSourceResourcePid) {
|
||||
return getLinkByGoldenResourcePidAndSourceResourcePid(new ResourcePersistentId(theGoldenResourcePid), new ResourcePersistentId(theSourceResourcePid));
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a golden resource Pid and source Pid, return the mdm link that matches these criterias if exists
|
||||
* @param theGoldenResourcePid The ResourcePersistenceId of the golden resource
|
||||
* @param theSourceResourcePid The ResourcepersistenceId of the Source resource
|
||||
* @return The {@link IMdmLink} entity that matches these criteria if exists
|
||||
*/
|
||||
public Optional<? extends IMdmLink> getLinkByGoldenResourcePidAndSourceResourcePid(ResourcePersistentId theGoldenResourcePid, ResourcePersistentId theSourceResourcePid) {
|
||||
if (theSourceResourcePid == null || theGoldenResourcePid == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
MdmLink link = myMdmLinkFactory.newMdmLink();
|
||||
link.setSourcePid(theSourceResourcePid);
|
||||
link.setGoldenResourcePid(theGoldenResourcePid);
|
||||
Example<MdmLink> example = Example.of(link);
|
||||
IMdmLink link = myMdmLinkFactory.newMdmLink();
|
||||
link.setSourcePersistenceId(theSourceResourcePid);
|
||||
link.setGoldenResourcePersistenceId(theGoldenResourcePid);
|
||||
Example<? extends IMdmLink> example = Example.of(link);
|
||||
return myMdmLinkDao.findOne(example);
|
||||
}
|
||||
|
||||
|
@ -135,123 +141,132 @@ public class MdmLinkDaoSvc {
|
|||
*
|
||||
* @param theSourcePid the source of the relationship.
|
||||
* @param theMatchResult the Match Result of the relationship
|
||||
* @return a list of {@link MdmLink} entities matching these criteria.
|
||||
* @return a list of {@link IMdmLink} entities matching these criteria.
|
||||
*/
|
||||
public List<MdmLink> getMdmLinksBySourcePidAndMatchResult(Long theSourcePid, MdmMatchResultEnum theMatchResult) {
|
||||
MdmLink exampleLink = myMdmLinkFactory.newMdmLink();
|
||||
exampleLink.setSourcePid(theSourcePid);
|
||||
public List<? extends IMdmLink> getMdmLinksBySourcePidAndMatchResult(ResourcePersistentId theSourcePid, MdmMatchResultEnum theMatchResult) {
|
||||
IMdmLink exampleLink = myMdmLinkFactory.newMdmLink();
|
||||
exampleLink.setSourcePersistenceId(theSourcePid);
|
||||
exampleLink.setMatchResult(theMatchResult);
|
||||
Example<MdmLink> example = Example.of(exampleLink);
|
||||
Example<? extends IMdmLink> example = Example.of(exampleLink);
|
||||
return myMdmLinkDao.findAll(example);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a source Pid, return its Matched {@link MdmLink}. There can only ever be at most one of these, but its possible
|
||||
* Given a source Pid, return its Matched {@link IMdmLink}. There can only ever be at most one of these, but its possible
|
||||
* the source has no matches, and may return an empty optional.
|
||||
*
|
||||
* @param theSourcePid The Pid of the source you wish to find the matching link for.
|
||||
* @return the {@link MdmLink} that contains the Match information for the source.
|
||||
* @return the {@link IMdmLink} that contains the Match information for the source.
|
||||
*/
|
||||
@Deprecated
|
||||
@Transactional
|
||||
public Optional<MdmLink> getMatchedLinkForSourcePid(Long theSourcePid) {
|
||||
public Optional<? extends IMdmLink> getMatchedLinkForSourcePid(ResourcePersistentId theSourcePid) {
|
||||
return myMdmLinkDao.findBySourcePidAndMatchResult(theSourcePid, MdmMatchResultEnum.MATCH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an IBaseResource, return its Matched {@link MdmLink}. There can only ever be at most one of these, but its possible
|
||||
* Given an IBaseResource, return its Matched {@link IMdmLink}. There can only ever be at most one of these, but its possible
|
||||
* the source has no matches, and may return an empty optional.
|
||||
*
|
||||
* @param theSourceResource The IBaseResource representing the source you wish to find the matching link for.
|
||||
* @return the {@link MdmLink} that contains the Match information for the source.
|
||||
* @return the {@link IMdmLink} that contains the Match information for the source.
|
||||
*/
|
||||
public Optional<MdmLink> getMatchedLinkForSource(IBaseResource theSourceResource) {
|
||||
public Optional<? extends IMdmLink> getMatchedLinkForSource(IBaseResource theSourceResource) {
|
||||
return getMdmLinkWithMatchResult(theSourceResource, MdmMatchResultEnum.MATCH);
|
||||
}
|
||||
|
||||
public Optional<MdmLink> getPossibleMatchedLinkForSource(IBaseResource theSourceResource) {
|
||||
public Optional<? extends IMdmLink> getPossibleMatchedLinkForSource(IBaseResource theSourceResource) {
|
||||
return getMdmLinkWithMatchResult(theSourceResource, MdmMatchResultEnum.POSSIBLE_MATCH);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private Optional<MdmLink> getMdmLinkWithMatchResult(IBaseResource theSourceResource, MdmMatchResultEnum theMatchResult) {
|
||||
Long pid = myJpaIdHelperService.getPidOrNull(theSourceResource);
|
||||
private Optional<? extends IMdmLink> getMdmLinkWithMatchResult(IBaseResource theSourceResource, MdmMatchResultEnum theMatchResult) {
|
||||
ResourcePersistentId pid = myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), theSourceResource);
|
||||
if (pid == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
MdmLink exampleLink = myMdmLinkFactory.newMdmLink();
|
||||
exampleLink.setSourcePid(pid);
|
||||
IMdmLink exampleLink = myMdmLinkFactory.newMdmLink();
|
||||
exampleLink.setSourcePersistenceId(pid);
|
||||
exampleLink.setMatchResult(theMatchResult);
|
||||
Example<MdmLink> example = Example.of(exampleLink);
|
||||
Example<? extends IMdmLink> example = Example.of(exampleLink);
|
||||
return myMdmLinkDao.findOne(example);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a golden resource a source and a match result, return the matching {@link MdmLink}, if it exists.
|
||||
* Given a golden resource a source and a match result, return the matching {@link IMdmLink}, if it exists.
|
||||
*
|
||||
* @param theGoldenResourcePid The Pid of the Golden Resource in the relationship
|
||||
* @param theSourcePid The Pid of the source in the relationship
|
||||
* @param theMatchResult The MatchResult you are looking for.
|
||||
* @return an Optional {@link MdmLink} containing the matched link if it exists.
|
||||
* @return an Optional {@link IMdmLink} containing the matched link if it exists.
|
||||
*/
|
||||
public Optional<MdmLink> getMdmLinksByGoldenResourcePidSourcePidAndMatchResult(Long theGoldenResourcePid,
|
||||
Long theSourcePid, MdmMatchResultEnum theMatchResult) {
|
||||
MdmLink exampleLink = myMdmLinkFactory.newMdmLink();
|
||||
exampleLink.setGoldenResourcePid(theGoldenResourcePid);
|
||||
exampleLink.setSourcePid(theSourcePid);
|
||||
public Optional<? extends IMdmLink> getMdmLinksByGoldenResourcePidSourcePidAndMatchResult(Long theGoldenResourcePid,
|
||||
Long theSourcePid, MdmMatchResultEnum theMatchResult) {
|
||||
return getMdmLinksByGoldenResourcePidSourcePidAndMatchResult(new ResourcePersistentId(theGoldenResourcePid), new ResourcePersistentId(theSourcePid), theMatchResult);
|
||||
}
|
||||
|
||||
public Optional<? extends IMdmLink> getMdmLinksByGoldenResourcePidSourcePidAndMatchResult(ResourcePersistentId theGoldenResourcePid,
|
||||
ResourcePersistentId theSourcePid, MdmMatchResultEnum theMatchResult) {
|
||||
IMdmLink exampleLink = myMdmLinkFactory.newMdmLink();
|
||||
exampleLink.setGoldenResourcePersistenceId(theGoldenResourcePid);
|
||||
exampleLink.setSourcePersistenceId(theSourcePid);
|
||||
exampleLink.setMatchResult(theMatchResult);
|
||||
Example<MdmLink> example = Example.of(exampleLink);
|
||||
Example<? extends IMdmLink> example = Example.of(exampleLink);
|
||||
return myMdmLinkDao.findOne(example);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all {@link MdmLink} which have {@link MdmMatchResultEnum#POSSIBLE_DUPLICATE} as their match result.
|
||||
* Get all {@link IMdmLink} which have {@link MdmMatchResultEnum#POSSIBLE_DUPLICATE} as their match result.
|
||||
*
|
||||
* @return A list of {@link MdmLink} that hold potential duplicate golden resources.
|
||||
* @return A list of {@link IMdmLink} that hold potential duplicate golden resources.
|
||||
*/
|
||||
public List<MdmLink> getPossibleDuplicates() {
|
||||
MdmLink exampleLink = myMdmLinkFactory.newMdmLink();
|
||||
public List<? extends IMdmLink> getPossibleDuplicates() {
|
||||
IMdmLink exampleLink = myMdmLinkFactory.newMdmLink();
|
||||
exampleLink.setMatchResult(MdmMatchResultEnum.POSSIBLE_DUPLICATE);
|
||||
Example<MdmLink> example = Example.of(exampleLink);
|
||||
Example<? extends IMdmLink> example = Example.of(exampleLink);
|
||||
return myMdmLinkDao.findAll(example);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Optional<MdmLink> findMdmLinkBySource(IBaseResource theSourceResource) {
|
||||
@Nullable Long pid = myJpaIdHelperService.getPidOrNull(theSourceResource);
|
||||
public Optional<? extends IMdmLink> findMdmLinkBySource(IBaseResource theSourceResource) {
|
||||
@Nullable ResourcePersistentId pid = myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), theSourceResource);
|
||||
if (pid == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
MdmLink exampleLink = myMdmLinkFactory.newMdmLink().setSourcePid(pid);
|
||||
Example<MdmLink> example = Example.of(exampleLink);
|
||||
IMdmLink exampleLink = myMdmLinkFactory.newMdmLink();
|
||||
exampleLink.setSourcePersistenceId(pid);
|
||||
Example<? extends IMdmLink> example = Example.of(exampleLink);
|
||||
return myMdmLinkDao.findOne(example);
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* Delete a given {@link MdmLink}. Note that this does not clear out the Golden resource.
|
||||
* Delete a given {@link IMdmLink}. Note that this does not clear out the Golden resource.
|
||||
* It is a simple entity delete.
|
||||
*
|
||||
* @param theMdmLink the {@link MdmLink} to delete.
|
||||
* @param theMdmLink the {@link IMdmLink} to delete.
|
||||
*/
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public void deleteLink(MdmLink theMdmLink) {
|
||||
public void deleteLink(IMdmLink theMdmLink) {
|
||||
myMdmLinkDao.validateMdmLink(theMdmLink);
|
||||
myMdmLinkDao.delete(theMdmLink);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a Golden Resource, return all links in which they are the source Golden Resource of the {@link MdmLink}
|
||||
* Given a Golden Resource, return all links in which they are the source Golden Resource of the {@link IMdmLink}
|
||||
*
|
||||
* @param theGoldenResource The {@link IBaseResource} Golden Resource who's links you would like to retrieve.
|
||||
* @return A list of all {@link MdmLink} entities in which theGoldenResource is the source Golden Resource
|
||||
* @return A list of all {@link IMdmLink} entities in which theGoldenResource is the source Golden Resource
|
||||
*/
|
||||
@Transactional
|
||||
public List<MdmLink> findMdmLinksByGoldenResource(IBaseResource theGoldenResource) {
|
||||
Long pid = myJpaIdHelperService.getPidOrNull(theGoldenResource);
|
||||
public List<? extends IMdmLink> findMdmLinksByGoldenResource(IBaseResource theGoldenResource) {
|
||||
ResourcePersistentId pid = myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), theGoldenResource);
|
||||
if (pid == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
MdmLink exampleLink = myMdmLinkFactory.newMdmLink().setGoldenResourcePid(pid);
|
||||
Example<MdmLink> example = Example.of(exampleLink);
|
||||
IMdmLink exampleLink = myMdmLinkFactory.newMdmLink();
|
||||
exampleLink.setGoldenResourcePersistenceId(pid);
|
||||
Example<? extends IMdmLink> example = Example.of(exampleLink);
|
||||
return myMdmLinkDao.findAll(example);
|
||||
}
|
||||
|
||||
|
@ -259,14 +274,15 @@ public class MdmLinkDaoSvc {
|
|||
* Persist an MDM link to the database.
|
||||
*
|
||||
* @param theMdmLink the link to save.
|
||||
* @return the persisted {@link MdmLink} entity.
|
||||
* @return the persisted {@link IMdmLink} entity.
|
||||
*/
|
||||
public MdmLink save(MdmLink theMdmLink) {
|
||||
if (theMdmLink.getCreated() == null) {
|
||||
theMdmLink.setCreated(new Date());
|
||||
public IMdmLink save(IMdmLink theMdmLink) {
|
||||
IMdmLink mdmLink = myMdmLinkDao.validateMdmLink(theMdmLink);
|
||||
if (mdmLink.getCreated() == null) {
|
||||
mdmLink.setCreated(new Date());
|
||||
}
|
||||
theMdmLink.setUpdated(new Date());
|
||||
return myMdmLinkDao.save(theMdmLink);
|
||||
mdmLink.setUpdated(new Date());
|
||||
return myMdmLinkDao.save(mdmLink);
|
||||
}
|
||||
|
||||
|
||||
|
@ -279,84 +295,47 @@ public class MdmLinkDaoSvc {
|
|||
* @param theLinkSource the {@link MdmLinkSourceEnum} being searched.
|
||||
* @param thePageRequest the {@link MdmPageRequest} paging information
|
||||
* @param thePartitionId List of partitions ID being searched, where the link's partition must be in the list.
|
||||
* @return a list of {@link MdmLink} entities which match the example.
|
||||
* @return a list of {@link IMdmLink} entities which match the example.
|
||||
*/
|
||||
public PageImpl<MdmLink> executeTypedQuery(IIdType theGoldenResourceId, IIdType theSourceId, MdmMatchResultEnum theMatchResult, MdmLinkSourceEnum theLinkSource, MdmPageRequest thePageRequest, List<Integer> thePartitionId) {
|
||||
CriteriaBuilder criteriaBuilder = myEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<MdmLink> criteriaQuery = criteriaBuilder.createQuery(MdmLink.class);
|
||||
Root<MdmLink> from = criteriaQuery.from(MdmLink.class);
|
||||
|
||||
List<Predicate> andPredicates = new ArrayList<>();
|
||||
|
||||
if (theGoldenResourceId != null) {
|
||||
Predicate goldenResourcePredicate = criteriaBuilder.equal(from.get("myGoldenResourcePid").as(Long.class), myJpaIdHelperService.getPidOrThrowException(theGoldenResourceId));
|
||||
andPredicates.add(goldenResourcePredicate);
|
||||
}
|
||||
if (theSourceId != null) {
|
||||
Predicate sourceIdPredicate = criteriaBuilder.equal(from.get("mySourcePid").as(Long.class), myJpaIdHelperService.getPidOrThrowException(theSourceId));
|
||||
andPredicates.add(sourceIdPredicate);
|
||||
}
|
||||
if (theMatchResult != null) {
|
||||
Predicate matchResultPredicate = criteriaBuilder.equal(from.get("myMatchResult").as(MdmMatchResultEnum.class), theMatchResult);
|
||||
andPredicates.add(matchResultPredicate);
|
||||
}
|
||||
if (theLinkSource != null) {
|
||||
Predicate linkSourcePredicate = criteriaBuilder.equal(from.get("myLinkSource").as(MdmLinkSourceEnum.class), theLinkSource);
|
||||
andPredicates.add(linkSourcePredicate);
|
||||
}
|
||||
if (!CollectionUtils.isEmpty(thePartitionId)) {
|
||||
Expression<Integer> exp = from.get("myPartitionId").get("myPartitionId").as(Integer.class);
|
||||
Predicate linkSourcePredicate = exp.in(thePartitionId);
|
||||
andPredicates.add(linkSourcePredicate);
|
||||
}
|
||||
|
||||
Predicate finalQuery = criteriaBuilder.and(andPredicates.toArray(new Predicate[0]));
|
||||
TypedQuery<MdmLink> typedQuery = myEntityManager.createQuery(criteriaQuery.where(finalQuery));
|
||||
|
||||
CriteriaQuery<Long> countQuery = criteriaBuilder.createQuery(Long.class);
|
||||
countQuery.select(criteriaBuilder.count(countQuery.from(MdmLink.class)))
|
||||
.where(finalQuery);
|
||||
|
||||
Long totalResults = myEntityManager.createQuery(countQuery).getSingleResult();
|
||||
|
||||
return new PageImpl<>(typedQuery.setFirstResult(thePageRequest.getOffset()).setMaxResults(thePageRequest.getCount()).getResultList(),
|
||||
PageRequest.of(thePageRequest.getPage(), thePageRequest.getCount()),
|
||||
totalResults);
|
||||
public Page<? extends IMdmLink> executeTypedQuery(IIdType theGoldenResourceId, IIdType theSourceId, MdmMatchResultEnum theMatchResult, MdmLinkSourceEnum theLinkSource, MdmPageRequest thePageRequest, List<Integer> thePartitionId) {
|
||||
return myMdmLinkDao.search(theGoldenResourceId, theSourceId, theMatchResult, theLinkSource, thePageRequest, thePartitionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a source {@link IBaseResource}, return all {@link MdmLink} entities in which this source is the source
|
||||
* Given a source {@link IBaseResource}, return all {@link IMdmLink} entities in which this source is the source
|
||||
* of the relationship. This will show you all links for a given Patient/Practitioner.
|
||||
*
|
||||
* @param theSourceResource the source resource to find links for.
|
||||
* @return all links for the source.
|
||||
*/
|
||||
@Transactional
|
||||
public List<MdmLink> findMdmLinksBySourceResource(IBaseResource theSourceResource) {
|
||||
Long pid = myJpaIdHelperService.getPidOrNull(theSourceResource);
|
||||
public List<? extends IMdmLink> findMdmLinksBySourceResource(IBaseResource theSourceResource) {
|
||||
ResourcePersistentId pid = myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), theSourceResource);
|
||||
if (pid == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
MdmLink exampleLink = myMdmLinkFactory.newMdmLink().setSourcePid(pid);
|
||||
Example<MdmLink> example = Example.of(exampleLink);
|
||||
IMdmLink exampleLink = myMdmLinkFactory.newMdmLink();
|
||||
exampleLink.setSourcePersistenceId(pid);
|
||||
Example<? extends IMdmLink> example = Example.of(exampleLink);
|
||||
return myMdmLinkDao.findAll(example);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all {@link MdmLink} entities in which theGoldenResource's PID is the source
|
||||
* Finds all {@link IMdmLink} entities in which theGoldenResource's PID is the source
|
||||
* of the relationship.
|
||||
*
|
||||
* @param theGoldenResource the source resource to find links for.
|
||||
* @return all links for the source.
|
||||
*/
|
||||
public List<MdmLink> findMdmMatchLinksByGoldenResource(IBaseResource theGoldenResource) {
|
||||
Long pid = myJpaIdHelperService.getPidOrNull(theGoldenResource);
|
||||
public List<? extends IMdmLink> findMdmMatchLinksByGoldenResource(IBaseResource theGoldenResource) {
|
||||
ResourcePersistentId pid = myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), theGoldenResource);
|
||||
if (pid == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
MdmLink exampleLink = myMdmLinkFactory.newMdmLink().setGoldenResourcePid(pid);
|
||||
IMdmLink exampleLink = myMdmLinkFactory.newMdmLink();
|
||||
exampleLink.setGoldenResourcePersistenceId(pid);
|
||||
exampleLink.setMatchResult(MdmMatchResultEnum.MATCH);
|
||||
Example<MdmLink> example = Example.of(exampleLink);
|
||||
Example<? extends IMdmLink> example = Example.of(exampleLink);
|
||||
return myMdmLinkDao.findAll(example);
|
||||
}
|
||||
|
||||
|
@ -364,37 +343,32 @@ public class MdmLinkDaoSvc {
|
|||
* Factory delegation method, whenever you need a new MdmLink, use this factory method.
|
||||
* //TODO Should we make the constructor private for MdmLink? or work out some way to ensure they can only be instantiated via factory.
|
||||
*
|
||||
* @return A new {@link MdmLink}.
|
||||
* @return A new {@link IMdmLink}.
|
||||
*/
|
||||
public MdmLink newMdmLink() {
|
||||
public IMdmLink newMdmLink() {
|
||||
return myMdmLinkFactory.newMdmLink();
|
||||
}
|
||||
|
||||
public Optional<MdmLink> getMatchedOrPossibleMatchedLinkForSource(IAnyResource theResource) {
|
||||
public Optional<? extends IMdmLink> getMatchedOrPossibleMatchedLinkForSource(IAnyResource theResource) {
|
||||
// TODO KHS instead of two queries, just do one query with an OR
|
||||
Optional<MdmLink> retval = getMatchedLinkForSource(theResource);
|
||||
Optional<? extends IMdmLink> retval = getMatchedLinkForSource(theResource);
|
||||
if (!retval.isPresent()) {
|
||||
retval = getPossibleMatchedLinkForSource(theResource);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
public Optional<MdmLink> getLinkByGoldenResourceAndSourceResource(@Nullable IAnyResource theGoldenResource, @Nullable IAnyResource theSourceResource) {
|
||||
public Optional<? extends IMdmLink> getLinkByGoldenResourceAndSourceResource(@Nullable IAnyResource theGoldenResource, @Nullable IAnyResource theSourceResource) {
|
||||
if (theGoldenResource == null || theSourceResource == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return getLinkByGoldenResourcePidAndSourceResourcePid(
|
||||
myJpaIdHelperService.getPidOrNull(theGoldenResource),
|
||||
myJpaIdHelperService.getPidOrNull(theSourceResource));
|
||||
myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), theGoldenResource),
|
||||
myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), theSourceResource));
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.MANDATORY)
|
||||
public void deleteLinksWithAnyReferenceToPids(List<Long> theGoldenResourcePids) {
|
||||
// Split into chunks of 500 so older versions of Oracle don't run into issues (500 = 1000 / 2 since the dao
|
||||
// method uses the list twice in the sql predicate)
|
||||
List<List<Long>> chunks = ListUtils.partition(theGoldenResourcePids, 500);
|
||||
for (List<Long> chunk : chunks) {
|
||||
myMdmLinkDao.deleteLinksWithAnyReferenceToPids(chunk);
|
||||
}
|
||||
public void deleteLinksWithAnyReferenceToPids(List<ResourcePersistentId> theGoldenResourcePids) {
|
||||
myMdmLinkDao.deleteLinksWithAnyReferenceToPids(theGoldenResourcePids);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,8 @@ package ca.uhn.fhir.jpa.mdm.interceptor;
|
|||
|
||||
import ca.uhn.fhir.interceptor.api.IInterceptorService;
|
||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.interceptor.MdmSearchExpandingInterceptor;
|
||||
import ca.uhn.fhir.mdm.interceptor.IMdmStorageInterceptor;
|
||||
import ca.uhn.fhir.mdm.interceptor.MdmSearchExpandingInterceptor;
|
||||
import ca.uhn.fhir.jpa.subscription.submit.interceptor.SubscriptionSubmitInterceptorLoader;
|
||||
import ca.uhn.fhir.mdm.api.IMdmSettings;
|
||||
import ca.uhn.fhir.mdm.log.Logs;
|
||||
|
|
|
@ -21,11 +21,13 @@ package ca.uhn.fhir.jpa.mdm.svc;
|
|||
*/
|
||||
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.jpa.dao.index.IJpaIdHelperService;
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
||||
import ca.uhn.fhir.jpa.dao.index.IdHelperService;
|
||||
import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc;
|
||||
import ca.uhn.fhir.jpa.mdm.util.MdmPartitionHelper;
|
||||
import ca.uhn.fhir.mdm.api.IGoldenResourceMergerSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLink;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLinkSvc;
|
||||
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||
|
@ -33,9 +35,11 @@ import ca.uhn.fhir.mdm.log.Logs;
|
|||
import ca.uhn.fhir.mdm.model.MdmTransactionContext;
|
||||
import ca.uhn.fhir.mdm.util.GoldenResourceHelper;
|
||||
import ca.uhn.fhir.mdm.util.MdmResourceUtil;
|
||||
import ca.uhn.fhir.mdm.util.MessageHelper;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.slf4j.Logger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
@ -57,19 +61,15 @@ public class GoldenResourceMergerSvcImpl implements IGoldenResourceMergerSvc {
|
|||
@Autowired
|
||||
IMdmLinkSvc myMdmLinkSvc;
|
||||
@Autowired
|
||||
IJpaIdHelperService myIdHelperService;
|
||||
IIdHelperService myIdHelperService;
|
||||
@Autowired
|
||||
MdmResourceDaoSvc myMdmResourceDaoSvc;
|
||||
@Autowired
|
||||
MessageHelper myMessageHelper;
|
||||
@Autowired
|
||||
MdmPartitionHelper myMdmPartitionHelper;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public IAnyResource mergeGoldenResources(IAnyResource theFromGoldenResource, IAnyResource theMergedResource, IAnyResource theToGoldenResource, MdmTransactionContext theMdmTransactionContext) {
|
||||
Long fromGoldenResourcePid = myIdHelperService.getPidOrThrowException(theFromGoldenResource);
|
||||
Long toGoldenResourcePid = myIdHelperService.getPidOrThrowException(theToGoldenResource);
|
||||
String resourceType = theMdmTransactionContext.getResourceType();
|
||||
|
||||
if (theMergedResource != null) {
|
||||
|
@ -92,10 +92,10 @@ public class GoldenResourceMergerSvcImpl implements IGoldenResourceMergerSvc {
|
|||
myMdmPartitionHelper.validateResourcesInSamePartition(theFromGoldenResource, theToGoldenResource);
|
||||
|
||||
//Merge the links from the FROM to the TO resource. Clean up dangling links.
|
||||
mergeGoldenResourceLinks(theFromGoldenResource, theToGoldenResource, toGoldenResourcePid, theMdmTransactionContext);
|
||||
mergeGoldenResourceLinks(theFromGoldenResource, theToGoldenResource, theFromGoldenResource.getIdElement(), theMdmTransactionContext);
|
||||
|
||||
//Create the new REDIRECT link
|
||||
addMergeLink(toGoldenResourcePid, fromGoldenResourcePid, resourceType);
|
||||
addMergeLink(theToGoldenResource, theFromGoldenResource, resourceType);
|
||||
|
||||
//Strip the golden resource tag from the now-deprecated resource.
|
||||
myMdmResourceDaoSvc.removeGoldenResourceTag(theFromGoldenResource, resourceType);
|
||||
|
@ -111,9 +111,9 @@ public class GoldenResourceMergerSvcImpl implements IGoldenResourceMergerSvc {
|
|||
return theToGoldenResource;
|
||||
}
|
||||
|
||||
private void addMergeLink(Long theGoldenResourcePidAkaActive, Long theTargetResourcePidAkaDeactivated, String theResourceType) {
|
||||
MdmLink mdmLink = myMdmLinkDaoSvc
|
||||
.getOrCreateMdmLinkByGoldenResourcePidAndSourceResourcePid(theGoldenResourcePidAkaActive, theTargetResourcePidAkaDeactivated);
|
||||
private void addMergeLink(IAnyResource theGoldenResource, IAnyResource theTargetResource, String theResourceType) {
|
||||
IMdmLink mdmLink = myMdmLinkDaoSvc
|
||||
.getOrCreateMdmLinkByGoldenResourceAndSourceResource(theGoldenResource, theTargetResource);
|
||||
|
||||
mdmLink
|
||||
.setMdmSourceType(theResourceType)
|
||||
|
@ -137,17 +137,18 @@ public class GoldenResourceMergerSvcImpl implements IGoldenResourceMergerSvc {
|
|||
* @param theToResourcePid
|
||||
* @param theMdmTransactionContext
|
||||
*/
|
||||
private void mergeGoldenResourceLinks(IAnyResource theFromResource, IAnyResource theToResource, Long theToResourcePid, MdmTransactionContext theMdmTransactionContext) {
|
||||
List<MdmLink> fromLinks = myMdmLinkDaoSvc.findMdmLinksByGoldenResource(theFromResource); // fromLinks - links going to theFromResource
|
||||
List<MdmLink> toLinks = myMdmLinkDaoSvc.findMdmLinksByGoldenResource(theToResource); // toLinks - links going to theToResource
|
||||
List<MdmLink> toDelete = new ArrayList<>();
|
||||
private void mergeGoldenResourceLinks(IAnyResource theFromResource, IAnyResource theToResource, IIdType theToResourcePid, MdmTransactionContext theMdmTransactionContext) {
|
||||
List<? extends IMdmLink> fromLinks = myMdmLinkDaoSvc.findMdmLinksByGoldenResource(theFromResource); // fromLinks - links going to theFromResource
|
||||
List<? extends IMdmLink> toLinks = myMdmLinkDaoSvc.findMdmLinksByGoldenResource(theToResource); // toLinks - links going to theToResource
|
||||
List<IMdmLink> toDelete = new ArrayList<>();
|
||||
ResourcePersistentId goldenResourcePid = myIdHelperService.resolveResourcePersistentIds((RequestPartitionId) theToResource.getUserData(Constants.RESOURCE_PARTITION_ID), theToResource.getIdElement().getResourceType(), theToResource.getIdElement().getIdPart());
|
||||
|
||||
for (MdmLink fromLink : fromLinks) {
|
||||
Optional<MdmLink> optionalToLink = findFirstLinkWithMatchingSource(toLinks, fromLink);
|
||||
for (IMdmLink fromLink : fromLinks) {
|
||||
Optional<? extends IMdmLink> optionalToLink = findFirstLinkWithMatchingSource(toLinks, fromLink);
|
||||
if (optionalToLink.isPresent()) {
|
||||
|
||||
// The original links already contain this target, so move it over to the toResource
|
||||
MdmLink toLink = optionalToLink.get();
|
||||
IMdmLink toLink = optionalToLink.get();
|
||||
if (fromLink.isManual()) {
|
||||
switch (toLink.getLinkSource()) {
|
||||
case AUTO:
|
||||
|
@ -167,7 +168,7 @@ public class GoldenResourceMergerSvcImpl implements IGoldenResourceMergerSvc {
|
|||
}
|
||||
}
|
||||
//2 The original TO links didn't contain this target, so move it over to the toGoldenResource
|
||||
fromLink.setGoldenResourcePid(theToResourcePid);
|
||||
fromLink.setGoldenResourcePersistenceId(goldenResourcePid);
|
||||
ourLog.trace("Saving link {}", fromLink);
|
||||
myMdmLinkDaoSvc.save(fromLink);
|
||||
}
|
||||
|
@ -175,9 +176,9 @@ public class GoldenResourceMergerSvcImpl implements IGoldenResourceMergerSvc {
|
|||
toDelete.forEach(link -> myMdmLinkDaoSvc.deleteLink(link));
|
||||
}
|
||||
|
||||
private Optional<MdmLink> findFirstLinkWithMatchingSource(List<MdmLink> theMdmLinks, MdmLink theLinkWithSourceToMatch) {
|
||||
private Optional<? extends IMdmLink> findFirstLinkWithMatchingSource(List<? extends IMdmLink> theMdmLinks, IMdmLink theLinkWithSourceToMatch) {
|
||||
return theMdmLinks.stream()
|
||||
.filter(mdmLink -> mdmLink.getSourcePid().equals(theLinkWithSourceToMatch.getSourcePid()))
|
||||
.filter(mdmLink -> mdmLink.getSourcePersistenceId().equals(theLinkWithSourceToMatch.getSourcePersistenceId()))
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.mdm.svc;
|
|||
*/
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLink;
|
||||
import ca.uhn.fhir.mdm.api.MdmLinkJson;
|
||||
|
||||
/**
|
||||
|
@ -34,6 +35,6 @@ public interface IMdmModelConverterSvc {
|
|||
* @param theLink Link to convert
|
||||
* @return Returns the converted link
|
||||
*/
|
||||
public MdmLinkJson toJson(MdmLink theLink);
|
||||
public MdmLinkJson toJson(IMdmLink theLink);
|
||||
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import ca.uhn.fhir.jpa.entity.MdmLink;
|
|||
import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc;
|
||||
import ca.uhn.fhir.jpa.mdm.svc.candidate.MatchedGoldenResourceCandidate;
|
||||
import ca.uhn.fhir.jpa.mdm.svc.candidate.MdmGoldenResourceFindingSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLink;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLinkSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmSettings;
|
||||
import ca.uhn.fhir.mdm.api.IMdmSurvivorshipService;
|
||||
|
@ -110,8 +111,8 @@ public class MdmEidUpdateService {
|
|||
}
|
||||
}
|
||||
|
||||
private boolean candidateIsSameAsMdmLinkGoldenResource(MdmLink theExistingMatchLink, MatchedGoldenResourceCandidate theGoldenResourceCandidate) {
|
||||
return theExistingMatchLink.getGoldenResourcePid().equals(theGoldenResourceCandidate.getCandidateGoldenResourcePid().getIdAsLong());
|
||||
private boolean candidateIsSameAsMdmLinkGoldenResource(IMdmLink theExistingMatchLink, MatchedGoldenResourceCandidate theGoldenResourceCandidate) {
|
||||
return theExistingMatchLink.getGoldenResourcePersistenceId().equals(theGoldenResourceCandidate.getCandidateGoldenResourcePid());
|
||||
}
|
||||
|
||||
private void createNewGoldenResourceAndFlagAsDuplicate(IAnyResource theResource, MdmTransactionContext theMdmTransactionContext, IAnyResource theOldGoldenResource) {
|
||||
|
@ -162,13 +163,13 @@ public class MdmEidUpdateService {
|
|||
myHasEidsInCommon = myEIDHelper.hasEidOverlap(myMatchedGoldenResource, theResource);
|
||||
myIncomingResourceHasAnEid = !myEIDHelper.getExternalEid(theResource).isEmpty();
|
||||
|
||||
Optional<MdmLink> theExistingMatchOrPossibleMatchLink = myMdmLinkDaoSvc.getMatchedOrPossibleMatchedLinkForSource(theResource);
|
||||
Optional<? extends IMdmLink> theExistingMatchOrPossibleMatchLink = myMdmLinkDaoSvc.getMatchedOrPossibleMatchedLinkForSource(theResource);
|
||||
myExistingGoldenResource = null;
|
||||
|
||||
if (theExistingMatchOrPossibleMatchLink.isPresent()) {
|
||||
MdmLink mdmLink = theExistingMatchOrPossibleMatchLink.get();
|
||||
Long existingGoldenResourcePid = mdmLink.getGoldenResourcePid();
|
||||
myExistingGoldenResource = myMdmResourceDaoSvc.readGoldenResourceByPid(new ResourcePersistentId(existingGoldenResourcePid), resourceType);
|
||||
IMdmLink mdmLink = theExistingMatchOrPossibleMatchLink.get();
|
||||
ResourcePersistentId existingGoldenResourcePid = mdmLink.getGoldenResourcePersistenceId();
|
||||
myExistingGoldenResource = myMdmResourceDaoSvc.readGoldenResourceByPid(existingGoldenResourcePid, resourceType);
|
||||
myRemainsMatchedToSameGoldenResource = candidateIsSameAsMdmLinkGoldenResource(mdmLink, theMatchedGoldenResourceCandidate);
|
||||
} else {
|
||||
myRemainsMatchedToSameGoldenResource = false;
|
||||
|
|
|
@ -21,14 +21,13 @@ package ca.uhn.fhir.jpa.mdm.svc;
|
|||
*/
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.dao.index.IdHelperService;
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.jpa.dao.index.IJpaIdHelperService;
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
||||
import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc;
|
||||
import ca.uhn.fhir.jpa.mdm.util.MdmPartitionHelper;
|
||||
import ca.uhn.fhir.jpa.model.entity.PartitionablePartitionId;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLink;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLinkCreateSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmSettings;
|
||||
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
||||
|
@ -38,6 +37,7 @@ 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.api.Constants;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -54,7 +54,7 @@ public class MdmLinkCreateSvcImpl implements IMdmLinkCreateSvc {
|
|||
@Autowired
|
||||
FhirContext myFhirContext;
|
||||
@Autowired
|
||||
IJpaIdHelperService myIdHelperService;
|
||||
IIdHelperService myIdHelperService;
|
||||
@Autowired
|
||||
MdmLinkDaoSvc myMdmLinkDaoSvc;
|
||||
@Autowired
|
||||
|
@ -71,23 +71,23 @@ public class MdmLinkCreateSvcImpl implements IMdmLinkCreateSvc {
|
|||
|
||||
validateCreateLinkRequest(theGoldenResource, theSourceResource, sourceType);
|
||||
|
||||
Long goldenResourceId = myIdHelperService.getPidOrThrowException(theGoldenResource);
|
||||
Long targetId = myIdHelperService.getPidOrThrowException(theSourceResource);
|
||||
ResourcePersistentId goldenResourceId = myIdHelperService.getPidOrThrowException(theGoldenResource);
|
||||
ResourcePersistentId targetId = myIdHelperService.getPidOrThrowException(theSourceResource);
|
||||
|
||||
// check if the golden resource and the source resource are in the same partition, throw error if not
|
||||
myMdmPartitionHelper.validateResourcesInSamePartition(theGoldenResource, theSourceResource);
|
||||
|
||||
Optional<MdmLink> optionalMdmLink = myMdmLinkDaoSvc.getLinkByGoldenResourcePidAndSourceResourcePid(goldenResourceId, targetId);
|
||||
Optional<? extends IMdmLink> optionalMdmLink = myMdmLinkDaoSvc.getLinkByGoldenResourcePidAndSourceResourcePid(goldenResourceId, targetId);
|
||||
if (optionalMdmLink.isPresent()) {
|
||||
throw new InvalidRequestException(Msg.code(753) + myMessageHelper.getMessageForPresentLink(theGoldenResource, theSourceResource));
|
||||
}
|
||||
|
||||
List<MdmLink> mdmLinks = myMdmLinkDaoSvc.getMdmLinksBySourcePidAndMatchResult(targetId, MdmMatchResultEnum.MATCH);
|
||||
List<? extends IMdmLink> mdmLinks = myMdmLinkDaoSvc.getMdmLinksBySourcePidAndMatchResult(targetId, MdmMatchResultEnum.MATCH);
|
||||
if (mdmLinks.size() > 0 && theMatchResult == MdmMatchResultEnum.MATCH) {
|
||||
throw new InvalidRequestException(Msg.code(754) + myMessageHelper.getMessageForMultipleGoldenRecords(theSourceResource));
|
||||
}
|
||||
|
||||
MdmLink mdmLink = myMdmLinkDaoSvc.getOrCreateMdmLinkByGoldenResourcePidAndSourceResourcePid(goldenResourceId, targetId);
|
||||
IMdmLink mdmLink = myMdmLinkDaoSvc.getOrCreateMdmLinkByGoldenResourceAndSourceResource(theGoldenResource, theSourceResource);
|
||||
mdmLink.setLinkSource(MdmLinkSourceEnum.MANUAL);
|
||||
if (theMatchResult == null) {
|
||||
mdmLink.setMatchResult(MdmMatchResultEnum.MATCH);
|
||||
|
|
|
@ -20,8 +20,8 @@ package ca.uhn.fhir.jpa.mdm.svc;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLink;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLinkQuerySvc;
|
||||
import ca.uhn.fhir.mdm.api.MdmLinkJson;
|
||||
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
||||
|
@ -57,7 +57,7 @@ public class MdmLinkQuerySvcImplSvc implements IMdmLinkQuerySvc {
|
|||
@Override
|
||||
@Transactional
|
||||
public Page<MdmLinkJson> queryLinks(IIdType theGoldenResourceId, IIdType theSourceResourceId, MdmMatchResultEnum theMatchResult, MdmLinkSourceEnum theLinkSource, MdmTransactionContext theMdmContext, MdmPageRequest thePageRequest, List<Integer> thePartitionId) {
|
||||
Page<MdmLink> mdmLinks = myMdmLinkDaoSvc.executeTypedQuery(theGoldenResourceId, theSourceResourceId, theMatchResult, theLinkSource, thePageRequest, thePartitionId);
|
||||
Page<? extends IMdmLink> mdmLinks = myMdmLinkDaoSvc.executeTypedQuery(theGoldenResourceId, theSourceResourceId, theMatchResult, theLinkSource, thePageRequest, thePartitionId);
|
||||
return mdmLinks.map(myMdmModelConverterSvc::toJson);
|
||||
}
|
||||
|
||||
|
@ -70,7 +70,7 @@ public class MdmLinkQuerySvcImplSvc implements IMdmLinkQuerySvc {
|
|||
@Override
|
||||
@Transactional
|
||||
public Page<MdmLinkJson> getDuplicateGoldenResources(MdmTransactionContext theMdmContext, MdmPageRequest thePageRequest, List<Integer> thePartitionId) {
|
||||
Page<MdmLink> mdmLinkPage = myMdmLinkDaoSvc.executeTypedQuery(null, null, MdmMatchResultEnum.POSSIBLE_DUPLICATE, null, thePageRequest, thePartitionId);
|
||||
Page<? extends IMdmLink> mdmLinkPage = myMdmLinkDaoSvc.executeTypedQuery(null, null, MdmMatchResultEnum.POSSIBLE_DUPLICATE, null, thePageRequest, thePartitionId);
|
||||
return mdmLinkPage.map(myMdmModelConverterSvc::toJson);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,9 +21,10 @@ package ca.uhn.fhir.jpa.mdm.svc;
|
|||
*/
|
||||
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.jpa.dao.index.IJpaIdHelperService;
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
||||
import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLink;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLinkSvc;
|
||||
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchOutcome;
|
||||
|
@ -33,7 +34,6 @@ import ca.uhn.fhir.mdm.model.MdmTransactionContext;
|
|||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.slf4j.Logger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
@ -57,7 +57,7 @@ public class MdmLinkSvcImpl implements IMdmLinkSvc {
|
|||
@Autowired
|
||||
private MdmLinkDaoSvc myMdmLinkDaoSvc;
|
||||
@Autowired
|
||||
private IJpaIdHelperService myIdHelperService;
|
||||
private IIdHelperService myIdHelperService;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
|
@ -74,13 +74,13 @@ public class MdmLinkSvcImpl implements IMdmLinkSvc {
|
|||
validateRequestIsLegal(theGoldenResource, theSourceResource, matchResultEnum, theLinkSource);
|
||||
|
||||
myMdmResourceDaoSvc.upsertGoldenResource(theGoldenResource, theMdmTransactionContext.getResourceType());
|
||||
MdmLink link = createOrUpdateLinkEntity(theGoldenResource, theSourceResource, theMatchOutcome, theLinkSource, theMdmTransactionContext);
|
||||
IMdmLink link = createOrUpdateLinkEntity(theGoldenResource, theSourceResource, theMatchOutcome, theLinkSource, theMdmTransactionContext);
|
||||
theMdmTransactionContext.addMdmLink(link);
|
||||
}
|
||||
|
||||
private boolean goldenResourceLinkedAsNoMatch(IAnyResource theGoldenResource, IAnyResource theSourceResource) {
|
||||
Long goldenResourceId = myIdHelperService.getPidOrThrowException(theGoldenResource);
|
||||
Long sourceId = myIdHelperService.getPidOrThrowException(theSourceResource);
|
||||
ResourcePersistentId goldenResourceId = myIdHelperService.getPidOrThrowException(theGoldenResource);
|
||||
ResourcePersistentId sourceId = myIdHelperService.getPidOrThrowException(theSourceResource);
|
||||
// TODO perf collapse into one query
|
||||
return myMdmLinkDaoSvc.getMdmLinksByGoldenResourcePidSourcePidAndMatchResult(goldenResourceId, sourceId, MdmMatchResultEnum.NO_MATCH).isPresent() ||
|
||||
myMdmLinkDaoSvc.getMdmLinksByGoldenResourcePidSourcePidAndMatchResult(sourceId, goldenResourceId, MdmMatchResultEnum.NO_MATCH).isPresent();
|
||||
|
@ -91,9 +91,9 @@ public class MdmLinkSvcImpl implements IMdmLinkSvc {
|
|||
if (theGoldenResource == null) {
|
||||
return;
|
||||
}
|
||||
Optional<MdmLink> optionalMdmLink = getMdmLinkForGoldenResourceSourceResourcePair(theGoldenResource, theSourceResource);
|
||||
Optional<? extends IMdmLink> optionalMdmLink = getMdmLinkForGoldenResourceSourceResourcePair(theGoldenResource, theSourceResource);
|
||||
if (optionalMdmLink.isPresent()) {
|
||||
MdmLink mdmLink = optionalMdmLink.get();
|
||||
IMdmLink mdmLink = optionalMdmLink.get();
|
||||
log(theMdmTransactionContext, "Deleting MdmLink [" + theGoldenResource.getIdElement().toVersionless() + " -> " + theSourceResource.getIdElement().toVersionless() + "] with result: " + mdmLink.getMatchResult());
|
||||
myMdmLinkDaoSvc.deleteLink(mdmLink);
|
||||
theMdmTransactionContext.addMdmLink(mdmLink);
|
||||
|
@ -103,15 +103,14 @@ public class MdmLinkSvcImpl implements IMdmLinkSvc {
|
|||
@Override
|
||||
@Transactional
|
||||
public void deleteLinksWithAnyReferenceTo(List<ResourcePersistentId> theGoldenResourceIds) {
|
||||
List<Long> goldenResourcePids = theGoldenResourceIds.stream().map(ResourcePersistentId::getIdAsLong).collect(Collectors.toList());
|
||||
myMdmLinkDaoSvc.deleteLinksWithAnyReferenceToPids(goldenResourcePids);
|
||||
myMdmLinkDaoSvc.deleteLinksWithAnyReferenceToPids(theGoldenResourceIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function which runs various business rules about what types of requests are allowed.
|
||||
*/
|
||||
private void validateRequestIsLegal(IAnyResource theGoldenResource, IAnyResource theResource, MdmMatchResultEnum theMatchResult, MdmLinkSourceEnum theLinkSource) {
|
||||
Optional<MdmLink> oExistingLink = getMdmLinkForGoldenResourceSourceResourcePair(theGoldenResource, theResource);
|
||||
Optional<? extends IMdmLink> oExistingLink = getMdmLinkForGoldenResourceSourceResourcePair(theGoldenResource, theResource);
|
||||
if (oExistingLink.isPresent() && systemIsAttemptingToModifyManualLink(theLinkSource, oExistingLink.get())) {
|
||||
throw new InternalErrorException(Msg.code(760) + "MDM system is not allowed to modify links on manually created links");
|
||||
}
|
||||
|
@ -131,19 +130,22 @@ public class MdmLinkSvcImpl implements IMdmLinkSvc {
|
|||
/**
|
||||
* Helper function to let us catch when System MDM rules are attempting to override a manually defined link.
|
||||
*/
|
||||
private boolean systemIsAttemptingToModifyManualLink(MdmLinkSourceEnum theIncomingSource, MdmLink theExistingSource) {
|
||||
private boolean systemIsAttemptingToModifyManualLink(MdmLinkSourceEnum theIncomingSource, IMdmLink theExistingSource) {
|
||||
return theIncomingSource == MdmLinkSourceEnum.AUTO && theExistingSource.isManual();
|
||||
}
|
||||
|
||||
private Optional<MdmLink> getMdmLinkForGoldenResourceSourceResourcePair(@Nonnull IAnyResource theGoldenResource, @Nonnull IAnyResource theCandidate) {
|
||||
private Optional<? extends IMdmLink> getMdmLinkForGoldenResourceSourceResourcePair(@Nonnull IAnyResource theGoldenResource, @Nonnull IAnyResource theCandidate) {
|
||||
if (theGoldenResource.getIdElement().getIdPart() == null || theCandidate.getIdElement().getIdPart() == null) {
|
||||
return Optional.empty();
|
||||
} else {
|
||||
return myMdmLinkDaoSvc.getLinkByGoldenResourceAndSourceResource(theGoldenResource, theCandidate);
|
||||
return myMdmLinkDaoSvc.getLinkByGoldenResourcePidAndSourceResourcePid(
|
||||
myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), theGoldenResource),
|
||||
myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), theCandidate)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private MdmLink createOrUpdateLinkEntity(IBaseResource theGoldenResource, IBaseResource theSourceResource, MdmMatchOutcome theMatchOutcome, MdmLinkSourceEnum theLinkSource, MdmTransactionContext theMdmTransactionContext) {
|
||||
private IMdmLink createOrUpdateLinkEntity(IAnyResource theGoldenResource, IAnyResource theSourceResource, MdmMatchOutcome theMatchOutcome, MdmLinkSourceEnum theLinkSource, MdmTransactionContext theMdmTransactionContext) {
|
||||
return myMdmLinkDaoSvc.createOrUpdateLinkEntity(theGoldenResource, theSourceResource, theMatchOutcome, theLinkSource, theMdmTransactionContext);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,15 +22,12 @@ package ca.uhn.fhir.jpa.mdm.svc;
|
|||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.dao.index.IdHelperService;
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
||||
import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc;
|
||||
import ca.uhn.fhir.jpa.mdm.util.MdmPartitionHelper;
|
||||
import ca.uhn.fhir.jpa.model.entity.PartitionablePartitionId;
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.jpa.dao.index.IJpaIdHelperService;
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLink;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLinkSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLinkUpdaterSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmSettings;
|
||||
|
@ -42,6 +39,7 @@ 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.api.Constants;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.provider.ProviderConstants;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
|
@ -59,7 +57,7 @@ public class MdmLinkUpdaterSvcImpl implements IMdmLinkUpdaterSvc {
|
|||
@Autowired
|
||||
FhirContext myFhirContext;
|
||||
@Autowired
|
||||
IJpaIdHelperService myIdHelperService;
|
||||
IIdHelperService myIdHelperService;
|
||||
@Autowired
|
||||
MdmLinkDaoSvc myMdmLinkDaoSvc;
|
||||
@Autowired
|
||||
|
@ -84,18 +82,18 @@ public class MdmLinkUpdaterSvcImpl implements IMdmLinkUpdaterSvc {
|
|||
|
||||
validateUpdateLinkRequest(theGoldenResource, theSourceResource, theMatchResult, sourceType);
|
||||
|
||||
Long goldenResourceId = myIdHelperService.getPidOrThrowException(theGoldenResource);
|
||||
Long targetId = myIdHelperService.getPidOrThrowException(theSourceResource);
|
||||
ResourcePersistentId goldenResourceId = myIdHelperService.getPidOrThrowException(theGoldenResource);
|
||||
ResourcePersistentId targetId = myIdHelperService.getPidOrThrowException(theSourceResource);
|
||||
|
||||
// check if the golden resource and the source resource are in the same partition, throw error if not
|
||||
myMdmPartitionHelper.validateResourcesInSamePartition(theGoldenResource, theSourceResource);
|
||||
|
||||
Optional<MdmLink> optionalMdmLink = myMdmLinkDaoSvc.getLinkByGoldenResourcePidAndSourceResourcePid(goldenResourceId, targetId);
|
||||
Optional<? extends IMdmLink> optionalMdmLink = myMdmLinkDaoSvc.getLinkByGoldenResourcePidAndSourceResourcePid(goldenResourceId, targetId);
|
||||
if (!optionalMdmLink.isPresent()) {
|
||||
throw new InvalidRequestException(Msg.code(738) + myMessageHelper.getMessageForNoLink(theGoldenResource, theSourceResource));
|
||||
}
|
||||
|
||||
MdmLink mdmLink = optionalMdmLink.get();
|
||||
IMdmLink mdmLink = optionalMdmLink.get();
|
||||
if (mdmLink.getMatchResult() == theMatchResult) {
|
||||
ourLog.warn("MDM Link for " + theGoldenResource.getIdElement().toVersionless() + ", " + theSourceResource.getIdElement().toVersionless() + " already has value " + theMatchResult + ". Nothing to do.");
|
||||
return theGoldenResource;
|
||||
|
@ -160,15 +158,15 @@ public class MdmLinkUpdaterSvcImpl implements IMdmLinkUpdaterSvc {
|
|||
public void notDuplicateGoldenResource(IAnyResource theGoldenResource, IAnyResource theTargetGoldenResource, MdmTransactionContext theMdmContext) {
|
||||
validateNotDuplicateGoldenResourceRequest(theGoldenResource, theTargetGoldenResource);
|
||||
|
||||
Long goldenResourceId = myIdHelperService.getPidOrThrowException(theGoldenResource);
|
||||
Long targetId = myIdHelperService.getPidOrThrowException(theTargetGoldenResource);
|
||||
ResourcePersistentId goldenResourceId = myIdHelperService.getPidOrThrowException(theGoldenResource);
|
||||
ResourcePersistentId targetId = myIdHelperService.getPidOrThrowException(theTargetGoldenResource);
|
||||
|
||||
Optional<MdmLink> oMdmLink = myMdmLinkDaoSvc.getLinkByGoldenResourcePidAndSourceResourcePid(goldenResourceId, targetId);
|
||||
Optional<? extends IMdmLink> oMdmLink = myMdmLinkDaoSvc.getLinkByGoldenResourcePidAndSourceResourcePid(goldenResourceId, targetId);
|
||||
if (!oMdmLink.isPresent()) {
|
||||
throw new InvalidRequestException(Msg.code(745) + "No link exists between " + theGoldenResource.getIdElement().toVersionless() + " and " + theTargetGoldenResource.getIdElement().toVersionless());
|
||||
}
|
||||
|
||||
MdmLink mdmLink = oMdmLink.get();
|
||||
IMdmLink mdmLink = oMdmLink.get();
|
||||
if (!mdmLink.isPossibleDuplicate()) {
|
||||
throw new InvalidRequestException(Msg.code(746) + theGoldenResource.getIdElement().toVersionless() + " and " + theTargetGoldenResource.getIdElement().toVersionless() + " are not linked as POSSIBLE_DUPLICATE.");
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ import ca.uhn.fhir.mdm.log.Logs;
|
|||
import ca.uhn.fhir.mdm.model.MdmTransactionContext;
|
||||
import ca.uhn.fhir.mdm.util.GoldenResourceHelper;
|
||||
import ca.uhn.fhir.mdm.util.MdmResourceUtil;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import ca.uhn.fhir.rest.server.TransactionLogMessages;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -92,9 +93,9 @@ public class MdmMatchLinkSvc {
|
|||
|
||||
private void handleMdmWithMultipleCandidates(IAnyResource theResource, CandidateList theCandidateList, MdmTransactionContext theMdmTransactionContext) {
|
||||
MatchedGoldenResourceCandidate firstMatch = theCandidateList.getFirstMatch();
|
||||
Long sampleGoldenResourcePid = firstMatch.getCandidateGoldenResourcePid().getIdAsLong();
|
||||
ResourcePersistentId sampleGoldenResourcePid = firstMatch.getCandidateGoldenResourcePid();
|
||||
boolean allSameGoldenResource = theCandidateList.stream()
|
||||
.allMatch(candidate -> candidate.getCandidateGoldenResourcePid().getIdAsLong().equals(sampleGoldenResourcePid));
|
||||
.allMatch(candidate -> candidate.getCandidateGoldenResourcePid().equals(sampleGoldenResourcePid));
|
||||
|
||||
if (allSameGoldenResource) {
|
||||
log(theMdmTransactionContext, "MDM received multiple match candidates, but they are all linked to the same Golden Resource.");
|
||||
|
|
|
@ -20,22 +20,22 @@ package ca.uhn.fhir.jpa.mdm.svc;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.index.IJpaIdHelperService;
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLink;
|
||||
import ca.uhn.fhir.mdm.api.MdmLinkJson;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
public class MdmModelConverterSvcImpl implements IMdmModelConverterSvc {
|
||||
|
||||
@Autowired
|
||||
IJpaIdHelperService myIdHelperService;
|
||||
IIdHelperService myIdHelperService;
|
||||
|
||||
@Override
|
||||
public MdmLinkJson toJson(MdmLink theLink) {
|
||||
public MdmLinkJson toJson(IMdmLink theLink) {
|
||||
MdmLinkJson retVal = new MdmLinkJson();
|
||||
String sourceId = myIdHelperService.resourceIdFromPidOrThrowException(theLink.getSourcePid()).toVersionless().getValue();
|
||||
String sourceId = myIdHelperService.resourceIdFromPidOrThrowException(theLink.getSourcePersistenceId(), theLink.getMdmSourceType()).toVersionless().getValue();
|
||||
retVal.setSourceId(sourceId);
|
||||
String goldenResourceId = myIdHelperService.resourceIdFromPidOrThrowException(theLink.getGoldenResourcePid()).toVersionless().getValue();
|
||||
String goldenResourceId = myIdHelperService.resourceIdFromPidOrThrowException(theLink.getGoldenResourcePersistenceId(), theLink.getMdmSourceType()).toVersionless().getValue();
|
||||
retVal.setGoldenResourceId(goldenResourceId);
|
||||
retVal.setCreated(theLink.getCreated());
|
||||
retVal.setEidMatch(theLink.getEidMatch());
|
||||
|
|
|
@ -24,6 +24,7 @@ import ca.uhn.fhir.context.FhirContext;
|
|||
import ca.uhn.fhir.mdm.api.IMdmSettings;
|
||||
import ca.uhn.fhir.mdm.log.Logs;
|
||||
import ca.uhn.fhir.mdm.rules.json.MdmResourceSearchParamJson;
|
||||
import ca.uhn.fhir.mdm.svc.MdmSearchParamSvc;
|
||||
import ca.uhn.fhir.mdm.util.MdmResourceUtil;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.slf4j.Logger;
|
||||
|
|
|
@ -20,7 +20,7 @@ package ca.uhn.fhir.jpa.mdm.svc.candidate;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.index.IJpaIdHelperService;
|
||||
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
||||
import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -29,7 +29,7 @@ import java.util.List;
|
|||
|
||||
public abstract class BaseCandidateFinder {
|
||||
@Autowired
|
||||
IJpaIdHelperService myIdHelperService;
|
||||
IIdHelperService myIdHelperService;
|
||||
@Autowired
|
||||
MdmLinkDaoSvc myMdmLinkDaoSvc;
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ package ca.uhn.fhir.jpa.mdm.svc.candidate;
|
|||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.mdm.svc.MdmSearchParamSvc;
|
||||
import ca.uhn.fhir.mdm.svc.MdmSearchParamSvc;
|
||||
import ca.uhn.fhir.jpa.partition.SystemRequestDetails;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.mdm.api.IMdmSettings;
|
||||
|
|
|
@ -24,6 +24,7 @@ import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
|||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc;
|
||||
import ca.uhn.fhir.jpa.mdm.svc.MdmResourceDaoSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLink;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchOutcome;
|
||||
import ca.uhn.fhir.mdm.log.Logs;
|
||||
import ca.uhn.fhir.mdm.model.CanonicalEID;
|
||||
|
@ -65,9 +66,10 @@ public class FindCandidateByEidSvc extends BaseCandidateFinder {
|
|||
if (isNoMatch(foundGoldenResource, theIncomingResource)) {
|
||||
continue;
|
||||
}
|
||||
Long pidOrNull = myIdHelperService.getPidOrNull(foundGoldenResource);
|
||||
MatchedGoldenResourceCandidate mpc = new MatchedGoldenResourceCandidate(new ResourcePersistentId(pidOrNull), MdmMatchOutcome.EID_MATCH);
|
||||
ResourcePersistentId pidOrNull = myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), foundGoldenResource);
|
||||
MatchedGoldenResourceCandidate mpc = new MatchedGoldenResourceCandidate(pidOrNull, MdmMatchOutcome.EID_MATCH);
|
||||
ourLog.debug("Incoming Resource {} matched Golden Resource {} by EID {}", theIncomingResource.getIdElement().toUnqualifiedVersionless(), foundGoldenResource.getIdElement().toUnqualifiedVersionless(), eid);
|
||||
|
||||
retval.add(mpc);
|
||||
}
|
||||
}
|
||||
|
@ -76,11 +78,11 @@ public class FindCandidateByEidSvc extends BaseCandidateFinder {
|
|||
}
|
||||
|
||||
private boolean isNoMatch(IAnyResource theGoldenResource, IAnyResource theSourceResource) {
|
||||
Optional<MdmLink> oLink = myMdmLinkDaoSvc.getLinkByGoldenResourceAndSourceResource(theGoldenResource, theSourceResource);
|
||||
Optional<? extends IMdmLink> oLink = myMdmLinkDaoSvc.getLinkByGoldenResourceAndSourceResource(theGoldenResource, theSourceResource);
|
||||
if (oLink.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
MdmLink link = oLink.get();
|
||||
MdmLink link = (MdmLink) oLink.get();
|
||||
return link.isNoMatch();
|
||||
}
|
||||
|
||||
|
|
|
@ -22,9 +22,9 @@ package ca.uhn.fhir.jpa.mdm.svc.candidate;
|
|||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.dao.index.IJpaIdHelperService;
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
||||
import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLink;
|
||||
import ca.uhn.fhir.mdm.api.IMdmMatchFinderSvc;
|
||||
import ca.uhn.fhir.mdm.api.MatchedTarget;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||
|
@ -46,7 +46,7 @@ import java.util.stream.Collectors;
|
|||
public class FindCandidateByExampleSvc extends BaseCandidateFinder {
|
||||
private static final Logger ourLog = Logs.getMdmTroubleshootingLog();
|
||||
@Autowired
|
||||
IJpaIdHelperService myIdHelperService;
|
||||
IIdHelperService myIdHelperService;
|
||||
@Autowired
|
||||
private FhirContext myFhirContext;
|
||||
@Autowired
|
||||
|
@ -66,7 +66,7 @@ public class FindCandidateByExampleSvc extends BaseCandidateFinder {
|
|||
protected List<MatchedGoldenResourceCandidate> findMatchGoldenResourceCandidates(IAnyResource theTarget) {
|
||||
List<MatchedGoldenResourceCandidate> retval = new ArrayList<>();
|
||||
|
||||
List<Long> goldenResourcePidsToExclude = getNoMatchGoldenResourcePids(theTarget);
|
||||
List<ResourcePersistentId> goldenResourcePidsToExclude = getNoMatchGoldenResourcePids(theTarget);
|
||||
|
||||
List<MatchedTarget> matchedCandidates = myMdmMatchFinderSvc.getMatchedTargets(myFhirContext.getResourceType(theTarget), theTarget, (RequestPartitionId) theTarget.getUserData(Constants.RESOURCE_PARTITION_ID));
|
||||
|
||||
|
@ -78,8 +78,7 @@ public class FindCandidateByExampleSvc extends BaseCandidateFinder {
|
|||
List<String> skippedLogMessages = new ArrayList<>();
|
||||
List<String> matchedLogMessages = new ArrayList<>();
|
||||
for (MatchedTarget match : matchedCandidates) {
|
||||
|
||||
Optional<MdmLink> optionalMdmLink = myMdmLinkDaoSvc.getMatchedLinkForSourcePid(myIdHelperService.getPidOrNull(match.getTarget()));
|
||||
Optional<? extends IMdmLink> optionalMdmLink = myMdmLinkDaoSvc.getMatchedLinkForSourcePid(myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), match.getTarget()));
|
||||
if (!optionalMdmLink.isPresent()) {
|
||||
if (ourLog.isDebugEnabled()) {
|
||||
skippedLogMessages.add(String.format("%s does not link to a Golden Resource (it may be a Golden Resource itself). Removing candidate.", match.getTarget().getIdElement().toUnqualifiedVersionless()));
|
||||
|
@ -87,16 +86,19 @@ public class FindCandidateByExampleSvc extends BaseCandidateFinder {
|
|||
continue;
|
||||
}
|
||||
|
||||
MdmLink matchMdmLink = optionalMdmLink.get();
|
||||
if (goldenResourcePidsToExclude.contains(matchMdmLink.getGoldenResourcePid())) {
|
||||
skippedLogMessages.add(String.format("Skipping MDM on candidate Golden Resource with PID %s due to manual NO_MATCH", matchMdmLink.getGoldenResourcePid()));
|
||||
|
||||
IMdmLink matchMdmLink = optionalMdmLink.get();
|
||||
if (goldenResourcePidsToExclude.contains(matchMdmLink.getGoldenResourcePersistenceId())) {
|
||||
skippedLogMessages.add(String.format("Skipping MDM on candidate Golden Resource with PID %s due to manual NO_MATCH", matchMdmLink.getGoldenResourcePersistenceId().toString()));
|
||||
continue;
|
||||
}
|
||||
|
||||
MatchedGoldenResourceCandidate candidate = new MatchedGoldenResourceCandidate(getResourcePersistentId(matchMdmLink.getGoldenResourcePid()), match.getMatchResult());
|
||||
MatchedGoldenResourceCandidate candidate = new MatchedGoldenResourceCandidate(matchMdmLink.getGoldenResourcePersistenceId(), match.getMatchResult());
|
||||
|
||||
if (ourLog.isDebugEnabled()) {
|
||||
matchedLogMessages.add(String.format("Navigating from matched resource %s to its Golden Resource %s", match.getTarget().getIdElement().toUnqualifiedVersionless(), matchMdmLink.getGoldenResource().getIdDt().toUnqualifiedVersionless()));
|
||||
matchedLogMessages.add(String.format("Navigating from matched resource %s to its Golden Resource %s", match.getTarget().getIdElement().toUnqualifiedVersionless(), matchMdmLink.getGoldenResourcePersistenceId().toString()));
|
||||
}
|
||||
|
||||
retval.add(candidate);
|
||||
}
|
||||
|
||||
|
@ -111,18 +113,14 @@ public class FindCandidateByExampleSvc extends BaseCandidateFinder {
|
|||
return retval;
|
||||
}
|
||||
|
||||
private List<Long> getNoMatchGoldenResourcePids(IBaseResource theBaseResource) {
|
||||
Long targetPid = myIdHelperService.getPidOrNull(theBaseResource);
|
||||
private List<ResourcePersistentId> getNoMatchGoldenResourcePids(IBaseResource theBaseResource) {
|
||||
ResourcePersistentId targetPid = myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), theBaseResource);
|
||||
return myMdmLinkDaoSvc.getMdmLinksBySourcePidAndMatchResult(targetPid, MdmMatchResultEnum.NO_MATCH)
|
||||
.stream()
|
||||
.map(MdmLink::getGoldenResourcePid)
|
||||
.map(IMdmLink::getGoldenResourcePersistenceId)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private ResourcePersistentId getResourcePersistentId(Long theGoldenResourcePid) {
|
||||
return new ResourcePersistentId(theGoldenResourcePid);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CandidateStrategyEnum getStrategy() {
|
||||
return CandidateStrategyEnum.SCORE;
|
||||
|
|
|
@ -20,7 +20,9 @@ package ca.uhn.fhir.jpa.mdm.svc.candidate;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLink;
|
||||
import ca.uhn.fhir.mdm.log.Logs;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
|
@ -45,11 +47,11 @@ public class FindCandidateByLinkSvc extends BaseCandidateFinder {
|
|||
protected List<MatchedGoldenResourceCandidate> findMatchGoldenResourceCandidates(IAnyResource theTarget) {
|
||||
List<MatchedGoldenResourceCandidate> retval = new ArrayList<>();
|
||||
|
||||
Long targetPid = myIdHelperService.getPidOrNull(theTarget);
|
||||
ResourcePersistentId targetPid = myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), theTarget);
|
||||
if (targetPid != null) {
|
||||
Optional<MdmLink> oLink = myMdmLinkDaoSvc.getMatchedLinkForSourcePid(targetPid);
|
||||
Optional<? extends IMdmLink> oLink = myMdmLinkDaoSvc.getMatchedLinkForSourcePid(targetPid);
|
||||
if (oLink.isPresent()) {
|
||||
ResourcePersistentId goldenResourcePid = new ResourcePersistentId(oLink.get().getGoldenResourcePid());
|
||||
ResourcePersistentId goldenResourcePid = new ResourcePersistentId(oLink.get().getGoldenResourcePersistenceId().getIdAsLong());
|
||||
ourLog.debug("Resource previously linked. Using existing link.");
|
||||
retval.add(new MatchedGoldenResourceCandidate(goldenResourcePid, oLink.get()));
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.mdm.svc.candidate;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.mdm.api.IMdmLink;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchOutcome;
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
|
@ -34,7 +35,7 @@ public class MatchedGoldenResourceCandidate {
|
|||
myMdmMatchOutcome = theMdmMatchOutcome;
|
||||
}
|
||||
|
||||
public MatchedGoldenResourceCandidate(ResourcePersistentId theGoldenResourcePid, MdmLink theMdmLink) {
|
||||
public MatchedGoldenResourceCandidate(ResourcePersistentId theGoldenResourcePid, IMdmLink theMdmLink) {
|
||||
myCandidateGoldenResourcePid = theGoldenResourcePid;
|
||||
myMdmMatchOutcome = new MdmMatchOutcome(theMdmLink.getVector(), theMdmLink.getScore()).setMatchResultEnum(theMdmLink.getMatchResult());
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ package ca.uhn.fhir.jpa.mdm.svc.candidate;
|
|||
*/
|
||||
|
||||
import ca.uhn.fhir.mdm.rules.json.MdmResourceSearchParamJson;
|
||||
import ca.uhn.fhir.jpa.mdm.svc.MdmSearchParamSvc;
|
||||
import ca.uhn.fhir.mdm.svc.MdmSearchParamSvc;
|
||||
import ca.uhn.fhir.util.UrlUtil;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
|
|
@ -20,14 +20,15 @@ package ca.uhn.fhir.jpa.mdm.svc.candidate;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.dao.index.IJpaIdHelperService;
|
||||
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.mdm.api.IMdmSettings;
|
||||
import ca.uhn.fhir.mdm.log.Logs;
|
||||
import ca.uhn.fhir.mdm.rules.json.MdmFilterSearchParamJson;
|
||||
import ca.uhn.fhir.mdm.rules.json.MdmResourceSearchParamJson;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -54,7 +55,7 @@ public class MdmCandidateSearchSvc {
|
|||
@Autowired
|
||||
private IMdmSettings myMdmSettings;
|
||||
@Autowired
|
||||
private IJpaIdHelperService myJpaIdHelperService;
|
||||
private IIdHelperService myIdHelperService;
|
||||
@Autowired
|
||||
private MdmCandidateSearchCriteriaBuilderSvc myMdmCandidateSearchCriteriaBuilderSvc;
|
||||
@Autowired
|
||||
|
@ -74,7 +75,7 @@ public class MdmCandidateSearchSvc {
|
|||
*/
|
||||
@Transactional
|
||||
public Collection<IAnyResource> findCandidates(String theResourceType, IAnyResource theResource, RequestPartitionId theRequestPartitionId) {
|
||||
Map<Long, IAnyResource> matchedPidsToResources = new HashMap<>();
|
||||
Map<ResourcePersistentId, IAnyResource> matchedPidsToResources = new HashMap<>();
|
||||
List<MdmFilterSearchParamJson> filterSearchParams = myMdmSettings.getMdmRules().getCandidateFilterSearchParams();
|
||||
List<String> filterCriteria = buildFilterQuery(filterSearchParams, theResourceType);
|
||||
List<MdmResourceSearchParamJson> candidateSearchParams = myMdmSettings.getMdmRules().getCandidateSearchParams();
|
||||
|
@ -97,7 +98,7 @@ public class MdmCandidateSearchSvc {
|
|||
// Sometimes, we are running this function on a resource that has not yet been persisted,
|
||||
// so it may not have an ID yet, precluding the need to remove it.
|
||||
if (theResource.getIdElement().getIdPart() != null) {
|
||||
if (matchedPidsToResources.remove(myJpaIdHelperService.getPidOrNull(theResource)) != null) {
|
||||
if (matchedPidsToResources.remove(myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), theResource)) != null) {
|
||||
ourLog.debug("Removing incoming resource {} from list of candidates.", theResource.getIdElement().toUnqualifiedVersionless());
|
||||
}
|
||||
}
|
||||
|
@ -119,7 +120,7 @@ public class MdmCandidateSearchSvc {
|
|||
* 4. Store all results in `theMatchedPidsToResources`
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
private void searchForIdsAndAddToMap(String theResourceType, IAnyResource theResource, Map<Long, IAnyResource> theMatchedPidsToResources, List<String> theFilterCriteria, MdmResourceSearchParamJson resourceSearchParam, RequestPartitionId theRequestPartitionId) {
|
||||
private void searchForIdsAndAddToMap(String theResourceType, IAnyResource theResource, Map<ResourcePersistentId, IAnyResource> theMatchedPidsToResources, List<String> theFilterCriteria, MdmResourceSearchParamJson resourceSearchParam, RequestPartitionId theRequestPartitionId) {
|
||||
//1.
|
||||
Optional<String> oResourceCriteria = myMdmCandidateSearchCriteriaBuilderSvc.buildResourceQueryString(theResourceType, theResource, theFilterCriteria, resourceSearchParam);
|
||||
if (!oResourceCriteria.isPresent()) {
|
||||
|
@ -138,7 +139,7 @@ public class MdmCandidateSearchSvc {
|
|||
int initialSize = theMatchedPidsToResources.size();
|
||||
|
||||
//4.
|
||||
resources.forEach(resource -> theMatchedPidsToResources.put(myJpaIdHelperService.getPidOrNull(resource), (IAnyResource) resource));
|
||||
resources.forEach(resource -> theMatchedPidsToResources.put(myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), resource), (IAnyResource) resource));
|
||||
|
||||
int newSize = theMatchedPidsToResources.size();
|
||||
|
||||
|
|
|
@ -5,8 +5,7 @@ import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
|||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome;
|
||||
import ca.uhn.fhir.jpa.dao.data.IMdmLinkDao;
|
||||
import ca.uhn.fhir.jpa.dao.index.IJpaIdHelperService;
|
||||
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.jpa.mdm.config.MdmConsumerConfig;
|
||||
import ca.uhn.fhir.jpa.mdm.config.MdmSubmitterConfig;
|
||||
|
@ -26,10 +25,12 @@ import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
|||
import ca.uhn.fhir.jpa.searchparam.registry.SearchParamRegistryImpl;
|
||||
import ca.uhn.fhir.jpa.subscription.match.config.SubscriptionProcessorConfig;
|
||||
import ca.uhn.fhir.jpa.test.BaseJpaR4Test;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLink;
|
||||
import ca.uhn.fhir.mdm.api.IMdmSettings;
|
||||
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.dao.IMdmLinkDao;
|
||||
import ca.uhn.fhir.mdm.model.MdmTransactionContext;
|
||||
import ca.uhn.fhir.mdm.rules.svc.MdmResourceMatcherSvc;
|
||||
import ca.uhn.fhir.mdm.util.EIDHelper;
|
||||
|
@ -116,7 +117,7 @@ abstract public class BaseMdmR4Test extends BaseJpaR4Test {
|
|||
@Autowired
|
||||
protected MdmLinkDaoSvc myMdmLinkDaoSvc;
|
||||
@Autowired
|
||||
protected IJpaIdHelperService myIdHelperService;
|
||||
protected IIdHelperService myIdHelperService;
|
||||
@Autowired
|
||||
protected IMdmSettings myMdmSettings;
|
||||
@Autowired
|
||||
|
@ -365,18 +366,18 @@ abstract public class BaseMdmR4Test extends BaseJpaR4Test {
|
|||
String resourceType = theBaseResource.getIdElement().getResourceType();
|
||||
IFhirResourceDao relevantDao = myDaoRegistry.getResourceDao(resourceType);
|
||||
|
||||
Optional<MdmLink> matchedLinkForTargetPid = myMdmLinkDaoSvc.getMatchedLinkForSourcePid(runInTransaction(() -> myIdHelperService.getPidOrNull(theBaseResource)));
|
||||
Optional<? extends IMdmLink> matchedLinkForTargetPid = myMdmLinkDaoSvc.getMatchedLinkForSourcePid(runInTransaction(() -> myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), theBaseResource)));
|
||||
if (matchedLinkForTargetPid.isPresent()) {
|
||||
Long goldenResourcePid = matchedLinkForTargetPid.get().getGoldenResourcePid();
|
||||
Long goldenResourcePid = matchedLinkForTargetPid.get().getGoldenResourcePersistenceId().getIdAsLong();
|
||||
return (T) relevantDao.readByPid(new ResourcePersistentId(goldenResourcePid));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected <T extends IBaseResource> T getTargetResourceFromMdmLink(MdmLink theMdmLink, String theResourceType) {
|
||||
protected <T extends IBaseResource> T getTargetResourceFromMdmLink(IMdmLink theMdmLink, String theResourceType) {
|
||||
IFhirResourceDao resourceDao = myDaoRegistry.getResourceDao(theResourceType);
|
||||
return (T) resourceDao.readByPid(new ResourcePersistentId(theMdmLink.getGoldenResourcePid()));
|
||||
return (T) resourceDao.readByPid(new ResourcePersistentId(theMdmLink.getGoldenResourcePersistenceId().getIdAsLong()));
|
||||
}
|
||||
|
||||
protected Patient addExternalEID(Patient thePatient, String theEID) {
|
||||
|
@ -545,11 +546,11 @@ abstract public class BaseMdmR4Test extends BaseJpaR4Test {
|
|||
Patient sourcePatient = createGoldenPatient();
|
||||
Patient patient = createPatient();
|
||||
|
||||
MdmLink mdmLink = myMdmLinkDaoSvc.newMdmLink();
|
||||
MdmLink mdmLink = (MdmLink) myMdmLinkDaoSvc.newMdmLink();
|
||||
mdmLink.setLinkSource(MdmLinkSourceEnum.MANUAL);
|
||||
mdmLink.setMatchResult(MdmMatchResultEnum.MATCH);
|
||||
mdmLink.setGoldenResourcePid(runInTransaction(() -> myIdHelperService.getPidOrNull(sourcePatient)));
|
||||
mdmLink.setSourcePid(runInTransaction(() -> myIdHelperService.getPidOrNull(patient)));
|
||||
mdmLink.setGoldenResourcePersistenceId(runInTransaction(() -> myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), sourcePatient)));
|
||||
mdmLink.setSourcePersistenceId(runInTransaction(() -> myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), patient)));
|
||||
return mdmLink;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package ca.uhn.fhir.jpa.mdm.config;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.jpa.mdm.dao.JpaMdmLinkImplFactory;
|
||||
import ca.uhn.fhir.jpa.mdm.helper.MdmLinkHelper;
|
||||
import ca.uhn.fhir.mdm.api.IMdmSettings;
|
||||
import ca.uhn.fhir.mdm.rules.config.MdmRuleValidator;
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package ca.uhn.fhir.jpa.mdm.config;
|
||||
|
||||
import ca.uhn.fhir.jpa.mdm.dao.JpaMdmLinkImplFactory;
|
||||
import ca.uhn.fhir.jpa.mdm.helper.MdmHelperR4;
|
||||
import ca.uhn.fhir.jpa.subscription.channel.config.SubscriptionChannelConfig;
|
||||
import ca.uhn.fhir.jpa.subscription.submit.config.SubscriptionSubmitterConfig;
|
||||
import ca.uhn.fhir.mdm.dao.IMdmLinkImplFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
package ca.uhn.fhir.jpa.mdm.dao;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.data.IMdmLinkDao;
|
||||
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
||||
import ca.uhn.fhir.mdm.api.IMdmSettings;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||
import ca.uhn.fhir.mdm.rules.json.MdmRulesJson;
|
||||
import ca.uhn.fhir.jpa.mdm.BaseMdmR4Test;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.dao.data.IMdmLinkJpaRepository;
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.jpa.mdm.BaseMdmR4Test;
|
||||
import ca.uhn.fhir.jpa.util.TestUtil;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLink;
|
||||
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||
import ca.uhn.fhir.mdm.model.MdmPidTuple;
|
||||
import ca.uhn.fhir.mdm.rules.json.MdmRulesJson;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import org.hl7.fhir.r4.model.Patient;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
|
@ -22,7 +24,6 @@ import static org.hamcrest.Matchers.equalTo;
|
|||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.in;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.isIn;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
@ -44,17 +45,17 @@ public class MdmLinkDaoSvcTest extends BaseMdmR4Test {
|
|||
|
||||
@Test
|
||||
public void testUpdate() {
|
||||
MdmLink createdLink = myMdmLinkDaoSvc.save(createResourcesAndBuildTestMDMLink());
|
||||
IMdmLink createdLink = myMdmLinkDaoSvc.save(createResourcesAndBuildTestMDMLink());
|
||||
assertThat(createdLink.getLinkSource(), is(MdmLinkSourceEnum.MANUAL));
|
||||
TestUtil.sleepOneClick();
|
||||
createdLink.setLinkSource(MdmLinkSourceEnum.AUTO);
|
||||
MdmLink updatedLink = myMdmLinkDaoSvc.save(createdLink);
|
||||
IMdmLink updatedLink = myMdmLinkDaoSvc.save(createdLink);
|
||||
assertNotEquals(updatedLink.getCreated(), updatedLink.getUpdated());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNew() {
|
||||
MdmLink newLink = myMdmLinkDaoSvc.newMdmLink();
|
||||
IMdmLink newLink = myMdmLinkDaoSvc.newMdmLink();
|
||||
MdmRulesJson rules = myMdmSettings.getMdmRules();
|
||||
assertEquals("1", rules.getVersion());
|
||||
assertEquals(rules.getVersion(), newLink.getVersion());
|
||||
|
@ -79,28 +80,28 @@ public class MdmLinkDaoSvcTest extends BaseMdmR4Test {
|
|||
List<Long> expectedExpandedPids = mdmLinks.stream().map(MdmLink::getSourcePid).collect(Collectors.toList());
|
||||
|
||||
//SUT
|
||||
List<IMdmLinkDao.MdmPidTuple> lists = myMdmLinkDao.expandPidsBySourcePidAndMatchResult(mdmLinks.get(0).getSourcePid(), MdmMatchResultEnum.MATCH);
|
||||
List<MdmPidTuple> lists = myMdmLinkDao.expandPidsBySourcePidAndMatchResult(new ResourcePersistentId(mdmLinks.get(0).getSourcePid()), MdmMatchResultEnum.MATCH);
|
||||
|
||||
assertThat(lists, hasSize(10));
|
||||
|
||||
lists.stream()
|
||||
.forEach(tuple -> {
|
||||
assertThat(tuple.getGoldenPid(), is(equalTo(golden.getIdElement().getIdPartAsLong())));
|
||||
assertThat(tuple.getSourcePid(), is(in(expectedExpandedPids)));
|
||||
assertThat(tuple.getGoldenPid().getIdAsLong(), is(equalTo(golden.getIdElement().getIdPartAsLong())));
|
||||
assertThat(tuple.getSourcePid().getIdAsLong(), is(in(expectedExpandedPids)));
|
||||
});
|
||||
}
|
||||
|
||||
private MdmLink createPatientAndLinkTo(Long thePatientPid, MdmMatchResultEnum theMdmMatchResultEnum) {
|
||||
Patient patient = createPatient();
|
||||
|
||||
MdmLink mdmLink = myMdmLinkDaoSvc.newMdmLink();
|
||||
MdmLink mdmLink = (MdmLink) myMdmLinkDaoSvc.newMdmLink();
|
||||
mdmLink.setLinkSource(MdmLinkSourceEnum.MANUAL);
|
||||
mdmLink.setMatchResult(theMdmMatchResultEnum);
|
||||
mdmLink.setCreated(new Date());
|
||||
mdmLink.setUpdated(new Date());
|
||||
mdmLink.setGoldenResourcePid(thePatientPid);
|
||||
mdmLink.setSourcePid(runInTransaction(()->myIdHelperService.getPidOrNull(patient)));
|
||||
MdmLink saved= myMdmLinkDao.save(mdmLink);
|
||||
mdmLink.setGoldenResourcePersistenceId(new ResourcePersistentId(thePatientPid));
|
||||
mdmLink.setSourcePersistenceId(runInTransaction(()->myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), patient)));
|
||||
MdmLink saved= (MdmLink) myMdmLinkDao.save(mdmLink);
|
||||
return saved;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package ca.uhn.fhir.jpa.mdm.helper;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.data.IMdmLinkDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IMdmLinkJpaRepository;
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -16,7 +16,7 @@ public class MdmLinkHelper {
|
|||
private static final Logger ourLog = LoggerFactory.getLogger(MdmLinkHelper.class);
|
||||
|
||||
@Autowired
|
||||
IMdmLinkDao myMdmLinkDao;
|
||||
IMdmLinkJpaRepository myMdmLinkDao;
|
||||
|
||||
@Transactional
|
||||
public void logMdmLinks() {
|
||||
|
|
|
@ -104,7 +104,7 @@ public class MdmEventIT extends BaseMdmR4Test {
|
|||
private MdmLink getLinkByTargetId(IBaseResource theResource) {
|
||||
MdmLink example = new MdmLink();
|
||||
example.setSourcePid(theResource.getIdElement().getIdPartAsLong());
|
||||
return myMdmLinkDao.findAll(Example.of(example)).get(0);
|
||||
return (MdmLink) myMdmLinkDao.findAll(Example.of(example)).get(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -8,6 +8,7 @@ import ca.uhn.fhir.jpa.mdm.BaseMdmR4Test;
|
|||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||
import ca.uhn.fhir.mdm.interceptor.IMdmStorageInterceptor;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import org.hl7.fhir.r4.model.Patient;
|
||||
|
@ -16,8 +17,6 @@ import org.junit.jupiter.api.BeforeEach;
|
|||
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.core.StringContains.containsString;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
@ -28,7 +27,7 @@ public class MdmExpungeTest extends BaseMdmR4Test {
|
|||
@Autowired
|
||||
IInterceptorService myInterceptorService;
|
||||
@Autowired
|
||||
IMdmStorageInterceptor myMdmStorageInterceptor;
|
||||
IMdmStorageInterceptor myMdmStorageInterceptor;
|
||||
@Autowired
|
||||
DaoConfig myDaoConfig;
|
||||
private ResourceTable myTargetEntity;
|
||||
|
@ -43,7 +42,7 @@ public class MdmExpungeTest extends BaseMdmR4Test {
|
|||
myTargetId = myTargetEntity.getIdDt().toVersionless();
|
||||
mySourceEntity = (ResourceTable) myPatientDao.create(new Patient()).getEntity();
|
||||
|
||||
MdmLink mdmLink = myMdmLinkDaoSvc.newMdmLink();
|
||||
MdmLink mdmLink = (MdmLink) myMdmLinkDaoSvc.newMdmLink();
|
||||
mdmLink.setLinkSource(MdmLinkSourceEnum.MANUAL);
|
||||
mdmLink.setMatchResult(MdmMatchResultEnum.MATCH);
|
||||
mdmLink.setGoldenResourcePid(mySourceEntity.getId());
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
package ca.uhn.fhir.jpa.mdm.interceptor;
|
||||
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome;
|
||||
import ca.uhn.fhir.jpa.dao.index.IJpaIdHelperService;
|
||||
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.jpa.mdm.BaseMdmR4Test;
|
||||
import ca.uhn.fhir.jpa.mdm.helper.MdmHelperConfig;
|
||||
import ca.uhn.fhir.jpa.mdm.helper.MdmHelperR4;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLink;
|
||||
import ca.uhn.fhir.mdm.model.CanonicalEID;
|
||||
import ca.uhn.fhir.mdm.rules.config.MdmSettings;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
|
@ -57,7 +59,7 @@ public class MdmStorageInterceptorIT extends BaseMdmR4Test {
|
|||
@Autowired
|
||||
public MdmHelperR4 myMdmHelper;
|
||||
@Autowired
|
||||
private IJpaIdHelperService myIdHelperService;
|
||||
private IIdHelperService myIdHelperService;
|
||||
|
||||
|
||||
@Override
|
||||
|
@ -74,7 +76,7 @@ public class MdmStorageInterceptorIT extends BaseMdmR4Test {
|
|||
private MdmLink getLinkByTargetId(IBaseResource theResource) {
|
||||
MdmLink example = new MdmLink();
|
||||
example.setSourcePid(theResource.getIdElement().getIdPartAsLong());
|
||||
return myMdmLinkDao.findAll(Example.of(example)).get(0);
|
||||
return (MdmLink) myMdmLinkDao.findAll(Example.of(example)).get(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -210,8 +212,8 @@ public class MdmStorageInterceptorIT extends BaseMdmR4Test {
|
|||
patient.setId(patientId);
|
||||
|
||||
// Updating a Golden Resource Patient who was created via MDM should fail.
|
||||
MdmLink mdmLink = runInTransaction(() -> myMdmLinkDaoSvc.getMatchedLinkForSourcePid(myIdHelperService.getPidOrNull(patient)).orElseThrow(() -> new IllegalStateException()));
|
||||
Long sourcePatientPid = mdmLink.getGoldenResourcePid();
|
||||
IMdmLink mdmLink = runInTransaction(() -> myMdmLinkDaoSvc.getMatchedLinkForSourcePid(myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), patient)).orElseThrow(() -> new IllegalStateException()));
|
||||
Long sourcePatientPid = mdmLink.getGoldenResourcePersistenceId().getIdAsLong();
|
||||
Patient goldenResourcePatient = myPatientDao.readByPid(new ResourcePersistentId(sourcePatientPid));
|
||||
goldenResourcePatient.setGender(Enumerations.AdministrativeGender.MALE);
|
||||
try {
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
package ca.uhn.fhir.jpa.mdm.matcher;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.index.IJpaIdHelperService;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
||||
import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLink;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||
import ca.uhn.fhir.mdm.util.MdmResourceUtil;
|
||||
import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc;
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import org.hamcrest.TypeSafeMatcher;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -21,42 +23,44 @@ public abstract class BaseGoldenResourceMatcher extends TypeSafeMatcher<IAnyReso
|
|||
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(BaseGoldenResourceMatcher.class);
|
||||
|
||||
protected IJpaIdHelperService myIdHelperService;
|
||||
protected IIdHelperService myIdHelperService;
|
||||
protected MdmLinkDaoSvc myMdmLinkDaoSvc;
|
||||
protected Collection<IAnyResource> myBaseResources;
|
||||
protected String myTargetType;
|
||||
|
||||
protected BaseGoldenResourceMatcher(IJpaIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theBaseResource) {
|
||||
protected BaseGoldenResourceMatcher(IIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theBaseResource) {
|
||||
myIdHelperService = theIdHelperService;
|
||||
myMdmLinkDaoSvc = theMdmLinkDaoSvc;
|
||||
myBaseResources = Arrays.stream(theBaseResource).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected Long getMatchedResourcePidFromResource(IAnyResource theResource) {
|
||||
Long retval;
|
||||
protected ResourcePersistentId getMatchedResourcePidFromResource(IAnyResource theResource) {
|
||||
ResourcePersistentId retval;
|
||||
|
||||
boolean isGoldenRecord = MdmResourceUtil.isMdmManaged(theResource);
|
||||
if (isGoldenRecord) {
|
||||
return myIdHelperService.getPidOrNull(theResource);
|
||||
return myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), theResource);
|
||||
}
|
||||
MdmLink matchLink = getMatchedMdmLink(theResource);
|
||||
IMdmLink matchLink = getMatchedMdmLink(theResource);
|
||||
|
||||
if (matchLink == null) {
|
||||
return null;
|
||||
} else {
|
||||
retval = matchLink.getGoldenResourcePid();
|
||||
retval = matchLink.getGoldenResourcePersistenceId();
|
||||
myTargetType = matchLink.getMdmSourceType();
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
protected List<Long> getPossibleMatchedGoldenResourcePidsFromTarget(IAnyResource theBaseResource) {
|
||||
return getMdmLinksForTarget(theBaseResource, MdmMatchResultEnum.POSSIBLE_MATCH).stream().map(MdmLink::getGoldenResourcePid).collect(Collectors.toList());
|
||||
protected List<ResourcePersistentId> getPossibleMatchedGoldenResourcePidsFromTarget(IAnyResource theBaseResource) {
|
||||
return getMdmLinksForTarget(theBaseResource, MdmMatchResultEnum.POSSIBLE_MATCH)
|
||||
.stream()
|
||||
.map(IMdmLink::getGoldenResourcePersistenceId).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
protected MdmLink getMatchedMdmLink(IAnyResource thePatientOrPractitionerResource) {
|
||||
List<MdmLink> mdmLinks = getMdmLinksForTarget(thePatientOrPractitionerResource, MdmMatchResultEnum.MATCH);
|
||||
protected IMdmLink getMatchedMdmLink(IAnyResource thePatientOrPractitionerResource) {
|
||||
List<? extends IMdmLink> mdmLinks = getMdmLinksForTarget(thePatientOrPractitionerResource, MdmMatchResultEnum.MATCH);
|
||||
if (mdmLinks.size() == 0) {
|
||||
return null;
|
||||
} else if (mdmLinks.size() == 1) {
|
||||
|
@ -66,9 +70,9 @@ public abstract class BaseGoldenResourceMatcher extends TypeSafeMatcher<IAnyReso
|
|||
}
|
||||
}
|
||||
|
||||
protected List<MdmLink> getMdmLinksForTarget(IAnyResource theTargetResource, MdmMatchResultEnum theMatchResult) {
|
||||
Long pidOrNull = myIdHelperService.getPidOrNull(theTargetResource);
|
||||
List<MdmLink> matchLinkForTarget = myMdmLinkDaoSvc.getMdmLinksBySourcePidAndMatchResult(pidOrNull, theMatchResult);
|
||||
protected List<? extends IMdmLink> getMdmLinksForTarget(IAnyResource theTargetResource, MdmMatchResultEnum theMatchResult) {
|
||||
ResourcePersistentId pidOrNull = myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), theTargetResource);
|
||||
List<? extends IMdmLink> matchLinkForTarget = myMdmLinkDaoSvc.getMdmLinksBySourcePidAndMatchResult(pidOrNull, theMatchResult);
|
||||
if (!matchLinkForTarget.isEmpty()) {
|
||||
return matchLinkForTarget;
|
||||
} else {
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
package ca.uhn.fhir.jpa.mdm.matcher;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.index.IJpaIdHelperService;
|
||||
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
||||
import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
|
@ -15,10 +16,10 @@ import java.util.stream.Collectors;
|
|||
*/
|
||||
public class IsLinkedTo extends BaseGoldenResourceMatcher {
|
||||
|
||||
private List<Long> baseResourceGoldenResourcePids;
|
||||
private Long incomingResourceGoldenResourcePid;
|
||||
private List<ResourcePersistentId> baseResourceGoldenResourcePids;
|
||||
private ResourcePersistentId incomingResourceGoldenResourcePid;
|
||||
|
||||
protected IsLinkedTo(IJpaIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theBaseResource) {
|
||||
protected IsLinkedTo(IIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theBaseResource) {
|
||||
super(theIdHelperService, theMdmLinkDaoSvc, theBaseResource);
|
||||
}
|
||||
|
||||
|
@ -41,7 +42,7 @@ public class IsLinkedTo extends BaseGoldenResourceMatcher {
|
|||
public void describeTo(Description theDescription) {
|
||||
}
|
||||
|
||||
public static Matcher<IAnyResource> linkedTo(IJpaIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theBaseResource) {
|
||||
public static Matcher<IAnyResource> linkedTo(IIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theBaseResource) {
|
||||
return new IsLinkedTo(theIdHelperService, theMdmLinkDaoSvc, theBaseResource);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
package ca.uhn.fhir.jpa.mdm.matcher;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.index.IJpaIdHelperService;
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
||||
import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLink;
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.hamcrest.TypeSafeMatcher;
|
||||
|
@ -12,17 +13,17 @@ import java.util.Optional;
|
|||
|
||||
public class IsMatchedToAGoldenResource extends TypeSafeMatcher<IAnyResource> {
|
||||
|
||||
private final IJpaIdHelperService myIdHelperService;
|
||||
private final IIdHelperService myIdHelperService;
|
||||
private final MdmLinkDaoSvc myMdmLinkDaoSvc;
|
||||
|
||||
public IsMatchedToAGoldenResource(IJpaIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc) {
|
||||
public IsMatchedToAGoldenResource(IIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc) {
|
||||
myIdHelperService = theIdHelperService;
|
||||
myMdmLinkDaoSvc = theMdmLinkDaoSvc;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean matchesSafely(IAnyResource theIncomingResource) {
|
||||
Optional<MdmLink> matchedLinkForTargetPid = myMdmLinkDaoSvc.getMatchedLinkForSourcePid(myIdHelperService.getPidOrNull(theIncomingResource));
|
||||
Optional<? extends IMdmLink> matchedLinkForTargetPid = myMdmLinkDaoSvc.getMatchedLinkForSourcePid(myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), theIncomingResource));
|
||||
return matchedLinkForTargetPid.isPresent();
|
||||
}
|
||||
|
||||
|
@ -31,7 +32,7 @@ public class IsMatchedToAGoldenResource extends TypeSafeMatcher<IAnyResource> {
|
|||
theDescription.appendText("target was not linked to a Golden Resource.");
|
||||
}
|
||||
|
||||
public static Matcher<IAnyResource> matchedToAGoldenResource(IJpaIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc) {
|
||||
public static Matcher<IAnyResource> matchedToAGoldenResource(IIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc) {
|
||||
return new IsMatchedToAGoldenResource(theIdHelperService, theMdmLinkDaoSvc);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
package ca.uhn.fhir.jpa.mdm.matcher;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.index.IJpaIdHelperService;
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
||||
import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLink;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
|
@ -18,9 +19,9 @@ public class IsPossibleDuplicateOf extends BaseGoldenResourceMatcher {
|
|||
* Matcher with tells us if there is an MdmLink with between these two resources that are considered POSSIBLE DUPLICATE.
|
||||
* For use only on GoldenResource.
|
||||
*/
|
||||
private Long incomingGoldenResourcePid;
|
||||
private ResourcePersistentId incomingGoldenResourcePid;
|
||||
|
||||
protected IsPossibleDuplicateOf(IJpaIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theBaseResource) {
|
||||
protected IsPossibleDuplicateOf(IIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theBaseResource) {
|
||||
super(theIdHelperService, theMdmLinkDaoSvc, theBaseResource);
|
||||
}
|
||||
|
||||
|
@ -28,7 +29,7 @@ public class IsPossibleDuplicateOf extends BaseGoldenResourceMatcher {
|
|||
protected boolean matchesSafely(IAnyResource theIncomingResource) {
|
||||
incomingGoldenResourcePid = getMatchedResourcePidFromResource(theIncomingResource);
|
||||
|
||||
List<Long> goldenResourcePidsToMatch = myBaseResources.stream()
|
||||
List<ResourcePersistentId> goldenResourcePidsToMatch = myBaseResources.stream()
|
||||
.map(this::getMatchedResourcePidFromResource)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
|
@ -36,7 +37,7 @@ public class IsPossibleDuplicateOf extends BaseGoldenResourceMatcher {
|
|||
//Returns true if there is a POSSIBLE_DUPLICATE between the incoming resource, and all of the resources passed in via the constructor.
|
||||
return goldenResourcePidsToMatch.stream()
|
||||
.map(baseResourcePid -> {
|
||||
Optional<MdmLink> duplicateLink = myMdmLinkDaoSvc.getMdmLinksByGoldenResourcePidSourcePidAndMatchResult(baseResourcePid, incomingGoldenResourcePid, MdmMatchResultEnum.POSSIBLE_DUPLICATE);
|
||||
Optional<? extends IMdmLink> duplicateLink = myMdmLinkDaoSvc.getMdmLinksByGoldenResourcePidSourcePidAndMatchResult(baseResourcePid, incomingGoldenResourcePid, MdmMatchResultEnum.POSSIBLE_DUPLICATE);
|
||||
if (!duplicateLink.isPresent()) {
|
||||
duplicateLink = myMdmLinkDaoSvc.getMdmLinksByGoldenResourcePidSourcePidAndMatchResult(incomingGoldenResourcePid, baseResourcePid, MdmMatchResultEnum.POSSIBLE_DUPLICATE);
|
||||
}
|
||||
|
@ -55,7 +56,7 @@ public class IsPossibleDuplicateOf extends BaseGoldenResourceMatcher {
|
|||
mismatchDescription.appendText("No MdmLink With POSSIBLE_DUPLICATE was found");
|
||||
}
|
||||
|
||||
public static Matcher<IAnyResource> possibleDuplicateOf(IJpaIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theBaseResource) {
|
||||
public static Matcher<IAnyResource> possibleDuplicateOf(IIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theBaseResource) {
|
||||
return new IsPossibleDuplicateOf(theIdHelperService, theMdmLinkDaoSvc, theBaseResource);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package ca.uhn.fhir.jpa.mdm.matcher;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.index.IJpaIdHelperService;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
||||
import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
|
@ -15,16 +17,16 @@ import java.util.stream.Collectors;
|
|||
*/
|
||||
public class IsPossibleLinkedTo extends BaseGoldenResourceMatcher {
|
||||
|
||||
private List<Long> baseResourceGoldenResourcePids;
|
||||
private Long incomingResourceGoldenResourcePid;
|
||||
private List<ResourcePersistentId> baseResourceGoldenResourcePids;
|
||||
private ResourcePersistentId incomingResourceGoldenResourcePid;
|
||||
|
||||
protected IsPossibleLinkedTo(IJpaIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theTargetResources) {
|
||||
protected IsPossibleLinkedTo(IIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theTargetResources) {
|
||||
super(theIdHelperService, theMdmLinkDaoSvc, theTargetResources);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean matchesSafely(IAnyResource theGoldenResource) {
|
||||
incomingResourceGoldenResourcePid = myIdHelperService.getPidOrNull(theGoldenResource);
|
||||
incomingResourceGoldenResourcePid = myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), theGoldenResource);
|
||||
|
||||
//OK, lets grab all the golden resource pids of the resources passed in via the constructor.
|
||||
baseResourceGoldenResourcePids = myBaseResources.stream()
|
||||
|
@ -40,7 +42,7 @@ public class IsPossibleLinkedTo extends BaseGoldenResourceMatcher {
|
|||
public void describeTo(Description theDescription) {
|
||||
}
|
||||
|
||||
public static Matcher<IAnyResource> possibleLinkedTo(IJpaIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theBaseResource) {
|
||||
public static Matcher<IAnyResource> possibleLinkedTo(IIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theBaseResource) {
|
||||
return new IsPossibleLinkedTo(theIdHelperService, theMdmLinkDaoSvc, theBaseResource);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
package ca.uhn.fhir.jpa.mdm.matcher;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.index.IJpaIdHelperService;
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
||||
import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLink;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
|
@ -17,15 +18,15 @@ import java.util.stream.Collectors;
|
|||
*/
|
||||
public class IsPossibleMatchWith extends BaseGoldenResourceMatcher {
|
||||
|
||||
protected IsPossibleMatchWith(IJpaIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theBaseResource) {
|
||||
protected IsPossibleMatchWith(IIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theBaseResource) {
|
||||
super(theIdHelperService, theMdmLinkDaoSvc, theBaseResource);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean matchesSafely(IAnyResource theIncomingResource) {
|
||||
List<MdmLink> mdmLinks = getMdmLinksForTarget(theIncomingResource, MdmMatchResultEnum.POSSIBLE_MATCH);
|
||||
List<? extends IMdmLink> mdmLinks = getMdmLinksForTarget(theIncomingResource, MdmMatchResultEnum.POSSIBLE_MATCH);
|
||||
|
||||
List<Long> goldenResourcePidsToMatch = myBaseResources.stream()
|
||||
List<ResourcePersistentId> goldenResourcePidsToMatch = myBaseResources.stream()
|
||||
.map(this::getMatchedResourcePidFromResource)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
|
@ -36,8 +37,8 @@ public class IsPossibleMatchWith extends BaseGoldenResourceMatcher {
|
|||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
List<Long> mdmLinkGoldenResourcePids = mdmLinks
|
||||
.stream().map(MdmLink::getGoldenResourcePid)
|
||||
List<ResourcePersistentId> mdmLinkGoldenResourcePids = mdmLinks
|
||||
.stream().map(IMdmLink::getGoldenResourcePersistenceId)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return mdmLinkGoldenResourcePids.containsAll(goldenResourcePidsToMatch);
|
||||
|
@ -54,7 +55,7 @@ public class IsPossibleMatchWith extends BaseGoldenResourceMatcher {
|
|||
mismatchDescription.appendText("No MDM Link With POSSIBLE_MATCH was found");
|
||||
}
|
||||
|
||||
public static Matcher<IAnyResource> possibleMatchWith(IJpaIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theBaseResource) {
|
||||
public static Matcher<IAnyResource> possibleMatchWith(IIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theBaseResource) {
|
||||
return new IsPossibleMatchWith(theIdHelperService, theMdmLinkDaoSvc, theBaseResource);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
package ca.uhn.fhir.jpa.mdm.matcher;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.index.IJpaIdHelperService;
|
||||
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
||||
import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
|
@ -11,10 +12,10 @@ import java.util.stream.Collectors;
|
|||
|
||||
public class IsSameGoldenResourceAs extends BaseGoldenResourceMatcher {
|
||||
|
||||
private List<Long> goldenResourcePidsToMatch;
|
||||
private Long incomingGoldenResourcePid;
|
||||
private List<ResourcePersistentId> goldenResourcePidsToMatch;
|
||||
private ResourcePersistentId incomingGoldenResourcePid;
|
||||
|
||||
public IsSameGoldenResourceAs(IJpaIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theBaseResource) {
|
||||
public IsSameGoldenResourceAs(IIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theBaseResource) {
|
||||
super(theIdHelperService, theMdmLinkDaoSvc, theBaseResource);
|
||||
}
|
||||
|
||||
|
@ -40,7 +41,7 @@ public class IsSameGoldenResourceAs extends BaseGoldenResourceMatcher {
|
|||
mismatchDescription.appendText(String.format(" was actually linked to %s/%s", myTargetType, incomingGoldenResourcePid));
|
||||
}
|
||||
|
||||
public static Matcher<IAnyResource> sameGoldenResourceAs(IJpaIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theBaseResource) {
|
||||
public static Matcher<IAnyResource> sameGoldenResourceAs(IIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theBaseResource) {
|
||||
return new IsSameGoldenResourceAs(theIdHelperService, theMdmLinkDaoSvc, theBaseResource);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package ca.uhn.fhir.jpa.mdm.provider;
|
|||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLink;
|
||||
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
|
@ -46,7 +47,7 @@ public abstract class BaseLinkR4Test extends BaseProviderR4Test {
|
|||
mySourcePatientId = new StringType(mySourcePatient.getIdElement().getValue());
|
||||
myVersionlessGodlenResourceId = new StringType(mySourcePatient.getIdElement().toVersionless().getValue());
|
||||
|
||||
myLink = getOnlyPatientLink();
|
||||
myLink = (MdmLink) getOnlyPatientLink();
|
||||
// Tests require our initial link to be a POSSIBLE_MATCH
|
||||
myLink.setMatchResult(MdmMatchResultEnum.POSSIBLE_MATCH);
|
||||
saveLink(myLink);
|
||||
|
@ -65,12 +66,12 @@ public abstract class BaseLinkR4Test extends BaseProviderR4Test {
|
|||
}
|
||||
|
||||
@Nonnull
|
||||
protected MdmLink getOnlyPatientLink() {
|
||||
protected IMdmLink getOnlyPatientLink() {
|
||||
return myMdmLinkDaoSvc.findMdmLinkBySource(myPatient).get();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
protected List<MdmLink> getPatientLinks() {
|
||||
protected List<? extends IMdmLink> getPatientLinks() {
|
||||
return myMdmLinkDaoSvc.findMdmLinksBySourceResource(myPatient);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -196,6 +196,6 @@ public class MdmProviderClearLinkR4Test extends BaseLinkR4Test {
|
|||
|
||||
@Nonnull
|
||||
protected List<MdmLink> getPractitionerLinks() {
|
||||
return myMdmLinkDaoSvc.findMdmLinksBySourceResource(myPractitioner);
|
||||
return (List<MdmLink>) myMdmLinkDaoSvc.findMdmLinksBySourceResource(myPractitioner);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ public class MdmProviderCreateLinkR4Test extends BaseLinkR4Test {
|
|||
myMdmProvider.createLink(sourcePatientId, patientId, MATCH_RESULT, myRequestDetails);
|
||||
assertLinkCount(2);
|
||||
|
||||
List<MdmLink> links = myMdmLinkDaoSvc.findMdmLinksBySourceResource(patient);
|
||||
List<MdmLink> links = (List<MdmLink>) myMdmLinkDaoSvc.findMdmLinksBySourceResource(patient);
|
||||
assertEquals(MdmLinkSourceEnum.MANUAL, links.get(0).getLinkSource());
|
||||
assertEquals(MdmMatchResultEnum.MATCH, links.get(0).getMatchResult());
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ public class MdmProviderCreateLinkR4Test extends BaseLinkR4Test {
|
|||
myMdmProvider.createLink(sourcePatientId, patientId, MATCH_RESULT, myRequestDetails);
|
||||
assertLinkCount(2);
|
||||
|
||||
List<MdmLink> links = myMdmLinkDaoSvc.findMdmLinksBySourceResource(patient);
|
||||
List<MdmLink> links = (List<MdmLink>) myMdmLinkDaoSvc.findMdmLinksBySourceResource(patient);
|
||||
assertEquals(links.size(), 1);
|
||||
assertEquals(MdmLinkSourceEnum.MANUAL, links.get(0).getLinkSource());
|
||||
assertEquals(MdmMatchResultEnum.MATCH, links.get(0).getMatchResult());
|
||||
|
@ -106,7 +106,7 @@ public class MdmProviderCreateLinkR4Test extends BaseLinkR4Test {
|
|||
myMdmProvider.createLink(sourcePatientId, patientId, null, myRequestDetails);
|
||||
assertLinkCount(2);
|
||||
|
||||
List<MdmLink> links = myMdmLinkDaoSvc.findMdmLinksBySourceResource(patient);
|
||||
List<MdmLink> links = (List<MdmLink>) myMdmLinkDaoSvc.findMdmLinksBySourceResource(patient);
|
||||
assertEquals(MdmLinkSourceEnum.MANUAL, links.get(0).getLinkSource());
|
||||
assertEquals(MdmMatchResultEnum.MATCH, links.get(0).getMatchResult());
|
||||
}
|
||||
|
@ -152,7 +152,7 @@ public class MdmProviderCreateLinkR4Test extends BaseLinkR4Test {
|
|||
myMdmProvider.createLink(sourcePatientId2, patientId, NO_MATCH_RESULT, myRequestDetails);
|
||||
|
||||
assertLinkCount(3);
|
||||
List<MdmLink> links = myMdmLinkDaoSvc.findMdmLinksBySourceResource(patient);
|
||||
List<MdmLink> links = (List<MdmLink>) myMdmLinkDaoSvc.findMdmLinksBySourceResource(patient);
|
||||
assertEquals(MdmLinkSourceEnum.MANUAL, links.get(1).getLinkSource());
|
||||
assertEquals(MdmMatchResultEnum.NO_MATCH, links.get(1).getMatchResult());
|
||||
}
|
||||
|
|
|
@ -97,7 +97,7 @@ public class MdmProviderMergeGoldenResourcesR4Test extends BaseProviderR4Test {
|
|||
// Optional<Identifier> redirect = fromSourcePatient.getIdentifier().stream().filter(theIdentifier -> theIdentifier.getSystem().equals("REDIRECT")).findFirst();
|
||||
// assertThat(redirect.get().getValue(), is(equalTo(myToSourcePatient.getIdElement().toUnqualified().getValue())));
|
||||
|
||||
List<MdmLink> links = myMdmLinkDaoSvc.findMdmLinksBySourceResource(myFromGoldenPatient);
|
||||
List<MdmLink> links = (List<MdmLink>) myMdmLinkDaoSvc.findMdmLinksBySourceResource(myFromGoldenPatient);
|
||||
assertThat(links, hasSize(1));
|
||||
|
||||
MdmLink link = links.get(0);
|
||||
|
@ -129,7 +129,7 @@ public class MdmProviderMergeGoldenResourcesR4Test extends BaseProviderR4Test {
|
|||
// 2 from the set-up and only one from this test should be golden resource
|
||||
assertEquals(3, getAllGoldenPatients().size());
|
||||
|
||||
List<MdmLink> links = myMdmLinkDaoSvc.findMdmLinksBySourceResource(fromGoldenPatient);
|
||||
List<MdmLink> links = (List<MdmLink>) myMdmLinkDaoSvc.findMdmLinksBySourceResource(fromGoldenPatient);
|
||||
assertThat(links, hasSize(1));
|
||||
|
||||
MdmLink link = links.get(0);
|
||||
|
@ -176,7 +176,7 @@ public class MdmProviderMergeGoldenResourcesR4Test extends BaseProviderR4Test {
|
|||
assertFalse(MdmResourceUtil.isGoldenRecord(fromSourcePatient));
|
||||
assertTrue(MdmResourceUtil.isGoldenRecordRedirected(fromSourcePatient));
|
||||
|
||||
List<MdmLink> links = myMdmLinkDaoSvc.findMdmLinksBySourceResource(myFromGoldenPatient);
|
||||
List<MdmLink> links = (List<MdmLink>) myMdmLinkDaoSvc.findMdmLinksBySourceResource(myFromGoldenPatient);
|
||||
assertThat(links, hasSize(1));
|
||||
|
||||
MdmLink link = links.get(0);
|
||||
|
|
|
@ -56,7 +56,7 @@ public class MdmProviderNotDuplicateGoldenResourceR4Test extends BaseProviderR4T
|
|||
myMdmProvider.notDuplicate(myGoldenPatientId, myTargetPatientId, myRequestDetails);
|
||||
assertLinkCount(1);
|
||||
|
||||
List<MdmLink> links = myMdmLinkDaoSvc.findMdmLinksBySourceResource(myTargetPatient);
|
||||
List<MdmLink> links = (List<MdmLink>) myMdmLinkDaoSvc.findMdmLinksBySourceResource(myTargetPatient);
|
||||
assertEquals(MdmLinkSourceEnum.MANUAL, links.get(0).getLinkSource());
|
||||
assertEquals(MdmMatchResultEnum.NO_MATCH, links.get(0).getMatchResult());
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ public class MdmProviderNotDuplicateGoldenResourceR4Test extends BaseProviderR4T
|
|||
myMdmProvider.notDuplicate(goldenPatientId, targetPatientId, myRequestDetails);
|
||||
assertLinkCount(1);
|
||||
|
||||
List<MdmLink> links = myMdmLinkDaoSvc.findMdmLinksBySourceResource(targetPatient);
|
||||
List<MdmLink> links = (List<MdmLink>) myMdmLinkDaoSvc.findMdmLinksBySourceResource(targetPatient);
|
||||
assertEquals(MdmLinkSourceEnum.MANUAL, links.get(0).getLinkSource());
|
||||
assertEquals(MdmMatchResultEnum.NO_MATCH, links.get(0).getMatchResult());
|
||||
}
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
package ca.uhn.fhir.jpa.mdm.provider;
|
||||
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.jpa.util.CircularQueueCaptureQueriesListener;
|
||||
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
import ca.uhn.fhir.util.StopWatch;
|
||||
|
@ -56,12 +58,15 @@ public class MdmProviderQueryLinkR4Test extends BaseLinkR4Test {
|
|||
myLinkSource = new StringType(MdmLinkSourceEnum.AUTO.name());
|
||||
Patient sourcePatient1 = createGoldenPatient();
|
||||
myGoldenResource1Id = new StringType(sourcePatient1.getIdElement().toVersionless().getValue());
|
||||
Long sourcePatient1Pid = runInTransaction(()->myIdHelperService.getPidOrNull(sourcePatient1));
|
||||
ResourcePersistentId sourcePatient1Pid = runInTransaction(()->myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), sourcePatient1));
|
||||
Patient sourcePatient2 = createGoldenPatient();
|
||||
myGoldenResource2Id = new StringType(sourcePatient2.getIdElement().toVersionless().getValue());
|
||||
Long sourcePatient2Pid = runInTransaction(()->myIdHelperService.getPidOrNull(sourcePatient2));
|
||||
ResourcePersistentId sourcePatient2Pid = runInTransaction(()->myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), sourcePatient2));
|
||||
|
||||
MdmLink possibleDuplicateMdmLink = myMdmLinkDaoSvc.newMdmLink().setGoldenResourcePid(sourcePatient1Pid).setSourcePid(sourcePatient2Pid).setMatchResult(MdmMatchResultEnum.POSSIBLE_DUPLICATE).setLinkSource(MdmLinkSourceEnum.AUTO);
|
||||
MdmLink possibleDuplicateMdmLink = (MdmLink) myMdmLinkDaoSvc.newMdmLink();
|
||||
possibleDuplicateMdmLink.setGoldenResourcePersistenceId(sourcePatient1Pid);
|
||||
possibleDuplicateMdmLink.setSourcePersistenceId(sourcePatient2Pid);
|
||||
possibleDuplicateMdmLink.setMatchResult(MdmMatchResultEnum.POSSIBLE_DUPLICATE).setLinkSource(MdmLinkSourceEnum.AUTO);
|
||||
saveLink(possibleDuplicateMdmLink);
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ public class MdmProviderUpdateLinkR4Test extends BaseLinkR4Test {
|
|||
myMdmProvider.updateLink(mySourcePatientId, myPatientId, NO_MATCH_RESULT, myRequestDetails);
|
||||
assertLinkCount(2);
|
||||
|
||||
List<MdmLink> links = getPatientLinks();
|
||||
List<MdmLink> links = (List<MdmLink>) getPatientLinks();
|
||||
assertEquals(MdmLinkSourceEnum.MANUAL, links.get(0).getLinkSource());
|
||||
assertEquals(MdmMatchResultEnum.NO_MATCH, links.get(0).getMatchResult());
|
||||
assertEquals(MdmLinkSourceEnum.AUTO, links.get(1).getLinkSource());
|
||||
|
@ -51,7 +51,7 @@ public class MdmProviderUpdateLinkR4Test extends BaseLinkR4Test {
|
|||
myMdmProvider.updateLink(mySourcePatientId, myPatientId, MATCH_RESULT, myRequestDetails);
|
||||
assertLinkCount(1);
|
||||
|
||||
List<MdmLink> links = getPatientLinks();
|
||||
List<MdmLink> links = (List<MdmLink>) getPatientLinks();
|
||||
assertEquals(MdmLinkSourceEnum.MANUAL, links.get(0).getLinkSource());
|
||||
assertEquals(MdmMatchResultEnum.MATCH, links.get(0).getMatchResult());
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ public class MdmProviderUpdateLinkR4Test extends BaseLinkR4Test {
|
|||
|
||||
Patient sourcePatient = getGoldenResourceFromTargetResource(patient);
|
||||
StringType sourcePatientId = new StringType(sourcePatient.getIdElement().getValue());
|
||||
MdmLink link = myMdmLinkDaoSvc.findMdmLinkBySource(patient).get();
|
||||
MdmLink link = (MdmLink) myMdmLinkDaoSvc.findMdmLinkBySource(patient).get();
|
||||
link.setMatchResult(MdmMatchResultEnum.POSSIBLE_MATCH);
|
||||
saveLink(link);
|
||||
assertEquals(MdmLinkSourceEnum.AUTO, link.getLinkSource());
|
||||
|
@ -74,7 +74,7 @@ public class MdmProviderUpdateLinkR4Test extends BaseLinkR4Test {
|
|||
myMdmProvider.updateLink(sourcePatientId, patientId, MATCH_RESULT, myRequestDetails);
|
||||
assertLinkCount(2);
|
||||
|
||||
List<MdmLink> links = myMdmLinkDaoSvc.findMdmLinksBySourceResource(patient);
|
||||
List<MdmLink> links = (List<MdmLink>) myMdmLinkDaoSvc.findMdmLinksBySourceResource(patient);
|
||||
assertEquals(MdmLinkSourceEnum.MANUAL, links.get(0).getLinkSource());
|
||||
assertEquals(MdmMatchResultEnum.MATCH, links.get(0).getMatchResult());
|
||||
assertNotNull(links.get(0).getPartitionId());
|
||||
|
|
|
@ -5,6 +5,7 @@ import ca.uhn.fhir.interceptor.api.Pointcut;
|
|||
import ca.uhn.fhir.jpa.mdm.BaseMdmR4Test;
|
||||
import ca.uhn.fhir.jpa.partition.SystemRequestDetails;
|
||||
import ca.uhn.fhir.mdm.api.IMdmSubmitSvc;
|
||||
import ca.uhn.fhir.mdm.svc.MdmSubmitSvcImpl;
|
||||
import ca.uhn.test.concurrency.PointcutLatch;
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
|
|
|
@ -85,7 +85,7 @@ public class MdmControllerSvcImplTest extends BaseLinkR4Test {
|
|||
|
||||
getGoldenResourceFromTargetResource(patient);
|
||||
|
||||
MdmLink link = myMdmLinkDaoSvc.findMdmLinkBySource(patient).get();
|
||||
MdmLink link = (MdmLink) myMdmLinkDaoSvc.findMdmLinkBySource(patient).get();
|
||||
link.setMatchResult(MdmMatchResultEnum.POSSIBLE_MATCH);
|
||||
saveLink(link);
|
||||
assertEquals(MdmLinkSourceEnum.AUTO, link.getLinkSource());
|
||||
|
@ -113,7 +113,7 @@ public class MdmControllerSvcImplTest extends BaseLinkR4Test {
|
|||
|
||||
getGoldenResourceFromTargetResource(patient);
|
||||
|
||||
MdmLink link = myMdmLinkDaoSvc.findMdmLinkBySource(patient).get();
|
||||
MdmLink link = (MdmLink) myMdmLinkDaoSvc.findMdmLinkBySource(patient).get();
|
||||
link.setMatchResult(MdmMatchResultEnum.POSSIBLE_DUPLICATE);
|
||||
saveLink(link);
|
||||
assertEquals(MdmLinkSourceEnum.AUTO, link.getLinkSource());
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package ca.uhn.fhir.jpa.mdm.svc;
|
||||
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLink;
|
||||
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchOutcome;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||
|
@ -9,8 +11,9 @@ import ca.uhn.fhir.mdm.model.MdmTransactionContext;
|
|||
import ca.uhn.fhir.interceptor.api.IInterceptorService;
|
||||
import ca.uhn.fhir.jpa.mdm.BaseMdmR4Test;
|
||||
import ca.uhn.fhir.jpa.mdm.helper.MdmLinkHelper;
|
||||
import ca.uhn.fhir.jpa.mdm.interceptor.IMdmStorageInterceptor;
|
||||
import ca.uhn.fhir.mdm.interceptor.IMdmStorageInterceptor;
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import ca.uhn.fhir.rest.server.TransactionLogMessages;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
@ -67,10 +70,10 @@ public class MdmGoldenResourceMergerSvcTest extends BaseMdmR4Test {
|
|||
public void before() {
|
||||
myFromGoldenPatient = createGoldenPatient();
|
||||
IdType fromSourcePatientId = myFromGoldenPatient.getIdElement().toUnqualifiedVersionless();
|
||||
myFromGoldenPatientPid = runInTransaction(()->myIdHelperService.getPidOrThrowException(fromSourcePatientId));
|
||||
myFromGoldenPatientPid = runInTransaction(()->myIdHelperService.getPidOrThrowException(RequestPartitionId.allPartitions(), fromSourcePatientId)).getIdAsLong();
|
||||
myToGoldenPatient = createGoldenPatient();
|
||||
IdType toGoldenPatientId = myToGoldenPatient.getIdElement().toUnqualifiedVersionless();
|
||||
myToGoldenPatientPid = runInTransaction(()->myIdHelperService.getPidOrThrowException(toGoldenPatientId));
|
||||
myToGoldenPatientPid = runInTransaction(()->myIdHelperService.getPidOrThrowException(RequestPartitionId.allPartitions(), toGoldenPatientId)).getIdAsLong();
|
||||
|
||||
myTargetPatient1 = createPatient();
|
||||
myTargetPatient2 = createPatient();
|
||||
|
@ -121,9 +124,9 @@ public class MdmGoldenResourceMergerSvcTest extends BaseMdmR4Test {
|
|||
|
||||
@Test
|
||||
public void mergeRemovesPossibleDuplicatesLink() {
|
||||
MdmLink mdmLink = myMdmLinkDaoSvc.newMdmLink()
|
||||
.setGoldenResourcePid(myToGoldenPatientPid)
|
||||
.setSourcePid(myFromGoldenPatientPid)
|
||||
MdmLink mdmLink = (MdmLink) myMdmLinkDaoSvc.newMdmLink()
|
||||
.setGoldenResourcePersistenceId(new ResourcePersistentId(myToGoldenPatientPid))
|
||||
.setSourcePersistenceId(new ResourcePersistentId(myFromGoldenPatientPid))
|
||||
.setMdmSourceType("Patient")
|
||||
.setMatchResult(MdmMatchResultEnum.POSSIBLE_DUPLICATE)
|
||||
.setLinkSource(MdmLinkSourceEnum.AUTO);
|
||||
|
@ -228,6 +231,7 @@ public class MdmGoldenResourceMergerSvcTest extends BaseMdmR4Test {
|
|||
private List<MdmLink> getNonRedirectLinksByGoldenResource(Patient theGoldenPatient) {
|
||||
return myMdmLinkDaoSvc.findMdmLinksByGoldenResource(theGoldenPatient).stream()
|
||||
.filter(link -> !link.isRedirect())
|
||||
.map( link -> (MdmLink) link)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
@ -340,7 +344,7 @@ public class MdmGoldenResourceMergerSvcTest extends BaseMdmR4Test {
|
|||
|
||||
|
||||
private void assertResourceHasLinkCount(IBaseResource theResource, int theCount) {
|
||||
List<MdmLink> links = myMdmLinkDaoSvc.findMdmLinksByGoldenResource(theResource);
|
||||
List<? extends IMdmLink> links = myMdmLinkDaoSvc.findMdmLinksByGoldenResource(theResource);
|
||||
assertEquals(theCount, links.size());
|
||||
}
|
||||
|
||||
|
@ -359,8 +363,8 @@ public class MdmGoldenResourceMergerSvcTest extends BaseMdmR4Test {
|
|||
}
|
||||
|
||||
private void assertResourceHasAutoLinkCount(Patient myToGoldenPatient, int theCount) {
|
||||
List<MdmLink> links = myMdmLinkDaoSvc.findMdmLinksByGoldenResource(myToGoldenPatient);
|
||||
assertEquals(theCount, links.stream().filter(MdmLink::isAuto).count());
|
||||
List<? extends IMdmLink> links = myMdmLinkDaoSvc.findMdmLinksByGoldenResource(myToGoldenPatient);
|
||||
assertEquals(theCount, links.stream().filter(IMdmLink::isAuto).count());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -456,7 +460,7 @@ public class MdmGoldenResourceMergerSvcTest extends BaseMdmR4Test {
|
|||
}
|
||||
|
||||
private MdmLink createMdmLink(Patient theSourcePatient, Patient theTargetPatient) {
|
||||
return myMdmLinkDaoSvc.createOrUpdateLinkEntity(theSourcePatient, theTargetPatient, POSSIBLE_MATCH, MdmLinkSourceEnum.AUTO, createContextForCreate("Patient"));
|
||||
return (MdmLink) myMdmLinkDaoSvc.createOrUpdateLinkEntity(theSourcePatient, theTargetPatient, POSSIBLE_MATCH, MdmLinkSourceEnum.AUTO, createContextForCreate("Patient"));
|
||||
}
|
||||
|
||||
private void populatePatient(Patient theSourcePatient) {
|
||||
|
|
|
@ -6,11 +6,13 @@ import ca.uhn.fhir.jpa.dao.expunge.ExpungeEverythingService;
|
|||
import ca.uhn.fhir.jpa.dao.expunge.IExpungeEverythingService;
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.jpa.mdm.BaseMdmR4Test;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLink;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLinkSvc;
|
||||
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchOutcome;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.hl7.fhir.r4.model.IdType;
|
||||
|
@ -88,10 +90,10 @@ public class MdmLinkSvcTest extends BaseMdmR4Test {
|
|||
Patient goldenPatient1 = createGoldenPatient();
|
||||
Patient goldenPatient2 = createGoldenPatient();
|
||||
|
||||
Long goldenPatient1Pid = runInTransaction(()->myIdHelperService.getPidOrNull(goldenPatient1));
|
||||
Long goldenPatient2Pid = runInTransaction(()->myIdHelperService.getPidOrNull(goldenPatient2));
|
||||
assertFalse(myMdmLinkDaoSvc.getLinkByGoldenResourcePidAndSourceResourcePid(goldenPatient1Pid, goldenPatient2Pid).isPresent());
|
||||
assertFalse(myMdmLinkDaoSvc.getLinkByGoldenResourcePidAndSourceResourcePid(goldenPatient2Pid, goldenPatient1Pid).isPresent());
|
||||
ResourcePersistentId goldenPatient1Pid = runInTransaction(()->myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), goldenPatient1));
|
||||
ResourcePersistentId goldenPatient2Pid = runInTransaction(()->myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), goldenPatient2));
|
||||
assertFalse(myMdmLinkDaoSvc.getLinkByGoldenResourcePidAndSourceResourcePid(goldenPatient1Pid.getIdAsLong(), goldenPatient2Pid.getIdAsLong()).isPresent());
|
||||
assertFalse(myMdmLinkDaoSvc.getLinkByGoldenResourcePidAndSourceResourcePid(goldenPatient2Pid.getIdAsLong(), goldenPatient1Pid.getIdAsLong()).isPresent());
|
||||
|
||||
saveNoMatchLink(goldenPatient1Pid, goldenPatient2Pid);
|
||||
|
||||
|
@ -106,10 +108,10 @@ public class MdmLinkSvcTest extends BaseMdmR4Test {
|
|||
Patient goldenPatient1 = createGoldenPatient();
|
||||
Patient goldenPatient2 = createGoldenPatient();
|
||||
|
||||
Long goldenPatient1Pid = runInTransaction(()->myIdHelperService.getPidOrNull(goldenPatient1));
|
||||
Long goldenPatient2Pid = runInTransaction(()->myIdHelperService.getPidOrNull(goldenPatient2));
|
||||
assertFalse(myMdmLinkDaoSvc.getLinkByGoldenResourcePidAndSourceResourcePid(goldenPatient1Pid, goldenPatient2Pid).isPresent());
|
||||
assertFalse(myMdmLinkDaoSvc.getLinkByGoldenResourcePidAndSourceResourcePid(goldenPatient2Pid, goldenPatient1Pid).isPresent());
|
||||
ResourcePersistentId goldenPatient1Pid = runInTransaction(()->myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), goldenPatient1));
|
||||
ResourcePersistentId goldenPatient2Pid = runInTransaction(()->myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), goldenPatient2));
|
||||
assertFalse(myMdmLinkDaoSvc.getLinkByGoldenResourcePidAndSourceResourcePid(goldenPatient1Pid.getIdAsLong(), goldenPatient2Pid.getIdAsLong()).isPresent());
|
||||
assertFalse(myMdmLinkDaoSvc.getLinkByGoldenResourcePidAndSourceResourcePid(goldenPatient2Pid.getIdAsLong(), goldenPatient1Pid.getIdAsLong()).isPresent());
|
||||
|
||||
saveNoMatchLink(goldenPatient2Pid, goldenPatient1Pid);
|
||||
|
||||
|
@ -118,12 +120,11 @@ public class MdmLinkSvcTest extends BaseMdmR4Test {
|
|||
assertLinkCount(1);
|
||||
}
|
||||
|
||||
private void saveNoMatchLink(Long theGoldenResourcePid, Long theTargetPid) {
|
||||
MdmLink noMatchLink = myMdmLinkDaoSvc.newMdmLink()
|
||||
.setGoldenResourcePid(theGoldenResourcePid)
|
||||
.setSourcePid(theTargetPid)
|
||||
.setLinkSource(MdmLinkSourceEnum.MANUAL)
|
||||
.setMatchResult(MdmMatchResultEnum.NO_MATCH);
|
||||
private void saveNoMatchLink(ResourcePersistentId theGoldenResourcePid, ResourcePersistentId theTargetPid) {
|
||||
MdmLink noMatchLink = (MdmLink) myMdmLinkDaoSvc.newMdmLink();
|
||||
noMatchLink.setGoldenResourcePersistenceId(theGoldenResourcePid);
|
||||
noMatchLink.setSourcePersistenceId(theTargetPid);
|
||||
noMatchLink.setLinkSource(MdmLinkSourceEnum.MANUAL).setMatchResult(MdmMatchResultEnum.NO_MATCH);
|
||||
saveLink(noMatchLink);
|
||||
}
|
||||
|
||||
|
@ -165,7 +166,7 @@ public class MdmLinkSvcTest extends BaseMdmR4Test {
|
|||
myMdmLinkDaoSvc.createOrUpdateLinkEntity(goldenPatient, patient1, MdmMatchOutcome.NEW_GOLDEN_RESOURCE_MATCH, MdmLinkSourceEnum.MANUAL, createContextForCreate("Patient"));
|
||||
myMdmLinkDaoSvc.createOrUpdateLinkEntity(goldenPatient, patient2, MdmMatchOutcome.NO_MATCH, MdmLinkSourceEnum.MANUAL, createContextForCreate("Patient"));
|
||||
|
||||
List<MdmLink> targets = myMdmLinkDaoSvc.findMdmLinksByGoldenResource(goldenPatient);
|
||||
List<? extends IMdmLink> targets = myMdmLinkDaoSvc.findMdmLinksByGoldenResource(goldenPatient);
|
||||
assertFalse(targets.isEmpty());
|
||||
assertEquals(2, targets.size());
|
||||
|
||||
|
@ -173,7 +174,7 @@ public class MdmLinkSvcTest extends BaseMdmR4Test {
|
|||
//assertEquals(patient1.getIdElement().toVersionless().getValue(), sourcePatient.getLinkFirstRep().getTarget().getReference());
|
||||
List<String> actual = targets
|
||||
.stream()
|
||||
.map(link -> link.getSourcePid().toString())
|
||||
.map(link -> link.getSourcePersistenceId().getId().toString())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<String> expected = Arrays.asList(patient1, patient2)
|
||||
|
@ -195,7 +196,7 @@ public class MdmLinkSvcTest extends BaseMdmR4Test {
|
|||
assertEquals(0, myMdmLinkDao.count());
|
||||
|
||||
myMdmLinkDaoSvc.createOrUpdateLinkEntity(goldenPatient, patient1, MdmMatchOutcome.NEW_GOLDEN_RESOURCE_MATCH, MdmLinkSourceEnum.MANUAL, createContextForCreate("Patient"));
|
||||
List<MdmLink> targets = myMdmLinkDaoSvc.findMdmLinksByGoldenResource(goldenPatient);
|
||||
List<? extends IMdmLink> targets = myMdmLinkDaoSvc.findMdmLinksByGoldenResource(goldenPatient);
|
||||
assertFalse(targets.isEmpty());
|
||||
assertEquals(1, targets.size());
|
||||
assertEquals(requestPartitionId.getFirstPartitionIdOrNull(), targets.get(0).getPartitionId().getPartitionId());
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
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.mdm.api.MdmConstants;
|
||||
import ca.uhn.fhir.mdm.model.CanonicalEID;
|
||||
import ca.uhn.fhir.mdm.util.EIDHelper;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.r4.model.Identifier;
|
||||
import org.hl7.fhir.r4.model.Patient;
|
||||
|
@ -140,20 +142,19 @@ public class MdmMatchLinkSvcMultipleEidModeTest extends BaseMdmR4Test {
|
|||
assertLinksCreatedNewResource(true, true, false);
|
||||
assertLinksMatchedByEid(false, false, true);
|
||||
|
||||
List<MdmLink> possibleDuplicates = myMdmLinkDaoSvc.getPossibleDuplicates();
|
||||
List<MdmLink> possibleDuplicates = (List<MdmLink>) myMdmLinkDaoSvc.getPossibleDuplicates();
|
||||
assertThat(possibleDuplicates, hasSize(1));
|
||||
|
||||
Patient finalPatient1 = patient1;
|
||||
Patient finalPatient2 = patient2;
|
||||
List<Long> duplicatePids = runInTransaction(()->Stream.of(finalPatient1, finalPatient2)
|
||||
.map(this::getGoldenResourceFromTargetResource)
|
||||
.map(myIdHelperService::getPidOrNull)
|
||||
List<ResourcePersistentId> duplicatePids = runInTransaction(()->Stream.of(finalPatient1, finalPatient2)
|
||||
.map(t -> myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), getGoldenResourceFromTargetResource(t)))
|
||||
.collect(Collectors.toList()));
|
||||
|
||||
//The two GoldenResources related to the patients should both show up in the only existing POSSIBLE_DUPLICATE MdmLink.
|
||||
MdmLink mdmLink = possibleDuplicates.get(0);
|
||||
assertThat(mdmLink.getGoldenResourcePid(), is(in(duplicatePids)));
|
||||
assertThat(mdmLink.getSourcePid(), is(in(duplicatePids)));
|
||||
assertThat(mdmLink.getGoldenResourcePersistenceId(), is(in(duplicatePids)));
|
||||
assertThat(mdmLink.getSourcePersistenceId(), is(in(duplicatePids)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -201,7 +202,7 @@ public class MdmMatchLinkSvcMultipleEidModeTest extends BaseMdmR4Test {
|
|||
assertThat(patient2, is(possibleMatchWith(patient1)));
|
||||
assertThat(patient2, is(possibleMatchWith(patient3)));
|
||||
|
||||
List<MdmLink> possibleDuplicates = myMdmLinkDaoSvc.getPossibleDuplicates();
|
||||
List<MdmLink> possibleDuplicates = (List<MdmLink>) myMdmLinkDaoSvc.getPossibleDuplicates();
|
||||
assertThat(possibleDuplicates, hasSize(1));
|
||||
assertThat(patient3, is(possibleDuplicateOf(patient1)));
|
||||
}
|
||||
|
|
|
@ -1,8 +1,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.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLink;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLinkSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLinkUpdaterSvc;
|
||||
import ca.uhn.fhir.mdm.api.MdmConstants;
|
||||
|
@ -14,6 +16,7 @@ import ca.uhn.fhir.mdm.util.EIDHelper;
|
|||
import ca.uhn.fhir.mdm.util.GoldenResourceHelper;
|
||||
import ca.uhn.fhir.mdm.util.MdmResourceUtil;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.r4.model.HumanName;
|
||||
|
@ -154,7 +157,7 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test {
|
|||
Patient janePatient = addExternalEID(buildJanePatient(), sampleEID);
|
||||
janePatient = createPatientAndUpdateLinks(janePatient);
|
||||
|
||||
Optional<MdmLink> mdmLink = myMdmLinkDaoSvc.getMatchedLinkForSourcePid(janePatient.getIdElement().getIdPartAsLong());
|
||||
Optional<? extends IMdmLink> mdmLink = myMdmLinkDaoSvc.getMatchedLinkForSourcePid(new ResourcePersistentId(janePatient.getIdElement().getIdPartAsLong()));
|
||||
assertThat(mdmLink.isPresent(), is(true));
|
||||
|
||||
Patient patient = getTargetResourceFromMdmLink(mdmLink.get(), "Patient");
|
||||
|
@ -167,7 +170,7 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test {
|
|||
@Test
|
||||
public void testWhenPatientIsCreatedWithoutAnEIDTheGoldenResourceGetsAutomaticallyAssignedOne() {
|
||||
Patient patient = createPatientAndUpdateLinks(buildJanePatient());
|
||||
MdmLink mdmLink = myMdmLinkDaoSvc.getMatchedLinkForSourcePid(patient.getIdElement().getIdPartAsLong()).get();
|
||||
IMdmLink mdmLink = myMdmLinkDaoSvc.getMatchedLinkForSourcePid(new ResourcePersistentId(patient.getIdElement().getIdPartAsLong())).get();
|
||||
|
||||
Patient targetPatient = getTargetResourceFromMdmLink(mdmLink, "Patient");
|
||||
Identifier identifierFirstRep = targetPatient.getIdentifierFirstRep();
|
||||
|
@ -179,7 +182,7 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test {
|
|||
public void testPatientAttributesAreCopiedOverWhenGoldenResourceIsCreatedFromPatient() {
|
||||
Patient patient = createPatientAndUpdateLinks(buildPatientWithNameIdAndBirthday("Gary", "GARY_ID", new Date()));
|
||||
|
||||
Optional<MdmLink> mdmLink = myMdmLinkDaoSvc.getMatchedLinkForSourcePid(patient.getIdElement().getIdPartAsLong());
|
||||
Optional<? extends IMdmLink> mdmLink = myMdmLinkDaoSvc.getMatchedLinkForSourcePid(new ResourcePersistentId(patient.getIdElement().getIdPartAsLong()));
|
||||
Patient read = getTargetResourceFromMdmLink(mdmLink.get(), "Patient");
|
||||
|
||||
assertThat(read.getNameFirstRep().getFamily(), is(equalTo(patient.getNameFirstRep().getFamily())));
|
||||
|
@ -268,20 +271,19 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test {
|
|||
Patient patient2 = addExternalEID(buildJanePatient(), "eid-2");
|
||||
patient2 = createPatientAndUpdateLinks(patient2);
|
||||
|
||||
List<MdmLink> possibleDuplicates = myMdmLinkDaoSvc.getPossibleDuplicates();
|
||||
List<MdmLink> possibleDuplicates = (List<MdmLink>) myMdmLinkDaoSvc.getPossibleDuplicates();
|
||||
assertThat(possibleDuplicates, hasSize(1));
|
||||
|
||||
Patient finalPatient1 = patient1;
|
||||
Patient finalPatient2 = patient2;
|
||||
List<Long> duplicatePids = runInTransaction(()->Stream.of(finalPatient1, finalPatient2)
|
||||
.map(this::getGoldenResourceFromTargetResource)
|
||||
.map(myIdHelperService::getPidOrNull)
|
||||
List<ResourcePersistentId> duplicatePids = runInTransaction(()->Stream.of(finalPatient1, finalPatient2)
|
||||
.map(t -> myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), getGoldenResourceFromTargetResource(t)))
|
||||
.collect(Collectors.toList()));
|
||||
|
||||
//The two GoldenResources related to the patients should both show up in the only existing POSSIBLE_DUPLICATE MdmLink.
|
||||
MdmLink mdmLink = possibleDuplicates.get(0);
|
||||
assertThat(mdmLink.getGoldenResourcePid(), is(in(duplicatePids)));
|
||||
assertThat(mdmLink.getSourcePid(), is(in(duplicatePids)));
|
||||
assertThat(mdmLink.getGoldenResourcePersistenceId(), is(in(duplicatePids)));
|
||||
assertThat(mdmLink.getSourcePersistenceId(), is(in(duplicatePids)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -366,7 +368,7 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test {
|
|||
assertThat(incomingJanePatient, is(possibleMatchWith(janePatient, janePatient2)));
|
||||
|
||||
//Ensure there is no successful MATCH links for incomingJanePatient
|
||||
Optional<MdmLink> matchedLinkForTargetPid = runInTransaction(()->myMdmLinkDaoSvc.getMatchedLinkForSourcePid(myIdHelperService.getPidOrNull(incomingJanePatient)));
|
||||
Optional<? extends IMdmLink> matchedLinkForTargetPid = runInTransaction(()->myMdmLinkDaoSvc.getMatchedLinkForSourcePid(myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), incomingJanePatient)));
|
||||
assertThat(matchedLinkForTargetPid.isPresent(), is(false));
|
||||
|
||||
logAllLinks();
|
||||
|
@ -589,7 +591,7 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test {
|
|||
}
|
||||
|
||||
private void assertNoDuplicates() {
|
||||
List<MdmLink> possibleDuplicates = myMdmLinkDaoSvc.getPossibleDuplicates();
|
||||
List<MdmLink> possibleDuplicates = (List<MdmLink>) myMdmLinkDaoSvc.getPossibleDuplicates();
|
||||
assertThat(possibleDuplicates, hasSize(0));
|
||||
}
|
||||
|
||||
|
@ -624,7 +626,7 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test {
|
|||
|
||||
assertThat(patient2, is(sameGoldenResourceAs(patient1)));
|
||||
|
||||
List<MdmLink> possibleDuplicates = myMdmLinkDaoSvc.getPossibleDuplicates();
|
||||
List<MdmLink> possibleDuplicates = (List<MdmLink>) myMdmLinkDaoSvc.getPossibleDuplicates();
|
||||
assertThat(possibleDuplicates, hasSize(1));
|
||||
assertThat(patient3, is(possibleDuplicateOf(patient1)));
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package ca.uhn.fhir.jpa.mdm.svc;
|
|||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.mdm.api.IMdmSettings;
|
||||
import ca.uhn.fhir.mdm.rules.json.MdmRulesJson;
|
||||
import ca.uhn.fhir.mdm.svc.MdmSearchParamSvc;
|
||||
import org.hl7.fhir.r4.model.Patient;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
|
|
@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.mdm.svc.candidate;
|
|||
|
||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.mdm.svc.MdmSearchParamSvc;
|
||||
import ca.uhn.fhir.mdm.svc.MdmSearchParamSvc;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.mdm.api.IMdmRuleValidator;
|
||||
import ca.uhn.fhir.mdm.rules.config.MdmSettings;
|
||||
|
|
|
@ -31,7 +31,7 @@ class MdmGoldenResourceFindingSvcTest extends BaseMdmR4Test {
|
|||
Patient jane = createPatientAndUpdateLinks(addExternalEID(buildJanePatient(), EID_1));
|
||||
|
||||
// hack the link into a NO_MATCH
|
||||
List<MdmLink> links = myMdmLinkDaoSvc.findMdmLinksBySourceResource(jane);
|
||||
List<MdmLink> links = (List<MdmLink>) myMdmLinkDaoSvc.findMdmLinksBySourceResource(jane);
|
||||
assertThat(links, hasSize(1));
|
||||
MdmLink link = links.get(0);
|
||||
link.setMatchResult(MdmMatchResultEnum.NO_MATCH);
|
||||
|
|
|
@ -53,8 +53,8 @@ class MdmClearStepTest extends BaseMdmR4Test {
|
|||
goldenPatient.setId(myGoldenId);
|
||||
myPatientDao.update(goldenPatient);
|
||||
|
||||
mySourcePid = myIdHelperService.getPidOrThrowException(sourcePatient);
|
||||
myGoldenPid = myIdHelperService.getPidOrThrowException(goldenPatient);
|
||||
mySourcePid = myIdHelperService.getPidOrThrowException(sourcePatient).getIdAsLong();
|
||||
myGoldenPid = myIdHelperService.getPidOrThrowException(goldenPatient).getIdAsLong();
|
||||
|
||||
myLink = buildMdmLink(mySourcePid, myGoldenPid);
|
||||
myMdmLinkDaoSvc.save(myLink);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.1.0-PRE24-SNAPSHOT</version>
|
||||
<version>6.1.0-PRE25-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue