001/*-
002 * #%L
003 * HAPI FHIR JPA Server - Master Data Management
004 * %%
005 * Copyright (C) 2014 - 2023 Smile CDR, Inc.
006 * %%
007 * Licensed under the Apache License, Version 2.0 (the "License");
008 * you may not use this file except in compliance with the License.
009 * You may obtain a copy of the License at
010 *
011 *      http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 * #L%
019 */
020package ca.uhn.fhir.jpa.mdm.svc.candidate;
021
022import ca.uhn.fhir.interceptor.model.RequestPartitionId;
023import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc;
024import ca.uhn.fhir.jpa.mdm.svc.MdmResourceDaoSvc;
025import ca.uhn.fhir.mdm.api.IMdmLink;
026import ca.uhn.fhir.mdm.api.MdmMatchOutcome;
027import ca.uhn.fhir.mdm.log.Logs;
028import ca.uhn.fhir.mdm.model.CanonicalEID;
029import ca.uhn.fhir.mdm.util.EIDHelper;
030import ca.uhn.fhir.mdm.util.MdmPartitionHelper;
031import ca.uhn.fhir.rest.api.server.storage.IResourcePersistentId;
032import org.hl7.fhir.instance.model.api.IAnyResource;
033import org.slf4j.Logger;
034import org.springframework.beans.factory.annotation.Autowired;
035import org.springframework.stereotype.Service;
036
037import java.util.ArrayList;
038import java.util.List;
039import java.util.Optional;
040
041@Service
042public class FindCandidateByEidSvc extends BaseCandidateFinder {
043
044        private static final Logger ourLog = Logs.getMdmTroubleshootingLog();
045
046        @Autowired
047        private EIDHelper myEIDHelper;
048
049        @Autowired
050        private MdmResourceDaoSvc myMdmResourceDaoSvc;
051
052        @Autowired
053        private MdmLinkDaoSvc myMdmLinkDaoSvc;
054
055        @Autowired
056        MdmPartitionHelper myMdmPartitionHelper;
057
058        @Override
059        protected List<MatchedGoldenResourceCandidate> findMatchGoldenResourceCandidates(IAnyResource theIncomingResource) {
060                List<MatchedGoldenResourceCandidate> retval = new ArrayList<>();
061
062                List<CanonicalEID> eidFromResource = myEIDHelper.getExternalEid(theIncomingResource);
063                if (!eidFromResource.isEmpty()) {
064                        for (CanonicalEID eid : eidFromResource) {
065                                Optional<IAnyResource> oFoundGoldenResource = myMdmResourceDaoSvc.searchGoldenResourceByEID(
066                                                eid.getValue(),
067                                                theIncomingResource.getIdElement().getResourceType(),
068                                                myMdmPartitionHelper.getRequestPartitionIdFromResourceForSearch(theIncomingResource));
069                                if (oFoundGoldenResource.isPresent()) {
070                                        IAnyResource foundGoldenResource = oFoundGoldenResource.get();
071                                        // Exclude manually declared NO_MATCH links from candidates
072                                        if (isNoMatch(foundGoldenResource, theIncomingResource)) {
073                                                continue;
074                                        }
075                                        IResourcePersistentId pidOrNull =
076                                                        myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), foundGoldenResource);
077                                        MatchedGoldenResourceCandidate mpc =
078                                                        new MatchedGoldenResourceCandidate(pidOrNull, MdmMatchOutcome.EID_MATCH);
079                                        ourLog.debug(
080                                                        "Incoming Resource {} matched Golden Resource {} by EID {}",
081                                                        theIncomingResource.getIdElement().toUnqualifiedVersionless(),
082                                                        foundGoldenResource.getIdElement().toUnqualifiedVersionless(),
083                                                        eid);
084
085                                        retval.add(mpc);
086                                }
087                        }
088                }
089                return retval;
090        }
091
092        private boolean isNoMatch(IAnyResource theGoldenResource, IAnyResource theSourceResource) {
093                Optional<? extends IMdmLink> oLink =
094                                myMdmLinkDaoSvc.getLinkByGoldenResourceAndSourceResource(theGoldenResource, theSourceResource);
095                if (oLink.isEmpty()) {
096                        return false;
097                }
098                IMdmLink link = oLink.get();
099                return link.isNoMatch();
100        }
101
102        @Override
103        protected CandidateStrategyEnum getStrategy() {
104                return CandidateStrategyEnum.EID;
105        }
106}