Skip to content

Commit

Permalink
Package refactoring.
Browse files Browse the repository at this point in the history
  • Loading branch information
kaicode authored and sivareddyp committed Oct 20, 2023
1 parent 12e3aa8 commit 8b43b14
Show file tree
Hide file tree
Showing 14 changed files with 92 additions and 168 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package org.snomed.cdsservice.model;

import org.snomed.cdsservice.service.model.SubstanceDefinedDailyDose;
import org.snomed.cdsservice.service.medication.dose.SubstanceDefinedDailyDose;

public class DosageComparisonByRoute {
PrescribedDailyDose totalPrescribedDailyDose;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package org.snomed.cdsservice.service;
package org.snomed.cdsservice.service.hello;

import org.snomed.cdsservice.model.CDSCard;
import org.snomed.cdsservice.model.CDSIndicator;
import org.snomed.cdsservice.model.CDSSource;
import org.snomed.cdsservice.rest.pojo.CDSRequest;
import org.snomed.cdsservice.service.CDSService;
import org.springframework.stereotype.Service;

import java.util.List;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.snomed.cdsservice.service;
package org.snomed.cdsservice.service.medication;

import com.google.common.base.Strings;
import org.hl7.fhir.r4.model.Coding;
Expand All @@ -10,6 +10,7 @@
import org.snomed.cdsservice.model.CDSSource;
import org.snomed.cdsservice.model.CDSTrigger;
import org.snomed.cdsservice.model.MedicationInterationCDSTrigger;
import org.snomed.cdsservice.service.ServiceException;
import org.snomed.cdsservice.service.tsclient.FHIRTerminologyServerClient;
import org.snomed.cdsservice.util.SnomedValueSetUtil;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down Expand Up @@ -71,11 +72,11 @@ public List<CDSTrigger> loadTriggers() throws ServiceException {
continue;
}

if (medication1SnomedCode != null && medication1SnomedCode.contains("|") && !medication1SnomedCode.startsWith("ECL=")) {
if (medication1SnomedCode.contains("|") && !medication1SnomedCode.startsWith("ECL=")) {
medication1SnomedCode = medication1SnomedCode.substring(medication1SnomedCode.indexOf("|")).trim();
}

if (medication2SnomedCode != null && medication2SnomedCode.contains("|") && !medication2SnomedCode.startsWith("ECL=")) {
if (medication2SnomedCode.contains("|") && !medication2SnomedCode.startsWith("ECL=")) {
medication2SnomedCode = medication2SnomedCode.substring(medication2SnomedCode.indexOf("|")).trim();
}

Expand All @@ -92,4 +93,4 @@ public List<CDSTrigger> loadTriggers() throws ServiceException {
}
return triggers;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.snomed.cdsservice.service;
package org.snomed.cdsservice.service.medication;

import com.google.common.base.Strings;
import org.apache.poi.ss.usermodel.Cell;
Expand All @@ -14,6 +14,7 @@
import org.snomed.cdsservice.model.CDSSource;
import org.snomed.cdsservice.model.CDSTrigger;
import org.snomed.cdsservice.model.MedicationConditionCDSTrigger;
import org.snomed.cdsservice.service.ServiceException;
import org.snomed.cdsservice.service.tsclient.FHIRTerminologyServerClient;
import org.snomed.cdsservice.util.SnomedSpreadsheetUtil;
import org.snomed.cdsservice.util.SnomedValueSetUtil;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.snomed.cdsservice.service;
package org.snomed.cdsservice.service.medication;

import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.parser.IParser;
Expand All @@ -10,6 +10,8 @@
import org.snomed.cdsservice.model.CDSReference;
import org.snomed.cdsservice.model.CDSTrigger;
import org.snomed.cdsservice.rest.pojo.CDSRequest;
import org.snomed.cdsservice.service.*;
import org.snomed.cdsservice.service.medication.dose.SnomedMedicationDefinedDailyDoseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.server.ResponseStatusException;
Expand All @@ -21,7 +23,7 @@
import java.util.stream.Stream;

@Service
public class MedicationOrderSelectService extends CDSService {
public class MedicationOrderSelectCDSService extends CDSService {

@Autowired
private FhirContext fhirContext;
Expand All @@ -39,7 +41,7 @@ public class MedicationOrderSelectService extends CDSService {

private List<CDSTrigger> drugDrugInteractionTriggers;

public MedicationOrderSelectService() {
public MedicationOrderSelectCDSService() {
super("medication-order-select");
setPrefetch(Map.of(
"patient", "Patient/{{context.patientId}}",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package org.snomed.cdsservice.service;
package org.snomed.cdsservice.service.medication.dose;

import org.hl7.fhir.r4.model.Coding;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.snomed.cdsservice.service.ServiceException;
import org.snomed.cdsservice.service.model.ManyToOneMapEntry;
import org.snomed.cdsservice.service.tsclient.FHIRTerminologyServerClient;
import org.snomed.cdsservice.util.SnomedValueSetUtil;
Expand Down Expand Up @@ -64,11 +65,11 @@ public List<ManyToOneMapEntry> loadDoseFormMap() throws ServiceException {
throw new ServiceException(format("Failed to expand value set '%s'", valueSetURI), e);
}
}
mapEntries.sort(Comparator.comparing(ManyToOneMapEntry::getMapPriority));
mapEntries.sort(Comparator.comparing(ManyToOneMapEntry::mapPriority));

return mapEntries;
} catch (Exception e) {
throw new ServiceException(format("Failed to load SNOMED CT Manufactured dose form to ATC route of administration - dynamic map %s.", tsvPath), e);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.snomed.cdsservice.service;
package org.snomed.cdsservice.service.medication.dose;

import jakarta.annotation.PostConstruct;
import net.steppschuh.markdowngenerator.list.UnorderedList;
Expand All @@ -9,8 +9,11 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.snomed.cdsservice.model.*;
import org.snomed.cdsservice.service.ArgumentAssertionUtil;
import org.snomed.cdsservice.service.ServiceException;
import org.snomed.cdsservice.service.medication.dose.MedicationDoseFormsLoaderService;
import org.snomed.cdsservice.service.model.ManyToOneMapEntry;
import org.snomed.cdsservice.service.model.SubstanceDefinedDailyDose;
import org.snomed.cdsservice.service.medication.dose.SubstanceDefinedDailyDose;
import org.snomed.cdsservice.service.tsclient.ConceptParameters;
import org.snomed.cdsservice.service.tsclient.FHIRTerminologyServerClient;
import org.snomed.cdsservice.service.tsclient.SnomedConceptNormalForm;
Expand Down Expand Up @@ -46,18 +49,19 @@ public class SnomedMedicationDefinedDailyDoseService {
public static final String ATTRIBUTE_HAS_CONCENTRATION_STRENGTH_NUMERATOR_UNIT = "733725009";
public static final String ATTRIBUTE_HAS_CONCENTRATION_STRENGTH_DENOMINATOR_VALUE = "1142137007";
public static final String ATTRIBUTE_HAS_CONCENTRATION_STRENGTH_DENOMINATOR_UNIT = "733722007";

public static final String WARNING = "warning";
public static final String INFO = "info";
private static final String NEW_LINE = "\n";
private final Map<String, List<SubstanceDefinedDailyDose>> substanceDDD = new HashMap<>();
private final Logger logger = LoggerFactory.getLogger(getClass());
@Value("${rules.medication-substance-daily-doses.tsv}")
private String tsvPath;

@Autowired
private FHIRTerminologyServerClient tsClient;

@Autowired
private MedicationDoseFormsLoaderService doseFormsLoaderService;
private List<ManyToOneMapEntry> doseFormsManySnomedToOneAtcCodeMap;

@Value("${rules.medication-substance-daily-doses.tsv}")
private String tsvPath;
@Value("${acceptable-daily-dose-threshold-factor}")
private String acceptableDailyDoseThresholdFactor;
@Value("${maximum-daily-dose-threshold-factor}")
Expand All @@ -67,6 +71,47 @@ public class SnomedMedicationDefinedDailyDoseService {
@Value("${who.atc.url-template}")
private String atcUrlTemplate;

private List<ManyToOneMapEntry> doseFormsManySnomedToOneAtcCodeMap;
private final Map<String, List<SubstanceDefinedDailyDose>> substanceDDD = new HashMap<>();
private final Logger logger = LoggerFactory.getLogger(getClass());

@PostConstruct
public void init() throws ServiceException {
doseFormsManySnomedToOneAtcCodeMap = doseFormsLoaderService.loadDoseFormMap();

logger.info("Loading SNOMED CT Substance Defined Daily Dose information");
try (BufferedReader reader = new BufferedReader(new FileReader(tsvPath))) {
String expectedHeader = "atc_code\tatc_name\tsnomed_code\tsnomed_label\tddd\tuom\tadm_r\tnote";
String header = reader.readLine();
if (!expectedHeader.equals(header)) {
throw new ServiceException(format("SNOMED Substance DDD file does not have the expected header. " + "Expected: '%s', Actual: '%s'", expectedHeader, header));
}

String line;
int row = 1;
try {
while ((line = reader.readLine()) != null) {
row++;
// Columns and indexes
// atc_code atc_name snomed_code snomed_label ddd uom adm_r note
// 0 1 2 3 4 5 6 7
String[] values = line.split("\t");
String substanceSnomedCode = values[2];
float dose = Float.parseFloat(values[4]);
String unit = values[5];
String atcRouteOfAdministrationCode = values[6];
String atcCode = values[0];
substanceDDD.computeIfAbsent(substanceSnomedCode, i -> new ArrayList<>()).add(new SubstanceDefinedDailyDose(atcRouteOfAdministrationCode, dose, unit, atcCode));
}
} catch (NumberFormatException e) {
throw new ServiceException(format("Failed to read SNOMED Substance DDDs from tab separated file. " + "Number format error while reading row %s", row), e);
}
} catch (Exception e) {
throw new ServiceException("Failed to read SNOMED Substance DDDs from tab separated file", e);
}
logger.info("Doses loaded for {} substances.", substanceDDD.size());
}

public List<CDSCard> checkMedications(List<MedicationRequest> medicationRequests) {
List<CDSCard> cards = new ArrayList<>();
Map<String, AggregatedMedicationsBySubstance> aggregatedMedicationsBySubstanceMap = new HashMap<>();
Expand Down Expand Up @@ -103,9 +148,9 @@ public List<CDSCard> checkMedications(List<MedicationRequest> medicationRequests
String atcRouteOfAdministrationCode = null;
String routeOfAdministrationLabel = null;
for (ManyToOneMapEntry manyToOneMapEntry : doseFormsManySnomedToOneAtcCodeMap) {
if (manyToOneMapEntry.getSourceCodes().contains(manufacturedDoseForm)) {
atcRouteOfAdministrationCode = manyToOneMapEntry.getTargetCode();
routeOfAdministrationLabel = manyToOneMapEntry.getLabel() != null ? manyToOneMapEntry.getLabel() : atcRouteOfAdministrationCode;
if (manyToOneMapEntry.sourceCodes().contains(manufacturedDoseForm)) {
atcRouteOfAdministrationCode = manyToOneMapEntry.targetCode();
routeOfAdministrationLabel = manyToOneMapEntry.label() != null ? manyToOneMapEntry.label() : atcRouteOfAdministrationCode;
}
}
if (atcRouteOfAdministrationCode == null) {
Expand Down Expand Up @@ -188,7 +233,7 @@ private void aggregateMedicationsBySubstance(Map<String, AggregatedMedicationsBy
}
SubstanceDefinedDailyDose substanceDefinedDailyDose = null;
for (SubstanceDefinedDailyDose substanceDDD : substanceDefinedDailyDoses) {
if (atcRouteOfAdministrationCode.equals(substanceDDD.getAtcRouteOfAdministration())) {
if (atcRouteOfAdministrationCode.equals(substanceDDD.atcRouteOfAdministration())) {
substanceDefinedDailyDose = substanceDDD;
}
}
Expand Down Expand Up @@ -223,7 +268,7 @@ private void aggregateMedicationsBySubstance(Map<String, AggregatedMedicationsBy


PrescribedDailyDose prescribedDailyDoseInUnitOfSubstanceStrength = getPrescribedDailyDoseInUnitOfSubstanceStrength(prescribedDailyDose, strengthValue, strengthUnit, denominatorValue, denominatorUnit);
PrescribedDailyDose prescribedDailyDoseInUnitOfDDD = getPrescribedDailyDoseInUnitOfDDD(prescribedDailyDoseInUnitOfSubstanceStrength.getQuantity(), prescribedDailyDoseInUnitOfSubstanceStrength.getUnit(), substanceDefinedDailyDose.getUnit());
PrescribedDailyDose prescribedDailyDoseInUnitOfDDD = getPrescribedDailyDoseInUnitOfDDD(prescribedDailyDoseInUnitOfSubstanceStrength.getQuantity(), prescribedDailyDoseInUnitOfSubstanceStrength.getUnit(), substanceDefinedDailyDose.unit());
AggregatedMedicationsBySubstance aggregatedMedicationsBySubstance = aggregatedMedicationsBySubstanceMap.get(substance);
if (aggregatedMedicationsBySubstance == null) {
String substanceShortName = getSnomedParameterValue(substance, "display");
Expand Down Expand Up @@ -259,7 +304,7 @@ private String getAtcUrl(Map.Entry<String, AggregatedMedicationsBySubstance> sub
return null;
}
DosageComparisonByRoute dosageComparisonByRoute = dosageInfoEntry.get().getValue();
return MessageFormat.format(atcUrlTemplate, dosageComparisonByRoute.getSubstanceDefinedDailyDose().getAtcCode());
return MessageFormat.format(atcUrlTemplate, dosageComparisonByRoute.getSubstanceDefinedDailyDose().atcCode());
}

private String getAlertIndicator(double prescribedDosageFactor) {
Expand All @@ -275,7 +320,7 @@ private String getAlertIndicator(double prescribedDosageFactor) {
private Double getPrescribedDosageFactor(Map<String, DosageComparisonByRoute> dosageComparisonByRouteMap) {
Double prescribedDosageFactor = Double.valueOf(0);
for (var eachRoute : dosageComparisonByRouteMap.entrySet()) {
prescribedDosageFactor = prescribedDosageFactor + (eachRoute.getValue().getTotalPrescribedDailyDose().getQuantity() / eachRoute.getValue().getSubstanceDefinedDailyDose().getDose());
prescribedDosageFactor = prescribedDosageFactor + (eachRoute.getValue().getTotalPrescribedDailyDose().getQuantity() / eachRoute.getValue().getSubstanceDefinedDailyDose().dose());
}
return prescribedDosageFactor;
}
Expand Down Expand Up @@ -311,43 +356,6 @@ private PrescribedDailyDose getPrescribedDailyDoseInUnitOfDDD(Double inputStreng
return new PrescribedDailyDose(prescribedDailyDoseQuantity, targetStrengthUnit);
}

@PostConstruct
public void init() throws ServiceException {
doseFormsManySnomedToOneAtcCodeMap = doseFormsLoaderService.loadDoseFormMap();

logger.info("Loading SNOMED CT Substance Defined Daily Dose information");
try (BufferedReader reader = new BufferedReader(new FileReader(tsvPath))) {
String expectedHeader = "atc_code\tatc_name\tsnomed_code\tsnomed_label\tddd\tuom\tadm_r\tnote";
String header = reader.readLine();
if (!expectedHeader.equals(header)) {
throw new ServiceException(format("SNOMED Substance DDD file does not have the expected header. " + "Expected: '%s', Actual: '%s'", expectedHeader, header));
}

String line;
int row = 1;
try {
while ((line = reader.readLine()) != null) {
row++;
// Columns and indexes
// atc_code atc_name snomed_code snomed_label ddd uom adm_r note
// 0 1 2 3 4 5 6 7
String[] values = line.split("\t");
String substanceSnomedCode = values[2];
float dose = Float.parseFloat(values[4]);
String unit = values[5];
String atcRouteOfAdministrationCode = values[6];
String atcCode = values[0];
substanceDDD.computeIfAbsent(substanceSnomedCode, i -> new ArrayList<>()).add(new SubstanceDefinedDailyDose(atcRouteOfAdministrationCode, dose, unit, atcCode));
}
} catch (NumberFormatException e) {
throw new ServiceException(format("Failed to read SNOMED Substance DDDs from tab separated file. " + "Number format error while reading row %s", row), e);
}
} catch (Exception e) {
throw new ServiceException("Failed to read SNOMED Substance DDDs from tab separated file", e);
}
logger.info("Doses loaded for {} substances.", substanceDDD.size());
}

private String getCardSummaryTemplate() {
return cardSummaryTemplate;
}
Expand All @@ -369,7 +377,7 @@ private void composeDosageByRoute(Map<String, DosageComparisonByRoute> dosageMap
DosageComparisonByRoute dosageComparisonByRouteValue = dosageInfo.getValue();
PrescribedDailyDose aggregatedDailyDosage = dosageComparisonByRouteValue.getTotalPrescribedDailyDose();
SubstanceDefinedDailyDose substanceDefinedDailyDose = dosageComparisonByRouteValue.getSubstanceDefinedDailyDose();
sb.append(new UnorderedList<>(List.of(dosageComparisonByRouteValue.getRouteOfAdministration(), new UnorderedList<>(List.of("Prescribed daily dose : " + aggregatedDailyDosage.getQuantity() + aggregatedDailyDosage.getUnit(), "Recommended average daily dose : " + substanceDefinedDailyDose.getDose() + substanceDefinedDailyDose.getUnit(), "Prescribed amount is " + getDecimalPlace(aggregatedDailyDosage.getQuantity() / substanceDefinedDailyDose.getDose()) + " times over the average daily dose"))))).append(NEW_LINE).append(NEW_LINE);
sb.append(new UnorderedList<>(List.of(dosageComparisonByRouteValue.getRouteOfAdministration(), new UnorderedList<>(List.of("Prescribed daily dose : " + aggregatedDailyDosage.getQuantity() + aggregatedDailyDosage.getUnit(), "Recommended average daily dose : " + substanceDefinedDailyDose.dose() + substanceDefinedDailyDose.unit(), "Prescribed amount is " + getDecimalPlace(aggregatedDailyDosage.getQuantity() / substanceDefinedDailyDose.dose()) + " times over the average daily dose"))))).append(NEW_LINE).append(NEW_LINE);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package org.snomed.cdsservice.service.medication.dose;

public record SubstanceDefinedDailyDose(String atcRouteOfAdministration, float dose, String unit, String atcCode) {

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,6 @@

import java.util.Set;

public class ManyToOneMapEntry {

private final Set<String> sourceCodes;
private final String targetCode;
private final int mapPriority;
private final String label;

public ManyToOneMapEntry(Set<String> sourceCodes, String targetCode, int mapPriority, String label) {
this.sourceCodes = sourceCodes;
this.targetCode = targetCode;
this.mapPriority = mapPriority;
this.label = label;
}


public Set<String> getSourceCodes() {
return sourceCodes;
}

public String getTargetCode() {
return targetCode;
}

public int getMapPriority() {
return mapPriority;
}

public String getLabel() {
return label;
}
public record ManyToOneMapEntry(Set<String> sourceCodes, String targetCode, int mapPriority, String label) {

}

This file was deleted.

Loading

0 comments on commit 8b43b14

Please sign in to comment.