diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/cache/SubscriptionCanonicalizer.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/cache/SubscriptionCanonicalizer.java index b7a3f09ce7c..4199054d76b 100644 --- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/cache/SubscriptionCanonicalizer.java +++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/cache/SubscriptionCanonicalizer.java @@ -63,7 +63,7 @@ public class SubscriptionCanonicalizer { } } - 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; CanonicalSubscription retVal = new CanonicalSubscription(); @@ -82,7 +82,7 @@ public class SubscriptionCanonicalizer { 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; CanonicalSubscription retVal = new CanonicalSubscription(); @@ -210,7 +210,7 @@ public class SubscriptionCanonicalizer { 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; CanonicalSubscription retVal = new CanonicalSubscription(); diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/matcher/CriteriaResourceMatcher.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/matcher/CriteriaResourceMatcher.java index 3e8fabb9aba..34f1793fede 100644 --- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/matcher/CriteriaResourceMatcher.java +++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/matcher/CriteriaResourceMatcher.java @@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.subscription.module.matcher; * #L% */ +import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.RuntimeResourceDefinition; import ca.uhn.fhir.context.RuntimeSearchParam; 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.param.BaseParamWithPrefix; import ca.uhn.fhir.rest.param.ReferenceParam; +import ca.uhn.fhir.rest.param.StringParam; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; 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.stereotype.Service; @@ -42,16 +46,18 @@ import java.util.function.Predicate; @Service public class CriteriaResourceMatcher { - public static final String CRITERIA = "CRITERIA"; + private static final String CRITERIA = "CRITERIA"; @Autowired private MatchUrlService myMatchUrlService; @Autowired 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; try { - searchParameterMap = myMatchUrlService.translateMatchUrl(theCriteria, theResourceDefinition); + searchParameterMap = myMatchUrlService.translateMatchUrl(theCriteria, myFhirContext.getResourceDefinition(theResource)); } catch (UnsupportedOperationException e) { return new SubscriptionMatchResult(theCriteria, CRITERIA); } @@ -63,7 +69,7 @@ public class CriteriaResourceMatcher { for (Map.Entry>> entry : searchParameterMap.entrySet()) { String theParamName = entry.getKey(); List> theAndOrParams = entry.getValue(); - SubscriptionMatchResult result = matchIdsWithAndOr(theParamName, theAndOrParams, theResourceDefinition, theSearchParams); + SubscriptionMatchResult result = matchIdsWithAndOr(theParamName, theAndOrParams, theResource, theSearchParams); if (!result.matched()){ return result; } @@ -72,7 +78,7 @@ public class CriteriaResourceMatcher { } // This method is modelled from SearchBuilder.searchForIdsWithAndOr() - private SubscriptionMatchResult matchIdsWithAndOr(String theParamName, List> theAndOrParams, RuntimeResourceDefinition theResourceDefinition, ResourceIndexedSearchParams theSearchParams) { + private SubscriptionMatchResult matchIdsWithAndOr(String theParamName, List> theAndOrParams, IBaseResource theResource, ResourceIndexedSearchParams theSearchParams) { if (theAndOrParams.isEmpty()) { return new SubscriptionMatchResult(true, CRITERIA); } @@ -90,30 +96,44 @@ public class CriteriaResourceMatcher { if (hasChain(theAndOrParams)) { 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(theParamName, CRITERIA); + return new SubscriptionMatchResult(matchIdsAndOr(theAndOrParams, theResource), CRITERIA); - } else if (theParamName.equals(IAnyResource.SP_RES_LANGUAGE)) { + case IAnyResource.SP_RES_LANGUAGE: - return new SubscriptionMatchResult(theParamName, CRITERIA); + return new SubscriptionMatchResult(theParamName, CRITERIA); - } else if (theParamName.equals(Constants.PARAM_HAS)) { + case Constants.PARAM_HAS: - 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)) { + case Constants.PARAM_TAG: + case Constants.PARAM_PROFILE: + case Constants.PARAM_SECURITY: - return new SubscriptionMatchResult(theParamName, CRITERIA); + return new SubscriptionMatchResult(theParamName, CRITERIA); - } else { + default: - String resourceName = theResourceDefinition.getName(); - RuntimeSearchParam paramDef = mySearchParamRegistry.getActiveSearchParam(resourceName, theParamName); - return matchResourceParam(theParamName, theAndOrParams, theSearchParams, resourceName, paramDef); + String resourceName = myFhirContext.getResourceDefinition(theResource).getName(); + RuntimeSearchParam paramDef = mySearchParamRegistry.getActiveSearchParam(resourceName, theParamName); + return matchResourceParam(theParamName, theAndOrParams, theSearchParams, resourceName, paramDef); } } + private boolean matchIdsAndOr(List> theAndOrParams, IBaseResource theResource) { + return theAndOrParams.stream().allMatch(nextAnd -> matchIdsOr(nextAnd, theResource)); + } + private boolean matchIdsOr(List 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> theAndOrParams, ResourceIndexedSearchParams theSearchParams, String theResourceName, RuntimeSearchParam theParamDef) { if (theParamDef != null) { switch (theParamDef.getParamType()) { diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/matcher/InMemorySubscriptionMatcher.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/matcher/InMemorySubscriptionMatcher.java index 414cac544b0..c7e789b0c37 100644 --- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/matcher/InMemorySubscriptionMatcher.java +++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/matcher/InMemorySubscriptionMatcher.java @@ -21,7 +21,6 @@ package ca.uhn.fhir.jpa.subscription.module.matcher; */ 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.searchparam.extractor.ResourceIndexedSearchParams; import ca.uhn.fhir.jpa.searchparam.extractor.ResourceLinkExtractor; @@ -61,7 +60,6 @@ public class InMemorySubscriptionMatcher implements ISubscriptionMatcher { ResourceIndexedSearchParams searchParams = new ResourceIndexedSearchParams(); mySearchParamExtractorService.extractFromResource(searchParams, entity, resource); myResourceLinkExtractor.extractResourceLinks(searchParams, entity, resource, resource.getMeta().getLastUpdated(), myInlineResourceLinkResolver); - RuntimeResourceDefinition resourceDefinition = myContext.getResourceDefinition(resource); - return myCriteriaResourceMatcher.match(criteria, resourceDefinition, searchParams); + return myCriteriaResourceMatcher.match(criteria, resource, searchParams); } } diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/SubscriptionDeliveringRestHookSubscriber.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/SubscriptionDeliveringRestHookSubscriber.java index 3358e8ab0cd..0667f7be9f2 100644 --- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/SubscriptionDeliveringRestHookSubscriber.java +++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/SubscriptionDeliveringRestHookSubscriber.java @@ -101,8 +101,8 @@ public class SubscriptionDeliveringRestHookSubscriber extends BaseSubscriptionDe try { operation.execute(); } catch (ResourceNotFoundException e) { - ourLog.error("Cannot reach " + theMsg.getSubscription().getEndpointUrl()); - e.printStackTrace(); + ourLog.error("Cannot reach {} ", theMsg.getSubscription().getEndpointUrl()); + ourLog.error("Exception: ", e); throw e; } } diff --git a/hapi-fhir-jpaserver-subscription/src/test/java/ca/uhn/fhir/jpa/subscription/module/matcher/InMemorySubscriptionMatcherTestR3.java b/hapi-fhir-jpaserver-subscription/src/test/java/ca/uhn/fhir/jpa/subscription/module/matcher/InMemorySubscriptionMatcherTestR3.java index eb0706b2001..ff6b32d436c 100644 --- a/hapi-fhir-jpaserver-subscription/src/test/java/ca/uhn/fhir/jpa/subscription/module/matcher/InMemorySubscriptionMatcherTestR3.java +++ b/hapi-fhir-jpaserver-subscription/src/test/java/ca/uhn/fhir/jpa/subscription/module/matcher/InMemorySubscriptionMatcherTestR3.java @@ -12,6 +12,7 @@ import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import java.util.Arrays; +import java.util.Collections; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -39,7 +40,6 @@ public class InMemorySubscriptionMatcherTestR3 extends BaseSubscriptionDstu3Test } @Test - @Ignore public void testResourceById() { ProcedureRequest pr = new ProcedureRequest(); @@ -47,12 +47,12 @@ public class InMemorySubscriptionMatcherTestR3 extends BaseSubscriptionDstu3Test pr.setIntent(ProcedureRequest.ProcedureRequestIntent.ORIGINALORDER); assertMatched(pr, "ProcedureRequest?_id=123"); - assertMatched(pr, "ProcedureRequest?_id=Patient/123"); - assertMatched(pr, "ProcedureRequest?_id=Patient/123,Patient/999"); - assertMatched(pr, "ProcedureRequest?_id=Patient/123&_id=Patient/123"); - assertNotMatched(pr, "ProcedureRequest?_id=Patient/888"); - assertNotMatched(pr, "ProcedureRequest?_id=Patient/888,Patient/999"); - assertNotMatched(pr, "ProcedureRequest?_id=Patient/123&_id=Patient/888"); + assertMatched(pr, "ProcedureRequest?_id=ProcedureRequest/123"); + assertMatched(pr, "ProcedureRequest?_id=ProcedureRequest/123,ProcedureRequest/999"); + assertMatched(pr, "ProcedureRequest?_id=ProcedureRequest/123&_id=ProcedureRequest/123"); + assertNotMatched(pr, "ProcedureRequest?_id=ProcedureRequest/888"); + assertNotMatched(pr, "ProcedureRequest?_id=ProcedureRequest/888,ProcedureRequest/999"); + assertNotMatched(pr, "ProcedureRequest?_id=ProcedureRequest/123&_id=ProcedureRequest/888"); } @@ -301,7 +301,7 @@ public class InMemorySubscriptionMatcherTestR3 extends BaseSubscriptionDstu3Test sp.setXpathUsage(SearchParameter.XPathUsageType.NORMAL); sp.setStatus(Enumerations.PublicationStatus.ACTIVE); - IBundleProvider bundle = new SimpleBundleProvider(Arrays.asList(sp), "uuid"); + IBundleProvider bundle = new SimpleBundleProvider(Collections.singletonList(sp), "uuid"); initSearchParamRegistry(bundle); { @@ -333,7 +333,7 @@ public class InMemorySubscriptionMatcherTestR3 extends BaseSubscriptionDstu3Test sp.setXpathUsage(SearchParameter.XPathUsageType.NORMAL); sp.setStatus(Enumerations.PublicationStatus.ACTIVE); - IBundleProvider bundle = new SimpleBundleProvider(Arrays.asList(sp), "uuid"); + IBundleProvider bundle = new SimpleBundleProvider(Collections.singletonList(sp), "uuid"); initSearchParamRegistry(bundle); { @@ -425,7 +425,7 @@ public class InMemorySubscriptionMatcherTestR3 extends BaseSubscriptionDstu3Test sp.setXpathUsage(SearchParameter.XPathUsageType.NORMAL); sp.setStatus(Enumerations.PublicationStatus.ACTIVE); - IBundleProvider bundle = new SimpleBundleProvider(Arrays.asList(sp), "uuid"); + IBundleProvider bundle = new SimpleBundleProvider(Collections.singletonList(sp), "uuid"); initSearchParamRegistry(bundle); { diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 072f559de66..aac1c8be1cc 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -320,6 +320,9 @@ result in the 10th result being returned). This will now result in an empty response Bundle as would be expected. + + Added support for _id in in-memory matcher + The casing of the base64Binary datatype was incorrect in the DSTU3 and R4 model classes. This has been corrected.