adding metrics (#5301)
* hapi metrics * step 1 * metrics service * adding metrics service * adding documentation * refactor * refactoring * cleanup * changing * adding changelog * some refactoring * format * review fixes part 1 * review points * review fixes * updates for code review * updates for code review * bumping versions --------- Co-authored-by: leif stawnyczy <leifstawnyczy@leifs-mbp.home> Co-authored-by: leif stawnyczy <leifstawnyczy@leifs-MacBook-Pro.local>
This commit is contained in:
parent
c3ff3dae82
commit
7e0fa9833c
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>6.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-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.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-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.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-bom</artifactId>
|
||||
<version>6.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-SNAPSHOT</version>
|
||||
|
||||
<packaging>pom</packaging>
|
||||
<name>HAPI FHIR BOM</name>
|
||||
|
@ -12,7 +12,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-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.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-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.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-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.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>6.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-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.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-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.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-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.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-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.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-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.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
type: add
|
||||
issue: 5274
|
||||
title: "Added a service for generating metrics on mdm links and resources.
|
||||
This includes JPA queries and updated indices.
|
||||
"
|
|
@ -11,7 +11,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-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.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-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.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-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.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository("metricsRepository")
|
||||
public interface IMdmLinkJpaMetricsRepository extends JpaRepository<MdmLink, Long>, IHapiFhirJpaRepository {
|
||||
|
||||
@Query("SELECT ml.myMatchResult AS match_result, ml.myLinkSource AS link_source, count(*) AS c "
|
||||
+ "FROM MdmLink ml "
|
||||
+ "WHERE ml.myMdmSourceType = :resourceName "
|
||||
+ "AND ml.myLinkSource in (:linkSource) "
|
||||
+ "AND ml.myMatchResult in (:matchResult) "
|
||||
+ "GROUP BY match_result, link_source "
|
||||
+ "ORDER BY match_result")
|
||||
Object[][] generateMetrics(
|
||||
@Param("resourceName") String theResourceType,
|
||||
@Param("linkSource") List<MdmLinkSourceEnum> theLinkSources,
|
||||
@Param("matchResult") List<MdmMatchResultEnum> theMatchTypes);
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
package ca.uhn.fhir.jpa.dao.mdm;
|
||||
|
||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.jpa.dao.data.IMdmLinkJpaMetricsRepository;
|
||||
import ca.uhn.fhir.mdm.api.BaseMdmMetricSvc;
|
||||
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||
import ca.uhn.fhir.mdm.api.params.GenerateMdmMetricsParameters;
|
||||
import ca.uhn.fhir.mdm.model.MdmLinkMetrics;
|
||||
import ca.uhn.fhir.mdm.model.MdmLinkScoreMetrics;
|
||||
import ca.uhn.fhir.mdm.model.MdmMetrics;
|
||||
import ca.uhn.fhir.mdm.model.MdmResourceMetrics;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.Query;
|
||||
|
||||
public class MdmMetricSvcJpaImpl extends BaseMdmMetricSvc {
|
||||
|
||||
private final IMdmLinkJpaMetricsRepository myJpaRepository;
|
||||
|
||||
private final EntityManagerFactory myEntityManagerFactory;
|
||||
|
||||
public MdmMetricSvcJpaImpl(
|
||||
IMdmLinkJpaMetricsRepository theRepository,
|
||||
DaoRegistry theDaoRegistry,
|
||||
EntityManagerFactory theEntityManagerFactory) {
|
||||
super(theDaoRegistry);
|
||||
myJpaRepository = theRepository;
|
||||
myEntityManagerFactory = theEntityManagerFactory;
|
||||
}
|
||||
|
||||
protected MdmLinkMetrics generateLinkMetrics(GenerateMdmMetricsParameters theParameters) {
|
||||
List<MdmLinkSourceEnum> linkSources = theParameters.getLinkSourceFilters();
|
||||
List<MdmMatchResultEnum> matchResults = theParameters.getMatchResultFilters();
|
||||
|
||||
if (linkSources.isEmpty()) {
|
||||
linkSources = Arrays.asList(MdmLinkSourceEnum.values());
|
||||
}
|
||||
if (matchResults.isEmpty()) {
|
||||
matchResults = Arrays.asList(MdmMatchResultEnum.values());
|
||||
}
|
||||
|
||||
Object[][] data = myJpaRepository.generateMetrics(theParameters.getResourceType(), linkSources, matchResults);
|
||||
MdmLinkMetrics metrics = new MdmLinkMetrics();
|
||||
metrics.setResourceType(theParameters.getResourceType());
|
||||
for (Object[] row : data) {
|
||||
MdmMatchResultEnum matchResult = (MdmMatchResultEnum) row[0];
|
||||
MdmLinkSourceEnum source = (MdmLinkSourceEnum) row[1];
|
||||
long count = (Long) row[2];
|
||||
metrics.addMetric(matchResult, source, count);
|
||||
}
|
||||
return metrics;
|
||||
}
|
||||
|
||||
protected MdmLinkScoreMetrics generateLinkScoreMetrics(GenerateMdmMetricsParameters theParameters) {
|
||||
String resourceType = theParameters.getResourceType();
|
||||
|
||||
List<MdmMatchResultEnum> matchResultTypes = theParameters.getMatchResultFilters();
|
||||
|
||||
// if no result type filter, add all result types
|
||||
if (matchResultTypes.isEmpty()) {
|
||||
matchResultTypes = Arrays.asList(MdmMatchResultEnum.values());
|
||||
}
|
||||
|
||||
String sql = "SELECT %s FROM MPI_LINK ml WHERE ml.TARGET_TYPE = :resourceType "
|
||||
+ "AND ml.MATCH_RESULT in (:matchResult)";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("sum(case when ml.SCORE is null then 1 else 0 end) as B_" + NULL_VALUE);
|
||||
|
||||
for (int i = 0; i < BUCKETS; i++) {
|
||||
double bucket = getBucket(i + 1);
|
||||
sb.append(",\n");
|
||||
if (i == 0) {
|
||||
// score <= .01
|
||||
sb.append(String.format("sum(case when ml.SCORE <= %.2f then 1 else 0 end) as B%d", bucket, i));
|
||||
} else {
|
||||
// score > i/100 && score <= i/100
|
||||
sb.append(String.format(
|
||||
"sum(case when ml.score > %.2f and ml.SCORE <= %.2f then 1 else 0 end) as B%d",
|
||||
getBucket(i), bucket, i));
|
||||
}
|
||||
}
|
||||
|
||||
EntityManager em = myEntityManagerFactory.createEntityManager();
|
||||
|
||||
Query nativeQuery = em.createNativeQuery(String.format(sql, sb.toString()));
|
||||
|
||||
org.hibernate.query.Query<?> hibernateQuery = (org.hibernate.query.Query<?>) nativeQuery;
|
||||
|
||||
hibernateQuery.setParameter("resourceType", resourceType);
|
||||
hibernateQuery.setParameter(
|
||||
"matchResult", matchResultTypes.stream().map(Enum::ordinal).collect(Collectors.toList()));
|
||||
|
||||
List<?> results = hibernateQuery.getResultList();
|
||||
|
||||
em.close();
|
||||
|
||||
MdmLinkScoreMetrics metrics = new MdmLinkScoreMetrics();
|
||||
|
||||
// we only get one row back
|
||||
Object[] row = (Object[]) results.get(0);
|
||||
int length = row.length;
|
||||
for (int i = 0; i < length; i++) {
|
||||
// if there's nothing in the db, these values will all be null
|
||||
BigInteger bi = row[i] != null ? (BigInteger) row[i] : BigInteger.valueOf(0);
|
||||
double bucket = getBucket(i);
|
||||
if (i == 0) {
|
||||
metrics.addScore(NULL_VALUE, bi.longValue());
|
||||
} else if (i == 1) {
|
||||
metrics.addScore(String.format(FIRST_BUCKET, bucket), bi.longValue());
|
||||
} else {
|
||||
metrics.addScore(String.format(NTH_BUCKET, getBucket(i - 1), bucket), bi.longValue());
|
||||
}
|
||||
}
|
||||
|
||||
return metrics;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public MdmMetrics generateMdmMetrics(GenerateMdmMetricsParameters theParameters) {
|
||||
MdmResourceMetrics resourceMetrics = generateResourceMetrics(theParameters);
|
||||
MdmLinkMetrics linkMetrics = generateLinkMetrics(theParameters);
|
||||
MdmLinkScoreMetrics scoreMetrics = generateLinkScoreMetrics(theParameters);
|
||||
|
||||
MdmMetrics metrics = MdmMetrics.fromSeperableMetrics(resourceMetrics, linkMetrics, scoreMetrics);
|
||||
return metrics;
|
||||
}
|
||||
}
|
|
@ -64,7 +64,10 @@ import javax.persistence.UniqueConstraint;
|
|||
@Index(name = "IDX_EMPI_MATCH_TGT_VER", columnList = "MATCH_RESULT, TARGET_PID, VERSION"),
|
||||
// v---- this one
|
||||
@Index(name = "IDX_EMPI_GR_TGT", columnList = "GOLDEN_RESOURCE_PID, TARGET_PID"),
|
||||
@Index(name = "FK_EMPI_LINK_TARGET", columnList = "TARGET_PID")
|
||||
@Index(name = "FK_EMPI_LINK_TARGET", columnList = "TARGET_PID"),
|
||||
// indexes for metrics
|
||||
@Index(name = "IDX_EMPI_TGT_MR_LS", columnList = "TARGET_TYPE, MATCH_RESULT, LINK_SOURCE"),
|
||||
@Index(name = "IDX_EMPI_TGT_MR_SCORE", columnList = "TARGET_TYPE, MATCH_RESULT, SCORE")
|
||||
})
|
||||
@Audited
|
||||
// This is the table name generated by default by envers, but we set it explicitly for clarity
|
||||
|
|
|
@ -93,6 +93,23 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks<VersionEnum> {
|
|||
init640_after_20230126();
|
||||
init660();
|
||||
init680();
|
||||
init700();
|
||||
}
|
||||
|
||||
protected void init700() {
|
||||
Builder version = forVersion(VersionEnum.V7_0_0);
|
||||
|
||||
// new indices on MdmLink
|
||||
Builder.BuilderWithTableName mdmLinkTable = version.onTable("MPI_LINK");
|
||||
|
||||
mdmLinkTable
|
||||
.addIndex("20230911.1", "IDX_EMPI_TGT_MR_LS")
|
||||
.unique(false)
|
||||
.withColumns("TARGET_TYPE", "MATCH_RESULT", "LINK_SOURCE");
|
||||
mdmLinkTable
|
||||
.addIndex("20230911.2", "IDX_EMPi_TGT_MR_SCore")
|
||||
.unique(false)
|
||||
.withColumns("TARGET_TYPE", "MATCH_RESULT", "SCORE");
|
||||
}
|
||||
|
||||
protected void init680() {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-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.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ import ca.uhn.fhir.jpa.mdm.svc.MdmLinkUpdaterSvcImpl;
|
|||
import ca.uhn.fhir.jpa.mdm.svc.MdmMatchFinderSvcImpl;
|
||||
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.MdmResourceDaoSvcImpl;
|
||||
import ca.uhn.fhir.jpa.mdm.svc.MdmResourceFilteringSvc;
|
||||
import ca.uhn.fhir.jpa.mdm.svc.candidate.CandidateSearcher;
|
||||
import ca.uhn.fhir.jpa.mdm.svc.candidate.FindCandidateByEidSvc;
|
||||
|
@ -57,6 +57,7 @@ import ca.uhn.fhir.mdm.api.IMdmLinkQuerySvc;
|
|||
import ca.uhn.fhir.mdm.api.IMdmLinkSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLinkUpdaterSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmMatchFinderSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmResourceDaoSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmSettings;
|
||||
import ca.uhn.fhir.mdm.batch2.MdmBatch2Config;
|
||||
import ca.uhn.fhir.mdm.blocklist.svc.IBlockListRuleProvider;
|
||||
|
@ -123,8 +124,8 @@ public class MdmConsumerConfig {
|
|||
}
|
||||
|
||||
@Bean
|
||||
MdmResourceDaoSvc mdmResourceDaoSvc() {
|
||||
return new MdmResourceDaoSvc();
|
||||
IMdmResourceDaoSvc mdmResourceDaoSvc() {
|
||||
return new MdmResourceDaoSvcImpl();
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
|
|
@ -29,6 +29,7 @@ import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc;
|
|||
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.IMdmResourceDaoSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmSurvivorshipService;
|
||||
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchOutcome;
|
||||
|
@ -74,7 +75,7 @@ public class GoldenResourceMergerSvcImpl implements IGoldenResourceMergerSvc {
|
|||
IIdHelperService myIdHelperService;
|
||||
|
||||
@Autowired
|
||||
MdmResourceDaoSvc myMdmResourceDaoSvc;
|
||||
IMdmResourceDaoSvc myMdmResourceDaoSvc;
|
||||
|
||||
@Autowired
|
||||
MdmPartitionHelper myMdmPartitionHelper;
|
||||
|
|
|
@ -24,6 +24,7 @@ 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.IMdmResourceDaoSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmSettings;
|
||||
import ca.uhn.fhir.mdm.api.IMdmSurvivorshipService;
|
||||
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
||||
|
@ -49,7 +50,7 @@ public class MdmEidUpdateService {
|
|||
private static final Logger ourLog = Logs.getMdmTroubleshootingLog();
|
||||
|
||||
@Autowired
|
||||
private MdmResourceDaoSvc myMdmResourceDaoSvc;
|
||||
private IMdmResourceDaoSvc myMdmResourceDaoSvc;
|
||||
|
||||
@Autowired
|
||||
private IMdmLinkSvc myMdmLinkSvc;
|
||||
|
|
|
@ -25,6 +25,7 @@ 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.IMdmResourceDaoSvc;
|
||||
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchOutcome;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||
|
@ -51,7 +52,7 @@ public class MdmLinkSvcImpl implements IMdmLinkSvc {
|
|||
private static final Logger ourLog = Logs.getMdmTroubleshootingLog();
|
||||
|
||||
@Autowired
|
||||
private MdmResourceDaoSvc myMdmResourceDaoSvc;
|
||||
private IMdmResourceDaoSvc myMdmResourceDaoSvc;
|
||||
|
||||
@Autowired
|
||||
private MdmLinkDaoSvc myMdmLinkDaoSvc;
|
||||
|
|
|
@ -30,6 +30,7 @@ import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc;
|
|||
import ca.uhn.fhir.jpa.model.entity.PartitionablePartitionId;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLink;
|
||||
import ca.uhn.fhir.mdm.api.IMdmLinkUpdaterSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmResourceDaoSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmSettings;
|
||||
import ca.uhn.fhir.mdm.api.IMdmSurvivorshipService;
|
||||
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
||||
|
@ -72,7 +73,7 @@ public class MdmLinkUpdaterSvcImpl implements IMdmLinkUpdaterSvc {
|
|||
MdmLinkDaoSvc myMdmLinkDaoSvc;
|
||||
|
||||
@Autowired
|
||||
MdmResourceDaoSvc myMdmResourceDaoSvc;
|
||||
IMdmResourceDaoSvc myMdmResourceDaoSvc;
|
||||
|
||||
@Autowired
|
||||
MdmMatchLinkSvc myMdmMatchLinkSvc;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
package ca.uhn.fhir.jpa.mdm.svc;
|
||||
|
||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.jpa.mdm.models.FindGoldenResourceCandidatesParams;
|
||||
import ca.uhn.fhir.jpa.mdm.svc.candidate.CandidateList;
|
||||
import ca.uhn.fhir.jpa.mdm.svc.candidate.CandidateStrategyEnum;
|
||||
|
@ -70,6 +71,9 @@ public class MdmMatchLinkSvc {
|
|||
@Autowired
|
||||
private IBlockRuleEvaluationSvc myBlockRuleEvaluationSvc;
|
||||
|
||||
@Autowired
|
||||
private DaoRegistry myDaoRegistry;
|
||||
|
||||
@Autowired
|
||||
private IMdmSurvivorshipService myMdmSurvivorshipService;
|
||||
|
||||
|
@ -106,6 +110,8 @@ public class MdmMatchLinkSvc {
|
|||
* (so that future resources may match to it).
|
||||
*/
|
||||
boolean isResourceBlocked = myBlockRuleEvaluationSvc.isMdmMatchingBlocked(theResource);
|
||||
// we will mark the golden resource special for this
|
||||
theMdmTransactionContext.setIsBlocked(isResourceBlocked);
|
||||
|
||||
if (!isResourceBlocked) {
|
||||
FindGoldenResourceCandidatesParams params =
|
||||
|
|
|
@ -26,14 +26,15 @@ import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
|||
import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome;
|
||||
import ca.uhn.fhir.jpa.model.entity.TagTypeEnum;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.mdm.api.IMdmResourceDaoSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmSettings;
|
||||
import ca.uhn.fhir.mdm.api.MdmConstants;
|
||||
import ca.uhn.fhir.mdm.util.MdmSearchParamBuildingUtils;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.api.server.SystemRequestDetails;
|
||||
import ca.uhn.fhir.rest.api.server.storage.IResourcePersistentId;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
@ -42,10 +43,9 @@ import org.springframework.stereotype.Service;
|
|||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@Service
|
||||
public class MdmResourceDaoSvc {
|
||||
public class MdmResourceDaoSvcImpl implements IMdmResourceDaoSvc {
|
||||
|
||||
private static final int MAX_MATCHING_GOLDEN_RESOURCES = 1000;
|
||||
|
||||
|
@ -55,6 +55,7 @@ public class MdmResourceDaoSvc {
|
|||
@Autowired
|
||||
IMdmSettings myMdmSettings;
|
||||
|
||||
@Override
|
||||
public DaoMethodOutcome upsertGoldenResource(IAnyResource theGoldenResource, String theResourceType) {
|
||||
IFhirResourceDao resourceDao = myDaoRegistry.getResourceDao(theResourceType);
|
||||
RequestDetails requestDetails = new SystemRequestDetails().setRequestPartitionId((RequestPartitionId)
|
||||
|
@ -66,12 +67,7 @@ public class MdmResourceDaoSvc {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a resource, remove its Golden Resource tag.
|
||||
*
|
||||
* @param theGoldenResource the {@link IAnyResource} to remove the tag from.
|
||||
* @param theResourcetype the type of that resource
|
||||
*/
|
||||
@Override
|
||||
public void removeGoldenResourceTag(IAnyResource theGoldenResource, String theResourcetype) {
|
||||
IFhirResourceDao resourceDao = myDaoRegistry.getResourceDao(theResourcetype);
|
||||
RequestDetails requestDetails = new SystemRequestDetails().setRequestPartitionId((RequestPartitionId)
|
||||
|
@ -84,18 +80,22 @@ public class MdmResourceDaoSvc {
|
|||
requestDetails);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAnyResource readGoldenResourceByPid(IResourcePersistentId theGoldenResourcePid, String theResourceType) {
|
||||
IFhirResourceDao resourceDao = myDaoRegistry.getResourceDao(theResourceType);
|
||||
return (IAnyResource) resourceDao.readByPid(theGoldenResourcePid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<IAnyResource> searchGoldenResourceByEID(String theEid, String theResourceType) {
|
||||
return this.searchGoldenResourceByEID(theEid, theResourceType, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<IAnyResource> searchGoldenResourceByEID(
|
||||
String theEid, String theResourceType, RequestPartitionId thePartitionId) {
|
||||
SearchParameterMap map = buildEidSearchParameterMap(theEid, theResourceType);
|
||||
SearchParameterMap map = MdmSearchParamBuildingUtils.buildEidSearchParameterMap(
|
||||
theEid, theResourceType, myMdmSettings.getMdmRules());
|
||||
|
||||
IFhirResourceDao resourceDao = myDaoRegistry.getResourceDao(theResourceType);
|
||||
SystemRequestDetails systemRequestDetails = new SystemRequestDetails();
|
||||
|
@ -118,16 +118,4 @@ public class MdmResourceDaoSvc {
|
|||
return Optional.of((IAnyResource) resources.get(0));
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private SearchParameterMap buildEidSearchParameterMap(String theEid, String theResourceType) {
|
||||
SearchParameterMap map = new SearchParameterMap();
|
||||
map.setLoadSynchronous(true);
|
||||
map.add(
|
||||
"identifier",
|
||||
new TokenParam(
|
||||
myMdmSettings.getMdmRules().getEnterpriseEIDSystemForResourceType(theResourceType), theEid));
|
||||
map.add("_tag", new TokenParam(MdmConstants.SYSTEM_GOLDEN_RECORD_STATUS, MdmConstants.CODE_GOLDEN_RECORD));
|
||||
return map;
|
||||
}
|
||||
}
|
|
@ -21,8 +21,8 @@ package ca.uhn.fhir.jpa.mdm.svc.candidate;
|
|||
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
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.IMdmResourceDaoSvc;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchOutcome;
|
||||
import ca.uhn.fhir.mdm.log.Logs;
|
||||
import ca.uhn.fhir.mdm.model.CanonicalEID;
|
||||
|
@ -47,7 +47,7 @@ public class FindCandidateByEidSvc extends BaseCandidateFinder {
|
|||
private EIDHelper myEIDHelper;
|
||||
|
||||
@Autowired
|
||||
private MdmResourceDaoSvc myMdmResourceDaoSvc;
|
||||
private IMdmResourceDaoSvc myMdmResourceDaoSvc;
|
||||
|
||||
@Autowired
|
||||
private MdmLinkDaoSvc myMdmLinkDaoSvc;
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
package ca.uhn.fhir.jpa.mdm.svc.candidate;
|
||||
|
||||
import ca.uhn.fhir.jpa.mdm.models.FindGoldenResourceCandidatesParams;
|
||||
import ca.uhn.fhir.jpa.mdm.svc.MdmResourceDaoSvc;
|
||||
import ca.uhn.fhir.mdm.api.IMdmResourceDaoSvc;
|
||||
import ca.uhn.fhir.mdm.log.Logs;
|
||||
import ca.uhn.fhir.mdm.model.MdmTransactionContext;
|
||||
import ca.uhn.fhir.rest.api.server.storage.IResourcePersistentId;
|
||||
|
@ -36,7 +36,7 @@ public class MdmGoldenResourceFindingSvc {
|
|||
private static final Logger ourLog = Logs.getMdmTroubleshootingLog();
|
||||
|
||||
@Autowired
|
||||
private MdmResourceDaoSvc myMdmResourceDaoSvc;
|
||||
private IMdmResourceDaoSvc myMdmResourceDaoSvc;
|
||||
|
||||
@Autowired
|
||||
private FindCandidateByEidSvc myFindCandidateByEidSvc;
|
||||
|
|
|
@ -98,8 +98,6 @@ abstract public class BaseMdmR4Test extends BaseJpaR4Test {
|
|||
.setValue("555-555-5555");
|
||||
private static final String NAME_GIVEN_FRANK = "Frank";
|
||||
|
||||
|
||||
|
||||
@Autowired
|
||||
protected IFhirResourceDao<Patient> myPatientDao;
|
||||
@Autowired
|
||||
|
|
|
@ -0,0 +1,172 @@
|
|||
package ca.uhn.fhir.jpa.mdm.dao;
|
||||
|
||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.jpa.config.HapiFhirLocalContainerEntityManagerFactoryBean;
|
||||
import ca.uhn.fhir.jpa.dao.data.IMdmLinkJpaMetricsRepository;
|
||||
import ca.uhn.fhir.jpa.dao.mdm.MdmMetricSvcJpaImpl;
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.jpa.mdm.BaseMdmR4Test;
|
||||
import ca.uhn.fhir.jpa.mdm.IMdmMetricSvcTest;
|
||||
import ca.uhn.fhir.jpa.mdm.helper.MdmLinkHelper;
|
||||
import ca.uhn.fhir.jpa.mdm.helper.testmodels.MDMState;
|
||||
import ca.uhn.fhir.jpa.mdm.models.GenerateMetricsTestParameters;
|
||||
import ca.uhn.fhir.jpa.mdm.models.LinkMetricTestParameters;
|
||||
import ca.uhn.fhir.jpa.mdm.models.LinkScoreMetricTestParams;
|
||||
import ca.uhn.fhir.jpa.mdm.models.ResourceMetricTestParams;
|
||||
import ca.uhn.fhir.jpa.model.dao.JpaPid;
|
||||
import ca.uhn.fhir.mdm.api.IMdmMetricSvc;
|
||||
import ca.uhn.fhir.mdm.model.MdmMetrics;
|
||||
import ca.uhn.fhir.mdm.util.MdmResourceUtil;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hl7.fhir.r4.model.Patient;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
@ContextConfiguration(classes = {
|
||||
MdmMetricSvcJpaIT.TestConfig.class
|
||||
})
|
||||
public class MdmMetricSvcJpaIT extends BaseMdmR4Test implements IMdmMetricSvcTest {
|
||||
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(MdmMetricSvcJpaIT.class);
|
||||
|
||||
@Configuration
|
||||
public static class TestConfig {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("metricsRepository")
|
||||
private IMdmLinkJpaMetricsRepository myJpaRepository;
|
||||
|
||||
@Autowired
|
||||
private DaoRegistry myDaoRegistry;
|
||||
|
||||
@Autowired
|
||||
private EntityManagerFactory myEntityManagerFactory;
|
||||
|
||||
@Autowired
|
||||
private HapiFhirLocalContainerEntityManagerFactoryBean myEntityFactory;
|
||||
|
||||
// this has to be provided via spring, or the
|
||||
// @Transactional barrier is never invoked
|
||||
@Bean
|
||||
IMdmMetricSvc mdmMetricSvc() {
|
||||
return new MdmMetricSvcJpaImpl(
|
||||
myJpaRepository,
|
||||
myDaoRegistry,
|
||||
myEntityManagerFactory
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private final ObjectMapper myObjectMapper = new ObjectMapper();
|
||||
|
||||
@Autowired
|
||||
private MdmLinkHelper myLinkHelper;
|
||||
|
||||
@Autowired
|
||||
private IMdmMetricSvc mySvc;
|
||||
|
||||
@BeforeEach
|
||||
public void before() throws Exception {
|
||||
super.before();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMdmMetricSvc getMetricsSvc() {
|
||||
return mySvc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateMdmMetricsSetup(GenerateMetricsTestParameters theParameters) {
|
||||
if (StringUtils.isNotBlank(theParameters.getInitialState())) {
|
||||
MDMState<Patient, JpaPid> state = new MDMState<>();
|
||||
state.setInputState(theParameters.getInitialState());
|
||||
myLinkHelper.setup(state);
|
||||
|
||||
// update scores if needed
|
||||
setupScores(theParameters.getScores());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateLinkMetricsSetup(LinkMetricTestParameters theParameters) {
|
||||
ourLog.info(theParameters.getInitialState());
|
||||
if (StringUtils.isNotBlank(theParameters.getInitialState())) {
|
||||
// we can only initialize the state if there is a state to initialize
|
||||
MDMState<Patient, JpaPid> state = new MDMState<>();
|
||||
state.setInputState(theParameters.getInitialState());
|
||||
myLinkHelper.setup(state);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateResourceMetricsSetup(ResourceMetricTestParams theParams) {
|
||||
MDMState<Patient, JpaPid> state = new MDMState<>();
|
||||
String initialState = theParams.getInitialState();
|
||||
if (StringUtils.isNotBlank(initialState)) {
|
||||
state.setInputState(initialState);
|
||||
|
||||
for (String forcedBlockedGRId : theParams.getBlockedResourceGoldenResourceIds()) {
|
||||
Patient gr = new Patient();
|
||||
gr.setActive(true);
|
||||
gr.setId("Patient/" + forcedBlockedGRId);
|
||||
MdmResourceUtil.setMdmManaged(gr);
|
||||
MdmResourceUtil.setGoldenResource(gr);
|
||||
MdmResourceUtil.setGoldenResourceAsBlockedResourceGoldenResource(gr);
|
||||
|
||||
Patient p = createPatient(gr, true, false);
|
||||
state.addParameter(forcedBlockedGRId, p);
|
||||
}
|
||||
|
||||
myLinkHelper.setup(state);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateLinkScoreMetricsSetup(LinkScoreMetricTestParams theParams) {
|
||||
MDMState<Patient, JpaPid> state = new MDMState<>();
|
||||
String initialState = theParams.getInitialState();
|
||||
|
||||
if (StringUtils.isNotBlank(initialState)) {
|
||||
state.setInputState(initialState);
|
||||
|
||||
myLinkHelper.setup(state);
|
||||
|
||||
// update scores if needed
|
||||
setupScores(theParams.getScores());
|
||||
}
|
||||
}
|
||||
|
||||
private void setupScores(List<Double> theParams) {
|
||||
List<MdmLink> links = myMdmLinkDao.findAll();
|
||||
for (int i = 0; i < theParams.size() && i < links.size(); i++) {
|
||||
Double score = theParams.get(i);
|
||||
MdmLink link = links.get(i);
|
||||
link.setScore(score);
|
||||
myMdmLinkDao.save(link);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStringMetrics(MdmMetrics theMetrics) {
|
||||
try {
|
||||
return myObjectMapper.writeValueAsString(theMetrics);
|
||||
} catch (JsonProcessingException ex) {
|
||||
// we've failed anyway - we might as well display the exception
|
||||
fail(ex);
|
||||
return "NOT PARSEABLE!";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -41,7 +41,7 @@ class MdmLinkUpdaterSvcImplIT extends BaseMdmR4Test {
|
|||
private IMdmLinkUpdaterSvc myMdmLinkUpdaterSvc;
|
||||
|
||||
@Autowired
|
||||
private MdmResourceDaoSvc myMdmResourceDaoSvc;
|
||||
private MdmResourceDaoSvcImpl myMdmResourceDaoSvc;
|
||||
|
||||
@Autowired
|
||||
private MessageHelper myMessageHelper;
|
||||
|
|
|
@ -7,13 +7,13 @@ import ca.uhn.fhir.jpa.mdm.BaseMdmR4Test;
|
|||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.searchparam.extractor.ISearchParamExtractor;
|
||||
import ca.uhn.fhir.mdm.api.IMdmResourceDaoSvc;
|
||||
import ca.uhn.fhir.mdm.util.MdmResourceUtil;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.api.server.SystemRequestDetails;
|
||||
import ca.uhn.fhir.rest.param.StringOrListParam;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.r4.model.Patient;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
|
@ -21,7 +21,6 @@ import org.junit.jupiter.api.Test;
|
|||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
|
@ -35,7 +34,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
|||
public class MdmResourceDaoSvcTest extends BaseMdmR4Test {
|
||||
private static final String TEST_EID = "TEST_EID";
|
||||
@Autowired
|
||||
MdmResourceDaoSvc myResourceDaoSvc;
|
||||
IMdmResourceDaoSvc myResourceDaoSvc;
|
||||
@Autowired
|
||||
private ISearchParamExtractor mySearchParamExtractor;
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-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.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-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.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-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.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-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.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-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.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-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.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-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.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-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.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -0,0 +1,177 @@
|
|||
package ca.uhn.fhir.jpa.mdm;
|
||||
|
||||
import ca.uhn.fhir.jpa.mdm.models.GenerateMetricsTestParameters;
|
||||
import ca.uhn.fhir.jpa.mdm.models.LinkMetricTestParameters;
|
||||
import ca.uhn.fhir.jpa.mdm.models.LinkScoreMetricTestParams;
|
||||
import ca.uhn.fhir.jpa.mdm.models.ResourceMetricTestParams;
|
||||
import ca.uhn.fhir.jpa.mdm.util.MdmMetricSvcTestUtil;
|
||||
import ca.uhn.fhir.mdm.api.IMdmMetricSvc;
|
||||
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||
import ca.uhn.fhir.mdm.api.params.GenerateMdmMetricsParameters;
|
||||
import ca.uhn.fhir.mdm.model.MdmMetrics;
|
||||
import ca.uhn.fhir.mdm.model.MdmResourceMetrics;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/**
|
||||
* Tests the various metrics returned by IMdmMetricSvc
|
||||
* Because of the way these metrics are broken down in 3 different ways,
|
||||
* these results are tested separately, even though there is a single
|
||||
* entry point.
|
||||
*/
|
||||
public interface IMdmMetricSvcTest {
|
||||
|
||||
IMdmMetricSvc getMetricsSvc();
|
||||
|
||||
void generateMdmMetricsSetup(GenerateMetricsTestParameters theParameters);
|
||||
|
||||
@Test
|
||||
default void generateMdmMetrics_generalTest_happyPath() {
|
||||
// setup
|
||||
GenerateMetricsTestParameters testParameters = new GenerateMetricsTestParameters();
|
||||
testParameters.setInitialState(MdmMetricSvcTestUtil.OUR_BASIC_STATE);
|
||||
testParameters.setScores(Arrays.asList(0.1, 0.2, 0.3, 0.4));
|
||||
|
||||
generateMdmMetricsSetup(testParameters);
|
||||
|
||||
// test
|
||||
GenerateMdmMetricsParameters parameters = new GenerateMdmMetricsParameters("Patient");
|
||||
MdmMetrics results = getMetricsSvc().generateMdmMetrics(parameters);
|
||||
|
||||
// verify
|
||||
assertNotNull(results);
|
||||
assertEquals("Patient", results.getResourceType());
|
||||
assertEquals(4, results.getGoldenResourcesCount());
|
||||
assertEquals(4, results.getSourceResourcesCount());
|
||||
assertEquals(0, results.getExcludedResources());
|
||||
|
||||
Map<MdmMatchResultEnum, Map<MdmLinkSourceEnum, Long>> map = results.getMatchTypeToLinkToCountMap();
|
||||
// See OUR_BASIC_STATE
|
||||
assertEquals(3, map.size());
|
||||
for (MdmMatchResultEnum matchResult : new MdmMatchResultEnum[] {
|
||||
MdmMatchResultEnum.MATCH, MdmMatchResultEnum.NO_MATCH, MdmMatchResultEnum.POSSIBLE_MATCH
|
||||
}) {
|
||||
assertTrue(map.containsKey(matchResult));
|
||||
Map<MdmLinkSourceEnum, Long> source2Count = map.get(matchResult);
|
||||
assertNotNull(source2Count);
|
||||
for (MdmLinkSourceEnum ls : MdmLinkSourceEnum.values()) {
|
||||
assertNotNull(source2Count.get(ls));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void generateLinkMetricsSetup(LinkMetricTestParameters theParameters);
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("ca.uhn.fhir.jpa.mdm.util.MdmMetricSvcTestUtil#linkMetricsParameters")
|
||||
default void test_generateLinkMetrics_multipleInputs(LinkMetricTestParameters theParameters) {
|
||||
// setup
|
||||
generateLinkMetricsSetup(theParameters);
|
||||
|
||||
// all tests use Patient resource type
|
||||
GenerateMdmMetricsParameters parameters = new GenerateMdmMetricsParameters("Patient");
|
||||
for (MdmLinkSourceEnum linkSource : theParameters.getLinkSourceFilters()) {
|
||||
parameters.addLinkSource(linkSource);
|
||||
}
|
||||
for (MdmMatchResultEnum matchResultEnum : theParameters.getMatchFilters()) {
|
||||
parameters.addMatchResult(matchResultEnum);
|
||||
}
|
||||
|
||||
// test
|
||||
MdmMetrics metrics = getMetricsSvc().generateMdmMetrics(parameters);
|
||||
|
||||
// verify
|
||||
assertNotNull(metrics);
|
||||
assertEquals(metrics.getResourceType(), "Patient");
|
||||
|
||||
MdmMetrics expectedMetrics = theParameters.getExpectedMetrics();
|
||||
|
||||
Supplier<String> err = () -> getComparingMetrics(metrics, expectedMetrics);
|
||||
|
||||
Map<MdmMatchResultEnum, Map<MdmLinkSourceEnum, Long>> actual = metrics.getMatchTypeToLinkToCountMap();
|
||||
Map<MdmMatchResultEnum, Map<MdmLinkSourceEnum, Long>> expected = expectedMetrics.getMatchTypeToLinkToCountMap();
|
||||
assertEquals(expected, actual, err.get());
|
||||
|
||||
for (MdmMatchResultEnum matchResult : MdmMatchResultEnum.values()) {
|
||||
assertEquals(expected.containsKey(matchResult), actual.containsKey(matchResult), err.get());
|
||||
if (actual.containsKey(matchResult)) {
|
||||
Map<MdmLinkSourceEnum, Long> actualMatch = actual.get(matchResult);
|
||||
Map<MdmLinkSourceEnum, Long> expectedMatch = expected.get(matchResult);
|
||||
assertEquals(expectedMatch, actualMatch, err.get());
|
||||
for (MdmLinkSourceEnum linkSource : MdmLinkSourceEnum.values()) {
|
||||
assertEquals(expectedMatch.get(linkSource), actualMatch.get(linkSource), err.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void generateResourceMetricsSetup(ResourceMetricTestParams theParams);
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("ca.uhn.fhir.jpa.mdm.util.MdmMetricSvcTestUtil#resourceMetricParameters")
|
||||
default void test_generateResourceMetrics_multipleInputs(ResourceMetricTestParams theParams) {
|
||||
// setup
|
||||
generateResourceMetricsSetup(theParams);
|
||||
|
||||
// test
|
||||
GenerateMdmMetricsParameters parameters = new GenerateMdmMetricsParameters("Patient");
|
||||
MdmResourceMetrics results = getMetricsSvc().generateMdmMetrics(parameters);
|
||||
|
||||
// verify
|
||||
assertNotNull(results);
|
||||
assertEquals("Patient", results.getResourceType());
|
||||
assertEquals(
|
||||
theParams.getExpectedResourceCount(),
|
||||
results.getSourceResourcesCount() + results.getGoldenResourcesCount());
|
||||
assertEquals(theParams.getExpectedBlockedResourceCount(), results.getExcludedResources());
|
||||
assertEquals(theParams.getExpectedGoldenResourceCount(), results.getGoldenResourcesCount());
|
||||
}
|
||||
|
||||
void generateLinkScoreMetricsSetup(LinkScoreMetricTestParams theParams);
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("ca.uhn.fhir.jpa.mdm.util.MdmMetricSvcTestUtil#linkScoreParameters")
|
||||
default void test_generateLinkScoreMetrics_multipleInputs(LinkScoreMetricTestParams theParams) {
|
||||
// setup
|
||||
generateLinkScoreMetricsSetup(theParams);
|
||||
|
||||
GenerateMdmMetricsParameters scoreMetricsParameters = new GenerateMdmMetricsParameters("Patient");
|
||||
for (MdmMatchResultEnum matchType : theParams.getMatchFilter()) {
|
||||
scoreMetricsParameters.addMatchResult(matchType);
|
||||
}
|
||||
|
||||
// test
|
||||
MdmMetrics actualMetrics = getMetricsSvc().generateMdmMetrics(scoreMetricsParameters);
|
||||
|
||||
// verify
|
||||
assertNotNull(actualMetrics);
|
||||
assertEquals("Patient", actualMetrics.getResourceType());
|
||||
|
||||
MdmMetrics expectedMetrics = theParams.getExpectedMetrics();
|
||||
|
||||
Map<String, Long> actual = actualMetrics.getScoreCounts();
|
||||
Map<String, Long> expected = expectedMetrics.getScoreCounts();
|
||||
assertEquals(expected.size(), actual.size());
|
||||
for (String score : expected.keySet()) {
|
||||
assertTrue(actual.containsKey(score), String.format("Score of %s is not in results", score));
|
||||
assertEquals(expected.get(score), actual.get(score), score);
|
||||
}
|
||||
}
|
||||
|
||||
private String getComparingMetrics(MdmMetrics theActual, MdmMetrics theExpected) {
|
||||
return String.format(
|
||||
"\nExpected: \n%s - \nActual: \n%s", getStringMetrics(theExpected), getStringMetrics(theActual));
|
||||
}
|
||||
|
||||
String getStringMetrics(MdmMetrics theMetrics);
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package ca.uhn.fhir.jpa.mdm.models;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class GenerateMetricsTestParameters {
|
||||
|
||||
private String myInitialState;
|
||||
|
||||
/**
|
||||
* The scores for each link.
|
||||
* The order should match the order of the
|
||||
* links listed in initial state.
|
||||
*/
|
||||
private List<Double> myScores;
|
||||
|
||||
public String getInitialState() {
|
||||
return myInitialState;
|
||||
}
|
||||
|
||||
public void setInitialState(String theInitialState) {
|
||||
myInitialState = theInitialState;
|
||||
}
|
||||
|
||||
public List<Double> getScores() {
|
||||
return myScores;
|
||||
}
|
||||
|
||||
public void setScores(List<Double> theScores) {
|
||||
myScores = theScores;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
package ca.uhn.fhir.jpa.mdm.models;
|
||||
|
||||
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||
import ca.uhn.fhir.mdm.model.MdmMetrics;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class LinkMetricTestParameters {
|
||||
/**
|
||||
* The initial state (as to be fed into MdmLinkHelper)
|
||||
*/
|
||||
private String myInitialState;
|
||||
|
||||
/**
|
||||
* The filters for MatchResult
|
||||
*/
|
||||
private List<MdmMatchResultEnum> myMatchFilters;
|
||||
|
||||
/**
|
||||
* The filters for LinkSource
|
||||
*/
|
||||
private List<MdmLinkSourceEnum> myLinkSourceEnums;
|
||||
|
||||
/**
|
||||
* The expected metrics to be returned
|
||||
*/
|
||||
private MdmMetrics myExpectedMetrics;
|
||||
|
||||
public String getInitialState() {
|
||||
return myInitialState;
|
||||
}
|
||||
|
||||
public void setInitialState(String theInitialState) {
|
||||
myInitialState = theInitialState;
|
||||
}
|
||||
|
||||
public List<MdmMatchResultEnum> getMatchFilters() {
|
||||
if (myMatchFilters == null) {
|
||||
myMatchFilters = new ArrayList<>();
|
||||
}
|
||||
return myMatchFilters;
|
||||
}
|
||||
|
||||
public void setMatchFilters(List<MdmMatchResultEnum> theMatchFilters) {
|
||||
myMatchFilters = theMatchFilters;
|
||||
}
|
||||
|
||||
public List<MdmLinkSourceEnum> getLinkSourceFilters() {
|
||||
if (myLinkSourceEnums == null) {
|
||||
myLinkSourceEnums = new ArrayList<>();
|
||||
}
|
||||
return myLinkSourceEnums;
|
||||
}
|
||||
|
||||
public void setLinkSourceFilters(List<MdmLinkSourceEnum> theLinkSourceEnums) {
|
||||
myLinkSourceEnums = theLinkSourceEnums;
|
||||
}
|
||||
|
||||
public MdmMetrics getExpectedMetrics() {
|
||||
return myExpectedMetrics;
|
||||
}
|
||||
|
||||
public void setExpectedMetrics(MdmMetrics theExpectedMetrics) {
|
||||
myExpectedMetrics = theExpectedMetrics;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
package ca.uhn.fhir.jpa.mdm.models;
|
||||
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||
import ca.uhn.fhir.mdm.model.MdmMetrics;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class LinkScoreMetricTestParams {
|
||||
private String myInitialState;
|
||||
|
||||
private List<MdmMatchResultEnum> myMatchFilter;
|
||||
|
||||
private MdmMetrics myExpectedMetrics;
|
||||
|
||||
/**
|
||||
* The scores for each link.
|
||||
* The order should match the order of the
|
||||
* links listed in initial state.
|
||||
*/
|
||||
private List<Double> myScores;
|
||||
|
||||
public String getInitialState() {
|
||||
return myInitialState;
|
||||
}
|
||||
|
||||
public void setInitialState(String theInitialState) {
|
||||
myInitialState = theInitialState;
|
||||
}
|
||||
|
||||
public MdmMetrics getExpectedMetrics() {
|
||||
return myExpectedMetrics;
|
||||
}
|
||||
|
||||
public void setExpectedMetrics(MdmMetrics theExpectedMetrics) {
|
||||
myExpectedMetrics = theExpectedMetrics;
|
||||
}
|
||||
|
||||
public List<MdmMatchResultEnum> getMatchFilter() {
|
||||
if (myMatchFilter == null) {
|
||||
myMatchFilter = new ArrayList<>();
|
||||
}
|
||||
return myMatchFilter;
|
||||
}
|
||||
|
||||
public void addMatchType(MdmMatchResultEnum theResultEnum) {
|
||||
getMatchFilter().add(theResultEnum);
|
||||
}
|
||||
|
||||
public List<Double> getScores() {
|
||||
if (myScores == null) {
|
||||
myScores = new ArrayList<>();
|
||||
}
|
||||
return myScores;
|
||||
}
|
||||
|
||||
public void setScores(List<Double> theScores) {
|
||||
myScores = theScores;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package ca.uhn.fhir.jpa.mdm.models;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ResourceMetricTestParams {
|
||||
/**
|
||||
* The initial state, as consumable by
|
||||
* MdmLinkHelper.
|
||||
*/
|
||||
private String myInitialState;
|
||||
|
||||
/**
|
||||
* The list of Golden Resource Ids (in initial state) that should be
|
||||
* saved as BlockedResources
|
||||
*/
|
||||
private List<String> myBlockedResourceGoldenResourceIds;
|
||||
|
||||
private long myExpectedResourceCount;
|
||||
|
||||
private long myExpectedGoldenResourceCount;
|
||||
|
||||
public String getInitialState() {
|
||||
return myInitialState;
|
||||
}
|
||||
|
||||
public void setInitialState(String theInitialState) {
|
||||
myInitialState = theInitialState;
|
||||
}
|
||||
|
||||
public List<String> getBlockedResourceGoldenResourceIds() {
|
||||
if (myBlockedResourceGoldenResourceIds == null) {
|
||||
myBlockedResourceGoldenResourceIds = new ArrayList<>();
|
||||
}
|
||||
return myBlockedResourceGoldenResourceIds;
|
||||
}
|
||||
|
||||
public void addBlockedResourceGoldenResources(String theBlockedResourceId) {
|
||||
getBlockedResourceGoldenResourceIds().add(theBlockedResourceId);
|
||||
}
|
||||
|
||||
public long getExpectedResourceCount() {
|
||||
return myExpectedResourceCount;
|
||||
}
|
||||
|
||||
public void setExpectedResourceCount(long theExpectedResourceCount) {
|
||||
myExpectedResourceCount = theExpectedResourceCount;
|
||||
}
|
||||
|
||||
public long getExpectedGoldenResourceCount() {
|
||||
return myExpectedGoldenResourceCount;
|
||||
}
|
||||
|
||||
public void setExpectedGoldenResourceCount(long theExpectedGoldenResourceCount) {
|
||||
myExpectedGoldenResourceCount = theExpectedGoldenResourceCount;
|
||||
}
|
||||
|
||||
public long getExpectedBlockedResourceCount() {
|
||||
return getBlockedResourceGoldenResourceIds().size();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
/**
|
||||
* This package is for persistence-agnostic mdm tests.
|
||||
* Even though the package is "jpaserver-test-utils", these
|
||||
* classes are not dependent on jpa backed persistence.
|
||||
*/
|
||||
package ca.uhn.fhir.jpa.mdm;
|
|
@ -0,0 +1,338 @@
|
|||
package ca.uhn.fhir.jpa.mdm.util;
|
||||
|
||||
import ca.uhn.fhir.jpa.mdm.models.LinkMetricTestParameters;
|
||||
import ca.uhn.fhir.jpa.mdm.models.LinkScoreMetricTestParams;
|
||||
import ca.uhn.fhir.jpa.mdm.models.ResourceMetricTestParams;
|
||||
import ca.uhn.fhir.mdm.api.BaseMdmMetricSvc;
|
||||
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||
import ca.uhn.fhir.mdm.model.MdmMetrics;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
/**
|
||||
* This provides parameter methods for the {@link ca.uhn.fhir.jpa.mdm.IMdmMetricSvcTest}.
|
||||
*/
|
||||
public class MdmMetricSvcTestUtil {
|
||||
|
||||
public static final String OUR_BASIC_STATE =
|
||||
"""
|
||||
G1, AUTO, MATCH, P1
|
||||
G2, AUTO, MATCH, P2,
|
||||
G3, AUTO, POSSIBLE_MATCH, P3,
|
||||
G4, MANUAL, MATCH, P4
|
||||
G2, AUTO, NO_MATCH, P1
|
||||
G1, MANUAL, NO_MATCH, P2
|
||||
G1, MANUAL, POSSIBLE_MATCH, P3
|
||||
""";
|
||||
|
||||
/**
|
||||
* Parameters supplied to {@link ca.uhn.fhir.jpa.mdm.IMdmMetricSvcTest#test_generateLinkMetrics_multipleInputs(LinkMetricTestParameters)}
|
||||
*/
|
||||
public static List<LinkMetricTestParameters> linkMetricsParameters() {
|
||||
List<LinkMetricTestParameters> params = new ArrayList<>();
|
||||
|
||||
// 1
|
||||
{
|
||||
LinkMetricTestParameters testParameters = new LinkMetricTestParameters();
|
||||
testParameters.setInitialState(OUR_BASIC_STATE);
|
||||
MdmMetrics metrics = new MdmMetrics();
|
||||
metrics.addMetric(MdmMatchResultEnum.MATCH, MdmLinkSourceEnum.AUTO, 2);
|
||||
metrics.addMetric(MdmMatchResultEnum.MATCH, MdmLinkSourceEnum.MANUAL, 1);
|
||||
metrics.addMetric(MdmMatchResultEnum.NO_MATCH, MdmLinkSourceEnum.AUTO, 1);
|
||||
metrics.addMetric(MdmMatchResultEnum.NO_MATCH, MdmLinkSourceEnum.MANUAL, 1);
|
||||
metrics.addMetric(MdmMatchResultEnum.POSSIBLE_MATCH, MdmLinkSourceEnum.AUTO, 1);
|
||||
metrics.addMetric(MdmMatchResultEnum.POSSIBLE_MATCH, MdmLinkSourceEnum.MANUAL, 1);
|
||||
testParameters.setExpectedMetrics(metrics);
|
||||
params.add(testParameters);
|
||||
}
|
||||
|
||||
// 2
|
||||
{
|
||||
// link source filter
|
||||
LinkMetricTestParameters testParameters = new LinkMetricTestParameters();
|
||||
testParameters.setInitialState(OUR_BASIC_STATE);
|
||||
testParameters.setLinkSourceFilters(Arrays.asList(MdmLinkSourceEnum.AUTO));
|
||||
MdmMetrics metrics = new MdmMetrics();
|
||||
metrics.addMetric(MdmMatchResultEnum.MATCH, MdmLinkSourceEnum.AUTO, 2);
|
||||
metrics.addMetric(MdmMatchResultEnum.NO_MATCH, MdmLinkSourceEnum.AUTO, 1);
|
||||
metrics.addMetric(MdmMatchResultEnum.POSSIBLE_MATCH, MdmLinkSourceEnum.AUTO, 1);
|
||||
testParameters.setExpectedMetrics(metrics);
|
||||
params.add(testParameters);
|
||||
}
|
||||
|
||||
// 3
|
||||
{
|
||||
// match result filter
|
||||
LinkMetricTestParameters testParameters = new LinkMetricTestParameters();
|
||||
testParameters.setInitialState(OUR_BASIC_STATE);
|
||||
testParameters.setMatchFilters(Arrays.asList(MdmMatchResultEnum.MATCH, MdmMatchResultEnum.POSSIBLE_MATCH));
|
||||
MdmMetrics metrics = new MdmMetrics();
|
||||
metrics.addMetric(MdmMatchResultEnum.MATCH, MdmLinkSourceEnum.AUTO, 2);
|
||||
metrics.addMetric(MdmMatchResultEnum.MATCH, MdmLinkSourceEnum.MANUAL, 1);
|
||||
metrics.addMetric(MdmMatchResultEnum.POSSIBLE_MATCH, MdmLinkSourceEnum.AUTO, 1);
|
||||
metrics.addMetric(MdmMatchResultEnum.POSSIBLE_MATCH, MdmLinkSourceEnum.MANUAL, 1);
|
||||
testParameters.setExpectedMetrics(metrics);
|
||||
params.add(testParameters);
|
||||
}
|
||||
|
||||
// 4
|
||||
{
|
||||
// match result and link source filters
|
||||
LinkMetricTestParameters testParameters = new LinkMetricTestParameters();
|
||||
testParameters.setInitialState(OUR_BASIC_STATE);
|
||||
testParameters.setMatchFilters(Arrays.asList(MdmMatchResultEnum.MATCH));
|
||||
testParameters.setLinkSourceFilters(Arrays.asList(MdmLinkSourceEnum.MANUAL));
|
||||
MdmMetrics metrics = new MdmMetrics();
|
||||
metrics.addMetric(MdmMatchResultEnum.MATCH, MdmLinkSourceEnum.MANUAL, 1);
|
||||
testParameters.setExpectedMetrics(metrics);
|
||||
params.add(testParameters);
|
||||
}
|
||||
|
||||
// 5
|
||||
{
|
||||
// no initial state
|
||||
LinkMetricTestParameters testParameters = new LinkMetricTestParameters();
|
||||
testParameters.setInitialState("");
|
||||
MdmMetrics metrics = new MdmMetrics();
|
||||
testParameters.setExpectedMetrics(metrics);
|
||||
params.add(testParameters);
|
||||
}
|
||||
|
||||
// 6
|
||||
{
|
||||
// initial state with filters to omit all values
|
||||
LinkMetricTestParameters testParameters = new LinkMetricTestParameters();
|
||||
testParameters.setInitialState("""
|
||||
G1, AUTO, NO_MATCH, P1
|
||||
G2, MANUAL, MATCH, P2
|
||||
""");
|
||||
testParameters.setMatchFilters(Arrays.asList(MdmMatchResultEnum.MATCH));
|
||||
testParameters.setLinkSourceFilters(Arrays.asList(MdmLinkSourceEnum.AUTO));
|
||||
testParameters.setExpectedMetrics(new MdmMetrics());
|
||||
params.add(testParameters);
|
||||
}
|
||||
|
||||
// 7
|
||||
{
|
||||
// initial state with filters to omit some values
|
||||
LinkMetricTestParameters testParameters = new LinkMetricTestParameters();
|
||||
testParameters.setInitialState("""
|
||||
G1, AUTO, NO_MATCH, P1
|
||||
G2, MANUAL, MATCH, P2
|
||||
""");
|
||||
testParameters.setMatchFilters(Arrays.asList(MdmMatchResultEnum.NO_MATCH));
|
||||
testParameters.setLinkSourceFilters(Arrays.asList(MdmLinkSourceEnum.AUTO));
|
||||
MdmMetrics metrics = new MdmMetrics();
|
||||
metrics.addMetric(MdmMatchResultEnum.NO_MATCH, MdmLinkSourceEnum.AUTO, 1);
|
||||
testParameters.setExpectedMetrics(metrics);
|
||||
params.add(testParameters);
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parameters supplied to {@link ca.uhn.fhir.jpa.mdm.IMdmMetricSvcTest#test_generateResourceMetrics_multipleInputs(ResourceMetricTestParams)}
|
||||
*/
|
||||
public static List<ResourceMetricTestParams> resourceMetricParameters() {
|
||||
List<ResourceMetricTestParams> params = new ArrayList<>();
|
||||
|
||||
// 1
|
||||
{
|
||||
// a mix of golden, regular, and blocked resources
|
||||
ResourceMetricTestParams p = new ResourceMetricTestParams();
|
||||
p.setInitialState(
|
||||
"""
|
||||
G1, AUTO, MATCH, P1
|
||||
G2, AUTO, MATCH, P2
|
||||
G2, AUTO, MATCH, P1,
|
||||
G3, AUTO, MATCH, P3
|
||||
""");
|
||||
p.addBlockedResourceGoldenResources("G2");
|
||||
p.addBlockedResourceGoldenResources("G3");
|
||||
p.setExpectedResourceCount(6);
|
||||
p.setExpectedGoldenResourceCount(3);
|
||||
params.add(p);
|
||||
}
|
||||
|
||||
// 2
|
||||
{
|
||||
// 2 non-golden, 1 golden
|
||||
ResourceMetricTestParams p = new ResourceMetricTestParams();
|
||||
p.setInitialState("""
|
||||
G1, AUTO, MATCH, P1,
|
||||
G1, MANUAL, MATCH, P2
|
||||
""");
|
||||
p.setExpectedResourceCount(3);
|
||||
p.setExpectedGoldenResourceCount(1);
|
||||
params.add(p);
|
||||
}
|
||||
|
||||
// 3
|
||||
{
|
||||
// 2 golden, 1 non-golden
|
||||
ResourceMetricTestParams p = new ResourceMetricTestParams();
|
||||
p.setInitialState("""
|
||||
G1, AUTO, MATCH, P1
|
||||
G2, AUTO, POSSIBLE_DUPLICATE, G1
|
||||
""");
|
||||
p.setExpectedGoldenResourceCount(2);
|
||||
p.setExpectedResourceCount(3);
|
||||
params.add(p);
|
||||
}
|
||||
|
||||
// 4
|
||||
{
|
||||
// 2 golden, 1 blocked, 0 non-golden
|
||||
ResourceMetricTestParams p = new ResourceMetricTestParams();
|
||||
p.setInitialState("""
|
||||
G1, AUTO, POSSIBLE_DUPLICATE, G2
|
||||
""");
|
||||
p.addBlockedResourceGoldenResources("G1");
|
||||
p.setExpectedResourceCount(2);
|
||||
p.setExpectedGoldenResourceCount(2);
|
||||
params.add(p);
|
||||
}
|
||||
|
||||
// 5
|
||||
{
|
||||
// no resources
|
||||
ResourceMetricTestParams p = new ResourceMetricTestParams();
|
||||
p.setInitialState("");
|
||||
params.add(p);
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parameters supplied to {@link ca.uhn.fhir.jpa.mdm.IMdmMetricSvcTest#generateLinkScoreMetricsSetup(LinkScoreMetricTestParams)}
|
||||
*/
|
||||
public static List<LinkScoreMetricTestParams> linkScoreParameters() {
|
||||
List<LinkScoreMetricTestParams> parameters = new ArrayList<>();
|
||||
|
||||
// 1
|
||||
{
|
||||
// score counts
|
||||
LinkScoreMetricTestParams p = new LinkScoreMetricTestParams();
|
||||
p.setInitialState(
|
||||
"""
|
||||
G1, AUTO, MATCH, P1
|
||||
G2, AUTO, POSSIBLE_MATCH, P2,
|
||||
G3, AUTO, POSSIBLE_MATCH, P1
|
||||
""");
|
||||
p.setScores(Arrays.asList(.2D, .2D, .1D));
|
||||
MdmMetrics metrics = new MdmMetrics();
|
||||
metrics.setResourceType("Patient");
|
||||
populateScoreIntoMetrics(p, metrics);
|
||||
p.setExpectedMetrics(metrics);
|
||||
parameters.add(p);
|
||||
}
|
||||
|
||||
// 2
|
||||
{
|
||||
// a null score
|
||||
LinkScoreMetricTestParams p = new LinkScoreMetricTestParams();
|
||||
p.setInitialState("""
|
||||
G1, AUTO, POSSIBLE_MATCH, P1,
|
||||
G2, AUTO, POSSIBLE_MATCH, P2
|
||||
""");
|
||||
p.setScores(Arrays.asList(null, 0.02D));
|
||||
MdmMetrics metrics = new MdmMetrics();
|
||||
metrics.setResourceType("Patient");
|
||||
populateScoreIntoMetrics(p, metrics);
|
||||
p.setExpectedMetrics(metrics);
|
||||
parameters.add(p);
|
||||
}
|
||||
|
||||
// 3
|
||||
{
|
||||
// match type filtering
|
||||
LinkScoreMetricTestParams p = new LinkScoreMetricTestParams();
|
||||
p.setInitialState(
|
||||
"""
|
||||
G1, AUTO, POSSIBLE_MATCH, P1
|
||||
G2, AUTO, MATCH, P2
|
||||
G3, AUTO, POSSIBLE_MATCH, P3
|
||||
G4, AUTO, MATCH, P4
|
||||
""");
|
||||
p.setScores(Arrays.asList(0.4D, 0.4D, 0.1D, 0.3D));
|
||||
p.addMatchType(MdmMatchResultEnum.POSSIBLE_MATCH);
|
||||
MdmMetrics metrics = new MdmMetrics();
|
||||
metrics.setResourceType("Patient");
|
||||
populateScoreIntoMetrics(p, metrics);
|
||||
p.setExpectedMetrics(metrics);
|
||||
parameters.add(p);
|
||||
}
|
||||
|
||||
// 4
|
||||
{
|
||||
// no links
|
||||
LinkScoreMetricTestParams p = new LinkScoreMetricTestParams();
|
||||
p.setInitialState("");
|
||||
MdmMetrics metrics = new MdmMetrics();
|
||||
metrics.setResourceType("Patient");
|
||||
p.setExpectedMetrics(metrics);
|
||||
populateScoreIntoMetrics(p, metrics);
|
||||
parameters.add(p);
|
||||
}
|
||||
|
||||
return parameters;
|
||||
}
|
||||
|
||||
private static void populateScoreIntoMetrics(LinkScoreMetricTestParams p, MdmMetrics metrics) {
|
||||
String initialState = p.getInitialState();
|
||||
Map<Integer, MdmMatchResultEnum> indexToMatchResult = new HashMap<>();
|
||||
if (isNotBlank(initialState)) {
|
||||
String[] states = initialState.split("\n");
|
||||
int len = states.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
String state = states[i];
|
||||
String[] values = state.split(",");
|
||||
indexToMatchResult.put(i, MdmMatchResultEnum.valueOf(values[2].trim()));
|
||||
}
|
||||
}
|
||||
|
||||
Map<Double, Long> score2Count = new HashMap<>();
|
||||
long nullCount = 0;
|
||||
for (int i = 0; i < p.getScores().size(); i++) {
|
||||
MdmMatchResultEnum matchResult = indexToMatchResult.get(i);
|
||||
// if it's not a filtered value, add it to the expected metrics
|
||||
if (p.getMatchFilter().isEmpty() || p.getMatchFilter().contains(matchResult)) {
|
||||
Double d = p.getScores().get(i);
|
||||
if (d == null) {
|
||||
nullCount++;
|
||||
} else {
|
||||
if (!score2Count.containsKey(d)) {
|
||||
score2Count.put(d, 0L);
|
||||
}
|
||||
score2Count.put(d, score2Count.get(d) + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
metrics.addScore(BaseMdmMetricSvc.NULL_VALUE, nullCount);
|
||||
for (int i = 0; i < BaseMdmMetricSvc.BUCKETS; i++) {
|
||||
double bucket = (double) Math.round((float) (100 * (i + 1)) / BaseMdmMetricSvc.BUCKETS) / 100;
|
||||
long count = 0;
|
||||
// TODO - do not add it if the corresponding link does not have
|
||||
// the correct MATCH_RESULT value
|
||||
if (score2Count.containsKey(bucket)) {
|
||||
count = score2Count.get(bucket);
|
||||
}
|
||||
if (i == 0) {
|
||||
metrics.addScore(String.format(BaseMdmMetricSvc.FIRST_BUCKET, bucket), count);
|
||||
} else {
|
||||
metrics.addScore(
|
||||
String.format(BaseMdmMetricSvc.NTH_BUCKET, (float) i / BaseMdmMetricSvc.BUCKETS, bucket),
|
||||
count);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>6.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
package ca.uhn.fhir.mdm.api;
|
||||
|
||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.mdm.api.params.GenerateMdmMetricsParameters;
|
||||
import ca.uhn.fhir.mdm.model.MdmResourceMetrics;
|
||||
import ca.uhn.fhir.mdm.util.MdmSearchParamBuildingUtils;
|
||||
import ca.uhn.fhir.rest.api.SearchTotalModeEnum;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.api.server.SystemRequestDetails;
|
||||
|
||||
public abstract class BaseMdmMetricSvc implements IMdmMetricSvc {
|
||||
|
||||
/**
|
||||
* Count of numbered buckets.
|
||||
* There will also be a NULL bucket, so there will be a total
|
||||
* of BUCKETS + 1 buckets.
|
||||
*/
|
||||
public static final int BUCKETS = 100;
|
||||
|
||||
/**
|
||||
* The NULL label
|
||||
*/
|
||||
public static final String NULL_VALUE = "NULL";
|
||||
|
||||
/**
|
||||
* The label for the first bucket
|
||||
*/
|
||||
public static final String FIRST_BUCKET = "x_<_%.2f";
|
||||
|
||||
/**
|
||||
* The label for the nth bucket (2... buckets)
|
||||
*/
|
||||
public static final String NTH_BUCKET = "%.2f_<_x_<=_%.2f";
|
||||
|
||||
protected final DaoRegistry myDaoRegistry;
|
||||
|
||||
public BaseMdmMetricSvc(DaoRegistry theDaoRegistry) {
|
||||
myDaoRegistry = theDaoRegistry;
|
||||
}
|
||||
|
||||
protected double getBucket(int theBucketId) {
|
||||
return (double) Math.round((float) (100 * theBucketId) / BUCKETS) / 100;
|
||||
}
|
||||
|
||||
protected MdmResourceMetrics generateResourceMetrics(GenerateMdmMetricsParameters theParameters) {
|
||||
String resourceType = theParameters.getResourceType();
|
||||
@SuppressWarnings("rawtypes")
|
||||
IFhirResourceDao dao = myDaoRegistry.getResourceDao(resourceType);
|
||||
|
||||
// TODO
|
||||
/*
|
||||
* We are using 3 different queries to count:
|
||||
* * all resources
|
||||
* * all golden resources
|
||||
* * all blocked resources.
|
||||
*
|
||||
* This is inefficient and if we want, we can speed it up with
|
||||
* a custom query in the future.
|
||||
*/
|
||||
IBundleProvider outcome = null;
|
||||
SearchParameterMap map = null;
|
||||
|
||||
MdmResourceMetrics metrics = new MdmResourceMetrics();
|
||||
metrics.setResourceType(resourceType);
|
||||
|
||||
// find golden resources
|
||||
map = MdmSearchParamBuildingUtils.buildBasicGoldenResourceSearchParameterMap(resourceType);
|
||||
setCountOnly(map);
|
||||
outcome = dao.search(map, new SystemRequestDetails());
|
||||
metrics.setGoldenResourcesCount(outcome.size());
|
||||
|
||||
// find blocked resources
|
||||
map = MdmSearchParamBuildingUtils.buildSearchParameterForBlockedResourceCount(resourceType);
|
||||
setCountOnly(map);
|
||||
outcome = dao.search(map, new SystemRequestDetails());
|
||||
metrics.setExcludedResources(outcome.size());
|
||||
|
||||
// find all resources
|
||||
map = new SearchParameterMap();
|
||||
setCountOnly(map);
|
||||
outcome = dao.search(map, new SystemRequestDetails());
|
||||
metrics.setSourceResourcesCount(outcome.size() - metrics.getGoldenResourcesCount());
|
||||
|
||||
return metrics;
|
||||
}
|
||||
|
||||
private void setCountOnly(SearchParameterMap theMap) {
|
||||
theMap.setCount(0);
|
||||
theMap.setLoadSynchronous(true);
|
||||
theMap.setSearchTotalMode(SearchTotalModeEnum.ACCURATE);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package ca.uhn.fhir.mdm.api;
|
||||
|
||||
import ca.uhn.fhir.mdm.api.params.GenerateMdmMetricsParameters;
|
||||
import ca.uhn.fhir.mdm.model.MdmMetrics;
|
||||
|
||||
public interface IMdmMetricSvc {
|
||||
|
||||
/**
|
||||
* Generates metrics on MDM Links.
|
||||
* Metrics include:
|
||||
* * breakdowns of counts of MATCH_RESULT types by LINK_SOURCE types.
|
||||
* * counts of resources of each type
|
||||
* * a histogram of score 'buckets' with the appropriate counts.
|
||||
* @param theParameters - Parameters defining resource type of interest,
|
||||
* as well as MatchResult and LinkSource filters.
|
||||
* @return The metrics in a JSON format.
|
||||
*/
|
||||
MdmMetrics generateMdmMetrics(GenerateMdmMetricsParameters theParameters);
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package ca.uhn.fhir.mdm.api;
|
||||
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome;
|
||||
import ca.uhn.fhir.rest.api.server.storage.IResourcePersistentId;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public interface IMdmResourceDaoSvc {
|
||||
DaoMethodOutcome upsertGoldenResource(IAnyResource theGoldenResource, String theResourceType);
|
||||
|
||||
/**
|
||||
* Given a resource, remove its Golden Resource tag.
|
||||
*
|
||||
* @param theGoldenResource the {@link IAnyResource} to remove the tag from.
|
||||
* @param theResourcetype the type of that resource
|
||||
*/
|
||||
void removeGoldenResourceTag(IAnyResource theGoldenResource, String theResourcetype);
|
||||
|
||||
IAnyResource readGoldenResourceByPid(IResourcePersistentId theGoldenResourcePid, String theResourceType);
|
||||
|
||||
Optional<IAnyResource> searchGoldenResourceByEID(String theEid, String theResourceType);
|
||||
|
||||
Optional<IAnyResource> searchGoldenResourceByEID(
|
||||
String theEid, String theResourceType, RequestPartitionId thePartitionId);
|
||||
}
|
|
@ -34,6 +34,13 @@ public class MdmConstants {
|
|||
"http://hapifhir.io/fhir/NamingSystem/mdm-golden-resource-enterprise-id";
|
||||
public static final String ALL_RESOURCE_SEARCH_PARAM_TYPE = "*";
|
||||
|
||||
/**
|
||||
* Blocked resource tag info
|
||||
*/
|
||||
public static final String CODE_BLOCKED = "BLOCKED_RESOURCE";
|
||||
|
||||
public static final String CODE_BLOCKED_DISPLAY = "Source Resource is omitted from MDM matching.";
|
||||
|
||||
public static final String FIHR_STRUCTURE_DEF_MATCH_GRADE_URL_NAMESPACE =
|
||||
"http://hl7.org/fhir/StructureDefinition/match-grade";
|
||||
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
package ca.uhn.fhir.mdm.api.params;
|
||||
|
||||
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class GenerateMdmLinkMetricParameters {
|
||||
|
||||
/**
|
||||
* The resource type of interest.
|
||||
* Must be provided!
|
||||
*/
|
||||
private final String myResourceType;
|
||||
|
||||
/**
|
||||
* The MDM MatchResult types of interest.
|
||||
* Specified MatchResults will be included.
|
||||
* If none are specified, all will be included.
|
||||
*/
|
||||
private List<MdmMatchResultEnum> myMatchResultFilters;
|
||||
|
||||
/**
|
||||
* The MDM Link values of interest.
|
||||
* Specified LinkSources will be included.
|
||||
* If none are specified, all are included.
|
||||
*/
|
||||
private List<MdmLinkSourceEnum> myLinkSourceFilters;
|
||||
|
||||
public GenerateMdmLinkMetricParameters(String theResourceType) {
|
||||
myResourceType = theResourceType;
|
||||
}
|
||||
|
||||
public String getResourceType() {
|
||||
return myResourceType;
|
||||
}
|
||||
|
||||
public List<MdmMatchResultEnum> getMatchResultFilters() {
|
||||
if (myMatchResultFilters == null) {
|
||||
myMatchResultFilters = new ArrayList<>();
|
||||
}
|
||||
return myMatchResultFilters;
|
||||
}
|
||||
|
||||
public void addMatchResultFilter(MdmMatchResultEnum theMdmMatchResultEnum) {
|
||||
getMatchResultFilters().add(theMdmMatchResultEnum);
|
||||
}
|
||||
|
||||
public List<MdmLinkSourceEnum> getLinkSourceFilters() {
|
||||
if (myLinkSourceFilters == null) {
|
||||
myLinkSourceFilters = new ArrayList<>();
|
||||
}
|
||||
return myLinkSourceFilters;
|
||||
}
|
||||
|
||||
public void addLinkSourceFilter(MdmLinkSourceEnum theLinkSource) {
|
||||
getLinkSourceFilters().add(theLinkSource);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
package ca.uhn.fhir.mdm.api.params;
|
||||
|
||||
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class GenerateMdmMetricsParameters {
|
||||
|
||||
/**
|
||||
* We only allow finding metrics by resource type
|
||||
*/
|
||||
private final String myResourceType;
|
||||
|
||||
/**
|
||||
* The MDM MatchResult types of interest.
|
||||
* Specified MatchResults will be included.
|
||||
* If none are specified, all will be included.
|
||||
*/
|
||||
private List<MdmMatchResultEnum> myMatchResultFilters;
|
||||
|
||||
/**
|
||||
* The MDM Link values of interest.
|
||||
* Specified LinkSources will be included.
|
||||
* If none are specified, all are included.
|
||||
*/
|
||||
private List<MdmLinkSourceEnum> myLinkSourceFilters;
|
||||
|
||||
public GenerateMdmMetricsParameters(String theResourceType) {
|
||||
myResourceType = theResourceType;
|
||||
}
|
||||
|
||||
public String getResourceType() {
|
||||
return myResourceType;
|
||||
}
|
||||
|
||||
public List<MdmMatchResultEnum> getMatchResultFilters() {
|
||||
if (myMatchResultFilters == null) {
|
||||
myMatchResultFilters = new ArrayList<>();
|
||||
}
|
||||
return myMatchResultFilters;
|
||||
}
|
||||
|
||||
public void addMatchResult(MdmMatchResultEnum theMdmMatchResultEnum) {
|
||||
getMatchResultFilters().add(theMdmMatchResultEnum);
|
||||
}
|
||||
|
||||
public List<MdmLinkSourceEnum> getLinkSourceFilters() {
|
||||
if (myLinkSourceFilters == null) {
|
||||
myLinkSourceFilters = new ArrayList<>();
|
||||
}
|
||||
return myLinkSourceFilters;
|
||||
}
|
||||
|
||||
public void addLinkSource(MdmLinkSourceEnum theLinkSource) {
|
||||
getLinkSourceFilters().add(theLinkSource);
|
||||
}
|
||||
|
||||
// public GenerateMdmLinkMetricParameters toLinkMetricParams() {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// public GenerateMdmResourceMetricsParameters toResourceMetricParams() {
|
||||
//
|
||||
// }
|
||||
//
|
||||
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package ca.uhn.fhir.mdm.api.params;
|
||||
|
||||
public class GenerateMdmResourceMetricsParameters {
|
||||
|
||||
/**
|
||||
* We only allow finding metrics by resource type
|
||||
*/
|
||||
private final String myResourceType;
|
||||
|
||||
public GenerateMdmResourceMetricsParameters(String theResourceType) {
|
||||
myResourceType = theResourceType;
|
||||
}
|
||||
|
||||
public String getResourceType() {
|
||||
return myResourceType;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package ca.uhn.fhir.mdm.api.params;
|
||||
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class GenerateScoreMetricsParameters {
|
||||
/**
|
||||
* The resource type of interest.
|
||||
*/
|
||||
private final String myResourceType;
|
||||
|
||||
/**
|
||||
* MatchResult types to filter for.
|
||||
* Specified MatchResults will be included.
|
||||
* If none specified, all will be included.
|
||||
*/
|
||||
private List<MdmMatchResultEnum> myMatchTypeFilters;
|
||||
|
||||
public GenerateScoreMetricsParameters(String theResourceType) {
|
||||
myResourceType = theResourceType;
|
||||
}
|
||||
|
||||
public String getResourceType() {
|
||||
return myResourceType;
|
||||
}
|
||||
|
||||
public List<MdmMatchResultEnum> getMatchTypes() {
|
||||
if (myMatchTypeFilters == null) {
|
||||
myMatchTypeFilters = new ArrayList<>();
|
||||
}
|
||||
return myMatchTypeFilters;
|
||||
}
|
||||
|
||||
public void addMatchType(MdmMatchResultEnum theMatchType) {
|
||||
getMatchTypes().add(theMatchType);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package ca.uhn.fhir.mdm.model;
|
||||
|
||||
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class MdmLinkMetrics {
|
||||
/**
|
||||
* The resource type to which these metrics apply.
|
||||
*/
|
||||
private String myResourceType;
|
||||
|
||||
/**
|
||||
* A mapping of MatchType -> LinkSource -> count.
|
||||
* Eg:
|
||||
* MATCH
|
||||
* AUTO - 2
|
||||
* MANUAL - 1
|
||||
* NO_MATCH
|
||||
* AUTO - 1
|
||||
* MANUAL - 3
|
||||
*/
|
||||
private Map<MdmMatchResultEnum, Map<MdmLinkSourceEnum, Long>> myMatchTypeToLinkToCountMap;
|
||||
|
||||
public String getResourceType() {
|
||||
return myResourceType;
|
||||
}
|
||||
|
||||
public void setResourceType(String theResourceType) {
|
||||
myResourceType = theResourceType;
|
||||
}
|
||||
|
||||
public Map<MdmMatchResultEnum, Map<MdmLinkSourceEnum, Long>> getMatchTypeToLinkToCountMap() {
|
||||
if (myMatchTypeToLinkToCountMap == null) {
|
||||
myMatchTypeToLinkToCountMap = new HashMap<>();
|
||||
}
|
||||
return myMatchTypeToLinkToCountMap;
|
||||
}
|
||||
|
||||
public void addMetric(
|
||||
MdmMatchResultEnum theMdmMatchResultEnum, MdmLinkSourceEnum theLinkSourceEnum, long theCount) {
|
||||
Map<MdmMatchResultEnum, Map<MdmLinkSourceEnum, Long>> map = getMatchTypeToLinkToCountMap();
|
||||
|
||||
if (!map.containsKey(theMdmMatchResultEnum)) {
|
||||
map.put(theMdmMatchResultEnum, new HashMap<>());
|
||||
}
|
||||
Map<MdmLinkSourceEnum, Long> lsToCountMap = map.get(theMdmMatchResultEnum);
|
||||
lsToCountMap.put(theLinkSourceEnum, theCount);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package ca.uhn.fhir.mdm.model;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class MdmLinkScoreMetrics {
|
||||
|
||||
private String myResourceType;
|
||||
|
||||
/**
|
||||
* Map of Score:Count
|
||||
* Scores are typically Doubles. But we cast to string because
|
||||
* Score is not a non-null field, and so "NULL" is a value.
|
||||
*/
|
||||
private Map<String, Long> myScoreCounts;
|
||||
|
||||
public void setResourceType(String theResourceType) {
|
||||
myResourceType = theResourceType;
|
||||
}
|
||||
|
||||
public String getResourceType() {
|
||||
return myResourceType;
|
||||
}
|
||||
|
||||
public Map<String, Long> getScoreCounts() {
|
||||
if (myScoreCounts == null) {
|
||||
myScoreCounts = new LinkedHashMap<>();
|
||||
}
|
||||
return myScoreCounts;
|
||||
}
|
||||
|
||||
public void addScore(String theScore, Long theCount) {
|
||||
getScoreCounts().put(theScore, theCount);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
package ca.uhn.fhir.mdm.model;
|
||||
|
||||
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||
import ca.uhn.fhir.model.api.IModelJson;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class MdmMetrics extends MdmResourceMetrics implements IModelJson {
|
||||
|
||||
@JsonProperty("resourceType")
|
||||
private String myResourceType;
|
||||
|
||||
/**
|
||||
* A mapping of MatchType -> LinkSource -> count.
|
||||
* Eg:
|
||||
* MATCH
|
||||
* AUTO - 2
|
||||
* MANUAL - 1
|
||||
* NO_MATCH
|
||||
* AUTO - 1
|
||||
* MANUAL - 3
|
||||
*/
|
||||
@JsonProperty("matchResult2linkSource2count")
|
||||
private Map<MdmMatchResultEnum, Map<MdmLinkSourceEnum, Long>> myMatchTypeToLinkToCountMap;
|
||||
|
||||
/**
|
||||
* Score buckets (in brackets of 0.01 size, and null) to counts.
|
||||
*/
|
||||
@JsonProperty("scoreCounts")
|
||||
private Map<String, Long> myScoreCounts;
|
||||
|
||||
/**
|
||||
* The number of golden resources.
|
||||
*/
|
||||
@JsonProperty("goldenResources")
|
||||
private long myGoldenResourcesCount;
|
||||
|
||||
/**
|
||||
* The number of source resources.
|
||||
*/
|
||||
@JsonProperty("sourceResources")
|
||||
private long mySourceResourcesCount;
|
||||
|
||||
/**
|
||||
* The number of excluded resources.
|
||||
* These are necessarily a subset of both
|
||||
* GoldenResources and SourceResources
|
||||
* (as each Blocked resource will still generate
|
||||
* a GoldenResource)
|
||||
*/
|
||||
@JsonProperty("excludedResources")
|
||||
private long myExcludedResources;
|
||||
|
||||
public String getResourceType() {
|
||||
return myResourceType;
|
||||
}
|
||||
|
||||
public Map<MdmMatchResultEnum, Map<MdmLinkSourceEnum, Long>> getMatchTypeToLinkToCountMap() {
|
||||
if (myMatchTypeToLinkToCountMap == null) {
|
||||
myMatchTypeToLinkToCountMap = new HashMap<>();
|
||||
}
|
||||
return myMatchTypeToLinkToCountMap;
|
||||
}
|
||||
|
||||
public void addMetric(
|
||||
MdmMatchResultEnum theMdmMatchResultEnum, MdmLinkSourceEnum theLinkSourceEnum, long theCount) {
|
||||
Map<MdmMatchResultEnum, Map<MdmLinkSourceEnum, Long>> map = getMatchTypeToLinkToCountMap();
|
||||
|
||||
if (!map.containsKey(theMdmMatchResultEnum)) {
|
||||
map.put(theMdmMatchResultEnum, new HashMap<>());
|
||||
}
|
||||
Map<MdmLinkSourceEnum, Long> lsToCountMap = map.get(theMdmMatchResultEnum);
|
||||
lsToCountMap.put(theLinkSourceEnum, theCount);
|
||||
}
|
||||
|
||||
public void setResourceType(String theResourceType) {
|
||||
myResourceType = theResourceType;
|
||||
}
|
||||
|
||||
public long getGoldenResourcesCount() {
|
||||
return myGoldenResourcesCount;
|
||||
}
|
||||
|
||||
public void setGoldenResourcesCount(long theGoldenResourcesCount) {
|
||||
myGoldenResourcesCount = theGoldenResourcesCount;
|
||||
}
|
||||
|
||||
public long getSourceResourcesCount() {
|
||||
return mySourceResourcesCount;
|
||||
}
|
||||
|
||||
public void setSourceResourcesCount(long theSourceResourcesCount) {
|
||||
mySourceResourcesCount = theSourceResourcesCount;
|
||||
}
|
||||
|
||||
public long getExcludedResources() {
|
||||
return myExcludedResources;
|
||||
}
|
||||
|
||||
public void setExcludedResources(long theExcludedResources) {
|
||||
myExcludedResources = theExcludedResources;
|
||||
}
|
||||
|
||||
public Map<String, Long> getScoreCounts() {
|
||||
if (myScoreCounts == null) {
|
||||
myScoreCounts = new LinkedHashMap<>();
|
||||
}
|
||||
return myScoreCounts;
|
||||
}
|
||||
|
||||
public void addScore(String theScore, Long theCount) {
|
||||
getScoreCounts().put(theScore, theCount);
|
||||
}
|
||||
|
||||
public static MdmMetrics fromSeperableMetrics(
|
||||
MdmResourceMetrics theMdmResourceMetrics,
|
||||
MdmLinkMetrics theLinkMetrics,
|
||||
MdmLinkScoreMetrics theLinkScoreMetrics) {
|
||||
MdmMetrics metrics = new MdmMetrics();
|
||||
metrics.setResourceType(theMdmResourceMetrics.getResourceType());
|
||||
metrics.setExcludedResources(theMdmResourceMetrics.getExcludedResources());
|
||||
metrics.setGoldenResourcesCount(theMdmResourceMetrics.getGoldenResourcesCount());
|
||||
metrics.setSourceResourcesCount(theMdmResourceMetrics.getSourceResourcesCount());
|
||||
metrics.myMatchTypeToLinkToCountMap = theLinkMetrics.getMatchTypeToLinkToCountMap();
|
||||
metrics.myScoreCounts = theLinkScoreMetrics.getScoreCounts();
|
||||
return metrics;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
package ca.uhn.fhir.mdm.model;
|
||||
|
||||
public class MdmResourceMetrics {
|
||||
|
||||
/**
|
||||
* The resource type to which these metrics apply.
|
||||
*/
|
||||
private String myResourceType;
|
||||
|
||||
/**
|
||||
* The number of golden resources.
|
||||
*/
|
||||
private long myGoldenResourcesCount;
|
||||
|
||||
/**
|
||||
* The number of source resources.
|
||||
*/
|
||||
private long mySourceResourcesCount;
|
||||
|
||||
/**
|
||||
* The number of excluded resources.
|
||||
* These are necessarily a subset of both
|
||||
* GoldenResources and SourceResources
|
||||
* (as each Blocked resource will still generate
|
||||
* a GoldenResource)
|
||||
*/
|
||||
private long myExcludedResources;
|
||||
|
||||
public String getResourceType() {
|
||||
return myResourceType;
|
||||
}
|
||||
|
||||
public void setResourceType(String theResourceType) {
|
||||
myResourceType = theResourceType;
|
||||
}
|
||||
|
||||
public long getGoldenResourcesCount() {
|
||||
return myGoldenResourcesCount;
|
||||
}
|
||||
|
||||
public void setGoldenResourcesCount(long theGoldenResourcesCount) {
|
||||
myGoldenResourcesCount = theGoldenResourcesCount;
|
||||
}
|
||||
|
||||
public long getSourceResourcesCount() {
|
||||
return mySourceResourcesCount;
|
||||
}
|
||||
|
||||
public void setSourceResourcesCount(long theSourceResourcesCount) {
|
||||
mySourceResourcesCount = theSourceResourcesCount;
|
||||
}
|
||||
|
||||
public long getExcludedResources() {
|
||||
return myExcludedResources;
|
||||
}
|
||||
|
||||
public void setExcludedResources(long theExcludedResources) {
|
||||
myExcludedResources = theExcludedResources;
|
||||
}
|
||||
}
|
|
@ -49,6 +49,12 @@ public class MdmTransactionContext {
|
|||
|
||||
private String myResourceType;
|
||||
|
||||
/**
|
||||
* Whether or not the currently processed resource is a 'blocked resource'.
|
||||
* This will only be set on matching.
|
||||
*/
|
||||
private boolean myIsBlockedResource;
|
||||
|
||||
private List<IMdmLink> myMdmLinkEvents = new ArrayList<>();
|
||||
|
||||
public TransactionLogMessages getTransactionLogMessages() {
|
||||
|
@ -111,4 +117,12 @@ public class MdmTransactionContext {
|
|||
public void setMdmLinks(List<IMdmLink> theMdmLinkEvents) {
|
||||
myMdmLinkEvents = theMdmLinkEvents;
|
||||
}
|
||||
|
||||
public void setIsBlocked(boolean theIsBlocked) {
|
||||
myIsBlockedResource = theIsBlocked;
|
||||
}
|
||||
|
||||
public boolean getIsBlocked() {
|
||||
return myIsBlockedResource;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -116,6 +116,14 @@ public class GoldenResourceHelper {
|
|||
MdmResourceUtil.setMdmManaged(newGoldenResource);
|
||||
MdmResourceUtil.setGoldenResource(newGoldenResource);
|
||||
|
||||
// TODO - on updating links, if resolving a link, this should go away?
|
||||
// blocked resource's golden resource will be marked special
|
||||
// they are not part of MDM matching algorithm (will not link to other resources)
|
||||
// but other resources can link to them
|
||||
if (theMdmTransactionContext.getIsBlocked()) {
|
||||
MdmResourceUtil.setGoldenResourceAsBlockedResourceGoldenResource(newGoldenResource);
|
||||
}
|
||||
|
||||
// add the partition id to the new resource
|
||||
newGoldenResource.setUserData(
|
||||
Constants.RESOURCE_PARTITION_ID,
|
||||
|
|
|
@ -132,6 +132,24 @@ public final class MdmResourceUtil {
|
|||
MdmConstants.DISPLAY_GOLDEN_REDIRECT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the BLOCKED tag to the golden resource.
|
||||
* Because this is called *before* a resource is saved,
|
||||
* we must add a new system/code combo to it
|
||||
* @param theBaseResource
|
||||
* @return
|
||||
*/
|
||||
public static IBaseResource setGoldenResourceAsBlockedResourceGoldenResource(IBaseResource theBaseResource) {
|
||||
IBaseCoding tag = theBaseResource.getMeta().addTag();
|
||||
tag.setSystem(MdmConstants.SYSTEM_GOLDEN_RECORD_STATUS);
|
||||
tag.setCode(MdmConstants.CODE_BLOCKED);
|
||||
tag.setDisplay(MdmConstants.CODE_BLOCKED_DISPLAY);
|
||||
tag.setUserSelected(false);
|
||||
tag.setVersion("1");
|
||||
|
||||
return theBaseResource;
|
||||
}
|
||||
|
||||
/**
|
||||
* WARNING: This code may _look_ like it replaces in place a code of a tag, but this DOES NOT ACTUALLY WORK!. In reality what will
|
||||
* happen is a secondary tag will be created with the same system. the only way to actually remove a tag from a resource
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
package ca.uhn.fhir.mdm.util;
|
||||
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.mdm.api.MdmConstants;
|
||||
import ca.uhn.fhir.mdm.rules.json.MdmRulesJson;
|
||||
import ca.uhn.fhir.rest.param.TokenAndListParam;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
|
||||
public class MdmSearchParamBuildingUtils {
|
||||
|
||||
private static final String IDENTIFIER = "identifier";
|
||||
|
||||
private static final String TAG = "_tag";
|
||||
|
||||
/**
|
||||
* Builds a search parameter map that can be used to find the
|
||||
* golden resources associated with MDM blocked resources (ie, those
|
||||
* resources that were omitted from MDM matching).
|
||||
*/
|
||||
public static SearchParameterMap buildSearchParameterForBlockedResourceCount(String theResourceType) {
|
||||
SearchParameterMap map = new SearchParameterMap();
|
||||
map.setLoadSynchronous(true);
|
||||
TokenAndListParam tagsToSearch = new TokenAndListParam();
|
||||
tagsToSearch.addAnd(new TokenParam(MdmConstants.SYSTEM_GOLDEN_RECORD_STATUS, MdmConstants.CODE_GOLDEN_RECORD));
|
||||
tagsToSearch.addAnd(new TokenParam(MdmConstants.SYSTEM_GOLDEN_RECORD_STATUS, MdmConstants.CODE_BLOCKED));
|
||||
|
||||
map.add(TAG, tagsToSearch);
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a SearchParameterMap used for searching for golden resources
|
||||
* by EID specifically.
|
||||
*/
|
||||
public static SearchParameterMap buildEidSearchParameterMap(
|
||||
String theEid, String theResourceType, MdmRulesJson theMdmRules) {
|
||||
SearchParameterMap map = buildBasicGoldenResourceSearchParameterMap(theEid);
|
||||
map.add(IDENTIFIER, new TokenParam(theMdmRules.getEnterpriseEIDSystemForResourceType(theResourceType), theEid));
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a SearchParameterMap that can be used to find golden resources.
|
||||
*/
|
||||
public static SearchParameterMap buildBasicGoldenResourceSearchParameterMap(String theResourceType) {
|
||||
SearchParameterMap map = new SearchParameterMap();
|
||||
map.setLoadSynchronous(true);
|
||||
map.add(TAG, new TokenParam(MdmConstants.SYSTEM_GOLDEN_RECORD_STATUS, MdmConstants.CODE_GOLDEN_RECORD));
|
||||
return map;
|
||||
}
|
||||
}
|
|
@ -1,11 +1,21 @@
|
|||
package ca.uhn.fhir.mdm.util;
|
||||
|
||||
import ca.uhn.fhir.mdm.api.MdmConstants;
|
||||
import org.hl7.fhir.r4.model.Coding;
|
||||
import org.hl7.fhir.r4.model.Organization;
|
||||
import org.hl7.fhir.r4.model.Patient;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class MdmResourceUtilTest {
|
||||
|
||||
|
@ -20,4 +30,28 @@ class MdmResourceUtilTest {
|
|||
|
||||
assertThat(hasGoldenRecordTag, is(equalTo(false)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetGoldenAndBlockedResource() {
|
||||
// setup
|
||||
Patient patient = new Patient();
|
||||
patient.setActive(true);
|
||||
|
||||
// test
|
||||
Patient changed = (Patient) MdmResourceUtil.setGoldenResourceAsBlockedResourceGoldenResource(
|
||||
MdmResourceUtil.setGoldenResource(patient)
|
||||
);
|
||||
|
||||
// verify
|
||||
assertNotNull(changed);
|
||||
List<Coding> tags = changed.getMeta().getTag();
|
||||
Set<String> codes = new HashSet<>();
|
||||
codes.add(MdmConstants.CODE_BLOCKED);
|
||||
codes.add(MdmConstants.CODE_GOLDEN_RECORD);
|
||||
assertEquals(2, tags.size());
|
||||
for (Coding code : tags) {
|
||||
assertEquals(MdmConstants.SYSTEM_GOLDEN_RECORD_STATUS, code.getSystem());
|
||||
assertTrue(codes.contains(code.getCode()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-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.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<artifactId>hapi-fhir-serviceloaders</artifactId>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<version>6.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<artifactId>hapi-fhir-serviceloaders</artifactId>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<version>6.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
@ -21,7 +21,7 @@
|
|||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-caching-api</artifactId>
|
||||
<version>6.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-SNAPSHOT</version>
|
||||
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<artifactId>hapi-fhir-serviceloaders</artifactId>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<version>6.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<version>6.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<version>6.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-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.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||
<version>6.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hapi-fhir-spring-boot-sample-client-apache</artifactId>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||
<version>6.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-SNAPSHOT</version>
|
||||
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||
<version>6.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-SNAPSHOT</version>
|
||||
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-spring-boot</artifactId>
|
||||
<version>6.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-SNAPSHOT</version>
|
||||
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-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.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-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.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-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.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-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.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-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.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-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.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-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.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-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.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-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.9.8-SNAPSHOT</version>
|
||||
<version>6.9.9-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