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