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&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&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<List<String>></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}