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