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