Add docs, enum, remove prints

This commit is contained in:
Tadgh 2021-04-21 10:39:23 -04:00
parent e997d49d42
commit ad8921ac4e
8 changed files with 72 additions and 40 deletions

View File

@ -1423,6 +1423,9 @@ public enum Pointcut implements IPointcut {
* <li>
* Boolean - Whether this pointcut invocation was deferred or not(since 5.4.0)
* </li>
* <li>
* ca.uhn.fhir.rest.api.InterceptorInvocationTimingEnum - The timing at which the invocation of the interceptor took place. Options are ACTIVE and DEFERRED.
* </li>
* </ul>
* <p>
* Hooks should return <code>void</code>.
@ -1433,7 +1436,7 @@ public enum Pointcut implements IPointcut {
"ca.uhn.fhir.rest.api.server.RequestDetails",
"ca.uhn.fhir.rest.server.servlet.ServletRequestDetails",
"ca.uhn.fhir.rest.api.server.storage.TransactionDetails",
Boolean.class.getName()
"ca.uhn.fhir.rest.api.InterceptorInvocationTimingEnum"
),
/**
@ -1468,7 +1471,7 @@ public enum Pointcut implements IPointcut {
* ca.uhn.fhir.rest.api.server.storage.TransactionDetails - The outer transaction details object (since 5.0.0)
* </li>
* <li>
* Boolean - Whether this pointcut invocation was deferred or not(since 5.4.0)
* ca.uhn.fhir.rest.api.InterceptorInvocationTimingEnum - The timing at which the invocation of the interceptor took place. Options are ACTIVE and DEFERRED.
* </li>
* </ul>
* <p>
@ -1481,7 +1484,7 @@ public enum Pointcut implements IPointcut {
"ca.uhn.fhir.rest.api.server.RequestDetails",
"ca.uhn.fhir.rest.server.servlet.ServletRequestDetails",
"ca.uhn.fhir.rest.api.server.storage.TransactionDetails",
Boolean.class.getName()
"ca.uhn.fhir.rest.api.InterceptorInvocationTimingEnum"
),
@ -1512,7 +1515,7 @@ public enum Pointcut implements IPointcut {
* ca.uhn.fhir.rest.api.server.storage.TransactionDetails - The outer transaction details object (since 5.0.0)
* </li>
* <li>
* Boolean - Whether this pointcut invocation was deferred or not(since 5.4.0)
* ca.uhn.fhir.rest.api.InterceptorInvocationTimingEnum - The timing at which the invocation of the interceptor took place. Options are ACTIVE and DEFERRED.
* </li>
* </ul>
* <p>
@ -1524,7 +1527,7 @@ public enum Pointcut implements IPointcut {
"ca.uhn.fhir.rest.api.server.RequestDetails",
"ca.uhn.fhir.rest.server.servlet.ServletRequestDetails",
"ca.uhn.fhir.rest.api.server.storage.TransactionDetails",
Boolean.class.getName()
"ca.uhn.fhir.rest.api.InterceptorInvocationTimingEnum"
),
/**

View File

@ -0,0 +1,10 @@
package ca.uhn.fhir.rest.api;
/**
* during invocation of certain pointcuts, it is important to know whether they are being executed in
* active or deferred fashion. This enum allows the pointcuts to see how they were invoked.
*/
public enum InterceptorInvocationTimingEnum {
ACTIVE,
DEFERRED
}

View File

@ -188,12 +188,17 @@ public class BundleUtil {
static int GRAY = 2;
static int BLACK = 3;
/**
*
* @param theContext
* @param theBundle
*/
public static void sortEntriesIntoProcessingOrder(FhirContext theContext, IBaseBundle theBundle) {
Map<BundleEntryParts, IBase> partsToIBaseMap = getPartsToIBaseMap(theContext, theBundle);
LinkedHashSet<IBase> retVal = new LinkedHashSet<>();
//Get all deletions.
LinkedHashSet<IBase> deleteParts = sortEntriesIntoProcessingOrder(theContext, theBundle, RequestTypeEnum.DELETE, partsToIBaseMap);
LinkedHashSet<IBase> deleteParts = sortEntriesOfTypeIntoProcessingOrder(theContext, RequestTypeEnum.DELETE, partsToIBaseMap);
if (deleteParts == null) {
throw new IllegalStateException("Cycle!");
} else {
@ -201,7 +206,7 @@ public class BundleUtil {
}
//Get all Creations
LinkedHashSet<IBase> createParts= sortEntriesIntoProcessingOrder(theContext, theBundle, RequestTypeEnum.POST, partsToIBaseMap);
LinkedHashSet<IBase> createParts= sortEntriesOfTypeIntoProcessingOrder(theContext, RequestTypeEnum.POST, partsToIBaseMap);
if (createParts== null) {
throw new IllegalStateException("Cycle!");
} else {
@ -209,7 +214,7 @@ public class BundleUtil {
}
// Get all Updates
LinkedHashSet<IBase> updateParts= sortEntriesIntoProcessingOrder(theContext, theBundle, RequestTypeEnum.PUT, partsToIBaseMap);
LinkedHashSet<IBase> updateParts= sortEntriesOfTypeIntoProcessingOrder(theContext, RequestTypeEnum.PUT, partsToIBaseMap);
if (updateParts == null) {
throw new IllegalStateException("Cycle!");
} else {
@ -223,7 +228,7 @@ public class BundleUtil {
TerserUtil.setField(theContext, "entry", theBundle, retVal.toArray(new IBase[0]));
}
public static LinkedHashSet<IBase> sortEntriesIntoProcessingOrder(FhirContext theContext, IBaseBundle theBundle, RequestTypeEnum theRequestTypeEnum, Map<BundleEntryParts, IBase> thePartsToIBaseMap) {
private static LinkedHashSet<IBase> sortEntriesOfTypeIntoProcessingOrder(FhirContext theContext, RequestTypeEnum theRequestTypeEnum, Map<BundleEntryParts, IBase> thePartsToIBaseMap) {
SortLegality legality = new SortLegality();
HashMap<String, Integer> color = new HashMap<>();
HashMap<String, List<String>> adjList = new HashMap<>();
@ -299,24 +304,10 @@ public class BundleUtil {
}
}
private static class SortLegality {
private boolean myIsLegal;
SortLegality() {
this.myIsLegal = true;
}
private void setLegal(boolean theLegal) {
myIsLegal = theLegal;
}
public boolean isLegal() {
return myIsLegal;
}
}
private static void depthFirstSearch(String theResourceId, HashMap<String, Integer> theResourceIdToColor, HashMap<String, List<String>> theAdjList, List<String> theTopologicalOrder, SortLegality theLegality) {
System.out.println("RECURSING ON " + theResourceId);
if (!theLegality.isLegal()) {
System.out.println("IMPOSSIBLE!");
ourLog.debug("Found a cycle while trying to sort bundle entries. This bundle is not sortable.");
return;
}
@ -361,6 +352,13 @@ public class BundleUtil {
return map;
}
/**
* Given a bundle, and a consumer, apply the consumer to each entry in the bundle.
* @param theContext The FHIR Context
* @param theBundle The bundle to have its entries processed.
* @param theProcessor a {@link Consumer} which will operate on all the entries of a bundle.
*/
public static void processEntries(FhirContext theContext, IBaseBundle theBundle, Consumer<ModifiableBundleEntry> theProcessor) {
RuntimeResourceDefinition bundleDef = theContext.getResourceDefinition(theBundle);
BaseRuntimeChildDefinition entryChildDef = bundleDef.getChildByName("entry");
@ -483,4 +481,20 @@ public class BundleUtil {
}
return isPatch;
}
private static class SortLegality {
private boolean myIsLegal;
SortLegality() {
this.myIsLegal = true;
}
private void setLegal(boolean theLegal) {
myIsLegal = theLegal;
}
public boolean isLegal() {
return myIsLegal;
}
}
}

View File

@ -70,6 +70,7 @@ import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.parser.LenientErrorHandler;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.InterceptorInvocationTimingEnum;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
@ -1365,7 +1366,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
.add(RequestDetails.class, theRequestDetails)
.addIfMatchesType(ServletRequestDetails.class, theRequestDetails)
.add(TransactionDetails.class, theTransactionDetails)
.add(Boolean.class, theTransactionDetails.isPointcutDeferred(Pointcut.STORAGE_PRECOMMIT_RESOURCE_CREATED));
.add(InterceptorInvocationTimingEnum.class, theTransactionDetails.getInvocationTiming(Pointcut.STORAGE_PRECOMMIT_RESOURCE_CREATED));
doCallHooks(theTransactionDetails, theRequestDetails, Pointcut.STORAGE_PRECOMMIT_RESOURCE_UPDATED, hookParams);
}

View File

@ -54,6 +54,7 @@ import ca.uhn.fhir.jpa.search.PersistedJpaBundleProvider;
import ca.uhn.fhir.jpa.search.cache.SearchCacheStatusEnum;
import ca.uhn.fhir.jpa.search.reindex.IResourceReindexingSvc;
import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
import ca.uhn.fhir.rest.api.InterceptorInvocationTimingEnum;
import ca.uhn.fhir.rest.api.SearchContainedModeEnum;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.util.JpaInterceptorBroadcaster;
@ -377,7 +378,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
.add(RequestDetails.class, theRequest)
.addIfMatchesType(ServletRequestDetails.class, theRequest)
.add(TransactionDetails.class, theTransactionDetails)
.add(Boolean.class, theTransactionDetails.isPointcutDeferred(Pointcut.STORAGE_PRECOMMIT_RESOURCE_CREATED));
.add(InterceptorInvocationTimingEnum.class, theTransactionDetails.getInvocationTiming(Pointcut.STORAGE_PRECOMMIT_RESOURCE_CREATED));
doCallHooks(theTransactionDetails, theRequest, Pointcut.STORAGE_PRECOMMIT_RESOURCE_CREATED, hookParams);
}
@ -485,7 +486,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
.add(RequestDetails.class, theRequestDetails)
.addIfMatchesType(ServletRequestDetails.class, theRequestDetails)
.add(TransactionDetails.class, theTransactionDetails)
.add(Boolean.class, theTransactionDetails.isPointcutDeferred(Pointcut.STORAGE_PRECOMMIT_RESOURCE_DELETED));
.add(InterceptorInvocationTimingEnum.class, theTransactionDetails.getInvocationTiming(Pointcut.STORAGE_PRECOMMIT_RESOURCE_DELETED));
doCallHooks(theTransactionDetails, theRequestDetails, Pointcut.STORAGE_PRECOMMIT_RESOURCE_DELETED, hookParams);
@ -597,7 +598,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
.add(RequestDetails.class, theRequest)
.addIfMatchesType(ServletRequestDetails.class, theRequest)
.add(TransactionDetails.class, transactionDetails)
.add(Boolean.class, transactionDetails.isPointcutDeferred(Pointcut.STORAGE_PRECOMMIT_RESOURCE_DELETED));
.add(InterceptorInvocationTimingEnum.class, transactionDetails.getInvocationTiming(Pointcut.STORAGE_PRECOMMIT_RESOURCE_DELETED));
doCallHooks(transactionDetails, theRequest, Pointcut.STORAGE_PRECOMMIT_RESOURCE_DELETED, hookParams);
}
});
@ -697,7 +698,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
.add(RequestDetails.class, theRequestDetails)
.addIfMatchesType(ServletRequestDetails.class, theRequestDetails)
.add(TransactionDetails.class, theTransactionDetails)
.add(Boolean.class, theTransactionDetails.isPointcutDeferred(Pointcut.STORAGE_PRECOMMIT_RESOURCE_UPDATED));
.add(InterceptorInvocationTimingEnum.class, theTransactionDetails.getInvocationTiming(Pointcut.STORAGE_PRECOMMIT_RESOURCE_UPDATED));
myInterceptorBroadcaster.callHooks(Pointcut.STORAGE_PRECOMMIT_RESOURCE_UPDATED, preCommitParams);
}
@ -742,7 +743,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
.add(RequestDetails.class, theRequestDetails)
.addIfMatchesType(ServletRequestDetails.class, theRequestDetails)
.add(TransactionDetails.class, theTransactionDetails)
.add(Boolean.class, theTransactionDetails.isPointcutDeferred(Pointcut.STORAGE_PRECOMMIT_RESOURCE_UPDATED));
.add(InterceptorInvocationTimingEnum.class, theTransactionDetails.getInvocationTiming(Pointcut.STORAGE_PRECOMMIT_RESOURCE_UPDATED));
myInterceptorBroadcaster.callHooks(Pointcut.STORAGE_PRECOMMIT_RESOURCE_UPDATED, preCommitParams);

View File

@ -4,6 +4,7 @@ import ca.uhn.fhir.interceptor.api.HookParams;
import ca.uhn.fhir.interceptor.api.IInterceptorService;
import ca.uhn.fhir.interceptor.api.Pointcut;
import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome;
import ca.uhn.fhir.rest.api.InterceptorInvocationTimingEnum;
import ca.uhn.fhir.rest.api.server.storage.DeferredInterceptorBroadcasts;
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
@ -313,14 +314,14 @@ public class TransactionHookTest extends BaseJpaR4SystemTest {
assertThat(createPointcutInvocations, hasSize(2));
IBaseResource firstCreatedResource = createPointcutInvocations.get(0).get(IBaseResource.class);
boolean wasDeferred = createPointcutInvocations.get(0).get(Boolean.class);
InterceptorInvocationTimingEnum timing = createPointcutInvocations.get(0).get(InterceptorInvocationTimingEnum.class);
assertTrue(firstCreatedResource instanceof Observation);
assertTrue(wasDeferred);
assertTrue(timing.equals(InterceptorInvocationTimingEnum.DEFERRED));
IBaseResource secondCreatedResource = createPointcutInvocations.get(1).get(IBaseResource.class);
wasDeferred = createPointcutInvocations.get(1).get(Boolean.class);
timing = createPointcutInvocations.get(1).get(InterceptorInvocationTimingEnum.class);
assertTrue(secondCreatedResource instanceof Patient);
assertTrue(wasDeferred);
assertTrue(timing.equals(InterceptorInvocationTimingEnum.DEFERRED));
assertThat(deferredInterceptorBroadcasts.get(Pointcut.STORAGE_PRECOMMIT_RESOURCE_DELETED), hasSize(1));
}

View File

@ -22,6 +22,7 @@ package ca.uhn.fhir.rest.api.server.storage;
import ca.uhn.fhir.interceptor.api.HookParams;
import ca.uhn.fhir.interceptor.api.Pointcut;
import ca.uhn.fhir.rest.api.InterceptorInvocationTimingEnum;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap;
import org.apache.commons.lang3.Validate;
@ -195,12 +196,12 @@ public class TransactionDetails {
myDeferredInterceptorBroadcasts.put(thePointcut, theHookParams);
}
public Boolean isPointcutDeferred(Pointcut thePointcut) {
public InterceptorInvocationTimingEnum getInvocationTiming(Pointcut thePointcut) {
if (myDeferredInterceptorBroadcasts == null) {
return false;
return InterceptorInvocationTimingEnum.ACTIVE;
}
List<HookParams> hookParams = myDeferredInterceptorBroadcasts.get(thePointcut);
return hookParams != null;
return hookParams == null ? InterceptorInvocationTimingEnum.ACTIVE : InterceptorInvocationTimingEnum.DEFERRED;
}
public void deferredBroadcastProcessingFinished() {

View File

@ -39,6 +39,7 @@ import ca.uhn.fhir.rest.annotation.RequiredParam;
import ca.uhn.fhir.rest.annotation.ResourceParam;
import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.rest.annotation.Update;
import ca.uhn.fhir.rest.api.InterceptorInvocationTimingEnum;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.server.IPreResourceAccessDetails;
import ca.uhn.fhir.rest.api.server.IPreResourceShowDetails;
@ -400,7 +401,7 @@ public class HashMapResourceProvider<T extends IBaseResource> implements IResour
.addIfMatchesType(ServletRequestDetails.class, theRequestDetails)
.add(IBaseResource.class, theResource)
.add(TransactionDetails.class, theTransactionDetails)
.add(Boolean.class, theTransactionDetails.isPointcutDeferred(Pointcut.STORAGE_PRECOMMIT_RESOURCE_CREATED));
.add(InterceptorInvocationTimingEnum.class, theTransactionDetails.getInvocationTiming(Pointcut.STORAGE_PRECOMMIT_RESOURCE_CREATED));
interceptorBroadcaster.callHooks(Pointcut.STORAGE_PRECOMMIT_RESOURCE_CREATED, preCommitParams);
} else {
@ -421,7 +422,7 @@ public class HashMapResourceProvider<T extends IBaseResource> implements IResour
.add(IBaseResource.class, myIdToHistory.get(theIdPart).getFirst())
.add(IBaseResource.class, theResource)
.add(TransactionDetails.class, theTransactionDetails)
.add(Boolean.class, theTransactionDetails.isPointcutDeferred(Pointcut.STORAGE_PRECOMMIT_RESOURCE_CREATED));
.add(InterceptorInvocationTimingEnum.class, theTransactionDetails.getInvocationTiming(Pointcut.STORAGE_PRECOMMIT_RESOURCE_CREATED));
interceptorBroadcaster.callHooks(Pointcut.STORAGE_PRECOMMIT_RESOURCE_UPDATED, preCommitParams);
}