Skip to content

Instantly share code, notes, and snippets.

@nvg
Created May 20, 2021 02:21
Show Gist options
  • Save nvg/17c9446d5ece900f827c995cc60681eb to your computer and use it in GitHub Desktop.
Save nvg/17c9446d5ece900f827c995cc60681eb to your computer and use it in GitHub Desktop.
Interceptor for ImagingStudy FHIR resource
package ca.onfhir.interceptor;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.fhirpath.IFhirPath;
import ca.uhn.fhir.interceptor.api.Hook;
import ca.uhn.fhir.interceptor.api.Interceptor;
import ca.uhn.fhir.interceptor.api.Pointcut;
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.r4.model.Endpoint;
import org.hl7.fhir.r4.model.ImagingStudy;
import org.hl7.fhir.r4.model.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.kafka.core.KafkaTemplate;
import org.thymeleaf.util.StringUtils;
import java.util.List;
@Interceptor
public class ImagingStudyInterceptor {
private static final String IMAGING_STUDY = "ImagingStudy";
private static final String URL_TEMPLATE = "%s/studies/%s/series/%s/instances/%s";
private static Logger log = LoggerFactory.getLogger(ImagingStudyInterceptor.class);
private FhirContext fhirContext;
private KafkaTemplate<String, Image> kafkaTemplate;
private DaoRegistry daoRegistry;
@Hook(Pointcut.STORAGE_PRECOMMIT_RESOURCE_CREATED)
public void sendImagingStudyForProcessing(IBaseResource resource, RequestDetails request, ServletRequestDetails servletRequest, TransactionDetails txDetails) {
if (!IMAGING_STUDY.equals(fhirContext.getResourceType(resource))) {
return;
}
ImagingStudy imagingStudy = (ImagingStudy) resource;
if (!imagingStudy.getEndpointFirstRep().hasReference()) {
log.warn("Imaging study {} has no endpoint", imagingStudy);
return;
}
IFhirPath fhirPath = fhirContext.newFhirPath();
List<ImagingStudy.ImagingStudySeriesComponent> series = fhirPath.evaluate(imagingStudy, "ImagingStudy.series" +
".where(modality.code='DX' and modality.system='http://dicom.nema.org/resources/ontology/DCM')",
ImagingStudy.ImagingStudySeriesComponent.class);
if (series.isEmpty()) {
log.info("No image series to process for resource {}", resource);
return;
}
series.forEach(i -> publish(imagingStudy, i));
}
private void publish(ImagingStudy study, ImagingStudy.ImagingStudySeriesComponent series) {
if (!study.getEndpointFirstRep().hasReference()) {
log.warn("Study has no endpoint, unable to build URL for {}", study);
return;
}
String studyUid = getStudyUid(study);
if (StringUtils.isEmpty(studyUid)) {
log.warn("Study has no UID, unable to build URL for {}", study);
return;
}
Endpoint endpoint;
Reference studyEndpointRef = study.getEndpointFirstRep();
if (studyEndpointRef.getResource() != null) {
endpoint = (Endpoint) studyEndpointRef.getResource();
} else {
IFhirResourceDao<Endpoint> resourceDao = getDaoRegistry().getResourceDao(Endpoint.class);
endpoint = resourceDao.read(studyEndpointRef.getReferenceElement());
}
for (ImagingStudy.ImagingStudySeriesInstanceComponent instance : series.getInstance()) {
Image image = new Image();
image.setImagingStudyId(study.getId());
image.setSeriesUid(series.getUid());
image.setImageUid(instance.getUid());
image.setImageUrl(String
.format(URL_TEMPLATE, endpoint.getAddress(), studyUid, series.getUid(), image.getImageUid()));
log.info("Sending {} to images topic", image);
kafkaTemplate.send("images", image);
}
}
private String getStudyUid(ImagingStudy study) {
return study.getIdentifier()
.stream()
.filter(i -> "urn:dicom:uid".equals(i.getSystem()))
.map(i -> i.getValue())
.map(s -> s.replace("urn:oid:", ""))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("Unable to find imaging study identifier"));
}
public FhirContext getFhirContext() {
return fhirContext;
}
public void setFhirContext(FhirContext fhirContext) {
this.fhirContext = fhirContext;
}
public KafkaTemplate<String, Image> getKafkaTemplate() {
return kafkaTemplate;
}
public void setKafkaTemplate(KafkaTemplate<String, Image> kafkaTemplate) {
this.kafkaTemplate = kafkaTemplate;
}
public DaoRegistry getDaoRegistry() {
return daoRegistry;
}
public void setDaoRegistry(DaoRegistry daoRegistry) {
this.daoRegistry = daoRegistry;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment