001/*-
002 * #%L
003 * Smile CDR - CDR
004 * %%
005 * Copyright (C) 2016 - 2025 Smile CDR, Inc.
006 * %%
007 * All rights reserved.
008 * #L%
009 */
010package ca.cdr.api.fhir.interceptor;
011
012import ca.cdr.api.consent.ConsentActiveResourceResolutionRequest;
013import ca.cdr.api.consent.ConsentFetchQueries;
014import ca.cdr.api.consent.ConsentFixedPolicyRequest;
015import ca.cdr.api.consent.ConsentLookupContext;
016import ca.cdr.api.consent.ConsentResourcePolicyRequest;
017import ca.cdr.api.fhirgw.json.AvailableRoutesJson;
018import ca.cdr.api.fhirgw.json.GatewayTargetJson;
019import ca.cdr.api.fhirgw.json.MatchedRoutesJson;
020import ca.cdr.api.fhirgw.model.CreateRequest;
021import ca.cdr.api.fhirgw.model.DeleteRequest;
022import ca.cdr.api.fhirgw.model.HistoryRequest;
023import ca.cdr.api.fhirgw.model.ISearchResultsAccumulator;
024import ca.cdr.api.fhirgw.model.OperationRequest;
025import ca.cdr.api.fhirgw.model.OperationResponse;
026import ca.cdr.api.fhirgw.model.ReadRequest;
027import ca.cdr.api.fhirgw.model.SearchPageRequest;
028import ca.cdr.api.fhirgw.model.SearchRequest;
029import ca.cdr.api.fhirgw.model.SearchResponse;
030import ca.cdr.api.fhirgw.model.TransactionRequest;
031import ca.cdr.api.fhirgw.model.UpdateRequest;
032import ca.cdr.api.model.json.AuditEventJson;
033import ca.cdr.api.model.json.AuditEventPrePersistJson;
034import ca.cdr.api.model.json.ConvertedTransactionBundlesJson;
035import ca.cdr.api.model.json.IOAuth2ClientDetails;
036import ca.cdr.api.model.json.OAuth2ClientDetailsJson;
037import ca.cdr.api.model.json.OpenIdTokenResponse;
038import ca.cdr.api.model.json.UserSessionDetailsJson;
039import ca.cdr.api.model.json.appgallery.common.AGApplicationJson;
040import ca.cdr.api.model.json.appgallery.console.AGConsoleJson;
041import ca.cdr.api.persistence.megascale.MegaScaleCredentialRequestJson;
042import ca.cdr.api.persistence.megascale.MegaScaleCredentialResponseJson;
043import ca.cdr.api.priorauth.PriorAuthCrdContextJson;
044import ca.cdr.api.pub.cdaexchange.model.CdaToFhirConversionResultJson;
045import ca.cdr.api.pub.hl7v2.model.Hl7v2ToFhirConversionResultJson;
046import ca.uhn.fhir.interceptor.api.IPointcut;
047import ca.uhn.fhir.rest.api.server.RequestDetails;
048import ca.uhn.fhir.rest.api.server.cdshooks.CdsServiceRequestJson;
049import ca.uhn.fhir.rest.server.interceptor.consent.IConsentService;
050import ca.uhn.fhir.rest.server.messaging.json.ResourceOperationJsonMessage;
051import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
052import ca.uhn.hl7v2.model.Message;
053import jakarta.annotation.Nonnull;
054import org.apache.commons.lang3.ArrayUtils;
055import org.apache.http.client.methods.HttpRequestBase;
056import org.hl7.fhir.instance.model.api.IBaseBundle;
057import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
058import org.hl7.fhir.instance.model.api.IBaseResource;
059
060import java.security.KeyStore;
061import java.util.Arrays;
062import java.util.Collections;
063import java.util.HashSet;
064import java.util.List;
065import java.util.Set;
066import java.util.stream.Collectors;
067
068/**
069 * Value for {@link CdrHook#value()}
070 * <p>
071 * Hook pointcuts are divided into several broad categories:
072 * <ul>
073 * <li>FHIRGW_xxx: Hooks on the FHIR Gateway module</li>
074 * </ul>
075 * </p>
076 */
077public enum CdrPointcut implements IPointcut {
078
079        /**
080         * <b>CDA pre-import Hook:</b>
081         * <p>This pointcut provides access to documents before they are imported via the $import-cda endpoint.</p>
082         * <p>Hooks may accept the following parameters:</p>
083         * <ul>
084         *    <li>{@link java.lang.String} - the document to be imported, in xml format.</li>
085         *    <li>{@link ca.cdr.api.pub.cdaexchange.model.CdaToFhirConversionResultJson} - object used to contain all
086         *    relevant data involved in the conversion of a CDA document to an IBaseBundle.</li>
087         * </ul>
088         * <p>Hooks should return the document after performing any modifications.</p>
089         */
090        CDA_PRE_IMPORT(String.class, String.class, CdaToFhirConversionResultJson.class),
091
092        /**
093         * <b>CDA post-import Hook:</b>
094         * <p>This pointcut provides access to documents after they are imported via the $import-cda endpoint.</p>
095         * <p>Hooks may accept the following parameters:</p>
096         * <ul>
097         *    <li>{@link IBaseOperationOutcome} - an operation outcome which can be used to track issues with the import.</li>
098         *    <li>{@link IBaseBundle} - the transaction bundle which can be modified by this Hook.</li>
099         *    <li>{@link java.lang.String} - the document that was imported, in xml format.</li>
100         *    <li>{@link ca.cdr.api.pub.cdaexchange.model.CdaToFhirConversionResultJson} - object used to contain all
101         *    relevant data involved in the conversion of a CDA document to an IBaseBundle.</li>
102         * </ul>
103         * <p>To modify the document before the {@link IBaseBundle} is generated, use the pre-import Hook instead.</p>
104         */
105        CDA_POST_IMPORT(
106                        void.class,
107                        IBaseOperationOutcome.class,
108                        IBaseBundle.class,
109                        String.class,
110                        CdaToFhirConversionResultJson.class),
111
112        /**
113         * <b>CDA post-export Hook:</b>
114         * <p>This pointcut provides access to documents after they are exported, and immediately
115         * before they are returned to the API client.</p>
116         * <p>Hooks may accept the following parameters:</p>
117         * <ul>
118         *    <li>{@link IBaseBundle} - the bundle associated with this export.</li>
119         *    <li>{@link java.lang.String} - the document being exported, in xml format.</li>
120         * </ul>
121         * <p>Hooks should return the document after performing any modifications. The resulting document
122         * is what will be returned to the API client.</p>
123         */
124        CDA_POST_EXPORT(String.class, IBaseBundle.class, String.class),
125
126        /**
127         * <b>Channel Import Hook:</b>
128         * The pointcut provides access to messages received on a broker queue.  It allows an interceptor to
129         * inspect, modify or mark for discard incoming messages before ingestion by the Channel Import module.
130         * <p>
131         * <p>
132         * Hooks may accept the following parameters:
133         * <ul>
134         * <li>
135         * {@link ResourceOperationJsonMessage} - Hook methods for this
136         * pointcut should take a single parameter of ResourceOperationJsonMessage as the input. This object
137         * contains the pre-processed channel import message.
138         * </li>
139         * </ul>
140         *
141         * </p>
142         * Hook methods must return a <code>Boolean</code> which indicates whether to process the message.
143         */
144        CHANNEL_IMPORT_MESSAGE_PRE_PROCESSED(Boolean.class, ResourceOperationJsonMessage.class),
145
146        /**
147         * <b>FHIR Gateway Hook:</b>
148         * This hook is called when the FHIR Gateway has just determined which routes should be invoked for
149         * a given FHIR <b>delete</b> operation. This hook is called once per client request, regardless of how many individual
150         * targets are eventually invoked against.
151         * <p>
152         * Hooks may accept the following parameters:
153         * <ul>
154         * <li>
155         * {@link ca.uhn.fhir.rest.server.servlet.ServletRequestDetails} - A bean containing details about the request that
156         * is about to be processed.
157         * </li>
158         * <li>
159         * {@link ca.cdr.api.fhirgw.model.DeleteRequest} - The delete that is about to be invoked. The hook method can modify this request, and modifications will affect all the operations that are performed against the target servers
160         * </li>
161         * <li>
162         * {@link ca.cdr.api.fhirgw.json.MatchedRoutesJson} - A collection of {@link ca.cdr.api.fhirgw.json.IBaseRouteJson} which have been selected for this request. Routes can be added or removed from this collection to affect which routes are invoked. They can be cast to their specific subclasses if necessary.
163         * </li>
164         * <li>
165         * {@link ca.cdr.api.fhirgw.json.AvailableRoutesJson} - A collection of {@link ca.cdr.api.fhirgw.json.IBaseRouteJson} which match the operation type of the request, e.g. read, create, delete, search, operation.
166         * </li>
167         * </ul>
168         * </p>
169         * Hook methods must return <code>void</code>.
170         *
171         */
172        FHIRGW_DELETE_POST_SELECT_ROUTE(
173                        void.class,
174                        ServletRequestDetails.class,
175                        DeleteRequest.class,
176                        MatchedRoutesJson.class,
177                        AvailableRoutesJson.class),
178
179        /**
180         * <b>FHIR Gateway Hook:</b>
181         * This hook is called when the FHIR Gateway has just determined which routes should be invoked for
182         * a given FHIR <b>update</b> operation. This hook is called once per client request, regardless of how many individual
183         * targets are eventually invoked against.
184         * <p>
185         * Hooks may accept the following parameters:
186         * <ul>
187         * <li>
188         * {@link ca.uhn.fhir.rest.server.servlet.ServletRequestDetails} - A bean containing details about the request that
189         * is about to be processed.
190         * </li>
191         * <li>
192         * {@link ca.cdr.api.fhirgw.model.UpdateRequest} - The update that is about to be invoked. The hook method can modify this request, and modifications will affect all the operations that are performed against the target servers
193         * </li>
194         * <li>
195         * {@link ca.cdr.api.fhirgw.json.MatchedRoutesJson} - A collection of {@link ca.cdr.api.fhirgw.json.IBaseRouteJson} which have been selected for this request. Routes can be added or removed from this collection to affect which routes are invoked. They can be cast to their specific subclasses if necessary.
196         * </li>
197         * <li>
198         * {@link ca.cdr.api.fhirgw.json.AvailableRoutesJson} - A collection of {@link ca.cdr.api.fhirgw.json.IBaseRouteJson} which match the operation type of the request, e.g. read, create, delete, search, operation.
199         * </li>
200         * </ul>
201         * </p>
202         * Hook methods must return <code>void</code>.
203         *
204         */
205        FHIRGW_UPDATE_POST_SELECT_ROUTE(
206                        void.class,
207                        ServletRequestDetails.class,
208                        UpdateRequest.class,
209                        MatchedRoutesJson.class,
210                        AvailableRoutesJson.class),
211
212        /**
213         * <b>FHIR Gateway Hook:</b>
214         * This hook is called when the FHIR Gateway has just determined which routes should be invoked for
215         * a given FHIR <b>operation</b> operation. This hook is called once per client request, regardless of how many individual
216         * targets are eventually invoked against.
217         * <p>
218         * Hooks may accept the following parameters:
219         * <ul>
220         * <li>
221         * {@link ca.uhn.fhir.rest.server.servlet.ServletRequestDetails} - A bean containing details about the request that
222         * is about to be processed.
223         * </li>
224         * <li>
225         * {@link ca.cdr.api.fhirgw.model.OperationRequest} - The operation that is about to be invoked. The hook method can modify this request, and modifications will affect all the operations that are performed against the target servers
226         * </li>
227         * <li>
228         * {@link ca.cdr.api.fhirgw.json.MatchedRoutesJson} - A collection of {@link ca.cdr.api.fhirgw.json.IBaseRouteJson} which have been selected for this request. Routes can be added or removed from this collection to affect which routes are invoked. They can be cast to their specific subclasses if necessary.
229         * </li>
230         * <li>
231         * {@link ca.cdr.api.fhirgw.json.AvailableRoutesJson} - A collection of {@link ca.cdr.api.fhirgw.json.IBaseRouteJson} which match the operation type of the request, e.g. read, create, delete, search, operation.
232         * </li>
233         * </ul>
234         * </p>
235         * Hook methods must return <code>void</code>.
236         *
237         */
238        FHIRGW_OPERATION_POST_SELECT_ROUTE(
239                        void.class,
240                        ServletRequestDetails.class,
241                        OperationRequest.class,
242                        MatchedRoutesJson.class,
243                        AvailableRoutesJson.class),
244
245        /**
246         * <b>FHIR Gateway Hook:</b>
247         * This hook is called when the FHIR Gateway has just determined which routes should be invoked for
248         * a given FHIR <b>search</b> operation. This hook is called once per client request, regardless of how many individual
249         * targets are eventually invoked against.
250         * <p>
251         * Hooks may accept the following parameters:
252         * <ul>
253         * <li>
254         * {@link ca.uhn.fhir.rest.server.servlet.ServletRequestDetails} - A bean containing details about the request that
255         * is about to be processed.
256         * </li>
257         * <li>
258         * {@link ca.cdr.api.fhirgw.model.SearchRequest} - The search that is about to be invoked. The hook method can modify this request, and modifications will affect all the operations that are performed against the target servers
259         * </li>
260         * <li>
261         * {@link ca.cdr.api.fhirgw.json.MatchedRoutesJson} - A collection of {@link ca.cdr.api.fhirgw.json.IBaseRouteJson} which have been selected for this request. Routes can be added or removed from this collection to affect which routes are invoked. They can be cast to their specific subclasses if necessary.
262         * </li>
263         * <li>
264         * {@link ca.cdr.api.fhirgw.json.AvailableRoutesJson} - A collection of {@link ca.cdr.api.fhirgw.json.IBaseRouteJson} which match the operation type of the request, e.g. read, create, delete, search, operation.
265         * </li>
266         * </ul>
267         * </p>
268         * Hook methods must return <code>void</code>.
269         *
270         */
271        FHIRGW_SEARCH_POST_SELECT_ROUTE(
272                        void.class,
273                        ServletRequestDetails.class,
274                        SearchRequest.class,
275                        MatchedRoutesJson.class,
276                        AvailableRoutesJson.class),
277
278        /**
279         * <b>FHIR Gateway Hook:</b>
280         * This hook is called when the FHIR Gateway has just determined which routes should be invoked for
281         * a given FHIR <b>create</b> operation. This hook is called once per client request, regardless of how many individual
282         * targets are eventually invoked against.
283         * <p>
284         * Hooks may accept the following parameters:
285         * <ul>
286         * <li>
287         * {@link ca.uhn.fhir.rest.server.servlet.ServletRequestDetails} - A bean containing details about the request that
288         * is about to be processed.
289         * </li>
290         * <li>
291         * {@link ca.cdr.api.fhirgw.model.CreateRequest} - The create that is about to be invoked. The hook method can modify this request, and modifications will affect all the operations that are performed against the target servers
292         * </li>
293         * <li>
294         * {@link ca.cdr.api.fhirgw.json.MatchedRoutesJson} - A collection of {@link ca.cdr.api.fhirgw.json.IBaseRouteJson} which have been selected for this request. Routes can be added or removed from this collection to affect which routes are invoked. They can be cast to their specific subclasses if necessary.
295         * </li>
296         * <li>
297         * {@link ca.cdr.api.fhirgw.json.AvailableRoutesJson} - A collection of {@link ca.cdr.api.fhirgw.json.IBaseRouteJson} which match the operation type of the request, e.g. read, create, delete, search, operation.
298         * </li>
299         * </ul>
300         * </p>
301         * Hook methods must return <code>void</code>.
302         *
303         */
304        FHIRGW_CREATE_POST_SELECT_ROUTE(
305                        void.class,
306                        ServletRequestDetails.class,
307                        CreateRequest.class,
308                        MatchedRoutesJson.class,
309                        AvailableRoutesJson.class),
310
311        /**
312         * <b>FHIR Gateway Hook:</b>
313         * This hook is called when the FHIR Gateway has just determined which routes should be invoked for
314         * a given FHIR <b>read</b> operation. This hook is called once per client request, regardless of how many individual
315         * targets are eventually invoked against.
316         * <p>
317         * Hooks may accept the following parameters:
318         * <ul>
319         * <li>
320         * {@link ca.uhn.fhir.rest.server.servlet.ServletRequestDetails} - A bean containing details about the request that
321         * is about to be processed.
322         * </li>
323         * <li>
324         * {@link ca.cdr.api.fhirgw.model.ReadRequest} - The read that is about to be invoked. The hook method can modify this request, and modifications will affect all the operations that are performed against the target servers
325         * </li>
326         * <li>
327         * {@link ca.cdr.api.fhirgw.json.MatchedRoutesJson} - A collection of {@link ca.cdr.api.fhirgw.json.IBaseRouteJson} which have been selected for this request. Routes can be added or removed from this collection to affect which routes are invoked. They can be cast to their specific subclasses if necessary.
328         * </li>
329         * <li>
330         * {@link ca.cdr.api.fhirgw.json.AvailableRoutesJson} - A collection of {@link ca.cdr.api.fhirgw.json.IBaseRouteJson} which match the operation type of the request, e.g. read, create, delete, search, operation.
331         * </li>
332         * </ul>
333         * </p>
334         * Hook methods must return <code>void</code>.
335         *
336         */
337        FHIRGW_READ_POST_SELECT_ROUTE(
338                        void.class,
339                        ServletRequestDetails.class,
340                        ReadRequest.class,
341                        MatchedRoutesJson.class,
342                        AvailableRoutesJson.class),
343
344        /**
345         * <b>FHIR Gateway Hook:</b>
346         * This hook is called when the FHIR Gateway has just determined which routes should be invoked for
347         * a given FHIR <b>transaction</b> operation. This hook is called once per client request, regardless of how many individual
348         * targets are eventually invoked against.
349         * <p>
350         * Hooks may accept the following parameters:
351         * <ul>
352         * <li>
353         * {@link ca.uhn.fhir.rest.server.servlet.ServletRequestDetails} - A bean containing details about the request that
354         * is about to be processed.
355         * </li>
356         * <li>
357         * {@link ca.cdr.api.fhirgw.model.TransactionRequest} - The transaction that is about to be invoked. The hook method can modify this request, and modifications will affect all the operations that are performed against the target servers.
358         * </li>
359         * <li>
360         * {@link ca.cdr.api.fhirgw.json.MatchedRoutesJson} - A collection of {@link ca.cdr.api.fhirgw.json.IBaseRouteJson} which have been selected for this request. Routes can be added or removed from this collection to affect which routes are invoked. They can be cast to their specific subclasses if necessary.
361         * </li>
362         * <li>
363         * {@link ca.cdr.api.fhirgw.json.AvailableRoutesJson} - A collection of {@link ca.cdr.api.fhirgw.json.IBaseRouteJson} which match the operation type of the request, e.g. read, create, delete, search, operation.
364         * </li>
365         * </ul>
366         * </p>
367         * Hook methods must return <code>void</code>.
368         *
369         */
370        FHIRGW_TRANSACTION_POST_SELECT_ROUTE(
371                        void.class,
372                        ServletRequestDetails.class,
373                        TransactionRequest.class,
374                        MatchedRoutesJson.class,
375                        AvailableRoutesJson.class),
376
377        /**
378         * <b>FHIR Gateway Hook:</b>
379         * This hook is called when the FHIR Gateway is about to invoke a FHIR <b>read</b> or <b>vread</b> operation against an individual
380         * target server. This hook is called once for each target that will be called, so if a single client read is being
381         * multicasted against two target servers, this hook will be invoked twice.
382         * <p>
383         * Hooks may accept the following parameters:
384         * <ul>
385         * <li>
386         * {@link ca.cdr.api.fhirgw.model.ReadRequest} - The read that is about to be invoked. The hook method can modify this request, and modifications will affect the operation that is actually performed against the target server.
387         * </li>
388         * <li>
389         * {@link ca.cdr.api.fhirgw.json.GatewayTargetJson} - The gateway target server definition. Hook methods should not modify this object, and any changes will be ignored.
390         * </li>
391         * <li>
392         * {@link ca.uhn.fhir.rest.server.servlet.ServletRequestDetails} - A bean containing details about the request that
393         * is about to be processed.
394         * </li>
395         * </ul>
396         * </p>
397         * Hook methods must return <code>void</code>.
398         */
399        FHIRGW_READ_TARGET_PREINVOKE(void.class, ReadRequest.class, GatewayTargetJson.class, ServletRequestDetails.class),
400
401        /**
402         * <b>FHIR Gateway Hook:</b>
403         * This hook is called when the FHIR Gateway is about to invoke a FHIR <b>instance history</b> operation against an individual
404         * target server. This hook is called once for each target that will be called, so if a single client instance history is being
405         * multicast against two target servers, this hook will be invoked twice.
406         * <p>
407         * Hooks may accept the following parameters:
408         * <ul>
409         * <li>
410         * {@link ca.cdr.api.fhirgw.model.HistoryRequest} - The instance history that is about to be invoked. The hook method can modify this request, and modifications will affect the operation that is actually performed against the target server.
411         * </li>
412         * <li>
413         * {@link ca.cdr.api.fhirgw.json.GatewayTargetJson} - The gateway target server definition. Hook methods should not modify this object, and any changes will be ignored.
414         * </li>
415         * <li>
416         * {@link ca.uhn.fhir.rest.server.servlet.ServletRequestDetails} - A bean containing details about the request that
417         * is about to be processed.
418         * </li>
419         * </ul>
420         * </p>
421         * Hook methods must return <code>void</code>.
422         */
423        FHIRGW_INSTANCE_HISTORY_TARGET_PREINVOKE(
424                        void.class, HistoryRequest.class, GatewayTargetJson.class, ServletRequestDetails.class),
425
426        /**
427         * <b>FHIR Gateway Hook:</b>
428         * This hook is called when the FHIR Gateway has just determined which routes should be invoked for
429         * a given FHIR <b>instance history</b> operation. This hook is called once per client request, regardless of how many individual
430         * targets are eventually invoked.
431         * <p>
432         * Hooks may accept the following parameters:
433         * <ul>
434         * <li>
435         * {@link ca.uhn.fhir.rest.server.servlet.ServletRequestDetails} - A bean containing details about the request that
436         * is about to be processed.
437         * </li>
438         * <li>
439         * {@link ca.cdr.api.fhirgw.model.HistoryRequest} - The transaction that is about to be invoked. The hook method can modify this request, and modifications will affect all the operations that are performed against the target servers.
440         * </li>
441         * <li>
442         * {@link ca.cdr.api.fhirgw.json.MatchedRoutesJson} - A collection of {@link ca.cdr.api.fhirgw.json.IBaseRouteJson} which have been selected for this request. Routes can be added or removed from this collection to affect which routes are invoked. They can be cast to their specific subclasses if necessary.
443         * </li>
444         * <li>
445         * {@link ca.cdr.api.fhirgw.json.AvailableRoutesJson} - A collection of {@link ca.cdr.api.fhirgw.json.IBaseRouteJson} which match the operation type of the request, e.g. read, create, delete, search, operation.
446         * </li>
447         * </ul>
448         * </p>
449         * Hook methods must return <code>void</code>.
450         *
451         */
452        FHIRGW_INSTANCE_HISTORY_POST_SELECT_ROUTE(
453                        void.class,
454                        ServletRequestDetails.class,
455                        HistoryRequest.class,
456                        MatchedRoutesJson.class,
457                        AvailableRoutesJson.class),
458
459        /**
460         * <b>FHIR Gateway Hook:</b>
461         * This hook is called when the FHIR Gateway is about to invoke a FHIR <b>operation</b> operation against an individual
462         * target server.
463         * <p>
464         * Hooks may accept the following parameters:
465         * <ul>
466         * <li>
467         * {@link ca.cdr.api.fhirgw.model.OperationRequest} - The read that is about to be invoked. The hook method can modify this request, and modifications will affect the operation that is actually performed against the target server.
468         * </li>
469         * <li>
470         * {@link ca.cdr.api.fhirgw.json.GatewayTargetJson} - The gateway target server definition. Hook methods should not modify this object, and any changes will be ignored.
471         * </li>
472         * <li>
473         * {@link ca.uhn.fhir.rest.server.servlet.ServletRequestDetails} - A bean containing details about the request that
474         * is about to be processed.
475         * </li>
476         * </ul>
477         * </p>
478         * Hook methods must return <code>void</code>.
479         */
480        FHIRGW_OPERATION_TARGET_PREINVOKE(
481                        void.class, OperationRequest.class, GatewayTargetJson.class, ServletRequestDetails.class),
482
483        /**
484         * <b>FHIR Gateway Hook:</b>
485         * This hook is called when the FHIR Gateway has finished invoking a FHIR <b>extended operation</b> operation against an individual
486         * target server. This hook is called once for each target that has been called, so if a single client operation is being
487         * multicasted against two target servers, this hook will be invoked twice.
488         * <p>
489         * <p>
490         * Hooks may accept the following parameters:
491         * <ul>
492         * <li>
493         * {@link ca.cdr.api.fhirgw.json.GatewayTargetJson} - The gateway target server definition. Hook methods should not modify this object, and any changes will be ignored.
494         * </li>
495         * <li>
496         * {@link ISearchResultsAccumulator} - The accumulator being used to collect the search results so far. This may be empty in the case of operations
497         * which do not return search results. Some operations, such as <b>$everything</b>, will return search results, but others such as <b>$</b>
498         * Hook methods may use this object to inspect results received by other endpoints when searching in serial mode, and can
499         * modify the results as needed. Note that the {@link #FHIRGW_SEARCH_TARGET_POSTINVOKE} pointcut is invoked once for each gateway
500         * target, <b>before</b> the search results are added to the accumulator. Results from the current target are found in the
501         * {@link SearchResponse} object, and will be moved from that object into the accumulator after this pointcut is complete.
502         * </li>
503         * <li>
504         * {@link ca.cdr.api.fhirgw.model.OperationResponse} - This object contains the Operation Response from the individual Gateway Target that was called. Interceptors may modify this object in any way they want. This may be null if the operation returns a Bundle (check the SearchResultsAccumulator instead).
505         * </li>
506         * </ul>
507         * </p>
508         * Hook methods must return <code>void</code>.
509         *
510         **/
511        FHIRGW_OPERATION_TARGET_POSTINVOKE(
512                        void.class,
513                        OperationRequest.class,
514                        ISearchResultsAccumulator.class,
515                        OperationResponse.class,
516                        GatewayTargetJson.class,
517                        ServletRequestDetails.class),
518
519        /**
520         * <b>FHIR Gateway Hook:</b>
521         * This hook is called when the FHIR Gateway is about to invoke a FHIR <b>search</b> operation against an individual
522         * target server. This hook is called once for each target that will be called, so if a single client search is being
523         * multicasted against two target servers, this hook will be invoked twice.
524         * <p>
525         * This hook can be contrasted with {@link #FHIRGW_SEARCH_PAGE_TARGET_PREINVOKE}:
526         * <ul>
527         *    <li>{@link #FHIRGW_SEARCH_TARGET_PREINVOKE} is called before the initial search is performed (which should return search results as well as paging links)</li>
528         *    <li>{@link #FHIRGW_SEARCH_PAGE_TARGET_PREINVOKE} is called before the subsequent pages of results are fetched</li>
529         * </ul>
530         * </p>
531         * <p>
532         * Hooks may accept the following parameters:
533         * <ul>
534         * <li>
535         * {@link ca.cdr.api.fhirgw.model.SearchRequest} - The search that is about to be invoked. The hook method can modify this request, and modifications will affect the operation that is actually performed against the target server.
536         * </li>
537         * <li>
538         * {@link ca.cdr.api.fhirgw.json.GatewayTargetJson} - The gateway target server definition. Hook methods should not modify this object, and any changes will be ignored.
539         * </li>
540         * <li>
541         * {@link ISearchResultsAccumulator} - The accumulator being used to collect the search results so far. Hook methods may use this object to inspect results recieved by other endpoints when searching in serial mode, and can modify the results as needed.
542         * </li>
543         * <li>
544         * {@link ca.uhn.fhir.rest.server.servlet.ServletRequestDetails} - A bean containing details about the request that
545         * is about to be processed.
546         * </li>
547         * </ul>
548         * </p>
549         * Hook methods must return <code>void</code>.
550         */
551        FHIRGW_SEARCH_TARGET_PREINVOKE(
552                        void.class,
553                        SearchRequest.class,
554                        GatewayTargetJson.class,
555                        ISearchResultsAccumulator.class,
556                        ServletRequestDetails.class),
557
558        /**
559         * <b>FHIR Gateway Hook:</b>
560         * This hook is called when the FHIR Gateway is about to invoke a FHIR <b>search</b> paging operation against an individual
561         * target server. This hook is called once for each target that will be called, so if a single client search is being
562         * multicasted against two target servers, this hook will be invoked twice.
563         * <p>
564         * This hook can be contrasted with {@link #FHIRGW_SEARCH_TARGET_PREINVOKE}:
565         * <ul>
566         *    <li>{@link #FHIRGW_SEARCH_TARGET_PREINVOKE} is called before the initial search is performed (which should return search results as well as paging links)</li>
567         *    <li>{@link #FHIRGW_SEARCH_PAGE_TARGET_PREINVOKE} is called before the subsequent pages of results are fetched</li>
568         * </ul>
569         * </p>
570         * <p>
571         * Hooks may accept the following parameters:
572         * <ul>
573         * <li>
574         * {@link ca.cdr.api.fhirgw.model.SearchPageRequest} - The search that is about to be invoked. The hook method can modify this request, and modifications will affect the operation that is actually performed against the target server.
575         * </li>
576         * <li>
577         * {@link ca.cdr.api.fhirgw.json.GatewayTargetJson} - The gateway target server definition. Hook methods should not modify this object, and any changes will be ignored.
578         * </li>
579         * <li>
580         * {@link ISearchResultsAccumulator} - The accumulator being used to collect the search results so far. Hook methods may use this object to inspect results received by other endpoints when searching in serial mode, and can modify the results as needed.
581         * </li>
582         * <li>
583         * {@link ca.uhn.fhir.rest.server.servlet.ServletRequestDetails} - A bean containing details about the request that
584         * is about to be processed.
585         * </li>
586         * </ul>
587         * </p>
588         * Hook methods must return <code>void</code>.
589         */
590        FHIRGW_SEARCH_PAGE_TARGET_PREINVOKE(
591                        void.class,
592                        SearchPageRequest.class,
593                        GatewayTargetJson.class,
594                        ISearchResultsAccumulator.class,
595                        ServletRequestDetails.class),
596
597        /**
598         * <b>FHIR Gateway Hook:</b>
599         * This hook is called when the FHIR Gateway has finished invoking a FHIR <b>search</b> operation against an individual
600         * target server. This hook is called once for each target that has been called, so if a single client search is being
601         * multicasted against two target servers, this hook will be invoked twice.
602         * <p>
603         * <p>
604         * Hooks may accept the following parameters:
605         * <ul>
606         * <li>
607         * {@link ca.cdr.api.fhirgw.json.GatewayTargetJson} - The gateway target server definition. Hook methods should not modify this object, and any changes will be ignored.
608         * </li>
609         * <li>
610         * {@link ISearchResultsAccumulator} - The accumulator being used to collect the search results so far.
611         * Hook methods may use this object to inspect results received by other endpoints when searching in serial mode, and can
612         * modify the results as needed. Note that the {@link #FHIRGW_SEARCH_TARGET_POSTINVOKE} pointcut is invoked once for each gateway
613         * target, <b>before</b> the search results are added to the accumulator. Results from the current target are found in the
614         * {@link SearchResponse} object, and will be moved from that object into the accumulator after this pointcut is complete.
615         * </li>
616         * <li>
617         * {@link ca.cdr.api.fhirgw.model.SearchResponse} - This object contains the search results from the individual Gateway Target that was called. Interceptors may modify this object in any way they want.
618         * </li>
619         * </ul>
620         * </p>
621         * Hook methods must return <code>void</code>.
622         */
623        FHIRGW_SEARCH_TARGET_POSTINVOKE(
624                        void.class,
625                        GatewayTargetJson.class,
626                        ISearchResultsAccumulator.class,
627                        SearchResponse.class,
628                        ServletRequestDetails.class),
629
630        /**
631         * <b>FHIR Gateway Hook:</b>
632         * This hook is called when the FHIR Gateway is about to invoke a FHIR <b>create</b> operation against an individual
633         * target server. This hook is called once for each target that will be called, so if a single client create is being
634         * multicasted against two target servers, this hook will be invoked twice.
635         * <p>
636         * For creates where a client id is specified, the <b>update</b> hook will be fired instead.
637         * </p>
638         * <p>
639         * Hooks may accept the following parameters:
640         * <ul>
641         * <li>
642         * {@link ca.cdr.api.fhirgw.model.CreateRequest} - The create that is about to be invoked. The hook method can modify this request, and modifications will affect the operation that is actually performed against the target server.
643         * </li>
644         * <li>
645         * {@link ca.cdr.api.fhirgw.json.GatewayTargetJson} - The gateway target server definition. Hook methods should not modify this object, and any changes will be ignored.
646         * </li>
647         * <li>
648         * {@link ca.uhn.fhir.rest.server.servlet.ServletRequestDetails} - A bean containing details about the request that
649         * is about to be processed.
650         * </li>
651         * </ul>
652         * </p>
653         * Hook methods must return <code>void</code>.
654         */
655        FHIRGW_CREATE_TARGET_PREINVOKE(
656                        void.class, CreateRequest.class, GatewayTargetJson.class, ServletRequestDetails.class),
657
658        /**
659         * <b>FHIR Gateway Hook:</b>
660         * This hook is called when the FHIR Gateway is about to invoke a FHIR <b>transaction</b> operation against an individual
661         * target server. This hook is called once for each target that will be called, so if a single client create is being
662         * multicasted against two target servers, this hook will be invoked twice.
663         * <p>
664         * For creates where a client id is specified, the <b>update</b> hook will be fired instead.
665         * </p>
666         * <p>
667         * Hooks may accept the following parameters:
668         * <ul>
669         * <li>
670         * {@link ca.cdr.api.fhirgw.model.TransactionRequest} - The transaction that is about to be invoked. The hook method can modify this request, and modifications will affect the operation that is actually performed against the target server.
671         * </li>
672         * <li>
673         * {@link ca.cdr.api.fhirgw.json.GatewayTargetJson} - The gateway target server definition. Hook methods should not modify this object, and any changes will be ignored.
674         * </li>
675         * <li>
676         * {@link ca.uhn.fhir.rest.server.servlet.ServletRequestDetails} - A bean containing details about the request that
677         * is about to be processed.
678         * </li>
679         * </ul>
680         * </p>
681         * Hook methods must return <code>void</code>.
682         */
683        FHIRGW_TRANSACTION_TARGET_PREINVOKE(
684                        void.class, TransactionRequest.class, GatewayTargetJson.class, ServletRequestDetails.class),
685
686        /**
687         * <b>FHIR Gateway Hook:</b>
688         * This hook is called when the FHIR Gateway is about to invoke a FHIR <b>update</b> operation against an individual
689         * target server. This hook is called once for each target that will be called, so if a single client update is being
690         * multicasted against two target servers, this hook will be invoked twice.
691         * <p>
692         * This hook will also be called for <b>create</b> operations when a client id is provided.
693         * </p>
694         * <p>
695         * Hooks may accept the following parameters:
696         * <ul>
697         * <li>
698         * {@link ca.cdr.api.fhirgw.model.UpdateRequest} - The update that is about to be invoked. The hook method can modify this request, and modifications will affect the operation that is actually performed against the target server.
699         * </li>
700         * <li>
701         * {@link ca.cdr.api.fhirgw.json.GatewayTargetJson} - The gateway target server definition. Hook methods should not modify this object, and any changes will be ignored.
702         * </li>
703         * <li>
704         * {@link ca.uhn.fhir.rest.server.servlet.ServletRequestDetails} - A bean containing details about the request that
705         * is about to be processed.
706         * </li>
707         * </ul>
708         * </p>
709         * Hook methods must return <code>void</code>.
710         */
711        FHIRGW_UPDATE_TARGET_PREINVOKE(
712                        void.class, UpdateRequest.class, GatewayTargetJson.class, ServletRequestDetails.class),
713
714        /**
715         * <b>FHIR Gateway Hook:</b>
716         * This hook is called when the FHIR Gateway is about to invoke a FHIR <b>delete</b> operation against an individual
717         * target server. This hook is called once for each target that will be called, so if a single client delete is being
718         * multicasted against two target servers, this hook will be invoked twice.
719         * <p>
720         * Hooks may accept the following parameters:
721         * <ul>
722         * <li>
723         * {@link ca.cdr.api.fhirgw.model.DeleteRequest} - The delete that is about to be invoked. The hook method can modify this request, and modifications will affect the operation that is actually performed against the target server.
724         * </li>
725         * <li>
726         * {@link ca.cdr.api.fhirgw.json.GatewayTargetJson} - The gateway target server definition. Hook methods should not modify this object, and any changes will be ignored.
727         * </li>
728         * <li>
729         * {@link ca.uhn.fhir.rest.server.servlet.ServletRequestDetails} - A bean containing details about the request that
730         * is about to be processed.
731         * </li>
732         * </ul>
733         * </p>
734         * Hook methods must return <code>void</code>.
735         */
736        FHIRGW_DELETE_TARGET_PREINVOKE(
737                        void.class, DeleteRequest.class, GatewayTargetJson.class, ServletRequestDetails.class),
738
739        /**
740         * <b>HL7v2 Hook:</b>
741         * This hook is the first one called when a HL7v2 endpoint processes incoming messages.  It is invoked before
742         * the HL7v2 to FHIR mapping takes place for each incoming request. It may be used to provide
743         * alternate handling for some requests, screen requests before they are handled, alter the incoming message,etc.
744         * <p>
745         * Note that any exceptions thrown by this method will not be trapped by HAPI (they will be passed up to the server)
746         * </p>
747         * <p>
748         * Hooks may accept the following parameters:
749         * <ul>
750         * <li>
751         * {@link ca.uhn.hl7v2.model.Message} - the message that is about to be processed. The hook method can modify this
752         * message and modifications will affect the end result of processing the message by this server.
753         * <br/>
754         * <b>NOTE:</b> This parameter is deprecated. Use {@link Hl7v2ToFhirConversionResultJson#getModifiableMessage()}
755         * or {@link Hl7v2ToFhirConversionResultJson#setModifiableMessage(Message)} instead.
756         * </li>
757         * <li>
758         * {@link Hl7v2ToFhirConversionResultJson} - Contains all relevant data involved in the conversion of an HL7 v2.x
759         * message to a list of IBaseBundle resources.
760         * </li>
761         * </ul>
762         * </p>
763         * Hook methods may return <code>true</code> or <code>void</code> if processing should continue normally.
764         * This is generally the right thing to do. If your interceptor is processing the response rather than
765         * letting HAPI do it, you must return <code>false</code>. In this case,
766         * no further processing will occur.
767         */
768        HL7V2IN_PRE_HL7V2_TO_FHIR_MAPPING_PROCESSING(
769                        Boolean.class, "ca.uhn.hl7v2.model.Message", "ca.cdr.api.pub.hl7v2.model.Hl7v2ToFhirConversionResultJson"),
770
771        /**
772         * <b>HL7v2 Hook:</b>
773         * This hook is invoked after Smile has transformed an HL7V2 message into a collection of Transaction Bundle operations.
774         * <p>
775         * Note that any exceptions thrown by this method will not be trapped by HAPI (they will be passed up to the server)
776         * </p>
777         * <p>
778         * Hooks may accept the following parameters:
779         * <ul>
780         * <li>
781         * {@link ConvertedTransactionBundlesJson} - Contains a list of IBaseBundle objects, each of which represents a transaction about to be executed
782         * against the FHIR repository. Any modifications to this bundle, or additions to it, will be propagated into the repository.
783         * <br/>
784         * <b>NOTE:</b> This parameter is deprecated. Use {@link Hl7v2ToFhirConversionResultJson#getBundles()}
785         * or {@link Hl7v2ToFhirConversionResultJson#setBundles(List)} instead.
786         * </li>
787         * <li>
788         * {@link ca.uhn.hl7v2.model.Message} - the message that was just processed. Any changes to this message will be ignored,
789         * as it has already been processed.
790         * <br/>
791         * <b>NOTE:</b> This parameter is deprecated. Use {@link Hl7v2ToFhirConversionResultJson#getModifiableMessage()}
792         * or {@link Hl7v2ToFhirConversionResultJson#setModifiableMessage(Message)} instead.
793         * </li>
794         * <li>
795         * {@link Hl7v2ToFhirConversionResultJson} - Contains all relevant data involved in the conversion of an HL7 v2.x
796         * message to a list of IBaseBundle resources.
797         * </li>
798         * </ul>
799         * </p>
800         */
801        HL7V2IN_POST_HL7V2_TO_FHIR_MAPPING_PROCESSING(
802                        void.class,
803                        "ca.uhn.hl7v2.model.Message",
804                        "ca.cdr.api.model.json.ConvertedTransactionBundlesJson",
805                        "ca.cdr.api.pub.hl7v2.model.Hl7v2ToFhirConversionResultJson"),
806
807        /**
808         * <b>Persistence (RDBMS) Hook:</b>
809         * This pointcut is invoked once by the Persistence (RDBMS) module when
810         * the module is starting up.
811         *
812         * <p>
813         * Hooks may accept the following parameters:
814         * <ul>
815         * <li>
816         * No parameters.
817         * </li>
818         * </ul>
819         * </p>
820         * Hook methods should not return a value.
821         *
822         * @since 2025.05.R01
823         */
824        STORAGE_STARTING_PRE_START(void.class),
825
826        /**
827         * <b>Persistence (RDBMS) Hook:</b>
828         * This pointcut is invoked my the Persistence (RDBMS) module when
829         * running in MegaScale mode in order to request the database credentials
830         * associated with a given partition ID.
831         * <p>
832         * Hooks may accept the following parameters:
833         * <ul>
834         * <li>
835         * {@link MegaScaleCredentialRequestJson} - Hook methods for this
836         * pointcut should take a {@link MegaScaleCredentialRequestJson}
837         * as input. This object contains the numeric ID of the partition
838         * for which database credentials are wanted.
839         * </li>
840         * </ul>
841         * </p>
842         *
843         * Hook methods for this pointcut must return a
844         * {@link MegaScaleCredentialResponseJson} object which contains the
845         * JDBC URL and credentials associated with the partition ID. These
846         * credentials will be cached, so this Pointcut will not be invoked
847         * repeatedly for the same partition ID (therefore it is ok if hook
848         * methods have some latency).
849         *
850         * @since 2023.02.R01
851         */
852        STORAGE_MEGASCALE_PROVIDE_DB_INFO(MegaScaleCredentialResponseJson.class, MegaScaleCredentialRequestJson.class),
853
854        /**
855         * <b>Server Endpoint Hook:</b>
856         * The pointcut provides the capability to supply a provisioned KeyStore file for TLS base encryption.
857         * Note that pointcut {@link #SERVER_CONFIGURATION_KEYSTORE} is invoked only if the endpoint listener
858         * is said to required TLS encryption for incoming connections through environment property <b>tls.enabled</b>
859         * <p>
860         * <p>
861         * Hooks may accept the following parameters:
862         * <ul>
863         * <li>
864         * {@link java.lang.String} - The keystore password
865         * </li>
866         * </ul>
867         * </p>
868         * <p>
869         * Interceptors for this pointcut must be registered with the specific
870         * endpoint module where the keystore will be used.
871         * </p>
872         * Hook methods must return <code>KeyStore</code>.
873         */
874        SERVER_CONFIGURATION_KEYSTORE(KeyStore.class, String.class),
875
876        /**
877         * <b>SMART/OIDC Hook:</b>
878         * The pointcut is called when a SMART Outbound Security module is configured in
879         * federated mode, and there are multiple federated providers configured, prior to
880         * the user being asked to select a provider. This pointcut can be used to
881         * programmatically select a provider instead of relying on the user to
882         * make a selection.
883         * <p>
884         * Hooks may accept the following parameters:
885         * <ul>
886         * <li>
887         * {@literal ca.cdr.api.fhir.interceptor.OidcAuthRequestDetails} - This object contains details about the auth request and can be used to extract request parameter values.
888         * </li>
889         * </ul>
890         * </p>
891         * Hook methods may return a {@link String}, which should be the Registration ID of an
892         * OpenID Connect Server definition (i.e. the value of the "Registration ID" field in the
893         * Smile CDR OIDC Server definition page). If the returned String is not {@literal null} and
894         * does not match any server definition, the flow will be halted and the user will
895         * see an error. If the returned string is {@literal null}, the user will be
896         * redirected to a server selection screen.
897         */
898        SMART_FEDERATED_OIDC_PRE_PROVIDER_SELECTION(String.class, OidcAuthRequestDetails.class),
899
900        /**
901         * <b>SMART/OIDC Hook:</b>
902         * The pointcut is called when an OIDC client is being saved. This could
903         * mean that a new client is being created, or an existing client
904         * is being updated or disabled.
905         * <p>
906         * This hook is called after the database transaction used to
907         * save the object has been committed. This means that the record already
908         * appears in the database. Any exceptions thrown by hooks for this
909         * pointcut may cause an error to appear for the user requesting the
910         * operation, but will not affect what has been saved in the database,
911         * so no exceptions should be thrown within this pointcut.
912         * </p>
913         * <p>
914         * Hooks may accept the following parameters:
915         * <ul>
916         * <li>
917         * {@link ca.cdr.api.model.json.IOAuth2ClientDetails} - The Client being saved. Pointcuts should not modify this object.
918         * </li>
919         * </ul>
920         * </p>
921         * Hook methods must return <code>void</code>.
922         */
923        SMART_OIDC_CLIENT_SAVED(void.class, IOAuth2ClientDetails.class),
924
925        /**
926         * <b>SMART/OIDC Hook:</b>
927         * The pointcut is called when an OIDC client is being saved. This could
928         * mean that a new client is being created, or an existing client
929         * is being updated or disabled.
930         * <p>
931         * This hook is called within the open database transaction used to
932         * save the object. This means that at the time this pointcut is invoked,
933         * the record does not yet appear in the database. It also means that any
934         * exception thrown by this pointcut will block the operation.
935         * </p>
936         * <p>
937         * Hooks may accept the following parameters:
938         * <ul>
939         * <li>
940         * {@link ca.cdr.api.model.json.IOAuth2ClientDetails} - The Client being saved. Pointcuts should not modify this object.
941         * </li>
942         * </ul>
943         * </p>
944         * Hook methods must return <code>void</code>.
945         */
946        SMART_OIDC_CLIENT_SAVING(void.class, IOAuth2ClientDetails.class),
947
948        /**
949         * <b>appSphere Hook:</b>
950         * The Pointcut is called when an appSphere admin updates the status of an application or service
951         * <p>
952         * This hook is called within the open database transaction used to
953         * save the object. This means that at the time this pointcut is invoked,
954         * the record does not yet appear in the database. It also means that any
955         * exception thrown by this pointcut will block the operation.
956         * </p>
957         * <p>
958         * Hooks may accept the following parameters:
959         * <ul>
960         * <li>
961         * {@link AGConsoleJson} - The application or service being updated. Pointcuts should not modify this object.
962         * </li>
963         * </ul>
964         * </p>
965         * Hook methods must return <code>void</code>.
966         */
967        AG_APPLICATION_STATUS_UPDATING(void.class, AGConsoleJson.class),
968
969        /**
970         * <b>appSphere Hook:</b>
971         * The pointcut is called after an appSphere admin updates the status of an application or service
972         * <p>
973         * This hook is called after the database transaction used to
974         * save the object has been committed. This means that the record already
975         * appears in the database. Any exceptions thrown by hooks for this
976         * pointcut may cause an error to appear for the user requesting the
977         * operation, but will not affect what has been saved in the database,
978         * so no exceptions should be thrown within this pointcut.
979         * </p>
980         * <p>
981         * Hooks may accept the following parameters:
982         * <ul>
983         * <li>
984         * {@link AGConsoleJson} - The application or service that was updated. Pointcuts should not modify this object.
985         * </li>
986         * </ul>
987         * </p>
988         * Hook methods must return <code>void</code>.
989         */
990        AG_APPLICATION_STATUS_UPDATED(void.class, AGConsoleJson.class),
991
992        /**
993         * <b>appSphere Hook:</b>
994         * The Pointcut is called when an appSphere developer registers an application, prior to commiting the registration to the database
995         * <p>
996         * This hook is called within the open database transaction used to
997         * save the object. This means that at the time this pointcut is invoked,
998         * the record does not yet appear in the database. It also means that any
999         * exception thrown by this pointcut will block the operation.
1000         * </p>
1001         * <p>
1002         * Hooks may accept the following parameters:
1003         * <ul>
1004         * <li>
1005         * {@link AGApplicationJson} - The application or service being registered. Pointcuts can modify this object.
1006         * </li>
1007         * </ul>
1008         * </p>
1009         * Hook methods must return <code>void</code>.
1010         */
1011        AG_APPLICATION_REGISTER(void.class, AGApplicationJson.class),
1012
1013        /**
1014         * <b>appSphere Hook:</b>
1015         * The Pointcut is called when an appSphere developer re-registers an application, prior to commiting the registration to the database
1016         * <p>
1017         * This hook is called within the open database transaction used to
1018         * save the object. This means that at the time this pointcut is invoked,
1019         * the record does not yet appear in the database. It also means that any
1020         * exception thrown by this pointcut will block the operation.
1021         * </p>
1022         * <p>
1023         * Hooks may accept the following parameters:
1024         * <ul>
1025         * <li>
1026         * {@link AGApplicationJson} - The application or service being re-registered. Pointcuts can modify this object.
1027         * </li>
1028         * </ul>
1029         * </p>
1030         * Hook methods must return <code>void</code>.
1031         */
1032        AG_APPLICATION_RE_REGISTER(void.class, AGApplicationJson.class),
1033
1034        /**
1035         * <b>System-to-System Data Exchange Hook:</b>
1036         * This pointcut is called when doing resource matching in the $member-match operation. It provides the ability for
1037         * clients to execute custom matching JavaScript for the patient matching in $member-match.
1038         * <p>
1039         * Hooks may accept the following parameters:
1040         * <ul>
1041         * <li>
1042         * {@link ca.cdr.api.fhir.interceptor.IMemberMatchRequest} - the wrapper request object that contains memberPatient
1043         * and CoverageToMatch Resources.
1044         * </li>
1045         * <li>
1046         * {@link ca.uhn.fhir.rest.api.server.RequestDetails} - A bean containing details about the request that is about to
1047         * be processed.
1048         * </li>
1049         * </ul>
1050         * </p>
1051         * Hook methods may return <code>Patient</code> if a matching patient is found, or <code>void</code> otherwise.
1052         * Note that if <code>void</code> is returned, then the system will perform the default matching algorithm to try to
1053         * find any matching patient.
1054         */
1055        MEMBER_MATCH(IBaseResource.class, IMemberMatchRequest.class, RequestDetails.class),
1056
1057        /**
1058         * <b>Consent Module Hook:</b>
1059         * <p>This pointcut can be used by customers to add a new implementation of a Consent resource policy.
1060         * This policy will be used if it is specified in the <code>consentResourcePolicy</code> property of a consent rule.</p>
1061         * <p>Parameters:</p>
1062         * <ul>
1063         * <li>
1064         * {@link ConsentResourcePolicyRequest} - Contains the policy name of the {@link IConsentService} that will be built.
1065         * This will come from the <code>consentResourcePolicy</code> property of a <code>consentRule</code>. This request object also contains
1066         * the Consent resource ({@link IBaseResource}) and the {@link UserSessionDetailsJson} of the user making the request.
1067         * </li>
1068         * </ul>
1069         * <p>Return Value:</p>
1070         * <ul><li>{@link IConsentService} The consent service that should be built from the provided policy name.
1071         * If an <code>IConsentService</code> cannot be mapped to the provided policy, null should be returned.</li></ul>
1072         */
1073        CONSENT_BUILD_CONSENT_RESOURCE_POLICY_CONSENT_SERVICE(IConsentService.class, ConsentResourcePolicyRequest.class),
1074
1075        /**
1076         * <b>Consent Module Hook:</b>
1077         * <p>This pointcut can be used by customers to add a new implementation of a fixed consent policy.
1078         * This policy will be used if it is specified in the <code>fixedPolicy</code> property of a consent rule.
1079         * Unlike a <code>consentResourcePolicy</code>, a <code>fixedPolicy</code> is not dependent on Consent resource.
1080         * A <code>fixedPolicy</code> can be used to make consent decisions based on the user that is requesting to access a resource.</p>
1081         * <p>Parameters:</p>
1082         * <ul>
1083         * <li>
1084         * {@link ConsentFixedPolicyRequest} The fixed policy request containing the policy name, the {@link UserSessionDetailsJson}, and a list of parameters. The
1085         * policy name is the name of the <code>IConsentService</code> that will be built. This will come from the <code>fixedPolicy</code>
1086         * property of a <code>consentRule</code>.
1087         * </li>
1088         * </ul>
1089         * <p>Return Value:</p>
1090         * <ul><li>{@link IConsentService} The consent service that should be built from the provided policy name.
1091         * If an <code>IConsentService</code> cannot be mapped to the provided policy, null should be returned.</li></ul>
1092         */
1093        CONSENT_BUILD_FIXED_POLICY_CONSENT_SERVICE(IConsentService.class, ConsentFixedPolicyRequest.class),
1094
1095        /**
1096         * <b>Consent Hook:</b>
1097         * This pointcut can be used by customers to customize the default behavior of the Consent resource-based
1098         * Consent Service.
1099         * Add the string representation of the (initial) queries that should be used to fetch consent resources to the {@link ConsentFetchQueries} object.
1100         * Implementers can use the {@link RequestDetails}, {@link ConsentLookupContext}, {@link IBaseResource}, and {@link UserSessionDetailsJson}
1101         * to determine the applicable queries.
1102         * <br/><br/>
1103         * <b>Note:</b> At least one of the CONSENT_FETCH_QUERIES or CONSENT_ACTIVE_CONSENT_RESOURCES_RESOLVE pointcuts must be implemented. Both pointcuts may also be implemented.
1104         * <p>
1105         * The hook can have the following parameters:
1106         * <ul>
1107         * <li>
1108         * {@link ConsentFetchQueries} the object that consent fetch queries should be added to.
1109         * </li>
1110         * <li>
1111         * {@link RequestDetails} the request
1112         * </li>
1113         * <li>
1114         * {@link ConsentLookupContext} the consent context object
1115         * </li>
1116         * <li>
1117         * {@link IBaseResource} the current clinical resource being evaluated for consent.  Will be present for willSeeResource and canSeeResource, but null for startOperation.
1118         * </li>
1119         * <li>
1120         * {@link UserSessionDetailsJson} the user session details.
1121         * </li>
1122         * </ul>
1123         * </p>
1124         * Hook methods need to add string representations of the consent queries to the {@link ConsentFetchQueries} object. This should
1125         * consist of one query to have a better performance, but in rare cases multiple queries can be provided.
1126         */
1127        CONSENT_FETCH_QUERIES(
1128                        void.class,
1129                        ConsentFetchQueries.class,
1130                        RequestDetails.class,
1131                        ConsentLookupContext.class,
1132                        IBaseResource.class,
1133                        UserSessionDetailsJson.class),
1134
1135        /**
1136         * <b>Consent Hook:</b> This pointcut can be used by customers to customize the default behavior of the Consent resource-based
1137         * Consent Service.
1138         * Add the Consent resources that should be used for the incoming request to the {@link ConsentActiveResourceResolutionRequest} object.
1139         * Implementers can use the {@link RequestDetails}, {@link ConsentLookupContext}, {@link IBaseResource}, and {@link UserSessionDetailsJson}
1140         * to determine the applicable consents.
1141         * <br/><br/>
1142         * <b>Note:</b> At least one of the CONSENT_ACTIVE_CONSENT_RESOURCES_RESOLVE or CONSENT_FETCH_QUERIES pointcuts must be implemented. Both pointcuts may also be implemented.
1143         * <p>
1144         * The hook can have the following parameters:
1145         * <ul>
1146         * <li>
1147         * {@link ConsentActiveResourceResolutionRequest} the object Consent resources should be added to
1148         * </li>
1149         * <li>
1150         * {@link RequestDetails} the request
1151         * </li>
1152         * <li>
1153         * {@link ConsentLookupContext} the consent context object
1154         * </li>
1155         * <li>
1156         * {@link IBaseResource} the current clinical resource being evaluated for consent.  Will be present for willSeeResource and canSeeResource, but null for startOperation.
1157         * </li>
1158         * <li>
1159         * {@link UserSessionDetailsJson} the user session details.
1160         * </li>
1161         * </ul>
1162         * </p>
1163         */
1164        CONSENT_ACTIVE_CONSENT_RESOURCES_RESOLVE(
1165                        void.class,
1166                        ConsentActiveResourceResolutionRequest.class,
1167                        RequestDetails.class,
1168                        ConsentLookupContext.class,
1169                        IBaseResource.class,
1170                        UserSessionDetailsJson.class),
1171
1172        /**
1173         * <b>Prior Auth CRD Gather context hook:</b>
1174         * This pointcut can be used by customers to customize the default behavior of the Prior Auth CRD
1175         * for determining patientId in Coverage context.
1176         * <p>
1177         * The hook can have the following parameters:
1178         * <ul>
1179         * <li>
1180         * {@link CdsServiceRequestJson} the CdsServiceRequestJson from the hook request
1181         * </li>
1182         * <li>
1183         * {@link PriorAuthCrdContextJson} the PriorAuthCrdContextJson to return result i.e. patientId
1184         * </li>
1185         * </ul>
1186         * </p>
1187         * Hook methods must return <code>void</code>.
1188         */
1189        PRIOR_AUTH_CRD_GATHER_CONTEXT(void.class, CdsServiceRequestJson.class, PriorAuthCrdContextJson.class),
1190
1191        /**
1192         * <b>Audit Event Pre Persist Hook:</b>
1193         * The pointcut is invoked right before an audit event is handed off to the persistence layer.
1194         * <p>
1195         * This hook is used to select key/value pairs that should be marshalled into a JSON string and saved as
1196         * additional user information with the audit event.
1197         * </p>
1198         *
1199         * <p>
1200         * The hook will have the following parameters:
1201         * <ul>
1202         * <li>
1203         * {@link AuditEventJson} the audit event that will be persisted. It is provided for reference only as any modification
1204         * to the object will be ignored.
1205         * </li>
1206         * <li>
1207         * {@link UserSessionDetailsJson} if present, the object capturing the details pertaining to the user whose actions lead
1208         * to the audit event which is about to be persisted.
1209         * </li>
1210         * <li>
1211         * {@link OAuth2ClientDetailsJson} if present, the object capturing the details pertaining to the Oauth2 client whose actions lead
1212         * to the audit event which is about to be persisted.
1213         * </li>
1214         * <li>
1215         * {@link AuditEventPrePersistJson} the parameter object accumulating key/value pairs the client wishes to see
1216         * added as additional information persisted with the audit event.
1217         * </li>
1218         * </ul>
1219         * </p>
1220         */
1221        AUDIT_EVENT_PRE_PERSIST(
1222                        void.class,
1223                        "ca.cdr.api.model.json.AuditEventJson",
1224                        "ca.cdr.api.model.json.UserSessionDetailsJson",
1225                        "ca.cdr.api.model.json.OAuth2ClientDetailsJson",
1226                        "ca.cdr.api.model.json.AuditEventPrePersistJson"),
1227
1228        /**
1229         * <b>Client Auth Pre Token Hook:</b>
1230         * The pointcut is invoked right before making the auth token call before member-match and batch-export call. If the
1231         * token needs to be different than the default client-secret, an OpenIdTokenResponse needs to be returned. The
1232         * token returned must not be null if the the execution is to continue.
1233         *
1234         * <p>
1235         * The hook will have the following parameters:
1236         * <ul>
1237         * <li>
1238         * {@link HttpRequestBase} the oauth token request to be executed.
1239         * </li>
1240         * </ul>
1241         * </p>
1242         */
1243        CLIENT_AUTH_PRE_TOKEN_REQUEST(OpenIdTokenResponse.class, HttpRequestBase.class),
1244
1245        /**
1246         * <b>Pulsar Hook:</b>
1247         * This hook is called just before the ConsumerBuilder.subscribe() method is called to create a new Pulsar Consumer.
1248         * It allows customers to modify the ConsumerBuilder configuration before the Consumer is created.
1249         * <p>
1250         * Hooks may accept the following parameters:
1251         * <ul>
1252         * <li>
1253         * ConsumerBuilder - The ConsumerBuilder that is about to be used to create a Consumer.
1254         * Hook methods can modify this builder to customize the Consumer configuration.
1255         * </li>
1256         * </ul>
1257         * </p>
1258         * Hook methods must return <code>void</code>.
1259         */
1260        PULSAR_CONSUMER_BUILDER(void.class, "org.apache.pulsar.client.api.ConsumerBuilder"),
1261
1262        /**
1263         * <b>Pulsar Hook:</b>
1264         * This hook is called just before the ProducerBuilder.create() method is called to create a new Pulsar Producer.
1265         * It allows customers to modify the ProducerBuilder configuration before the Producer is created.
1266         * <p>
1267         * Hooks may accept the following parameters:
1268         * <ul>
1269         * <li>
1270         * ProducerBuilder - The ProducerBuilder that is about to be used to create a Producer.
1271         * Hook methods can modify this builder to customize the Producer configuration.
1272         * </li>
1273         * </ul>
1274         * </p>
1275         * Hook methods must return <code>void</code>.
1276         */
1277        PULSAR_PRODUCER_BUILDER(void.class, "org.apache.pulsar.client.api.ProducerBuilder"),
1278
1279        /**
1280         * <b>Camel Hook:</b>
1281         * This hook is called just before the SpringCamelContext.start() method is called.
1282         * It allows customers to add additional beans to the SpringCamelContext registry
1283         * and make other desired customizations.
1284         * <p>
1285         * Hooks may accept the following parameters:
1286         * <ul>
1287         * <li>
1288         * SpringCamelContext - The SpringCamelContext that is about to be started.
1289         * </li>
1290         * </ul>
1291         * </p>
1292         * Hook methods must return <code>void</code>.
1293         */
1294        CAMEL_SPRING_CAMEL_CONTEXT_PRE_START(void.class, "org.apache.camel.spring.SpringCamelContext");
1295
1296        private final List<String> myParameterTypes;
1297        private final Class<?> myReturnType;
1298        private final ExceptionHandlingSpec myExceptionHandlingSpec;
1299
1300        CdrPointcut(
1301                        @Nonnull Class<?> theReturnType,
1302                        @Nonnull ExceptionHandlingSpec theExceptionHandlingSpec,
1303                        String... theParameterTypes) {
1304
1305                // This class uses capital-B Boolean for the boolean return type
1306                assert !theReturnType.equals(boolean.class);
1307
1308                myReturnType = theReturnType;
1309                myExceptionHandlingSpec = theExceptionHandlingSpec;
1310                myParameterTypes = Collections.unmodifiableList(Arrays.asList(theParameterTypes));
1311        }
1312
1313        CdrPointcut(@Nonnull Class<?> theReturnType, String... theParameterTypes) {
1314                this(theReturnType, new ExceptionHandlingSpec(), theParameterTypes);
1315        }
1316
1317        CdrPointcut(@Nonnull Class<?> theReturnType, Class<?>... theParameterTypes) {
1318                this(theReturnType, new ExceptionHandlingSpec(), toNames(theParameterTypes));
1319        }
1320
1321        CdrPointcut(@Nonnull Class<?> theReturnType) {
1322                this(theReturnType, new ExceptionHandlingSpec(), ArrayUtils.EMPTY_STRING_ARRAY);
1323        }
1324
1325        CdrPointcut(@Nonnull Class<?> theReturnType, Class<?> theParameterTypes) {
1326                this(theReturnType, new ExceptionHandlingSpec(), theParameterTypes.getName());
1327        }
1328
1329        private static String[] toNames(Class<?>[] theParameterTypes) {
1330                return Arrays.stream(theParameterTypes)
1331                                .map(Class::getName)
1332                                .collect(Collectors.toList())
1333                                .toArray(new String[0]);
1334        }
1335
1336        @Override
1337        public boolean isShouldLogAndSwallowException(@Nonnull Throwable theException) {
1338                for (Class<? extends Throwable> next : myExceptionHandlingSpec.myTypesToLogAndSwallow) {
1339                        if (next.isAssignableFrom(theException.getClass())) {
1340                                return true;
1341                        }
1342                }
1343                return false;
1344        }
1345
1346        @Override
1347        @Nonnull
1348        public Class<?> getReturnType() {
1349                return myReturnType;
1350        }
1351
1352        @Override
1353        public Class<?> getBooleanReturnTypeForEnum() {
1354                return Boolean.class;
1355        }
1356
1357        @Override
1358        @Nonnull
1359        public List<String> getParameterTypes() {
1360                return myParameterTypes;
1361        }
1362
1363        private static class ExceptionHandlingSpec {
1364
1365                private final Set<Class<? extends Throwable>> myTypesToLogAndSwallow = new HashSet<>();
1366
1367                ExceptionHandlingSpec addLogAndSwallow(@Nonnull Class<? extends Throwable> theType) {
1368                        myTypesToLogAndSwallow.add(theType);
1369                        return this;
1370                }
1371        }
1372}