Merge pull request #1644 from jamesagnew/ks-20191220-inmemory-reference-host

improve in-memory reference matching
This commit is contained in:
Ken Stevens 2019-12-20 19:43:15 -05:00 committed by GitHub
commit 9d0194b0de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 73 additions and 3 deletions

View File

@ -282,9 +282,7 @@ public final class ResourceIndexedSearchParams {
} else { } else {
ForcedId forcedId = target.getForcedId(); ForcedId forcedId = target.getForcedId();
if (forcedId != null) { if (forcedId != null) {
// TODO KHS is forcedId.getForcedId().equals(theReference.getIdPart() also valid? return forcedId.getForcedId().equals(theReference.getValue());
return forcedId.getForcedId().equals(theReference.getValue()) ||
forcedId.getForcedId().equals(theReference.getIdPart());
} else { } else {
return false; return false;
} }

View File

@ -23,12 +23,14 @@ package ca.uhn.fhir.jpa.searchparam.matcher;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition; import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam; import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
import ca.uhn.fhir.jpa.searchparam.MatchUrlService; import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.extractor.ResourceIndexedSearchParams; import ca.uhn.fhir.jpa.searchparam.extractor.ResourceIndexedSearchParams;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
import ca.uhn.fhir.jpa.searchparam.util.SourceParam; import ca.uhn.fhir.jpa.searchparam.util.SourceParam;
import ca.uhn.fhir.model.api.IQueryParameterType; import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum; import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
import ca.uhn.fhir.rest.param.BaseParamWithPrefix; import ca.uhn.fhir.rest.param.BaseParamWithPrefix;
@ -56,6 +58,8 @@ public class InMemoryResourceMatcher {
@Autowired @Autowired
ISearchParamRegistry mySearchParamRegistry; ISearchParamRegistry mySearchParamRegistry;
@Autowired @Autowired
ModelConfig myModelConfig;
@Autowired
FhirContext myFhirContext; FhirContext myFhirContext;
/** /**
@ -212,9 +216,29 @@ public class InMemoryResourceMatcher {
} }
private boolean matchParams(String theResourceName, String theParamName, RuntimeSearchParam paramDef, List<? extends IQueryParameterType> theNextAnd, ResourceIndexedSearchParams theSearchParams) { private boolean matchParams(String theResourceName, String theParamName, RuntimeSearchParam paramDef, List<? extends IQueryParameterType> theNextAnd, ResourceIndexedSearchParams theSearchParams) {
if (paramDef.getParamType() == RestSearchParameterTypeEnum.REFERENCE) {
stripBaseUrlsFromReferenceParams(theNextAnd);
}
return theNextAnd.stream().anyMatch(token -> theSearchParams.matchParam(theResourceName, theParamName, paramDef, token)); return theNextAnd.stream().anyMatch(token -> theSearchParams.matchParam(theResourceName, theParamName, paramDef, token));
} }
private void stripBaseUrlsFromReferenceParams(List<? extends IQueryParameterType> theNextAnd) {
if (myModelConfig.getTreatBaseUrlsAsLocal().isEmpty()) {
return;
}
for (IQueryParameterType param : theNextAnd) {
ReferenceParam ref = (ReferenceParam) param;
IIdType dt = new IdDt(ref.getBaseUrl(), ref.getResourceType(), ref.getIdPart(), null);
if (dt.hasBaseUrl()) {
if (myModelConfig.getTreatBaseUrlsAsLocal().contains(dt.getBaseUrl())) {
ref.setValue(dt.toUnqualified().getValue());
}
}
}
}
private boolean hasChain(List<List<IQueryParameterType>> theAndOrParams) { private boolean hasChain(List<List<IQueryParameterType>> theAndOrParams) {
return theAndOrParams.stream().flatMap(List::stream).anyMatch(param -> param instanceof ReferenceParam && ((ReferenceParam) param).getChain() != null); return theAndOrParams.stream().flatMap(List::stream).anyMatch(param -> param instanceof ReferenceParam && ((ReferenceParam) param).getChain() != null);
} }

View File

@ -2,6 +2,7 @@ package ca.uhn.fhir.jpa.searchparam.matcher;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeSearchParam; import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate; import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate;
import ca.uhn.fhir.jpa.searchparam.MatchUrlService; import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
import ca.uhn.fhir.jpa.searchparam.extractor.ResourceIndexedSearchParams; import ca.uhn.fhir.jpa.searchparam.extractor.ResourceIndexedSearchParams;
@ -67,6 +68,11 @@ public class InMemoryResourceMatcherR5Test {
FhirContext fhirContext() { FhirContext fhirContext() {
return FhirContext.forR5(); return FhirContext.forR5();
} }
@Bean
ModelConfig modelConfig() {
return new ModelConfig();
}
} }
@Before @Before

View File

@ -1,18 +1,23 @@
package ca.uhn.fhir.jpa.subscription.module.matcher; package ca.uhn.fhir.jpa.subscription.module.matcher;
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
import ca.uhn.fhir.jpa.searchparam.matcher.InMemoryMatchResult; import ca.uhn.fhir.jpa.searchparam.matcher.InMemoryMatchResult;
import ca.uhn.fhir.jpa.searchparam.matcher.SearchParamMatcher; import ca.uhn.fhir.jpa.searchparam.matcher.SearchParamMatcher;
import ca.uhn.fhir.jpa.subscription.module.BaseSubscriptionDstu3Test; import ca.uhn.fhir.jpa.subscription.module.BaseSubscriptionDstu3Test;
import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.server.SimpleBundleProvider; import ca.uhn.fhir.rest.server.SimpleBundleProvider;
import ca.uhn.fhir.util.UrlUtil;
import org.hl7.fhir.dstu3.model.*; import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.dstu3.model.codesystems.MedicationRequestCategory; import org.hl7.fhir.dstu3.model.codesystems.MedicationRequestCategory;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.After;
import org.junit.Test; import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import static org.junit.Assert.*; import static org.junit.Assert.*;
@ -21,6 +26,8 @@ public class InMemorySubscriptionMatcherR3Test extends BaseSubscriptionDstu3Test
SubscriptionStrategyEvaluator mySubscriptionStrategyEvaluator; SubscriptionStrategyEvaluator mySubscriptionStrategyEvaluator;
@Autowired @Autowired
SearchParamMatcher mySearchParamMatcher; SearchParamMatcher mySearchParamMatcher;
@Autowired
ModelConfig myModelConfig;
private void assertUnsupported(IBaseResource resource, String criteria) { private void assertUnsupported(IBaseResource resource, String criteria) {
assertFalse(mySearchParamMatcher.match(criteria, resource, null).supported()); assertFalse(mySearchParamMatcher.match(criteria, resource, null).supported());
@ -48,6 +55,10 @@ public class InMemorySubscriptionMatcherR3Test extends BaseSubscriptionDstu3Test
assertEquals(theSubscriptionMatchingStrategy, mySubscriptionStrategyEvaluator.determineStrategy(criteria)); assertEquals(theSubscriptionMatchingStrategy, mySubscriptionStrategyEvaluator.determineStrategy(criteria));
} }
@After
public void after() {
myModelConfig.setTreatBaseUrlsAsLocal(new ModelConfig().getTreatBaseUrlsAsLocal());
}
/** /**
* Technically this is an invalid reference in most cases, but this shouldn't choke * Technically this is an invalid reference in most cases, but this shouldn't choke
@ -580,4 +591,35 @@ public class InMemorySubscriptionMatcherR3Test extends BaseSubscriptionDstu3Test
assertNotMatched(observation, criteria); assertNotMatched(observation, criteria);
} }
@Test
public void testExternalReferenceMatches() {
String goodReference = "http://example.com/base/Organization/FOO";
String goodCriteria = "Patient?organization=" + UrlUtil.escapeUrlParam(goodReference);
String badReference1 = "http://example.com/bad/Organization/FOO";
String badCriteria1 = "Patient?organization=" + UrlUtil.escapeUrlParam(badReference1);
String badReference2 = "http://example.org/base/Organization/FOO";
String badCriteria2 = "Patient?organization=" + UrlUtil.escapeUrlParam(badReference2);
String badReference3 = "https://example.com/base/Organization/FOO";
String badCriteria3 = "Patient?organization=" + UrlUtil.escapeUrlParam(badReference3);
String badReference4 = "http://example.com/base/Organization/GOO";
String badCriteria4 = "Patient?organization=" + UrlUtil.escapeUrlParam(badReference4);
Set<String> urls = new HashSet<>();
urls.add("http://example.com/base/");
myModelConfig.setTreatBaseUrlsAsLocal(urls);
Patient patient = new Patient();
patient.getManagingOrganization().setReference("Organization/FOO");
assertMatched(patient, goodCriteria);
assertNotMatched(patient, badCriteria1);
assertNotMatched(patient, badCriteria2);
assertNotMatched(patient, badCriteria3);
assertNotMatched(patient, badCriteria4);
}
} }