From fd90eb699ff1f65f37b1fffbd3e672a915086ad8 Mon Sep 17 00:00:00 2001 From: Nick Date: Mon, 7 Dec 2020 18:03:56 -0500 Subject: [PATCH] Review updates --- .../uhn/hapi/fhir/docs/server_jpa_mdm/mdm.md | 7 +- .../fhir/docs/server_jpa_mdm/mdm_details.md | 52 +++----- .../hapi/fhir/docs/server_jpa_mdm/mdm_eid.md | 4 +- .../docs/server_jpa_mdm/mdm_operations.md | 31 ++--- .../fhir/docs/server_jpa_mdm/mdm_rules.md | 3 +- .../ca/uhn/fhir/jpa/dao/data/IMdmLinkDao.java | 4 +- .../dao/expunge/ResourceTableFKProvider.java | 3 +- .../java/ca/uhn/fhir/jpa/entity/MdmLink.java | 78 +++++------- .../search/cache/SearchCacheStatusEnum.java | 20 +++ .../jpa/mdm/broker/MdmMessageHandler.java | 4 +- .../jpa/mdm/config/MdmConsumerConfig.java | 11 +- .../ca/uhn/fhir/jpa/mdm/config/MdmLoader.java | 6 - .../mdm/config/MdmSearchParameterLoader.java | 117 ------------------ .../uhn/fhir/jpa/mdm/dao/MdmLinkDaoSvc.java | 94 +++++++------- .../mdm/svc/GoldenResourceMergerSvcImpl.java | 31 +---- .../uhn/fhir/jpa/mdm/svc/MdmClearSvcImpl.java | 12 +- .../jpa/mdm/svc/MdmControllerSvcImpl.java | 14 +-- .../fhir/jpa/mdm/svc/MdmEidUpdateService.java | 6 +- .../fhir/jpa/mdm/svc/MdmLinkQuerySvcImpl.java | 17 +-- .../uhn/fhir/jpa/mdm/svc/MdmLinkSvcImpl.java | 36 +++--- .../jpa/mdm/svc/MdmLinkUpdaterSvcImpl.java | 44 +++---- .../jpa/mdm/svc/MdmMatchFinderSvcImpl.java | 9 +- .../uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvc.java | 27 ++-- .../fhir/jpa/mdm/svc/MdmSearchParamSvc.java | 14 +-- .../fhir/jpa/mdm/svc/MdmSubmitSvcImpl.java | 26 ++-- .../svc/candidate/CandidateStrategyEnum.java | 4 +- ...vc.java => FindCandidateByExampleSvc.java} | 6 +- .../svc/candidate/FindCandidateByLinkSvc.java | 2 +- .../svc/candidate/MdmCandidateSearchSvc.java | 6 +- .../MdmGoldenResourceFindingSvc.java | 10 +- .../ca/uhn/fhir/jpa/mdm/BaseMdmR4Test.java | 43 +++---- .../fhir/jpa/mdm/helper/MdmLinkHelper.java | 2 +- .../jpa/mdm/interceptor/MdmExpungeTest.java | 4 +- .../interceptor/MdmStorageInterceptorIT.java | 8 +- .../matcher/BaseGoldenResourceMatcher.java | 4 +- .../matcher/IsMatchedToAGoldenResource.java | 2 +- .../mdm/matcher/IsPossibleDuplicateOf.java | 4 +- .../fhir/jpa/mdm/provider/BaseLinkR4Test.java | 4 +- .../mdm/provider/MdmProviderBatchR4Test.java | 4 +- .../provider/MdmProviderClearLinkR4Test.java | 2 +- .../mdm/provider/MdmProviderMatchR4Test.java | 1 - ...MdmProviderMergeGoldenResourcesR4Test.java | 5 +- .../provider/MdmProviderQueryLinkR4Test.java | 2 +- .../mdm/searchparam/SearchParameterTest.java | 50 -------- .../fhir/jpa/mdm/svc/MdmBatchSvcImplTest.java | 10 +- .../svc/MdmGoldenResourceMergerSvcTest.java | 6 +- .../uhn/fhir/jpa/mdm/svc/MdmLinkSvcTest.java | 16 +-- .../MdmMatchLinkSvcMultipleEidModeTest.java | 12 +- .../fhir/jpa/mdm/svc/MdmMatchLinkSvcTest.java | 34 +++-- .../jpa/mdm/svc/MdmResourceDaoSvcTest.java | 8 +- .../tasks/HapiFhirJpaMigrationTasks.java | 25 +++- .../uhn/fhir/mdm/api/IMdmControllerSvc.java | 4 +- .../ca/uhn/fhir/mdm/api/IMdmExpungeSvc.java | 4 +- .../ca/uhn/fhir/mdm/api/IMdmLinkQuerySvc.java | 2 +- .../java/ca/uhn/fhir/mdm/api/IMdmLinkSvc.java | 15 +-- .../uhn/fhir/mdm/api/IMdmLinkUpdaterSvc.java | 4 +- .../uhn/fhir/mdm/api/IMdmMatchFinderSvc.java | 1 + .../ca/uhn/fhir/mdm/api/IMdmSubmitSvc.java | 16 +-- .../java/ca/uhn/fhir/mdm/api/MdmLinkJson.java | 12 +- .../uhn/fhir/mdm/api/MdmMatchResultEnum.java | 5 +- .../fhir/mdm/provider/BaseMdmProvider.java | 2 +- .../mdm/provider/MdmControllerHelper.java | 6 +- .../fhir/mdm/provider/MdmControllerUtil.java | 16 +-- .../fhir/mdm/provider/MdmProviderDstu3.java | 16 +-- .../uhn/fhir/mdm/provider/MdmProviderR4.java | 16 +-- .../fhir/mdm/rules/config/MdmSettings.java | 2 +- .../mdm/rules/svc/MdmResourceMatcherSvc.java | 17 ++- .../java/ca/uhn/fhir/mdm/util/EIDHelper.java | 2 +- .../fhir/mdm/util/GoldenResourceHelper.java | 46 +++---- .../ca/uhn/fhir/mdm/util/MessageHelper.java | 16 +-- .../server/provider/ProviderConstants.java | 2 +- 71 files changed, 460 insertions(+), 688 deletions(-) delete mode 100644 hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/config/MdmSearchParameterLoader.java rename hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/candidate/{FindCandidateByScoreSvc.java => FindCandidateByExampleSvc.java} (95%) delete mode 100644 hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/searchparam/SearchParameterTest.java diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm.md b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm.md index 7ea6bb2c124..6ebf41dc9ba 100644 --- a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm.md +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm.md @@ -4,7 +4,7 @@ A Master Data Management (MDM) module allows for links to be created and maintained among FHIR resources. These links indicate the fact that different FHIR resources are known or believed to refer to the same actual (real world) resource. The links are created and updated using different combinations of automatic and manual linking. -The real-world resource is referred to as the Golden Resource in this context. The resource believed to be a duplicate is said to be a target resource. +The real-world resource is referred to as the Golden Resource in this context. The resource believed to be a duplicate is said to be a source resource. ## Working Example @@ -16,10 +16,9 @@ To get up and running with HAPI MDM, either enable it using the `hapi.properties Once MDM is enabled, the next thing you will want to do is configure your [MDM Rules](/hapi-fhir/docs/server_jpa_mdm/mdm_rules.html) -HAPI MDM watches for incoming target resources and automatically links them to the appropriate Golden Resources based on these rules. For example, if the rules indicate that any two patients with the same SSN, birthdate and first and last name are the same patient, then two different Patient resources with matching values for these attributes will automatically be linked to the same Golden Patient resource. If no existing resources match the incoming Patient, then a new Golden Patient resource will be created and linked to the incoming Patient. +HAPI MDM watches for incoming source resources and automatically links them to the appropriate Golden Resources based on these rules. For example, if the rules indicate that any two patients with the same SSN, birthdate and first and last name are the same patient, then two different Patient resources with matching values for these attributes will automatically be linked to the same Golden Patient resource. If no existing resources match the incoming Patient, then a new Golden Patient resource will be created and linked to the incoming Patient. -Based on how well two patients match, the MDM Rules may link the Patient to the Golden Patient as a MATCH or a -POSSIBLE_MATCH. In the case of a POSSIBLE_MATCH, a user will need to later use [MDM Operations](/hapi-fhir/docs/server_jpa_mdm/mdm_operations.html) to either confirm the link as a MATCH, or mark the link as a NO_MATCH in which case HAPI MDM will create a new Person for them. +Based on how well two patients match, the MDM Rules may link the Patient to the Golden Patient as a MATCH or a POSSIBLE_MATCH. In the case of a POSSIBLE_MATCH, a user will need to later use [MDM Operations](/hapi-fhir/docs/server_jpa_mdm/mdm_operations.html) to either confirm the link as a MATCH, or mark the link as a NO_MATCH in which case HAPI MDM will create a new Golden Resource Patient record for them. Another thing that can happen in the linking process is HAPI MDM can determine that two Patients resources may be duplicates. In this case, it marks them as POSSIBLE_DUPLICATE and the user can use [MDM Operations](/hapi-fhir/docs/server_jpa_mdm/mdm_operations.html) to either merge the two Patients or mark them as NO_MATCH in which case HAPI MDM will know not to mark them as possible duplicates in the future. diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_details.md b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_details.md index 20cb58709a7..37a17d821fa 100644 --- a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_details.md +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_details.md @@ -10,75 +10,57 @@ Because HAPI MDM is implemented on the HAPI JPA Server, it uses the FHIR model t There are several resources that are used: -* Target resource - Represents the record in being matched. For example, it can be a Patient resource who receives healthcare services and that should be mapped to a master record. -* Golden resource - Represents a master record that the target record should point to. For example, it can be a real-world patient Patient resource that multiple duplicate Patient resources point to. +* Source resource - Represents the record in being matched. For example, it can be a Patient resource who receives healthcare services and that should be mapped to a master record. +* Golden Resource - Represents a master record that the source record should point to. For example, it can be a real-world Patient resource that multiple duplicate Patient resources point to. # Automatic Linking -With MDM enabled, the default behavior of the MDM is to create a new Golden record for every target record that is created such that there is a 1:1 relationship between them. Any relinking is then expected to be done manually via the [MDM Operations](/hapi-fhir/docs/server_jpa_mdm/mdm_operations.html). +With MDM enabled, the default behavior of the MDM is to create a new Golden Record for every source record that is created such that there is a 1:1 relationship between them. Any relinking is then expected to be done manually via the [MDM Operations](/hapi-fhir/docs/server_jpa_mdm/mdm_operations.html). In a typical configuration it is often desirable to have links created automatically using matching rules. For example, you might decide that if a Patient shares the same name, gender, and date of birth as another Patient, you have at least a little confidence that they are the same Patient. -This automatic linking is done via configurable matching rules that create links between Target record and Golden Record. Based on the strength of the match configured in these rules, the link will be set to either POSSIBLE_MATCH or MATCH. +This automatic linking is done via configurable matching rules that create links between source record and Golden Record. Based on the strength of the match configured in these rules, the link will be set to either POSSIBLE_MATCH or MATCH. -It is important to note that before a resource is processed by MDM, it is first checked to ensure that it has at least one attribute that the MDM system cares about, as defined in the `mdm-rules.json` file. If the incoming resource has no such attributes, then MDM processing does not occur on it. In this case, no Golden Resource is created for this target resource. If in the future the target resource is updated to contain attributes the MDM system does concern itself with, it will be processed at that time. +It is important to note that before a resource is processed by MDM, it is first checked to ensure that it has at least one attribute that the MDM system cares about, as defined in the `mdm-rules.json` file. If the incoming resource has no such attributes, then MDM processing does not occur on it. In this case, no Golden Resource is created for this source resource. If in the future the source resource is updated to contain attributes the MDM system does concern itself with, it will be processed at that time. ## Design Below are some simplifying principles HAPI MDM follows to reduce complexity and ensure data integrity. -1. When MDM is enabled on a HAPI FHIR server, any Golden Resource in the repository that has the "hapi-mdm" tag is considered read-only by the FHIR endpoint. These Golden Resources are managed exclusively by HAPI MDM. Users can only change them via [MDM Operations](/hapi-fhir/docs/server_jpa_mdm/mdm_operations.html). In most cases, users will indirectly change them by creating and updating the corresponding target resources. +1. When MDM is enabled on a HAPI FHIR server, any Golden Resource in the repository that has the "hapi-mdm" tag is considered read-only by the FHIR endpoint. These Golden Resources are managed exclusively by HAPI MDM. Users can only change them via [MDM Operations](/hapi-fhir/docs/server_jpa_mdm/mdm_operations.html). In most cases, users will indirectly change them by creating and updating the corresponding source resources. -1. Every target resource in the system has a MATCH link to at most one Golden resource. +1. Every source resource in the system has a MATCH link to at most one Golden Resource. -1. The only target resources in the system that do not have a MATCH link are those that have the 'NO-MDM' tag or those that have POSSIBLE_MATCH links pending review. +1. The only source resources in the system that do not have a MATCH link are those that have the 'NO-MDM' tag or those that have POSSIBLE_MATCH links pending review. -1. The HAPI MDM rules define a single identifier system that holds the external enterprise id ("EID"). If a target resource has an external EID, then the Golden resource it links to always has the same EID. If a target resource has no EID when it arrives, a unique UUID will be assigned as that target resource's EID. +1. The HAPI MDM rules define a single identifier system that holds the external enterprise id ("EID"). If a source resource has an external EID, then the Golden Resource it links to always has the same EID. If a source resource has no EID when it arrives, a unique UUID will be assigned as that source resource's EID. 1. A Golden Resource can have both an internal EID (auto-created by HAPI), and an external EID (provided by an external system). -1. Two different Golden resources cannot have the same EID. +1. Two different Golden Resources cannot have the same EID. -1. Target resources are only ever compared to Golden resources via this EID. +1. Source resources are only ever compared to Golden Resources via this EID. ## Links -1. HAPI MDM manages mdm-link records ("links") that link a target resource to a Golden resource. When these are - created/updated by matching rules, the links are marked as AUTO. When these links are changed manually, they are marked as MANUAL. +1. HAPI MDM manages mdm-link records ("links") that link a source resource to a Golden Resource. When these are created/updated by matching rules, the links are marked as AUTO. When these links are changed manually, they are marked as MANUAL. 1. Once a link has been manually assigned as NO_MATCH or MATCH, the system will not change it. -1. When a new target resource is created/updated it is then compared to all other target resources of the same type in the repository. The outcome of each of these comparisons is either NO_MATCH, POSSIBLE_MATCH or MATCH. +1. When a new source resource is created/updated it is then compared to all other source resources of the same type in the repository. The outcome of each of these comparisons is either NO_MATCH, POSSIBLE_MATCH or MATCH. 1. HAPI MDM stores these extra link details in a table called `MPI_LINK`. - - ### Possible rule match outcomes: -When a new target resource is compared with all other resources of the same type in the repository, there are four possible outcomes: +When a new source resource is compared with all other resources of the same type in the repository, there are four possible outcomes: - +* CASE 1: No MATCH and no POSSIBLE_MATCH outcomes -> a new Golden Resource is created and linked to that source resource as MATCH. If the incoming resource has an EID, it is copied to the Golden Resource. Otherwise a new UUID is generated and used as the internal EID. -* CASE 1: No MATCH and no POSSIBLE_MATCH outcomes -> a new Golden resource is created and linked to that target resource as MATCH. If the incoming resource has an EID, it is copied to the Golden resource. Otherwise a new UUID is generated and used as the internal EID. +* CASE 2: All of the MATCH source resources are already linked to the same Golden Resource -> a new Link is created between the new source resource and that Golden Resource and is set to MATCH. -* CASE 2: All of the MATCH target resources are already linked to the same Golden Resource -> a new Link is created between the new target resource and that Golden Resource and is set to MATCH. - -* CASE 3: The MATCH target resources link to more than one Golden resource -> Mark all links as POSSIBLE_MATCH. All other Golden resources are marked as POSSIBLE_DUPLICATE of this first Golden Resource. These duplicates are manually reviewed later and either merged or marked as NO_MATCH and the system will no longer consider them as a POSSIBLE_DUPLICATE going forward. POSSIBLE_DUPLICATE is the only link type that can have a Golden Resource as both the source and target of the link. +* CASE 3: The MATCH source resources link to more than one Golden Resource -> Mark all links as POSSIBLE_MATCH. All other Golden Resources are marked as POSSIBLE_DUPLICATE of this first Golden Resource. These duplicates are manually reviewed later and either merged or marked as NO_MATCH and the system will no longer consider them as a POSSIBLE_DUPLICATE going forward. POSSIBLE_DUPLICATE is the only link type that can have a Golden Resource as both the source and target of the link. * CASE 4: Only POSSIBLE_MATCH outcomes -> In this case, new POSSIBLE_MATCH links are created and await manual reassignment to either NO_MATCH or MATCH. diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_eid.md b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_eid.md index 75a93d684e9..d86d3a68ecc 100644 --- a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_eid.md +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_eid.md @@ -1,6 +1,6 @@ # MDM Enterprise Identifiers -An Enterprise Identifier (EID) is a unique identifier that can be attached to target resources. Each implementation is expected to use exactly one EID system for incoming resources, defined in the MDM Rules file. If a target resource with a valid EID is submitted, that EID will be copied over to the Golden resource that was matched. In the case that the incoming target resource had no EID assigned, an internal EID will be created for it. There are thus two classes of EID: +An Enterprise Identifier (EID) is a unique identifier that can be attached to source resources. Each implementation is expected to use exactly one EID system for incoming resources, defined in the MDM Rules file. If a source resource with a valid EID is submitted, that EID will be copied over to the Golden Resource that was matched. In the case that the incoming source resource had no EID assigned, an internal EID will be created for it. There are thus two classes of EID: * Internal EIDs, created by HAPI-MDM, and * External EIDs, provided by the submitted resources. @@ -15,7 +15,7 @@ contains two EID related settings. Both are enabled by default. ## MDM EID Scenarios -MDM EID management follows a complex set of rules to link related target records via their Enterprise Id. The following diagrams outline how EIDs are replicated from Patient resources to their linked Golden Patient resources under various scenarios according to the values of the EID Settings. +MDM EID management follows a complex set of rules to link related source records via their Enterprise Id. The following diagrams outline how EIDs are replicated from Patient resources to their linked Golden Patient resources under various scenarios according to the values of the EID Settings. ## MDM EID Create Scenarios diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_operations.md b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_operations.md index 008cac4cbaa..9b38e7308cd 100644 --- a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_operations.md +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_operations.md @@ -31,7 +31,7 @@ Use the `$mdm-query-links` operation to view MDM links. The results returned are String 0..1 - The id of the target resource (e.g. Patient resource). + The id of the source resource (e.g. Patient resource). @@ -82,9 +82,9 @@ This operation returns a `Parameters` resource that looks like the following: "name": "link", "part": [ { "name": "goldenResourceId", - "valueString": "Person/123" + "valueString": "Patient/123" }, { - "name": "targetResourceId", + "name": "sourceResourceId", "valueString": "Patient/456" }, { "name": "matchResult", @@ -129,10 +129,10 @@ This operation returns `Parameters` similar to `$mdm-query-links`: "name": "link", "part": [ { "name": "goldenResourceId", - "valueString": "Person/123" + "valueString": "Patient/123" }, { - "name": "targetResourceId", - "valueString": "Person/456" + "name": "sourceResourceId", + "valueString": "Patient/456" }, { "name": "matchResult", "valueString": "POSSIBLE_DUPLICATE" @@ -164,7 +164,7 @@ This operation takes the following parameters: String 1..1 - The id of the Golden resource. + The id of the Golden Resource. @@ -172,7 +172,7 @@ This operation takes the following parameters: String 1..1 - The id of the Person that personId has a possible duplicate link to. + The id of the source resource that has a possible duplicate link to. @@ -232,7 +232,7 @@ Use the `$mdm-update-link` operation to change the `matchResult` update of an md String 1..1 - The id of the Golden resource. + The id of the Golden Resource. @@ -240,7 +240,7 @@ Use the `$mdm-update-link` operation to change the `matchResult` update of an md String 1..1 - The id of the target resource. + The id of the source resource. @@ -284,14 +284,9 @@ Any supported MDM type can be used. The following request body shows how to upda The operation returns the updated Golden Resource. For the query above `Patient` resource will be returned. Note that this is the only way to modify MDM-managed Golden Resources. -## Merge Persons +## Merge Golden Resources - -The `$mdm-merge-golden-resources` operation can be used to merge one Golden resource with another. When -doing this, you will need to decide which resource to merge from and which one to merge to. +The `$mdm-merge-golden-resources` operation can be used to merge one Golden Resource with another. When doing this, you will need to decide which resource to merge from and which one to merge to. After the merge is complete, `fromGoldenResourceId` will be deactivated by assigning a metadata tag `REDIRECTED`. @@ -451,7 +446,7 @@ MDM will respond with the appropriate resource bundle. ## Clearing MDM Links -The `$mdm-clear` operation is used to batch-delete MDM links and related persons from the database. This operation is meant to be used during the rules-tuning phase of the MDM implementation so that you can quickly test your ruleset. It permits the user to reset the state of their MDM system without manual deletion of all related links and golden resources. +The `$mdm-clear` operation is used to batch-delete MDM links and related Golden Resources from the database. This operation is meant to be used during the rules-tuning phase of the MDM implementation so that you can quickly test your ruleset. It permits the user to reset the state of their MDM system without manual deletion of all related links and golden resources. After the operation is complete, all targeted MDM links are removed from the system, and their related Golden Resources are deleted and expunged from the server. diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_rules.md b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_rules.md index b3569fa50ae..6eb89df53e0 100644 --- a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_rules.md +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_rules.md @@ -2,8 +2,7 @@ HAPI MDM rules are defined in a single json document. -Note that in all the following configuration, valid options for `resourceType` include any supported resource, such as `Organization`, `Patient`, `Practitioner`, and `*`. Use `*` if the -criteria is identical across both resource types and you would like to apply it to all resources. +Note that in all the following configuration, valid options for `resourceType` include any supported resource, such as `Organization`, `Patient`, `Practitioner`, and `*`. Use `*` if the criteria is identical across both resource types and you would like to apply it to all resources. Here is an example of a full HAPI MDM rules json document: diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IMdmLinkDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IMdmLinkDao.java index be63bbd2d9a..bd519869845 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IMdmLinkDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IMdmLinkDao.java @@ -31,10 +31,10 @@ import org.springframework.stereotype.Repository; @Repository public interface IMdmLinkDao extends JpaRepository { @Modifying - @Query("DELETE FROM MdmLink f WHERE myPersonPid = :pid OR myTargetPid = :pid") + @Query("DELETE FROM MdmLink f WHERE myGoldenResourcePid = :pid OR mySourcePid = :pid") int deleteWithAnyReferenceToPid(@Param("pid") Long thePid); @Modifying - @Query("DELETE FROM MdmLink f WHERE (myPersonPid = :pid OR myTargetPid = :pid) AND myMatchResult <> :matchResult") + @Query("DELETE FROM MdmLink f WHERE (myGoldenResourcePid = :pid OR mySourcePid = :pid) AND myMatchResult <> :matchResult") int deleteWithAnyReferenceToPidAndMatchResultNot(@Param("pid") Long thePid, @Param("matchResult") MdmMatchResultEnum theMatchResult); } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/expunge/ResourceTableFKProvider.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/expunge/ResourceTableFKProvider.java index bcca4ec1c02..593b9e544db 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/expunge/ResourceTableFKProvider.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/expunge/ResourceTableFKProvider.java @@ -54,9 +54,8 @@ public class ResourceTableFKProvider { retval.add(new ResourceForeignKey("HFJ_SPIDX_TOKEN", "RES_ID")); retval.add(new ResourceForeignKey("HFJ_SPIDX_URI", "RES_ID")); retval.add(new ResourceForeignKey("HFJ_SUBSCRIPTION_STATS", "RES_ID")); - retval.add(new ResourceForeignKey("MPI_LINK", "PERSON_PID")); retval.add(new ResourceForeignKey("MPI_LINK", "GOLDEN_RESOURCE_PID")); - retval.add(new ResourceForeignKey("MPI_LINK", "TARGET_PID")); + retval.add(new ResourceForeignKey("MPI_LINK", "SOURCE_PID")); retval.add(new ResourceForeignKey("NPM_PACKAGE_VER", "BINARY_RES_ID")); retval.add(new ResourceForeignKey("NPM_PACKAGE_VER_RES", "BINARY_RES_ID")); retval.add(new ResourceForeignKey("TRM_CODESYSTEM", "RES_ID")); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/MdmLink.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/MdmLink.java index 6534658003c..6e551ac1def 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/MdmLink.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/MdmLink.java @@ -45,13 +45,13 @@ import java.util.Date; @Entity @Table(name = "MPI_LINK", uniqueConstraints = { - @UniqueConstraint(name = "IDX_EMPI_PERSON_TGT", columnNames = {"PERSON_PID", "TARGET_PID"}), + @UniqueConstraint(name = "IDX_MDM_GOLDEN_RESOURCE_SRC", columnNames = {"GOLDEN_RESOURCE_PID", "SOURCE_PID"}), }) public class MdmLink { public static final int VERSION_LENGTH = 16; private static final int MATCH_RESULT_LENGTH = 16; private static final int LINK_SOURCE_LENGTH = 16; - public static final int TARGET_TYPE_LENGTH = 40; + public static final int SOURCE_TYPE_LENGTH = 40; @SequenceGenerator(name = "SEQ_EMPI_LINK_ID", sequenceName = "SEQ_EMPI_LINK_ID") @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_EMPI_LINK_ID") @@ -60,27 +60,18 @@ public class MdmLink { private Long myId; @ManyToOne(optional = false, fetch = FetchType.LAZY, cascade = {}) - @JoinColumn(name = "GOLDEN_RESOURCE_PID", referencedColumnName = "RES_ID", foreignKey = @ForeignKey(name = "FK_EMPI_LINK_GOLDEN_RESOURCE"), insertable=false, updatable=false, nullable=false) + @JoinColumn(name = "GOLDEN_RESOURCE_PID", referencedColumnName = "RES_ID", foreignKey = @ForeignKey(name = "FK_MDM_LINK_GOLDEN_RESOURCE"), insertable=false, updatable=false, nullable=false) private ResourceTable myGoldenResource; @Column(name = "GOLDEN_RESOURCE_PID", nullable=false) private Long myGoldenResourcePid; - @Deprecated @ManyToOne(optional = false, fetch = FetchType.LAZY, cascade = {}) - @JoinColumn(name = "PERSON_PID", referencedColumnName = "RES_ID", foreignKey = @ForeignKey(name = "FK_EMPI_LINK_PERSON"), insertable=false, updatable=false, nullable=false) - private ResourceTable myPerson; + @JoinColumn(name = "SOURCE_PID", referencedColumnName = "RES_ID", foreignKey = @ForeignKey(name = "FK_MDM_LINK_SOURCE"), insertable=false, updatable=false, nullable=false) + private ResourceTable mySource; - @Deprecated - @Column(name = "PERSON_PID", nullable=false) - private Long myPersonPid; - - @ManyToOne(optional = false, fetch = FetchType.LAZY, cascade = {}) - @JoinColumn(name = "TARGET_PID", referencedColumnName = "RES_ID", foreignKey = @ForeignKey(name = "FK_EMPI_LINK_TARGET"), insertable=false, updatable=false, nullable=false) - private ResourceTable myTarget; - - @Column(name = "TARGET_PID", updatable=false, nullable=false) - private Long myTargetPid; + @Column(name = "SOURCE_PID", updatable=false, nullable=false) + private Long mySourcePid; @Column(name = "MATCH_RESULT", nullable = false) @Enumerated(EnumType.ORDINAL) @@ -106,8 +97,8 @@ public class MdmLink { private Boolean myEidMatch; /** This link created a new person **/ - @Column(name = "NEW_PERSON") - private Boolean myHadToCreateNewResource; + @Column(name = "NEW_GOLDEN_RESOURCE") + private Boolean myHadToCreateNewGoldenResource; @Column(name = "VECTOR") private Long myVector; @@ -125,8 +116,8 @@ public class MdmLink { myVersion = theVersion; } - @Column(name = "TARGET_TYPE", nullable = true, length = TARGET_TYPE_LENGTH) - private String myMdmTargetType; + @Column(name = "SOURCE_TYPE", nullable = true, length = SOURCE_TYPE_LENGTH) + private String myMdmSourceType; public Long getId() { return myId; @@ -151,34 +142,27 @@ public class MdmLink { return myGoldenResourcePid; } - public MdmLink setPersonPid(Long thePersonPid) { - myPersonPid = thePersonPid; - return this; - } - public MdmLink setGoldenResourcePid(Long theGoldenResourcePid) { - setPersonPid(theGoldenResourcePid); - myGoldenResourcePid = theGoldenResourcePid; return this; } - public ResourceTable getTarget() { - return myTarget; + public ResourceTable getSource() { + return mySource; } - public MdmLink setTarget(ResourceTable theTarget) { - myTarget = theTarget; - myTargetPid = theTarget.getId(); + public MdmLink setSource(ResourceTable theSource) { + mySource = theSource; + mySourcePid = theSource.getId(); return this; } - public Long getTargetPid() { - return myTargetPid; + public Long getSourcePid() { + return mySourcePid; } - public MdmLink setTargetPid(Long theTargetPid) { - myTargetPid = theTargetPid; + public MdmLink setSourcePid(Long theSourcePid) { + mySourcePid = theSourcePid; return this; } @@ -286,17 +270,17 @@ public class MdmLink { return this; } - public boolean getHadToCreateNewResource() { - return myHadToCreateNewResource != null && myHadToCreateNewResource; + public boolean getHadToCreateNewGoldenResource() { + return myHadToCreateNewGoldenResource != null && myHadToCreateNewGoldenResource; } - public MdmLink setHadToCreateNewResource(Boolean theHadToCreateNewResource) { - myHadToCreateNewResource = theHadToCreateNewResource; + public MdmLink setHadToCreateNewGoldenResource(Boolean theHadToCreateNewResource) { + myHadToCreateNewGoldenResource = theHadToCreateNewResource; return this; } - public MdmLink setMdmTargetType(String mdmTargetType) { - myMdmTargetType = mdmTargetType; + public MdmLink setMdmSourceType(String mdmSourceType) { + myMdmSourceType = mdmSourceType; return this; } @@ -305,19 +289,19 @@ public class MdmLink { return new ToStringBuilder(this) .append("myId", myId) .append("myGoldenResource", myGoldenResourcePid) - .append("myTargetPid", myTargetPid) - .append("myMdmTargetType", myMdmTargetType) + .append("mySourcePid", mySourcePid) + .append("myMdmSourceType", myMdmSourceType) .append("myMatchResult", myMatchResult) .append("myLinkSource", myLinkSource) .append("myEidMatch", myEidMatch) - .append("myHadToCreateNewResource", myHadToCreateNewResource) + .append("myHadToCreateNewResource", myHadToCreateNewGoldenResource) .append("myScore", myScore) .append("myRuleCount", myRuleCount) .toString(); } - public String getMdmTargetType() { - return myMdmTargetType; + public String getMdmSourceType() { + return myMdmSourceType; } public Long getRuleCount() { diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/cache/SearchCacheStatusEnum.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/cache/SearchCacheStatusEnum.java index 8537bbcd00c..3bfec97204c 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/cache/SearchCacheStatusEnum.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/cache/SearchCacheStatusEnum.java @@ -1,5 +1,25 @@ package ca.uhn.fhir.jpa.search.cache; +/*- + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2020 University Health Network + * %% + * 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% + */ + public enum SearchCacheStatusEnum { NOT_TRIED, diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/broker/MdmMessageHandler.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/broker/MdmMessageHandler.java index 4230638dc2b..253bb93ea5b 100644 --- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/broker/MdmMessageHandler.java +++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/broker/MdmMessageHandler.java @@ -138,7 +138,7 @@ public class MdmMessageHandler implements MessageHandler { } private void handleCreatePatientOrPractitioner(ResourceModifiedMessage theMsg, MdmTransactionContext theMdmTransactionContext) { - myMdmMatchLinkSvc.updateMdmLinksForMdmTarget(getResourceFromPayload(theMsg), theMdmTransactionContext); + myMdmMatchLinkSvc.updateMdmLinksForMdmSource(getResourceFromPayload(theMsg), theMdmTransactionContext); } private IAnyResource getResourceFromPayload(ResourceModifiedMessage theMsg) { @@ -146,7 +146,7 @@ public class MdmMessageHandler implements MessageHandler { } private void handleUpdatePatientOrPractitioner(ResourceModifiedMessage theMsg, MdmTransactionContext theMdmTransactionContext) { - myMdmMatchLinkSvc.updateMdmLinksForMdmTarget(getResourceFromPayload(theMsg), theMdmTransactionContext); + myMdmMatchLinkSvc.updateMdmLinksForMdmSource(getResourceFromPayload(theMsg), theMdmTransactionContext); } private void log(MdmTransactionContext theMdmContext, String theMessage) { diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/config/MdmConsumerConfig.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/config/MdmConsumerConfig.java index 1dc52d37f96..9770aca1d27 100644 --- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/config/MdmConsumerConfig.java +++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/config/MdmConsumerConfig.java @@ -61,7 +61,7 @@ import ca.uhn.fhir.jpa.mdm.svc.candidate.MdmCandidateSearchSvc; import ca.uhn.fhir.jpa.mdm.svc.candidate.MdmGoldenResourceFindingSvc; import ca.uhn.fhir.jpa.mdm.svc.candidate.FindCandidateByEidSvc; import ca.uhn.fhir.jpa.mdm.svc.candidate.FindCandidateByLinkSvc; -import ca.uhn.fhir.jpa.mdm.svc.candidate.FindCandidateByScoreSvc; +import ca.uhn.fhir.jpa.mdm.svc.candidate.FindCandidateByExampleSvc; import ca.uhn.fhir.rest.server.util.ISearchParamRetriever; import ca.uhn.fhir.validation.IResourceLoader; import org.slf4j.Logger; @@ -122,11 +122,6 @@ public class MdmConsumerConfig { return new MdmSubscriptionLoader(); } - @Bean - MdmSearchParameterLoader mdmSearchParameterLoader() { - return new MdmSearchParameterLoader(); - } - @Bean MdmGoldenResourceFindingSvc mdmGoldenResourceFindingSvc() { return new MdmGoldenResourceFindingSvc(); @@ -143,8 +138,8 @@ public class MdmConsumerConfig { } @Bean - FindCandidateByScoreSvc findCandidateByScoreSvc() { - return new FindCandidateByScoreSvc(); + FindCandidateByExampleSvc findCandidateByScoreSvc() { + return new FindCandidateByExampleSvc(); } @Bean diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/config/MdmLoader.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/config/MdmLoader.java index 57b5b076a32..84a9c860cf8 100644 --- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/config/MdmLoader.java +++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/config/MdmLoader.java @@ -40,8 +40,6 @@ public class MdmLoader { MdmProviderLoader myMdmProviderLoader; @Autowired MdmSubscriptionLoader myMdmSubscriptionLoader; - @Autowired - MdmSearchParameterLoader myMdmSearchParameterLoader; @EventListener(classes = {ContextRefreshedEvent.class}) // This @Order is here to ensure that MatchingQueueSubscriberLoader has initialized before we initialize this. @@ -57,9 +55,5 @@ public class MdmLoader { myMdmSubscriptionLoader.daoUpdateMdmSubscriptions(); ourLog.info("MDM subscriptions updated"); - - //TODO GGG MDM: Do we need these search parameters, or equivalent, anymore? Don't think so... ask @fil512 - myMdmSearchParameterLoader.daoUpdateMdmSearchParameters(); - ourLog.info("MDM search parameters updated"); } } diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/config/MdmSearchParameterLoader.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/config/MdmSearchParameterLoader.java deleted file mode 100644 index 1d7233d5ea8..00000000000 --- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/config/MdmSearchParameterLoader.java +++ /dev/null @@ -1,117 +0,0 @@ -package ca.uhn.fhir.jpa.mdm.config; - -/*- - * #%L - * HAPI FHIR JPA Server - Master Data Management - * %% - * Copyright (C) 2014 - 2020 University Health Network - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * #L% - */ - -import ca.uhn.fhir.context.ConfigurationException; -import ca.uhn.fhir.context.FhirContext; -import ca.uhn.fhir.mdm.api.MdmConstants; -import ca.uhn.fhir.jpa.api.dao.DaoRegistry; -import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao; -import org.hl7.fhir.instance.model.api.IBaseResource; -import org.hl7.fhir.r4.model.Enumerations; -import org.hl7.fhir.r4.model.SearchParameter; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -@Service -public class MdmSearchParameterLoader { - - public static final String MDM_PERSON_ASSURANCE_SEARCH_PARAMETER_ID = "person-assurance"; - public static final String MDM_PERSON_ACTIVE_SEARCH_PARAMETER_ID = "person-active"; - - @Autowired - public FhirContext myFhirContext; - @Autowired - public DaoRegistry myDaoRegistry; - - synchronized public void daoUpdateMdmSearchParameters() { - IBaseResource goldenResourceAssurance; - IBaseResource goldenResourceActive; - switch (myFhirContext.getVersion().getVersion()) { - case DSTU3: - goldenResourceAssurance = buildAssuranceMdmSearchParameterDstu3(); - goldenResourceActive = buildActiveMdmSearchParameterDstu3(); - break; - case R4: - goldenResourceAssurance = buildAssuranceMdmSearchParameterR4(); - goldenResourceActive = buildActiveMdmSearchParameterR4(); - break; - default: - throw new ConfigurationException("MDM not supported for FHIR version " + myFhirContext.getVersion().getVersion()); - } - - IFhirResourceDao searchParameterDao = myDaoRegistry.getResourceDao("SearchParameter"); - searchParameterDao.update(goldenResourceAssurance); - searchParameterDao.update(goldenResourceActive); - } - - private org.hl7.fhir.dstu3.model.SearchParameter buildAssuranceMdmSearchParameterDstu3() { - org.hl7.fhir.dstu3.model.SearchParameter retval = new org.hl7.fhir.dstu3.model.SearchParameter(); - retval.setId(MDM_PERSON_ASSURANCE_SEARCH_PARAMETER_ID); - retval.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE); - retval.getMeta().addTag().setSystem(MdmConstants.SYSTEM_MDM_MANAGED).setCode(MdmConstants.CODE_HAPI_MDM_MANAGED); - retval.setCode("assurance"); - retval.addBase("Person"); - retval.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN); - retval.setDescription("The assurance level of the link on a Person"); - retval.setExpression("Person.link.assurance"); - return retval; - } - - private SearchParameter buildAssuranceMdmSearchParameterR4() { - SearchParameter retval = new SearchParameter(); - retval.setId(MDM_PERSON_ASSURANCE_SEARCH_PARAMETER_ID); - retval.setStatus(Enumerations.PublicationStatus.ACTIVE); - retval.getMeta().addTag().setSystem(MdmConstants.SYSTEM_MDM_MANAGED).setCode(MdmConstants.CODE_HAPI_MDM_MANAGED); - retval.setCode("assurance"); - retval.addBase("Person"); - retval.setType(Enumerations.SearchParamType.TOKEN); - retval.setDescription("The assurance level of the link on a Person"); - retval.setExpression("Person.link.assurance"); - return retval; - } - - private org.hl7.fhir.dstu3.model.SearchParameter buildActiveMdmSearchParameterDstu3() { - org.hl7.fhir.dstu3.model.SearchParameter retval = new org.hl7.fhir.dstu3.model.SearchParameter(); - retval.setId(MDM_PERSON_ACTIVE_SEARCH_PARAMETER_ID); - retval.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE); - retval.getMeta().addTag().setSystem(MdmConstants.SYSTEM_MDM_MANAGED).setCode(MdmConstants.CODE_HAPI_MDM_MANAGED); - retval.setCode("active"); - retval.addBase("Person"); - retval.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN); - retval.setDescription("The active status of a Person"); - retval.setExpression("Person.active"); - return retval; - } - - private SearchParameter buildActiveMdmSearchParameterR4() { - SearchParameter retval = new SearchParameter(); - retval.setId(MDM_PERSON_ACTIVE_SEARCH_PARAMETER_ID); - retval.setStatus(Enumerations.PublicationStatus.ACTIVE); - retval.getMeta().addTag().setSystem(MdmConstants.SYSTEM_MDM_MANAGED).setCode(MdmConstants.CODE_HAPI_MDM_MANAGED); - retval.setCode("active"); - retval.addBase("Person"); - retval.setType(Enumerations.SearchParamType.TOKEN); - retval.setDescription("The active status of a Person"); - retval.setExpression("Person.active"); - return retval; - } -} diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/dao/MdmLinkDaoSvc.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/dao/MdmLinkDaoSvc.java index fe093af485c..08b4268c354 100644 --- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/dao/MdmLinkDaoSvc.java +++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/dao/MdmLinkDaoSvc.java @@ -60,24 +60,24 @@ public class MdmLinkDaoSvc { private FhirContext myFhirContext; @Transactional - public MdmLink createOrUpdateLinkEntity(IBaseResource theGoldenResource, IBaseResource theTargetResource, MdmMatchOutcome theMatchOutcome, MdmLinkSourceEnum theLinkSource, @Nullable MdmTransactionContext theMdmTransactionContext) { + public MdmLink createOrUpdateLinkEntity(IBaseResource theGoldenResource, IBaseResource theSourceResource, MdmMatchOutcome theMatchOutcome, MdmLinkSourceEnum theLinkSource, @Nullable MdmTransactionContext theMdmTransactionContext) { Long goldenResourcePid = myIdHelperService.getPidOrNull(theGoldenResource); - Long targetResourcePid = myIdHelperService.getPidOrNull(theTargetResource); + Long sourceResourcePid = myIdHelperService.getPidOrNull(theSourceResource); - MdmLink mdmLink = getOrCreateMdmLinkByGoldenResourcePidAndTargetResourcePid(goldenResourcePid, targetResourcePid); + MdmLink mdmLink = getOrCreateMdmLinkByGoldenResourcePidAndSourceResourcePid(goldenResourcePid, sourceResourcePid); mdmLink.setLinkSource(theLinkSource); mdmLink.setMatchResult(theMatchOutcome.getMatchResultEnum()); // Preserve these flags for link updates mdmLink.setEidMatch(theMatchOutcome.isEidMatch() | mdmLink.isEidMatch()); - mdmLink.setHadToCreateNewResource(theMatchOutcome.isCreatedNewResource() | mdmLink.getHadToCreateNewResource()); - mdmLink.setMdmTargetType(myFhirContext.getResourceType(theTargetResource)); + mdmLink.setHadToCreateNewGoldenResource(theMatchOutcome.isCreatedNewResource() | mdmLink.getHadToCreateNewGoldenResource()); + mdmLink.setMdmSourceType(myFhirContext.getResourceType(theSourceResource)); if (mdmLink.getScore() != null) { mdmLink.setScore(Math.max(theMatchOutcome.score, mdmLink.getScore())); } else { mdmLink.setScore(theMatchOutcome.score); } - String message = String.format("Creating MdmLink from %s to %s -> %s", theGoldenResource.getIdElement().toUnqualifiedVersionless(), theTargetResource.getIdElement().toUnqualifiedVersionless(), theMatchOutcome); + String message = String.format("Creating MdmLink from %s to %s -> %s", theGoldenResource.getIdElement().toUnqualifiedVersionless(), theSourceResource.getIdElement().toUnqualifiedVersionless(), theMatchOutcome); theMdmTransactionContext.addTransactionLogMessage(message); ourLog.debug(message); save(mdmLink); @@ -85,54 +85,54 @@ public class MdmLinkDaoSvc { } @Nonnull - public MdmLink getOrCreateMdmLinkByGoldenResourcePidAndTargetResourcePid(Long theGoldenResourcePid, Long theTargetResourcePid) { - Optional oExisting = getLinkByGoldenResourcePidAndTargetResourcePid(theGoldenResourcePid, theTargetResourcePid); + public MdmLink getOrCreateMdmLinkByGoldenResourcePidAndSourceResourcePid(Long theGoldenResourcePid, Long theSourceResourcePid) { + Optional oExisting = getLinkByGoldenResourcePidAndSourceResourcePid(theGoldenResourcePid, theSourceResourcePid); if (oExisting.isPresent()) { return oExisting.get(); } else { MdmLink newLink = myMdmLinkFactory.newMdmLink(); newLink.setGoldenResourcePid(theGoldenResourcePid); - newLink.setTargetPid(theTargetResourcePid); + newLink.setSourcePid(theSourceResourcePid); return newLink; } } - public Optional getLinkByGoldenResourcePidAndTargetResourcePid(Long theGoldenResourcePid, Long theTargetResourcePid) { - if (theTargetResourcePid == null || theGoldenResourcePid == null) { + public Optional getLinkByGoldenResourcePidAndSourceResourcePid(Long theGoldenResourcePid, Long theSourceResourcePid) { + if (theSourceResourcePid == null || theGoldenResourcePid == null) { return Optional.empty(); } MdmLink link = myMdmLinkFactory.newMdmLink(); - link.setTargetPid(theTargetResourcePid); + link.setSourcePid(theSourceResourcePid); link.setGoldenResourcePid(theGoldenResourcePid); Example example = Example.of(link); return myMdmLinkDao.findOne(example); } /** - * Given a Target Pid, and a match result, return all links that match these criteria. + * Given a source resource Pid, and a match result, return all links that match these criteria. * - * @param theTargetPid the target of the relationship. + * @param theSourcePid the source of the relationship. * @param theMatchResult the Match Result of the relationship * @return a list of {@link MdmLink} entities matching these criteria. */ - public List getMdmLinksByTargetPidAndMatchResult(Long theTargetPid, MdmMatchResultEnum theMatchResult) { + public List getMdmLinksBySourcePidAndMatchResult(Long theSourcePid, MdmMatchResultEnum theMatchResult) { MdmLink exampleLink = myMdmLinkFactory.newMdmLink(); - exampleLink.setTargetPid(theTargetPid); + exampleLink.setSourcePid(theSourcePid); exampleLink.setMatchResult(theMatchResult); Example example = Example.of(exampleLink); return myMdmLinkDao.findAll(example); } /** - * Given a target Pid, return its Matched {@link MdmLink}. There can only ever be at most one of these, but its possible - * the target has no matches, and may return an empty optional. + * Given a source Pid, return its Matched {@link MdmLink}. There can only ever be at most one of these, but its possible + * the source has no matches, and may return an empty optional. * - * @param theTargetPid The Pid of the target you wish to find the matching link for. - * @return the {@link MdmLink} that contains the Match information for the target. + * @param theSourcePid The Pid of the source you wish to find the matching link for. + * @return the {@link MdmLink} that contains the Match information for the source. */ - public Optional getMatchedLinkForTargetPid(Long theTargetPid) { + public Optional getMatchedLinkForSourcePid(Long theSourcePid) { MdmLink exampleLink = myMdmLinkFactory.newMdmLink(); - exampleLink.setTargetPid(theTargetPid); + exampleLink.setSourcePid(theSourcePid); exampleLink.setMatchResult(MdmMatchResultEnum.MATCH); Example example = Example.of(exampleLink); return myMdmLinkDao.findOne(example); @@ -140,36 +140,37 @@ public class MdmLinkDaoSvc { /** * Given an IBaseResource, return its Matched {@link MdmLink}. There can only ever be at most one of these, but its possible - * the target has no matches, and may return an empty optional. + * the source has no matches, and may return an empty optional. * - * @param theTarget The IBaseResource representing the target you wish to find the matching link for. - * @return the {@link MdmLink} that contains the Match information for the target. + * @param theSourceResource The IBaseResource representing the source you wish to find the matching link for. + * @return the {@link MdmLink} that contains the Match information for the source. */ - public Optional getMatchedLinkForTarget(IBaseResource theTarget) { - Long pid = myIdHelperService.getPidOrNull(theTarget); + public Optional getMatchedLinkForSource(IBaseResource theSourceResource) { + Long pid = myIdHelperService.getPidOrNull(theSourceResource); if (pid == null) { return Optional.empty(); } MdmLink exampleLink = myMdmLinkFactory.newMdmLink(); - exampleLink.setTargetPid(pid); + exampleLink.setSourcePid(pid); exampleLink.setMatchResult(MdmMatchResultEnum.MATCH); Example example = Example.of(exampleLink); return myMdmLinkDao.findOne(example); } /** - * Given a golden resource a target and a match result, return the matching {@link MdmLink}, if it exists. + * Given a golden resource a source and a match result, return the matching {@link MdmLink}, if it exists. * * @param theGoldenResourcePid The Pid of the Golden Resource in the relationship - * @param theTargetPid The Pid of the target in the relationship + * @param theSourcePid The Pid of the source in the relationship * @param theMatchResult The MatchResult you are looking for. * @return an Optional {@link MdmLink} containing the matched link if it exists. */ - public Optional getMdmLinksByGoldenResourcePidTargetPidAndMatchResult(Long theGoldenResourcePid, Long theTargetPid, MdmMatchResultEnum theMatchResult) { + public Optional getMdmLinksByGoldenResourcePidSourcePidAndMatchResult(Long theGoldenResourcePid, + Long theSourcePid, MdmMatchResultEnum theMatchResult) { MdmLink exampleLink = myMdmLinkFactory.newMdmLink(); exampleLink.setGoldenResourcePid(theGoldenResourcePid); - exampleLink.setTargetPid(theTargetPid); + exampleLink.setSourcePid(theSourcePid); exampleLink.setMatchResult(theMatchResult); Example example = Example.of(exampleLink); return myMdmLinkDao.findOne(example); @@ -187,12 +188,12 @@ public class MdmLinkDaoSvc { return myMdmLinkDao.findAll(example); } - public Optional findMdmLinkByTarget(IBaseResource theTargetResource) { - @Nullable Long pid = myIdHelperService.getPidOrNull(theTargetResource); + public Optional findMdmLinkBySource(IBaseResource theSourceResource) { + @Nullable Long pid = myIdHelperService.getPidOrNull(theSourceResource); if (pid == null) { return Optional.empty(); } - MdmLink exampleLink = myMdmLinkFactory.newMdmLink().setTargetPid(pid); + MdmLink exampleLink = myMdmLinkFactory.newMdmLink().setSourcePid(pid); Example example = Example.of(exampleLink); return myMdmLinkDao.findOne(example); } @@ -239,11 +240,10 @@ public class MdmLinkDaoSvc { Set goldenResources = theLinks.stream().map(MdmLink::getGoldenResourcePid).collect(Collectors.toSet()); //TODO GGG this is probably invalid... we are essentially looking for GOLDEN -> GOLDEN links, which are either POSSIBLE_DUPLICATE //and REDIRECT - //goldenResources.addAll(theLinks.stream().filter(link -> "Person".equals(link.getEmpiTargetType())).map(EmpiLink::getTargetPid).collect(Collectors.toSet())); goldenResources.addAll(theLinks.stream() .filter(link -> link.getMatchResult().equals(MdmMatchResultEnum.REDIRECT) || link.getMatchResult().equals(MdmMatchResultEnum.POSSIBLE_DUPLICATE)) - .map(MdmLink::getTargetPid).collect(Collectors.toSet())); + .map(MdmLink::getSourcePid).collect(Collectors.toSet())); ourLog.info("Deleting {} MDM link records...", theLinks.size()); myMdmLinkDao.deleteAll(theLinks); ourLog.info("{} MDM link records deleted", theLinks.size()); @@ -254,12 +254,12 @@ public class MdmLinkDaoSvc { * Given a valid {@link String}, delete all {@link MdmLink} entities for that type, and get the Pids * for the Golden Resources which were the sources of the links. * - * @param theTargetType the type of relationship you would like to delete. + * @param theSourceType the type of relationship you would like to delete. * @return A list of longs representing the Pids of the Golden Resources resources used as the sources of the relationships that were deleted. */ - public List deleteAllMdmLinksOfTypeAndReturnGoldenResourcePids(String theTargetType) { + public List deleteAllMdmLinksOfTypeAndReturnGoldenResourcePids(String theSourceType) { MdmLink link = new MdmLink(); - link.setMdmTargetType(theTargetType); + link.setMdmSourceType(theSourceType); Example exampleLink = Example.of(link); List allOfType = myMdmLinkDao.findAll(exampleLink); return deleteMdmLinksAndReturnGoldenResourcePids(allOfType); @@ -291,18 +291,18 @@ public class MdmLinkDaoSvc { } /** - * Given a target {@link IBaseResource}, return all {@link MdmLink} entities in which this target is the target + * Given a source {@link IBaseResource}, return all {@link MdmLink} entities in which this source is the source * of the relationship. This will show you all links for a given Patient/Practitioner. * - * @param theTargetResource the target resource to find links for. - * @return all links for the target. + * @param theSourceResource the source resource to find links for. + * @return all links for the source. */ - public List findMdmLinksByTarget(IBaseResource theTargetResource) { - Long pid = myIdHelperService.getPidOrNull(theTargetResource); + public List findMdmLinksBySourceResource(IBaseResource theSourceResource) { + Long pid = myIdHelperService.getPidOrNull(theSourceResource); if (pid == null) { return Collections.emptyList(); } - MdmLink exampleLink = myMdmLinkFactory.newMdmLink().setTargetPid(pid); + MdmLink exampleLink = myMdmLinkFactory.newMdmLink().setSourcePid(pid); Example example = Example.of(exampleLink); return myMdmLinkDao.findAll(example); } @@ -314,7 +314,7 @@ public class MdmLinkDaoSvc { * @param theGoldenResource the source resource to find links for. * @return all links for the source. */ - public List findMdmMatchLinksBySource(IBaseResource theGoldenResource) { + public List findMdmMatchLinksByGoldenResource(IBaseResource theGoldenResource) { Long pid = myIdHelperService.getPidOrNull(theGoldenResource); if (pid == null) { return Collections.emptyList(); diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/GoldenResourceMergerSvcImpl.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/GoldenResourceMergerSvcImpl.java index 9de278f981b..7711337e54c 100644 --- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/GoldenResourceMergerSvcImpl.java +++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/GoldenResourceMergerSvcImpl.java @@ -86,31 +86,12 @@ public class GoldenResourceMergerSvcImpl implements IGoldenResourceMergerSvc { return theToGoldenResource; } - /** - * Removes non-manual links from source to target - * - * @param theFrom Target of the link - * @param theTo Source resource of the link - * @param theMdmTransactionContext Context to keep track of the deletions - */ - private void removeTargetLinks(IAnyResource theFrom, IAnyResource theTo, MdmTransactionContext theMdmTransactionContext) { - List allLinksWithTheFromAsTarget = myMdmLinkDaoSvc.findMdmLinksByGoldenResource(theFrom); - allLinksWithTheFromAsTarget - .stream() - //TODO GGG NG MDM: Why are we keeping manual links? Haven't we already copied those over in the previous merge step? - .filter(MdmLink::isAuto) // only keep manual links - .forEach(l -> { - theMdmTransactionContext.addTransactionLogMessage(String.format("Deleting link %s", l)); - myMdmLinkDaoSvc.deleteLink(l); - }); - } - private void addMergeLink(Long theGoldenResourcePidAkaActive, Long theTargetResourcePidAkaDeactivated, String theResourceType) { MdmLink mdmLink = myMdmLinkDaoSvc - .getOrCreateMdmLinkByGoldenResourcePidAndTargetResourcePid(theGoldenResourcePidAkaActive, theTargetResourcePidAkaDeactivated); + .getOrCreateMdmLinkByGoldenResourcePidAndSourceResourcePid(theGoldenResourcePidAkaActive, theTargetResourcePidAkaDeactivated); mdmLink - .setMdmTargetType(theResourceType) + .setMdmSourceType(theResourceType) .setMatchResult(MdmMatchResultEnum.REDIRECT) .setLinkSource(MdmLinkSourceEnum.MANUAL); myMdmLinkDaoSvc.save(mdmLink); @@ -137,7 +118,7 @@ public class GoldenResourceMergerSvcImpl implements IGoldenResourceMergerSvc { List toDelete = new ArrayList<>(); for (MdmLink fromLink : fromLinks) { - Optional optionalToLink = findFirstLinkWithMatchingTarget(toLinks, fromLink); + Optional optionalToLink = findFirstLinkWithMatchingSource(toLinks, fromLink); if (optionalToLink.isPresent()) { // The original links already contain this target, so move it over to the toResource @@ -151,7 +132,7 @@ public class GoldenResourceMergerSvcImpl implements IGoldenResourceMergerSvc { break; case MANUAL: if (fromLink.getMatchResult() != toLink.getMatchResult()) { - throw new InvalidRequestException("A MANUAL " + fromLink.getMatchResult() + " link may not be merged into a MANUAL " + toLink.getMatchResult() + " link for the same target"); + throw new InvalidRequestException("A MANUAL " + fromLink.getMatchResult() + " link may not be merged into a MANUAL " + toLink.getMatchResult() + " link for the same source resource"); } } } else { @@ -169,9 +150,9 @@ public class GoldenResourceMergerSvcImpl implements IGoldenResourceMergerSvc { toDelete.forEach(link -> myMdmLinkDaoSvc.deleteLink(link)); } - private Optional findFirstLinkWithMatchingTarget(List theMdmLinks, MdmLink theLinkWithTargetToMatch) { + private Optional findFirstLinkWithMatchingSource(List theMdmLinks, MdmLink theLinkWithSourceToMatch) { return theMdmLinks.stream() - .filter(mdmLink -> mdmLink.getTargetPid().equals(theLinkWithTargetToMatch.getTargetPid())) + .filter(mdmLink -> mdmLink.getSourcePid().equals(theLinkWithSourceToMatch.getSourcePid())) .findFirst(); } diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmClearSvcImpl.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmClearSvcImpl.java index b4ac6893afc..9142c517c93 100644 --- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmClearSvcImpl.java +++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmClearSvcImpl.java @@ -51,16 +51,16 @@ public class MdmClearSvcImpl implements IMdmExpungeSvc { } @Override - public long expungeAllMdmLinksOfTargetType(String theResourceType, ServletRequestDetails theRequestDetails) { - throwExceptionIfInvalidTargetType(theResourceType); - ourLog.info("Clearing all MDM Links for resource type {}...", theResourceType); - List goldenResourcePids = myMdmLinkDaoSvc.deleteAllMdmLinksOfTypeAndReturnGoldenResourcePids(theResourceType); - DeleteMethodOutcome deleteOutcome = myMdmGoldenResourceDeletingSvcImpl.expungeGoldenResourcePids(goldenResourcePids, theResourceType, theRequestDetails); + public long expungeAllMdmLinksOfSourceType(String theSourceResourceType, ServletRequestDetails theRequestDetails) { + throwExceptionIfInvalidSourceResourceType(theSourceResourceType); + ourLog.info("Clearing all MDM Links for resource type {}...", theSourceResourceType); + List goldenResourcePids = myMdmLinkDaoSvc.deleteAllMdmLinksOfTypeAndReturnGoldenResourcePids(theSourceResourceType); + DeleteMethodOutcome deleteOutcome = myMdmGoldenResourceDeletingSvcImpl.expungeGoldenResourcePids(goldenResourcePids, theSourceResourceType, theRequestDetails); ourLog.info("MDM clear operation complete. Removed {} MDM links and {} Golden Resources.", goldenResourcePids.size(), deleteOutcome.getExpungedResourcesCount()); return goldenResourcePids.size(); } - private void throwExceptionIfInvalidTargetType(String theResourceType) { + private void throwExceptionIfInvalidSourceResourceType(String theResourceType) { if (!myMdmSettings.isSupportedMdmType(theResourceType)) { throw new InvalidRequestException(ProviderConstants.MDM_CLEAR + " does not support resource type: " + theResourceType); } diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmControllerSvcImpl.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmControllerSvcImpl.java index 20b24aaec8b..ffd93ef3fa9 100644 --- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmControllerSvcImpl.java +++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmControllerSvcImpl.java @@ -65,13 +65,13 @@ public class MdmControllerSvcImpl implements IMdmControllerSvc { } @Override - public Stream queryLinks(@Nullable String theGoldenResourceId, @Nullable String theTargetId, @Nullable String theMatchResult, @Nullable String theLinkSource, MdmTransactionContext theMdmTransactionContext) { + public Stream queryLinks(@Nullable String theGoldenResourceId, @Nullable String theSourceResourceId, @Nullable String theMatchResult, @Nullable String theLinkSource, MdmTransactionContext theMdmTransactionContext) { IIdType goldenResourceId = MdmControllerUtil.extractGoldenResourceIdDtOrNull(ProviderConstants.MDM_QUERY_LINKS_GOLDEN_RESOURCE_ID, theGoldenResourceId); - IIdType targetId = MdmControllerUtil.extractTargetIdDtOrNull(ProviderConstants.MDM_QUERY_LINKS_RESOURCE_ID, theTargetId); + IIdType sourceId = MdmControllerUtil.extractSourceIdDtOrNull(ProviderConstants.MDM_QUERY_LINKS_RESOURCE_ID, theSourceResourceId); MdmMatchResultEnum matchResult = MdmControllerUtil.extractMatchResultOrNull(theMatchResult); MdmLinkSourceEnum linkSource = MdmControllerUtil.extractLinkSourceOrNull(theLinkSource); - return myMdmLinkQuerySvc.queryLinks(goldenResourceId, targetId, matchResult, linkSource, theMdmTransactionContext); + return myMdmLinkQuerySvc.queryLinks(goldenResourceId, sourceId, matchResult, linkSource, theMdmTransactionContext); } @Override @@ -80,14 +80,14 @@ public class MdmControllerSvcImpl implements IMdmControllerSvc { } @Override - public IAnyResource updateLink(String theGoldenResourceId, String theTargetId, String theMatchResult, MdmTransactionContext theMdmTransactionContext) { + public IAnyResource updateLink(String theGoldenResourceId, String theSourceResourceId, String theMatchResult, MdmTransactionContext theMdmTransactionContext) { MdmMatchResultEnum matchResult = MdmControllerUtil.extractMatchResultOrNull(theMatchResult); IAnyResource goldenResource = myMdmControllerHelper.getLatestGoldenResourceFromIdOrThrowException(ProviderConstants.MDM_UPDATE_LINK_GOLDEN_RESOURCE_ID, theGoldenResourceId); - IAnyResource target = myMdmControllerHelper.getLatestTargetFromIdOrThrowException(ProviderConstants.MDM_UPDATE_LINK_RESOURCE_ID, theTargetId); + IAnyResource source = myMdmControllerHelper.getLatestSourceFromIdOrThrowException(ProviderConstants.MDM_UPDATE_LINK_RESOURCE_ID, theSourceResourceId); myMdmControllerHelper.validateSameVersion(goldenResource, theGoldenResourceId); - myMdmControllerHelper.validateSameVersion(target, theTargetId); + myMdmControllerHelper.validateSameVersion(source, theSourceResourceId); - return myIMdmLinkUpdaterSvc.updateLink(goldenResource, target, matchResult, theMdmTransactionContext); + return myIMdmLinkUpdaterSvc.updateLink(goldenResource, source, matchResult, theMdmTransactionContext); } @Override diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmEidUpdateService.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmEidUpdateService.java index 527a4f5b441..70bd9a756e5 100644 --- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmEidUpdateService.java +++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmEidUpdateService.java @@ -85,7 +85,7 @@ public class MdmEidUpdateService { // the user is simply updating their EID. We propagate this change to the GoldenResource. //overwrite. No EIDS in common, but still same GoldenResource. if (myMdmSettings.isPreventMultipleEids()) { - if (myMdmLinkDaoSvc.findMdmMatchLinksBySource(theUpdateContext.getMatchedGoldenResource()).size() <= 1) { // If there is only 0/1 link on the GoldenResource, we can safely overwrite the EID. + if (myMdmLinkDaoSvc.findMdmMatchLinksByGoldenResource(theUpdateContext.getMatchedGoldenResource()).size() <= 1) { // If there is only 0/1 link on the GoldenResource, we can safely overwrite the EID. handleExternalEidOverwrite(theUpdateContext.getMatchedGoldenResource(), theResource, theMdmTransactionContext); } else { // If the GoldenResource has multiple targets tied to it, we can't just overwrite the EID, so we split the GoldenResource. createNewGoldenResourceAndFlagAsDuplicate(theResource, theMdmTransactionContext, theUpdateContext.getExistingGoldenResource()); @@ -109,7 +109,7 @@ public class MdmEidUpdateService { private void createNewGoldenResourceAndFlagAsDuplicate(IAnyResource theResource, MdmTransactionContext theMdmTransactionContext, IAnyResource theOldGoldenResource) { log(theMdmTransactionContext, "Duplicate detected based on the fact that both resources have different external EIDs."); - IAnyResource newGoldenResource = myGoldenResourceHelper.createGoldenResourceFromMdmTarget(theResource); + IAnyResource newGoldenResource = myGoldenResourceHelper.createGoldenResourceFromMdmSourceResource(theResource); myMdmLinkSvc.updateLink(newGoldenResource, theResource, MdmMatchOutcome.NEW_GOLDEN_RESOURCE_MATCH, MdmLinkSourceEnum.AUTO, theMdmTransactionContext); myMdmLinkSvc.updateLink(newGoldenResource, theOldGoldenResource, MdmMatchOutcome.POSSIBLE_DUPLICATE, MdmLinkSourceEnum.AUTO, theMdmTransactionContext); @@ -150,7 +150,7 @@ public class MdmEidUpdateService { myHasEidsInCommon = myEIDHelper.hasEidOverlap(myMatchedGoldenResource, theResource); myIncomingResourceHasAnEid = !myEIDHelper.getExternalEid(theResource).isEmpty(); - Optional theExistingMatchLink = myMdmLinkDaoSvc.getMatchedLinkForTarget(theResource); + Optional theExistingMatchLink = myMdmLinkDaoSvc.getMatchedLinkForSource(theResource); myExistingGoldenResource = null; if (theExistingMatchLink.isPresent()) { diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmLinkQuerySvcImpl.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmLinkQuerySvcImpl.java index ff21f141206..6de2be07136 100644 --- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmLinkQuerySvcImpl.java +++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmLinkQuerySvcImpl.java @@ -37,6 +37,7 @@ import org.springframework.data.domain.Example; import java.util.stream.Stream; public class MdmLinkQuerySvcImpl implements IMdmLinkQuerySvc { + private static final Logger ourLog = LoggerFactory.getLogger(MdmLinkQuerySvcImpl.class); @Autowired @@ -45,8 +46,8 @@ public class MdmLinkQuerySvcImpl implements IMdmLinkQuerySvc { MdmLinkDaoSvc myMdmLinkDaoSvc; @Override - public Stream queryLinks(IIdType theGoldenResourceId, IIdType theTargetId, MdmMatchResultEnum theMatchResult, MdmLinkSourceEnum theLinkSource, MdmTransactionContext theMdmContext) { - Example exampleLink = exampleLinkFromParameters(theGoldenResourceId, theTargetId, theMatchResult, theLinkSource); + public Stream queryLinks(IIdType theGoldenResourceId, IIdType theSourceResourceId, MdmMatchResultEnum theMatchResult, MdmLinkSourceEnum theLinkSource, MdmTransactionContext theMdmContext) { + Example exampleLink = exampleLinkFromParameters(theGoldenResourceId, theSourceResourceId, theMatchResult, theLinkSource); return myMdmLinkDaoSvc.findMdmLinkByExample(exampleLink).stream() .filter(mdmLink -> mdmLink.getMatchResult() != MdmMatchResultEnum.POSSIBLE_DUPLICATE) .map(this::toJson); @@ -60,15 +61,15 @@ public class MdmLinkQuerySvcImpl implements IMdmLinkQuerySvc { private MdmLinkJson toJson(MdmLink theLink) { MdmLinkJson retval = new MdmLinkJson(); - String targetId = myIdHelperService.resourceIdFromPidOrThrowException(theLink.getTargetPid()).toVersionless().getValue(); - retval.setTargetId(targetId); + String sourceId = myIdHelperService.resourceIdFromPidOrThrowException(theLink.getSourcePid()).toVersionless().getValue(); + retval.setSourceId(sourceId); String goldenResourceId = myIdHelperService.resourceIdFromPidOrThrowException(theLink.getGoldenResourcePid()).toVersionless().getValue(); retval.setGoldenResourceId(goldenResourceId); retval.setCreated(theLink.getCreated()); retval.setEidMatch(theLink.getEidMatch()); retval.setLinkSource(theLink.getLinkSource()); retval.setMatchResult(theLink.getMatchResult()); - retval.setLinkCreatedNewResource(theLink.getHadToCreateNewResource()); + retval.setLinkCreatedNewResource(theLink.getHadToCreateNewGoldenResource()); retval.setScore(theLink.getScore()); retval.setUpdated(theLink.getUpdated()); retval.setVector(theLink.getVector()); @@ -76,13 +77,13 @@ public class MdmLinkQuerySvcImpl implements IMdmLinkQuerySvc { return retval; } - private Example exampleLinkFromParameters(IIdType theGoldenResourceId, IIdType theTargetId, MdmMatchResultEnum theMatchResult, MdmLinkSourceEnum theLinkSource) { + private Example exampleLinkFromParameters(IIdType theGoldenResourceId, IIdType theSourceId, MdmMatchResultEnum theMatchResult, MdmLinkSourceEnum theLinkSource) { MdmLink mdmLink = myMdmLinkDaoSvc.newMdmLink(); if (theGoldenResourceId != null) { mdmLink.setGoldenResourcePid(myIdHelperService.getPidOrThrowException(theGoldenResourceId)); } - if (theTargetId != null) { - mdmLink.setTargetPid(myIdHelperService.getPidOrThrowException(theTargetId)); + if (theSourceId != null) { + mdmLink.setSourcePid(myIdHelperService.getPidOrThrowException(theSourceId)); } if (theMatchResult != null) { mdmLink.setMatchResult(theMatchResult); diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmLinkSvcImpl.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmLinkSvcImpl.java index b860c9df8d7..4758868bdb5 100644 --- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmLinkSvcImpl.java +++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmLinkSvcImpl.java @@ -40,7 +40,7 @@ import javax.transaction.Transactional; import java.util.Optional; /** - * This class is in charge of managing MdmLinks between Golden Resources and target resources + * This class is in charge of managing MdmLinks between Golden Resources and source resources */ @Service public class MdmLinkSvcImpl implements IMdmLinkSvc { @@ -56,36 +56,36 @@ public class MdmLinkSvcImpl implements IMdmLinkSvc { @Override @Transactional - public void updateLink(IAnyResource theGoldenResource, IAnyResource theTarget, MdmMatchOutcome theMatchOutcome, MdmLinkSourceEnum theLinkSource, MdmTransactionContext theMdmTransactionContext) { - if (theMatchOutcome.isPossibleDuplicate() && goldenResourceLinkedAsNoMatch(theGoldenResource, theTarget)) { + public void updateLink(IAnyResource theGoldenResource, IAnyResource theSourceResource, MdmMatchOutcome theMatchOutcome, MdmLinkSourceEnum theLinkSource, MdmTransactionContext theMdmTransactionContext) { + if (theMatchOutcome.isPossibleDuplicate() && goldenResourceLinkedAsNoMatch(theGoldenResource, theSourceResource)) { log(theMdmTransactionContext, theGoldenResource.getIdElement().toUnqualifiedVersionless() + " is linked as NO_MATCH with " + - theTarget.getIdElement().toUnqualifiedVersionless() + + theSourceResource.getIdElement().toUnqualifiedVersionless() + " not linking as POSSIBLE_DUPLICATE."); return; } MdmMatchResultEnum matchResultEnum = theMatchOutcome.getMatchResultEnum(); - validateRequestIsLegal(theGoldenResource, theTarget, matchResultEnum, theLinkSource); + validateRequestIsLegal(theGoldenResource, theSourceResource, matchResultEnum, theLinkSource); myMdmResourceDaoSvc.upsertGoldenResource(theGoldenResource, theMdmTransactionContext.getResourceType()); - createOrUpdateLinkEntity(theGoldenResource, theTarget, theMatchOutcome, theLinkSource, theMdmTransactionContext); + createOrUpdateLinkEntity(theGoldenResource, theSourceResource, theMatchOutcome, theLinkSource, theMdmTransactionContext); } - private boolean goldenResourceLinkedAsNoMatch(IAnyResource theGoldenResource, IAnyResource theTarget) { + private boolean goldenResourceLinkedAsNoMatch(IAnyResource theGoldenResource, IAnyResource theSourceResource) { Long goldenResourceId = myIdHelperService.getPidOrThrowException(theGoldenResource); - Long targetId = myIdHelperService.getPidOrThrowException(theTarget); + Long sourceId = myIdHelperService.getPidOrThrowException(theSourceResource); // TODO perf collapse into one query - return myMdmLinkDaoSvc.getMdmLinksByGoldenResourcePidTargetPidAndMatchResult(goldenResourceId, targetId, MdmMatchResultEnum.NO_MATCH).isPresent() || - myMdmLinkDaoSvc.getMdmLinksByGoldenResourcePidTargetPidAndMatchResult(targetId, goldenResourceId, MdmMatchResultEnum.NO_MATCH).isPresent(); + return myMdmLinkDaoSvc.getMdmLinksByGoldenResourcePidSourcePidAndMatchResult(goldenResourceId, sourceId, MdmMatchResultEnum.NO_MATCH).isPresent() || + myMdmLinkDaoSvc.getMdmLinksByGoldenResourcePidSourcePidAndMatchResult(sourceId, goldenResourceId, MdmMatchResultEnum.NO_MATCH).isPresent(); } @Override - public void deleteLink(IAnyResource theGoldenResource, IAnyResource theTargetResource, MdmTransactionContext theMdmTransactionContext) { - Optional optionalMdmLink = getMdmLinkForGoldenResourceTargetPair(theGoldenResource, theTargetResource); + public void deleteLink(IAnyResource theGoldenResource, IAnyResource theSourceResource, MdmTransactionContext theMdmTransactionContext) { + Optional optionalMdmLink = getMdmLinkForGoldenResourceSourceResourcePair(theGoldenResource, theSourceResource); if (optionalMdmLink.isPresent()) { MdmLink mdmLink = optionalMdmLink.get(); - log(theMdmTransactionContext, "Deleting MdmLink [" + theGoldenResource.getIdElement().toVersionless() + " -> " + theTargetResource.getIdElement().toVersionless() + "] with result: " + mdmLink.getMatchResult()); + log(theMdmTransactionContext, "Deleting MdmLink [" + theGoldenResource.getIdElement().toVersionless() + " -> " + theSourceResource.getIdElement().toVersionless() + "] with result: " + mdmLink.getMatchResult()); myMdmLinkDaoSvc.deleteLink(mdmLink); } } @@ -94,7 +94,7 @@ public class MdmLinkSvcImpl implements IMdmLinkSvc { * Helper function which runs various business rules about what types of requests are allowed. */ private void validateRequestIsLegal(IAnyResource theGoldenResource, IAnyResource theResource, MdmMatchResultEnum theMatchResult, MdmLinkSourceEnum theLinkSource) { - Optional oExistingLink = getMdmLinkForGoldenResourceTargetPair(theGoldenResource, theResource); + Optional oExistingLink = getMdmLinkForGoldenResourceSourceResourcePair(theGoldenResource, theResource); if (oExistingLink.isPresent() && systemIsAttemptingToModifyManualLink(theLinkSource, oExistingLink.get())) { throw new InternalErrorException("MDM system is not allowed to modify links on manually created links"); } @@ -118,19 +118,19 @@ public class MdmLinkSvcImpl implements IMdmLinkSvc { return theIncomingSource == MdmLinkSourceEnum.AUTO && theExistingSource.isManual(); } - private Optional getMdmLinkForGoldenResourceTargetPair(IAnyResource theGoldenResource, IAnyResource theCandidate) { + private Optional getMdmLinkForGoldenResourceSourceResourcePair(IAnyResource theGoldenResource, IAnyResource theCandidate) { if (theGoldenResource.getIdElement().getIdPart() == null || theCandidate.getIdElement().getIdPart() == null) { return Optional.empty(); } else { - return myMdmLinkDaoSvc.getLinkByGoldenResourcePidAndTargetResourcePid( + return myMdmLinkDaoSvc.getLinkByGoldenResourcePidAndSourceResourcePid( myIdHelperService.getPidOrNull(theGoldenResource), myIdHelperService.getPidOrNull(theCandidate) ); } } - private void createOrUpdateLinkEntity(IBaseResource theGoldenResource, IBaseResource theTargetResource, MdmMatchOutcome theMatchOutcome, MdmLinkSourceEnum theLinkSource, MdmTransactionContext theMdmTransactionContext) { - myMdmLinkDaoSvc.createOrUpdateLinkEntity(theGoldenResource, theTargetResource, theMatchOutcome, theLinkSource, theMdmTransactionContext); + private void createOrUpdateLinkEntity(IBaseResource theGoldenResource, IBaseResource theSourceResource, MdmMatchOutcome theMatchOutcome, MdmLinkSourceEnum theLinkSource, MdmTransactionContext theMdmTransactionContext) { + myMdmLinkDaoSvc.createOrUpdateLinkEntity(theGoldenResource, theSourceResource, theMatchOutcome, theLinkSource, theMdmTransactionContext); } private void log(MdmTransactionContext theMdmTransactionContext, String theMessage) { diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmLinkUpdaterSvcImpl.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmLinkUpdaterSvcImpl.java index 5d6c2cf1fcf..65d09bd3a1c 100644 --- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmLinkUpdaterSvcImpl.java +++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmLinkUpdaterSvcImpl.java @@ -66,38 +66,38 @@ public class MdmLinkUpdaterSvcImpl implements IMdmLinkUpdaterSvc { @Transactional @Override - public IAnyResource updateLink(IAnyResource theGoldenResource, IAnyResource theTarget, MdmMatchResultEnum theMatchResult, MdmTransactionContext theMdmContext) { - String targetType = myFhirContext.getResourceType(theTarget); + public IAnyResource updateLink(IAnyResource theGoldenResource, IAnyResource theSourceResource, MdmMatchResultEnum theMatchResult, MdmTransactionContext theMdmContext) { + String sourceType = myFhirContext.getResourceType(theSourceResource); - validateUpdateLinkRequest(theGoldenResource, theTarget, theMatchResult, targetType); + validateUpdateLinkRequest(theGoldenResource, theSourceResource, theMatchResult, sourceType); Long goldenResourceId = myIdHelperService.getPidOrThrowException(theGoldenResource); - Long targetId = myIdHelperService.getPidOrThrowException(theTarget); + Long targetId = myIdHelperService.getPidOrThrowException(theSourceResource); - Optional optionalMdmLink = myMdmLinkDaoSvc.getLinkByGoldenResourcePidAndTargetResourcePid(goldenResourceId, targetId); + Optional optionalMdmLink = myMdmLinkDaoSvc.getLinkByGoldenResourcePidAndSourceResourcePid(goldenResourceId, targetId); if (!optionalMdmLink.isPresent()) { - throw new InvalidRequestException(myMessageHelper.getMessageForNoLink(theGoldenResource, theTarget)); + throw new InvalidRequestException(myMessageHelper.getMessageForNoLink(theGoldenResource, theSourceResource)); } MdmLink mdmLink = optionalMdmLink.get(); if (mdmLink.getMatchResult() == theMatchResult) { - ourLog.warn("MDM Link for " + theGoldenResource.getIdElement().toVersionless() + ", " + theTarget.getIdElement().toVersionless() + " already has value " + theMatchResult + ". Nothing to do."); + ourLog.warn("MDM Link for " + theGoldenResource.getIdElement().toVersionless() + ", " + theSourceResource.getIdElement().toVersionless() + " already has value " + theMatchResult + ". Nothing to do."); return theGoldenResource; } - ourLog.info("Manually updating MDM Link for " + theGoldenResource.getIdElement().toVersionless() + ", " + theTarget.getIdElement().toVersionless() + " from " + mdmLink.getMatchResult() + " to " + theMatchResult + "."); + ourLog.info("Manually updating MDM Link for " + theGoldenResource.getIdElement().toVersionless() + ", " + theSourceResource.getIdElement().toVersionless() + " from " + mdmLink.getMatchResult() + " to " + theMatchResult + "."); mdmLink.setMatchResult(theMatchResult); mdmLink.setLinkSource(MdmLinkSourceEnum.MANUAL); myMdmLinkDaoSvc.save(mdmLink); myMdmResourceDaoSvc.upsertGoldenResource(theGoldenResource, theMdmContext.getResourceType()); if (theMatchResult == MdmMatchResultEnum.NO_MATCH) { // Need to find a new Golden Resource to link this target to - myMdmMatchLinkSvc.updateMdmLinksForMdmTarget(theTarget, theMdmContext); + myMdmMatchLinkSvc.updateMdmLinksForMdmSource(theSourceResource, theMdmContext); } return theGoldenResource; } - private void validateUpdateLinkRequest(IAnyResource theGoldenRecord, IAnyResource theTarget, MdmMatchResultEnum theMatchResult, String theTargetType) { + private void validateUpdateLinkRequest(IAnyResource theGoldenRecord, IAnyResource theSourceResource, MdmMatchResultEnum theMatchResult, String theSourceType) { String goldenRecordType = myFhirContext.getResourceType(theGoldenRecord); if (theMatchResult != MdmMatchResultEnum.NO_MATCH && @@ -109,39 +109,39 @@ public class MdmLinkUpdaterSvcImpl implements IMdmLinkUpdaterSvc { throw new InvalidRequestException(myMessageHelper.getMessageForUnsupportedFirstArgumentTypeInUpdate(goldenRecordType)); } - if (!myMdmSettings.isSupportedMdmType(theTargetType)) { - throw new InvalidRequestException(myMessageHelper.getMessageForUnsupportedSecondArgumentTypeInUpdate(theTargetType)); + if (!myMdmSettings.isSupportedMdmType(theSourceType)) { + throw new InvalidRequestException(myMessageHelper.getMessageForUnsupportedSecondArgumentTypeInUpdate(theSourceType)); } - if (!Objects.equals(goldenRecordType, theTargetType)) { - throw new InvalidRequestException(myMessageHelper.getMessageForArgumentTypeMismatchInUpdate(goldenRecordType, theTargetType)); + if (!Objects.equals(goldenRecordType, theSourceType)) { + throw new InvalidRequestException(myMessageHelper.getMessageForArgumentTypeMismatchInUpdate(goldenRecordType, theSourceType)); } if (!MdmUtil.isMdmManaged(theGoldenRecord)) { throw new InvalidRequestException(myMessageHelper.getMessageForUnmanagedResource()); } - if (!MdmUtil.isMdmAllowed(theTarget)) { - throw new InvalidRequestException(myMessageHelper.getMessageForUnsupportedTarget()); + if (!MdmUtil.isMdmAllowed(theSourceResource)) { + throw new InvalidRequestException(myMessageHelper.getMessageForUnsupportedSourceResource()); } } @Transactional @Override - public void notDuplicateGoldenResource(IAnyResource theGoldenResource, IAnyResource theTarget, MdmTransactionContext theMdmContext) { - validateNotDuplicateGoldenResourceRequest(theGoldenResource, theTarget); + public void notDuplicateGoldenResource(IAnyResource theGoldenResource, IAnyResource theTargetGoldenResource, MdmTransactionContext theMdmContext) { + validateNotDuplicateGoldenResourceRequest(theGoldenResource, theTargetGoldenResource); Long goldenResourceId = myIdHelperService.getPidOrThrowException(theGoldenResource); - Long targetId = myIdHelperService.getPidOrThrowException(theTarget); + Long targetId = myIdHelperService.getPidOrThrowException(theTargetGoldenResource); - Optional oMdmLink = myMdmLinkDaoSvc.getLinkByGoldenResourcePidAndTargetResourcePid(goldenResourceId, targetId); + Optional oMdmLink = myMdmLinkDaoSvc.getLinkByGoldenResourcePidAndSourceResourcePid(goldenResourceId, targetId); if (!oMdmLink.isPresent()) { - throw new InvalidRequestException("No link exists between " + theGoldenResource.getIdElement().toVersionless() + " and " + theTarget.getIdElement().toVersionless()); + throw new InvalidRequestException("No link exists between " + theGoldenResource.getIdElement().toVersionless() + " and " + theTargetGoldenResource.getIdElement().toVersionless()); } MdmLink mdmLink = oMdmLink.get(); if (!mdmLink.isPossibleDuplicate()) { - throw new InvalidRequestException(theGoldenResource.getIdElement().toVersionless() + " and " + theTarget.getIdElement().toVersionless() + " are not linked as POSSIBLE_DUPLICATE."); + throw new InvalidRequestException(theGoldenResource.getIdElement().toVersionless() + " and " + theTargetGoldenResource.getIdElement().toVersionless() + " are not linked as POSSIBLE_DUPLICATE."); } mdmLink.setMatchResult(MdmMatchResultEnum.NO_MATCH); mdmLink.setLinkSource(MdmLinkSourceEnum.MANUAL); diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchFinderSvcImpl.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchFinderSvcImpl.java index 22258c6c01d..3696fd6626f 100644 --- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchFinderSvcImpl.java +++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchFinderSvcImpl.java @@ -22,9 +22,11 @@ package ca.uhn.fhir.jpa.mdm.svc; import ca.uhn.fhir.mdm.api.IMdmMatchFinderSvc; import ca.uhn.fhir.mdm.api.MatchedTarget; +import ca.uhn.fhir.mdm.log.Logs; import ca.uhn.fhir.mdm.rules.svc.MdmResourceMatcherSvc; import ca.uhn.fhir.jpa.mdm.svc.candidate.MdmCandidateSearchSvc; import org.hl7.fhir.instance.model.api.IAnyResource; +import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -36,6 +38,8 @@ import java.util.stream.Collectors; @Service public class MdmMatchFinderSvcImpl implements IMdmMatchFinderSvc { + private static final Logger ourLog = Logs.getMdmTroubleshootingLog(); + @Autowired private MdmCandidateSearchSvc myMdmCandidateSearchSvc; @Autowired @@ -46,9 +50,12 @@ public class MdmMatchFinderSvcImpl implements IMdmMatchFinderSvc { public List getMatchedTargets(String theResourceType, IAnyResource theResource) { Collection targetCandidates = myMdmCandidateSearchSvc.findCandidates(theResourceType, theResource); - return targetCandidates.stream() + List matches = targetCandidates.stream() .map(candidate -> new MatchedTarget(candidate, myMdmResourceMatcherSvc.getMatchResult(theResource, candidate))) .collect(Collectors.toList()); + + ourLog.info("Found {} matched targets for {}", matches.size(), theResourceType); + return matches; } } diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvc.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvc.java index aba04bda3e8..37edd7fed6f 100644 --- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvc.java +++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvc.java @@ -41,8 +41,8 @@ import java.util.List; /** * MdmMatchLinkSvc is the entrypoint for HAPI's MDM system. An incoming resource can call - * updateMdmLinksForMdmTarget and the underlying MDM system will take care of matching it to a GoldenResource, or creating a - * new GoldenResource if a suitable one was not found. + * updateMdmLinksForMdmSource and the underlying MDM system will take care of matching it to a GoldenResource, + * or creating a new GoldenResource if a suitable one was not found. */ @Service public class MdmMatchLinkSvc { @@ -58,15 +58,15 @@ public class MdmMatchLinkSvc { private MdmEidUpdateService myEidUpdateService; /** - * Given an MDM Target (consisting of either a Patient or a Practitioner), find a suitable Golden Resource candidate for them, + * Given an MDM source (consisting of any supported MDM type), find a suitable Golden Resource candidate for them, * or create one if one does not exist. Performs matching based on rules defined in mdm-rules.json. * Does nothing if resource is determined to be not managed by MDM. * - * @param theResource the incoming MDM target, which can be any supported MDM type. + * @param theResource the incoming MDM source, which can be any supported MDM type. * @param theMdmTransactionContext * @return an {@link TransactionLogMessages} which contains all informational messages related to MDM processing of this resource. */ - public MdmTransactionContext updateMdmLinksForMdmTarget(IAnyResource theResource, MdmTransactionContext theMdmTransactionContext) { + public MdmTransactionContext updateMdmLinksForMdmSource(IAnyResource theResource, MdmTransactionContext theMdmTransactionContext) { if (MdmUtil.isMdmAllowed(theResource)) { return doMdmUpdate(theResource, theMdmTransactionContext); } else { @@ -122,30 +122,29 @@ public class MdmMatchLinkSvc { private void handleMdmWithNoCandidates(IAnyResource theResource, MdmTransactionContext theMdmTransactionContext) { log(theMdmTransactionContext, String.format("There were no matched candidates for MDM, creating a new %s.", theResource.getIdElement().getResourceType())); - IAnyResource newGoldenResource = myGoldenResourceHelper.createGoldenResourceFromMdmTarget(theResource); + IAnyResource newGoldenResource = myGoldenResourceHelper.createGoldenResourceFromMdmSourceResource(theResource); // TODO GGG :) // 1. Get the right helper - // 2. Create source resoruce for the MDM target + // 2. Create source resource for the MDM source // 3. UPDATE MDM LINK TABLE - myMdmLinkSvc.updateLink(newGoldenResource, theResource, MdmMatchOutcome.NEW_GOLDEN_RESOURCE_MATCH, MdmLinkSourceEnum.AUTO, theMdmTransactionContext); } - private void handleMdmCreate(IAnyResource theTargetResource, MatchedGoldenResourceCandidate theGoldenResourceCandidate, MdmTransactionContext theMdmTransactionContext) { + private void handleMdmCreate(IAnyResource theSourceResource, MatchedGoldenResourceCandidate theGoldenResourceCandidate, MdmTransactionContext theMdmTransactionContext) { log(theMdmTransactionContext, "MDM has narrowed down to one candidate for matching."); IAnyResource golenResource = myMdmGoldenResourceFindingSvc.getGoldenResourceFromMatchedGoldenResourceCandidate(theGoldenResourceCandidate, theMdmTransactionContext.getResourceType()); - if (myGoldenResourceHelper.isPotentialDuplicate(golenResource, theTargetResource)) { + if (myGoldenResourceHelper.isPotentialDuplicate(golenResource, theSourceResource)) { log(theMdmTransactionContext, "Duplicate detected based on the fact that both resources have different external EIDs."); - IAnyResource newGoldenResource = myGoldenResourceHelper.createGoldenResourceFromMdmTarget(theTargetResource); - myMdmLinkSvc.updateLink(newGoldenResource, theTargetResource, MdmMatchOutcome.NEW_GOLDEN_RESOURCE_MATCH, MdmLinkSourceEnum.AUTO, theMdmTransactionContext); + IAnyResource newGoldenResource = myGoldenResourceHelper.createGoldenResourceFromMdmSourceResource(theSourceResource); + myMdmLinkSvc.updateLink(newGoldenResource, theSourceResource, MdmMatchOutcome.NEW_GOLDEN_RESOURCE_MATCH, MdmLinkSourceEnum.AUTO, theMdmTransactionContext); myMdmLinkSvc.updateLink(newGoldenResource, golenResource, MdmMatchOutcome.POSSIBLE_DUPLICATE, MdmLinkSourceEnum.AUTO, theMdmTransactionContext); } else { if (theGoldenResourceCandidate.isMatch()) { - myGoldenResourceHelper.handleExternalEidAddition(golenResource, theTargetResource, theMdmTransactionContext); + myGoldenResourceHelper.handleExternalEidAddition(golenResource, theSourceResource, theMdmTransactionContext); //TODO MDM GGG/NG: eventually we need to add survivorship rules of attributes here. Currently no data is copied over except EIDs. } - myMdmLinkSvc.updateLink(golenResource, theTargetResource, theGoldenResourceCandidate.getMatchResult(), MdmLinkSourceEnum.AUTO, theMdmTransactionContext); + myMdmLinkSvc.updateLink(golenResource, theSourceResource, theGoldenResourceCandidate.getMatchResult(), MdmLinkSourceEnum.AUTO, theMdmTransactionContext); } } diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmSearchParamSvc.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmSearchParamSvc.java index e5c599913ef..b8a53004eef 100644 --- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmSearchParamSvc.java +++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmSearchParamSvc.java @@ -72,27 +72,27 @@ public class MdmSearchParamSvc implements ISearchParamRetriever { } /** - * Given a target type, and a criteria string of the shape name=x&birthDate=y, generate a {@link SearchParameterMap} + * Given a source type, and a criteria string of the shape name=x&birthDate=y, generate a {@link SearchParameterMap} * that represents this query. * - * @param theTargetType the resource type to execute the search on + * @param theSourceType the resource type to execute the search on * @param theCriteria the string search criteria. * * @return the generated SearchParameterMap, or an empty one if there is no criteria. */ - public SearchParameterMap getSearchParameterMapFromCriteria(String theTargetType, @Nullable String theCriteria) { + public SearchParameterMap getSearchParameterMapFromCriteria(String theSourceType, @Nullable String theCriteria) { SearchParameterMap spMap; if (StringUtils.isBlank(theCriteria)) { spMap = new SearchParameterMap(); } else { - spMap = mapFromCriteria(theTargetType, theCriteria); + spMap = mapFromCriteria(theSourceType, theCriteria); } return spMap; } - public ISearchBuilder generateSearchBuilderForType(String theTargetType) { - IFhirResourceDao resourceDao = myDaoRegistry.getResourceDao(theTargetType); - return mySearchBuilderFactory.newSearchBuilder(resourceDao, theTargetType, resourceDao.getResourceType()); + public ISearchBuilder generateSearchBuilderForType(String theSourceType) { + IFhirResourceDao resourceDao = myDaoRegistry.getResourceDao(theSourceType); + return mySearchBuilderFactory.newSearchBuilder(resourceDao, theSourceType, resourceDao.getResourceType()); } /** diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmSubmitSvcImpl.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmSubmitSvcImpl.java index b38f1cbcd2d..d38a0a11630 100644 --- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmSubmitSvcImpl.java +++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmSubmitSvcImpl.java @@ -69,9 +69,9 @@ public class MdmSubmitSvcImpl implements IMdmSubmitSvc { @Override @Transactional - public long submitAllTargetTypesToMdm(@Nullable String theCriteria) { + public long submitAllSourceTypesToMdm(@Nullable String theCriteria) { long submittedCount = myMdmSettings.getMdmRules().getMdmTypes().stream() - .mapToLong(targetType -> submitTargetTypeToMdm(targetType, theCriteria)) + .mapToLong(type -> submitSourceResourceTypeToMdm(type, theCriteria)) .sum(); return submittedCount; @@ -79,17 +79,17 @@ public class MdmSubmitSvcImpl implements IMdmSubmitSvc { @Override @Transactional - public long submitTargetTypeToMdm(String theTargetType, @Nullable String theCriteria) { + public long submitSourceResourceTypeToMdm(String theSourceResourceType, @Nullable String theCriteria) { if (theCriteria == null) { - ourLog.info("Submitting all resources of type {} to MDM", theTargetType); + ourLog.info("Submitting all resources of type {} to MDM", theSourceResourceType); } else { - ourLog.info("Submitting resources of type {} with criteria {} to MDM", theTargetType, theCriteria); + ourLog.info("Submitting resources of type {} with criteria {} to MDM", theSourceResourceType, theCriteria); } - validateTargetType(theTargetType); - SearchParameterMap spMap = myMdmSearchParamSvc.getSearchParameterMapFromCriteria(theTargetType, theCriteria); + validateSourceType(theSourceResourceType); + SearchParameterMap spMap = myMdmSearchParamSvc.getSearchParameterMapFromCriteria(theSourceResourceType, theCriteria); spMap.setLoadSynchronousUpTo(BUFFER_SIZE); - ISearchBuilder searchBuilder = myMdmSearchParamSvc.generateSearchBuilderForType(theTargetType); + ISearchBuilder searchBuilder = myMdmSearchParamSvc.generateSearchBuilderForType(theSourceResourceType); return submitAllMatchingResourcesToMdmChannel(spMap, searchBuilder); } @@ -130,19 +130,19 @@ public class MdmSubmitSvcImpl implements IMdmSubmitSvc { @Override @Transactional public long submitPractitionerTypeToMdm(@Nullable String theCriteria) { - return submitTargetTypeToMdm("Practitioner", theCriteria); + return submitSourceResourceTypeToMdm("Practitioner", theCriteria); } @Override @Transactional public long submitPatientTypeToMdm(@Nullable String theCriteria) { - return submitTargetTypeToMdm("Patient", theCriteria); + return submitSourceResourceTypeToMdm("Patient", theCriteria); } @Override @Transactional - public long submitTargetToMdm(IIdType theId) { - validateTargetType(theId.getResourceType()); + public long submitSourceResourceToMdm(IIdType theId) { + validateSourceType(theId.getResourceType()); IFhirResourceDao resourceDao = myDaoRegistry.getResourceDao(theId.getResourceType()); IBaseResource read = resourceDao.read(theId); myMdmChannelSubmitterSvc.submitResourceToMdmChannel(read); @@ -154,7 +154,7 @@ public class MdmSubmitSvcImpl implements IMdmSubmitSvc { myMdmSettings = theMdmSettings; } - private void validateTargetType(String theResourceType) { + private void validateSourceType(String theResourceType) { if(!myMdmSettings.getMdmRules().getMdmTypes().contains(theResourceType)) { throw new InvalidRequestException(ProviderConstants.OPERATION_MDM_SUBMIT + " does not support resource type: " + theResourceType); } diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/candidate/CandidateStrategyEnum.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/candidate/CandidateStrategyEnum.java index 8c84b16bf17..3fbebef7e94 100644 --- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/candidate/CandidateStrategyEnum.java +++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/candidate/CandidateStrategyEnum.java @@ -23,9 +23,9 @@ package ca.uhn.fhir.jpa.mdm.svc.candidate; public enum CandidateStrategyEnum { /** Find Golden Resource candidates based on matching EID */ EID, - /** Find Golden Resource candidates based on a link already existing for the target resource */ + /** Find Golden Resource candidates based on a link already existing for the source resource */ LINK, - /** Find Golden Resource candidates based on other targets that match the incoming target using the MDM Matching rules */ + /** Find Golden Resource candidates based on other sources that match the incoming source using the MDM Matching rules */ SCORE; public boolean isEidMatch() { diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/candidate/FindCandidateByScoreSvc.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/candidate/FindCandidateByExampleSvc.java similarity index 95% rename from hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/candidate/FindCandidateByScoreSvc.java rename to hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/candidate/FindCandidateByExampleSvc.java index df6086d91e5..bc8b43efafb 100644 --- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/candidate/FindCandidateByScoreSvc.java +++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/candidate/FindCandidateByExampleSvc.java @@ -41,7 +41,7 @@ import java.util.Optional; import java.util.stream.Collectors; @Service -public class FindCandidateByScoreSvc extends BaseCandidateFinder { +public class FindCandidateByExampleSvc extends BaseCandidateFinder { private static final Logger ourLog = Logs.getMdmTroubleshootingLog(); @Autowired @@ -75,7 +75,7 @@ public class FindCandidateByScoreSvc extends BaseCandidateFinder { // MatchedTargetCandidate -> Golden Resource -> MdmLink -> MatchedGoldenResourceCandidate matchedCandidates = matchedCandidates.stream().filter(mc -> mc.isMatch() || mc.isPossibleMatch()).collect(Collectors.toList()); for (MatchedTarget match : matchedCandidates) { - Optional optionalMdmLink = myMdmLinkDaoSvc.getMatchedLinkForTargetPid(myIdHelperService.getPidOrNull(match.getTarget())); + Optional optionalMdmLink = myMdmLinkDaoSvc.getMatchedLinkForSourcePid(myIdHelperService.getPidOrNull(match.getTarget())); if (!optionalMdmLink.isPresent()) { continue; } @@ -94,7 +94,7 @@ public class FindCandidateByScoreSvc extends BaseCandidateFinder { private List getNoMatchGoldenResourcePids(IBaseResource theBaseResource) { Long targetPid = myIdHelperService.getPidOrNull(theBaseResource); - return myMdmLinkDaoSvc.getMdmLinksByTargetPidAndMatchResult(targetPid, MdmMatchResultEnum.NO_MATCH) + return myMdmLinkDaoSvc.getMdmLinksBySourcePidAndMatchResult(targetPid, MdmMatchResultEnum.NO_MATCH) .stream() .map(MdmLink::getGoldenResourcePid) .collect(Collectors.toList()); diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/candidate/FindCandidateByLinkSvc.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/candidate/FindCandidateByLinkSvc.java index 382a277ca0c..6eb8ba5e7cb 100644 --- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/candidate/FindCandidateByLinkSvc.java +++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/candidate/FindCandidateByLinkSvc.java @@ -47,7 +47,7 @@ public class FindCandidateByLinkSvc extends BaseCandidateFinder { Long targetPid = myIdHelperService.getPidOrNull(theTarget); if (targetPid != null) { - Optional oLink = myMdmLinkDaoSvc.getMatchedLinkForTargetPid(targetPid); + Optional oLink = myMdmLinkDaoSvc.getMatchedLinkForSourcePid(targetPid); if (oLink.isPresent()) { ResourcePersistentId goldenResourcePid = new ResourcePersistentId(oLink.get().getGoldenResourcePid()); ourLog.debug("Resource previously linked. Using existing link."); diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/candidate/MdmCandidateSearchSvc.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/candidate/MdmCandidateSearchSvc.java index 7fae56e6e8f..9d6f726663a 100644 --- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/candidate/MdmCandidateSearchSvc.java +++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/candidate/MdmCandidateSearchSvc.java @@ -66,11 +66,11 @@ public class MdmCandidateSearchSvc { } /** - * Given a target resource, search for all resources that are considered an MDM match based on defined MDM rules. + * Given a source resource, search for all resources that are considered an MDM match based on defined MDM rules. * * * @param theResourceType - * @param theResource the target {@link IBaseResource} we are attempting to match. + * @param theResource the {@link IBaseResource} we are attempting to match. * * @return the list of candidate {@link IBaseResource} which could be matches to theResource */ @@ -100,6 +100,8 @@ public class MdmCandidateSearchSvc { if (theResource.getIdElement().getIdPart() != null) { matchedPidsToResources.remove(myIdHelperService.getPidOrNull(theResource)); } + + ourLog.info("Found {} resources for {}", matchedPidsToResources.size(), theResourceType); return matchedPidsToResources.values(); } diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/candidate/MdmGoldenResourceFindingSvc.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/candidate/MdmGoldenResourceFindingSvc.java index fbeed20a35f..718ccc4e7ed 100644 --- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/candidate/MdmGoldenResourceFindingSvc.java +++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/candidate/MdmGoldenResourceFindingSvc.java @@ -44,17 +44,17 @@ public class MdmGoldenResourceFindingSvc { private FindCandidateByLinkSvc myFindCandidateByLinkSvc; @Autowired - private FindCandidateByScoreSvc myFindCandidateByScoreSvc; + private FindCandidateByExampleSvc myFindCandidateByExampleSvc; /** * Given an incoming IBaseResource, limited to the supported MDM type, return a list of {@link MatchedGoldenResourceCandidate} * indicating possible candidates for a matching Golden Resource. Uses several separate methods for finding candidates: *

* 0. First, check the incoming Resource for an EID. If it is present, and we can find a Golden Resource with this EID, it automatically matches. - * 1. First, check link table for any entries where this baseresource is the target of a Golden Resource. If found, return. + * 1. First, check link table for any entries where this baseresource is the source of a Golden Resource. If found, return. * 2. If none are found, attempt to find Golden Resources which link to this theResource. * 3. If none are found, attempt to find Golden Resources similar to our incoming resource based on the MDM rules and field matchers. - * 4. If none are found, attempt to find Golden Resources that are linked to targets that are similar to our incoming resource based on the MDM rules and + * 4. If none are found, attempt to find Golden Resources that are linked to sources that are similar to our incoming resource based on the MDM rules and * field matchers. * * @param theResource the {@link IBaseResource} we are attempting to find matching candidate Golden Resources for. @@ -68,9 +68,9 @@ public class MdmGoldenResourceFindingSvc { } if (matchedGoldenResourceCandidates.isEmpty()) { - //OK, so we have not found any links in the MdmLink table with us as a target. Next, let's find + //OK, so we have not found any links in the MdmLink table with us as a source. Next, let's find //possible Golden Resources matches by following MDM rules. - matchedGoldenResourceCandidates = myFindCandidateByScoreSvc.findCandidates(theResource); + matchedGoldenResourceCandidates = myFindCandidateByExampleSvc.findCandidates(theResource); } return matchedGoldenResourceCandidates; diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/BaseMdmR4Test.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/BaseMdmR4Test.java index af4101b266c..9b9f1b8a41b 100644 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/BaseMdmR4Test.java +++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/BaseMdmR4Test.java @@ -1,22 +1,14 @@ package ca.uhn.fhir.jpa.mdm; import ca.uhn.fhir.context.FhirContext; -import ca.uhn.fhir.mdm.api.MdmConstants; -import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum; -import ca.uhn.fhir.mdm.api.MdmMatchResultEnum; -import ca.uhn.fhir.mdm.api.IMdmSettings; -import ca.uhn.fhir.mdm.model.MdmTransactionContext; -import ca.uhn.fhir.mdm.rules.svc.MdmResourceMatcherSvc; -import ca.uhn.fhir.mdm.util.EIDHelper; -import ca.uhn.fhir.mdm.util.MdmUtil; import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster; import ca.uhn.fhir.jpa.api.dao.DaoRegistry; import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao; import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome; import ca.uhn.fhir.jpa.dao.data.IMdmLinkDao; import ca.uhn.fhir.jpa.dao.index.IdHelperService; +import ca.uhn.fhir.jpa.entity.MdmLink; import ca.uhn.fhir.jpa.mdm.config.MdmConsumerConfig; -import ca.uhn.fhir.jpa.mdm.config.MdmSearchParameterLoader; import ca.uhn.fhir.jpa.mdm.config.MdmSubmitterConfig; import ca.uhn.fhir.jpa.mdm.config.TestMdmConfigR4; import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc; @@ -27,11 +19,18 @@ import ca.uhn.fhir.jpa.mdm.matcher.IsPossibleLinkedTo; import ca.uhn.fhir.jpa.mdm.matcher.IsPossibleMatchWith; import ca.uhn.fhir.jpa.mdm.matcher.IsSameGoldenResourceAs; import ca.uhn.fhir.jpa.mdm.svc.MdmMatchLinkSvc; -import ca.uhn.fhir.jpa.entity.MdmLink; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.searchparam.registry.SearchParamRegistryImpl; import ca.uhn.fhir.jpa.subscription.match.config.SubscriptionProcessorConfig; import ca.uhn.fhir.jpa.test.BaseJpaR4Test; +import ca.uhn.fhir.mdm.api.IMdmSettings; +import ca.uhn.fhir.mdm.api.MdmConstants; +import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum; +import ca.uhn.fhir.mdm.api.MdmMatchResultEnum; +import ca.uhn.fhir.mdm.model.MdmTransactionContext; +import ca.uhn.fhir.mdm.rules.svc.MdmResourceMatcherSvc; +import ca.uhn.fhir.mdm.util.EIDHelper; +import ca.uhn.fhir.mdm.util.MdmUtil; import ca.uhn.fhir.model.api.TemporalPrecisionEnum; import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId; @@ -112,8 +111,6 @@ abstract public class BaseMdmR4Test extends BaseJpaR4Test { @Autowired protected EIDHelper myEIDHelper; @Autowired - MdmSearchParameterLoader myMdmSearchParameterLoader; - @Autowired SearchParamRegistryImpl mySearchParamRegistry; @Autowired private IInterceptorBroadcaster myInterceptorBroadcaster; @@ -314,7 +311,7 @@ abstract public class BaseMdmR4Test extends BaseJpaR4Test { String resourceType = theBaseResource.getIdElement().getResourceType(); IFhirResourceDao relevantDao = myDaoRegistry.getResourceDao(resourceType); - Optional matchedLinkForTargetPid = myMdmLinkDaoSvc.getMatchedLinkForTargetPid(myIdHelperService.getPidOrNull(theBaseResource)); + Optional matchedLinkForTargetPid = myMdmLinkDaoSvc.getMatchedLinkForSourcePid(myIdHelperService.getPidOrNull(theBaseResource)); if (matchedLinkForTargetPid.isPresent()) { Long goldenResourcePid = matchedLinkForTargetPid.get().getGoldenResourcePid(); return (IAnyResource) relevantDao.readByPid(new ResourcePersistentId(goldenResourcePid)); @@ -340,7 +337,7 @@ abstract public class BaseMdmR4Test extends BaseJpaR4Test { protected Patient createPatientAndUpdateLinks(Patient thePatient) { thePatient = createPatient(thePatient); - myMdmMatchLinkSvc.updateMdmLinksForMdmTarget(thePatient, createContextForCreate("Patient")); + myMdmMatchLinkSvc.updateMdmLinksForMdmSource(thePatient, createContextForCreate("Patient")); return thePatient; } @@ -359,7 +356,7 @@ abstract public class BaseMdmR4Test extends BaseJpaR4Test { protected Medication createMedicationAndUpdateLinks(Medication theMedication) { theMedication = createMedication(theMedication); - myMdmMatchLinkSvc.updateMdmLinksForMdmTarget(theMedication, createContextForCreate("Medication")); + myMdmMatchLinkSvc.updateMdmLinksForMdmSource(theMedication, createContextForCreate("Medication")); return theMedication; } @@ -381,7 +378,7 @@ abstract public class BaseMdmR4Test extends BaseJpaR4Test { protected Patient updatePatientAndUpdateLinks(Patient thePatient) { thePatient = (Patient) myPatientDao.update(thePatient).getResource(); - myMdmMatchLinkSvc.updateMdmLinksForMdmTarget(thePatient, createContextForUpdate(thePatient.getIdElement().getResourceType())); + myMdmMatchLinkSvc.updateMdmLinksForMdmSource(thePatient, createContextForUpdate(thePatient.getIdElement().getResourceType())); return thePatient; } @@ -389,7 +386,7 @@ abstract public class BaseMdmR4Test extends BaseJpaR4Test { thePractitioner.setActive(true); DaoMethodOutcome daoMethodOutcome = myPractitionerDao.create(thePractitioner); thePractitioner.setId(daoMethodOutcome.getId()); - myMdmMatchLinkSvc.updateMdmLinksForMdmTarget(thePractitioner, createContextForCreate("Practitioner")); + myMdmMatchLinkSvc.updateMdmLinksForMdmSource(thePractitioner, createContextForCreate("Practitioner")); return thePractitioner; } @@ -454,14 +451,14 @@ abstract public class BaseMdmR4Test extends BaseJpaR4Test { mdmLink.setLinkSource(MdmLinkSourceEnum.MANUAL); mdmLink.setMatchResult(MdmMatchResultEnum.MATCH); mdmLink.setGoldenResourcePid(myIdHelperService.getPidOrNull(sourcePatient)); - mdmLink.setTargetPid(myIdHelperService.getPidOrNull(patient)); + mdmLink.setSourcePid(myIdHelperService.getPidOrNull(patient)); return mdmLink; } - protected void loadMdmSearchParameters() { - myMdmSearchParameterLoader.daoUpdateMdmSearchParameters(); - mySearchParamRegistry.forceRefresh(); - } +// protected void loadMdmSearchParameters() { +// myMdmSearchParameterLoader.daoUpdateMdmSearchParameters(); +// mySearchParamRegistry.forceRefresh(); +// } protected void logAllLinks() { ourLog.info("Logging all MDM Links:"); @@ -476,7 +473,7 @@ abstract public class BaseMdmR4Test extends BaseJpaR4Test { } protected void assertLinksCreatedNewResource(Boolean... theExpectedValues) { - assertFields(MdmLink::getHadToCreateNewResource, theExpectedValues); + assertFields(MdmLink::getHadToCreateNewGoldenResource, theExpectedValues); } protected void assertLinksMatchedByEid(Boolean... theExpectedValues) { diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/helper/MdmLinkHelper.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/helper/MdmLinkHelper.java index b479fd5192e..33f2a87cfb1 100644 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/helper/MdmLinkHelper.java +++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/helper/MdmLinkHelper.java @@ -24,7 +24,7 @@ public class MdmLinkHelper { ourLog.info("All MDM Links:"); for (MdmLink link : links) { IdDt goldenResourceId = link.getGoldenResource().getIdDt().toVersionless(); - IdDt targetId = link.getTarget().getIdDt().toVersionless(); + IdDt targetId = link.getSource().getIdDt().toVersionless(); ourLog.info("{}: {}, {}, {}, {}", link.getId(), goldenResourceId, targetId, link.getMatchResult(), link.getLinkSource()); } } diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmExpungeTest.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmExpungeTest.java index 78d221a808e..e0133bc58b7 100644 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmExpungeTest.java +++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmExpungeTest.java @@ -45,7 +45,7 @@ public class MdmExpungeTest extends BaseMdmR4Test { mdmLink.setLinkSource(MdmLinkSourceEnum.MANUAL); mdmLink.setMatchResult(MdmMatchResultEnum.MATCH); mdmLink.setGoldenResourcePid(mySourceEntity.getId()); - mdmLink.setTargetPid(myTargetEntity.getId()); + mdmLink.setSourcePid(myTargetEntity.getId()); saveLink(mdmLink); } @@ -61,7 +61,7 @@ public class MdmExpungeTest extends BaseMdmR4Test { fail(); } catch (InternalErrorException e) { assertThat(e.getMessage(), containsString("ViolationException")); - assertThat(e.getMessage(), containsString("FK_EMPI_LINK_TARGET")); + assertThat(e.getMessage(), containsString("FK_MDM_LINK_SOURCE")); } myInterceptorService.registerInterceptor(myMdmStorageInterceptor); myPatientDao.expunge(myTargetId.toVersionless(), expungeOptions, null); diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmStorageInterceptorIT.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmStorageInterceptorIT.java index edccc9b2a6b..0cac56d4355 100644 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmStorageInterceptorIT.java +++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmStorageInterceptorIT.java @@ -20,7 +20,6 @@ import org.hl7.fhir.r4.model.Medication; import org.hl7.fhir.r4.model.Organization; import org.hl7.fhir.r4.model.Patient; import org.hl7.fhir.r4.model.SearchParameter; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; import org.slf4j.Logger; @@ -60,11 +59,6 @@ public class MdmStorageInterceptorIT extends BaseMdmR4Test { @Autowired private IdHelperService myIdHelperService; - @BeforeEach - public void before() { - super.loadMdmSearchParameters(); - } - @Test public void testCreatePractitioner() throws InterruptedException { myMdmHelper.createWithLatch(buildPractitionerWithNameAndId("somename", "some_id")); @@ -196,7 +190,7 @@ public class MdmStorageInterceptorIT extends BaseMdmR4Test { patient.setId(patientId); // Updating a Golden Resource Patient who was created via MDM should fail. - MdmLink mdmLink = myMdmLinkDaoSvc.getMatchedLinkForTargetPid(myIdHelperService.getPidOrNull(patient)).get(); + MdmLink mdmLink = myMdmLinkDaoSvc.getMatchedLinkForSourcePid(myIdHelperService.getPidOrNull(patient)).get(); Long sourcePatientPid = mdmLink.getGoldenResourcePid(); Patient goldenResourcePatient = (Patient) myPatientDao.readByPid(new ResourcePersistentId(sourcePatientPid)); goldenResourcePatient.setGender(Enumerations.AdministrativeGender.MALE); diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/BaseGoldenResourceMatcher.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/BaseGoldenResourceMatcher.java index 1b5d345741c..f249332d8e5 100644 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/BaseGoldenResourceMatcher.java +++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/BaseGoldenResourceMatcher.java @@ -46,7 +46,7 @@ public abstract class BaseGoldenResourceMatcher extends TypeSafeMatcher getMdmLinksForTarget(IAnyResource theTargetResource, MdmMatchResultEnum theMatchResult) { Long pidOrNull = myIdHelperService.getPidOrNull(theTargetResource); - List matchLinkForTarget = myMdmLinkDaoSvc.getMdmLinksByTargetPidAndMatchResult(pidOrNull, theMatchResult); + List matchLinkForTarget = myMdmLinkDaoSvc.getMdmLinksBySourcePidAndMatchResult(pidOrNull, theMatchResult); if (!matchLinkForTarget.isEmpty()) { return matchLinkForTarget; } else { diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/IsMatchedToAGoldenResource.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/IsMatchedToAGoldenResource.java index f9b30e10cc4..1ef0994b454 100644 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/IsMatchedToAGoldenResource.java +++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/IsMatchedToAGoldenResource.java @@ -22,7 +22,7 @@ public class IsMatchedToAGoldenResource extends TypeSafeMatcher { @Override protected boolean matchesSafely(IAnyResource theIncomingResource) { - Optional matchedLinkForTargetPid = myMdmLinkDaoSvc.getMatchedLinkForTargetPid(myIdHelperService.getPidOrNull(theIncomingResource)); + Optional matchedLinkForTargetPid = myMdmLinkDaoSvc.getMatchedLinkForSourcePid(myIdHelperService.getPidOrNull(theIncomingResource)); return matchedLinkForTargetPid.isPresent(); } diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/IsPossibleDuplicateOf.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/IsPossibleDuplicateOf.java index 7d0a9944b5f..fb7cf3af9cf 100644 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/IsPossibleDuplicateOf.java +++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/IsPossibleDuplicateOf.java @@ -36,9 +36,9 @@ public class IsPossibleDuplicateOf extends BaseGoldenResourceMatcher { //Returns true if there is a POSSIBLE_DUPLICATE between the incoming resource, and all of the resources passed in via the constructor. return goldenResourcePidsToMatch.stream() .map(baseResourcePid -> { - Optional duplicateLink = myMdmLinkDaoSvc.getMdmLinksByGoldenResourcePidTargetPidAndMatchResult(baseResourcePid, incomingGoldenResourcePid, MdmMatchResultEnum.POSSIBLE_DUPLICATE); + Optional duplicateLink = myMdmLinkDaoSvc.getMdmLinksByGoldenResourcePidSourcePidAndMatchResult(baseResourcePid, incomingGoldenResourcePid, MdmMatchResultEnum.POSSIBLE_DUPLICATE); if (!duplicateLink.isPresent()) { - duplicateLink = myMdmLinkDaoSvc.getMdmLinksByGoldenResourcePidTargetPidAndMatchResult(incomingGoldenResourcePid, baseResourcePid, MdmMatchResultEnum.POSSIBLE_DUPLICATE); + duplicateLink = myMdmLinkDaoSvc.getMdmLinksByGoldenResourcePidSourcePidAndMatchResult(incomingGoldenResourcePid, baseResourcePid, MdmMatchResultEnum.POSSIBLE_DUPLICATE); } return duplicateLink; }).allMatch(Optional::isPresent); diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/BaseLinkR4Test.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/BaseLinkR4Test.java index 022a573ea63..d44a313340d 100644 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/BaseLinkR4Test.java +++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/BaseLinkR4Test.java @@ -61,11 +61,11 @@ public abstract class BaseLinkR4Test extends BaseProviderR4Test { @Nonnull protected MdmLink getOnlyPatientLink() { - return myMdmLinkDaoSvc.findMdmLinkByTarget(myPatient).get(); + return myMdmLinkDaoSvc.findMdmLinkBySource(myPatient).get(); } @Nonnull protected List getPatientLinks() { - return myMdmLinkDaoSvc.findMdmLinksByTarget(myPatient); + return myMdmLinkDaoSvc.findMdmLinksBySourceResource(myPatient); } } diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderBatchR4Test.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderBatchR4Test.java index cf46779ace3..188cf4fd0c3 100644 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderBatchR4Test.java +++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderBatchR4Test.java @@ -73,7 +73,7 @@ public class MdmProviderBatchR4Test extends BaseLinkR4Test { StringType criteria = null; myMdmProviderR4.clearMdmLinks(null, myRequestDetails); - afterMdmLatch.runWithExpectedCount(1, () -> myMdmProviderR4.mdmBatchOnAllTargets(new StringType("Medication"), criteria, null)); + afterMdmLatch.runWithExpectedCount(1, () -> myMdmProviderR4.mdmBatchOnAllSourceResources(new StringType("Medication"), criteria, null)); assertLinkCount(1); } @@ -134,7 +134,7 @@ public class MdmProviderBatchR4Test extends BaseLinkR4Test { StringType criteria = new StringType(""); myMdmProviderR4.clearMdmLinks(null, myRequestDetails); afterMdmLatch.runWithExpectedCount(3, () -> { - myMdmProviderR4.mdmBatchOnAllTargets(null, criteria, null); + myMdmProviderR4.mdmBatchOnAllSourceResources(null, criteria, null); }); assertLinkCount(3); } diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderClearLinkR4Test.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderClearLinkR4Test.java index 7d7d7b87405..97b5d6ba866 100644 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderClearLinkR4Test.java +++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderClearLinkR4Test.java @@ -177,6 +177,6 @@ public class MdmProviderClearLinkR4Test extends BaseLinkR4Test { @Nonnull protected List getPractitionerLinks() { - return myMdmLinkDaoSvc.findMdmLinksByTarget(myPractitioner); + return myMdmLinkDaoSvc.findMdmLinksBySourceResource(myPractitioner); } } diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderMatchR4Test.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderMatchR4Test.java index cfab0caaf44..9b25fb413a6 100644 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderMatchR4Test.java +++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderMatchR4Test.java @@ -30,7 +30,6 @@ public class MdmProviderMatchR4Test extends BaseProviderR4Test { @BeforeEach public void before() { super.before(); - super.loadMdmSearchParameters(); } @Test diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderMergeGoldenResourcesR4Test.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderMergeGoldenResourcesR4Test.java index 6ae703dfbf3..f6715b81e10 100644 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderMergeGoldenResourcesR4Test.java +++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderMergeGoldenResourcesR4Test.java @@ -31,7 +31,6 @@ public class MdmProviderMergeGoldenResourcesR4Test extends BaseProviderR4Test { @BeforeEach public void before() { super.before(); - super.loadMdmSearchParameters(); myFromGoldenPatient = createGoldenPatient(); myFromGoldenPatientId = new StringType(myFromGoldenPatient.getIdElement().getValue()); @@ -58,11 +57,11 @@ public class MdmProviderMergeGoldenResourcesR4Test extends BaseProviderR4Test { // Optional redirect = fromSourcePatient.getIdentifier().stream().filter(theIdentifier -> theIdentifier.getSystem().equals("REDIRECT")).findFirst(); // assertThat(redirect.get().getValue(), is(equalTo(myToSourcePatient.getIdElement().toUnqualified().getValue()))); - List links = myMdmLinkDaoSvc.findMdmLinksByTarget(myFromGoldenPatient); + List links = myMdmLinkDaoSvc.findMdmLinksBySourceResource(myFromGoldenPatient); assertThat(links, hasSize(1)); MdmLink link = links.get(0); - assertEquals(link.getTargetPid(), myFromGoldenPatient.getIdElement().toUnqualifiedVersionless().getIdPartAsLong()); + assertEquals(link.getSourcePid(), myFromGoldenPatient.getIdElement().toUnqualifiedVersionless().getIdPartAsLong()); assertEquals(link.getGoldenResourcePid(), myToGoldenPatient.getIdElement().toUnqualifiedVersionless().getIdPartAsLong()); assertEquals(link.getMatchResult(), MdmMatchResultEnum.REDIRECT); assertEquals(link.getLinkSource(), MdmLinkSourceEnum.MANUAL); diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderQueryLinkR4Test.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderQueryLinkR4Test.java index a765c06c979..265d40288d6 100644 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderQueryLinkR4Test.java +++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderQueryLinkR4Test.java @@ -49,7 +49,7 @@ public class MdmProviderQueryLinkR4Test extends BaseLinkR4Test { myGoldenResource2Id = new StringType(sourcePatient2.getIdElement().toVersionless().getValue()); Long sourcePatient2Pid = myIdHelperService.getPidOrNull(sourcePatient2); - MdmLink possibleDuplicateMdmLink = myMdmLinkDaoSvc.newMdmLink().setGoldenResourcePid(sourcePatient1Pid).setTargetPid(sourcePatient2Pid).setMatchResult(MdmMatchResultEnum.POSSIBLE_DUPLICATE).setLinkSource(MdmLinkSourceEnum.AUTO); + MdmLink possibleDuplicateMdmLink = myMdmLinkDaoSvc.newMdmLink().setGoldenResourcePid(sourcePatient1Pid).setSourcePid(sourcePatient2Pid).setMatchResult(MdmMatchResultEnum.POSSIBLE_DUPLICATE).setLinkSource(MdmLinkSourceEnum.AUTO); saveLink(possibleDuplicateMdmLink); } diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/searchparam/SearchParameterTest.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/searchparam/SearchParameterTest.java deleted file mode 100644 index f3f8b00f8f5..00000000000 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/searchparam/SearchParameterTest.java +++ /dev/null @@ -1,50 +0,0 @@ -package ca.uhn.fhir.jpa.mdm.searchparam; - -import ca.uhn.fhir.jpa.mdm.BaseMdmR4Test; -import org.junit.jupiter.api.BeforeEach; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class SearchParameterTest extends BaseMdmR4Test { - private static final Logger ourLog = LoggerFactory.getLogger(SearchParameterTest.class); - - @BeforeEach - public void before() { - super.loadMdmSearchParameters(); - } - - /** - * TODO GGG MDM ask ken if we still need this search parameter. - * The implementation this test tests will instead need to rely on MPI_LINK table? - */ - /* - @Test - public void testCanFindPossibleMatches() { - // Create a possible match - Patient patient = buildJanePatient(); - patient.getNameFirstRep().setFamily("familyone"); - patient = createPatientAndUpdateLinks(patient); - - Patient patient2 = buildJanePatient(); - patient2.getNameFirstRep().setFamily("pleasedonotmatchatall"); - patient2 = createPatientAndUpdateLinks(patient2); - - assertThat(patient2, is(possibleMatchWith(patient))); - // Now confirm we can find it using our custom search parameter - - SearchParameterMap map = new SearchParameterMap(); - map.setLoadSynchronous(true); - map.add("assurance", new TokenParam(Person.IdentityAssuranceLevel.LEVEL2.toCode())); - IBundleProvider result = myPersonDao.search(map); - - assertEquals(1, result.size().intValue()); - Person person = (Person) result.getResources(0, 1).get(0); - String encoded = myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(person); - ourLog.info("Search result: {}", encoded); - List links = person.getLink(); - assertEquals(2, links.size()); - assertEquals(Person.IdentityAssuranceLevel.LEVEL2, links.get(0).getAssurance()); - assertEquals(Person.IdentityAssuranceLevel.LEVEL1, links.get(1).getAssurance()); - } - */ -} diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmBatchSvcImplTest.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmBatchSvcImplTest.java index 0aac0e67d00..b972988e423 100644 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmBatchSvcImplTest.java +++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmBatchSvcImplTest.java @@ -54,7 +54,7 @@ class MdmBatchSvcImplTest extends BaseMdmR4Test { assertLinkCount(0); //SUT - afterMdmLatch.runWithExpectedCount(30, () -> myMdmSubmitSvc.submitAllTargetTypesToMdm(null)); + afterMdmLatch.runWithExpectedCount(30, () -> myMdmSubmitSvc.submitAllSourceTypesToMdm(null)); assertLinkCount(30); } @@ -69,7 +69,7 @@ class MdmBatchSvcImplTest extends BaseMdmR4Test { assertLinkCount(0); //SUT - afterMdmLatch.runWithExpectedCount(10, () -> myMdmSubmitSvc.submitTargetTypeToMdm("Patient", null)); + afterMdmLatch.runWithExpectedCount(10, () -> myMdmSubmitSvc.submitSourceResourceTypeToMdm("Patient", null)); assertLinkCount(10); } @@ -86,7 +86,7 @@ class MdmBatchSvcImplTest extends BaseMdmR4Test { assertLinkCount(0); //SUT - afterMdmLatch.runWithExpectedCount(10, () -> myMdmSubmitSvc.submitTargetTypeToMdm("Medication", null)); + afterMdmLatch.runWithExpectedCount(10, () -> myMdmSubmitSvc.submitSourceResourceTypeToMdm("Medication", null)); assertLinkCount(10); } @@ -101,7 +101,7 @@ class MdmBatchSvcImplTest extends BaseMdmR4Test { assertLinkCount(0); //SUT - afterMdmLatch.runWithExpectedCount(10, () -> myMdmSubmitSvc.submitAllTargetTypesToMdm(null)); + afterMdmLatch.runWithExpectedCount(10, () -> myMdmSubmitSvc.submitAllSourceTypesToMdm(null)); assertLinkCount(10); } @@ -114,7 +114,7 @@ class MdmBatchSvcImplTest extends BaseMdmR4Test { assertLinkCount(0); //SUT - afterMdmLatch.runWithExpectedCount(1, () -> myMdmSubmitSvc.submitTargetTypeToMdm("Patient", "Patient?name=gary")); + afterMdmLatch.runWithExpectedCount(1, () -> myMdmSubmitSvc.submitSourceResourceTypeToMdm("Patient", "Patient?name=gary")); assertLinkCount(1); } diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmGoldenResourceMergerSvcTest.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmGoldenResourceMergerSvcTest.java index c744e2422db..b7dd763953c 100644 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmGoldenResourceMergerSvcTest.java +++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmGoldenResourceMergerSvcTest.java @@ -64,8 +64,6 @@ public class MdmGoldenResourceMergerSvcTest extends BaseMdmR4Test { @BeforeEach public void before() { - super.loadMdmSearchParameters(); - myFromGoldenPatient = createGoldenPatient(); IdType fromSourcePatientId = myFromGoldenPatient.getIdElement().toUnqualifiedVersionless(); myFromGoldenPatientPid = myIdHelperService.getPidOrThrowException(fromSourcePatientId); @@ -124,8 +122,8 @@ public class MdmGoldenResourceMergerSvcTest extends BaseMdmR4Test { public void mergeRemovesPossibleDuplicatesLink() { MdmLink mdmLink = myMdmLinkDaoSvc.newMdmLink() .setGoldenResourcePid(myToGoldenPatientPid) - .setTargetPid(myFromGoldenPatientPid) - .setMdmTargetType("Patient") + .setSourcePid(myFromGoldenPatientPid) + .setMdmSourceType("Patient") .setMatchResult(MdmMatchResultEnum.POSSIBLE_DUPLICATE) .setLinkSource(MdmLinkSourceEnum.AUTO); diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmLinkSvcTest.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmLinkSvcTest.java index 4ec426e4263..a65bfad0f67 100644 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmLinkSvcTest.java +++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmLinkSvcTest.java @@ -90,13 +90,13 @@ public class MdmLinkSvcTest extends BaseMdmR4Test { Long goldenPatient1Pid = myIdHelperService.getPidOrNull(goldenPatient1); Long goldenPatient2Pid = myIdHelperService.getPidOrNull(goldenPatient2); - assertFalse(myMdmLinkDaoSvc.getLinkByGoldenResourcePidAndTargetResourcePid(goldenPatient1Pid, goldenPatient2Pid).isPresent()); - assertFalse(myMdmLinkDaoSvc.getLinkByGoldenResourcePidAndTargetResourcePid(goldenPatient2Pid, goldenPatient1Pid).isPresent()); + assertFalse(myMdmLinkDaoSvc.getLinkByGoldenResourcePidAndSourceResourcePid(goldenPatient1Pid, goldenPatient2Pid).isPresent()); + assertFalse(myMdmLinkDaoSvc.getLinkByGoldenResourcePidAndSourceResourcePid(goldenPatient2Pid, goldenPatient1Pid).isPresent()); saveNoMatchLink(goldenPatient1Pid, goldenPatient2Pid); myMdmLinkSvc.updateLink(goldenPatient1, goldenPatient2, MdmMatchOutcome.POSSIBLE_DUPLICATE, MdmLinkSourceEnum.AUTO, createContextForCreate("Patient")); - assertFalse(myMdmLinkDaoSvc.getMdmLinksByGoldenResourcePidTargetPidAndMatchResult(goldenPatient1Pid, goldenPatient2Pid, MdmMatchResultEnum.POSSIBLE_DUPLICATE).isPresent()); + assertFalse(myMdmLinkDaoSvc.getMdmLinksByGoldenResourcePidSourcePidAndMatchResult(goldenPatient1Pid, goldenPatient2Pid, MdmMatchResultEnum.POSSIBLE_DUPLICATE).isPresent()); assertLinkCount(1); } @@ -108,20 +108,20 @@ public class MdmLinkSvcTest extends BaseMdmR4Test { Long goldenPatient1Pid = myIdHelperService.getPidOrNull(goldenPatient1); Long goldenPatient2Pid = myIdHelperService.getPidOrNull(goldenPatient2); - assertFalse(myMdmLinkDaoSvc.getLinkByGoldenResourcePidAndTargetResourcePid(goldenPatient1Pid, goldenPatient2Pid).isPresent()); - assertFalse(myMdmLinkDaoSvc.getLinkByGoldenResourcePidAndTargetResourcePid(goldenPatient2Pid, goldenPatient1Pid).isPresent()); + assertFalse(myMdmLinkDaoSvc.getLinkByGoldenResourcePidAndSourceResourcePid(goldenPatient1Pid, goldenPatient2Pid).isPresent()); + assertFalse(myMdmLinkDaoSvc.getLinkByGoldenResourcePidAndSourceResourcePid(goldenPatient2Pid, goldenPatient1Pid).isPresent()); saveNoMatchLink(goldenPatient2Pid, goldenPatient1Pid); myMdmLinkSvc.updateLink(goldenPatient1, goldenPatient2, MdmMatchOutcome.POSSIBLE_DUPLICATE, MdmLinkSourceEnum.AUTO, createContextForCreate("Patient")); - assertFalse(myMdmLinkDaoSvc.getMdmLinksByGoldenResourcePidTargetPidAndMatchResult(goldenPatient1Pid, goldenPatient2Pid, MdmMatchResultEnum.POSSIBLE_DUPLICATE).isPresent()); + assertFalse(myMdmLinkDaoSvc.getMdmLinksByGoldenResourcePidSourcePidAndMatchResult(goldenPatient1Pid, goldenPatient2Pid, MdmMatchResultEnum.POSSIBLE_DUPLICATE).isPresent()); assertLinkCount(1); } private void saveNoMatchLink(Long theGoldenResourcePid, Long theTargetPid) { MdmLink noMatchLink = myMdmLinkDaoSvc.newMdmLink() .setGoldenResourcePid(theGoldenResourcePid) - .setTargetPid(theTargetPid) + .setSourcePid(theTargetPid) .setLinkSource(MdmLinkSourceEnum.MANUAL) .setMatchResult(MdmMatchResultEnum.NO_MATCH); saveLink(noMatchLink); @@ -177,7 +177,7 @@ public class MdmLinkSvcTest extends BaseMdmR4Test { //assertEquals(patient1.getIdElement().toVersionless().getValue(), sourcePatient.getLinkFirstRep().getTarget().getReference()); List actual = targets .stream() - .map(link -> link.getTargetPid().toString()) + .map(link -> link.getSourcePid().toString()) .collect(Collectors.toList()); List expected = Arrays.asList(patient1, patient2) diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvcMultipleEidModeTest.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvcMultipleEidModeTest.java index 38333892c88..e08fb1a8453 100644 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvcMultipleEidModeTest.java +++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvcMultipleEidModeTest.java @@ -1,14 +1,13 @@ package ca.uhn.fhir.jpa.mdm.svc; +import ca.uhn.fhir.jpa.entity.MdmLink; +import ca.uhn.fhir.jpa.mdm.BaseMdmR4Test; import ca.uhn.fhir.mdm.api.MdmConstants; import ca.uhn.fhir.mdm.model.CanonicalEID; import ca.uhn.fhir.mdm.util.EIDHelper; -import ca.uhn.fhir.jpa.mdm.BaseMdmR4Test; -import ca.uhn.fhir.jpa.entity.MdmLink; import org.hl7.fhir.instance.model.api.IAnyResource; import org.hl7.fhir.r4.model.Identifier; import org.hl7.fhir.r4.model.Patient; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; @@ -37,11 +36,6 @@ public class MdmMatchLinkSvcMultipleEidModeTest extends BaseMdmR4Test { @Autowired private EIDHelper myEidHelper; - @BeforeEach - public void before() { - super.loadMdmSearchParameters(); - } - @Test public void testIncomingPatientWithEIDThatMatchesGoldenResourceWithHapiEidAddsExternalEidsToGoldenResource() { // Existing GoldenResource with system-assigned EID found linked from matched Patient. incoming Patient has EID. @@ -156,7 +150,7 @@ public class MdmMatchLinkSvcMultipleEidModeTest extends BaseMdmR4Test { //The two GoldenResources related to the patients should both show up in the only existing POSSIBLE_DUPLICATE MdmLink. MdmLink mdmLink = possibleDuplicates.get(0); assertThat(mdmLink.getGoldenResourcePid(), is(in(duplicatePids))); - assertThat(mdmLink.getTargetPid(), is(in(duplicatePids))); + assertThat(mdmLink.getSourcePid(), is(in(duplicatePids))); } @Test diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvcTest.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvcTest.java index 2691914e51d..ed4df25b577 100644 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvcTest.java +++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvcTest.java @@ -1,16 +1,16 @@ package ca.uhn.fhir.jpa.mdm.svc; +import ca.uhn.fhir.jpa.entity.MdmLink; +import ca.uhn.fhir.jpa.mdm.BaseMdmR4Test; +import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; +import ca.uhn.fhir.mdm.api.IMdmLinkSvc; import ca.uhn.fhir.mdm.api.MdmConstants; import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum; import ca.uhn.fhir.mdm.api.MdmMatchOutcome; -import ca.uhn.fhir.mdm.api.IMdmLinkSvc; import ca.uhn.fhir.mdm.model.CanonicalEID; import ca.uhn.fhir.mdm.util.EIDHelper; -import ca.uhn.fhir.mdm.util.MdmUtil; import ca.uhn.fhir.mdm.util.GoldenResourceHelper; -import ca.uhn.fhir.jpa.mdm.BaseMdmR4Test; -import ca.uhn.fhir.jpa.entity.MdmLink; -import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; +import ca.uhn.fhir.mdm.util.MdmUtil; import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.param.TokenParam; import org.hl7.fhir.instance.model.api.IAnyResource; @@ -19,7 +19,6 @@ import org.hl7.fhir.r4.model.HumanName; import org.hl7.fhir.r4.model.Identifier; import org.hl7.fhir.r4.model.Patient; import org.hl7.fhir.r4.model.Practitioner; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; @@ -57,11 +56,6 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test { @Autowired private GoldenResourceHelper myGoldenResourceHelper; - @BeforeEach - public void before() { - super.loadMdmSearchParameters(); - } - @Test public void testAddPatientLinksToNewGoldenResourceIfNoneFound() { createPatientAndUpdateLinks(buildJanePatient()); @@ -120,7 +114,7 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test { myMdmLinkSvc.updateLink(janeGoldenResource, unmatchedJane, MdmMatchOutcome.NO_MATCH, MdmLinkSourceEnum.MANUAL, createContextForCreate("Patient")); //rerun MDM rules against unmatchedJane. - myMdmMatchLinkSvc.updateMdmLinksForMdmTarget(unmatchedJane, createContextForCreate("Patient")); + myMdmMatchLinkSvc.updateMdmLinksForMdmSource(unmatchedJane, createContextForCreate("Patient")); assertThat(unmatchedJane, is(not(sameGoldenResourceAs(janeGoldenResource)))); assertThat(unmatchedJane, is(not(linkedTo(originalJane)))); @@ -145,7 +139,7 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test { //Now normally, when we run update links, it should link to janeGoldenResource. However, this manual NO_MATCH link //should cause a whole new GoldenResource to be created. - myMdmMatchLinkSvc.updateMdmLinksForMdmTarget(unmatchedPatient, createContextForCreate("Patient")); + myMdmMatchLinkSvc.updateMdmLinksForMdmSource(unmatchedPatient, createContextForCreate("Patient")); assertThat(unmatchedPatient, is(not(sameGoldenResourceAs(janeGoldenResource)))); assertThat(unmatchedPatient, is(not(linkedTo(originalJane)))); @@ -161,7 +155,7 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test { Patient janePatient = addExternalEID(buildJanePatient(), sampleEID); janePatient = createPatientAndUpdateLinks(janePatient); - Optional mdmLink = myMdmLinkDaoSvc.getMatchedLinkForTargetPid(janePatient.getIdElement().getIdPartAsLong()); + Optional mdmLink = myMdmLinkDaoSvc.getMatchedLinkForSourcePid(janePatient.getIdElement().getIdPartAsLong()); assertThat(mdmLink.isPresent(), is(true)); Patient patient = getTargetResourceFromMdmLink(mdmLink.get(), "Patient"); @@ -174,7 +168,7 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test { @Test public void testWhenPatientIsCreatedWithoutAnEIDTheGoldenResourceGetsAutomaticallyAssignedOne() { Patient patient = createPatientAndUpdateLinks(buildJanePatient()); - MdmLink mdmLink = myMdmLinkDaoSvc.getMatchedLinkForTargetPid(patient.getIdElement().getIdPartAsLong()).get(); + MdmLink mdmLink = myMdmLinkDaoSvc.getMatchedLinkForSourcePid(patient.getIdElement().getIdPartAsLong()).get(); Patient targetPatient = getTargetResourceFromMdmLink(mdmLink, "Patient"); Identifier identifierFirstRep = targetPatient.getIdentifierFirstRep(); @@ -186,7 +180,7 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test { public void testPatientAttributesAreCopiedOverWhenGoldenResourceIsCreatedFromPatient() { Patient patient = createPatientAndUpdateLinks(buildPatientWithNameIdAndBirthday("Gary", "GARY_ID", new Date())); - Optional mdmLink = myMdmLinkDaoSvc.getMatchedLinkForTargetPid(patient.getIdElement().getIdPartAsLong()); + Optional mdmLink = myMdmLinkDaoSvc.getMatchedLinkForSourcePid(patient.getIdElement().getIdPartAsLong()); Patient read = getTargetResourceFromMdmLink(mdmLink.get(), "Patient"); // TODO NG - rules haven't been determined yet revisit once implemented... @@ -288,7 +282,7 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test { //The two GoldenResources related to the patients should both show up in the only existing POSSIBLE_DUPLICATE MdmLink. MdmLink mdmLink = possibleDuplicates.get(0); assertThat(mdmLink.getGoldenResourcePid(), is(in(duplicatePids))); - assertThat(mdmLink.getTargetPid(), is(in(duplicatePids))); + assertThat(mdmLink.getSourcePid(), is(in(duplicatePids))); } @Test @@ -358,7 +352,7 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test { //In a normal situation, janePatient2 would just match to jane patient, but here we need to hack it so they are their //own individual GoldenResource for the purpose of this test. - IAnyResource goldenResource = myGoldenResourceHelper.createGoldenResourceFromMdmTarget(janePatient2); + IAnyResource goldenResource = myGoldenResourceHelper.createGoldenResourceFromMdmSourceResource(janePatient2); myMdmLinkSvc.updateLink(goldenResource, janePatient2, MdmMatchOutcome.NEW_GOLDEN_RESOURCE_MATCH, MdmLinkSourceEnum.AUTO, createContextForCreate("Patient")); assertThat(janePatient, is(not(sameGoldenResourceAs(janePatient2)))); @@ -372,7 +366,7 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test { assertThat(incomingJanePatient, is(possibleMatchWith(janePatient, janePatient2))); //Ensure there is no successful MATCH links for incomingJanePatient - Optional matchedLinkForTargetPid = myMdmLinkDaoSvc.getMatchedLinkForTargetPid(myIdHelperService.getPidOrNull(incomingJanePatient)); + Optional matchedLinkForTargetPid = myMdmLinkDaoSvc.getMatchedLinkForSourcePid(myIdHelperService.getPidOrNull(incomingJanePatient)); assertThat(matchedLinkForTargetPid.isPresent(), is(false)); logAllLinks(); @@ -449,7 +443,7 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test { public void testCreateGoldenResourceFromMdmTarget() { // Create Use Case #2 - adding patient with no EID Patient janePatient = buildJanePatient(); - Patient janeGoldenResourcePatient = myGoldenResourceHelper.createGoldenResourceFromMdmTarget(janePatient); + Patient janeGoldenResourcePatient = myGoldenResourceHelper.createGoldenResourceFromMdmSourceResource(janePatient); // golden record now contains HAPI-generated EID and HAPI tag assertTrue(MdmUtil.isMdmManaged(janeGoldenResourcePatient)); diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmResourceDaoSvcTest.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmResourceDaoSvcTest.java index bb22a17b461..fa8dac78590 100644 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmResourceDaoSvcTest.java +++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmResourceDaoSvcTest.java @@ -1,10 +1,9 @@ package ca.uhn.fhir.jpa.mdm.svc; -import ca.uhn.fhir.mdm.util.MdmUtil; import ca.uhn.fhir.jpa.mdm.BaseMdmR4Test; +import ca.uhn.fhir.mdm.util.MdmUtil; import org.hl7.fhir.instance.model.api.IAnyResource; import org.hl7.fhir.r4.model.Patient; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -19,11 +18,6 @@ public class MdmResourceDaoSvcTest extends BaseMdmR4Test { @Autowired MdmResourceDaoSvc myResourceDaoSvc; - @BeforeEach - public void before() { - super.loadMdmSearchParameters(); - } - @Test public void testSearchPatientByEidExcludesNonGoldenPatients() { Patient goodSourcePatient = addExternalEID(createGoldenPatient(), TEST_EID); diff --git a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/HapiFhirJpaMigrationTasks.java b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/HapiFhirJpaMigrationTasks.java index b20e3911d8a..0367a65d911 100644 --- a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/HapiFhirJpaMigrationTasks.java +++ b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/HapiFhirJpaMigrationTasks.java @@ -21,11 +21,6 @@ package ca.uhn.fhir.jpa.migrate.tasks; */ import ca.uhn.fhir.interceptor.model.RequestPartitionId; -import ca.uhn.fhir.jpa.entity.MdmLink; -import ca.uhn.fhir.jpa.entity.Search; -import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion; -import ca.uhn.fhir.jpa.entity.TermConceptMap; -import ca.uhn.fhir.jpa.entity.TermValueSet; import ca.uhn.fhir.jpa.migrate.DriverTypeEnum; import ca.uhn.fhir.jpa.migrate.taskdef.ArbitrarySqlTask; import ca.uhn.fhir.jpa.migrate.taskdef.CalculateHashesTask; @@ -85,9 +80,27 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks { mdmLink.addColumn("20201029.1", "GOLDEN_RESOURCE_PID").nonNullable().type(ColumnTypeEnum.LONG); mdmLink.addColumn("20201029.2", "RULE_COUNT").nullable().type(ColumnTypeEnum.LONG); mdmLink - .addForeignKey("20201029.3", "FK_EMPI_LINK_GOLDEN_RESOURCE") + .addForeignKey("20201029.3", "FK_MDM_LINK_GOLDEN_RESOURCE") .toColumn("GOLDEN_RESOURCE_PID") .references("HFJ_RESOURCE", "RES_ID"); + + mdmLink.dropIndex("20201029.4", "IDX_EMPI_PERSON_TGT"); + mdmLink.dropForeignKey("20201029.5", "FK_EMPI_LINK_TARGET", "HFJ_RESOURCE"); + mdmLink.dropForeignKey("20201029.6", "FK_EMPI_LINK_PERSON", "HFJ_RESOURCE"); + + mdmLink.renameColumn("20201029.7", "NEW_PERSON", "NEW_GOLDEN_RESOURCE"); + mdmLink.renameColumn("20201029.8", "TARGET_PID", "SOURCE_PID"); + mdmLink.renameColumn("20201029.9", "TARGET_TYPE", "SOURCE_TYPE"); + + mdmLink + .addForeignKey("20201029.10", "FK_MDM_LINK_SOURCE") + .toColumn("SOURCE_PID") + .references("HFJ_RESOURCE", "RES_ID"); + + mdmLink.addIndex("20201029.11", "IDX_MDM_GOLDEN_RESOURCE_SRC") + .unique(true).withColumns("GOLDEN_RESOURCE_PID", "SOURCE_PID"); + + mdmLink.dropColumn("20201029.12", "PERSON_PID"); } protected void init510() { diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmControllerSvc.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmControllerSvc.java index b3bd2667e09..0ca08944bfc 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmControllerSvc.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmControllerSvc.java @@ -28,7 +28,7 @@ import java.util.stream.Stream; public interface IMdmControllerSvc { - Stream queryLinks(@Nullable String theGoldenResourceId, @Nullable String theTargetId, @Nullable String theMatchResult, @Nullable String theLinkSource, MdmTransactionContext theMdmTransactionContext); + Stream queryLinks(@Nullable String theGoldenResourceId, @Nullable String theSourceResourceId, @Nullable String theMatchResult, @Nullable String theLinkSource, MdmTransactionContext theMdmTransactionContext); Stream getDuplicateGoldenResources(MdmTransactionContext theMdmTransactionContext); @@ -36,5 +36,5 @@ public interface IMdmControllerSvc { IAnyResource mergeGoldenResources(String theFromGoldenResourceId, String theToGoldenResourceId, MdmTransactionContext theMdmTransactionContext); - IAnyResource updateLink(String theGoldenResourceId, String theTargetId, String theMatchResult, MdmTransactionContext theMdmTransactionContext); + IAnyResource updateLink(String theGoldenResourceId, String theSourceResourceId, String theMatchResult, MdmTransactionContext theMdmTransactionContext); } diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmExpungeSvc.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmExpungeSvc.java index e119bd5a910..9c97e06607b 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmExpungeSvc.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmExpungeSvc.java @@ -27,11 +27,11 @@ public interface IMdmExpungeSvc { /** * Given a resource type, delete the underlying MDM links, and their related golden resource objects. * - * @param theResourceType The type of resources + * @param theSourceResourceType The type of resources * @param theRequestDetails * @return the count of deleted MDM links */ - long expungeAllMdmLinksOfTargetType(String theResourceType, ServletRequestDetails theRequestDetails); + long expungeAllMdmLinksOfSourceType(String theSourceResourceType, ServletRequestDetails theRequestDetails); /** * Delete all MDM links, and their related golden resource objects. diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmLinkQuerySvc.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmLinkQuerySvc.java index 23a0e145902..35dc4846191 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmLinkQuerySvc.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmLinkQuerySvc.java @@ -29,6 +29,6 @@ import java.util.stream.Stream; * This service supports the MDM operation providers for those services that return multiple MDM links. */ public interface IMdmLinkQuerySvc { - Stream queryLinks(IIdType theGoldenResourceId, IIdType theTargetId, MdmMatchResultEnum theMatchResult, MdmLinkSourceEnum theLinkSource, MdmTransactionContext theMdmContext); + Stream queryLinks(IIdType theGoldenResourceId, IIdType theSourceResourceId, MdmMatchResultEnum theMatchResult, MdmLinkSourceEnum theLinkSource, MdmTransactionContext theMdmContext); Stream getDuplicateGoldenResources(MdmTransactionContext theMdmContext); } diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmLinkSvc.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmLinkSvc.java index c295fadfbd3..54933eef81d 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmLinkSvc.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmLinkSvc.java @@ -26,22 +26,23 @@ import org.hl7.fhir.instance.model.api.IAnyResource; public interface IMdmLinkSvc { /** - * Update a link between a Golden Resource record and its target record. If a link does not exist between + * Update a link between a Golden Resource record and its source resource record. If a link does not exist between * these two records, create it. * - * @param theGoldenResource the Golden Resource to link the target resource to. - * @param theTargetResource the target resource, which can be of the MDM supported types + * @param theGoldenResource the Golden Resource to link the source resource to. + * @param theSourceResource the source resource, which can be of any of the MDM supported types * @param theMatchResult the current status of the match to set the link to. * @param theLinkSource MANUAL or AUTO: what caused the link. * @param theMdmTransactionContext */ - void updateLink(IAnyResource theGoldenResource, IAnyResource theTargetResource, MdmMatchOutcome theMatchResult, MdmLinkSourceEnum theLinkSource, MdmTransactionContext theMdmTransactionContext); + void updateLink(IAnyResource theGoldenResource, IAnyResource theSourceResource, MdmMatchOutcome theMatchResult, MdmLinkSourceEnum theLinkSource, MdmTransactionContext theMdmTransactionContext); /** - * Delete a link between given Golden Resource and the corresponing target + * Delete a link between given Golden Resource and the corresponding source resource * * @param theExistingGoldenResource - * @param theResource + * @param theSourceResource + * @param theMdmTransactionContext */ - void deleteLink(IAnyResource theExistingGoldenResource, IAnyResource theResource, MdmTransactionContext theMdmTransactionContext); + void deleteLink(IAnyResource theExistingGoldenResource, IAnyResource theSourceResource, MdmTransactionContext theMdmTransactionContext); } diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmLinkUpdaterSvc.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmLinkUpdaterSvc.java index ba0646bc843..f1fe0f7fc3e 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmLinkUpdaterSvc.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmLinkUpdaterSvc.java @@ -24,6 +24,6 @@ import ca.uhn.fhir.mdm.model.MdmTransactionContext; import org.hl7.fhir.instance.model.api.IAnyResource; public interface IMdmLinkUpdaterSvc { - IAnyResource updateLink(IAnyResource theGoldenResource, IAnyResource theTarget, MdmMatchResultEnum theMatchResult, MdmTransactionContext theMdmContext); - void notDuplicateGoldenResource(IAnyResource theGoldenResource, IAnyResource theTarget, MdmTransactionContext theMdmContext); + IAnyResource updateLink(IAnyResource theGoldenResource, IAnyResource theSourceResource, MdmMatchResultEnum theMatchResult, MdmTransactionContext theMdmContext); + void notDuplicateGoldenResource(IAnyResource theGoldenResource, IAnyResource theTargetGoldenResource, MdmTransactionContext theMdmContext); } diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmMatchFinderSvc.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmMatchFinderSvc.java index c59a9c29276..8d18fa0b445 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmMatchFinderSvc.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmMatchFinderSvc.java @@ -26,6 +26,7 @@ import javax.annotation.Nonnull; import java.util.List; public interface IMdmMatchFinderSvc { + /** * Retrieve a list of possible target candidates for matching, based on the given {@link IAnyResource} * Internally, performs all MDM matching rules on the type of the resource. diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmSubmitSvc.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmSubmitSvc.java index c001247e438..fa7329c53ec 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmSubmitSvc.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmSubmitSvc.java @@ -28,6 +28,7 @@ public interface IMdmSubmitSvc { /** * Submit all eligible resources for MDM processing. + * * @param theCriteria The FHIR search critieria for filtering the resources to be submitted for MDM processing. * NOTE: * When using this function, the criteria supplied must be valid for all MDM types. e.g. , if you @@ -36,19 +37,19 @@ public interface IMdmSubmitSvc { * * @return */ - long submitAllTargetTypesToMdm(@Nullable String theCriteria); + long submitAllSourceTypesToMdm(@Nullable String theCriteria); /** * Given a type and a search criteria, submit all found resources for MDM processing. * - * @param theTargetType the resource type that you wish to execute a search over for submission to MDM. + * @param theSourceResourceType the resource type that you wish to execute a search over for submission to MDM. * @param theCriteria The FHIR search critieria for filtering the resources to be submitted for MDM processing.. * @return the number of resources submitted for MDM processing. */ - long submitTargetTypeToMdm(String theTargetType, String theCriteria); + long submitSourceResourceTypeToMdm(String theSourceResourceType, String theCriteria); /** - * Convenience method that calls {@link #submitTargetTypeToMdm(String, String)} with the type pre-populated. + * Convenience method that calls {@link #submitSourceResourceTypeToMdm(String, String)} with the type pre-populated. * * @param theCriteria The FHIR search critieria for filtering the resources to be submitted for MDM processing. * @return the number of resources submitted for MDM processing. @@ -56,7 +57,7 @@ public interface IMdmSubmitSvc { long submitPractitionerTypeToMdm(String theCriteria); /** - * Convenience method that calls {@link #submitTargetTypeToMdm(String, String)} with the type pre-populated. + * Convenience method that calls {@link #submitSourceResourceTypeToMdm(String, String)} with the type pre-populated. * * @param theCriteria The FHIR search critieria for filtering the resources to be submitted for MDM processing. * @return the number of resources submitted for MDM processing. @@ -64,11 +65,12 @@ public interface IMdmSubmitSvc { long submitPatientTypeToMdm(String theCriteria); /** - * Given an ID and a target type valid for MDM, manually submit the given ID for MDM processing. + * Given an ID and a source resource type valid for MDM, manually submit the given ID for MDM processing. + * * @param theId the ID of the resource to process for MDM. * @return the constant `1`, as if this function returns successfully, it will have processed one resource for MDM. */ - long submitTargetToMdm(IIdType theId); + long submitSourceResourceToMdm(IIdType theId); /** * This setter exists to allow imported modules to override settings. diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmLinkJson.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmLinkJson.java index 2d5cc71b982..da3285ccab4 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmLinkJson.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmLinkJson.java @@ -30,8 +30,8 @@ public class MdmLinkJson implements IModelJson { @JsonProperty("goldenResourceId") private String myGoldenResourceId; - @JsonProperty("targetId") - private String myTargetId; + @JsonProperty("sourceId") + private String mySourceId; @JsonProperty("matchResult") private MdmMatchResultEnum myMatchResult; @@ -71,12 +71,12 @@ public class MdmLinkJson implements IModelJson { return this; } - public String getTargetId() { - return myTargetId; + public String getSourceId() { + return mySourceId; } - public MdmLinkJson setTargetId(String theTargetId) { - myTargetId = theTargetId; + public MdmLinkJson setSourceId(String theSourceId) { + mySourceId = theSourceId; return this; } diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmMatchResultEnum.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmMatchResultEnum.java index 384bae6a8fb..278fac12a35 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmMatchResultEnum.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmMatchResultEnum.java @@ -43,14 +43,13 @@ public enum MdmMatchResultEnum { POSSIBLE_DUPLICATE, /** - * Link between Golden Record and Target pointing to the Golden Record for that Target + * Link between Golden Record and Source Resource pointing to the Golden Record for that Source Resource */ - GOLDEN_RECORD, /** * Link between two Golden Resources resulting from a merge. One golden resource is deactivated. The inactive golden - * resource points to the active golden resource after the merge. The target resource points to the inactive golden + * resource points to the active golden resource after the merge. The source resource points to the inactive golden * resource after the merge. */ REDIRECT diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/BaseMdmProvider.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/BaseMdmProvider.java index 953b53b4a49..8a5e84e0e18 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/BaseMdmProvider.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/BaseMdmProvider.java @@ -100,7 +100,7 @@ public abstract class BaseMdmProvider { theMdmLinkStream.forEach(mdmLink -> { IBase resultPart = ParametersUtil.addParameterToParameters(myFhirContext, retval, "link"); ParametersUtil.addPartString(myFhirContext, resultPart, "goldenResourceId", mdmLink.getGoldenResourceId()); - ParametersUtil.addPartString(myFhirContext, resultPart, "targetResourceId", mdmLink.getTargetId()); + ParametersUtil.addPartString(myFhirContext, resultPart, "sourceResourceId", mdmLink.getSourceId()); if (includeResultAndSource) { ParametersUtil.addPartString(myFhirContext, resultPart, "matchResult", mdmLink.getMatchResult().name()); diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/MdmControllerHelper.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/MdmControllerHelper.java index e12a473bdf3..f0a96f3639a 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/MdmControllerHelper.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/MdmControllerHelper.java @@ -67,9 +67,9 @@ public class MdmControllerHelper { } - public IAnyResource getLatestTargetFromIdOrThrowException(String theParamName, String theId) { - IIdType targetId = MdmControllerUtil.getTargetIdDtOrThrowException(theParamName, theId); - return loadResource(targetId.toUnqualifiedVersionless()); + public IAnyResource getLatestSourceFromIdOrThrowException(String theParamName, String theSourceId) { + IIdType sourceId = MdmControllerUtil.getSourceIdDtOrThrowException(theParamName, theSourceId); + return loadResource(sourceId.toUnqualifiedVersionless()); } protected IAnyResource loadResource(IIdType theResourceId) { diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/MdmControllerUtil.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/MdmControllerUtil.java index bd2f3c94c46..3bfafd2b82b 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/MdmControllerUtil.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/MdmControllerUtil.java @@ -48,11 +48,11 @@ public class MdmControllerUtil { return getGoldenIdDtOrThrowException(theName, theGoldenResourceId); } - public static IIdType extractTargetIdDtOrNull(String theName, String theTargetId) { - if (theTargetId == null) { + public static IIdType extractSourceIdDtOrNull(String theName, String theSourceId) { + if (theSourceId == null) { return null; } - return getTargetIdDtOrThrowException(theName, theTargetId); + return getSourceIdDtOrThrowException(theName, theSourceId); } static IdDt getGoldenIdDtOrThrowException(String theParamName, String theId) { @@ -64,11 +64,11 @@ public class MdmControllerUtil { return goldenResourceId; } - public static IIdType getTargetIdDtOrThrowException(String theParamName, String theId) { - IdDt targetId = new IdDt(theId); - if (targetId.getIdPart() == null) { - throw new InvalidRequestException(theParamName + " is '" + theId + "'. must have form / where is the id of the resource and is the type of the resource"); + public static IIdType getSourceIdDtOrThrowException(String theParamName, String theSourceId) { + IdDt sourceId = new IdDt(theSourceId); + if (sourceId.getIdPart() == null) { + throw new InvalidRequestException(theParamName + " is '" + theSourceId + "'. must have form / where is the id of the resource and is the type of the resource"); } - return targetId; + return sourceId; } } diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/MdmProviderDstu3.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/MdmProviderDstu3.java index 5bb6cb2fc36..ba1236b5d43 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/MdmProviderDstu3.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/MdmProviderDstu3.java @@ -163,13 +163,13 @@ public class MdmProviderDstu3 extends BaseMdmProvider { @Operation(name = ProviderConstants.MDM_CLEAR, returnParameters = { @OperationParam(name = ProviderConstants.OPERATION_MDM_BATCH_RUN_OUT_PARAM_SUBMIT_COUNT, type= DecimalType.class) }) - public Parameters clearMdmLinks(@OperationParam(name=ProviderConstants.MDM_CLEAR_TARGET_TYPE, min = 0, max = 1) StringType theTargetType, + public Parameters clearMdmLinks(@OperationParam(name=ProviderConstants.MDM_CLEAR_SOURCE_TYPE, min = 0, max = 1) StringType theSourceResourceType, ServletRequestDetails theRequestDetails) { long resetCount; - if (theTargetType == null || StringUtils.isBlank(theTargetType.getValue())) { + if (theSourceResourceType == null || StringUtils.isBlank(theSourceResourceType.getValue())) { resetCount = myMdmExpungeSvc.expungeAllMdmLinks(theRequestDetails); } else { - resetCount = myMdmExpungeSvc.expungeAllMdmLinksOfTargetType(theTargetType.getValueNotNull(), theRequestDetails); + resetCount = myMdmExpungeSvc.expungeAllMdmLinksOfSourceType(theSourceResourceType.getValueNotNull(), theRequestDetails); } Parameters parameters = new Parameters(); parameters.addParameter().setName(ProviderConstants.OPERATION_MDM_CLEAR_OUT_PARAM_DELETED_COUNT) @@ -219,7 +219,7 @@ public class MdmProviderDstu3 extends BaseMdmProvider { @Operation(name = ProviderConstants.OPERATION_MDM_SUBMIT, idempotent = false, returnParameters = { @OperationParam(name = ProviderConstants.OPERATION_MDM_BATCH_RUN_OUT_PARAM_SUBMIT_COUNT, type= IntegerType.class) }) - public Parameters mdmBatchOnAllTargets( + public Parameters mdmBatchOnAllSourceResources( @OperationParam(name= ProviderConstants.MDM_BATCH_RUN_RESOURCE_TYPE, min = 0 , max = 1) StringType theResourceType, @OperationParam(name= ProviderConstants.MDM_BATCH_RUN_CRITERIA,min = 0 , max = 1) StringType theCriteria, ServletRequestDetails theRequestDetails) { @@ -228,9 +228,9 @@ public class MdmProviderDstu3 extends BaseMdmProvider { long submittedCount; if (resourceType != null) { - submittedCount = myMdmSubmitSvc.submitTargetTypeToMdm(resourceType, criteria); + submittedCount = myMdmSubmitSvc.submitSourceResourceTypeToMdm(resourceType, criteria); } else { - submittedCount = myMdmSubmitSvc.submitAllTargetTypesToMdm(criteria); + submittedCount = myMdmSubmitSvc.submitAllSourceTypesToMdm(criteria); } return buildMdmOutParametersWithCount(submittedCount); } @@ -245,7 +245,7 @@ public class MdmProviderDstu3 extends BaseMdmProvider { public Parameters mdmBatchPatientInstance( @IdParam IIdType theIdParam, RequestDetails theRequest) { - long submittedCount = myMdmSubmitSvc.submitTargetToMdm(theIdParam); + long submittedCount = myMdmSubmitSvc.submitSourceResourceToMdm(theIdParam); return buildMdmOutParametersWithCount(submittedCount); } @@ -266,7 +266,7 @@ public class MdmProviderDstu3 extends BaseMdmProvider { public Parameters mdmBatchPractitionerInstance( @IdParam IIdType theIdParam, RequestDetails theRequest) { - long submittedCount = myMdmSubmitSvc.submitTargetToMdm(theIdParam); + long submittedCount = myMdmSubmitSvc.submitSourceResourceToMdm(theIdParam); return buildMdmOutParametersWithCount(submittedCount); } diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/MdmProviderR4.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/MdmProviderR4.java index 6ae21aedb40..55a4587f11f 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/MdmProviderR4.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/MdmProviderR4.java @@ -164,13 +164,13 @@ public class MdmProviderR4 extends BaseMdmProvider { @Operation(name = ProviderConstants.MDM_CLEAR, returnParameters = { @OperationParam(name = ProviderConstants.OPERATION_MDM_BATCH_RUN_OUT_PARAM_SUBMIT_COUNT, type=DecimalType.class) }) - public Parameters clearMdmLinks(@OperationParam(name=ProviderConstants.MDM_CLEAR_TARGET_TYPE, min = 0, max = 1) StringType theTargetType, + public Parameters clearMdmLinks(@OperationParam(name=ProviderConstants.MDM_CLEAR_SOURCE_TYPE, min = 0, max = 1) StringType theSourceType, ServletRequestDetails theRequestDetails) { long resetCount; - if (theTargetType == null || StringUtils.isBlank(theTargetType.getValue())) { + if (theSourceType == null || StringUtils.isBlank(theSourceType.getValue())) { resetCount = myMdmExpungeSvc.expungeAllMdmLinks(theRequestDetails); } else { - resetCount = myMdmExpungeSvc.expungeAllMdmLinksOfTargetType(theTargetType.getValueNotNull(), theRequestDetails); + resetCount = myMdmExpungeSvc.expungeAllMdmLinksOfSourceType(theSourceType.getValueNotNull(), theRequestDetails); } Parameters parameters = new Parameters(); parameters.addParameter().setName(ProviderConstants.OPERATION_MDM_CLEAR_OUT_PARAM_DELETED_COUNT) @@ -221,7 +221,7 @@ public class MdmProviderR4 extends BaseMdmProvider { @Operation(name = ProviderConstants.OPERATION_MDM_SUBMIT, idempotent = false, returnParameters = { @OperationParam(name = ProviderConstants.OPERATION_MDM_BATCH_RUN_OUT_PARAM_SUBMIT_COUNT, type= IntegerType.class) }) - public Parameters mdmBatchOnAllTargets( + public Parameters mdmBatchOnAllSourceResources( @OperationParam(name= ProviderConstants.MDM_BATCH_RUN_RESOURCE_TYPE, min = 0 , max = 1) StringType theResourceType, @OperationParam(name= ProviderConstants.MDM_BATCH_RUN_CRITERIA,min = 0 , max = 1) StringType theCriteria, ServletRequestDetails theRequestDetails) { @@ -230,9 +230,9 @@ public class MdmProviderR4 extends BaseMdmProvider { long submittedCount; if (resourceType != null) { - submittedCount = myMdmSubmitSvc.submitTargetTypeToMdm(resourceType, criteria); + submittedCount = myMdmSubmitSvc.submitSourceResourceTypeToMdm(resourceType, criteria); } else { - submittedCount = myMdmSubmitSvc.submitAllTargetTypesToMdm(criteria); + submittedCount = myMdmSubmitSvc.submitAllSourceTypesToMdm(criteria); } return buildMdmOutParametersWithCount(submittedCount); } @@ -248,7 +248,7 @@ public class MdmProviderR4 extends BaseMdmProvider { public Parameters mdmBatchPatientInstance( @IdParam IIdType theIdParam, RequestDetails theRequest) { - long submittedCount = myMdmSubmitSvc.submitTargetToMdm(theIdParam); + long submittedCount = myMdmSubmitSvc.submitSourceResourceToMdm(theIdParam); return buildMdmOutParametersWithCount(submittedCount); } @@ -269,7 +269,7 @@ public class MdmProviderR4 extends BaseMdmProvider { public Parameters mdmBatchPractitionerInstance( @IdParam IIdType theIdParam, RequestDetails theRequest) { - long submittedCount = myMdmSubmitSvc.submitTargetToMdm(theIdParam); + long submittedCount = myMdmSubmitSvc.submitSourceResourceToMdm(theIdParam); return buildMdmOutParametersWithCount(submittedCount); } diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/rules/config/MdmSettings.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/rules/config/MdmSettings.java index f6d4e71af54..6bc7eecf4ee 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/rules/config/MdmSettings.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/rules/config/MdmSettings.java @@ -42,7 +42,7 @@ public class MdmSettings implements IMdmSettings { /** * If disabled, the underlying MDM system will operate under the following assumptions: * - * 1. Target resource may have more than 1 EID of the same system simultaneously. + * 1. Source resource may have more than 1 EID of the same system simultaneously. * 2. During linking, incoming patient EIDs will be merged with existing Golden Resource EIDs. */ private boolean myPreventMultipleEids; diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/rules/svc/MdmResourceMatcherSvc.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/rules/svc/MdmResourceMatcherSvc.java index cb46d089693..4d0320f188d 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/rules/svc/MdmResourceMatcherSvc.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/rules/svc/MdmResourceMatcherSvc.java @@ -120,25 +120,22 @@ public class MdmResourceMatcherSvc { int appliedRuleCount = 0; //TODO GGG MDM: This grabs ALL comparators, not just the ones we care about (e.g. the ones for Medication) - String resourceType = myFhirContext.getResourceType(theLeftResource); - for (int i = 0; i < myFieldMatchers.size(); ++i) { //any that are not for the resourceType in question. MdmResourceFieldMatcher fieldComparator = myFieldMatchers.get(i); if (!isValidResourceType(resourceType, fieldComparator.getResourceType())) { ourLog.debug("Matcher {} is not valid for resource type: {}. Skipping it.", fieldComparator.getName(), resourceType); continue; - } else { - ourLog.debug("Matcher {} is valid for resource type: {}. Evaluating match.", fieldComparator.getName(), resourceType); - MdmMatchEvaluation matchEvaluation = fieldComparator.match(theLeftResource, theRightResource); - if (matchEvaluation.match) { - vector |= (1 << i); - } - score += matchEvaluation.score; - appliedRuleCount += 1; } + ourLog.debug("Matcher {} is valid for resource type: {}. Evaluating match.", fieldComparator.getName(), resourceType); + MdmMatchEvaluation matchEvaluation = fieldComparator.match(theLeftResource, theRightResource); + if (matchEvaluation.match) { + vector |= (1 << i); + } + score += matchEvaluation.score; + appliedRuleCount += 1; } MdmMatchOutcome retVal = new MdmMatchOutcome(vector, score); diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/util/EIDHelper.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/util/EIDHelper.java index 02d75f44fdd..16c0b7d02f7 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/util/EIDHelper.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/util/EIDHelper.java @@ -97,7 +97,7 @@ public final class EIDHelper { } /** - * An incoming resource is a potential duplicate if it matches a target resource that has a golden resource with an + * An incoming resource is a potential duplicate if it matches a source resource that has a golden resource with an * official EID, but the incoming resource also has an EID that does not match. */ public boolean hasEidOverlap(IAnyResource theExistingGoldenResource, IAnyResource theComparingGoldenResource) { diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/util/GoldenResourceHelper.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/util/GoldenResourceHelper.java index 8582a75ea2a..7ea253ff457 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/util/GoldenResourceHelper.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/util/GoldenResourceHelper.java @@ -76,7 +76,7 @@ public class GoldenResourceHelper { * @param Supported MDM resource type (e.g. Patient, Practitioner) * @param theIncomingResource The resource that will be used as the starting point for the MDM linking. */ - public T createGoldenResourceFromMdmTarget(T theIncomingResource) { + public T createGoldenResourceFromMdmSourceResource(T theIncomingResource) { validateContextSupported(); // get a ref to the actual ID Field @@ -101,7 +101,7 @@ public class GoldenResourceHelper { */ //TODO GGG ask james if there is any way we can convert this canonical EID into a generic STU-agnostic IBase. private void addHapiEidIfNoExternalEidIsPresent( - IBaseResource theNewGoldenResource, BaseRuntimeChildDefinition theGoldenResourceIdentifier, IAnyResource theTargetResource) { + IBaseResource theNewGoldenResource, BaseRuntimeChildDefinition theGoldenResourceIdentifier, IAnyResource theSourceResource) { List eidsToApply = myEIDHelper.getExternalEid(theNewGoldenResource); if (!eidsToApply.isEmpty()) { @@ -111,8 +111,8 @@ public class GoldenResourceHelper { CanonicalEID hapiEid = myEIDHelper.createHapiEid(); theGoldenResourceIdentifier.getMutator().addValue(theNewGoldenResource, toId(hapiEid)); - // set identifier on the target resource - cloneEidIntoResource(theTargetResource, hapiEid); + // set identifier on the source resource + cloneEidIntoResource(theSourceResource, hapiEid); } private void cloneEidIntoResource(IBaseResource theResourceToCloneInto, CanonicalEID theEid) { @@ -204,35 +204,35 @@ public class GoldenResourceHelper { } /** - * Updates EID on Golden Resource, based on the incoming target resource. If the incoming resource has an external EID, it is applied + * Updates EID on Golden Resource, based on the incoming source resource. If the incoming resource has an external EID, it is applied * to the Golden Resource, unless that golden resource already has an external EID which does not match, in which case throw {@link IllegalArgumentException} *

* If running in multiple EID mode, then incoming EIDs are simply added to the Golden Resource without checking for matches. * * @param theGoldenResource The golden resource to update the external EID on. - * @param theTargetResource The target we will retrieve the external EID from. + * @param theSourceResource The source we will retrieve the external EID from. * @return the modified {@link IBaseResource} representing the Golden Resource. */ - public IAnyResource updateGoldenResourceExternalEidFromTargetResource(IAnyResource theGoldenResource, IAnyResource - theTargetResource, MdmTransactionContext theMdmTransactionContext) { + public IAnyResource updateGoldenResourceExternalEidFromSourceResource(IAnyResource theGoldenResource, IAnyResource + theSourceResource, MdmTransactionContext theMdmTransactionContext) { //This handles overwriting an automatically assigned EID if a patient that links is coming in with an official EID. - List incomingTargetEid = myEIDHelper.getExternalEid(theTargetResource); + List incomingSourceEid = myEIDHelper.getExternalEid(theSourceResource); List goldenResourceOfficialEid = myEIDHelper.getExternalEid(theGoldenResource); - if (incomingTargetEid.isEmpty()) { + if (incomingSourceEid.isEmpty()) { return theGoldenResource; } if (goldenResourceOfficialEid.isEmpty() || !myMdmSettings.isPreventMultipleEids()) { - log(theMdmTransactionContext, "Incoming resource:" + theTargetResource.getIdElement().toUnqualifiedVersionless() + " + with EID " + incomingTargetEid.stream().map(CanonicalEID::toString).collect(Collectors.joining(",")) - + " is applying this EIDs to its related Target Resource, as this Target Resource does not yet have an external EID"); - addCanonicalEidsToGoldenResourceIfAbsent(theGoldenResource, incomingTargetEid); - } else if (!goldenResourceOfficialEid.isEmpty() && myEIDHelper.eidMatchExists(goldenResourceOfficialEid, incomingTargetEid)) { - log(theMdmTransactionContext, "incoming resource:" + theTargetResource.getIdElement().toVersionless() + " with EIDs " + incomingTargetEid.stream().map(CanonicalEID::toString).collect(Collectors.joining(",")) + " does not need to overwrite Golden Resource, as this EID is already present"); + log(theMdmTransactionContext, "Incoming resource:" + theSourceResource.getIdElement().toUnqualifiedVersionless() + " + with EID " + incomingSourceEid.stream().map(CanonicalEID::toString).collect(Collectors.joining(",")) + + " is applying this EIDs to its related Source Resource, as this Source Resource does not yet have an external EID"); + addCanonicalEidsToGoldenResourceIfAbsent(theGoldenResource, incomingSourceEid); + } else if (!goldenResourceOfficialEid.isEmpty() && myEIDHelper.eidMatchExists(goldenResourceOfficialEid, incomingSourceEid)) { + log(theMdmTransactionContext, "incoming resource:" + theSourceResource.getIdElement().toVersionless() + " with EIDs " + incomingSourceEid.stream().map(CanonicalEID::toString).collect(Collectors.joining(",")) + " does not need to overwrite Golden Resource, as this EID is already present"); } else { throw new IllegalArgumentException( - String.format("Target EIDs %s would create a duplicate golden resource, as EIDs %s already exist!", - incomingTargetEid.toString(), goldenResourceOfficialEid.toString())); + String.format("Source EIDs %s would create a duplicate golden resource, as EIDs %s already exist!", + incomingSourceEid.toString(), goldenResourceOfficialEid.toString())); } return theGoldenResource; } @@ -285,10 +285,10 @@ public class GoldenResourceHelper { /** * Given a list of incoming External EIDs, and a Golden Resource, apply all the EIDs to this resource, which did not already exist on it. */ - private void addCanonicalEidsToGoldenResourceIfAbsent(IBaseResource theGoldenResource, List theIncomingTargetExternalEids) { + private void addCanonicalEidsToGoldenResourceIfAbsent(IBaseResource theGoldenResource, List theIncomingSourceExternalEids) { List goldenResourceExternalEids = myEIDHelper.getExternalEid(theGoldenResource); - for (CanonicalEID incomingExternalEid : theIncomingTargetExternalEids) { + for (CanonicalEID incomingExternalEid : theIncomingSourceExternalEids) { if (goldenResourceExternalEids.contains(incomingExternalEid)) { continue; } else { @@ -345,7 +345,7 @@ public class GoldenResourceHelper { } /** - * An incoming resource is a potential duplicate if it matches a target that has a golden resource with an official + * An incoming resource is a potential duplicate if it matches a source that has a golden resource with an official * EID, but the incoming resource also has an EID that does not match. */ public boolean isPotentialDuplicate(IAnyResource theExistingGoldenResource, IAnyResource theComparingGoldenResource) { @@ -359,11 +359,11 @@ public class GoldenResourceHelper { ourLog.debug(theMessage); } - public void handleExternalEidAddition(IAnyResource theGoldenResource, IAnyResource theTargetResource, MdmTransactionContext + public void handleExternalEidAddition(IAnyResource theGoldenResource, IAnyResource theSourceResource, MdmTransactionContext theMdmTransactionContext) { - List eidFromResource = myEIDHelper.getExternalEid(theTargetResource); + List eidFromResource = myEIDHelper.getExternalEid(theSourceResource); if (!eidFromResource.isEmpty()) { - updateGoldenResourceExternalEidFromTargetResource(theGoldenResource, theTargetResource, theMdmTransactionContext); + updateGoldenResourceExternalEidFromSourceResource(theGoldenResource, theSourceResource, theMdmTransactionContext); } } diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/util/MessageHelper.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/util/MessageHelper.java index 435fb9d9a52..e446c3f9771 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/util/MessageHelper.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/util/MessageHelper.java @@ -72,22 +72,22 @@ public class MessageHelper { + myMdmSettings.getSupportedMdmTypes() + ". Was " + theGoldenRecordType; } - public String getMessageForArgumentTypeMismatchInUpdate(String theGoldenRecordType, String theTargetType) { + public String getMessageForArgumentTypeMismatchInUpdate(String theGoldenRecordType, String theSourceResourceType) { return "Arguments to " + ProviderConstants.MDM_UPDATE_LINK + " must be of the same type. Were " + - theGoldenRecordType + " and " + theTargetType; + theGoldenRecordType + " and " + theSourceResourceType; } - public String getMessageForUnsupportedTarget() { - return "The target is marked with the " + MdmConstants.CODE_NO_MDM_MANAGED + public String getMessageForUnsupportedSourceResource() { + return "The source resource is marked with the " + MdmConstants.CODE_NO_MDM_MANAGED + " tag which means it may not be MDM linked."; } - public String getMessageForNoLink(IAnyResource theGoldenRecord, IAnyResource theTarget) { + public String getMessageForNoLink(IAnyResource theGoldenRecord, IAnyResource theSourceResource) { return getMessageForNoLink(theGoldenRecord.getIdElement().toVersionless().toString(), - theTarget.getIdElement().toVersionless().toString()); + theSourceResource.getIdElement().toVersionless().toString()); } - public String getMessageForNoLink(String theGoldenRecord, String theTarget) { - return "No link exists between " + theGoldenRecord + " and " + theTarget; + public String getMessageForNoLink(String theGoldenRecord, String theSourceResource) { + return "No link exists between " + theGoldenRecord + " and " + theSourceResource; } } diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/provider/ProviderConstants.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/provider/ProviderConstants.java index 3de765c2503..7a9f9304d41 100644 --- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/provider/ProviderConstants.java +++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/provider/ProviderConstants.java @@ -87,7 +87,7 @@ public class ProviderConstants { public static final String MDM_NOT_DUPLICATE = "$mdm-not-duplicate"; public static final String MDM_CLEAR = "$mdm-clear"; - public static final String MDM_CLEAR_TARGET_TYPE = "targetType"; + public static final String MDM_CLEAR_SOURCE_TYPE = "sourceType"; public static final String OPERATION_MDM_SUBMIT = "$mdm-submit"; public static final String MDM_BATCH_RUN_CRITERIA = "criteria" ; public static final String OPERATION_MDM_BATCH_RUN_OUT_PARAM_SUBMIT_COUNT = "submitted" ;