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