Add Registries for CDS CR Services (#5342)

* Add registries for CdsCrServices and CrDiscoveryServices to allow registration of custom services

* Add changelog

* Fix broken find method

* Fix crDiscoveryServiceFactory
This commit is contained in:
Brenin Rhodes 2023-10-03 05:15:32 -06:00 committed by GitHub
parent 4e9bd153cf
commit 743e2c178b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 236 additions and 26 deletions

View File

@ -0,0 +1,4 @@
---
type: add
issue: 5341
title: "Added registries for CdsCrServices and CrDiscoveryServices in CDS Hooks to allow registration of custom services."

View File

@ -34,28 +34,36 @@ import ca.uhn.hapi.fhir.cdshooks.module.CdsHooksObjectMapperFactory;
import ca.uhn.hapi.fhir.cdshooks.svc.CdsConfigServiceImpl;
import ca.uhn.hapi.fhir.cdshooks.svc.CdsHooksContextBooter;
import ca.uhn.hapi.fhir.cdshooks.svc.CdsServiceRegistryImpl;
import ca.uhn.hapi.fhir.cdshooks.svc.cr.CdsCrServiceDstu3;
import ca.uhn.hapi.fhir.cdshooks.svc.cr.CdsCrServiceR4;
import ca.uhn.hapi.fhir.cdshooks.svc.cr.CdsCrServiceR5;
import ca.uhn.hapi.fhir.cdshooks.svc.cr.CdsCrServiceRegistry;
import ca.uhn.hapi.fhir.cdshooks.svc.cr.CdsServiceInterceptor;
import ca.uhn.hapi.fhir.cdshooks.svc.cr.ICdsCrService;
import ca.uhn.hapi.fhir.cdshooks.svc.cr.ICdsCrServiceFactory;
import ca.uhn.hapi.fhir.cdshooks.svc.cr.discovery.CrDiscoveryServiceDstu3;
import ca.uhn.hapi.fhir.cdshooks.svc.cr.discovery.CrDiscoveryServiceR4;
import ca.uhn.hapi.fhir.cdshooks.svc.cr.discovery.CrDiscoveryServiceR5;
import ca.uhn.hapi.fhir.cdshooks.svc.cr.ICdsCrServiceRegistry;
import ca.uhn.hapi.fhir.cdshooks.svc.cr.discovery.CdsCrDiscoveryServiceRegistry;
import ca.uhn.hapi.fhir.cdshooks.svc.cr.discovery.ICdsCrDiscoveryServiceRegistry;
import ca.uhn.hapi.fhir.cdshooks.svc.cr.discovery.ICrDiscoveryService;
import ca.uhn.hapi.fhir.cdshooks.svc.cr.discovery.ICrDiscoveryServiceFactory;
import ca.uhn.hapi.fhir.cdshooks.svc.prefetch.CdsPrefetchDaoSvc;
import ca.uhn.hapi.fhir.cdshooks.svc.prefetch.CdsPrefetchFhirClientSvc;
import ca.uhn.hapi.fhir.cdshooks.svc.prefetch.CdsPrefetchSvc;
import ca.uhn.hapi.fhir.cdshooks.svc.prefetch.CdsResolutionStrategySvc;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.hl7.fhir.instance.model.api.IIdType;
import org.opencds.cqf.fhir.api.Repository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Optional;
@Configuration
public class CdsHooksConfig {
private static final Logger ourLog = LoggerFactory.getLogger(CdsHooksConfig.class);
public static final String CDS_HOOKS_OBJECT_MAPPER_FACTORY = "cdsHooksObjectMapperFactory";
@ -97,7 +105,15 @@ public class CdsHooksConfig {
}
@Bean
public ICdsCrServiceFactory cdsCrServiceFactory(FhirContext theFhirContext, ICdsConfigService theCdsConfigService) {
public ICdsCrServiceRegistry cdsCrServiceRegistry() {
return new CdsCrServiceRegistry();
}
@Bean
public ICdsCrServiceFactory cdsCrServiceFactory(
FhirContext theFhirContext,
ICdsConfigService theCdsConfigService,
ICdsCrServiceRegistry theCdsCrServiceRegistry) {
return id -> {
if (myRepositoryFactory == null) {
return null;
@ -105,22 +121,35 @@ public class CdsHooksConfig {
RequestDetails rd =
theCdsConfigService.createRequestDetails(theFhirContext, id, PLAN_DEFINITION_RESOURCE_NAME);
Repository repository = myRepositoryFactory.create(rd);
switch (theFhirContext.getVersion().getVersion()) {
case DSTU3:
return new CdsCrServiceDstu3(rd, repository);
case R4:
return new CdsCrServiceR4(rd, repository);
case R5:
return new CdsCrServiceR5(rd, repository);
default:
return null;
Optional<Class<? extends ICdsCrService>> clazz =
theCdsCrServiceRegistry.find(theFhirContext.getVersion().getVersion());
if (clazz.isEmpty()) {
return null;
}
try {
Constructor<? extends ICdsCrService> constructor =
clazz.get().getConstructor(RequestDetails.class, Repository.class);
return constructor.newInstance(rd, repository);
} catch (NoSuchMethodException
| InvocationTargetException
| InstantiationException
| IllegalAccessException e) {
ourLog.error("Error encountered attempting to construct the CdsCrService: " + e.getMessage());
return null;
}
};
}
@Bean
public ICdsCrDiscoveryServiceRegistry cdsCrDiscoveryServiceRegistry() {
return new CdsCrDiscoveryServiceRegistry();
}
@Bean
public ICrDiscoveryServiceFactory crDiscoveryServiceFactory(
FhirContext theFhirContext, ICdsConfigService theCdsConfigService) {
FhirContext theFhirContext,
ICdsConfigService theCdsConfigService,
ICdsCrDiscoveryServiceRegistry theCdsCrDiscoveryServiceRegistry) {
return id -> {
if (myRepositoryFactory == null) {
return null;
@ -128,15 +157,21 @@ public class CdsHooksConfig {
RequestDetails rd =
theCdsConfigService.createRequestDetails(theFhirContext, id, PLAN_DEFINITION_RESOURCE_NAME);
Repository repository = myRepositoryFactory.create(rd);
switch (theFhirContext.getVersion().getVersion()) {
case DSTU3:
return new CrDiscoveryServiceDstu3(rd.getId(), repository);
case R4:
return new CrDiscoveryServiceR4(rd.getId(), repository);
case R5:
return new CrDiscoveryServiceR5(rd.getId(), repository);
default:
return null;
Optional<Class<? extends ICrDiscoveryService>> clazz = theCdsCrDiscoveryServiceRegistry.find(
theFhirContext.getVersion().getVersion());
if (clazz.isEmpty()) {
return null;
}
try {
Constructor<? extends ICrDiscoveryService> constructor =
clazz.get().getConstructor(IIdType.class, Repository.class);
return constructor.newInstance(rd.getId(), repository);
} catch (NoSuchMethodException
| InvocationTargetException
| InstantiationException
| IllegalAccessException e) {
ourLog.error("Error encountered attempting to construct the CrDiscoveryService: " + e.getMessage());
return null;
}
};
}

View File

@ -0,0 +1,51 @@
/*-
* #%L
* HAPI FHIR - CDS Hooks
* %%
* Copyright (C) 2014 - 2023 Smile CDR, Inc.
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
package ca.uhn.hapi.fhir.cdshooks.svc.cr;
import ca.uhn.fhir.context.FhirVersionEnum;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import javax.annotation.Nonnull;
public class CdsCrServiceRegistry implements ICdsCrServiceRegistry {
private final Map<FhirVersionEnum, Class<? extends ICdsCrService>> myCdsCrServices;
public CdsCrServiceRegistry() {
myCdsCrServices = new HashMap<>();
myCdsCrServices.put(FhirVersionEnum.DSTU3, CdsCrServiceDstu3.class);
myCdsCrServices.put(FhirVersionEnum.R4, CdsCrServiceR4.class);
myCdsCrServices.put(FhirVersionEnum.R5, CdsCrServiceR5.class);
}
public void register(
@Nonnull FhirVersionEnum theFhirVersion, @Nonnull Class<? extends ICdsCrService> theCdsCrService) {
myCdsCrServices.put(theFhirVersion, theCdsCrService);
}
public void unregister(@Nonnull FhirVersionEnum theFhirVersion) {
myCdsCrServices.remove(theFhirVersion);
}
public Optional<Class<? extends ICdsCrService>> find(@Nonnull FhirVersionEnum theFhirVersion) {
return Optional.ofNullable(myCdsCrServices.get(theFhirVersion));
}
}

View File

@ -0,0 +1,33 @@
/*-
* #%L
* HAPI FHIR - CDS Hooks
* %%
* Copyright (C) 2014 - 2023 Smile CDR, Inc.
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
package ca.uhn.hapi.fhir.cdshooks.svc.cr;
import ca.uhn.fhir.context.FhirVersionEnum;
import java.util.Optional;
import javax.annotation.Nonnull;
public interface ICdsCrServiceRegistry {
void register(@Nonnull FhirVersionEnum theFhirVersion, @Nonnull Class<? extends ICdsCrService> theCdsCrService);
void unregister(@Nonnull FhirVersionEnum theFhirVersion);
Optional<Class<? extends ICdsCrService>> find(@Nonnull FhirVersionEnum theFhirVersion);
}

View File

@ -0,0 +1,53 @@
/*-
* #%L
* HAPI FHIR - CDS Hooks
* %%
* Copyright (C) 2014 - 2023 Smile CDR, Inc.
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
package ca.uhn.hapi.fhir.cdshooks.svc.cr.discovery;
import ca.uhn.fhir.context.FhirVersionEnum;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import javax.annotation.Nonnull;
public class CdsCrDiscoveryServiceRegistry implements ICdsCrDiscoveryServiceRegistry {
private final Map<FhirVersionEnum, Class<? extends ICrDiscoveryService>> myCrDiscoveryServices;
public CdsCrDiscoveryServiceRegistry() {
myCrDiscoveryServices = new HashMap<>();
myCrDiscoveryServices.put(FhirVersionEnum.DSTU3, CrDiscoveryServiceDstu3.class);
myCrDiscoveryServices.put(FhirVersionEnum.R4, CrDiscoveryServiceR4.class);
myCrDiscoveryServices.put(FhirVersionEnum.R5, CrDiscoveryServiceR5.class);
}
public void register(
@Nonnull FhirVersionEnum theFhirVersion,
@Nonnull Class<? extends ICrDiscoveryService> theCrDiscoveryService) {
myCrDiscoveryServices.put(theFhirVersion, theCrDiscoveryService);
}
public void unregister(@Nonnull FhirVersionEnum theFhirVersion) {
myCrDiscoveryServices.remove(theFhirVersion);
}
@Override
public Optional<Class<? extends ICrDiscoveryService>> find(@Nonnull FhirVersionEnum theFhirVersion) {
return Optional.ofNullable(myCrDiscoveryServices.get(theFhirVersion));
}
}

View File

@ -0,0 +1,34 @@
/*-
* #%L
* HAPI FHIR - CDS Hooks
* %%
* Copyright (C) 2014 - 2023 Smile CDR, Inc.
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
package ca.uhn.hapi.fhir.cdshooks.svc.cr.discovery;
import ca.uhn.fhir.context.FhirVersionEnum;
import java.util.Optional;
import javax.annotation.Nonnull;
public interface ICdsCrDiscoveryServiceRegistry {
void register(
@Nonnull FhirVersionEnum theFhirVersion, @Nonnull Class<? extends ICrDiscoveryService> ICrDiscoveryService);
void unregister(@Nonnull FhirVersionEnum theFhirVersion);
Optional<Class<? extends ICrDiscoveryService>> find(@Nonnull FhirVersionEnum theFhirVersion);
}