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