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