diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/bulk/export/svc/JpaBulkExportProcessor.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/bulk/export/svc/JpaBulkExportProcessor.java index 79485f5d3d90..f92a04b6fbc5 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/bulk/export/svc/JpaBulkExportProcessor.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/bulk/export/svc/JpaBulkExportProcessor.java @@ -37,7 +37,7 @@ import ca.uhn.fhir.jpa.model.search.SearchBuilderLoadIncludesParameters; import ca.uhn.fhir.jpa.model.search.SearchRuntimeDetails; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; -import ca.uhn.fhir.mdm.svc.MdmExpandersHolder; +import ca.uhn.fhir.mdm.svc.IBulkExportMdmResourceExpander; import ca.uhn.fhir.model.api.Include; import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.rest.api.server.SystemRequestDetails; @@ -56,6 +56,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import java.io.IOException; import java.util.ArrayList; @@ -86,7 +87,7 @@ public class JpaBulkExportProcessor implements IBulkExportProcessor { private EntityManager myEntityManager; private IHapiTransactionService myHapiTransactionService; private ISearchParamRegistry mySearchParamRegistry; - private MdmExpandersHolder myMdmExpandersHolder; + private IBulkExportMdmResourceExpander myBulkExportMdmResourceExpander; @Autowired public JpaBulkExportProcessor( @@ -99,7 +100,8 @@ public JpaBulkExportProcessor( EntityManager theEntityManager, IHapiTransactionService theHapiTransactionService, ISearchParamRegistry theSearchParamRegistry, - MdmExpandersHolder theMdmExpandersHolder) { + @Qualifier("bulkExportMdmResourceExpander") + IBulkExportMdmResourceExpander theBulkExportMdmResourceExpander) { myContext = theContext; myBulkExportHelperSvc = theBulkExportHelperSvc; myStorageSettings = theStorageSettings; @@ -109,7 +111,7 @@ public JpaBulkExportProcessor( myEntityManager = theEntityManager; myHapiTransactionService = theHapiTransactionService; mySearchParamRegistry = theSearchParamRegistry; - myMdmExpandersHolder = theMdmExpandersHolder; + myBulkExportMdmResourceExpander = theBulkExportMdmResourceExpander; } @Override @@ -349,7 +351,7 @@ protected RuntimeSearchParam getPatientSearchParamForCurrentResourceType(String public void expandMdmResources(List theResources) { for (IBaseResource resource : theResources) { if (!PATIENT_BULK_EXPORT_FORWARD_REFERENCE_RESOURCE_TYPES.contains(resource.fhirType())) { - myMdmExpandersHolder.getBulkExportMDMResourceExpanderInstance().annotateResource(resource); + myBulkExportMdmResourceExpander.annotateResource(resource); } } } @@ -405,9 +407,8 @@ private LinkedHashSet getExpandedPatientList( if (theParameters.isExpandMdm()) { RequestPartitionId partitionId = theParameters.getPartitionIdOrAllPartitions(); - patientPidsToExport.addAll(myMdmExpandersHolder - .getBulkExportMDMResourceExpanderInstance() - .expandGroup(theParameters.getGroupId(), partitionId)); + patientPidsToExport.addAll( + myBulkExportMdmResourceExpander.expandGroup(theParameters.getGroupId(), partitionId)); } return patientPidsToExport; } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/JpaBulkExportConfig.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/JpaBulkExportConfig.java index f08fffc689b6..233f98f791be 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/JpaBulkExportConfig.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/JpaBulkExportConfig.java @@ -29,7 +29,7 @@ import ca.uhn.fhir.jpa.dao.SearchBuilderFactory; import ca.uhn.fhir.jpa.dao.tx.IHapiTransactionService; import ca.uhn.fhir.jpa.model.dao.JpaPid; -import ca.uhn.fhir.mdm.svc.MdmExpandersHolder; +import ca.uhn.fhir.mdm.svc.IBulkExportMdmResourceExpander; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry; import jakarta.persistence.EntityManager; import org.springframework.context.annotation.Bean; @@ -48,7 +48,7 @@ public IBulkExportProcessor jpaBulkExportProcessor( EntityManager theEntityManager, IHapiTransactionService theHapiTransactionService, ISearchParamRegistry theSearchParamRegistry, - MdmExpandersHolder theMdmExpandersHolder) { + IBulkExportMdmResourceExpander theBulkExportMdmResourceExpander) { return new JpaBulkExportProcessor( theFhirContext, theBulkExportHelperService, @@ -59,7 +59,7 @@ public IBulkExportProcessor jpaBulkExportProcessor( theEntityManager, theHapiTransactionService, theSearchParamRegistry, - theMdmExpandersHolder); + theBulkExportMdmResourceExpander); } @Bean diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/MdmJpaConfig.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/MdmJpaConfig.java index acf2b94bff19..77f5bbf89219 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/MdmJpaConfig.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/MdmJpaConfig.java @@ -30,15 +30,18 @@ import ca.uhn.fhir.jpa.entity.MdmLink; import ca.uhn.fhir.jpa.model.dao.JpaPid; import ca.uhn.fhir.mdm.api.IMdmLinkExpandSvc; +import ca.uhn.fhir.mdm.api.IMdmSettings; +import ca.uhn.fhir.mdm.api.MdmModeEnum; import ca.uhn.fhir.mdm.dao.IMdmLinkDao; import ca.uhn.fhir.mdm.dao.IMdmLinkImplFactory; import ca.uhn.fhir.mdm.svc.BulkExportMdmEidMatchOnlyResourceExpander; import ca.uhn.fhir.mdm.svc.BulkExportMdmResourceExpander; +import ca.uhn.fhir.mdm.svc.IBulkExportMdmResourceExpander; import ca.uhn.fhir.mdm.svc.MdmEidMatchOnlyExpandSvc; -import ca.uhn.fhir.mdm.svc.MdmExpandersHolder; import ca.uhn.fhir.mdm.svc.MdmExpansionCacheSvc; import ca.uhn.fhir.mdm.svc.MdmLinkExpandSvc; import ca.uhn.fhir.mdm.svc.MdmSearchExpansionSvc; +import ca.uhn.fhir.mdm.util.EIDHelper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; @@ -47,29 +50,45 @@ public class MdmJpaConfig { @Bean - public MdmExpandersHolder mdmLinkExpandSvcHolder( - FhirContext theFhirContext, - IMdmLinkExpandSvc theMdmLinkExpandSvc, - MdmEidMatchOnlyExpandSvc theMdmEidMatchOnlyLinkExpandSvc, - BulkExportMdmEidMatchOnlyResourceExpander theBulkExportMdmEidMatchOnlyResourceExpander, - BulkExportMdmResourceExpander theBulkExportMdmResourceExpander) { - return new MdmExpandersHolder( - theFhirContext, - theMdmLinkExpandSvc, - theMdmEidMatchOnlyLinkExpandSvc, - theBulkExportMdmResourceExpander, - theBulkExportMdmEidMatchOnlyResourceExpander); + public MdmEidMatchOnlyExpandSvc mdmEidMatchOnlyLinkExpandSvc( + IMdmSettings theMdmSettings, DaoRegistry theDaoRegistry, FhirContext theFhirContext) { + MdmEidMatchOnlyExpandSvc mdmEidMatchOnlyExpandSvc = new MdmEidMatchOnlyExpandSvc(theDaoRegistry); + mdmEidMatchOnlyExpandSvc.setMyEidHelper(new EIDHelper(theFhirContext, theMdmSettings)); + return mdmEidMatchOnlyExpandSvc; } @Bean - public MdmEidMatchOnlyExpandSvc mdmEidMatchOnlyLinkExpandSvc(DaoRegistry theDaoRegistry) { - return new MdmEidMatchOnlyExpandSvc(theDaoRegistry); + @Primary + public IMdmLinkExpandSvc mdmLinkExpandSvc( + IMdmSettings theMdmSettings, DaoRegistry theDaoRegistry, FhirContext theFhirContext) { + IMdmLinkExpandSvc res; + if (isEidMatchOnly(theMdmSettings)) { + res = mdmEidMatchOnlyLinkExpandSvc(theMdmSettings, theDaoRegistry, theFhirContext); + } else { + res = new MdmLinkExpandSvc(); + } + return res; } @Bean - @Primary - public IMdmLinkExpandSvc mdmLinkExpandSvc() { - return new MdmLinkExpandSvc(); + public IBulkExportMdmResourceExpander bulkExportMdmResourceExpander( + MdmExpansionCacheSvc theMdmExpansionCacheSvc, + IMdmLinkDao theMdmLinkDao, + IIdHelperService theIdHelperService, + DaoRegistry theDaoRegistry, + FhirContext theFhirContext, + MdmEidMatchOnlyExpandSvc theMdmEidMatchOnlyLinkExpandSvc, + IMdmSettings theMdmSettings) { + + IBulkExportMdmResourceExpander res; + if (isEidMatchOnly(theMdmSettings)) { + res = new BulkExportMdmEidMatchOnlyResourceExpander( + theDaoRegistry, theMdmEidMatchOnlyLinkExpandSvc, theFhirContext, theIdHelperService); + } else { + res = new BulkExportMdmResourceExpander( + theMdmExpansionCacheSvc, theMdmLinkDao, theIdHelperService, theDaoRegistry, theFhirContext); + } + return res; } @Bean @@ -82,27 +101,6 @@ public IMdmLinkDao mdmLinkDao() { return new MdmLinkDaoJpaImpl(); } - @Bean - public BulkExportMdmResourceExpander bulkExportMDMResourceExpander( - MdmExpansionCacheSvc theMdmExpansionCacheSvc, - IMdmLinkDao theMdmLinkDao, - IIdHelperService theIdHelperService, - DaoRegistry theDaoRegistry, - FhirContext theFhirContext) { - return new BulkExportMdmResourceExpander( - theMdmExpansionCacheSvc, theMdmLinkDao, theIdHelperService, theDaoRegistry, theFhirContext); - } - - @Bean - public BulkExportMdmEidMatchOnlyResourceExpander bulkExportMDMEidMatchOnlyResourceExpander( - DaoRegistry theDaoRegistry, - MdmEidMatchOnlyExpandSvc theMdmEidMatchOnlyLinkExpandSvc, - FhirContext theFhirContext, - IIdHelperService theIdHelperService) { - return new BulkExportMdmEidMatchOnlyResourceExpander( - theDaoRegistry, theMdmEidMatchOnlyLinkExpandSvc, theFhirContext, theIdHelperService); - } - @Bean public IMdmLinkImplFactory mdmLinkImplFactory() { return new JpaMdmLinkImplFactory(); @@ -112,4 +110,11 @@ public IMdmLinkImplFactory mdmLinkImplFactory() { public IMdmClearHelperSvc helperSvc(IDeleteExpungeSvc theDeleteExpungeSvc) { return new MdmClearHelperSvcImpl(theDeleteExpungeSvc); } + + private boolean isEidMatchOnly(IMdmSettings theMdmSettings) { + return theMdmSettings.getMode() == MdmModeEnum.MATCH_ONLY + && theMdmSettings.getMdmRules() != null + && theMdmSettings.getMdmRules().getEnterpriseEIDSystems() != null + && !theMdmSettings.getMdmRules().getEnterpriseEIDSystems().isEmpty(); + } } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/bulk/export/svc/JpaBulkExportProcessorTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/bulk/export/svc/JpaBulkExportProcessorTest.java index 3a1adefeffc1..67c697ebcea9 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/bulk/export/svc/JpaBulkExportProcessorTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/bulk/export/svc/JpaBulkExportProcessorTest.java @@ -19,7 +19,6 @@ import ca.uhn.fhir.jpa.model.search.SearchBuilderLoadIncludesParameters; import ca.uhn.fhir.jpa.model.search.SearchRuntimeDetails; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; -import ca.uhn.fhir.mdm.svc.MdmExpandersHolder; import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum; import ca.uhn.fhir.rest.api.server.RequestDetails; @@ -130,9 +129,6 @@ public JpaPid next() { @Mock private IIdHelperService myIdHelperService; - @Mock - private MdmExpandersHolder myMdmExpandersHolder; - @Mock private IBulkExportMdmResourceExpander myBulkExportMDMResourceExpander; @@ -298,8 +294,6 @@ public void getResourcePidIterator_groupExportStyleWithPatientResource_returnsIt // mdm expansion stuff final JpaPid mdmExpandedPatientId = JpaPid.fromId(4567L); if (theMdm) { - - when(myMdmExpandersHolder.getBulkExportMDMResourceExpanderInstance()).thenReturn(myBulkExportMDMResourceExpander); // mock the call to expandGroup method of the expander when(myBulkExportMDMResourceExpander.expandGroup(parameters.getGroupId(), getPartitionIdFromParams(thePartitioned))) .thenReturn(Set.of(mdmExpandedPatientId)); @@ -395,7 +389,6 @@ public void getResourcePidIterator_groupExportStyleWithNonPatientResource_return .thenReturn(observationResultsIterator); if (theMdm) { - when(myMdmExpandersHolder.getBulkExportMDMResourceExpanderInstance()).thenReturn(myBulkExportMDMResourceExpander); // mock the call to expandGroup method of the expander when(myBulkExportMDMResourceExpander.expandGroup(parameters.getGroupId(), getPartitionIdFromParams(thePartitioned))) .thenReturn(Collections.emptySet()); diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/helper/MdmHelperConfig.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/helper/MdmHelperConfig.java index 42feead36fc1..1fa1edafa701 100644 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/helper/MdmHelperConfig.java +++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/helper/MdmHelperConfig.java @@ -1,8 +1,12 @@ package ca.uhn.fhir.jpa.mdm.helper; +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.jpa.api.dao.DaoRegistry; +import ca.uhn.fhir.mdm.api.IMdmLinkExpandSvc; import ca.uhn.fhir.mdm.api.IMdmSettings; import ca.uhn.fhir.mdm.rules.config.MdmRuleValidator; import ca.uhn.fhir.mdm.rules.config.MdmSettings; +import ca.uhn.fhir.mdm.svc.MdmLinkExpandSvc; import com.google.common.base.Charsets; import org.apache.commons.io.IOUtils; import org.springframework.beans.factory.annotation.Value; @@ -39,4 +43,10 @@ IMdmSettings mdmSettings(MdmRuleValidator theMdmRuleValidator) throws IOExceptio .setPreventEidUpdates(myPreventEidUpdates) .setPreventMultipleEids(myPreventMultipleEids); } + + @Bean + @Primary + public IMdmLinkExpandSvc mdmLinkExpandSvc() { + return new MdmLinkExpandSvc(); + } } diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmReadVirtualizationInterceptorTest.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmReadVirtualizationInterceptorTest.java index 001b4b57b501..52cdab3657e0 100644 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmReadVirtualizationInterceptorTest.java +++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmReadVirtualizationInterceptorTest.java @@ -9,9 +9,7 @@ import ca.uhn.fhir.jpa.mdm.helper.testmodels.MDMState; import ca.uhn.fhir.jpa.model.dao.JpaPid; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; -import ca.uhn.fhir.mdm.api.IMdmSettings; import ca.uhn.fhir.mdm.interceptor.MdmReadVirtualizationInterceptor; -import ca.uhn.fhir.mdm.svc.MdmExpandersHolder; import ca.uhn.fhir.rest.api.RestOperationTypeEnum; import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.api.server.SystemRequestDetails; @@ -129,7 +127,7 @@ public void testRead_ObservationReferencingSourcePatient(boolean theUseClientAss Observation obs = myObservationDao.read(myObservationReferencingSourcePatientA0Id, mySrd); // Verify - assertEquals(mySourcePatientA0Id.getValue(), obs.getSubject().getReference()); + assertEquals(myGoldenResourcePatientAId.getValue(), obs.getSubject().getReference()); } /** diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/bulk/BulkExportUseCaseTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/bulk/BulkExportUseCaseTest.java index 986796df5535..b0ec3f1e4eec 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/bulk/BulkExportUseCaseTest.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/bulk/BulkExportUseCaseTest.java @@ -24,7 +24,6 @@ import ca.uhn.fhir.mdm.rules.config.MdmRuleValidator; import ca.uhn.fhir.mdm.rules.config.MdmSettings; import ca.uhn.fhir.mdm.rules.json.MdmRulesJson; -import ca.uhn.fhir.mdm.svc.MdmExpandersHolder; import ca.uhn.fhir.parser.IParser; import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.MethodOutcome; @@ -75,6 +74,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; import java.io.IOException; import java.util.ArrayList; @@ -102,11 +102,11 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; - +@ContextConfiguration(classes = {BulkExportUseCaseTestConfig.class}) public class BulkExportUseCaseTest extends BaseResourceProviderR4Test { private static final Logger ourLog = LoggerFactory.getLogger(BulkExportUseCaseTest.class); - private static final String TEST_PATIENT_EID_SYS = "http://patient-eid-sys"; + static final String TEST_PATIENT_EID_SYS = "http://patient-eid-sys"; @Autowired private IJobCoordinator myJobCoordinator; @@ -120,10 +120,7 @@ public class BulkExportUseCaseTest extends BaseResourceProviderR4Test { private IBatch2WorkChunkRepository myWorkChunkRepository; @Autowired private IInterceptorService myInterceptorService; - @Autowired - private MdmRuleValidator myMdmRulesValidator; - @Autowired - private MdmExpandersHolder myMdmExpandersHolder; + @BeforeEach public void beforeEach() { @@ -685,12 +682,6 @@ public void testExportEmptyResult() { @Nested public class GroupBulkExportTests { - - @AfterEach - void tearDown() { - restoreMdmSettingsToDefault(); - } - @Test public void testGroupExportSuccessfulyExportsPatientForwardReferences() { BundleBuilder bb = new BundleBuilder(myFhirContext); @@ -1865,8 +1856,6 @@ private IIdType createPatient() { @Test void testGroupExportWithMdmEnabled_EidMatchOnly() { - - createAndSetMdmSettingsForEidMatchOnly(); BundleBuilder bb = new BundleBuilder(myFhirContext); //In this test, we create two patients with the same Eid value for the eid system specified in mdm rules @@ -1918,23 +1907,6 @@ void testGroupExportWithMdmEnabled_EidMatchOnly() { } - - private void createAndSetMdmSettingsForEidMatchOnly() { - MdmSettings mdmSettings = new MdmSettings(myMdmRulesValidator); - mdmSettings.setEnabled(true); - mdmSettings.setMdmMode(MdmModeEnum.MATCH_ONLY); - MdmRulesJson rules = new MdmRulesJson(); - rules.setMdmTypes(List.of("Patient")); - rules.addEnterpriseEIDSystem("Patient", TEST_PATIENT_EID_SYS); - mdmSettings.setMdmRules(rules); - - myMdmExpandersHolder.setMdmSettings(mdmSettings); - } - - private void restoreMdmSettingsToDefault() { - myMdmExpandersHolder.setMdmSettings(new MdmSettings(myMdmRulesValidator)); - } - private static void assertResourcesIds(List theResources, String... theExpectedResourceIds) { assertThat(theResources).hasSize(theExpectedResourceIds.length); assertThat(theResources) diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/bulk/BulkExportUseCaseTestConfig.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/bulk/BulkExportUseCaseTestConfig.java new file mode 100644 index 000000000000..0712759c52f8 --- /dev/null +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/bulk/BulkExportUseCaseTestConfig.java @@ -0,0 +1,39 @@ +package ca.uhn.fhir.jpa.bulk; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.mdm.api.IMdmRuleValidator; +import ca.uhn.fhir.mdm.api.IMdmSettings; +import ca.uhn.fhir.mdm.api.MdmModeEnum; +import ca.uhn.fhir.mdm.rules.config.MdmRuleValidator; +import ca.uhn.fhir.mdm.rules.config.MdmSettings; +import ca.uhn.fhir.mdm.rules.json.MdmRulesJson; +import ca.uhn.fhir.rest.server.util.ISearchParamRegistry; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; + +import java.util.List; + +import static ca.uhn.fhir.jpa.bulk.BulkExportUseCaseTest.TEST_PATIENT_EID_SYS; + +public class BulkExportUseCaseTestConfig { + + @Autowired + private IMdmRuleValidator myMdmRulesValidator; + + @Bean + public IMdmSettings mdmSettings() { + MdmSettings mdmSettings = new MdmSettings(myMdmRulesValidator); + mdmSettings.setEnabled(true); + mdmSettings.setMdmMode(MdmModeEnum.MATCH_ONLY); + MdmRulesJson rules = new MdmRulesJson(); + rules.setMdmTypes(List.of("Patient")); + rules.addEnterpriseEIDSystem("Patient", TEST_PATIENT_EID_SYS); + mdmSettings.setMdmRules(rules); + return mdmSettings; + } + + @Bean + public IMdmRuleValidator mdmRuleValidator(FhirContext theFhirContext, ISearchParamRegistry theSearchParamRetriever) { + return new MdmRuleValidator(theFhirContext, theSearchParamRetriever); + } +} diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmLinkExpandSvc.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmLinkExpandSvc.java index bd52509dc8f3..963c5599f69f 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmLinkExpandSvc.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmLinkExpandSvc.java @@ -24,6 +24,8 @@ import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IIdType; +import java.util.List; +import java.util.Map; import java.util.Set; public interface IMdmLinkExpandSvc { @@ -41,4 +43,6 @@ Set expandMdmByGoldenResourcePid( RequestPartitionId theRequestPartitionId, IResourcePersistentId theGoldenResourcePid); Set expandMdmByGoldenResourceId(RequestPartitionId theRequestPartitionId, IIdType theId); + + Map getGoldenResourceIdsFromIds(List ids); } diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/interceptor/MdmReadVirtualizationInterceptor.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/interceptor/MdmReadVirtualizationInterceptor.java index b082b4363924..595df9ff2b69 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/interceptor/MdmReadVirtualizationInterceptor.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/interceptor/MdmReadVirtualizationInterceptor.java @@ -25,6 +25,7 @@ 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.IMdmLinkExpandSvc; import ca.uhn.fhir.mdm.api.MdmConstants; import ca.uhn.fhir.mdm.log.Logs; import ca.uhn.fhir.mdm.svc.MdmSearchExpansionResults; @@ -41,8 +42,10 @@ import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -88,6 +91,9 @@ public class MdmReadVirtualizationInterceptor

@Autowired private MdmSearchExpansionSvc myMdmSearchExpansionSvc; + @Autowired + private IMdmLinkExpandSvc mdmLinkExpandSvc; + @Hook( value = Pointcut.STORAGE_PRESEARCH_REGISTERED, order = MdmConstants.ORDER_PRESEARCH_REGISTERED_MDM_READ_VIRTUALIZATION_INTERCEPTOR) @@ -125,10 +131,12 @@ public void preSearchRegistered( @Hook(Pointcut.STORAGE_PRESHOW_RESOURCES) public void preShowResources(RequestDetails theRequestDetails, IPreResourceShowDetails theDetails) { MdmSearchExpansionResults expansionResults = MdmSearchExpansionSvc.getCachedExpansionResults(theRequestDetails); - if (expansionResults == null) { - // This means the PRESEARCH hook didn't save anything, which probably means - // no RequestDetails is available - return; + boolean isExpansionResults = expansionResults != null && !expansionResults.isEmpty(); + if (!isExpansionResults) { + ourMdmTroubleshootingLog + .atDebug() + .setMessage("No expansion results found.") + .log(); } if (theRequestDetails.getUserData().get(CURRENTLY_PROCESSING_FLAG) != null) { @@ -141,26 +149,29 @@ public void preShowResources(RequestDetails theRequestDetails, IPreResourceShowD * we'll replace that resource with the originally requested resource, * making sure to avoid adding duplicates to the results. */ - Set resourcesInBundle = new HashSet<>(); - for (int resourceIdx = 0; resourceIdx < theDetails.size(); resourceIdx++) { - IBaseResource resource = theDetails.getResource(resourceIdx); - IIdType id = resource.getIdElement().toUnqualifiedVersionless(); - Optional originalIdOpt = expansionResults.getOriginalIdForExpandedId(id); - if (originalIdOpt.isPresent()) { - IIdType originalId = originalIdOpt.get(); - if (resourcesInBundle.add(originalId)) { - IBaseResource originalResource = fetchResourceFromRepository(theRequestDetails, originalId); - theDetails.setResource(resourceIdx, originalResource); + if (isExpansionResults) { + Set resourcesInBundle = new HashSet<>(); + for (int resourceIdx = 0; resourceIdx < theDetails.size(); resourceIdx++) { + IBaseResource resource = theDetails.getResource(resourceIdx); + IIdType id = resource.getIdElement().toUnqualifiedVersionless(); + Optional originalIdOpt = expansionResults.getOriginalIdForExpandedId(id); + if (originalIdOpt.isPresent()) { + IIdType originalId = originalIdOpt.get(); + if (resourcesInBundle.add(originalId)) { + IBaseResource originalResource = fetchResourceFromRepository(theRequestDetails, originalId); + theDetails.setResource(resourceIdx, originalResource); + } else { + theDetails.setResource(resourceIdx, null); + } } else { - theDetails.setResource(resourceIdx, null); - } - } else { - if (!resourcesInBundle.add(id)) { - theDetails.setResource(resourceIdx, null); + if (!resourcesInBundle.add(id)) { + theDetails.setResource(resourceIdx, null); + } } } } + HashMap refIdToRefInfoMap = new HashMap<>(); FhirTerser terser = myFhirContext.newTerser(); for (int resourceIdx = 0; resourceIdx < theDetails.size(); resourceIdx++) { IBaseResource resource = theDetails.getResource(resourceIdx); @@ -178,7 +189,10 @@ public void preShowResources(RequestDetails theRequestDetails, IPreResourceShowD && referenceId.hasIdPart() && !referenceId.isLocal() && !referenceId.isUuid()) { - Optional nonExpandedId = expansionResults.getOriginalIdForExpandedId(referenceId); + + Optional nonExpandedId = isExpansionResults + ? expansionResults.getOriginalIdForExpandedId(referenceId) + : Optional.empty(); if (nonExpandedId != null && nonExpandedId.isPresent()) { ourMdmTroubleshootingLog.debug( "MDM virtualization is replacing reference at {} value {} with {}", @@ -188,9 +202,18 @@ public void preShowResources(RequestDetails theRequestDetails, IPreResourceShowD referenceInfo .getResourceReference() .setReference(nonExpandedId.get().getValue()); + } else if (!isExpansionResults) { + // If there are no expansion results, this means that the search parameters didn't include + // anything that needed mdm expanding. According to the documentation + // (https://smilecdr.com/docs/mdm/mdm_virtualized_endpoint.html), references will still need + // to point to the golden record. We save those here to be processed later. + refIdToRefInfoMap.put(referenceId, referenceInfo); } } } + if (!refIdToRefInfoMap.isEmpty()) { + mapReferencesToGoldenResources(refIdToRefInfoMap); + } } } @@ -204,6 +227,15 @@ public void preShowResources(RequestDetails theRequestDetails, IPreResourceShowD .log(); } + private void mapReferencesToGoldenResources(HashMap refIdToRefInfoMap) { + List targetIds = refIdToRefInfoMap.keySet().stream().toList(); + Map goldenIdMap = mdmLinkExpandSvc.getGoldenResourceIdsFromIds(targetIds); + for (IIdType targetId : targetIds) { + if (goldenIdMap.containsKey(targetId)) + refIdToRefInfoMap.get(targetId).getResourceReference().setReference(goldenIdMap.get(targetId)); + } + } + private IBaseResource fetchResourceFromRepository(RequestDetails theRequestDetails, IIdType originalId) { IFhirResourceDao dao = myDaoRegistry.getResourceDao(originalId.getResourceType()); theRequestDetails.getUserData().put(CURRENTLY_PROCESSING_FLAG, Boolean.TRUE); diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/svc/MdmEidMatchOnlyExpandSvc.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/svc/MdmEidMatchOnlyExpandSvc.java index 3422455e9fde..d44df300e3fa 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/svc/MdmEidMatchOnlyExpandSvc.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/svc/MdmEidMatchOnlyExpandSvc.java @@ -100,7 +100,7 @@ public Set expandMdmBySourceResourcePid( public Set expandMdmByGoldenResourceId( RequestPartitionId theRequestPartitionId, IResourcePersistentId theGoldenResourcePid) { // This operation is not applicable when using MDM in MATCH_ONLY mode, - // return an emtpy set to rather than an exception to not affect existing code + // return an empty set to rather than an exception to not affect existing code return Collections.emptySet(); } @@ -108,14 +108,21 @@ public Set expandMdmByGoldenResourceId( public Set expandMdmByGoldenResourcePid( RequestPartitionId theRequestPartitionId, IResourcePersistentId theGoldenResourcePid) { // This operation is not applicable when using MDM in MATCH_ONLY mode, - // return an emtpy set to rather than an exception to not affect existing code + // return an empty set to rather than an exception to not affect existing code return Collections.emptySet(); } @Override public Set expandMdmByGoldenResourceId(RequestPartitionId theRequestPartitionId, IIdType theId) { // This operation is not applicable when using MDM in MATCH_ONLY mode, - // return an emtpy set to rather than an exception to not affect existing code + // return an empty set to rather than an exception to not affect existing code return Collections.emptySet(); } + + @Override + public Map getGoldenResourceIdsFromIds(List ids) { + // This operation is not applicable when using MDM in MATCH_ONLY mode, + // return an empty set to rather than an exception to not affect existing code + return Collections.emptyMap(); + } } diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/svc/MdmExpandersHolder.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/svc/MdmExpandersHolder.java deleted file mode 100644 index f3c423d09abf..000000000000 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/svc/MdmExpandersHolder.java +++ /dev/null @@ -1,181 +0,0 @@ -/*- - * #%L - * HAPI FHIR - Master Data Management - * %% - * Copyright (C) 2014 - 2025 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.svc; - -import ca.uhn.fhir.context.FhirContext; -import ca.uhn.fhir.mdm.api.IMdmLinkExpandSvc; -import ca.uhn.fhir.mdm.api.IMdmSettings; -import ca.uhn.fhir.mdm.api.MdmModeEnum; -import ca.uhn.fhir.mdm.util.EIDHelper; - -/** - * Holder class that manages two different MDM expansion implementation approaches based on MdmSettings. - *

- * This class addresses the dependency injection challenge where MdmSettings may not be available when these - * service objects are created. It holds references to both implementation approaches and determines which ones - * to use based on the MdmSettings. setMdmSettings method should be called when MdmSettings is constructed or updated - * for proper functioning. - *

- * The two implementation approaches are: - *

- * 1. Eid Match-Only Mode: A simplified approach where resources are matched based solely on - * Enterprise ID (EID) values without creating golden resources or MDM links. This mode is activated when - * MdmSettings specify MATCH_ONLY mode and EID systems are defined. - *

- * 2. Full MDM Mode: The complete MDM solution that creates golden resources and manages - * MDM links between resources. - *

- * Each approach has two service implementations, one for mdm expansion for searches and the other for mdm expansion for group bulk export: - *

- * Eid Match-Only Mode implementations: - * - MdmEidMatchOnlyLinkExpandSvc - * - BulkExportMdmEidMatchOnlyResourceExpander - *

- * Full MDM Mode implementations: - * - MdmLinkExpandSvc - * - BulkExportMdmResourceExpander - *

- * - * This class holds references to these service objects rather than creating them by itself, because some of these service objects have Spring annotations - * like @Transactional, for those annotations to work the objects need to be created by Spring itself. - */ -public class MdmExpandersHolder { - - /** MDM configuration settings used to determine which implementation to use */ - private IMdmSettings myMdmSettings; - - /** Cached instance of the selected link expand service */ - private IMdmLinkExpandSvc myLinkExpandSvcInstanceToUse; - - /** Cached instance of the selected bulk export resource expander */ - private IBulkExportMdmResourceExpander myBulkExportMDMResourceExpanderInstanceToUse; - - /** Full MDM link expand service implementation - * We have to use the interface as the type here instead of concrete implementing class MdmLinkExpandSvc - * because the class has Spring annotations like @Transactional which rely on a Proxy interface implementation and doesn't work if concrete classes are used as beans. */ - private final IMdmLinkExpandSvc myMdmLinkExpandSvc; - - /** EID-only match expand service implementation */ - private final MdmEidMatchOnlyExpandSvc myMdmEidMatchOnlyExpandSvc; - - /** Full MDM bulk export resource expander implementation */ - private final BulkExportMdmResourceExpander myBulkExportMDMResourceExpander; - - /** EID-only match bulk export resource expander implementation */ - private final BulkExportMdmEidMatchOnlyResourceExpander myBulkExportMDMEidMatchOnlyResourceExpander; - - private final FhirContext myFhirContext; - - public MdmExpandersHolder( - FhirContext theFhirContext, - IMdmLinkExpandSvc theMdmLinkExpandSvc, - MdmEidMatchOnlyExpandSvc theMdmEidMatchOnlyLinkExpandSvc, - BulkExportMdmResourceExpander theBulkExportMDMResourceExpander, - BulkExportMdmEidMatchOnlyResourceExpander theBulkExportMDMEidMatchOnlyResourceExpander) { - - myFhirContext = theFhirContext; - myMdmLinkExpandSvc = theMdmLinkExpandSvc; - myMdmEidMatchOnlyExpandSvc = theMdmEidMatchOnlyLinkExpandSvc; - myBulkExportMDMResourceExpander = theBulkExportMDMResourceExpander; - myBulkExportMDMEidMatchOnlyResourceExpander = theBulkExportMDMEidMatchOnlyResourceExpander; - } - - /** - * Returns the appropriate expand service instance appropriate for the mdm settings - */ - public IMdmLinkExpandSvc getLinkExpandSvcInstance() { - if (myLinkExpandSvcInstanceToUse != null) { - // we already determined instance to use, just return it - return myLinkExpandSvcInstanceToUse; - } - - myLinkExpandSvcInstanceToUse = determineExpandSvsInstanceToUse(); - - return myLinkExpandSvcInstanceToUse; - } - - /** - * Returns the appropriate bulk export resource expander instance appropriate for the mdm settings - */ - public IBulkExportMdmResourceExpander getBulkExportMDMResourceExpanderInstance() { - if (myBulkExportMDMResourceExpanderInstanceToUse != null) { - // we already determined instance to use, just return it - return myBulkExportMDMResourceExpanderInstanceToUse; - } - - myBulkExportMDMResourceExpanderInstanceToUse = determineBulkExportMDMResourceExpanderInstanceToUse(); - - return myBulkExportMDMResourceExpanderInstanceToUse; - } - - /** - * Determines which bulk export resource expander to use based on MDM mode and EID configuration. - */ - public IBulkExportMdmResourceExpander determineBulkExportMDMResourceExpanderInstanceToUse() { - if (isMatchOnlyWithEidSystems()) { - return myBulkExportMDMEidMatchOnlyResourceExpander; - } else { - return myBulkExportMDMResourceExpander; - } - } - - /** - * Determines if MDM is configured in MATCH_ONLY mode and EID systems are defined in the MDM rules. - */ - private boolean isMatchOnlyWithEidSystems() { - - if (myMdmSettings == null) { - // if mdmSettings is not set yet, assume we are using the full mdm mode - // to not break existing code, because previously we were just using the - // full mdm implementation without checking the mdm settings. - // This would be called again when mdmSettings setter is called - return false; - } - boolean isMatchOnly = myMdmSettings.getMode() == MdmModeEnum.MATCH_ONLY; - boolean hasEidSystems = false; - if (myMdmSettings.getMdmRules() != null) { - hasEidSystems = myMdmSettings.getMdmRules().getEnterpriseEIDSystems() != null - && !myMdmSettings.getMdmRules().getEnterpriseEIDSystems().isEmpty(); - } - return isMatchOnly && hasEidSystems; - } - - /** - * Determines which expand service to use and configures it if necessary. - */ - private IMdmLinkExpandSvc determineExpandSvsInstanceToUse() { - if (isMatchOnlyWithEidSystems()) { - myMdmEidMatchOnlyExpandSvc.setMyEidHelper(new EIDHelper(myFhirContext, myMdmSettings)); - return myMdmEidMatchOnlyExpandSvc; - } else { - return myMdmLinkExpandSvc; - } - } - - /** - * Sets the MDM settings and immediately determines which service implementations to use. - * This method is called after MDM settings become available during application startup. - */ - public void setMdmSettings(IMdmSettings theMdmSettings) { - myMdmSettings = theMdmSettings; - myLinkExpandSvcInstanceToUse = determineExpandSvsInstanceToUse(); - myBulkExportMDMResourceExpanderInstanceToUse = determineBulkExportMDMResourceExpanderInstanceToUse(); - } -} diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/svc/MdmLinkExpandSvc.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/svc/MdmLinkExpandSvc.java index 82fb144b9282..c62453ecff0d 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/svc/MdmLinkExpandSvc.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/svc/MdmLinkExpandSvc.java @@ -20,6 +20,7 @@ package ca.uhn.fhir.mdm.svc; import ca.uhn.fhir.interceptor.model.RequestPartitionId; +import ca.uhn.fhir.jpa.api.model.PersistentIdToForcedIdMap; import ca.uhn.fhir.jpa.api.svc.IIdHelperService; import ca.uhn.fhir.mdm.api.IMdmLinkExpandSvc; import ca.uhn.fhir.mdm.api.MdmMatchResultEnum; @@ -37,7 +38,9 @@ import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.stream.Collectors; @@ -143,6 +146,58 @@ public Set expandMdmByGoldenResourceId(RequestPartitionId theRequestPart return expandMdmByGoldenResourcePid(theRequestPartitionId, pidOrThrowException); } + /*** + * Return an id->golden-record-id map, for those ids that do have one. + * @param ids + * @return + */ + public Map getGoldenResourceIdsFromIds(List ids) { + // --------------------------------------------------------------------------------------------- + // Goal: Create a IIDType to golden record ID for those ids that do have one. + // Steps: + // 1.- Go from IIDTypes to source pid for each one of the specified ids + // 2.- Find the golden record pids for those source pids that do have one (not all of them will) + // 3.- Find the typed resource IDs for the golden record pids found in step 2 + // 4.- Create and return a map of the original ids (those that do have a golden record) to + // the golden record's typed resource IDs + // --------------------------------------------------------------------------------------------- + + // Find the pids and place them in a map to find our way back + Map pidToIdMap = ids.stream() + .collect(Collectors.toMap( + id -> myIdHelperService.getPidOrThrowException( + RequestPartitionId.allPartitions(), (IIdType) id), + id -> id)); + + // Get the mapped pids from the ids - not all of them will have a golden record + Set pidSet = pidToIdMap.keySet(); + + // Get the golden record pids for the source pids that do have in a single DB call, and place results in a map + Collection> allGoldenTuples = + myMdmLinkDao.resolveGoldenResources(pidSet.stream().toList()); + // We will get **all** the mappings for the gold record associated with the given pid. (i.e. There PatientA and + // PatientB + // both point to the same golden record, we will get back two map entries, even though we passed in the pid of + // PatientA only). We filter so we keep only the record for PatientA (and drop PatientB) + Collection> goldenTuples = allGoldenTuples.stream() + .filter(t -> pidSet.contains(t.getSourcePid())) + .toList(); + Map sourcePidToGoldenPidMap = + goldenTuples.stream().collect(Collectors.toMap(MdmPidTuple::getSourcePid, MdmPidTuple::getGoldenPid)); + + // Now find the typed resource IDs (Patient/ABC) for all the golden record PIDs + Collection pids = sourcePidToGoldenPidMap.values(); + PersistentIdToForcedIdMap> forcedIdMap = + myIdHelperService.translatePidsToForcedIds(new HashSet(pids)); + + // Build the source id --> golden typed resource IDs + Map iIdTypeStringMap = sourcePidToGoldenPidMap.keySet().stream() + .collect(Collectors.toMap( + pidToIdMap::get, + pid -> forcedIdMap.get(sourcePidToGoldenPidMap.get(pid)).orElse(""))); + return iIdTypeStringMap; + } + @Nonnull public Set flattenPidTuplesToSet( RequestPartitionId theRequestPartitionId, diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/svc/MdmSearchExpansionResults.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/svc/MdmSearchExpansionResults.java index fead2d0422fd..8e2e5faac324 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/svc/MdmSearchExpansionResults.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/svc/MdmSearchExpansionResults.java @@ -20,6 +20,7 @@ package ca.uhn.fhir.mdm.svc; import org.hl7.fhir.instance.model.api.IIdType; +import org.jetbrains.annotations.VisibleForTesting; import java.util.HashMap; import java.util.HashSet; @@ -65,4 +66,8 @@ public static boolean isRemapCandidate(IIdType theId) { && theId.hasIdPart() && theId.getValue().equals(theId.toUnqualifiedVersionless().getValue()); } + + public boolean isEmpty() { + return myOriginalIdToExpandedId.isEmpty(); + } } diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/svc/MdmSearchExpansionSvc.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/svc/MdmSearchExpansionSvc.java index c025086451d2..92ad886840fb 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/svc/MdmSearchExpansionSvc.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/svc/MdmSearchExpansionSvc.java @@ -46,7 +46,7 @@ import static org.apache.commons.lang3.StringUtils.isBlank; public class MdmSearchExpansionSvc { - private static final String EXPANSION_RESULTS = MdmSearchExpansionSvc.class.getName() + "_EXPANSION_RESULTS"; + public static final String EXPANSION_RESULTS = MdmSearchExpansionSvc.class.getName() + "_EXPANSION_RESULTS"; private static final String RESOURCE_NAME = MdmSearchExpansionSvc.class.getName() + "_RESOURCE_NAME"; private static final String QUERY_STRING = MdmSearchExpansionSvc.class.getName() + "_QUERY_STRING"; private static final Logger ourLog = Logs.getMdmTroubleshootingLog(); @@ -58,7 +58,7 @@ public class MdmSearchExpansionSvc { private IRequestPartitionHelperSvc myRequestPartitionHelperSvc; @Autowired - private MdmExpandersHolder myMdmExpandersHolder; + private IMdmLinkExpandSvc myMdmLinkExpandSvc; /** * This method looks through all the reference parameters within a {@link SearchParameterMap} @@ -141,8 +141,6 @@ private void expandAnyReferenceParameters( IParamTester theParamTester, MdmSearchExpansionResults theResultsToPopulate) { - IMdmLinkExpandSvc mdmLinkExpandSvc = myMdmExpandersHolder.getLinkExpandSvcInstance(); - List toRemove = new ArrayList<>(); List toAdd = new ArrayList<>(); for (IQueryParameterType iQueryParameterType : orList) { @@ -153,12 +151,12 @@ private void expandAnyReferenceParameters( // First, attempt to expand as a source resource. IIdType sourceId = newId(refParam.getValue()); Set expandedResourceIds = - mdmLinkExpandSvc.expandMdmBySourceResourceId(theRequestPartitionId, sourceId); + myMdmLinkExpandSvc.expandMdmBySourceResourceId(theRequestPartitionId, sourceId); // If we failed, attempt to expand as a golden resource if (expandedResourceIds.isEmpty()) { expandedResourceIds = - mdmLinkExpandSvc.expandMdmByGoldenResourceId(theRequestPartitionId, sourceId); + myMdmLinkExpandSvc.expandMdmByGoldenResourceId(theRequestPartitionId, sourceId); } // Rebuild the search param list. @@ -239,11 +237,10 @@ private void expandIdParameter( } else if (mdmExpand) { ourLog.debug("_id parameter must be expanded out from: {}", id.getValue()); - IMdmLinkExpandSvc mdmLinkExpandSvc = myMdmExpandersHolder.getLinkExpandSvcInstance(); - Set expandedResourceIds = mdmLinkExpandSvc.expandMdmBySourceResourceId(theRequestPartitionId, id); + Set expandedResourceIds = myMdmLinkExpandSvc.expandMdmBySourceResourceId(theRequestPartitionId, id); if (expandedResourceIds.isEmpty()) { - expandedResourceIds = mdmLinkExpandSvc.expandMdmByGoldenResourceId(theRequestPartitionId, id); + expandedResourceIds = myMdmLinkExpandSvc.expandMdmByGoldenResourceId(theRequestPartitionId, id); } // Rebuild