adding pre-member-match hook
This commit is contained in:
parent
41d9abf6ac
commit
d36be49ad4
|
@ -46,6 +46,7 @@ import javax.annotation.Nonnull;
|
|||
* <li>SUBSCRIPTION_xxx: Hooks on the HAPI FHIR Subscription framework</li>
|
||||
* <li>STORAGE_xxx: Hooks on the storage engine</li>
|
||||
* <li>VALIDATION_xxx: Hooks on the HAPI FHIR Validation framework</li>
|
||||
* <li>MDM_XXX: Hooks on Master Data Management framework</li>
|
||||
* <li>JPA_PERFTRACE_xxx: Performance tracing hooks on the JPA server</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
|
@ -2461,6 +2462,28 @@ public enum Pointcut implements IPointcut {
|
|||
MDM_SUBMIT(
|
||||
void.class, "ca.uhn.fhir.rest.api.server.RequestDetails", "ca.uhn.fhir.mdm.model.mdmevents.MdmSubmitEvent"),
|
||||
|
||||
/**
|
||||
* <b>P2P MemberMatch Pre Hook:</b>
|
||||
* This hook is invoked whenever a $member-match call is made.
|
||||
* It is invoked after basic parameter validation, but before the
|
||||
* database operations of MemberMatch are performed and results returned.
|
||||
* </p>
|
||||
* <p>
|
||||
* This hook will take the following parameters:
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li>
|
||||
* ca.uhn.fhir.rest.api.server.RequestDetails - An object containing details about the request that is about to be processed.
|
||||
* </li>
|
||||
* <li>
|
||||
* ca.uhn.fhir.jpa.model.MemberMatchPreHookEvent - An event with the member-match
|
||||
* parameters, including the Patient, CoverageToMatch, CoverateToLink, and Consent objects.
|
||||
* </li>
|
||||
* </ul>
|
||||
*/
|
||||
P2P_MEMBER_MATCH_PRE_HOOK(
|
||||
void.class, "ca.uhn.fhir.rest.api.server.RequestDetails", "ca.uhn.fhir.jpa.model.MemberMatchPreHookEvent"),
|
||||
|
||||
/**
|
||||
* <b>JPA Hook:</b>
|
||||
* This hook is invoked when a cross-partition reference is about to be
|
||||
|
|
|
@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.config.r4;
|
|||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
|
||||
import ca.uhn.fhir.jpa.api.IDaoRegistry;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirSystemDao;
|
||||
|
@ -118,7 +119,9 @@ public class JpaR4Config {
|
|||
|
||||
@Bean
|
||||
public MemberMatchR4ResourceProvider memberMatchR4ResourceProvider(
|
||||
FhirContext theFhirContext, MemberMatcherR4Helper theMemberMatchR4Helper) {
|
||||
return new MemberMatchR4ResourceProvider(theFhirContext, theMemberMatchR4Helper);
|
||||
FhirContext theFhirContext, IInterceptorBroadcaster theIInterceptorBroadcaster, MemberMatcherR4Helper theMemberMatchR4Helper) {
|
||||
return new MemberMatchR4ResourceProvider(theFhirContext,
|
||||
theMemberMatchR4Helper,
|
||||
theIInterceptorBroadcaster);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
package ca.uhn.fhir.jpa.model;
|
||||
|
||||
import org.hl7.fhir.r4.model.Consent;
|
||||
import org.hl7.fhir.r4.model.Coverage;
|
||||
import org.hl7.fhir.r4.model.Patient;
|
||||
|
||||
public class MemberMatchPreHookEvent {
|
||||
private Patient myPatient;
|
||||
|
||||
private Coverage myCoverageToMatch;
|
||||
|
||||
private Coverage myCoverageToLink;
|
||||
|
||||
private Consent myConsent;
|
||||
|
||||
public Patient getPatient() {
|
||||
return myPatient;
|
||||
}
|
||||
|
||||
public void setPatient(Patient thePatient) {
|
||||
myPatient = thePatient;
|
||||
}
|
||||
|
||||
public Coverage getCoverageToMatch() {
|
||||
return myCoverageToMatch;
|
||||
}
|
||||
|
||||
public void setCoverageToMatch(Coverage theCoverageToMatch) {
|
||||
myCoverageToMatch = theCoverageToMatch;
|
||||
}
|
||||
|
||||
public Coverage getCoverageToLink() {
|
||||
return myCoverageToLink;
|
||||
}
|
||||
|
||||
public void setCoverageToLink(Coverage theCoverageToLink) {
|
||||
myCoverageToLink = theCoverageToLink;
|
||||
}
|
||||
|
||||
public Consent getConsent() {
|
||||
return myConsent;
|
||||
}
|
||||
|
||||
public void setConsent(Consent theConsent) {
|
||||
myConsent = theConsent;
|
||||
}
|
||||
}
|
|
@ -21,6 +21,10 @@ package ca.uhn.fhir.jpa.provider.r4;
|
|||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.interceptor.api.HookParams;
|
||||
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
|
||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||
import ca.uhn.fhir.jpa.model.MemberMatchPreHookEvent;
|
||||
import ca.uhn.fhir.model.api.annotation.Description;
|
||||
import ca.uhn.fhir.rest.annotation.Operation;
|
||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||
|
@ -28,22 +32,29 @@ import ca.uhn.fhir.rest.api.Constants;
|
|||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||
import ca.uhn.fhir.rest.server.provider.ProviderConstants;
|
||||
import ca.uhn.fhir.rest.server.util.CompositeInterceptorBroadcaster;
|
||||
import org.hl7.fhir.r4.model.Consent;
|
||||
import org.hl7.fhir.r4.model.Coverage;
|
||||
import org.hl7.fhir.r4.model.Parameters;
|
||||
import org.hl7.fhir.r4.model.Patient;
|
||||
|
||||
import java.util.Optional;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Optional;
|
||||
|
||||
public class MemberMatchR4ResourceProvider {
|
||||
|
||||
private final MemberMatcherR4Helper myMemberMatcherR4Helper;
|
||||
private final FhirContext myFhirContext;
|
||||
private final IInterceptorBroadcaster myInterceptorBroadcaster;
|
||||
|
||||
public MemberMatchR4ResourceProvider(FhirContext theFhirContext, MemberMatcherR4Helper theMemberMatcherR4Helper) {
|
||||
public MemberMatchR4ResourceProvider(
|
||||
FhirContext theFhirContext,
|
||||
MemberMatcherR4Helper theMemberMatcherR4Helper,
|
||||
IInterceptorBroadcaster theIInterceptorBroadcaster
|
||||
) {
|
||||
myFhirContext = theFhirContext;
|
||||
myMemberMatcherR4Helper = theMemberMatcherR4Helper;
|
||||
myInterceptorBroadcaster = theIInterceptorBroadcaster;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -127,6 +138,24 @@ public class MemberMatchR4ResourceProvider {
|
|||
throw new UnprocessableEntityException(Msg.code(2147) + i18nMessage);
|
||||
}
|
||||
|
||||
if (CompositeInterceptorBroadcaster.hasHooks(Pointcut.P2P_MEMBER_MATCH_PRE_HOOK, myInterceptorBroadcaster, theRequestDetails)) {
|
||||
MemberMatchPreHookEvent preHookParams = new MemberMatchPreHookEvent();
|
||||
preHookParams.setConsent(theConsent);
|
||||
preHookParams.setPatient(theMemberPatient);
|
||||
preHookParams.setCoverageToMatch(theCoverageToMatch);
|
||||
preHookParams.setCoverageToLink(theCoverageToLink);
|
||||
|
||||
HookParams params = new HookParams();
|
||||
params.add(MemberMatchPreHookEvent.class, preHookParams);
|
||||
params.add(RequestDetails.class, theRequestDetails);
|
||||
CompositeInterceptorBroadcaster.doCallHooks(
|
||||
myInterceptorBroadcaster,
|
||||
theRequestDetails,
|
||||
Pointcut.P2P_MEMBER_MATCH_PRE_HOOK,
|
||||
params
|
||||
);
|
||||
}
|
||||
|
||||
myMemberMatcherR4Helper.addMemberIdentifierToMemberPatient(theMemberPatient, patient.getIdentifierFirstRep());
|
||||
myMemberMatcherR4Helper.updateConsentForMemberMatch(theConsent, patient, theMemberPatient, theRequestDetails);
|
||||
return myMemberMatcherR4Helper.buildSuccessReturnParameters(theMemberPatient, theCoverageToLink, theConsent);
|
||||
|
@ -137,8 +166,8 @@ public class MemberMatchR4ResourceProvider {
|
|||
validateParam(theMemberPatient, Constants.PARAM_MEMBER_PATIENT);
|
||||
validateParam(theOldCoverage, Constants.PARAM_OLD_COVERAGE);
|
||||
validateParam(theNewCoverage, Constants.PARAM_NEW_COVERAGE);
|
||||
validateParam(theConsent, Constants.PARAM_CONSENT);
|
||||
validateMemberPatientParam(theMemberPatient);
|
||||
validateParam(theConsent, Constants.PARAM_CONSENT);
|
||||
validateConsentParam(theConsent);
|
||||
}
|
||||
|
||||
|
|
|
@ -46,10 +46,10 @@ import org.hl7.fhir.r4.model.Parameters;
|
|||
import org.hl7.fhir.r4.model.Patient;
|
||||
import org.hl7.fhir.r4.model.Reference;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static ca.uhn.fhir.rest.api.Constants.PARAM_CONSENT;
|
||||
import static ca.uhn.fhir.rest.api.Constants.PARAM_MEMBER_IDENTIFIER;
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
package ca.uhn.fhir.jpa.provider.r4;
|
||||
|
||||
import ca.uhn.fhir.interceptor.api.Hook;
|
||||
import ca.uhn.fhir.interceptor.api.IInterceptorService;
|
||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
|
||||
import ca.uhn.fhir.jpa.model.MemberMatchPreHookEvent;
|
||||
import ca.uhn.fhir.jpa.provider.BaseResourceProviderR4Test;
|
||||
import ca.uhn.fhir.parser.StrictErrorHandler;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.client.apache.ResourceEntity;
|
||||
import ca.uhn.fhir.util.ParametersUtil;
|
||||
import com.google.common.collect.Lists;
|
||||
|
@ -32,6 +37,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import static ca.uhn.fhir.rest.api.Constants.PARAM_CONSENT;
|
||||
import static ca.uhn.fhir.rest.api.Constants.PARAM_CONSENT_PATIENT_REFERENCE;
|
||||
|
@ -46,6 +52,7 @@ import static org.hamcrest.Matchers.containsString;
|
|||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@SuppressWarnings("Duplicates")
|
||||
public class PatientMemberMatchOperationR4Test extends BaseResourceProviderR4Test {
|
||||
|
@ -72,6 +79,9 @@ public class PatientMemberMatchOperationR4Test extends BaseResourceProviderR4Tes
|
|||
@Autowired
|
||||
MemberMatchR4ResourceProvider theMemberMatchR4ResourceProvider;
|
||||
|
||||
@Autowired
|
||||
IInterceptorService myInterceptorService;
|
||||
|
||||
@BeforeEach
|
||||
public void beforeDisableResultReuse() {
|
||||
myStorageSettings.setReuseCachedSearchResultsForMillis(null);
|
||||
|
@ -150,6 +160,48 @@ public class PatientMemberMatchOperationR4Test extends BaseResourceProviderR4Tes
|
|||
myClient.create().resource(ourExistingCoverage).execute().getId().toUnqualifiedVersionless().getValue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMemberMatch_invokesPreMemberMatchHook() throws Exception {
|
||||
// setup
|
||||
AtomicBoolean setter = new AtomicBoolean();
|
||||
createCoverageWithBeneficiary(true, true);
|
||||
Parameters inputParameters = buildInputParameters(myPatient, oldCoverage, newCoverage, myConsent);
|
||||
|
||||
Object interceptor = new Object() {
|
||||
@Hook(Pointcut.P2P_MEMBER_MATCH_PRE_HOOK)
|
||||
void validateConsent(RequestDetails theRequestDetails, MemberMatchPreHookEvent theEvent) {
|
||||
assertNotNull(theRequestDetails);
|
||||
assertNotNull(theEvent);
|
||||
assertNotNull(theEvent.getConsent());
|
||||
assertNotNull(theEvent.getCoverageToMatch());
|
||||
assertNotNull(theEvent.getCoverageToLink());
|
||||
assertNotNull(theEvent.getPatient());
|
||||
|
||||
assertEquals(myPatient.getId(), theEvent.getPatient().getId());
|
||||
assertEquals(oldCoverage.getId(), theEvent.getCoverageToMatch().getIdElement().getIdPart());
|
||||
assertEquals(newCoverage.getId(), theEvent.getCoverageToLink().getIdElement().getIdPart());
|
||||
assertEquals(myConsent.getId(), theEvent.getConsent().getId());
|
||||
|
||||
setter.getAndSet(true);
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
myInterceptorService.registerInterceptor(interceptor);
|
||||
|
||||
// test
|
||||
Parameters parametersResponse = performOperation(myServerBase + ourQuery,
|
||||
EncodingEnum.JSON, inputParameters);
|
||||
|
||||
validateMemberPatient(parametersResponse);
|
||||
validateNewCoverage(parametersResponse, newCoverage);
|
||||
} finally {
|
||||
myInterceptorService.unregisterInterceptor(interceptor);
|
||||
}
|
||||
|
||||
assertTrue(setter.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMemberMatchByCoverageId() throws Exception {
|
||||
createCoverageWithBeneficiary(true, true);
|
||||
|
@ -162,7 +214,6 @@ public class PatientMemberMatchOperationR4Test extends BaseResourceProviderR4Tes
|
|||
validateNewCoverage(parametersResponse, newCoverage);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCoverageNoBeneficiaryReturns422() throws Exception {
|
||||
createCoverageWithBeneficiary(false, false);
|
||||
|
|
Loading…
Reference in New Issue