Skip to content

Commit

Permalink
feat: add default implementation of reference validator
Browse files Browse the repository at this point in the history
This adds a generic interface for MII mappers containing a default
implementation of a reference validator.
  • Loading branch information
pcvolkmer committed Nov 25, 2024
1 parent 15525dc commit faa6052
Show file tree
Hide file tree
Showing 9 changed files with 296 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.util.List;
import java.util.regex.Pattern;
import org.hl7.fhir.r4.model.*;
import org.hl7.fhir.r4.model.Enumerations.ResourceType;
import org.miracum.streams.ume.obdstofhir.FhirProperties;
import org.miracum.streams.ume.obdstofhir.mapper.ObdsToFhirMapper;
import org.slf4j.Logger;
Expand All @@ -14,7 +15,8 @@
import org.springframework.util.StringUtils;

@Service
public class ConditionMapper extends ObdsToFhirMapper {
public class ConditionMapper extends ObdsToFhirMapper
implements Mapper<OBDS.MengePatient.Patient.MengeMeldung.Meldung, Condition> {

private static final Logger LOG = LoggerFactory.getLogger(ConditionMapper.class);
private static final Pattern icdVersionPattern =
Expand All @@ -28,6 +30,8 @@ public ConditionMapper(FhirProperties fhirProperties) {
public Condition map(OBDS.MengePatient.Patient.MengeMeldung.Meldung meldung, Reference patient) {
var condition = new Condition();

verifyReference(patient, ResourceType.PATIENT);

if (meldung.getDiagnose().getDiagnosesicherung() != null) {
Coding verStatus =
new Coding(fhirProperties.getSystems().getConditionVerStatus(), "confirmed", "");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.miracum.streams.ume.obdstofhir.mapper.mii;

import java.util.Objects;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.r4.model.Enumerations.ResourceType;
import org.hl7.fhir.r4.model.Reference;

public interface Mapper<S, D> {

/**
* Default implementation of reference validation. This does not check the existance of the
* referenced resource!
*
* @param reference The reference to be validated
* @param resourceType The required resource type of the reference
* @return Will return `true` if reference is usable
* @throws NullPointerException if reference is null
* @throws IllegalArgumentException if reference is not of required reesource type.
*/
default boolean verifyReference(Reference reference, ResourceType resourceType)
throws NullPointerException, IllegalArgumentException {
Objects.requireNonNull(
reference, String.format("Reference to %s must not be null", resourceType.toString()));
Validate.isTrue(
Objects.equals(reference.getReferenceElement().getResourceType(), resourceType.toCode()),
String.format("The reference should point to a %s resource", resourceType.toString()));

return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class StrahlentherapieMapper extends ObdsToFhirMapper {
public class StrahlentherapieMapper extends ObdsToFhirMapper implements Mapper<STTyp, Procedure> {
private static final Logger LOG = LoggerFactory.getLogger(StrahlentherapieMapper.class);

public StrahlentherapieMapper(FhirProperties fhirProperties) {
Expand All @@ -27,13 +27,9 @@ public StrahlentherapieMapper(FhirProperties fhirProperties) {

public Procedure map(STTyp st, Reference subject) {
Objects.requireNonNull(st);
Objects.requireNonNull(subject);

Validate.notBlank(st.getSTID(), "Required ST_ID is unset");
Validate.isTrue(
Objects.equals(
subject.getReferenceElement().getResourceType(), ResourceType.PATIENT.toCode()),
"The subject reference should point to a Patient resource");

verifyReference(subject, ResourceType.PATIENT);

var procedure = new Procedure();
procedure.getMeta().addProfile(fhirProperties.getProfiles().getMiiPrOnkoStrahlentherapie());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
import org.springframework.util.StringUtils;

@Service
public class SystemischeTherapieMedicationStatementMapper extends ObdsToFhirMapper {
public class SystemischeTherapieMedicationStatementMapper extends ObdsToFhirMapper
implements Mapper<SYSTTyp, Bundle> {

private static final Logger LOG =
LoggerFactory.getLogger(SystemischeTherapieProcedureMapper.class);
Expand All @@ -34,18 +35,10 @@ public SystemischeTherapieMedicationStatementMapper(FhirProperties fhirPropertie

public Bundle map(SYSTTyp syst, Reference patient, Reference procedure) {
Objects.requireNonNull(syst, "Systemtherapie must not be null");
Objects.requireNonNull(patient, "Reference to Patient must not be null");
Objects.requireNonNull(procedure, "Reference to Procedure must not be null");

Validate.notBlank(syst.getSYSTID(), "Required SYST_ID is unset");
Validate.isTrue(
Objects.equals(
patient.getReferenceElement().getResourceType(), ResourceType.PATIENT.toCode()),
"The subject reference should point to a Patient resource");
Validate.isTrue(
Objects.equals(
procedure.getReferenceElement().getResourceType(), ResourceType.PROCEDURE.toCode()),
"The subject reference should point to a Procedure resource");

verifyReference(patient, ResourceType.PATIENT);
verifyReference(procedure, ResourceType.PROCEDURE);

var bundle = new Bundle();
bundle.setType(Bundle.BundleType.TRANSACTION);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
import org.springframework.stereotype.Service;

@Service
public class SystemischeTherapieProcedureMapper extends ObdsToFhirMapper {
public class SystemischeTherapieProcedureMapper extends ObdsToFhirMapper
implements Mapper<SYSTTyp, Procedure> {

private static final Logger LOG =
LoggerFactory.getLogger(SystemischeTherapieProcedureMapper.class);
Expand All @@ -30,13 +31,9 @@ public SystemischeTherapieProcedureMapper(FhirProperties fhirProperties) {

public Procedure map(SYSTTyp syst, Reference subject) {
Objects.requireNonNull(syst, "Systemtherapie must not be null");
Objects.requireNonNull(subject, "Reference must not be null");

Validate.notBlank(syst.getSYSTID(), "Required SYST_ID is unset");
Validate.isTrue(
Objects.equals(
subject.getReferenceElement().getResourceType(), ResourceType.PATIENT.toCode()),
"The subject reference should point to a Patient resource");

verifyReference(subject, ResourceType.PATIENT);

var procedure = new Procedure();
procedure.getMeta().addProfile(fhirProperties.getProfiles().getMiiPrOnkoSystemischeTherapie());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.miracum.streams.ume.obdstofhir.mapper.mii;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;

import ca.uhn.fhir.context.FhirContext;
import com.fasterxml.jackson.databind.DeserializationFeature;
Expand All @@ -14,6 +15,7 @@
import org.approvaltests.Approvals;
import org.hl7.fhir.r4.model.Reference;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.miracum.streams.ume.obdstofhir.FhirProperties;
Expand Down Expand Up @@ -64,4 +66,61 @@ void map_withGivenObds_shouldCreateValidConditionResource(String sourceFile) thr
Approvals.verify(
fhirJson, Approvals.NAMES.withParameters(sourceFile).forFile().withExtension(".fhir.json"));
}

@Test
void shouldNotVerifyNullReferences() throws Exception {
final var resource = this.getClass().getClassLoader().getResource("obds3/Testpatient_1.xml");
assertThat(resource).isNotNull();

final var xmlMapper =
XmlMapper.builder()
.defaultUseWrapper(false)
.addModule(new JakartaXmlBindAnnotationModule())
.addModule(new Jdk8Module())
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.build();

final var obds = xmlMapper.readValue(resource.openStream(), OBDS.class);

var obdsPatient = obds.getMengePatient().getPatient().getFirst();

var wrongPatient = (Reference) null;
var conMeldung =
obdsPatient.getMengeMeldung().getMeldung().stream()
.filter(m -> m.getDiagnose() != null)
.findFirst()
.get();

var ex = assertThrows(NullPointerException.class, () -> sut.map(conMeldung, wrongPatient));
assertThat(ex).hasMessage("Reference to PATIENT must not be null");
}

@Test
void shouldNotVerifyWrongReferencesType() throws Exception {
final var resource = this.getClass().getClassLoader().getResource("obds3/Testpatient_1.xml");
assertThat(resource).isNotNull();

final var xmlMapper =
XmlMapper.builder()
.defaultUseWrapper(false)
.addModule(new JakartaXmlBindAnnotationModule())
.addModule(new Jdk8Module())
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.build();

final var obds = xmlMapper.readValue(resource.openStream(), OBDS.class);

var obdsPatient = obds.getMengePatient().getPatient().getFirst();

var wrongPatient = new Reference("Procedure/any");
var conMeldung =
obdsPatient.getMengeMeldung().getMeldung().stream()
.filter(m -> m.getDiagnose() != null)
.findFirst()
.get();

var ex = assertThrows(IllegalArgumentException.class, () -> sut.map(conMeldung, wrongPatient));

assertThat(ex).hasMessage("The reference should point to a PATIENT resource");
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.miracum.streams.ume.obdstofhir.mapper.mii;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;

import ca.uhn.fhir.context.FhirContext;
import com.fasterxml.jackson.databind.DeserializationFeature;
Expand All @@ -12,6 +13,7 @@
import org.approvaltests.Approvals;
import org.hl7.fhir.r4.model.Reference;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.miracum.streams.ume.obdstofhir.FhirProperties;
Expand Down Expand Up @@ -60,4 +62,64 @@ void map_withGivenObds_shouldCreateValidProcedure(String sourceFile) throws IOEx
Approvals.verify(
fhirJson, Approvals.NAMES.withParameters(sourceFile).forFile().withExtension(".fhir.json"));
}

@Test
void shouldNotVerifyNullReferences() throws Exception {
final var resource = this.getClass().getClassLoader().getResource("obds3/Testpatient_1.xml");
assertThat(resource).isNotNull();

final var xmlMapper =
XmlMapper.builder()
.defaultUseWrapper(false)
.addModule(new JakartaXmlBindAnnotationModule())
.addModule(new Jdk8Module())
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.build();

final var obds = xmlMapper.readValue(resource.openStream(), OBDS.class);

var obdsPatient = obds.getMengePatient().getPatient().getFirst();

var wrongPatient = (Reference) null;
var stMeldung =
obdsPatient.getMengeMeldung().getMeldung().stream()
.filter(m -> m.getST() != null)
.findFirst()
.get();

var ex =
assertThrows(NullPointerException.class, () -> sut.map(stMeldung.getST(), wrongPatient));
assertThat(ex).hasMessage("Reference to PATIENT must not be null");
}

@Test
void shouldNotVerifyWrongReferencesType() throws Exception {
final var resource = this.getClass().getClassLoader().getResource("obds3/Testpatient_1.xml");
assertThat(resource).isNotNull();

final var xmlMapper =
XmlMapper.builder()
.defaultUseWrapper(false)
.addModule(new JakartaXmlBindAnnotationModule())
.addModule(new Jdk8Module())
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.build();

final var obds = xmlMapper.readValue(resource.openStream(), OBDS.class);

var obdsPatient = obds.getMengePatient().getPatient().getFirst();

var wrongPatient = new Reference("Procedure/any");
var stMeldung =
obdsPatient.getMengeMeldung().getMeldung().stream()
.filter(m -> m.getST() != null)
.findFirst()
.get();

var ex =
assertThrows(
IllegalArgumentException.class, () -> sut.map(stMeldung.getST(), wrongPatient));

assertThat(ex).hasMessage("The reference should point to a PATIENT resource");
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.miracum.streams.ume.obdstofhir.mapper.mii;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;

import ca.uhn.fhir.context.FhirContext;
import com.fasterxml.jackson.databind.DeserializationFeature;
Expand All @@ -12,6 +13,7 @@
import org.approvaltests.Approvals;
import org.hl7.fhir.r4.model.Reference;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.miracum.streams.ume.obdstofhir.FhirProperties;
Expand Down Expand Up @@ -63,4 +65,68 @@ void map_withGivenObds_shouldCreateValidMedicationStatement(String sourceFile)
Approvals.verify(
fhirJson, Approvals.NAMES.withParameters(sourceFile).forFile().withExtension(".fhir.json"));
}

@Test
void shouldNotVerifyNullReferences() throws Exception {
final var resource = this.getClass().getClassLoader().getResource("obds3/Testpatient_1.xml");
assertThat(resource).isNotNull();

final var xmlMapper =
XmlMapper.builder()
.defaultUseWrapper(false)
.addModule(new JakartaXmlBindAnnotationModule())
.addModule(new Jdk8Module())
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.build();

final var obds = xmlMapper.readValue(resource.openStream(), OBDS.class);

var obdsPatient = obds.getMengePatient().getPatient().getFirst();

var wrongPatient = (Reference) null;
var procedure = new Reference("Procedure/any");
var systMeldung =
obdsPatient.getMengeMeldung().getMeldung().stream()
.filter(m -> m.getSYST() != null)
.findFirst()
.get();

var ex =
assertThrows(
NullPointerException.class,
() -> sut.map(systMeldung.getSYST(), wrongPatient, procedure));
assertThat(ex).hasMessage("Reference to PATIENT must not be null");
}

@Test
void shouldNotVerifyWrongReferencesType() throws Exception {
final var resource = this.getClass().getClassLoader().getResource("obds3/Testpatient_1.xml");
assertThat(resource).isNotNull();

final var xmlMapper =
XmlMapper.builder()
.defaultUseWrapper(false)
.addModule(new JakartaXmlBindAnnotationModule())
.addModule(new Jdk8Module())
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.build();

final var obds = xmlMapper.readValue(resource.openStream(), OBDS.class);

var obdsPatient = obds.getMengePatient().getPatient().getFirst();

var wrongPatient = new Reference("Procedure/any");
var procedure = new Reference("Procedure/any");
var systMeldung =
obdsPatient.getMengeMeldung().getMeldung().stream()
.filter(m -> m.getSYST() != null)
.findFirst()
.get();

var ex =
assertThrows(
IllegalArgumentException.class,
() -> sut.map(systMeldung.getSYST(), wrongPatient, procedure));
assertThat(ex).hasMessage("The reference should point to a PATIENT resource");
}
}
Loading

0 comments on commit faa6052

Please sign in to comment.