Skip to content

DO NOT MERGE Bundle operations #6950

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 27 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,11 @@ public void addDocumentEntry(IBaseResource theResource) {
addEntryAndReturnRequest(theResource);
}

public void addDocumentEntry(IBaseResource theResource, String theFullUrl) {
setType("document");
addEntryAndReturnRequest(theResource, theFullUrl);
}

/**
* Creates new entry and adds it to the bundle
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ FindCandidateByExampleSvc findCandidateByScoreSvc() {
}

@Bean
MdmProviderLoader mdmProviderLoader() {
protected MdmProviderLoader mdmProviderLoader() {
return new MdmProviderLoader();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,40 +20,68 @@
package ca.uhn.fhir.jpa.mdm.svc;

import ca.uhn.fhir.interceptor.model.RequestPartitionId;
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.mdm.svc.candidate.MdmCandidateSearchSvc;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.mdm.api.IMdmMatchFinderSvc;
import ca.uhn.fhir.mdm.api.IMdmSettings;
import ca.uhn.fhir.mdm.api.MatchedTarget;
import ca.uhn.fhir.mdm.api.MdmMatchOutcome;
import ca.uhn.fhir.mdm.log.Logs;
import ca.uhn.fhir.mdm.model.CanonicalEID;
import ca.uhn.fhir.mdm.rules.svc.MdmResourceMatcherSvc;
import ca.uhn.fhir.mdm.util.EIDHelper;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.api.server.SystemRequestDetails;
import ca.uhn.fhir.rest.param.TokenParam;
import jakarta.annotation.Nonnull;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

import static ca.uhn.fhir.jpa.mdm.svc.candidate.CandidateSearcher.idOrType;
import static org.hl7.fhir.dstu2016may.model.Basic.SP_IDENTIFIER;

@Service
public class MdmMatchFinderSvcImpl implements IMdmMatchFinderSvc {

private static final Logger ourLog = Logs.getMdmTroubleshootingLog();

@Autowired
private DaoRegistry myDaoRegistry;

@Autowired
private MdmCandidateSearchSvc myMdmCandidateSearchSvc;

@Autowired
private MdmResourceMatcherSvc myMdmResourceMatcherSvc;

@Autowired
private EIDHelper myEIDHelper;

@Autowired
IMdmSettings myMdmSettings;

@Override
@Nonnull
@Transactional
public List<MatchedTarget> getMatchedTargets(
String theResourceType, IAnyResource theResource, RequestPartitionId theRequestPartitionId) {

List<MatchedTarget> retval = matchBasedOnEid(theResourceType, theResource, theRequestPartitionId);
if (!retval.isEmpty()) {
return retval;
}

Collection<IAnyResource> targetCandidates =
myMdmCandidateSearchSvc.findCandidates(theResourceType, theResource, theRequestPartitionId);

Expand All @@ -65,4 +93,42 @@ public List<MatchedTarget> getMatchedTargets(
ourLog.trace("Found {} matched targets for {}.", matches.size(), idOrType(theResource, theResourceType));
return matches;
}

private List<MatchedTarget> matchBasedOnEid(
String theResourceType, IAnyResource theResource, RequestPartitionId theRequestPartitionId) {
List<CanonicalEID> eidFromResource = myEIDHelper.getExternalEid(theResource);
List<MatchedTarget> retval = new ArrayList<>();
for (CanonicalEID eid : eidFromResource) {
retval.addAll(searchForResourceByEID(
theResource.getIdElement().toUnqualifiedVersionless(),
eid.getValue(),
theResourceType,
theRequestPartitionId));
}
return retval;
}

private Collection<? extends MatchedTarget> searchForResourceByEID(
IIdType theResourceIdToExclude,
String theEid,
String theResourceType,
RequestPartitionId theRequestPartitionId) {
SearchParameterMap map = SearchParameterMap.newSynchronous();
map.add(
SP_IDENTIFIER,
new TokenParam(
myMdmSettings.getMdmRules().getEnterpriseEIDSystemForResourceType(theResourceType), theEid));

IFhirResourceDao<?> resourceDao = myDaoRegistry.getResourceDao(theResourceType);
SystemRequestDetails systemRequestDetails = new SystemRequestDetails();
systemRequestDetails.setRequestPartitionId(theRequestPartitionId);
IBundleProvider search = resourceDao.search(map, systemRequestDetails);
return search.getAllResources().stream()
.map(IAnyResource.class::cast)
// Exclude the incoming resource from the matched results
.filter(resource ->
!theResourceIdToExclude.equals(resource.getIdElement().toUnqualifiedVersionless()))
.map(resource -> new MatchedTarget(resource, MdmMatchOutcome.EID_MATCH))
.toList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public MdmMatchOutcome(Long theVector, Double theScore) {
}

public boolean isMatch() {
return myMatchResultEnum == MdmMatchResultEnum.MATCH;
return isEidMatch() || myMatchResultEnum == MdmMatchResultEnum.MATCH;
}

public boolean isPossibleMatch() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@
@Service
public class MdmProviderLoader {
@Autowired
private FhirContext myFhirContext;
protected FhirContext myFhirContext;

@Autowired
private ResourceProviderFactory myResourceProviderFactory;
protected ResourceProviderFactory myResourceProviderFactory;

@Autowired
private MdmControllerHelper myMdmControllerHelper;
Expand All @@ -60,7 +60,7 @@ public class MdmProviderLoader {
@Autowired
private IInterceptorBroadcaster myInterceptorBroadcaster;

private Supplier<Object> myMdmProviderSupplier;
protected Supplier<Object> myMdmProviderSupplier;
private Supplier<Object> myPatientMatchProviderSupplier;
private Supplier<Object> myMdmHistoryProviderSupplier;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,10 @@
import ca.uhn.fhir.rest.param.TokenAndListParam;
import ca.uhn.fhir.rest.param.TokenParam;

public class MdmSearchParamBuildingUtils {

private static final String IDENTIFIER = "identifier";
import static ca.uhn.fhir.rest.api.Constants.PARAM_TAG;
import static org.hl7.fhir.dstu2016may.model.Basic.SP_IDENTIFIER;

private static final String TAG = "_tag";
public class MdmSearchParamBuildingUtils {

/**
* Builds a search parameter map that can be used to find the
Expand All @@ -43,7 +42,7 @@ public static SearchParameterMap buildSearchParameterForBlockedResourceCount(Str
tagsToSearch.addAnd(new TokenParam(MdmConstants.SYSTEM_GOLDEN_RECORD_STATUS, MdmConstants.CODE_GOLDEN_RECORD));
tagsToSearch.addAnd(new TokenParam(MdmConstants.SYSTEM_GOLDEN_RECORD_STATUS, MdmConstants.CODE_BLOCKED));

map.add(TAG, tagsToSearch);
map.add(PARAM_TAG, tagsToSearch);
return map;
}

Expand All @@ -54,7 +53,9 @@ public static SearchParameterMap buildSearchParameterForBlockedResourceCount(Str
public static SearchParameterMap buildEidSearchParameterMap(
String theEid, String theResourceType, MdmRulesJson theMdmRules) {
SearchParameterMap map = buildBasicGoldenResourceSearchParameterMap(theEid);
map.add(IDENTIFIER, new TokenParam(theMdmRules.getEnterpriseEIDSystemForResourceType(theResourceType), theEid));
map.add(
SP_IDENTIFIER,
new TokenParam(theMdmRules.getEnterpriseEIDSystemForResourceType(theResourceType), theEid));
return map;
}

Expand All @@ -64,7 +65,7 @@ public static SearchParameterMap buildEidSearchParameterMap(
public static SearchParameterMap buildBasicGoldenResourceSearchParameterMap(String theResourceType) {
SearchParameterMap map = new SearchParameterMap();
map.setLoadSynchronous(true);
map.add(TAG, new TokenParam(MdmConstants.SYSTEM_GOLDEN_RECORD_STATUS, MdmConstants.CODE_GOLDEN_RECORD));
map.add(PARAM_TAG, new TokenParam(MdmConstants.SYSTEM_GOLDEN_RECORD_STATUS, MdmConstants.CODE_GOLDEN_RECORD));
return map;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -299,4 +299,7 @@ public class ProviderConstants {
public static final String OPERATION_REPLACE_REFERENCES_RESOURCE_LIMIT_DEFAULT_STRING = "512";
public static final Integer OPERATION_REPLACE_REFERENCES_RESOURCE_LIMIT_DEFAULT =
Integer.parseInt(OPERATION_REPLACE_REFERENCES_RESOURCE_LIMIT_DEFAULT_STRING);

public static final String OPERATION_MDM_BUNDLE_MATCH = "$mdm-bundle-match";
public static final String MDM_BUNDLE_MATCH_PARAM_INPUT_BUNDLE = "bundle";
}
Original file line number Diff line number Diff line change
Expand Up @@ -188,13 +188,13 @@ public void register(IFhirResourceDao theResourceDao) {
myResourceNameToResourceDao.put(resourceName, theResourceDao);
}

public IFhirResourceDao getDaoOrThrowException(Class<? extends IBaseResource> theClass) {
IFhirResourceDao retVal = getResourceDao(theClass);
public <T extends IBaseResource> IFhirResourceDao<T> getDaoOrThrowException(Class<T> theClass) {
IFhirResourceDao<T> retVal = getResourceDao(theClass);
if (retVal == null) {
List<String> supportedResourceNames = myResourceNameToResourceDao.keySet().stream()
.map(t -> myFhirContext.getResourceType(t))
.sorted()
.collect(Collectors.toList());
.toList();
throw new InvalidRequestException(Msg.code(573)
+ "Unable to process request, this server does not know how to handle resources of type "
+ myFhirContext.getResourceType(theClass) + " - Can handle: " + supportedResourceNames);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ private void startSession(int theCount, boolean theExactMatch) {
myPointcutLatchSession.set(new PointcutLatchSession(getName(), theCount, theExactMatch));
}

private String getName() {
public String getName() {
return myName + " " + this.getClass().getSimpleName();
}

Expand Down
Loading