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