Merge branch 'master' into windows-fixes

# Conflicts:
#	hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/SubscriptionDeliveringRestHookSubscriber.java
This commit is contained in:
Ken Stevens 2019-01-23 17:16:08 -05:00
commit cdd75bbe3a
10 changed files with 166 additions and 115 deletions

View File

@ -64,7 +64,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();
@ -83,7 +83,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();
@ -217,7 +217,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,7 +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(), e); ourLog.error("Cannot reach {} ", theMsg.getSubscription().getEndpointUrl());
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

@ -35,7 +35,7 @@ import ca.uhn.fhir.model.api.annotation.DatatypeDef;
/** /**
* Primitive type "base64Binary" in FHIR: a sequence of bytes represented in base64 * Primitive type "base64Binary" in FHIR: a sequence of bytes represented in base64
*/ */
@DatatypeDef(name = "base64binary") @DatatypeDef(name = "base64Binary")
public class Base64BinaryType extends PrimitiveType<byte[]> { public class Base64BinaryType extends PrimitiveType<byte[]> {
private static final long serialVersionUID = 3L; private static final long serialVersionUID = 3L;

View File

@ -46,7 +46,13 @@ public class ModelDstu3Test {
@Test @Test
public void testSetters() { public void testSetters() {
Claim claim = new Claim(); Claim claim = new Claim();
claim.setIdentifier(new ArrayList<Identifier>()).setCareTeam(new ArrayList<CareTeamComponent>()); claim.setIdentifier(new ArrayList<>()).setCareTeam(new ArrayList<>());
}
@Test
public void testbase64BinaryName() {
assertEquals("base64Binary", ourCtx.getElementDefinition("base64binary").getName());
assertEquals("base64Binary", ourCtx.getElementDefinition("base64Binary").getName());
} }
@Test @Test

View File

@ -35,7 +35,7 @@ import ca.uhn.fhir.model.api.annotation.DatatypeDef;
/** /**
* Primitive type "base64Binary" in FHIR: a sequence of bytes represented in base64 * Primitive type "base64Binary" in FHIR: a sequence of bytes represented in base64
*/ */
@DatatypeDef(name="base64binary") @DatatypeDef(name="base64Binary")
public class Base64BinaryType extends PrimitiveType<byte[]> { public class Base64BinaryType extends PrimitiveType<byte[]> {
private static final long serialVersionUID = 3L; private static final long serialVersionUID = 3L;

View File

@ -0,0 +1,19 @@
package org.hl7.fhir.r4.model;
import ca.uhn.fhir.context.FhirContext;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class ModelR4Test {
private static FhirContext ourCtx = FhirContext.forR4();
@Test
public void testbase64BinaryName() {
assertEquals("base64Binary", ourCtx.getElementDefinition("base64binary").getName());
assertEquals("base64Binary", ourCtx.getElementDefinition("base64Binary").getName());
}
}

View File

@ -19,7 +19,7 @@
<ul> <ul>
<li>Spring (JPA): 5.0.8.RELEASE -&gt; 5.1.3.RELEASE</li> <li>Spring (JPA): 5.0.8.RELEASE -&gt; 5.1.3.RELEASE</li>
<li>Spring-Data (JPA): 2.0.7.RELEASE -&gt; 2.1.3.RELEASE</li> <li>Spring-Data (JPA): 2.0.7.RELEASE -&gt; 2.1.3.RELEASE</li>
<li>Hibernate-Core (JPA): 5.3.6.FINAL -&gt; 5.4.0.FINAL</li> <li>Hibernate-Core (JPA): 5.3.6.FINAL -&gt; 5.4.1.FINAL</li>
<li>Hibernate-Search (JPA): 5.10.3.FINAL -&gt; 5.11.0.FINAL</li> <li>Hibernate-Search (JPA): 5.10.3.FINAL -&gt; 5.11.0.FINAL</li>
<li>Thymeleaf (JPA): 3.0.9.RELEASE -&gt; 3.0.11.RELEASE</li> <li>Thymeleaf (JPA): 3.0.9.RELEASE -&gt; 3.0.11.RELEASE</li>
<li>thymeleaf-spring4 (Testpage Overlay) has been replaced with thymeleaf-spring5</li> <li>thymeleaf-spring4 (Testpage Overlay) has been replaced with thymeleaf-spring5</li>
@ -320,6 +320,13 @@
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">
The casing of the base64Binary datatype was incorrect in the DSTU3 and R4 model classes.
This has been corrected.
</action>
</release> </release>
<release version="3.6.0" date="2018-11-12" description="Food"> <release version="3.6.0" date="2018-11-12" description="Food">
<action type="add"> <action type="add">