3924 mdm match resources across partitions and storing golden resources on a specific partition (#4770)

* added mdm search all partition for golden resource functionality

* added mdm partition setting

* build header fix

* test fixes and added missing side effect of allowing cross partition links on opeartions

* added changelog, also test fixes

* fixed changelog to an actual yaml file

* review fixes,  also simplified tests

* reverted one test because the original test schenario was correct

* added setting clearing in afterEach method so test dont fail while run in maven

* bump to pre-15

---------

Co-authored-by: Long Ma <long@smilecdr.com>
This commit is contained in:
longma1 2023-04-28 02:15:35 -06:00 committed by GitHub
parent 457b39bac1
commit 2171ad04a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
94 changed files with 417 additions and 143 deletions

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-bom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<packaging>pom</packaging>
<name>HAPI FHIR BOM</name>
@ -12,7 +12,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-cli</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../../hapi-deployable-pom</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -0,0 +1,5 @@
---
type: add
issue: 4773
title: "Added mdm setting allowing for resources to be matched regardless of partition, also added mdm setting
for the storage of all golden resources in a single designated partition"

View File

@ -11,7 +11,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -48,7 +48,7 @@ import ca.uhn.fhir.jpa.mdm.svc.candidate.FindCandidateByLinkSvc;
import ca.uhn.fhir.jpa.mdm.svc.candidate.MdmCandidateSearchCriteriaBuilderSvc;
import ca.uhn.fhir.jpa.mdm.svc.candidate.MdmCandidateSearchSvc;
import ca.uhn.fhir.jpa.mdm.svc.candidate.MdmGoldenResourceFindingSvc;
import ca.uhn.fhir.jpa.mdm.util.MdmPartitionHelper;
import ca.uhn.fhir.mdm.util.MdmPartitionHelper;
import ca.uhn.fhir.jpa.partition.IRequestPartitionHelperSvc;
import ca.uhn.fhir.jpa.subscription.channel.api.IChannelFactory;
import ca.uhn.fhir.mdm.api.IGoldenResourceMergerSvc;
@ -266,7 +266,10 @@ public class MdmConsumerConfig {
}
@Bean
MdmPartitionHelper mdmPartitionHelper() {return new MdmPartitionHelper();}
MdmPartitionHelper mdmPartitionHelper(MessageHelper theMessageHelper,
IMdmSettings theMdmSettings) {
return new MdmPartitionHelper(theMessageHelper, theMdmSettings);
}
@Bean
public IGoldenResourceSearchSvc goldenResourceSearchSvc() {

View File

@ -23,7 +23,7 @@ import ca.uhn.fhir.i18n.Msg;
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc;
import ca.uhn.fhir.jpa.mdm.util.MdmPartitionHelper;
import ca.uhn.fhir.mdm.util.MdmPartitionHelper;
import ca.uhn.fhir.mdm.api.IGoldenResourceMergerSvc;
import ca.uhn.fhir.mdm.api.IMdmLink;
import ca.uhn.fhir.mdm.api.IMdmLinkSvc;
@ -87,8 +87,7 @@ public class GoldenResourceMergerSvcImpl implements IGoldenResourceMergerSvc {
myMdmResourceDaoSvc.upsertGoldenResource(theToGoldenResource, resourceType);
}
// check if the golden resource and the source resource are in the same partition, throw error if not
myMdmPartitionHelper.validateResourcesInSamePartition(theFromGoldenResource, theToGoldenResource);
myMdmPartitionHelper.validateMdmResourcesPartitionMatches(theFromGoldenResource, theToGoldenResource);
//Merge the links from the FROM to the TO resource. Clean up dangling links.
mergeGoldenResourceLinks(theFromGoldenResource, theToGoldenResource, theFromGoldenResource.getIdElement(), theMdmTransactionContext);

View File

@ -24,7 +24,7 @@ import ca.uhn.fhir.i18n.Msg;
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc;
import ca.uhn.fhir.jpa.mdm.util.MdmPartitionHelper;
import ca.uhn.fhir.mdm.util.MdmPartitionHelper;
import ca.uhn.fhir.jpa.model.entity.PartitionablePartitionId;
import ca.uhn.fhir.mdm.api.IMdmLink;
import ca.uhn.fhir.mdm.api.IMdmLinkCreateSvc;
@ -74,7 +74,7 @@ public class MdmLinkCreateSvcImpl implements IMdmLinkCreateSvc {
IResourcePersistentId targetId = myIdHelperService.getPidOrThrowException(theSourceResource);
// check if the golden resource and the source resource are in the same partition, throw error if not
myMdmPartitionHelper.validateResourcesInSamePartition(theGoldenResource, theSourceResource);
myMdmPartitionHelper.validateMdmResourcesPartitionMatches(theGoldenResource, theSourceResource);
Optional<? extends IMdmLink> optionalMdmLink = myMdmLinkDaoSvc.getLinkByGoldenResourcePidAndSourceResourcePid(goldenResourceId, targetId);
if (optionalMdmLink.isPresent()) {

View File

@ -24,7 +24,7 @@ import ca.uhn.fhir.i18n.Msg;
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc;
import ca.uhn.fhir.jpa.mdm.util.MdmPartitionHelper;
import ca.uhn.fhir.mdm.util.MdmPartitionHelper;
import ca.uhn.fhir.jpa.model.entity.PartitionablePartitionId;
import ca.uhn.fhir.mdm.api.IMdmLink;
import ca.uhn.fhir.mdm.api.IMdmLinkUpdaterSvc;
@ -82,8 +82,8 @@ public class MdmLinkUpdaterSvcImpl implements IMdmLinkUpdaterSvc {
IResourcePersistentId goldenResourceId = myIdHelperService.getPidOrThrowException(theGoldenResource);
IResourcePersistentId sourceResourceId = myIdHelperService.getPidOrThrowException(theSourceResource);
// check if the golden resource and the source resource are in the same partition, throw error if not
myMdmPartitionHelper.validateResourcesInSamePartition(theGoldenResource, theSourceResource);
// check if the golden resource and the source resource are in the same partition if cross partition mdm is not allowed, throw error if not
myMdmPartitionHelper.validateMdmResourcesPartitionMatches(theGoldenResource, theSourceResource);
Optional<? extends IMdmLink> optionalMdmLink = myMdmLinkDaoSvc.getLinkByGoldenResourcePidAndSourceResourcePid(goldenResourceId, sourceResourceId);
if (optionalMdmLink.isEmpty()) {

View File

@ -22,12 +22,12 @@ package ca.uhn.fhir.jpa.mdm.svc.candidate;
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc;
import ca.uhn.fhir.jpa.mdm.svc.MdmResourceDaoSvc;
import ca.uhn.fhir.mdm.util.MdmPartitionHelper;
import ca.uhn.fhir.mdm.api.IMdmLink;
import ca.uhn.fhir.mdm.api.MdmMatchOutcome;
import ca.uhn.fhir.mdm.log.Logs;
import ca.uhn.fhir.mdm.model.CanonicalEID;
import ca.uhn.fhir.mdm.util.EIDHelper;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.server.storage.IResourcePersistentId;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.slf4j.Logger;
@ -49,6 +49,8 @@ public class FindCandidateByEidSvc extends BaseCandidateFinder {
private MdmResourceDaoSvc myMdmResourceDaoSvc;
@Autowired
private MdmLinkDaoSvc myMdmLinkDaoSvc;
@Autowired
MdmPartitionHelper myMdmPartitionHelper;
@Override
protected List<MatchedGoldenResourceCandidate> findMatchGoldenResourceCandidates(IAnyResource theIncomingResource) {
@ -57,7 +59,7 @@ public class FindCandidateByEidSvc extends BaseCandidateFinder {
List<CanonicalEID> eidFromResource = myEIDHelper.getExternalEid(theIncomingResource);
if (!eidFromResource.isEmpty()) {
for (CanonicalEID eid : eidFromResource) {
Optional<IAnyResource> oFoundGoldenResource = myMdmResourceDaoSvc.searchGoldenResourceByEID(eid.getValue(), theIncomingResource.getIdElement().getResourceType(), (RequestPartitionId) theIncomingResource.getUserData(Constants.RESOURCE_PARTITION_ID));
Optional<IAnyResource> oFoundGoldenResource = myMdmResourceDaoSvc.searchGoldenResourceByEID(eid.getValue(), theIncomingResource.getIdElement().getResourceType(), myMdmPartitionHelper.getRequestPartitionIdFromResourceForSearch(theIncomingResource));
if (oFoundGoldenResource.isPresent()) {
IAnyResource foundGoldenResource = oFoundGoldenResource.get();
// Exclude manually declared NO_MATCH links from candidates

View File

@ -23,12 +23,12 @@ import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc;
import ca.uhn.fhir.mdm.util.MdmPartitionHelper;
import ca.uhn.fhir.mdm.api.IMdmLink;
import ca.uhn.fhir.mdm.api.IMdmMatchFinderSvc;
import ca.uhn.fhir.mdm.api.MatchedTarget;
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
import ca.uhn.fhir.mdm.log.Logs;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.server.storage.IResourcePersistentId;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IBaseResource;
@ -52,6 +52,8 @@ public class FindCandidateByExampleSvc<P extends IResourcePersistentId> extends
private MdmLinkDaoSvc<P, IMdmLink<P>> myMdmLinkDaoSvc;
@Autowired
private IMdmMatchFinderSvc myMdmMatchFinderSvc;
@Autowired
MdmPartitionHelper myMdmPartitionHelper;
/**
* Attempt to find matching Golden Resources by resolving them from similar Matching target resources. Runs MDM logic
@ -67,7 +69,7 @@ public class FindCandidateByExampleSvc<P extends IResourcePersistentId> extends
List<P> goldenResourcePidsToExclude = getNoMatchGoldenResourcePids(theTarget);
List<MatchedTarget> matchedCandidates = myMdmMatchFinderSvc.getMatchedTargets(myFhirContext.getResourceType(theTarget), theTarget, (RequestPartitionId) theTarget.getUserData(Constants.RESOURCE_PARTITION_ID));
List<MatchedTarget> matchedCandidates = myMdmMatchFinderSvc.getMatchedTargets(myFhirContext.getResourceType(theTarget), theTarget, myMdmPartitionHelper.getRequestPartitionIdFromResourceForSearch(theTarget));
// Convert all possible match targets to their equivalent Golden Resources by looking up in the MdmLink table,
// while ensuring that the matches aren't in our NO_MATCH list.

View File

@ -1,44 +0,0 @@
/*-
* #%L
* HAPI FHIR JPA Server - Master Data Management
* %%
* Copyright (C) 2014 - 2023 Smile CDR, Inc.
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
package ca.uhn.fhir.jpa.mdm.util;
import ca.uhn.fhir.i18n.Msg;
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
import ca.uhn.fhir.mdm.util.MessageHelper;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class MdmPartitionHelper {
@Autowired
MessageHelper myMessageHelper;
public void validateResourcesInSamePartition(IAnyResource theFromResource, IAnyResource theToResource){
RequestPartitionId fromGoldenResourcePartitionId = (RequestPartitionId) theFromResource.getUserData(Constants.RESOURCE_PARTITION_ID);
RequestPartitionId toGoldenPartitionId = (RequestPartitionId) theToResource.getUserData(Constants.RESOURCE_PARTITION_ID);
if (fromGoldenResourcePartitionId != null && toGoldenPartitionId != null && fromGoldenResourcePartitionId.hasPartitionIds() && toGoldenPartitionId.hasPartitionIds() &&
!fromGoldenResourcePartitionId.hasPartitionId(toGoldenPartitionId.getFirstPartitionIdOrNull())) {
throw new InvalidRequestException(Msg.code(2075) + myMessageHelper.getMessageForMismatchPartition(theFromResource, theToResource));
}
}
}

View File

@ -78,7 +78,7 @@ public class MdmProviderCreateLinkR4Test extends BaseLinkR4Test {
assertLinkCount(1);
RequestPartitionId requestPartitionId1 = RequestPartitionId.fromPartitionId(1);
Patient patient = createPatientOnPartition(buildPatientWithNameAndId("PatientGiven", "ID.PatientGiven.123"), true, false, requestPartitionId1);
Patient patient = createPatientOnPartition(buildPatientWithNameAndId("PatientGiven", "ID.PatientGiven.123"), false, false, requestPartitionId1);
StringType patientId = new StringType(patient.getIdElement().getValue());
RequestPartitionId requestPartitionId2 = RequestPartitionId.fromPartitionId(2);

View File

@ -0,0 +1,99 @@
package ca.uhn.fhir.jpa.mdm.provider;
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
import ca.uhn.fhir.jpa.entity.MdmLink;
import ca.uhn.fhir.jpa.entity.PartitionEntity;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.mdm.api.IMdmLink;
import ca.uhn.fhir.mdm.api.IMdmSettings;
import ca.uhn.fhir.mdm.api.MdmConstants;
import ca.uhn.fhir.mdm.util.MdmResourceUtil;
import ca.uhn.fhir.mdm.util.MessageHelper;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.api.server.SystemRequestDetails;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.Extension;
import org.hl7.fhir.r4.model.Patient;
import org.hl7.fhir.r4.model.StringType;
import org.hl7.fhir.r4.model.codesystems.MatchGrade;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import java.io.IOException;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class MdmProviderCrossPartitionR4Test extends BaseProviderR4Test{
@Autowired
private IMdmSettings myMdmSettings;
private static final String PARTITION_GOLDEN_RESOURCE = "PARTITION-GOLDEN";
@BeforeEach
public void before() throws Exception {
super.before();
myPartitionSettings.setPartitioningEnabled(true);
myPartitionLookupSvc.createPartition(new PartitionEntity().setId(1).setName(PARTITION_1), null);
myPartitionLookupSvc.createPartition(new PartitionEntity().setId(2).setName(PARTITION_2), null);
myPartitionLookupSvc.createPartition(new PartitionEntity().setId(3).setName(PARTITION_GOLDEN_RESOURCE), null);
}
@Override
@AfterEach
public void after() throws IOException {
super.after();
myPartitionSettings.setPartitioningEnabled(false);
myMdmSettings.setSearchAllPartitionForMatch(false);
myMdmSettings.setGoldenResourcePartitionName("");
}
@Test
public void testCreateLinkWithMatchResultOnDifferentPartitions() {
myMdmSettings.setSearchAllPartitionForMatch(true);
createPatientOnPartition(buildJanePatient(), RequestPartitionId.fromPartitionId(1));
Bundle result = (Bundle) myMdmProvider.match(buildJanePatient(), new SystemRequestDetails().setRequestPartitionId(RequestPartitionId.fromPartitionId(2)));
assertEquals(1, result.getEntry().size());
}
@Test
public void testCreateLinkWithMatchResultOnDifferentPartitionsWithoutSearchAllPartition() {
myMdmSettings.setSearchAllPartitionForMatch(false);
createPatientOnPartition(buildJanePatient(), RequestPartitionId.fromPartitionId(1));
Bundle result = (Bundle) myMdmProvider.match(buildJanePatient(), new SystemRequestDetails().setRequestPartitionId(RequestPartitionId.fromPartitionId(2)));
assertEquals(0, result.getEntry().size());
}
@Test
public void testCreateLinkWithResourcesInSpecificPartition(){
myMdmSettings.setGoldenResourcePartitionName(PARTITION_GOLDEN_RESOURCE);
myMdmSettings.setSearchAllPartitionForMatch(true);
assertLinkCount(0);
Patient jane = createPatientOnPartition(buildJanePatient(), RequestPartitionId.fromPartitionId(1));
myMdmMatchLinkSvc.updateMdmLinksForMdmSource(jane, createContextForCreate("Patient"));
assertLinkCount(1);
RequestDetails requestDetails = new SystemRequestDetails();
requestDetails.setTenantId(PARTITION_GOLDEN_RESOURCE);
IBundleProvider searchResult = myPatientDao.search(new SearchParameterMap(), requestDetails);
assertEquals(searchResult.getAllResources().size(), 1);
assertTrue(MdmResourceUtil.isGoldenRecord(searchResult.getAllResources().get(0)));
}
}

View File

@ -4,6 +4,7 @@ import ca.uhn.fhir.interceptor.model.RequestPartitionId;
import ca.uhn.fhir.i18n.Msg;
import ca.uhn.fhir.jpa.entity.MdmLink;
import ca.uhn.fhir.jpa.entity.PartitionEntity;
import ca.uhn.fhir.mdm.api.IMdmSettings;
import ca.uhn.fhir.mdm.api.MdmConstants;
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
@ -12,9 +13,11 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
import org.hl7.fhir.r4.model.Patient;
import org.hl7.fhir.r4.model.StringType;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import java.io.IOException;
import java.util.List;
import static org.hamcrest.MatcherAssert.assertThat;
@ -31,6 +34,20 @@ public class MdmProviderUpdateLinkR4Test extends BaseLinkR4Test {
@Autowired
private MessageHelper myMessageHelper;
@Autowired
private IMdmSettings myMdmSettings;
@Override
@AfterEach
public void after() throws IOException {
super.after();
myPartitionSettings.setPartitioningEnabled(false);
myMdmSettings.setSearchAllPartitionForMatch(false);
myMdmSettings.setGoldenResourcePartitionName("");
}
@Test
public void testUpdateLinkNoMatch() {
assertLinkCount(1);
@ -88,7 +105,7 @@ public class MdmProviderUpdateLinkR4Test extends BaseLinkR4Test {
myPartitionLookupSvc.createPartition(new PartitionEntity().setId(2).setName(PARTITION_2), null);
RequestPartitionId requestPartitionId1 = RequestPartitionId.fromPartitionId(1);
RequestPartitionId requestPartitionId2 = RequestPartitionId.fromPartitionId(2);
Patient patient = createPatientOnPartition(buildFrankPatient(), true, false, requestPartitionId1);
Patient patient = createPatientOnPartition(buildFrankPatient(), false, false, requestPartitionId1);
StringType patientId = new StringType(patient.getIdElement().getValue());
Patient sourcePatient = createPatientOnPartition(buildJanePatient(), true, false, requestPartitionId2);

View File

@ -4,7 +4,7 @@ import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
import ca.uhn.fhir.jpa.entity.MdmLink;
import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc;
import ca.uhn.fhir.jpa.mdm.util.MdmPartitionHelper;
import ca.uhn.fhir.mdm.util.MdmPartitionHelper;
import ca.uhn.fhir.jpa.model.dao.JpaPid;
import ca.uhn.fhir.mdm.api.IMdmLink;
import ca.uhn.fhir.mdm.api.IMdmSettings;

View File

@ -0,0 +1,72 @@
package ca.uhn.fhir.jpa.mdm.svc.candidate;
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
import ca.uhn.fhir.jpa.entity.MdmLink;
import ca.uhn.fhir.jpa.entity.PartitionEntity;
import ca.uhn.fhir.jpa.mdm.BaseMdmR4Test;
import ca.uhn.fhir.mdm.api.IMdmSettings;
import org.hl7.fhir.r4.model.Patient;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
public class MdmPartitionedGoldenResourceFindingTest extends BaseMdmR4Test {
@Autowired
IMdmSettings myMdmSettings;
/**
* These test will do wacky stuff with partition, if you just want to write simple match test put and would
* like to not deal with that headache, please see MdmGoldenResourceFindingSvcTest
*/
@Test
public void testNoMatchOnResourcesInDifferentPartition(){
myMdmSettings.setSearchAllPartitionForMatch(false);
myPartitionSettings.setPartitioningEnabled(true);
myPartitionLookupSvc.createPartition(new PartitionEntity().setId(1).setName(PARTITION_1), null);
myPartitionLookupSvc.createPartition(new PartitionEntity().setId(2).setName(PARTITION_2), null);
Patient jane = createPatientAndUpdateLinksOnPartition(addExternalEID(buildJanePatient(), EID_1), RequestPartitionId.fromPartitionId(1));
Patient jane2 = createPatientAndUpdateLinksOnPartition(addExternalEID(buildJanePatient(), EID_1), RequestPartitionId.fromPartitionId(2));
// hack the link into a NO_MATCH
List<MdmLink> links = myMdmLinkDaoSvc.findMdmLinksBySourceResource(jane);
assertThat(links, hasSize(1));
Long janeOriginalGoldenResourceId = links.get(0).getGoldenResourcePersistenceId().getId();
List<MdmLink> links2 = myMdmLinkDaoSvc.findMdmLinksBySourceResource(jane2);
assertThat(links2, hasSize(1));
Long jane2GoldenResourceId = links2.get(0).getGoldenResourcePersistenceId().getId();
assertNotEquals(janeOriginalGoldenResourceId, jane2GoldenResourceId);
}
@Test
public void testMatchOnResourcesInDifferentPartitionIfSearchAllPartition(){
myMdmSettings.setSearchAllPartitionForMatch(true);
myPartitionSettings.setPartitioningEnabled(true);
myPartitionLookupSvc.createPartition(new PartitionEntity().setId(1).setName(PARTITION_1), null);
myPartitionLookupSvc.createPartition(new PartitionEntity().setId(2).setName(PARTITION_2), null);
Patient jane = createPatientAndUpdateLinksOnPartition(addExternalEID(buildJanePatient(), EID_1), RequestPartitionId.fromPartitionId(1));
Patient jane2 = createPatientAndUpdateLinksOnPartition(addExternalEID(buildJanePatient(), EID_1), RequestPartitionId.fromPartitionId(2));
// hack the link into a NO_MATCH
List<MdmLink> links = myMdmLinkDaoSvc.findMdmLinksBySourceResource(jane);
assertThat(links, hasSize(1));
Long janeOriginalGoldenResourceId = links.get(0).getGoldenResourcePersistenceId().getId();
List<MdmLink> links2 = myMdmLinkDaoSvc.findMdmLinksBySourceResource(jane2);
assertThat(links2, hasSize(1));
Long jane2GoldenResourceId = links2.get(0).getGoldenResourcePersistenceId().getId();
assertEquals(janeOriginalGoldenResourceId, jane2GoldenResourceId);
}
}

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -7,7 +7,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -54,4 +54,12 @@ public interface IMdmSettings {
}
int getCandidateSearchLimit();
String getGoldenResourcePartitionName();
void setGoldenResourcePartitionName(String theGoldenResourcePartitionName);
boolean getSearchAllPartitionForMatch();
void setSearchAllPartitionForMatch(boolean theSearchAllPartitionForMatch);
}

View File

@ -137,8 +137,13 @@ public class MdmControllerHelper {
* Helper method which will return a bundle of all Matches and Possible Matches.
*/
public IBaseBundle getMatchesAndPossibleMatchesForResource(IAnyResource theResource, String theResourceType, RequestDetails theRequestDetails) {
RequestPartitionId requestPartitionId;
ReadPartitionIdRequestDetails details = ReadPartitionIdRequestDetails.forSearchType(theResourceType, null, null);
RequestPartitionId requestPartitionId = myRequestPartitionHelperSvc.determineReadPartitionForRequest(theRequestDetails, details);
if (myMdmSettings.getSearchAllPartitionForMatch()){
requestPartitionId = RequestPartitionId.allPartitions();
} else {
requestPartitionId = myRequestPartitionHelperSvc.determineReadPartitionForRequest(theRequestDetails, details);
}
List<MatchedTarget> matches = myMdmMatchFinderSvc.getMatchedTargets(theResourceType, theResource, requestPartitionId);
matches.sort(Comparator.comparing((MatchedTarget m) -> m.getMatchResult().getNormalizedScore()).reversed());

View File

@ -19,10 +19,8 @@
*/
package ca.uhn.fhir.mdm.rules.config;
import ca.uhn.fhir.mdm.api.IMdmLink;
import ca.uhn.fhir.mdm.api.IMdmRuleValidator;
import ca.uhn.fhir.mdm.api.IMdmSettings;
import ca.uhn.fhir.mdm.dao.IMdmLinkImplFactory;
import ca.uhn.fhir.mdm.rules.json.MdmRulesJson;
import ca.uhn.fhir.util.JsonUtil;
import org.springframework.beans.factory.annotation.Autowired;
@ -41,6 +39,8 @@ public class MdmSettings implements IMdmSettings {
private String mySurvivorshipRules;
private MdmRulesJson myMdmRules;
private boolean myPreventEidUpdates;
private String myGoldenResourcePartitionName;
private boolean mySearchAllPartitionForMatch = false;
/**
* If disabled, the underlying MDM system will operate under the following assumptions:
@ -138,4 +138,24 @@ public class MdmSettings implements IMdmSettings {
public void setCandidateSearchLimit(int theCandidateSearchLimit) {
myCandidateSearchLimit = theCandidateSearchLimit;
}
@Override
public String getGoldenResourcePartitionName() {
return myGoldenResourcePartitionName;
}
@Override
public void setGoldenResourcePartitionName(String theGoldenResourcePartitionName) {
myGoldenResourcePartitionName = theGoldenResourcePartitionName;
}
@Override
public boolean getSearchAllPartitionForMatch() {
return mySearchAllPartitionForMatch;
}
@Override
public void setSearchAllPartitionForMatch(boolean theSearchAllPartitionForMatch) {
mySearchAllPartitionForMatch = theSearchAllPartitionForMatch;
}
}

View File

@ -64,6 +64,8 @@ public class GoldenResourceHelper {
private EIDHelper myEIDHelper;
@Autowired
private IMdmSurvivorshipService myMdmSurvivorshipService;
@Autowired
private MdmPartitionHelper myMdmPartitionHelper;
private final FhirContext myFhirContext;
@ -101,7 +103,7 @@ public class GoldenResourceHelper {
MdmResourceUtil.setGoldenResource(newGoldenResource);
// add the partition id to the new resource
newGoldenResource.setUserData(Constants.RESOURCE_PARTITION_ID, theIncomingResource.getUserData(Constants.RESOURCE_PARTITION_ID));
newGoldenResource.setUserData(Constants.RESOURCE_PARTITION_ID, myMdmPartitionHelper.getRequestPartitionIdForNewGoldenResources(theIncomingResource));
return (T) newGoldenResource;
}

View File

@ -0,0 +1,84 @@
/*-
* #%L
* HAPI FHIR - Master Data Management
* %%
* Copyright (C) 2014 - 2023 Smile CDR, Inc.
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
package ca.uhn.fhir.mdm.util;
import ca.uhn.fhir.i18n.Msg;
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
import ca.uhn.fhir.mdm.api.IMdmSettings;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.springframework.stereotype.Service;
@Service
public class MdmPartitionHelper {
private final MessageHelper myMessageHelper;
private final IMdmSettings myMdmSettings;
public MdmPartitionHelper(MessageHelper theMessageHelper, IMdmSettings theMdmSettings){
myMessageHelper = theMessageHelper;
myMdmSettings = theMdmSettings;
}
/**
* Checks the partition of the two resources are in compliance with the settings
* If the mdm settings states mdm resources that only matches against resources in the same partition, validate
* the resources have the same partition
* This is used to check in merging golden resources as well as when creating a link between source and golden resource
* @param theFromResource
* @param theToResource
*/
public void validateMdmResourcesPartitionMatches(IAnyResource theFromResource, IAnyResource theToResource){
if (!myMdmSettings.getSearchAllPartitionForMatch()){
RequestPartitionId fromGoldenResourcePartitionId = (RequestPartitionId) theFromResource.getUserData(Constants.RESOURCE_PARTITION_ID);
RequestPartitionId toGoldenPartitionId = (RequestPartitionId) theToResource.getUserData(Constants.RESOURCE_PARTITION_ID);
if (fromGoldenResourcePartitionId != null && toGoldenPartitionId != null && fromGoldenResourcePartitionId.hasPartitionIds() && toGoldenPartitionId.hasPartitionIds() &&
!fromGoldenResourcePartitionId.hasPartitionId(toGoldenPartitionId.getFirstPartitionIdOrNull())) {
throw new InvalidRequestException(Msg.code(2075) + myMessageHelper.getMessageForMismatchPartition(theFromResource, theToResource));
}
}
}
/**
* Generates the request partition id for a mdm candidate search for a given resource.
* If the system is configured to search across all partition for matches, this will return all partition
* and if not, this function will return the request partition id of the source resource
* @param theResource
* @return The RequestPartitionId that should be used for the candidate search for the given resource
*/
public RequestPartitionId getRequestPartitionIdFromResourceForSearch(IAnyResource theResource){
if (myMdmSettings.getSearchAllPartitionForMatch()){
return RequestPartitionId.allPartitions();
}
else {
return (RequestPartitionId) theResource.getUserData(Constants.RESOURCE_PARTITION_ID);
}
}
public RequestPartitionId getRequestPartitionIdForNewGoldenResources(IAnyResource theSourceResource){
if (StringUtils.isBlank(myMdmSettings.getGoldenResourcePartitionName())){
return (RequestPartitionId) theSourceResource.getUserData(Constants.RESOURCE_PARTITION_ID);
}
else {
return RequestPartitionId.fromPartitionName(myMdmSettings.getGoldenResourcePartitionName());
}
}
}

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -7,7 +7,7 @@
<parent>
<artifactId>hapi-fhir-serviceloaders</artifactId>
<groupId>ca.uhn.hapi.fhir</groupId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -7,7 +7,7 @@
<parent>
<artifactId>hapi-fhir-serviceloaders</artifactId>
<groupId>ca.uhn.hapi.fhir</groupId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
@ -21,7 +21,7 @@
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-caching-api</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
</dependency>
<dependency>

View File

@ -7,7 +7,7 @@
<parent>
<artifactId>hapi-fhir-serviceloaders</artifactId>
<groupId>ca.uhn.hapi.fhir</groupId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -7,7 +7,7 @@
<parent>
<artifactId>hapi-fhir</artifactId>
<groupId>ca.uhn.hapi.fhir</groupId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>hapi-deployable-pom</artifactId>
<groupId>ca.uhn.hapi.fhir</groupId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
</parent>
<artifactId>hapi-fhir-spring-boot-sample-client-apache</artifactId>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-spring-boot</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -7,7 +7,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -7,7 +7,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -7,7 +7,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -7,7 +7,7 @@
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<packaging>pom</packaging>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<name>HAPI-FHIR</name>
<description>An open-source implementation of the FHIR specification in Java.</description>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>6.5.14-SNAPSHOT</version>
<version>6.5.16-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>