parent
6c4d4e43a1
commit
3d07fc1c22
|
@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.subscription.dbmatcher;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||||
|
import ca.uhn.fhir.jpa.subscription.module.CanonicalSubscription;
|
||||||
import ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage;
|
import ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage;
|
||||||
import ca.uhn.fhir.jpa.subscription.module.matcher.ISubscriptionMatcher;
|
import ca.uhn.fhir.jpa.subscription.module.matcher.ISubscriptionMatcher;
|
||||||
import ca.uhn.fhir.jpa.subscription.module.matcher.SubscriptionMatchResult;
|
import ca.uhn.fhir.jpa.subscription.module.matcher.SubscriptionMatchResult;
|
||||||
|
@ -43,16 +44,16 @@ public class CompositeInMemoryDaoSubscriptionMatcher implements ISubscriptionMat
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SubscriptionMatchResult match(String criteria, ResourceModifiedMessage msg) {
|
public SubscriptionMatchResult match(CanonicalSubscription theSubscription, ResourceModifiedMessage theMsg) {
|
||||||
SubscriptionMatchResult result;
|
SubscriptionMatchResult result;
|
||||||
if (myDaoConfig.isEnableInMemorySubscriptionMatching()) {
|
if (myDaoConfig.isEnableInMemorySubscriptionMatching()) {
|
||||||
result = myInMemorySubscriptionMatcher.match(criteria, msg);
|
result = myInMemorySubscriptionMatcher.match(theSubscription, theMsg);
|
||||||
if (!result.supported()) {
|
if (!result.supported()) {
|
||||||
ourLog.info("Criteria {} not supported by InMemoryMatcher: {}. Reverting to DatabaseMatcher", criteria, result.getUnsupportedReason());
|
ourLog.info("Criteria {} for Subscription {} not supported by InMemoryMatcher: {}. Reverting to DatabaseMatcher", theSubscription.getCriteriaString(), theSubscription.getIdElementString(), result.getUnsupportedReason());
|
||||||
result = myDaoSubscriptionMatcher.match(criteria, msg);
|
result = myDaoSubscriptionMatcher.match(theSubscription, theMsg);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
result = myDaoSubscriptionMatcher.match(criteria, msg);
|
result = myDaoSubscriptionMatcher.match(theSubscription, theMsg);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
||||||
import ca.uhn.fhir.jpa.provider.ServletSubRequestDetails;
|
import ca.uhn.fhir.jpa.provider.ServletSubRequestDetails;
|
||||||
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.subscription.module.CanonicalSubscription;
|
||||||
import ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage;
|
import ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage;
|
||||||
import ca.uhn.fhir.jpa.subscription.module.matcher.ISubscriptionMatcher;
|
import ca.uhn.fhir.jpa.subscription.module.matcher.ISubscriptionMatcher;
|
||||||
import ca.uhn.fhir.jpa.subscription.module.matcher.SubscriptionMatchResult;
|
import ca.uhn.fhir.jpa.subscription.module.matcher.SubscriptionMatchResult;
|
||||||
|
@ -49,10 +50,11 @@ public class DaoSubscriptionMatcher implements ISubscriptionMatcher {
|
||||||
MatchUrlService myMatchUrlService;
|
MatchUrlService myMatchUrlService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SubscriptionMatchResult match(String criteria, ResourceModifiedMessage msg) {
|
public SubscriptionMatchResult match(CanonicalSubscription theSubscription, ResourceModifiedMessage theMsg) {
|
||||||
IIdType id = msg.getId(myCtx);
|
IIdType id = theMsg.getId(myCtx);
|
||||||
String resourceType = id.getResourceType();
|
String resourceType = id.getResourceType();
|
||||||
String resourceId = id.getIdPart();
|
String resourceId = id.getIdPart();
|
||||||
|
String criteria = theSubscription.getCriteriaString();
|
||||||
|
|
||||||
// run the subscriptions query and look for matches, add the id as part of the criteria to avoid getting matches of previous resources rather than the recent resource
|
// run the subscriptions query and look for matches, add the id as part of the criteria to avoid getting matches of previous resources rather than the recent resource
|
||||||
criteria += "&_id=" + resourceType + "/" + resourceId;
|
criteria += "&_id=" + resourceType + "/" + resourceId;
|
||||||
|
|
|
@ -4,6 +4,7 @@ import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.jpa.config.TestR4Config;
|
import ca.uhn.fhir.jpa.config.TestR4Config;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
|
||||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||||
|
import ca.uhn.fhir.jpa.subscription.module.CanonicalSubscription;
|
||||||
import ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage;
|
import ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage;
|
||||||
import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
|
import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
|
||||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||||
|
@ -380,10 +381,13 @@ public class InMemorySubscriptionMatcherTestR4 {
|
||||||
params.add(Patient.SP_FAMILY, new StringParam("testSearchNameParam01Fam"));
|
params.add(Patient.SP_FAMILY, new StringParam("testSearchNameParam01Fam"));
|
||||||
try {
|
try {
|
||||||
String criteria = params.toNormalizedQueryString(myContext);
|
String criteria = params.toNormalizedQueryString(myContext);
|
||||||
|
CanonicalSubscription subscription = new CanonicalSubscription();
|
||||||
|
subscription.setCriteriaString(criteria);
|
||||||
|
subscription.setIdElement(new IdType("Subscription", 123L));
|
||||||
ResourceModifiedMessage msg = new ResourceModifiedMessage(myContext, patient, ResourceModifiedMessage.OperationTypeEnum.CREATE);
|
ResourceModifiedMessage msg = new ResourceModifiedMessage(myContext, patient, ResourceModifiedMessage.OperationTypeEnum.CREATE);
|
||||||
msg.setSubscriptionId("Subscription/123");
|
msg.setSubscriptionId("Subscription/123");
|
||||||
msg.setId(new IdType("Patient/ABC"));
|
msg.setId(new IdType("Patient/ABC"));
|
||||||
SubscriptionMatchResult result = myInMemorySubscriptionMatcher.match(criteria, msg);
|
SubscriptionMatchResult result = myInMemorySubscriptionMatcher.match(subscription, msg);
|
||||||
fail();
|
fail();
|
||||||
} catch (InternalErrorException e){
|
} catch (InternalErrorException e){
|
||||||
assertEquals("Failure processing resource ID[Patient/ABC] for subscription ID[Subscription/123]: Invalid resource reference found at path[Patient.managingOrganization] - Does not contain resource type - urn:uuid:13720262-b392-465f-913e-54fb198ff954", e.getMessage());
|
assertEquals("Failure processing resource ID[Patient/ABC] for subscription ID[Subscription/123]: Invalid resource reference found at path[Patient.managingOrganization] - Does not contain resource type - urn:uuid:13720262-b392-465f-913e-54fb198ff954", e.getMessage());
|
||||||
|
|
|
@ -57,7 +57,7 @@ public class CriteriaResourceMatcher {
|
||||||
}
|
}
|
||||||
searchParameterMap.clean();
|
searchParameterMap.clean();
|
||||||
if (searchParameterMap.getLastUpdated() != null) {
|
if (searchParameterMap.getLastUpdated() != null) {
|
||||||
return new SubscriptionMatchResult(Constants.PARAM_LASTUPDATED, "Qualifiers not supported");
|
return new SubscriptionMatchResult(Constants.PARAM_LASTUPDATED, "Standard Parameters not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Map.Entry<String, List<List<? extends IQueryParameterType>>> entry : searchParameterMap.entrySet()) {
|
for (Map.Entry<String, List<List<? extends IQueryParameterType>>> entry : searchParameterMap.entrySet()) {
|
||||||
|
@ -79,7 +79,7 @@ public class CriteriaResourceMatcher {
|
||||||
|
|
||||||
if (hasQualifiers(theAndOrParams)) {
|
if (hasQualifiers(theAndOrParams)) {
|
||||||
|
|
||||||
return new SubscriptionMatchResult(theParamName, "Qualifiers not supported.");
|
return new SubscriptionMatchResult(theParamName, "Standard Parameters not supported.");
|
||||||
|
|
||||||
}
|
}
|
||||||
if (hasPrefixes(theAndOrParams)) {
|
if (hasPrefixes(theAndOrParams)) {
|
||||||
|
|
|
@ -20,8 +20,9 @@ package ca.uhn.fhir.jpa.subscription.module.matcher;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import ca.uhn.fhir.jpa.subscription.module.CanonicalSubscription;
|
||||||
import ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage;
|
import ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage;
|
||||||
|
|
||||||
public interface ISubscriptionMatcher {
|
public interface ISubscriptionMatcher {
|
||||||
SubscriptionMatchResult match(String criteria, ResourceModifiedMessage msg);
|
SubscriptionMatchResult match(CanonicalSubscription subscription, ResourceModifiedMessage msg);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ 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;
|
||||||
import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorService;
|
import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorService;
|
||||||
|
import ca.uhn.fhir.jpa.subscription.module.CanonicalSubscription;
|
||||||
import ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage;
|
import ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
@ -45,11 +46,11 @@ public class InMemorySubscriptionMatcher implements ISubscriptionMatcher {
|
||||||
private InlineResourceLinkResolver myInlineResourceLinkResolver;
|
private InlineResourceLinkResolver myInlineResourceLinkResolver;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SubscriptionMatchResult match(String criteria, ResourceModifiedMessage msg) {
|
public SubscriptionMatchResult match(CanonicalSubscription theSubscription, ResourceModifiedMessage theMsg) {
|
||||||
try {
|
try {
|
||||||
return match(criteria, msg.getNewPayload(myContext));
|
return match(theSubscription.getCriteriaString(), theMsg.getNewPayload(myContext));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new InternalErrorException("Failure processing resource ID[" + msg.getId(myContext) + "] for subscription ID[" + msg.getSubscriptionId() + "]: " + e.getMessage(), e);
|
throw new InternalErrorException("Failure processing resource ID[" + theMsg.getId(myContext) + "] for subscription ID[" + theSubscription.getIdElementString() + "]: " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,14 +43,6 @@ public class SubscriptionMatchResult {
|
||||||
this.myMatcherShortName = theMatcherShortName;
|
this.myMatcherShortName = theMatcherShortName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SubscriptionMatchResult(String theUnsupportedParameter, String theUnsupportedReason, String theMatcherShortName) {
|
|
||||||
this.myMatch = false;
|
|
||||||
this.mySupported = false;
|
|
||||||
this.myUnsupportedParameter = theUnsupportedParameter;
|
|
||||||
this.myUnsupportedReason = theUnsupportedReason;
|
|
||||||
this.myMatcherShortName = theMatcherShortName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean supported() {
|
public boolean supported() {
|
||||||
return mySupported;
|
return mySupported;
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,8 +78,7 @@ public class SubscriptionMatchingSubscriber implements MessageHandler {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
IIdType id = theMsg.getId(myFhirContext);
|
IIdType resourceId = theMsg.getId(myFhirContext);
|
||||||
String resourceType = id.getResourceType();
|
|
||||||
|
|
||||||
Collection<ActiveSubscription> subscriptions = mySubscriptionRegistry.getAll();
|
Collection<ActiveSubscription> subscriptions = mySubscriptionRegistry.getAll();
|
||||||
|
|
||||||
|
@ -87,8 +86,7 @@ public class SubscriptionMatchingSubscriber implements MessageHandler {
|
||||||
|
|
||||||
for (ActiveSubscription nextActiveSubscription : subscriptions) {
|
for (ActiveSubscription nextActiveSubscription : subscriptions) {
|
||||||
|
|
||||||
String nextSubscriptionId = nextActiveSubscription.getIdElement(myFhirContext).toUnqualifiedVersionless().getValue();
|
String nextSubscriptionId = getId(nextActiveSubscription);
|
||||||
String nextCriteriaString = nextActiveSubscription.getCriteriaString();
|
|
||||||
|
|
||||||
if (isNotBlank(theMsg.getSubscriptionId())) {
|
if (isNotBlank(theMsg.getSubscriptionId())) {
|
||||||
if (!theMsg.getSubscriptionId().equals(nextSubscriptionId)) {
|
if (!theMsg.getSubscriptionId().equals(nextSubscriptionId)) {
|
||||||
|
@ -97,29 +95,16 @@ public class SubscriptionMatchingSubscriber implements MessageHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StringUtils.isBlank(nextCriteriaString)) {
|
if (!validCriteria(nextActiveSubscription, resourceId)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// see if the criteria matches the created object
|
SubscriptionMatchResult matchResult = mySubscriptionMatcher.match(nextActiveSubscription.getSubscription(), theMsg);
|
||||||
ourLog.trace("Checking subscription {} for {} with criteria {}", nextSubscriptionId, resourceType, nextCriteriaString);
|
|
||||||
String criteriaResource = nextCriteriaString;
|
|
||||||
int index = criteriaResource.indexOf("?");
|
|
||||||
if (index != -1) {
|
|
||||||
criteriaResource = criteriaResource.substring(0, criteriaResource.indexOf("?"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resourceType != null && nextCriteriaString != null && !criteriaResource.equals(resourceType)) {
|
|
||||||
ourLog.trace("Skipping subscription search for {} because it does not match the criteria {}", resourceType, nextCriteriaString);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
SubscriptionMatchResult matchResult = mySubscriptionMatcher.match(nextCriteriaString, theMsg);
|
|
||||||
if (!matchResult.matched()) {
|
if (!matchResult.matched()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ourLog.info("Subscription {} was matched by resource {} using matcher {}", nextActiveSubscription.getSubscription().getIdElement(myFhirContext).getValue(), id.toUnqualifiedVersionless().getValue(), matchResult.matcherShortName());
|
ourLog.info("Subscription {} was matched by resource {} using matcher {}", nextActiveSubscription.getSubscription().getIdElement(myFhirContext).getValue(), resourceId.toUnqualifiedVersionless().getValue(), matchResult.matcherShortName());
|
||||||
|
|
||||||
ResourceDeliveryMessage deliveryMsg = new ResourceDeliveryMessage();
|
ResourceDeliveryMessage deliveryMsg = new ResourceDeliveryMessage();
|
||||||
deliveryMsg.setPayload(myFhirContext, theMsg.getNewPayload(myFhirContext));
|
deliveryMsg.setPayload(myFhirContext, theMsg.getNewPayload(myFhirContext));
|
||||||
|
@ -136,4 +121,33 @@ public class SubscriptionMatchingSubscriber implements MessageHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getId(ActiveSubscription theActiveSubscription) {
|
||||||
|
return theActiveSubscription.getIdElement(myFhirContext).toUnqualifiedVersionless().getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean validCriteria(ActiveSubscription theActiveSubscription, IIdType theResourceId) {
|
||||||
|
String criteriaString = theActiveSubscription.getCriteriaString();
|
||||||
|
String subscriptionId = getId(theActiveSubscription);
|
||||||
|
String resourceType = theResourceId.getResourceType();
|
||||||
|
|
||||||
|
if (StringUtils.isBlank(criteriaString)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see if the criteria matches the created object
|
||||||
|
ourLog.trace("Checking subscription {} for {} with criteria {}", subscriptionId, resourceType, criteriaString);
|
||||||
|
String criteriaResource = criteriaString;
|
||||||
|
int index = criteriaResource.indexOf("?");
|
||||||
|
if (index != -1) {
|
||||||
|
criteriaResource = criteriaResource.substring(0, criteriaResource.indexOf("?"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resourceType != null && criteriaString != null && !criteriaResource.equals(resourceType)) {
|
||||||
|
ourLog.trace("Skipping subscription search for {} because it does not match the criteria {}", resourceType, criteriaString);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue