简体   繁体   中英

Implement mediator design pattern in Spring REST app?

I am working in FHIR APIs. I have a PatientService interface and 2 implementation classes such as DSTU2PatientService, STU3PatientService.

Our client has an implemented FHIR DSTU2 API for demographics, whereas Procedure is in STU3.

My use case is, how to distinguish which service( DSTU2/STU3 ) should be called when request comes from the patient to get their health data from EHR system.

How to include mediator pattern to achieve the call dynamically? I don't want to use if condition.

application.properties

fhir.demogrphics=DSTU2
fhir.procedure=STU3

FHIRPatientService.java

public interface FHIRPatientService {

    Object getDemographics(PatientDTO patient);

    Object getProcedures(PatientDTO patient);
}

I have integrated the FHIR DSTU2 API DSTU2PatientService .

DSTU2PatientService.java

@Service(value = "dstu2PatientService")
public class DSTU2PatientService implements PatientService {

    private static final Logger LOG = LoggerFactory.getLogger(DSTU2PatientService.class);

    private FhirContext fhirContextDstu2;

    @Autowired
    private FHIRConfig fhirConfig;  
    @Autowired
    private BasicAuthInterceptor authInterceptor;

    public DSTU2PatientService(@Qualifier("fhirContextDstu2") FhirContext fhirContextDstu2) {
        this.fhirContextDstu2 = fhirContextDstu2;
    }

    @Override
    public Object getDemographics(PatientDTO patient) {
        Bundle bundle = null;
        try {
            IGenericClient clientDstu2 = fhirContextDstu2.newRestfulGenericClient(fhirConfig.getFhirServerPathDstu2());
            clientDstu2.registerInterceptor(authInterceptor);

            bundle = clientDstu2.search()
                .forResource(Patient.class)
                .where(Patient.GIVEN.matches().value(patient.getGiven()))
                .and(Patient.FAMILY.matches().value(patient.getFamily()))
                .and(Patient.BIRTHDATE.exactly().day(patient.getBirthdate()))
                .and(Patient.ADDRESS.contains().value(patient.getAddress()))
                .and(Patient.GENDER.exactly().codes(patient.getGender()))
                .returnBundle(Bundle.class)
                .execute();
        }catch(Exception e){
            LOG.error("Demographics: {}", e.getMessage());
            bundle = new Bundle();
        }
        return bundle;
    }

    @Override
    public Object getProcedures(PatientDTO patient) {
        Bundle bundle = null;
        try {
            IGenericClient clientDstu2 = fhirContextDstu2.newRestfulGenericClient(fhirConfig.getFhirServerPathDstu2());
            clientDstu2.registerInterceptor(authInterceptor);
            clientDstu2.registerInterceptor(CommonUtil.headersInterceptor(patient.getMychartId()));
            bundle = clientDstu2.search()
                    .forResource(Procedure.class)
                    .where(new ReferenceClientParam("patient").hasId(patient.getSubject()))
                    .and(Procedure.DATE.afterOrEquals().day(patient.getStartDate()))
                    .and(Procedure.DATE.beforeOrEquals().day(patient.getEndDate()))
                    .returnBundle(Bundle.class)
                    .execute();
        }catch(Exception e){
            LOG.error("Procedures: {}", e.getMessage());
            bundle = new Bundle();
        }
        return bundle;
    }
}

I have integrated the FHIR STU3 API STU3PatientService .

STU3PatientService.java

@Service(value = "stu3PatientService")
public class STU3PatientService implements PatientService {

    private static final Logger LOG = LoggerFactory.getLogger(STU3PatientService.class);

    private FhirContext fhirContextStu3;

    @Autowired
    private FHIRConfig fhirConfig;

    @Autowired
    private BasicAuthInterceptor authInterceptor;

    public STU3PatientService(@Qualifier("fhirContextStu3") FhirContext fhirContextStu3) {
        this.fhirContextStu3 = fhirContextStu3;
    }

    @Override
    public Object getDemographics(PatientDTO patient) {
        Bundle bundle = null;
        try {
            IGenericClient clientStu3 = fhirContextStu3.newRestfulGenericClient(fhirConfig.getFhirServerPathStu3());
            clientStu3.registerInterceptor(authInterceptor);

            bundle = clientStu3.search()
                    .forResource(Patient.class)
                    .where(Patient.GIVEN.matches().value(patient.getGiven()))
                    .and(Patient.FAMILY.matches().value(patient.getFamily()))
                    .and(Patient.BIRTHDATE.exactly().day(patient.getBirthdate()))
                    .and(Patient.ADDRESS.contains().value(patient.getAddress()))
                    .and(Patient.GENDER.exactly().codes(patient.getGender()))
                    .returnBundle(Bundle.class)
                    .execute();
        }catch(Exception e){
            LOG.error("Demographics: {}", e.getMessage());
            bundle = new Bundle();
        }
        return bundle;
    }

    @Override
    public bundle getProcedures(PatientDTO patient) {
        Bundle bundle = null;
        try {
            IGenericClient clientStu3 = fhirContextStu3.newRestfulGenericClient(fhirConfig.getFhirServerPathStu3());
            clientStu3.registerInterceptor(authInterceptor);
            clientStu3.registerInterceptor(CommonUtil.headersInterceptor(patient.getMychartId()));

            bundle = clientStu3.search()
                    .forResource(Procedure.class)
                    .where(new ReferenceClientParam("patient").hasId(patient.getSubject()))
                    .and(Procedure.DATE.afterOrEquals().day(patient.getStartDate()))
                    .and(Procedure.DATE.beforeOrEquals().day(patient.getEndDate()))
                    .returnBundle(Bundle.class)
                    .execute();
        }catch(Exception e){
            LOG.error("Procedures: {}", e.getMessage());
            bundle = new Bundle();
        }
        return bundle;
    }

}

FHIRComponent.java

@Component(value = "fhirService")
public class FHIRComponent {

    private static final Logger LOG = LoggerFactory.getLogger(FHIRComponent.class);

    private FHIRResourceVersionConfig fhirResourceVersionConfig;
    private PatientService dstu2PatientService;
    private PatientService stu3PatientService;

    public FHIRComponent(
            @Qualifier("dstu2PatientService") FHIRPatientService dstu2PatientService,
            @Qualifier("stu3PatientService") FHIRPatientService stu3PatientService,
            FHIRResourceVersionConfig fhirResourceVersionConfig) {
        this.dstu2PatientService = dstu2PatientService;
        this.stu3PatientService = stu3PatientService;
        this.fhirResourceVersionConfig = fhirResourceVersionConfig;
    }

    public Object getDemographics(PatientDTO patient, String resourceType) {
        Object result = null;

        if("DSTU2".equalsIgnoreCase(fhirResourceVersionConfig.findResource(resourceName)))
            result = patientServiceDstu2.getDemographics(patient);
        else
            result = patientServiceStu3.getDemographics(patient);
        return result;
    }

    public Object getConditions(PatientDTO patient) {
        Object result = null;

        if("DSTU2".equalsIgnoreCase(fhirResourceVersionConfig.findResource(resourceName)))
            result = patientServiceDstu2.getConditions(patient);
        else
            result = patientServiceStu3.getConditions(patient);
        return result;
    }
}

You need to make the FHIRPatientService aware for which code it is responsible:

public interface FHIRPatientService {

   String getCode();

   Object getDemographics(PatientDTO patient);

   Object getProcedures(PatientDTO patient);
}

Then you can refactor your component

@Component(value = "fhirService")
public class FHIRComponent {

    private static final Logger LOG = LoggerFactory.getLogger(FHIRComponent.class);

    private FHIRResourceVersionConfig fhirResourceVersionConfig;
    private List<PatientService> patientServices;//spring will inject all services

    public FHIRComponent(
        List<PatientService> patientServices,
        FHIRResourceVersionConfig fhirResourceVersionConfig) {
        this.patientServices= patientServices;
        this.fhirResourceVersionConfig = fhirResourceVersionConfig;
    }

    private Optional<PatientService> getService(String resourceType){
        return patientServices.stream()
            .filter(service => service.getCode().equalsIgnoreCase(fhirResourceVersionConfig.findResource(resourceName)))
            .findAny() 
    }

    public Object getDemographics(PatientDTO patient, String resourceType) {
        return getService(resourceType)
            .map(service => service.getDemographics(patient))
            .orElse(null);
   }
  ...

I hope my explenation is a bit clear...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM