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>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-bom</artifactId>
|
<artifactId>hapi-fhir-bom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<name>HAPI FHIR BOM</name>
|
<name>HAPI FHIR BOM</name>
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-cli</artifactId>
|
<artifactId>hapi-fhir-cli</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</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>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</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"),
|
@Index(name = "IDX_EMPI_MATCH_TGT_VER", columnList = "MATCH_RESULT, TARGET_PID, VERSION"),
|
||||||
// v---- this one
|
// v---- this one
|
||||||
@Index(name = "IDX_EMPI_GR_TGT", columnList = "GOLDEN_RESOURCE_PID, TARGET_PID"),
|
@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
|
@Audited
|
||||||
// This is the table name generated by default by envers, but we set it explicitly for clarity
|
// 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();
|
init640_after_20230126();
|
||||||
init660();
|
init660();
|
||||||
init680();
|
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() {
|
protected void init680() {
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</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.MdmMatchFinderSvcImpl;
|
||||||
import ca.uhn.fhir.jpa.mdm.svc.MdmMatchLinkSvc;
|
import ca.uhn.fhir.jpa.mdm.svc.MdmMatchLinkSvc;
|
||||||
import ca.uhn.fhir.jpa.mdm.svc.MdmModelConverterSvcImpl;
|
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.MdmResourceFilteringSvc;
|
||||||
import ca.uhn.fhir.jpa.mdm.svc.candidate.CandidateSearcher;
|
import ca.uhn.fhir.jpa.mdm.svc.candidate.CandidateSearcher;
|
||||||
import ca.uhn.fhir.jpa.mdm.svc.candidate.FindCandidateByEidSvc;
|
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.IMdmLinkSvc;
|
||||||
import ca.uhn.fhir.mdm.api.IMdmLinkUpdaterSvc;
|
import ca.uhn.fhir.mdm.api.IMdmLinkUpdaterSvc;
|
||||||
import ca.uhn.fhir.mdm.api.IMdmMatchFinderSvc;
|
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.api.IMdmSettings;
|
||||||
import ca.uhn.fhir.mdm.batch2.MdmBatch2Config;
|
import ca.uhn.fhir.mdm.batch2.MdmBatch2Config;
|
||||||
import ca.uhn.fhir.mdm.blocklist.svc.IBlockListRuleProvider;
|
import ca.uhn.fhir.mdm.blocklist.svc.IBlockListRuleProvider;
|
||||||
|
@ -123,8 +124,8 @@ public class MdmConsumerConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
MdmResourceDaoSvc mdmResourceDaoSvc() {
|
IMdmResourceDaoSvc mdmResourceDaoSvc() {
|
||||||
return new MdmResourceDaoSvc();
|
return new MdmResourceDaoSvcImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@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.IGoldenResourceMergerSvc;
|
||||||
import ca.uhn.fhir.mdm.api.IMdmLink;
|
import ca.uhn.fhir.mdm.api.IMdmLink;
|
||||||
import ca.uhn.fhir.mdm.api.IMdmLinkSvc;
|
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.IMdmSurvivorshipService;
|
||||||
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
||||||
import ca.uhn.fhir.mdm.api.MdmMatchOutcome;
|
import ca.uhn.fhir.mdm.api.MdmMatchOutcome;
|
||||||
|
@ -74,7 +75,7 @@ public class GoldenResourceMergerSvcImpl implements IGoldenResourceMergerSvc {
|
||||||
IIdHelperService myIdHelperService;
|
IIdHelperService myIdHelperService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
MdmResourceDaoSvc myMdmResourceDaoSvc;
|
IMdmResourceDaoSvc myMdmResourceDaoSvc;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
MdmPartitionHelper myMdmPartitionHelper;
|
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.jpa.mdm.svc.candidate.MdmGoldenResourceFindingSvc;
|
||||||
import ca.uhn.fhir.mdm.api.IMdmLink;
|
import ca.uhn.fhir.mdm.api.IMdmLink;
|
||||||
import ca.uhn.fhir.mdm.api.IMdmLinkSvc;
|
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.IMdmSettings;
|
||||||
import ca.uhn.fhir.mdm.api.IMdmSurvivorshipService;
|
import ca.uhn.fhir.mdm.api.IMdmSurvivorshipService;
|
||||||
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
||||||
|
@ -49,7 +50,7 @@ public class MdmEidUpdateService {
|
||||||
private static final Logger ourLog = Logs.getMdmTroubleshootingLog();
|
private static final Logger ourLog = Logs.getMdmTroubleshootingLog();
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private MdmResourceDaoSvc myMdmResourceDaoSvc;
|
private IMdmResourceDaoSvc myMdmResourceDaoSvc;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private IMdmLinkSvc myMdmLinkSvc;
|
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.jpa.mdm.dao.MdmLinkDaoSvc;
|
||||||
import ca.uhn.fhir.mdm.api.IMdmLink;
|
import ca.uhn.fhir.mdm.api.IMdmLink;
|
||||||
import ca.uhn.fhir.mdm.api.IMdmLinkSvc;
|
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.MdmLinkSourceEnum;
|
||||||
import ca.uhn.fhir.mdm.api.MdmMatchOutcome;
|
import ca.uhn.fhir.mdm.api.MdmMatchOutcome;
|
||||||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||||
|
@ -51,7 +52,7 @@ public class MdmLinkSvcImpl implements IMdmLinkSvc {
|
||||||
private static final Logger ourLog = Logs.getMdmTroubleshootingLog();
|
private static final Logger ourLog = Logs.getMdmTroubleshootingLog();
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private MdmResourceDaoSvc myMdmResourceDaoSvc;
|
private IMdmResourceDaoSvc myMdmResourceDaoSvc;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private MdmLinkDaoSvc myMdmLinkDaoSvc;
|
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.jpa.model.entity.PartitionablePartitionId;
|
||||||
import ca.uhn.fhir.mdm.api.IMdmLink;
|
import ca.uhn.fhir.mdm.api.IMdmLink;
|
||||||
import ca.uhn.fhir.mdm.api.IMdmLinkUpdaterSvc;
|
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.IMdmSettings;
|
||||||
import ca.uhn.fhir.mdm.api.IMdmSurvivorshipService;
|
import ca.uhn.fhir.mdm.api.IMdmSurvivorshipService;
|
||||||
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
||||||
|
@ -72,7 +73,7 @@ public class MdmLinkUpdaterSvcImpl implements IMdmLinkUpdaterSvc {
|
||||||
MdmLinkDaoSvc myMdmLinkDaoSvc;
|
MdmLinkDaoSvc myMdmLinkDaoSvc;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
MdmResourceDaoSvc myMdmResourceDaoSvc;
|
IMdmResourceDaoSvc myMdmResourceDaoSvc;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
MdmMatchLinkSvc myMdmMatchLinkSvc;
|
MdmMatchLinkSvc myMdmMatchLinkSvc;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
*/
|
*/
|
||||||
package ca.uhn.fhir.jpa.mdm.svc;
|
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.models.FindGoldenResourceCandidatesParams;
|
||||||
import ca.uhn.fhir.jpa.mdm.svc.candidate.CandidateList;
|
import ca.uhn.fhir.jpa.mdm.svc.candidate.CandidateList;
|
||||||
import ca.uhn.fhir.jpa.mdm.svc.candidate.CandidateStrategyEnum;
|
import ca.uhn.fhir.jpa.mdm.svc.candidate.CandidateStrategyEnum;
|
||||||
|
@ -70,6 +71,9 @@ public class MdmMatchLinkSvc {
|
||||||
@Autowired
|
@Autowired
|
||||||
private IBlockRuleEvaluationSvc myBlockRuleEvaluationSvc;
|
private IBlockRuleEvaluationSvc myBlockRuleEvaluationSvc;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DaoRegistry myDaoRegistry;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private IMdmSurvivorshipService myMdmSurvivorshipService;
|
private IMdmSurvivorshipService myMdmSurvivorshipService;
|
||||||
|
|
||||||
|
@ -106,6 +110,8 @@ public class MdmMatchLinkSvc {
|
||||||
* (so that future resources may match to it).
|
* (so that future resources may match to it).
|
||||||
*/
|
*/
|
||||||
boolean isResourceBlocked = myBlockRuleEvaluationSvc.isMdmMatchingBlocked(theResource);
|
boolean isResourceBlocked = myBlockRuleEvaluationSvc.isMdmMatchingBlocked(theResource);
|
||||||
|
// we will mark the golden resource special for this
|
||||||
|
theMdmTransactionContext.setIsBlocked(isResourceBlocked);
|
||||||
|
|
||||||
if (!isResourceBlocked) {
|
if (!isResourceBlocked) {
|
||||||
FindGoldenResourceCandidatesParams params =
|
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.api.model.DaoMethodOutcome;
|
||||||
import ca.uhn.fhir.jpa.model.entity.TagTypeEnum;
|
import ca.uhn.fhir.jpa.model.entity.TagTypeEnum;
|
||||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
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.IMdmSettings;
|
||||||
import ca.uhn.fhir.mdm.api.MdmConstants;
|
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.Constants;
|
||||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.api.server.SystemRequestDetails;
|
import ca.uhn.fhir.rest.api.server.SystemRequestDetails;
|
||||||
import ca.uhn.fhir.rest.api.server.storage.IResourcePersistentId;
|
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 ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
@ -42,10 +43,9 @@ import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class MdmResourceDaoSvc {
|
public class MdmResourceDaoSvcImpl implements IMdmResourceDaoSvc {
|
||||||
|
|
||||||
private static final int MAX_MATCHING_GOLDEN_RESOURCES = 1000;
|
private static final int MAX_MATCHING_GOLDEN_RESOURCES = 1000;
|
||||||
|
|
||||||
|
@ -55,6 +55,7 @@ public class MdmResourceDaoSvc {
|
||||||
@Autowired
|
@Autowired
|
||||||
IMdmSettings myMdmSettings;
|
IMdmSettings myMdmSettings;
|
||||||
|
|
||||||
|
@Override
|
||||||
public DaoMethodOutcome upsertGoldenResource(IAnyResource theGoldenResource, String theResourceType) {
|
public DaoMethodOutcome upsertGoldenResource(IAnyResource theGoldenResource, String theResourceType) {
|
||||||
IFhirResourceDao resourceDao = myDaoRegistry.getResourceDao(theResourceType);
|
IFhirResourceDao resourceDao = myDaoRegistry.getResourceDao(theResourceType);
|
||||||
RequestDetails requestDetails = new SystemRequestDetails().setRequestPartitionId((RequestPartitionId)
|
RequestDetails requestDetails = new SystemRequestDetails().setRequestPartitionId((RequestPartitionId)
|
||||||
|
@ -66,12 +67,7 @@ public class MdmResourceDaoSvc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
public void removeGoldenResourceTag(IAnyResource theGoldenResource, String theResourcetype) {
|
public void removeGoldenResourceTag(IAnyResource theGoldenResource, String theResourcetype) {
|
||||||
IFhirResourceDao resourceDao = myDaoRegistry.getResourceDao(theResourcetype);
|
IFhirResourceDao resourceDao = myDaoRegistry.getResourceDao(theResourcetype);
|
||||||
RequestDetails requestDetails = new SystemRequestDetails().setRequestPartitionId((RequestPartitionId)
|
RequestDetails requestDetails = new SystemRequestDetails().setRequestPartitionId((RequestPartitionId)
|
||||||
|
@ -84,18 +80,22 @@ public class MdmResourceDaoSvc {
|
||||||
requestDetails);
|
requestDetails);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public IAnyResource readGoldenResourceByPid(IResourcePersistentId theGoldenResourcePid, String theResourceType) {
|
public IAnyResource readGoldenResourceByPid(IResourcePersistentId theGoldenResourcePid, String theResourceType) {
|
||||||
IFhirResourceDao resourceDao = myDaoRegistry.getResourceDao(theResourceType);
|
IFhirResourceDao resourceDao = myDaoRegistry.getResourceDao(theResourceType);
|
||||||
return (IAnyResource) resourceDao.readByPid(theGoldenResourcePid);
|
return (IAnyResource) resourceDao.readByPid(theGoldenResourcePid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Optional<IAnyResource> searchGoldenResourceByEID(String theEid, String theResourceType) {
|
public Optional<IAnyResource> searchGoldenResourceByEID(String theEid, String theResourceType) {
|
||||||
return this.searchGoldenResourceByEID(theEid, theResourceType, null);
|
return this.searchGoldenResourceByEID(theEid, theResourceType, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Optional<IAnyResource> searchGoldenResourceByEID(
|
public Optional<IAnyResource> searchGoldenResourceByEID(
|
||||||
String theEid, String theResourceType, RequestPartitionId thePartitionId) {
|
String theEid, String theResourceType, RequestPartitionId thePartitionId) {
|
||||||
SearchParameterMap map = buildEidSearchParameterMap(theEid, theResourceType);
|
SearchParameterMap map = MdmSearchParamBuildingUtils.buildEidSearchParameterMap(
|
||||||
|
theEid, theResourceType, myMdmSettings.getMdmRules());
|
||||||
|
|
||||||
IFhirResourceDao resourceDao = myDaoRegistry.getResourceDao(theResourceType);
|
IFhirResourceDao resourceDao = myDaoRegistry.getResourceDao(theResourceType);
|
||||||
SystemRequestDetails systemRequestDetails = new SystemRequestDetails();
|
SystemRequestDetails systemRequestDetails = new SystemRequestDetails();
|
||||||
|
@ -118,16 +118,4 @@ public class MdmResourceDaoSvc {
|
||||||
return Optional.of((IAnyResource) resources.get(0));
|
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.interceptor.model.RequestPartitionId;
|
||||||
import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc;
|
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.IMdmLink;
|
||||||
|
import ca.uhn.fhir.mdm.api.IMdmResourceDaoSvc;
|
||||||
import ca.uhn.fhir.mdm.api.MdmMatchOutcome;
|
import ca.uhn.fhir.mdm.api.MdmMatchOutcome;
|
||||||
import ca.uhn.fhir.mdm.log.Logs;
|
import ca.uhn.fhir.mdm.log.Logs;
|
||||||
import ca.uhn.fhir.mdm.model.CanonicalEID;
|
import ca.uhn.fhir.mdm.model.CanonicalEID;
|
||||||
|
@ -47,7 +47,7 @@ public class FindCandidateByEidSvc extends BaseCandidateFinder {
|
||||||
private EIDHelper myEIDHelper;
|
private EIDHelper myEIDHelper;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private MdmResourceDaoSvc myMdmResourceDaoSvc;
|
private IMdmResourceDaoSvc myMdmResourceDaoSvc;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private MdmLinkDaoSvc myMdmLinkDaoSvc;
|
private MdmLinkDaoSvc myMdmLinkDaoSvc;
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
package ca.uhn.fhir.jpa.mdm.svc.candidate;
|
package ca.uhn.fhir.jpa.mdm.svc.candidate;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.mdm.models.FindGoldenResourceCandidatesParams;
|
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.log.Logs;
|
||||||
import ca.uhn.fhir.mdm.model.MdmTransactionContext;
|
import ca.uhn.fhir.mdm.model.MdmTransactionContext;
|
||||||
import ca.uhn.fhir.rest.api.server.storage.IResourcePersistentId;
|
import ca.uhn.fhir.rest.api.server.storage.IResourcePersistentId;
|
||||||
|
@ -36,7 +36,7 @@ public class MdmGoldenResourceFindingSvc {
|
||||||
private static final Logger ourLog = Logs.getMdmTroubleshootingLog();
|
private static final Logger ourLog = Logs.getMdmTroubleshootingLog();
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private MdmResourceDaoSvc myMdmResourceDaoSvc;
|
private IMdmResourceDaoSvc myMdmResourceDaoSvc;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private FindCandidateByEidSvc myFindCandidateByEidSvc;
|
private FindCandidateByEidSvc myFindCandidateByEidSvc;
|
||||||
|
|
|
@ -98,8 +98,6 @@ abstract public class BaseMdmR4Test extends BaseJpaR4Test {
|
||||||
.setValue("555-555-5555");
|
.setValue("555-555-5555");
|
||||||
private static final String NAME_GIVEN_FRANK = "Frank";
|
private static final String NAME_GIVEN_FRANK = "Frank";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
protected IFhirResourceDao<Patient> myPatientDao;
|
protected IFhirResourceDao<Patient> myPatientDao;
|
||||||
@Autowired
|
@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;
|
private IMdmLinkUpdaterSvc myMdmLinkUpdaterSvc;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private MdmResourceDaoSvc myMdmResourceDaoSvc;
|
private MdmResourceDaoSvcImpl myMdmResourceDaoSvc;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private MessageHelper myMessageHelper;
|
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.model.config.PartitionSettings;
|
||||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||||
import ca.uhn.fhir.jpa.searchparam.extractor.ISearchParamExtractor;
|
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.mdm.util.MdmResourceUtil;
|
||||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||||
import ca.uhn.fhir.rest.api.server.SystemRequestDetails;
|
import ca.uhn.fhir.rest.api.server.SystemRequestDetails;
|
||||||
import ca.uhn.fhir.rest.param.StringOrListParam;
|
import ca.uhn.fhir.rest.param.StringOrListParam;
|
||||||
import ca.uhn.fhir.rest.param.StringParam;
|
import ca.uhn.fhir.rest.param.StringParam;
|
||||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
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.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.r4.model.Patient;
|
import org.hl7.fhir.r4.model.Patient;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
@ -21,7 +21,6 @@ import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@ -35,7 +34,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
public class MdmResourceDaoSvcTest extends BaseMdmR4Test {
|
public class MdmResourceDaoSvcTest extends BaseMdmR4Test {
|
||||||
private static final String TEST_EID = "TEST_EID";
|
private static final String TEST_EID = "TEST_EID";
|
||||||
@Autowired
|
@Autowired
|
||||||
MdmResourceDaoSvc myResourceDaoSvc;
|
IMdmResourceDaoSvc myResourceDaoSvc;
|
||||||
@Autowired
|
@Autowired
|
||||||
private ISearchParamExtractor mySearchParamExtractor;
|
private ISearchParamExtractor mySearchParamExtractor;
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</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>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</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";
|
"http://hapifhir.io/fhir/NamingSystem/mdm-golden-resource-enterprise-id";
|
||||||
public static final String ALL_RESOURCE_SEARCH_PARAM_TYPE = "*";
|
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 =
|
public static final String FIHR_STRUCTURE_DEF_MATCH_GRADE_URL_NAMESPACE =
|
||||||
"http://hl7.org/fhir/StructureDefinition/match-grade";
|
"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;
|
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<>();
|
private List<IMdmLink> myMdmLinkEvents = new ArrayList<>();
|
||||||
|
|
||||||
public TransactionLogMessages getTransactionLogMessages() {
|
public TransactionLogMessages getTransactionLogMessages() {
|
||||||
|
@ -111,4 +117,12 @@ public class MdmTransactionContext {
|
||||||
public void setMdmLinks(List<IMdmLink> theMdmLinkEvents) {
|
public void setMdmLinks(List<IMdmLink> theMdmLinkEvents) {
|
||||||
myMdmLinkEvents = 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.setMdmManaged(newGoldenResource);
|
||||||
MdmResourceUtil.setGoldenResource(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
|
// add the partition id to the new resource
|
||||||
newGoldenResource.setUserData(
|
newGoldenResource.setUserData(
|
||||||
Constants.RESOURCE_PARTITION_ID,
|
Constants.RESOURCE_PARTITION_ID,
|
||||||
|
|
|
@ -132,6 +132,24 @@ public final class MdmResourceUtil {
|
||||||
MdmConstants.DISPLAY_GOLDEN_REDIRECT);
|
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
|
* 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
|
* 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;
|
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.Organization;
|
||||||
|
import org.hl7.fhir.r4.model.Patient;
|
||||||
import org.junit.jupiter.api.Test;
|
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.equalTo;
|
||||||
import static org.hamcrest.CoreMatchers.is;
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
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 {
|
class MdmResourceUtilTest {
|
||||||
|
|
||||||
|
@ -20,4 +30,28 @@ class MdmResourceUtilTest {
|
||||||
|
|
||||||
assertThat(hasGoldenRecordTag, is(equalTo(false)));
|
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>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>hapi-fhir-serviceloaders</artifactId>
|
<artifactId>hapi-fhir-serviceloaders</artifactId>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>hapi-fhir-serviceloaders</artifactId>
|
<artifactId>hapi-fhir-serviceloaders</artifactId>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-caching-api</artifactId>
|
<artifactId>hapi-fhir-caching-api</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>hapi-fhir-serviceloaders</artifactId>
|
<artifactId>hapi-fhir-serviceloaders</artifactId>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<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>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hapi-fhir-spring-boot-sample-client-apache</artifactId>
|
<artifactId>hapi-fhir-spring-boot-sample-client-apache</artifactId>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-spring-boot</artifactId>
|
<artifactId>hapi-fhir-spring-boot</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.9.8-SNAPSHOT</version>
|
<version>6.9.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue