Vague skeleton of pointcut

This commit is contained in:
Tadgh 2021-04-09 11:08:47 -04:00
parent fa921a3cc9
commit 8f30f7b0f2
4 changed files with 84 additions and 14 deletions

View File

@ -1511,6 +1511,46 @@ public enum Pointcut implements IPointcut {
"ca.uhn.fhir.rest.api.server.storage.TransactionDetails"
),
/**
* <b>Storage Hook:</b>
* Invoked before a resource will be deleted
* <p>
* Hooks will have access to the contents of the resource being deleted
* but should not make any changes as storage has already occurred
* </p>
* Hooks may accept the following parameters:
* <ul>
* <li>org.hl7.fhir.instance.model.api.IBaseResource - The resource being deleted</li>
* <li>
* ca.uhn.fhir.rest.api.server.RequestDetails - A bean containing details about the request that is about to be processed, including details such as the
* resource type and logical ID (if any) and other FHIR-specific aspects of the request which have been
* pulled out of the servlet request. Note that the bean
* properties are not all guaranteed to be populated, depending on how early during processing the
* exception occurred.
* </li>
* <li>
* ca.uhn.fhir.rest.server.servlet.ServletRequestDetails - A bean containing details about the request that is about to be processed, including details such as the
* resource type and logical ID (if any) and other FHIR-specific aspects of the request which have been
* pulled out of the servlet request. This parameter is identical to the RequestDetails parameter above but will
* only be populated when operating in a RestfulServer implementation. It is provided as a convenience.
* </li>
* <li>
* ca.uhn.fhir.rest.api.server.storage.TransactionDetails - The outer transaction details object (since 5.0.0)
* </li>
* </ul>
* <p>
* Hooks should return <code>void</code>.
* </p>
*/
STORAGE_TRANSACTION_PROCESSED(void.class,
"org.hl7.fhir.instance.model.api.IBaseResource",
"ca.uhn.fhir.rest.api.server.storage.DeferredInterceptorBroadcasts",
"ca.uhn.fhir.rest.api.server.RequestDetails",
"ca.uhn.fhir.rest.server.servlet.ServletRequestDetails",
"ca.uhn.fhir.rest.api.server.storage.TransactionDetails"
),
/**
* <b>Storage Hook:</b>
* Invoked when a resource delete operation is about to fail due to referential integrity checks. Intended for use with {@literal ca.uhn.fhir.jpa.interceptor.CascadingDeleteInterceptor}.

View File

@ -995,25 +995,16 @@ public abstract class BaseTransactionProcessor {
flushSession(theIdToPersistedOutcome);
theTransactionStopWatch.endCurrentTask();
if (conditionalRequestUrls.size() > 0) {
theTransactionStopWatch.startTask("Check for conflicts in conditional resources");
}
/*
* Double check we didn't allow any duplicates we shouldn't have
*/
for (Map.Entry<String, Class<? extends IBaseResource>> nextEntry : conditionalRequestUrls.entrySet()) {
String matchUrl = nextEntry.getKey();
Class<? extends IBaseResource> resType = nextEntry.getValue();
if (isNotBlank(matchUrl)) {
Set<ResourcePersistentId> val = myMatchResourceUrlService.processMatchUrl(matchUrl, resType, theRequest);
if (val.size() > 1) {
throw new InvalidRequestException(
"Unable to process " + theActionName + " - Request would cause multiple resources to match URL: \"" + matchUrl + "\". Does transaction request contain duplicates?");
}
}
if (conditionalRequestUrls.size() > 0) {
theTransactionStopWatch.startTask("Check for conflicts in conditional resources");
}
validateNoDuplicates(theRequest, theActionName, conditionalRequestUrls);
theTransactionStopWatch.endCurrentTask();
for (IIdType next : theAllIds) {
@ -1034,6 +1025,13 @@ public abstract class BaseTransactionProcessor {
JpaInterceptorBroadcaster.doCallHooks(myInterceptorBroadcaster, theRequest, nextPointcut, nextParams);
}
theTransactionDetails.deferredBroadcastProcessingFinished();
//finishedCallingDeferredInterceptorBroadcasts
return entriesToProcess;
} finally {
@ -1043,6 +1041,20 @@ public abstract class BaseTransactionProcessor {
}
}
private void validateNoDuplicates(RequestDetails theRequest, String theActionName, Map<String, Class<? extends IBaseResource>> conditionalRequestUrls) {
for (Map.Entry<String, Class<? extends IBaseResource>> nextEntry : conditionalRequestUrls.entrySet()) {
String matchUrl = nextEntry.getKey();
Class<? extends IBaseResource> resType = nextEntry.getValue();
if (isNotBlank(matchUrl)) {
Set<ResourcePersistentId> val = myMatchResourceUrlService.processMatchUrl(matchUrl, resType, theRequest);
if (val.size() > 1) {
throw new InvalidRequestException(
"Unable to process " + theActionName + " - Request would cause multiple resources to match URL: \"" + matchUrl + "\". Does transaction request contain duplicates?");
}
}
}
}
protected abstract void flushSession(Map<IIdType, DaoMethodOutcome> theIdToPersistedOutcome);
private void validateResourcePresent(IBaseResource theResource, Integer theOrder, String theVerb) {

View File

@ -0,0 +1,8 @@
package ca.uhn.fhir.rest.api.server.storage;
import com.google.common.collect.ListMultimap;
public class DeferredInterceptorBroadcasts {
public DeferredInterceptorBroadcasts(ListMultimap)
}

View File

@ -53,6 +53,7 @@ public class TransactionDetails {
private Map<String, Object> myUserData;
private ListMultimap<Pointcut, HookParams> myDeferredInterceptorBroadcasts;
private EnumSet<Pointcut> myDeferredInterceptorBroadcastPointcuts;
private boolean myIsPointcutDeferred;
/**
* Constructor
@ -189,7 +190,16 @@ public class TransactionDetails {
*/
public void addDeferredInterceptorBroadcast(Pointcut thePointcut, HookParams theHookParams) {
Validate.isTrue(isAcceptingDeferredInterceptorBroadcasts(thePointcut));
myIsPointcutDeferred = true;
myDeferredInterceptorBroadcasts.put(thePointcut, theHookParams);
}
public boolean isPointcutDeferred() {
return myIsPointcutDeferred;
}
public void deferredBroadcastProcessingFinished() {
myIsPointcutDeferred = false;
}
}