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