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