_id support (#1176)

* added support for _id in in-memory matcher
This commit is contained in:
Ken Stevens 2019-01-23 14:37:34 -05:00 committed by GitHub
parent f53130c9ae
commit 5a08593abd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 56 additions and 35 deletions

View File

@ -63,7 +63,7 @@ public class SubscriptionCanonicalizer<S extends IBaseResource> {
} }
} }
protected CanonicalSubscription canonicalizeDstu2(IBaseResource theSubscription) { private CanonicalSubscription canonicalizeDstu2(IBaseResource theSubscription) {
ca.uhn.fhir.model.dstu2.resource.Subscription subscription = (ca.uhn.fhir.model.dstu2.resource.Subscription) theSubscription; ca.uhn.fhir.model.dstu2.resource.Subscription subscription = (ca.uhn.fhir.model.dstu2.resource.Subscription) theSubscription;
CanonicalSubscription retVal = new CanonicalSubscription(); CanonicalSubscription retVal = new CanonicalSubscription();
@ -82,7 +82,7 @@ public class SubscriptionCanonicalizer<S extends IBaseResource> {
return retVal; return retVal;
} }
protected CanonicalSubscription canonicalizeDstu3(IBaseResource theSubscription) { private CanonicalSubscription canonicalizeDstu3(IBaseResource theSubscription) {
org.hl7.fhir.dstu3.model.Subscription subscription = (org.hl7.fhir.dstu3.model.Subscription) theSubscription; org.hl7.fhir.dstu3.model.Subscription subscription = (org.hl7.fhir.dstu3.model.Subscription) theSubscription;
CanonicalSubscription retVal = new CanonicalSubscription(); CanonicalSubscription retVal = new CanonicalSubscription();
@ -210,7 +210,7 @@ public class SubscriptionCanonicalizer<S extends IBaseResource> {
return null; return null;
} }
protected CanonicalSubscription canonicalizeR4(IBaseResource theSubscription) { private CanonicalSubscription canonicalizeR4(IBaseResource theSubscription) {
org.hl7.fhir.r4.model.Subscription subscription = (org.hl7.fhir.r4.model.Subscription) theSubscription; org.hl7.fhir.r4.model.Subscription subscription = (org.hl7.fhir.r4.model.Subscription) theSubscription;
CanonicalSubscription retVal = new CanonicalSubscription(); CanonicalSubscription retVal = new CanonicalSubscription();

View File

@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.subscription.module.matcher;
* #L% * #L%
*/ */
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.searchparam.MatchUrlService; import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
@ -30,8 +31,11 @@ import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.param.BaseParamWithPrefix; import ca.uhn.fhir.rest.param.BaseParamWithPrefix;
import ca.uhn.fhir.rest.param.ReferenceParam; import ca.uhn.fhir.rest.param.ReferenceParam;
import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import org.hl7.fhir.instance.model.api.IAnyResource; import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -42,16 +46,18 @@ import java.util.function.Predicate;
@Service @Service
public class CriteriaResourceMatcher { public class CriteriaResourceMatcher {
public static final String CRITERIA = "CRITERIA"; private static final String CRITERIA = "CRITERIA";
@Autowired @Autowired
private MatchUrlService myMatchUrlService; private MatchUrlService myMatchUrlService;
@Autowired @Autowired
ISearchParamRegistry mySearchParamRegistry; ISearchParamRegistry mySearchParamRegistry;
@Autowired
FhirContext myFhirContext;
public SubscriptionMatchResult match(String theCriteria, RuntimeResourceDefinition theResourceDefinition, ResourceIndexedSearchParams theSearchParams) { public SubscriptionMatchResult match(String theCriteria, IBaseResource theResource, ResourceIndexedSearchParams theSearchParams) {
SearchParameterMap searchParameterMap; SearchParameterMap searchParameterMap;
try { try {
searchParameterMap = myMatchUrlService.translateMatchUrl(theCriteria, theResourceDefinition); searchParameterMap = myMatchUrlService.translateMatchUrl(theCriteria, myFhirContext.getResourceDefinition(theResource));
} catch (UnsupportedOperationException e) { } catch (UnsupportedOperationException e) {
return new SubscriptionMatchResult(theCriteria, CRITERIA); return new SubscriptionMatchResult(theCriteria, CRITERIA);
} }
@ -63,7 +69,7 @@ public class CriteriaResourceMatcher {
for (Map.Entry<String, List<List<? extends IQueryParameterType>>> entry : searchParameterMap.entrySet()) { for (Map.Entry<String, List<List<? extends IQueryParameterType>>> entry : searchParameterMap.entrySet()) {
String theParamName = entry.getKey(); String theParamName = entry.getKey();
List<List<? extends IQueryParameterType>> theAndOrParams = entry.getValue(); List<List<? extends IQueryParameterType>> theAndOrParams = entry.getValue();
SubscriptionMatchResult result = matchIdsWithAndOr(theParamName, theAndOrParams, theResourceDefinition, theSearchParams); SubscriptionMatchResult result = matchIdsWithAndOr(theParamName, theAndOrParams, theResource, theSearchParams);
if (!result.matched()){ if (!result.matched()){
return result; return result;
} }
@ -72,7 +78,7 @@ public class CriteriaResourceMatcher {
} }
// This method is modelled from SearchBuilder.searchForIdsWithAndOr() // This method is modelled from SearchBuilder.searchForIdsWithAndOr()
private SubscriptionMatchResult matchIdsWithAndOr(String theParamName, List<List<? extends IQueryParameterType>> theAndOrParams, RuntimeResourceDefinition theResourceDefinition, ResourceIndexedSearchParams theSearchParams) { private SubscriptionMatchResult matchIdsWithAndOr(String theParamName, List<List<? extends IQueryParameterType>> theAndOrParams, IBaseResource theResource, ResourceIndexedSearchParams theSearchParams) {
if (theAndOrParams.isEmpty()) { if (theAndOrParams.isEmpty()) {
return new SubscriptionMatchResult(true, CRITERIA); return new SubscriptionMatchResult(true, CRITERIA);
} }
@ -90,30 +96,44 @@ public class CriteriaResourceMatcher {
if (hasChain(theAndOrParams)) { if (hasChain(theAndOrParams)) {
return new SubscriptionMatchResult(theParamName, "Chained references are not supported"); return new SubscriptionMatchResult(theParamName, "Chained references are not supported");
} }
if (theParamName.equals(IAnyResource.SP_RES_ID)) { switch (theParamName) {
case IAnyResource.SP_RES_ID:
return new SubscriptionMatchResult(matchIdsAndOr(theAndOrParams, theResource), CRITERIA);
case IAnyResource.SP_RES_LANGUAGE:
return new SubscriptionMatchResult(theParamName, CRITERIA); return new SubscriptionMatchResult(theParamName, CRITERIA);
} else if (theParamName.equals(IAnyResource.SP_RES_LANGUAGE)) { case Constants.PARAM_HAS:
return new SubscriptionMatchResult(theParamName, CRITERIA); return new SubscriptionMatchResult(theParamName, CRITERIA);
} else if (theParamName.equals(Constants.PARAM_HAS)) { case Constants.PARAM_TAG:
case Constants.PARAM_PROFILE:
case Constants.PARAM_SECURITY:
return new SubscriptionMatchResult(theParamName, CRITERIA); return new SubscriptionMatchResult(theParamName, CRITERIA);
} else if (theParamName.equals(Constants.PARAM_TAG) || theParamName.equals(Constants.PARAM_PROFILE) || theParamName.equals(Constants.PARAM_SECURITY)) { default:
return new SubscriptionMatchResult(theParamName, CRITERIA); String resourceName = myFhirContext.getResourceDefinition(theResource).getName();
} else {
String resourceName = theResourceDefinition.getName();
RuntimeSearchParam paramDef = mySearchParamRegistry.getActiveSearchParam(resourceName, theParamName); RuntimeSearchParam paramDef = mySearchParamRegistry.getActiveSearchParam(resourceName, theParamName);
return matchResourceParam(theParamName, theAndOrParams, theSearchParams, resourceName, paramDef); return matchResourceParam(theParamName, theAndOrParams, theSearchParams, resourceName, paramDef);
} }
} }
private boolean matchIdsAndOr(List<List<? extends IQueryParameterType>> theAndOrParams, IBaseResource theResource) {
return theAndOrParams.stream().allMatch(nextAnd -> matchIdsOr(nextAnd, theResource));
}
private boolean matchIdsOr(List<? extends IQueryParameterType> theOrParams, IBaseResource theResource) {
return theOrParams.stream().anyMatch(param -> param instanceof StringParam && matchId(((StringParam)param).getValue(), theResource.getIdElement()));
}
private boolean matchId(String theValue, IIdType theId) {
return theValue.equals(theId.getValue()) || theValue.equals(theId.getIdPart());
}
private SubscriptionMatchResult matchResourceParam(String theParamName, List<List<? extends IQueryParameterType>> theAndOrParams, ResourceIndexedSearchParams theSearchParams, String theResourceName, RuntimeSearchParam theParamDef) { private SubscriptionMatchResult matchResourceParam(String theParamName, List<List<? extends IQueryParameterType>> theAndOrParams, ResourceIndexedSearchParams theSearchParams, String theResourceName, RuntimeSearchParam theParamDef) {
if (theParamDef != null) { if (theParamDef != null) {
switch (theParamDef.getParamType()) { switch (theParamDef.getParamType()) {

View File

@ -21,7 +21,6 @@ package ca.uhn.fhir.jpa.subscription.module.matcher;
*/ */
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.searchparam.extractor.ResourceIndexedSearchParams; import ca.uhn.fhir.jpa.searchparam.extractor.ResourceIndexedSearchParams;
import ca.uhn.fhir.jpa.searchparam.extractor.ResourceLinkExtractor; import ca.uhn.fhir.jpa.searchparam.extractor.ResourceLinkExtractor;
@ -61,7 +60,6 @@ public class InMemorySubscriptionMatcher implements ISubscriptionMatcher {
ResourceIndexedSearchParams searchParams = new ResourceIndexedSearchParams(); ResourceIndexedSearchParams searchParams = new ResourceIndexedSearchParams();
mySearchParamExtractorService.extractFromResource(searchParams, entity, resource); mySearchParamExtractorService.extractFromResource(searchParams, entity, resource);
myResourceLinkExtractor.extractResourceLinks(searchParams, entity, resource, resource.getMeta().getLastUpdated(), myInlineResourceLinkResolver); myResourceLinkExtractor.extractResourceLinks(searchParams, entity, resource, resource.getMeta().getLastUpdated(), myInlineResourceLinkResolver);
RuntimeResourceDefinition resourceDefinition = myContext.getResourceDefinition(resource); return myCriteriaResourceMatcher.match(criteria, resource, searchParams);
return myCriteriaResourceMatcher.match(criteria, resourceDefinition, searchParams);
} }
} }

View File

@ -101,8 +101,8 @@ public class SubscriptionDeliveringRestHookSubscriber extends BaseSubscriptionDe
try { try {
operation.execute(); operation.execute();
} catch (ResourceNotFoundException e) { } catch (ResourceNotFoundException e) {
ourLog.error("Cannot reach " + theMsg.getSubscription().getEndpointUrl()); ourLog.error("Cannot reach {} ", theMsg.getSubscription().getEndpointUrl());
e.printStackTrace(); ourLog.error("Exception: ", e);
throw e; throw e;
} }
} }

View File

@ -12,6 +12,7 @@ import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
@ -39,7 +40,6 @@ public class InMemorySubscriptionMatcherTestR3 extends BaseSubscriptionDstu3Test
} }
@Test @Test
@Ignore
public void testResourceById() { public void testResourceById() {
ProcedureRequest pr = new ProcedureRequest(); ProcedureRequest pr = new ProcedureRequest();
@ -47,12 +47,12 @@ public class InMemorySubscriptionMatcherTestR3 extends BaseSubscriptionDstu3Test
pr.setIntent(ProcedureRequest.ProcedureRequestIntent.ORIGINALORDER); pr.setIntent(ProcedureRequest.ProcedureRequestIntent.ORIGINALORDER);
assertMatched(pr, "ProcedureRequest?_id=123"); assertMatched(pr, "ProcedureRequest?_id=123");
assertMatched(pr, "ProcedureRequest?_id=Patient/123"); assertMatched(pr, "ProcedureRequest?_id=ProcedureRequest/123");
assertMatched(pr, "ProcedureRequest?_id=Patient/123,Patient/999"); assertMatched(pr, "ProcedureRequest?_id=ProcedureRequest/123,ProcedureRequest/999");
assertMatched(pr, "ProcedureRequest?_id=Patient/123&_id=Patient/123"); assertMatched(pr, "ProcedureRequest?_id=ProcedureRequest/123&_id=ProcedureRequest/123");
assertNotMatched(pr, "ProcedureRequest?_id=Patient/888"); assertNotMatched(pr, "ProcedureRequest?_id=ProcedureRequest/888");
assertNotMatched(pr, "ProcedureRequest?_id=Patient/888,Patient/999"); assertNotMatched(pr, "ProcedureRequest?_id=ProcedureRequest/888,ProcedureRequest/999");
assertNotMatched(pr, "ProcedureRequest?_id=Patient/123&_id=Patient/888"); assertNotMatched(pr, "ProcedureRequest?_id=ProcedureRequest/123&_id=ProcedureRequest/888");
} }
@ -301,7 +301,7 @@ public class InMemorySubscriptionMatcherTestR3 extends BaseSubscriptionDstu3Test
sp.setXpathUsage(SearchParameter.XPathUsageType.NORMAL); sp.setXpathUsage(SearchParameter.XPathUsageType.NORMAL);
sp.setStatus(Enumerations.PublicationStatus.ACTIVE); sp.setStatus(Enumerations.PublicationStatus.ACTIVE);
IBundleProvider bundle = new SimpleBundleProvider(Arrays.asList(sp), "uuid"); IBundleProvider bundle = new SimpleBundleProvider(Collections.singletonList(sp), "uuid");
initSearchParamRegistry(bundle); initSearchParamRegistry(bundle);
{ {
@ -333,7 +333,7 @@ public class InMemorySubscriptionMatcherTestR3 extends BaseSubscriptionDstu3Test
sp.setXpathUsage(SearchParameter.XPathUsageType.NORMAL); sp.setXpathUsage(SearchParameter.XPathUsageType.NORMAL);
sp.setStatus(Enumerations.PublicationStatus.ACTIVE); sp.setStatus(Enumerations.PublicationStatus.ACTIVE);
IBundleProvider bundle = new SimpleBundleProvider(Arrays.asList(sp), "uuid"); IBundleProvider bundle = new SimpleBundleProvider(Collections.singletonList(sp), "uuid");
initSearchParamRegistry(bundle); initSearchParamRegistry(bundle);
{ {
@ -425,7 +425,7 @@ public class InMemorySubscriptionMatcherTestR3 extends BaseSubscriptionDstu3Test
sp.setXpathUsage(SearchParameter.XPathUsageType.NORMAL); sp.setXpathUsage(SearchParameter.XPathUsageType.NORMAL);
sp.setStatus(Enumerations.PublicationStatus.ACTIVE); sp.setStatus(Enumerations.PublicationStatus.ACTIVE);
IBundleProvider bundle = new SimpleBundleProvider(Arrays.asList(sp), "uuid"); IBundleProvider bundle = new SimpleBundleProvider(Collections.singletonList(sp), "uuid");
initSearchParamRegistry(bundle); initSearchParamRegistry(bundle);
{ {

View File

@ -320,6 +320,9 @@
result in the 10th result being returned). This will now result in an empty result in the 10th result being returned). This will now result in an empty
response Bundle as would be expected. response Bundle as would be expected.
</action> </action>
<action type="add">
Added support for _id in in-memory matcher
</action>
<action type="fix"> <action type="fix">
The casing of the base64Binary datatype was incorrect in the DSTU3 and R4 model classes. The casing of the base64Binary datatype was incorrect in the DSTU3 and R4 model classes.
This has been corrected. This has been corrected.