mirror of
https://github.com/pcvolkmer/onkostar-plugin-dnpm.git
synced 2025-07-04 18:12:55 +00:00
refactor: use package name following Java guidelines
This commit is contained in:
54
src/main/java/dev/dnpm/VerweisVon.java
Normal file
54
src/main/java/dev/dnpm/VerweisVon.java
Normal file
@ -0,0 +1,54 @@
|
||||
package dev.dnpm;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
public class VerweisVon {
|
||||
private int procedure_id;
|
||||
private int data_form_id;
|
||||
private String data_catalogue;
|
||||
private String data_catalogue_entry;
|
||||
private String formname;
|
||||
private Date datum;
|
||||
|
||||
public VerweisVon() {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public int getProcedure_id() { return this.procedure_id; }
|
||||
public int getData_form_id() { return this.data_form_id; }
|
||||
public String getData_catalogue_name() { return this.data_catalogue; }
|
||||
public String getData_catalogue_entry_name() { return this.data_catalogue_entry; }
|
||||
public String getFormname() { return this.formname; }
|
||||
public Date getDate() { return this.datum; }
|
||||
public String getTable() {
|
||||
return "dk_" + this.data_catalogue.toLowerCase().replaceAll("[^a-zA-Z0-9]", "_");
|
||||
}
|
||||
public String getField() {
|
||||
return this.data_catalogue_entry.toLowerCase();
|
||||
}
|
||||
public String getSQL() {
|
||||
return "SELECT " + this.getField() + " AS value FROM " + this.getTable() + " WHERE id = " + this.getProcedure_id();
|
||||
}
|
||||
private String getDatumAsString() {
|
||||
SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd.MM.yyyy");
|
||||
String Datum = null;
|
||||
if (this.getDate() != null) {
|
||||
Datum = DATE_FORMAT.format(this.getDate());
|
||||
}
|
||||
return Datum;
|
||||
}
|
||||
public String getVerbundenesFormular() {
|
||||
String FName = "Formular " + this.getFormname();
|
||||
if (this.getDatumAsString() != null ) { FName += " vom " + this.getDatumAsString(); }
|
||||
return FName;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setProcedure_id(int procedure_id) {this.procedure_id = procedure_id; }
|
||||
public void setData_form_id(int data_form_id) {this.data_form_id = data_form_id; }
|
||||
public void setData_catalogue_name(String data_catalogue_name) {this.data_catalogue = data_catalogue_name; }
|
||||
public void setData_catalogue_entry_name(String data_catalogue_entry) {this.data_catalogue_entry = data_catalogue_entry; }
|
||||
public void setDate(Date datum) { this.datum = datum; }
|
||||
public void setFormname(String formname) { this.formname = formname; }
|
||||
}
|
12
src/main/java/dev/dnpm/analyzer/Analyzer.java
Normal file
12
src/main/java/dev/dnpm/analyzer/Analyzer.java
Normal file
@ -0,0 +1,12 @@
|
||||
package dev.dnpm.analyzer;
|
||||
|
||||
import de.itc.onkostar.api.analysis.OnkostarPluginType;
|
||||
|
||||
public abstract class Analyzer implements IPluginPart {
|
||||
|
||||
@Override
|
||||
public final OnkostarPluginType getType() {
|
||||
return OnkostarPluginType.ANALYZER;
|
||||
}
|
||||
|
||||
}
|
145
src/main/java/dev/dnpm/analyzer/AnalyzerUtils.java
Normal file
145
src/main/java/dev/dnpm/analyzer/AnalyzerUtils.java
Normal file
@ -0,0 +1,145 @@
|
||||
package dev.dnpm.analyzer;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Klasse mit Hilfsfunktionen für Analyzer
|
||||
*
|
||||
* @since 0.1.0
|
||||
*/
|
||||
public class AnalyzerUtils {
|
||||
|
||||
private AnalyzerUtils() {}
|
||||
|
||||
/**
|
||||
* Prüft, ob in InputMap einen Eintrag mit key <code>key</code> und Typ <code>type</code>
|
||||
* gefunden wurde.
|
||||
*
|
||||
* @param input InputMap
|
||||
* @param key Key des Werts
|
||||
* @param type Typ des Werts
|
||||
* @return <code>true</code>>, wenn ein Wert von dem Typ gefunden wurde
|
||||
*/
|
||||
public static boolean requiredValuePresent(final Map<String, Object> input, final String key, final Class<?> type) {
|
||||
var value = input.get(key);
|
||||
|
||||
if (null == value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return type.isInstance(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Übergibt ein Optional mit Wert, wenn in InputMap ein Eintrag mit key <code>key</code> und Typ <code>type</code>
|
||||
* gefunden wurde. Anderenfalls ein leeres Optional
|
||||
*
|
||||
* <p><b>Beispiel</b>
|
||||
* <pre>
|
||||
* var id = AnalyzerUtils.getRequiredValue(input, "id", Integer.class);
|
||||
* if (id.isEmpty()) {
|
||||
* logger.error("Keine ID angegeben!");
|
||||
* return false;
|
||||
* }
|
||||
*
|
||||
* var idNummer = id.get();
|
||||
* ...
|
||||
* </pre>
|
||||
*
|
||||
* @param input InputMap
|
||||
* @param key Key des Werts
|
||||
* @param type Typ des Werts
|
||||
* @return Optional mit entsprechendem Wert oder leeres Optional
|
||||
*/
|
||||
public static <T> Optional<T> getRequiredValue(final Map<String, Object> input, final String key, final Class<T> type) {
|
||||
if (! requiredValuePresent(input, key, type)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
var result = Optional.of((T)input.get(key));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prüft, ob ein Wert in der InputMap als Zeichenkette dem angegebenen RegExp entspricht
|
||||
*
|
||||
* @param input InputMap
|
||||
* @param key Key des Werts
|
||||
* @param regexp Der zu prüfende reguläre Ausdruck
|
||||
* @return <code>true</code>>, wenn ein Wert gefunden wurde, der dem RegExp entspricht
|
||||
*/
|
||||
public static boolean requiredValueMatches(final Map<String, Object> input, final String key, final String regexp) {
|
||||
var value = input.get(key);
|
||||
|
||||
if (null == value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return value.toString().matches(regexp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Übergibt ein Optional mit dem Wert als Zeichenkette, wenn er dem angegebenen RegExp entspricht.
|
||||
* Hierzu wird die Methode <code>toString()</code> auf den Wert angewendet.
|
||||
*
|
||||
* @param input InputMap
|
||||
* @param key Key des Werts
|
||||
* @param regexp Der zu prüfende reguläre Ausdruck
|
||||
* @return Optional mit entsprechendem Wert als Zeichenkette oder leeres Optional
|
||||
*/
|
||||
public static Optional<String> getRequiredValueMatching(final Map<String, Object> input, final String key, final String regexp) {
|
||||
if (! requiredValueMatches(input, key, regexp)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
return Optional.of(input.get(key).toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Prüft, ob ein Wert in der InputMap eine ID ist und damit eine Zahl größer Null ist.
|
||||
*
|
||||
* @param input InputMap
|
||||
* @param key Key des Werts
|
||||
* @return <code>true</code>>, wenn ein Wert gefunden wurde, der dem RegExp entspricht
|
||||
*/
|
||||
public static boolean requiredValueIsId(final Map<String, Object> input, final String key) {
|
||||
return requiredValuePresent(input, key, Integer.class) && Integer.parseInt(input.get(key).toString()) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Übergibt ein Optional, wenn der Wert eine ID ist und damit eine Zahl größer Null ist.
|
||||
* <p><b>Beispiel</b>
|
||||
* <pre>
|
||||
* var id = AnalyzerUtils.getRequiredId(input, "id");
|
||||
* if (id.isEmpty()) {
|
||||
* logger.error("Keine gültige ID angegeben!");
|
||||
* return false;
|
||||
* }
|
||||
*
|
||||
* // Ist hier immer größer als Null
|
||||
* var idNummer = id.get();
|
||||
* ...
|
||||
* </pre>
|
||||
*
|
||||
* @param input InputMap
|
||||
* @param key Key des Werts
|
||||
* @return Optional mit entsprechendem Wert oder leeres Optional
|
||||
*/
|
||||
public static Optional<Integer> getRequiredId(final Map<String, Object> input, final String key) {
|
||||
if (! requiredValuePresent(input, key, Integer.class)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
var id = (int)input.get(key);
|
||||
|
||||
if (id > 0) {
|
||||
return Optional.of(id);
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
}
|
25
src/main/java/dev/dnpm/analyzer/BackendService.java
Normal file
25
src/main/java/dev/dnpm/analyzer/BackendService.java
Normal file
@ -0,0 +1,25 @@
|
||||
package dev.dnpm.analyzer;
|
||||
|
||||
import de.itc.onkostar.api.Disease;
|
||||
import de.itc.onkostar.api.Procedure;
|
||||
import de.itc.onkostar.api.analysis.OnkostarPluginType;
|
||||
|
||||
public abstract class BackendService implements IPluginPart {
|
||||
|
||||
@Override
|
||||
public final OnkostarPluginType getType() {
|
||||
return OnkostarPluginType.BACKEND_SERVICE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ein Backend-Service verwendet die Methode nicht, daher wird hier eine final Stub-Implementierung
|
||||
* verwendet, die ein Überschreiben verhindert.
|
||||
* @param procedure
|
||||
* @param disease
|
||||
*/
|
||||
@Override
|
||||
public final void analyze(Procedure procedure, Disease disease) {
|
||||
// No op
|
||||
}
|
||||
|
||||
}
|
63
src/main/java/dev/dnpm/analyzer/ConsentManager.java
Normal file
63
src/main/java/dev/dnpm/analyzer/ConsentManager.java
Normal file
@ -0,0 +1,63 @@
|
||||
package dev.dnpm.analyzer;
|
||||
|
||||
import dev.dnpm.services.consent.ConsentManagerServiceFactory;
|
||||
import de.itc.onkostar.api.Disease;
|
||||
import de.itc.onkostar.api.IOnkostarApi;
|
||||
import de.itc.onkostar.api.Procedure;
|
||||
import de.itc.onkostar.api.analysis.AnalyzerRequirement;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ConsentManager extends Analyzer {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
private final IOnkostarApi onkostarApi;
|
||||
|
||||
private final ConsentManagerServiceFactory consentManagerServiceFactory;
|
||||
|
||||
public ConsentManager(
|
||||
final IOnkostarApi onkostarApi,
|
||||
final ConsentManagerServiceFactory consentManagerServiceFactory
|
||||
) {
|
||||
this.onkostarApi = onkostarApi;
|
||||
this.consentManagerServiceFactory = consentManagerServiceFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Aktualisiert Consent Daten in verknüpften Formularen";
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnalyzerRequirement getRequirement() {
|
||||
return AnalyzerRequirement.PROCEDURE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRelevantForAnalyzer(Procedure prozedur, Disease erkrankung) {
|
||||
return prozedur.getFormName().equals(onkostarApi.getGlobalSetting("consentform"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRelevantForDeletedProcedure() {
|
||||
// TODO is relevant for deleted procedure = true
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSynchronous() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void analyze(Procedure prozedur, Disease erkrankung) {
|
||||
var consentManagerService = consentManagerServiceFactory.currentUsableInstance();
|
||||
if (! consentManagerService.canApply(prozedur)) {
|
||||
logger.error("Fehler im ConsentManagement: Kann Prozedur mit Formularnamen '{}' nicht anwenden", prozedur.getFormName());
|
||||
return;
|
||||
}
|
||||
consentManagerService.applyConsent(prozedur);
|
||||
}
|
||||
|
||||
}
|
260
src/main/java/dev/dnpm/analyzer/DNPMHelper.java
Normal file
260
src/main/java/dev/dnpm/analyzer/DNPMHelper.java
Normal file
@ -0,0 +1,260 @@
|
||||
package dev.dnpm.analyzer;
|
||||
|
||||
import dev.dnpm.dto.EcogStatusWithDate;
|
||||
import dev.dnpm.VerweisVon;
|
||||
import dev.dnpm.security.DelegatingDataBasedPermissionEvaluator;
|
||||
import dev.dnpm.security.IllegalSecuredObjectAccessException;
|
||||
import dev.dnpm.security.PermissionType;
|
||||
import dev.dnpm.services.systemtherapie.SystemtherapieService;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.itc.onkostar.api.Disease;
|
||||
import de.itc.onkostar.api.IOnkostarApi;
|
||||
import de.itc.onkostar.api.Procedure;
|
||||
import de.itc.onkostar.api.analysis.AnalyzerRequirement;
|
||||
import org.hibernate.SQLQuery;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.transform.Transformers;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class DNPMHelper extends BackendService {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(DNPMHelper.class);
|
||||
|
||||
private final IOnkostarApi onkostarApi;
|
||||
|
||||
private final SystemtherapieService systemtherapieService;
|
||||
|
||||
private final DelegatingDataBasedPermissionEvaluator delegatingDataBasedPermissionEvaluator;
|
||||
|
||||
public DNPMHelper(
|
||||
final IOnkostarApi onkostarApi,
|
||||
final SystemtherapieService systemtherapieService,
|
||||
final DelegatingDataBasedPermissionEvaluator permissionEvaluator
|
||||
) {
|
||||
this.onkostarApi = onkostarApi;
|
||||
this.systemtherapieService = systemtherapieService;
|
||||
this.delegatingDataBasedPermissionEvaluator = permissionEvaluator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Methoden für DNPM-Formulare";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRelevantForDeletedProcedure() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSynchronous() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnalyzerRequirement getRequirement() {
|
||||
return AnalyzerRequirement.PROCEDURE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRelevantForAnalyzer(Procedure entry, Disease currentDisease) {
|
||||
// Plugin enthält nur Methoden für Formulare und soll nicht ausgeführt werden
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Map<String, String>> getVerweise(final Map<String, Object> input) {
|
||||
var procedureId = AnalyzerUtils.getRequiredId(input, "ProcedureId");
|
||||
var patientId = AnalyzerUtils.getRequiredId(input, "PatientId");
|
||||
|
||||
if (procedureId.isEmpty() || patientId.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var verbundeneFormulare = new ArrayList<Map<String, String>>();
|
||||
|
||||
try {
|
||||
SessionFactory sessionFactory = onkostarApi.getSessionFactory();
|
||||
Session session = sessionFactory.getCurrentSession();
|
||||
|
||||
String sql = "SELECT prozedur.id AS procedure_id, prozedur.data_form_id, data_catalogue.name AS data_catalogue, data_catalogue_entry.name AS data_catalogue_entry, data_form.description AS formname, prozedur.beginndatum AS datum " +
|
||||
"FROM prozedur " +
|
||||
"LEFT JOIN data_form_data_catalogue ON data_form_data_catalogue.data_form_id = prozedur.data_form_id " +
|
||||
"LEFT JOIN data_catalogue_entry ON data_catalogue_entry.data_catalogue_id = data_form_data_catalogue.data_catalogue_id " +
|
||||
"LEFT JOIN data_catalogue ON data_catalogue.id = data_catalogue_entry.data_catalogue_id " +
|
||||
"LEFT JOIN data_form ON data_form.id = prozedur.data_form_id " +
|
||||
"WHERE patient_id = " + patientId.get() + " " +
|
||||
"AND geloescht = 0 " +
|
||||
"AND data_catalogue_entry.type = 'formReference' " +
|
||||
"GROUP BY prozedur.id, prozedur.data_form_id, data_catalogue.name, data_catalogue_entry.name";
|
||||
|
||||
SQLQuery query = session.createSQLQuery(sql)
|
||||
.addScalar("procedure_id", StandardBasicTypes.INTEGER)
|
||||
.addScalar("data_form_id", StandardBasicTypes.INTEGER)
|
||||
.addScalar("data_catalogue", StandardBasicTypes.STRING)
|
||||
.addScalar("data_catalogue_entry", StandardBasicTypes.STRING)
|
||||
.addScalar("formname", StandardBasicTypes.STRING)
|
||||
.addScalar("datum", StandardBasicTypes.DATE);
|
||||
|
||||
query.setResultTransformer(Transformers.aliasToBean(VerweisVon.class));
|
||||
List<VerweisVon> result = query.list();
|
||||
try {
|
||||
int value = 0;
|
||||
for (VerweisVon verweisVon : result) {
|
||||
sql = verweisVon.getSQL();
|
||||
query = session.createSQLQuery(sql)
|
||||
.addScalar("value", StandardBasicTypes.INTEGER);
|
||||
if (query.uniqueResult() != null) {
|
||||
value = (Integer) query.uniqueResult();
|
||||
}
|
||||
if (value == procedureId.get()) {
|
||||
verbundeneFormulare.add(Map.of("formular", verweisVon.getVerbundenesFormular()));
|
||||
value = 0;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.warn("Fehler beim Hinzufügen eines Formularverweises", e);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Fehler beim Ermitteln der Formularverweise", e);
|
||||
return null;
|
||||
}
|
||||
return verbundeneFormulare;
|
||||
}
|
||||
|
||||
public List<Map<String, String>> getSystemischeTherapienFromDiagnose(final Map<String, Object> input) {
|
||||
var diagnoseId = AnalyzerUtils.getRequiredId(input, "DiagnoseId");
|
||||
if (diagnoseId.isEmpty()) {
|
||||
logger.error("Kein Parameter 'DiagnoseId' angegeben, gebe 'null' zurück");
|
||||
return null;
|
||||
}
|
||||
|
||||
return systemtherapieService.getSystemischeTherapienFromDiagnose(diagnoseId.get());
|
||||
}
|
||||
|
||||
public String getProzedurenFromDiagnose(final Map<String, Object> input) {
|
||||
// Prozedur, Feldname, Wert
|
||||
var dataForm = AnalyzerUtils.getRequiredValue(input, "dataForm", String.class);
|
||||
var diagnoseId = AnalyzerUtils.getRequiredId(input, "DiagnoseId");
|
||||
var patientId = AnalyzerUtils.getRequiredId(input, "PatientId");
|
||||
|
||||
if (dataForm.isEmpty() || diagnoseId.isEmpty() || patientId.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
var formulare = new ArrayList<Map<String, Object>>();
|
||||
List<Procedure> prozeduren = onkostarApi.getProceduresByPatientId(patientId.get());
|
||||
for (Procedure Prozedur : prozeduren) {
|
||||
// Formular gehört zur aktuellen Diagnose und hat den angegebenen Namen
|
||||
if (Prozedur.getDiseaseIds().contains(diagnoseId.get()) && Prozedur.getFormName().contains(dataForm.get())) {
|
||||
// alle Werte auslesen
|
||||
// System.out.println(WerteListe.getKey() + ": " + WerteListe.getValue());
|
||||
formulare.add(Map.of(
|
||||
"Formular", Prozedur.getFormName(),
|
||||
"Felder", new HashMap<>(Prozedur.getAllValues())
|
||||
));
|
||||
}
|
||||
}
|
||||
try {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
return objectMapper.writeValueAsString(formulare);
|
||||
} catch (JsonProcessingException e) {
|
||||
logger.error("Kann Formulare nicht in JSON mappen", e);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public Object getEmpfehlung(final Map<String, Object> input) {
|
||||
var procedureID = AnalyzerUtils.getRequiredId(input, "ProcedureID");
|
||||
|
||||
if (procedureID.isEmpty()) {
|
||||
logger.error("Kein Parameter 'ProcedureID' angegeben, gebe 'null' zurück");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
SessionFactory sessionFactory = onkostarApi.getSessionFactory();
|
||||
Session session = sessionFactory.getCurrentSession();
|
||||
var sql = "SELECT prozedur.id, genname, geneid, geneidlink, empfehlung, beginndatum FROM prozedur "
|
||||
+ "LEFT JOIN dk_mtb_einzelempfehlung em ON em.id = prozedur.id "
|
||||
+ "JOIN data_form df ON prozedur.data_form_id = df.id AND df.name = 'MR.MTB_Einzelempfehlung' "
|
||||
+ "WHERE prozedur.hauptprozedur_id = " + procedureID.get() + " AND prozedur.geloescht = 0 "
|
||||
+ "ORDER BY beginndatum";
|
||||
|
||||
SQLQuery query = session.createSQLQuery(sql)
|
||||
.addScalar("id", StandardBasicTypes.STRING)
|
||||
.addScalar("genname", StandardBasicTypes.STRING)
|
||||
.addScalar("geneid", StandardBasicTypes.STRING)
|
||||
.addScalar("geneidlink", StandardBasicTypes.STRING)
|
||||
.addScalar("empfehlung", StandardBasicTypes.STRING)
|
||||
.addScalar("beginndatum", StandardBasicTypes.STRING);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<String[]> rows = query.list();
|
||||
return rows;
|
||||
} catch (Exception e) {
|
||||
logger.error("Fehler bei Abfrage von Empfehlungen", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Object updateEmpfehlungPrio(final Map<String, Object> input) {
|
||||
// Auslesen und Prüfen der Parameter aus 'input'
|
||||
var rid = AnalyzerUtils.getRequiredId(input, "rid");
|
||||
if (rid.isEmpty()) {
|
||||
logger.error("Kein Parameter 'rid' angegeben, gebe 'false' zurück");
|
||||
return false;
|
||||
}
|
||||
|
||||
var strDate = AnalyzerUtils.getRequiredValueMatching(input, "bd", "[\\d]{4}-[\\d]{2}-[\\d]{2}");
|
||||
if (strDate.isEmpty()) {
|
||||
logger.error("Kein oder ungültiger Parameter 'bd' angegeben, gebe 'false' zurück");
|
||||
return false;
|
||||
}
|
||||
|
||||
//String strD = strDate.toString();
|
||||
//String CompareDate = strD.substring(1, 11);
|
||||
//DateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd");
|
||||
|
||||
try {
|
||||
String sql = "UPDATE prozedur SET beginndatum = '" + strDate.get() + "' WHERE id = '" + rid.get() + "' ";
|
||||
SQLQuery result = onkostarApi.getSessionFactory().getCurrentSession().createSQLQuery(sql);
|
||||
result.executeUpdate();
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return "Achtung: Ein Fehler ist aufgetreten, Änderung konnte nicht gespeichert werden!";
|
||||
//return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public List<EcogStatusWithDate> getEcogStatus(final Map<String, Object> input) {
|
||||
var pid = AnalyzerUtils.getRequiredId(input, "PatientId");
|
||||
if (pid.isEmpty()) {
|
||||
logger.error("Kein Parameter 'PatientId' angegeben, gebe leere Liste zurück");
|
||||
return List.of();
|
||||
}
|
||||
|
||||
var patient = onkostarApi.getPatient(pid.get());
|
||||
if (null == patient) {
|
||||
logger.error("Patient nicht gefunden, gebe leere Liste zurück");
|
||||
return List.of();
|
||||
}
|
||||
|
||||
if (delegatingDataBasedPermissionEvaluator.hasPermission(SecurityContextHolder.getContext().getAuthentication(), patient, PermissionType.READ)) {
|
||||
return systemtherapieService.ecogStatus(patient);
|
||||
}
|
||||
|
||||
throw new IllegalSecuredObjectAccessException("Kein Zugriff auf diesen Patienten");
|
||||
}
|
||||
}
|
134
src/main/java/dev/dnpm/analyzer/EinzelempfehlungAnalyzer.java
Normal file
134
src/main/java/dev/dnpm/analyzer/EinzelempfehlungAnalyzer.java
Normal file
@ -0,0 +1,134 @@
|
||||
package dev.dnpm.analyzer;
|
||||
|
||||
import dev.dnpm.dto.Studie;
|
||||
import dev.dnpm.dto.Variant;
|
||||
import dev.dnpm.security.PermissionType;
|
||||
import dev.dnpm.security.PersonPoolBasedPermissionEvaluator;
|
||||
import dev.dnpm.services.StudienService;
|
||||
import dev.dnpm.services.molekulargenetik.MolekulargenetikFormService;
|
||||
import de.itc.onkostar.api.Disease;
|
||||
import de.itc.onkostar.api.IOnkostarApi;
|
||||
import de.itc.onkostar.api.Procedure;
|
||||
import de.itc.onkostar.api.analysis.AnalyzerRequirement;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Diese Klasse implementiert ein Plugin, welches Funktionen für DNPM UF Einzelempfehlung bereitstellt.
|
||||
*
|
||||
* @since 0.2.0
|
||||
*/
|
||||
@Component
|
||||
public class EinzelempfehlungAnalyzer extends BackendService {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(EinzelempfehlungAnalyzer.class);
|
||||
|
||||
private final IOnkostarApi onkostarApi;
|
||||
|
||||
private final MolekulargenetikFormService molekulargenetikFormService;
|
||||
|
||||
private final StudienService studienService;
|
||||
|
||||
private final PersonPoolBasedPermissionEvaluator permissionEvaluator;
|
||||
|
||||
public EinzelempfehlungAnalyzer(
|
||||
final IOnkostarApi onkostarApi,
|
||||
final StudienService studienService,
|
||||
final MolekulargenetikFormService molekulargenetikFormService,
|
||||
final PersonPoolBasedPermissionEvaluator permissionEvaluator
|
||||
) {
|
||||
this.onkostarApi = onkostarApi;
|
||||
this.studienService = studienService;
|
||||
this.molekulargenetikFormService = molekulargenetikFormService;
|
||||
this.permissionEvaluator = permissionEvaluator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Stellt Funktionen zur Nutzung im Therapieplan-Unterformular für Einzelempfehlungen bereit";
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
@Override
|
||||
public boolean isRelevantForDeletedProcedure() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRelevantForAnalyzer(Procedure procedure, Disease disease) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSynchronous() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnalyzerRequirement getRequirement() {
|
||||
return AnalyzerRequirement.PROCEDURE;
|
||||
}
|
||||
|
||||
public List<Variant> getVariants(Map<String, Object> input) {
|
||||
var procedureId = AnalyzerUtils.getRequiredId(input, "id");
|
||||
|
||||
if (procedureId.isEmpty()) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
var procedure = onkostarApi.getProcedure(procedureId.get());
|
||||
if (null == procedure) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
if (permissionEvaluator.hasPermission(SecurityContextHolder.getContext().getAuthentication(), procedure, PermissionType.READ)) {
|
||||
return molekulargenetikFormService.getVariants(procedure);
|
||||
} else {
|
||||
logger.error("Security: No permission to access procedure '{}'", procedure.getId());
|
||||
return List.of();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Übergibt alle Studien, deren (Kurz-)Beschreibung oder NCT-Nummer den übergebenen Eingabewert <code>q</code> enthält
|
||||
*
|
||||
* <p>Wurde der Eingabewert nicht angegeben oder ist leer, werden alle Studien übergeben.
|
||||
*
|
||||
* <p>Beispiel zur Nutzung in einem Formularscript
|
||||
* <pre>
|
||||
* executePluginMethod(
|
||||
* 'TherapieplanAnalyzer',
|
||||
* 'getStudien',
|
||||
* { q: 'NCT-12', inactive: true },
|
||||
* (response) => console.log(response),
|
||||
* false
|
||||
* );
|
||||
* </pre>
|
||||
*
|
||||
* @param input Map mit Eingabewerten
|
||||
* @return Liste mit Studien
|
||||
*/
|
||||
public List<Studie> getStudien(Map<String, Object> input) {
|
||||
var query = AnalyzerUtils.getRequiredValue(input, "q", String.class);
|
||||
var inactive = AnalyzerUtils.getRequiredValue(input, "inactive", Boolean.class).orElse(false);
|
||||
|
||||
if (query.isEmpty() || query.get().isBlank()) {
|
||||
if (inactive) {
|
||||
return studienService.findAll();
|
||||
}
|
||||
return studienService.findActive();
|
||||
}
|
||||
if (inactive) {
|
||||
return studienService.findByQuery(query.get());
|
||||
}
|
||||
return studienService.findActiveByQuery(query.get());
|
||||
}
|
||||
|
||||
}
|
103
src/main/java/dev/dnpm/analyzer/FollowUpAnalyzer.java
Normal file
103
src/main/java/dev/dnpm/analyzer/FollowUpAnalyzer.java
Normal file
@ -0,0 +1,103 @@
|
||||
package dev.dnpm.analyzer;
|
||||
|
||||
import de.itc.onkostar.api.Disease;
|
||||
import de.itc.onkostar.api.IOnkostarApi;
|
||||
import de.itc.onkostar.api.Item;
|
||||
import de.itc.onkostar.api.Procedure;
|
||||
import de.itc.onkostar.api.analysis.AnalyseTriggerEvent;
|
||||
import de.itc.onkostar.api.analysis.AnalyzerRequirement;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Diese Klasse implementiert ein Plugin, welches Aktionen nach Bearbeitung eines FollowUps durchführt.
|
||||
*
|
||||
* @since 0.0.2
|
||||
*/
|
||||
@Component
|
||||
public class FollowUpAnalyzer extends Analyzer {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
private final IOnkostarApi onkostarApi;
|
||||
|
||||
public FollowUpAnalyzer(IOnkostarApi onkostarApi) {
|
||||
this.onkostarApi = onkostarApi;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Aktualisiert verknüpfte Formulare nach Änderungen im FollowUp-Formular";
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
@Override
|
||||
public boolean isRelevantForDeletedProcedure() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRelevantForAnalyzer(Procedure procedure, Disease disease) {
|
||||
return null != procedure && procedure.getFormName().equals("DNPM FollowUp");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSynchronous() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnalyzerRequirement getRequirement() {
|
||||
return AnalyzerRequirement.PROCEDURE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<AnalyseTriggerEvent> getTriggerEvents() {
|
||||
return Set.of(
|
||||
AnalyseTriggerEvent.EDIT_SAVE,
|
||||
AnalyseTriggerEvent.EDIT_LOCK,
|
||||
AnalyseTriggerEvent.REORG
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void analyze(Procedure procedure, Disease disease) {
|
||||
backlinkToEinzelempfehlung(procedure);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verlinke aktuelles FollowUp in angegebener Einzelempfehlung
|
||||
*
|
||||
* @param procedure Das FollowUp
|
||||
*/
|
||||
private void backlinkToEinzelempfehlung(Procedure procedure) {
|
||||
if (null == procedure.getValue("LinkTherapieempfehlung")) {
|
||||
return;
|
||||
}
|
||||
|
||||
var referencedProcedureId = procedure.getValue("LinkTherapieempfehlung");
|
||||
if (null == referencedProcedureId || referencedProcedureId.getInt() == 0) {
|
||||
// Alles gut, es ist keine Einzelempfehlung angegeben
|
||||
return;
|
||||
}
|
||||
|
||||
var referencedProcedure = onkostarApi.getProcedure(referencedProcedureId.getInt());
|
||||
if (null == referencedProcedure) {
|
||||
logger.error("Referenzierte Einzelempfehlung wurde nicht gefunden: {}", referencedProcedureId);
|
||||
return;
|
||||
}
|
||||
|
||||
referencedProcedure.setValue("refdnpmfollowup", new Item("ref_dnpm_followup", procedure.getId()));
|
||||
|
||||
try {
|
||||
onkostarApi.saveProcedure(referencedProcedure);
|
||||
} catch (Exception e) {
|
||||
logger.error("FollowUp konnte nicht mit Einzelempfehlung verknüpft werden", e);
|
||||
}
|
||||
}
|
||||
}
|
19
src/main/java/dev/dnpm/analyzer/IPluginPart.java
Normal file
19
src/main/java/dev/dnpm/analyzer/IPluginPart.java
Normal file
@ -0,0 +1,19 @@
|
||||
package dev.dnpm.analyzer;
|
||||
|
||||
import de.itc.onkostar.api.analysis.IProcedureAnalyzer;
|
||||
|
||||
public interface IPluginPart extends IProcedureAnalyzer {
|
||||
|
||||
default String getVersion() {
|
||||
return "0.4.0";
|
||||
}
|
||||
|
||||
default String getName() {
|
||||
return "DNPM Plugin";
|
||||
}
|
||||
|
||||
default String getDescription() {
|
||||
return String.format("Plugin-Bestandteil '%s'", this.getClass().getSimpleName());
|
||||
}
|
||||
|
||||
}
|
97
src/main/java/dev/dnpm/analyzer/Merkmalskatalog.java
Normal file
97
src/main/java/dev/dnpm/analyzer/Merkmalskatalog.java
Normal file
@ -0,0 +1,97 @@
|
||||
package dev.dnpm.analyzer;
|
||||
|
||||
import de.itc.onkostar.api.Disease;
|
||||
import de.itc.onkostar.api.IOnkostarApi;
|
||||
import de.itc.onkostar.api.Procedure;
|
||||
import de.itc.onkostar.api.analysis.AnalyzerRequirement;
|
||||
import org.hibernate.SQLQuery;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class Merkmalskatalog extends BackendService {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
private final IOnkostarApi onkostarApi;
|
||||
|
||||
public Merkmalskatalog(final IOnkostarApi onkostarApi) {
|
||||
this.onkostarApi = onkostarApi;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Methoden für Merkmalskataloge";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRelevantForDeletedProcedure() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSynchronous() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnalyzerRequirement getRequirement() {
|
||||
return AnalyzerRequirement.PROCEDURE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRelevantForAnalyzer(Procedure procedure, Disease currentDisease) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<String[]> getMerkmalskatalog(final Map<String, Object> input) {
|
||||
var merkmalskatalog = AnalyzerUtils.getRequiredValue(input, "Merkmalskatalog", String.class);
|
||||
var spalten = AnalyzerUtils.getRequiredValue(input, "Spalten", String.class);
|
||||
|
||||
if (merkmalskatalog.isEmpty()) {
|
||||
logger.error("Kein Merkmalskatalog angegeben!");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (spalten.isEmpty()) {
|
||||
logger.error("Keine Spalten angegeben!");
|
||||
return null;
|
||||
}
|
||||
|
||||
String[] spaltenArray = spalten.get().split("\\s*,\\s*");
|
||||
|
||||
try {
|
||||
SQLQuery query = getSqlQuery(merkmalskatalog.get());
|
||||
|
||||
for (String s : spaltenArray) {
|
||||
query.addScalar(s, StandardBasicTypes.STRING);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<String[]> rows = query.list();
|
||||
return rows;
|
||||
} catch (Exception e) {
|
||||
logger.error("Fehler bei der Ausführung von getMerkmalskatalog()", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private SQLQuery getSqlQuery(String merkmalskatalog) {
|
||||
SessionFactory sessionFactory = onkostarApi.getSessionFactory();
|
||||
Session session = sessionFactory.getCurrentSession();
|
||||
|
||||
String sql = "SELECT p.id, p.code, p.shortdesc, p.description, p.note, p.synonyms "
|
||||
+ "FROM property_catalogue "
|
||||
+ "LEFT JOIN property_catalogue_version ON property_catalogue_version.datacatalog_id = property_catalogue.id "
|
||||
+ "LEFT JOIN property_catalogue_version_entry p ON p.property_version_id = property_catalogue_version.id "
|
||||
+ "WHERE name = '" + merkmalskatalog + "' AND aktiv = 1 "
|
||||
+ "ORDER BY position ASC";
|
||||
|
||||
return session.createSQLQuery(sql);
|
||||
}
|
||||
}
|
168
src/main/java/dev/dnpm/analyzer/TherapieMitEcogAnalyzer.java
Normal file
168
src/main/java/dev/dnpm/analyzer/TherapieMitEcogAnalyzer.java
Normal file
@ -0,0 +1,168 @@
|
||||
package dev.dnpm.analyzer;
|
||||
|
||||
import dev.dnpm.dto.EcogStatusWithDate;
|
||||
import dev.dnpm.services.strahlentherapie.StrahlentherapieService;
|
||||
import dev.dnpm.services.systemtherapie.SystemtherapieService;
|
||||
import de.itc.onkostar.api.Disease;
|
||||
import de.itc.onkostar.api.IOnkostarApi;
|
||||
import de.itc.onkostar.api.Item;
|
||||
import de.itc.onkostar.api.Procedure;
|
||||
import de.itc.onkostar.api.analysis.AnalyseTriggerEvent;
|
||||
import de.itc.onkostar.api.analysis.AnalyzerRequirement;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Diese Klasse implementiert ein Plugin, welches Aktionen nach Bearbeitung eines Formulars zur Systemtherapie durchführt.
|
||||
*
|
||||
* @since 0.6.0
|
||||
*/
|
||||
@Component
|
||||
public class TherapieMitEcogAnalyzer extends Analyzer {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
private final IOnkostarApi onkostarApi;
|
||||
|
||||
private final StrahlentherapieService strahlentherapieService;
|
||||
private final SystemtherapieService systemtherapieService;
|
||||
|
||||
public TherapieMitEcogAnalyzer(
|
||||
final IOnkostarApi onkostarApi,
|
||||
final StrahlentherapieService strahlentherapieService,
|
||||
final SystemtherapieService systemtherapieService
|
||||
) {
|
||||
this.onkostarApi = onkostarApi;
|
||||
this.strahlentherapieService = strahlentherapieService;
|
||||
this.systemtherapieService = systemtherapieService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Aktualisiert verknüpfte Formulare nach Änderungen in Formularen vom Typ Strahlen-/Systemtherapie mit ECOG-Status";
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
@Override
|
||||
public boolean isRelevantForDeletedProcedure() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRelevantForAnalyzer(Procedure procedure, Disease disease) {
|
||||
return null != procedure && null != disease && (
|
||||
procedure.getFormName().equals("OS.Strahlentherapie")
|
||||
|| procedure.getFormName().equals("OS.Strahlentherapie.VarianteUKW")
|
||||
|| procedure.getFormName().equals("OS.Systemische Therapie")
|
||||
|| procedure.getFormName().equals("OS.Systemische Therapie.VarianteUKW")
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSynchronous() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnalyzerRequirement getRequirement() {
|
||||
return AnalyzerRequirement.PROCEDURE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<AnalyseTriggerEvent> getTriggerEvents() {
|
||||
return Set.of(
|
||||
AnalyseTriggerEvent.EDIT_SAVE,
|
||||
AnalyseTriggerEvent.EDIT_LOCK,
|
||||
AnalyseTriggerEvent.REORG
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void analyze(Procedure procedure, Disease disease) {
|
||||
var date = procedure.getStartDate();
|
||||
var status = procedure.getValue("ECOGvorTherapie");
|
||||
|
||||
if (null == date || null == status) {
|
||||
// Ignore
|
||||
return;
|
||||
}
|
||||
|
||||
var ecog = strahlentherapieService.ecogStatus(procedure.getPatient())
|
||||
.stream()
|
||||
.filter(ecogStatusWithDate -> ecogStatusWithDate.getDate().after(disease.getDiagnosisDate()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
ecog.addAll(systemtherapieService.ecogStatus(procedure.getPatient())
|
||||
.stream()
|
||||
.filter(ecogStatusWithDate -> ecogStatusWithDate.getDate().after(disease.getDiagnosisDate()))
|
||||
.collect(Collectors.toList()));
|
||||
|
||||
|
||||
if (ecog.isEmpty()) {
|
||||
// Nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
procedure.getPatient().getDiseases().stream()
|
||||
.flatMap(d -> onkostarApi.getProceduresForDiseaseByForm(d.getId(), "DNPM Klinik/Anamnese").stream())
|
||||
.forEach(p -> {
|
||||
var ufEcog = p.getValue("ECOGVerlauf");
|
||||
if (null != ufEcog && ufEcog.getValue() instanceof List) {
|
||||
updateExistingEcogVerlauf(p, ecog, ufEcog);
|
||||
} else {
|
||||
newEcogverlauf(p, ecog);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateExistingEcogVerlauf(Procedure p, List<EcogStatusWithDate> ecogFromCompleted, Item ufEcog) {
|
||||
var shouldSave = false;
|
||||
var existingDates = ufEcog.<List<Map<String, String>>>getValue().stream()
|
||||
.map(v -> v.get("Datum"))
|
||||
.collect(Collectors.toList());
|
||||
for (var ecog : ecogFromCompleted) {
|
||||
var formattedDate = new SimpleDateFormat("yyyy-MM-dd").format(ecog.getDate());
|
||||
if (!existingDates.contains(formattedDate)) {
|
||||
var newSubProcedure = new Procedure(onkostarApi);
|
||||
newSubProcedure.setStartDate(ecog.getDate());
|
||||
newSubProcedure.setValue("Datum", new Item("Datum", ecog.getDate()));
|
||||
newSubProcedure.setValue("ECOG", new Item("ECOG", ecog.getStatus()));
|
||||
p.addSubProcedure("ECOGVerlauf", newSubProcedure);
|
||||
shouldSave = true;
|
||||
}
|
||||
}
|
||||
if (shouldSave) {
|
||||
try {
|
||||
onkostarApi.saveProcedure(p, true);
|
||||
} catch (Exception e) {
|
||||
logger.error("Cannot update ECOG for procedure '{}'", p.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void newEcogverlauf(Procedure p, List<EcogStatusWithDate> ecogFromCompleted) {
|
||||
p.setValue("ECOGVerlauf", new Item("ECOGVerlauf", List.of()));
|
||||
for (var ecog : ecogFromCompleted) {
|
||||
var newSubProcedure = new Procedure(onkostarApi);
|
||||
newSubProcedure.setStartDate(ecog.getDate());
|
||||
newSubProcedure.setValue("Datum", new Item("Datum", ecog.getDate()));
|
||||
newSubProcedure.setValue("ECOG", new Item("ECOG", ecog.getStatus()));
|
||||
p.addSubProcedure("ECOGVerlauf", newSubProcedure);
|
||||
}
|
||||
try {
|
||||
onkostarApi.saveProcedure(p, true);
|
||||
} catch (Exception e) {
|
||||
logger.error("Create update ECOG for procedure '{}'", p.getId());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
127
src/main/java/dev/dnpm/analyzer/TherapieplanAnalyzer.java
Normal file
127
src/main/java/dev/dnpm/analyzer/TherapieplanAnalyzer.java
Normal file
@ -0,0 +1,127 @@
|
||||
package dev.dnpm.analyzer;
|
||||
|
||||
import dev.dnpm.security.DelegatingDataBasedPermissionEvaluator;
|
||||
import dev.dnpm.security.PermissionType;
|
||||
import dev.dnpm.services.mtb.MtbService;
|
||||
import dev.dnpm.services.therapieplan.TherapieplanServiceFactory;
|
||||
import de.itc.onkostar.api.Disease;
|
||||
import de.itc.onkostar.api.Procedure;
|
||||
import de.itc.onkostar.api.analysis.AnalyseTriggerEvent;
|
||||
import de.itc.onkostar.api.analysis.AnalyzerRequirement;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Diese Klasse implementiert ein Plugin, welches Aktionen nach Bearbeitung eines Therapieplans durchführt.
|
||||
*
|
||||
* @since 0.0.2
|
||||
*/
|
||||
@Component
|
||||
public class TherapieplanAnalyzer extends Analyzer {
|
||||
|
||||
private final TherapieplanServiceFactory therapieplanServiceFactory;
|
||||
|
||||
private final MtbService mtbService;
|
||||
|
||||
private final DelegatingDataBasedPermissionEvaluator permissionEvaluator;
|
||||
|
||||
public TherapieplanAnalyzer(
|
||||
final TherapieplanServiceFactory therapieplanServiceFactory,
|
||||
final MtbService mtbService,
|
||||
final DelegatingDataBasedPermissionEvaluator permissionEvaluator
|
||||
) {
|
||||
this.therapieplanServiceFactory = therapieplanServiceFactory;
|
||||
this.mtbService = mtbService;
|
||||
this.permissionEvaluator = permissionEvaluator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Aktualisiert Unterformulare nach Änderungen im Therapieplan-Formular";
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
@Override
|
||||
public boolean isRelevantForDeletedProcedure() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRelevantForAnalyzer(Procedure procedure, Disease disease) {
|
||||
return null != procedure && procedure.getFormName().equals("DNPM Therapieplan");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSynchronous() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnalyzerRequirement getRequirement() {
|
||||
return AnalyzerRequirement.PROCEDURE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<AnalyseTriggerEvent> getTriggerEvents() {
|
||||
return Set.of(
|
||||
AnalyseTriggerEvent.EDIT_SAVE,
|
||||
AnalyseTriggerEvent.EDIT_LOCK,
|
||||
AnalyseTriggerEvent.REORG
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void analyze(Procedure procedure, Disease disease) {
|
||||
therapieplanServiceFactory.currentUsableInstance().updateRequiredMtbEntries(procedure);
|
||||
}
|
||||
|
||||
/**
|
||||
* Übergibt den Text der referenzierten MTBs für den Protokollauszug
|
||||
*
|
||||
* <p>Wurde der Eingabewert <code>id</code> nicht übergeben, wird ein leerer String zurück gegeben.
|
||||
*
|
||||
* <p>Beispiel zur Nutzung in einem Formularscript
|
||||
* <pre>
|
||||
* executePluginMethod(
|
||||
* 'TherapieplanAnalyzer',
|
||||
* 'getProtokollauszug',
|
||||
* { id: 12345 },
|
||||
* (response) => console.log(response),
|
||||
* false
|
||||
* );
|
||||
* </pre>
|
||||
*
|
||||
* @param input Map mit Eingabewerten
|
||||
* @return Zeichenkette mit Protokollauszug
|
||||
*/
|
||||
public String getProtokollauszug(Map<String, Object> input) {
|
||||
var procedureId = AnalyzerUtils.getRequiredId(input, "id");
|
||||
|
||||
if (procedureId.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (
|
||||
permissionEvaluator.hasPermission(
|
||||
SecurityContextHolder.getContext().getAuthentication(),
|
||||
procedureId.get(),
|
||||
Procedure.class.getSimpleName(),
|
||||
PermissionType.READ
|
||||
)
|
||||
) {
|
||||
return mtbService.getProtocol(
|
||||
therapieplanServiceFactory
|
||||
.currentUsableInstance()
|
||||
.findReferencedMtbs(procedureId.get())
|
||||
);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
88
src/main/java/dev/dnpm/config/PluginConfiguration.java
Normal file
88
src/main/java/dev/dnpm/config/PluginConfiguration.java
Normal file
@ -0,0 +1,88 @@
|
||||
package dev.dnpm.config;
|
||||
|
||||
import dev.dnpm.database.SettingsRepository;
|
||||
import dev.dnpm.services.*;
|
||||
import dev.dnpm.services.consent.ConsentManagerServiceFactory;
|
||||
import dev.dnpm.services.molekulargenetik.MolekulargenetikFormService;
|
||||
import dev.dnpm.services.molekulargenetik.OsMolekulargenetikFormService;
|
||||
import dev.dnpm.services.mtb.DefaultMtbService;
|
||||
import dev.dnpm.services.mtb.MtbService;
|
||||
import dev.dnpm.services.strahlentherapie.DefaultStrahlentherapieService;
|
||||
import dev.dnpm.services.strahlentherapie.StrahlentherapieService;
|
||||
import dev.dnpm.services.systemtherapie.DefaultSystemtherapieService;
|
||||
import dev.dnpm.services.systemtherapie.SystemtherapieService;
|
||||
import dev.dnpm.services.therapieplan.TherapieplanServiceFactory;
|
||||
import de.itc.onkostar.api.IOnkostarApi;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
/**
|
||||
* Dynamische Konfiguration des Plugins basierend auf Onkostar-Einstellungen
|
||||
*
|
||||
* @since 0.0.2
|
||||
*/
|
||||
@Configuration
|
||||
@ComponentScan(basePackages = { "dev.dnpm.analyzer", "dev.dnpm.security" })
|
||||
@EnableJpaRepositories(basePackages = "dev.dnpm.database")
|
||||
public class PluginConfiguration {
|
||||
|
||||
@Bean
|
||||
public FormService formService(final DataSource dataSource) {
|
||||
return new DefaultFormService(dataSource);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public StudienService studienService(final DataSource dataSource) {
|
||||
return new DefaultStudienService(dataSource);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SettingsService settingsService(final SettingsRepository settingsRepository) {
|
||||
return new SettingsService(settingsRepository);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MtbService mtbService(final IOnkostarApi onkostarApi) {
|
||||
return new DefaultMtbService(onkostarApi);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SystemtherapieService systemtherapieService(
|
||||
final IOnkostarApi onkostarApi,
|
||||
final SettingsService settingsService
|
||||
) {
|
||||
return new DefaultSystemtherapieService(onkostarApi, settingsService);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public StrahlentherapieService strahlentherapieService(
|
||||
final IOnkostarApi onkostarApi,
|
||||
final SettingsService settingsService
|
||||
) {
|
||||
return new DefaultStrahlentherapieService(onkostarApi, settingsService);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ConsentManagerServiceFactory consentManagerServiceFactory(final IOnkostarApi onkostarApi) {
|
||||
return new ConsentManagerServiceFactory(onkostarApi);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TherapieplanServiceFactory therapieplanServiceFactory(
|
||||
final IOnkostarApi onkostarApi,
|
||||
final SettingsService settingsService,
|
||||
final FormService formService
|
||||
) {
|
||||
return new TherapieplanServiceFactory(onkostarApi, settingsService, formService);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MolekulargenetikFormService molekulargenetikFormService() {
|
||||
return new OsMolekulargenetikFormService();
|
||||
}
|
||||
|
||||
}
|
22
src/main/java/dev/dnpm/database/ReadOnlyRepository.java
Normal file
22
src/main/java/dev/dnpm/database/ReadOnlyRepository.java
Normal file
@ -0,0 +1,22 @@
|
||||
package dev.dnpm.database;
|
||||
|
||||
import org.springframework.data.repository.NoRepositoryBean;
|
||||
import org.springframework.data.repository.Repository;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Basis-Repository for ReadOnly Spring-Data-JPA Repositories
|
||||
* <p>Entity-Klassen müssen in Package <code>de.itc.db.dnpm</code> liegen
|
||||
* @param <T> Typ des Entities
|
||||
* @param <ID> Typ der ID
|
||||
*/
|
||||
@NoRepositoryBean
|
||||
public interface ReadOnlyRepository<T, ID extends Serializable> extends Repository<T, ID> {
|
||||
|
||||
T findById(ID id);
|
||||
|
||||
List<T> findAll();
|
||||
|
||||
}
|
14
src/main/java/dev/dnpm/database/SettingsRepository.java
Normal file
14
src/main/java/dev/dnpm/database/SettingsRepository.java
Normal file
@ -0,0 +1,14 @@
|
||||
package dev.dnpm.database;
|
||||
|
||||
import de.itc.db.dnpm.Setting;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* Spring Data JPA Repository zum Lesen von Einstellungen
|
||||
*/
|
||||
@Repository("dnpmSettingRepository")
|
||||
public interface SettingsRepository extends ReadOnlyRepository<Setting, Long> {
|
||||
|
||||
Setting findByName(String name);
|
||||
|
||||
}
|
44
src/main/java/dev/dnpm/dto/EcogStatusWithDate.java
Normal file
44
src/main/java/dev/dnpm/dto/EcogStatusWithDate.java
Normal file
@ -0,0 +1,44 @@
|
||||
package dev.dnpm.dto;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Datenklasse zum Abbilden des ECOG-Status und Datum
|
||||
*/
|
||||
public class EcogStatusWithDate {
|
||||
private final Date date;
|
||||
private final String status;
|
||||
|
||||
public EcogStatusWithDate(Date date, String status) {
|
||||
Assert.notNull(date, "Date cannot be null");
|
||||
Assert.hasText(status, "Status cannot be empty String");
|
||||
Assert.isTrue(isValidEcogCode(status), "Not a valid ADT.LeistungszustandECOG code");
|
||||
this.date = date;
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
private boolean isValidEcogCode(String status) {
|
||||
switch (status) {
|
||||
case "0":
|
||||
case "1":
|
||||
case "2":
|
||||
case "3":
|
||||
case "4":
|
||||
case "5":
|
||||
case "U":
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public Date getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
}
|
74
src/main/java/dev/dnpm/dto/Studie.java
Normal file
74
src/main/java/dev/dnpm/dto/Studie.java
Normal file
@ -0,0 +1,74 @@
|
||||
package dev.dnpm.dto;
|
||||
|
||||
public class Studie {
|
||||
private final String kategorieName;
|
||||
private final String code;
|
||||
private final String studiennummer;
|
||||
private final String shortDesc;
|
||||
private final String description;
|
||||
private final int version;
|
||||
|
||||
private final boolean active;
|
||||
|
||||
public Studie(final String kategorieName, final int version, final String code, final String studiennummer, final String shortDesc, final String description, final boolean active) {
|
||||
this.kategorieName = kategorieName;
|
||||
this.version = version;
|
||||
this.code = code;
|
||||
this.studiennummer = studiennummer;
|
||||
this.shortDesc = shortDesc;
|
||||
this.description = description;
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
public String getKategorieName() {
|
||||
return kategorieName;
|
||||
}
|
||||
|
||||
public int getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getStudiennummer() {
|
||||
return studiennummer;
|
||||
}
|
||||
|
||||
public String getShortDesc() {
|
||||
return shortDesc;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
if (this.hasNctNumber()) {
|
||||
return Type.NCT;
|
||||
} else if (this.hasEudraCtNumber()) {
|
||||
return Type.EUDRA_CT;
|
||||
} else {
|
||||
return Type.UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasNctNumber() {
|
||||
return null != studiennummer && studiennummer.toLowerCase().startsWith("nct");
|
||||
}
|
||||
|
||||
private boolean hasEudraCtNumber() {
|
||||
return null != studiennummer && studiennummer.matches("\\d{4}-\\d{6}-\\d{2}");
|
||||
}
|
||||
|
||||
public enum Type {
|
||||
NCT,
|
||||
EUDRA_CT,
|
||||
UNKNOWN
|
||||
}
|
||||
}
|
110
src/main/java/dev/dnpm/dto/Variant.java
Normal file
110
src/main/java/dev/dnpm/dto/Variant.java
Normal file
@ -0,0 +1,110 @@
|
||||
package dev.dnpm.dto;
|
||||
|
||||
import de.itc.onkostar.api.Procedure;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Ein Auszug der Variante aus dem NGS-Bericht zur Übertragung an das Frontend zur Auswahl der stützenden molekularen Alteration
|
||||
*
|
||||
* @since 0.2.0
|
||||
*/
|
||||
public class Variant {
|
||||
private final Integer id;
|
||||
|
||||
private final String ergebnis;
|
||||
|
||||
private final String gen;
|
||||
|
||||
private final String exon;
|
||||
|
||||
private final String pathogenitaetsklasse;
|
||||
|
||||
private Variant(
|
||||
final int id,
|
||||
final String ergebnis,
|
||||
final String gen,
|
||||
final String exon,
|
||||
final String pathogenitaetsklasse
|
||||
) {
|
||||
this.id = id;
|
||||
this.ergebnis = ergebnis;
|
||||
this.gen = gen;
|
||||
this.exon = exon;
|
||||
this.pathogenitaetsklasse = pathogenitaetsklasse;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getErgebnis() {
|
||||
return ergebnis;
|
||||
}
|
||||
|
||||
public String getGen() {
|
||||
return gen;
|
||||
}
|
||||
|
||||
public String getExon() {
|
||||
return exon;
|
||||
}
|
||||
|
||||
public String getPathogenitaetsklasse() {
|
||||
return pathogenitaetsklasse;
|
||||
}
|
||||
|
||||
/**
|
||||
* Erstellt ein Optional einer Variante aus einer Prozedur
|
||||
* @param procedure Die zu verwendende Prozedur
|
||||
* @return Das Optional, wenn die Prozedur verwendet werden kann, ansonsten ein leeres Optional
|
||||
*/
|
||||
public static Optional<Variant> fromProcedure(Procedure procedure) {
|
||||
if (!"OS.Molekulargenetische Untersuchung".equals(procedure.getFormName())) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
var ergebnis = procedure.getValue("Ergebnis");
|
||||
var gene = procedure.getValue("Untersucht");
|
||||
var exon = procedure.getValue("ExonInt");
|
||||
var pathogenitaetsklasse = procedure.getValue("Pathogenitaetsklasse");
|
||||
|
||||
if (null == gene) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
if (ergebnis.getString().equals("P")) {
|
||||
return Optional.of(
|
||||
new Variant(
|
||||
procedure.getId(),
|
||||
"Einfache Variante (Mutation)",
|
||||
gene.getString().isBlank() ? "-" : gene.getString(),
|
||||
null == exon || exon.getString().isBlank() ? "-" : exon.getString(),
|
||||
null == pathogenitaetsklasse || pathogenitaetsklasse.getString().isBlank() ? "-" : pathogenitaetsklasse.getString()
|
||||
)
|
||||
);
|
||||
} else if (ergebnis.getString().equals("CNV")) {
|
||||
return Optional.of(
|
||||
new Variant(
|
||||
procedure.getId(),
|
||||
"Copy Number Variation (CNV)",
|
||||
gene.getString().isBlank() ? "-" : gene.getString(),
|
||||
null == exon || exon.getString().isBlank() ? "-" : exon.getString(),
|
||||
null == pathogenitaetsklasse || pathogenitaetsklasse.getString().isBlank() ? "-" : pathogenitaetsklasse.getString()
|
||||
)
|
||||
);
|
||||
} else if (ergebnis.getString().equals("F")) {
|
||||
return Optional.of(
|
||||
new Variant(
|
||||
procedure.getId(),
|
||||
"Fusion (Translokation Inversion Insertion)",
|
||||
gene.getString().isBlank() ? "-" : gene.getString(),
|
||||
null == exon || exon.getString().isBlank() ? "-" : exon.getString(),
|
||||
null == pathogenitaetsklasse || pathogenitaetsklasse.getString().isBlank() ? "-" : pathogenitaetsklasse.getString()
|
||||
)
|
||||
);
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
}
|
9
src/main/java/dev/dnpm/exceptions/FormException.java
Normal file
9
src/main/java/dev/dnpm/exceptions/FormException.java
Normal file
@ -0,0 +1,9 @@
|
||||
package dev.dnpm.exceptions;
|
||||
|
||||
public class FormException extends RuntimeException {
|
||||
|
||||
public FormException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package dev.dnpm.security;
|
||||
|
||||
import de.itc.onkostar.api.IOnkostarApi;
|
||||
import de.itc.onkostar.api.Patient;
|
||||
import de.itc.onkostar.api.Procedure;
|
||||
import org.springframework.security.access.PermissionEvaluator;
|
||||
|
||||
public abstract class AbstractDelegatedPermissionEvaluator implements PermissionEvaluator {
|
||||
|
||||
protected static final String PATIENT = Patient.class.getSimpleName();
|
||||
|
||||
protected static final String PROCEDURE = Procedure.class.getSimpleName();
|
||||
|
||||
protected final IOnkostarApi onkostarApi;
|
||||
|
||||
protected final SecurityService securityService;
|
||||
|
||||
protected AbstractDelegatedPermissionEvaluator(final IOnkostarApi onkostarApi, final SecurityService securityService) {
|
||||
this.onkostarApi = onkostarApi;
|
||||
this.securityService = securityService;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package dev.dnpm.security;
|
||||
|
||||
import org.springframework.security.access.PermissionEvaluator;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* PermissionEvaluator zur Gesamtprüfung der Zugriffsberechtigung.
|
||||
* Die konkrete Berechtigungsprüfung wird an die nachgelagerten PermissionEvaluatoren delegiert,
|
||||
* welche jeweils einzeln dem Zugriff zustimmen müssen.
|
||||
*/
|
||||
@Component
|
||||
public class DelegatingDataBasedPermissionEvaluator implements PermissionEvaluator {
|
||||
|
||||
private final List<AbstractDelegatedPermissionEvaluator> permissionEvaluators;
|
||||
|
||||
public DelegatingDataBasedPermissionEvaluator(final List<AbstractDelegatedPermissionEvaluator> permissionEvaluators) {
|
||||
this.permissionEvaluators = permissionEvaluators;
|
||||
}
|
||||
|
||||
/**
|
||||
* Auswertung der Zugriffsberechtigung für authentifizierten Benutzer auf Zielobjekt mit angeforderter Berechtigung.
|
||||
* Hierbei wird die Berechtigungsprüfung an alle nachgelagerten PermissionEvaluatoren delegiert.
|
||||
* Alle müssen dem Zugriff zustimmen.
|
||||
*
|
||||
* @param authentication Das Authentication Objekt
|
||||
* @param targetObject Das Zielobjekt
|
||||
* @param permissionType Die angeforderte Berechtigung
|
||||
* @return Gibt <code>true</code> zurück, wenn der Benutzer die Berechtigung hat
|
||||
*/
|
||||
@Override
|
||||
public boolean hasPermission(Authentication authentication, Object targetObject, Object permissionType) {
|
||||
return permissionEvaluators.stream()
|
||||
.allMatch(permissionEvaluator -> permissionEvaluator.hasPermission(authentication, targetObject, permissionType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Auswertung anhand der ID und des Namens des Zielobjekts.
|
||||
* Hierbei wird die Berechtigungsprüfung an alle nachgelagerten PermissionEvaluatoren delegiert.
|
||||
* Alle müssen dem Zugriff zustimmen.
|
||||
*
|
||||
* @param authentication Authentication-Object
|
||||
* @param targetId ID des Objekts
|
||||
* @param targetType Name der Zielobjektklasse
|
||||
* @param permissionType Die angeforderte Berechtigung
|
||||
* @return Gibt <code>true</code> zurück, wenn der Benutzer die Berechtigung hat
|
||||
*/
|
||||
@Override
|
||||
public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permissionType) {
|
||||
return permissionEvaluators.stream()
|
||||
.allMatch(permissionEvaluator -> permissionEvaluator.hasPermission(authentication, targetId, targetType, permissionType));
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package dev.dnpm.security;
|
||||
|
||||
import de.itc.onkostar.api.IOnkostarApi;
|
||||
import de.itc.onkostar.api.Procedure;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Permission-Evaluator zur Auswertung der Berechtigung auf Objekte aufgrund der Formularberechtigung
|
||||
*/
|
||||
@Component
|
||||
public class FormBasedPermissionEvaluator extends AbstractDelegatedPermissionEvaluator {
|
||||
|
||||
public FormBasedPermissionEvaluator(final IOnkostarApi onkostarApi, final SecurityService securityService) {
|
||||
super(onkostarApi, securityService);
|
||||
}
|
||||
|
||||
/**
|
||||
* Auswertung der Zugriffsberechtigung für authentifizierten Benutzer auf Zielobjekt mit angeforderter Berechtigung.
|
||||
* Zugriff auf Objekte vom Typ "Patient" wird immer gewährt.
|
||||
*
|
||||
* @param authentication Das Authentication Objekt
|
||||
* @param targetObject Das Zielobjekt
|
||||
* @param permissionType Die angeforderte Berechtigung
|
||||
* @return Gibt <code>true</code> zurück, wenn der Benutzer die Berechtigung hat
|
||||
*/
|
||||
@Override
|
||||
public boolean hasPermission(Authentication authentication, Object targetObject, Object permissionType) {
|
||||
if (permissionType instanceof PermissionType && targetObject instanceof Procedure) {
|
||||
return this.securityService.getFormNamesForPermission(authentication, (PermissionType)permissionType)
|
||||
.contains(((Procedure)targetObject).getFormName());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Auswertung anhand der ID und des Namens des Zielobjekts.
|
||||
* Zugriff auf Objekte vom Typ "Patient" wird immer gewährt.
|
||||
*
|
||||
* @param authentication Authentication-Object
|
||||
* @param targetId ID des Objekts
|
||||
* @param targetType Name der Zielobjektklasse
|
||||
* @param permissionType Die angeforderte Berechtigung
|
||||
* @return Gibt <code>true</code> zurück, wenn der Benutzer die Berechtigung hat
|
||||
*/
|
||||
@Override
|
||||
public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permissionType) {
|
||||
if (permissionType instanceof PermissionType && targetId instanceof Integer && PROCEDURE.equals(targetType)) {
|
||||
var procedure = this.onkostarApi.getProcedure((int)targetId);
|
||||
if (null != procedure) {
|
||||
return this.securityService.getFormNamesForPermission(authentication, (PermissionType) permissionType).contains(procedure.getFormName());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
package dev.dnpm.security;
|
||||
|
||||
import de.itc.onkostar.api.Procedure;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.annotation.AfterReturning;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Before;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
// TODO Disabled for now - check bytecode reported incompatibility for older OS installations
|
||||
//@Component
|
||||
@Aspect
|
||||
public class FormBasedSecurityAspects {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
private final FormBasedPermissionEvaluator permissionEvaluator;
|
||||
|
||||
public FormBasedSecurityAspects(
|
||||
final FormBasedPermissionEvaluator permissionEvaluator
|
||||
) {
|
||||
this.permissionEvaluator = permissionEvaluator;
|
||||
}
|
||||
|
||||
@AfterReturning(value = "@annotation(dev.dnpm.security.FormSecuredResult)", returning = "procedure")
|
||||
public void afterProcedureFormBased(Procedure procedure) {
|
||||
if (
|
||||
null != procedure
|
||||
&& ! permissionEvaluator.hasPermission(SecurityContextHolder.getContext().getAuthentication(), procedure, PermissionType.READ_WRITE)
|
||||
) {
|
||||
logger.warn("Rückgabe von Prozedur blockiert: {}", procedure.getId());
|
||||
throw new IllegalSecuredObjectAccessException();
|
||||
}
|
||||
}
|
||||
|
||||
@Before(value = "@annotation(dev.dnpm.security.FormSecured)")
|
||||
public void beforeProcedureFormBased(JoinPoint jp) {
|
||||
Arrays.stream(jp.getArgs())
|
||||
.filter(arg -> arg instanceof Procedure)
|
||||
.forEach(procedure -> {
|
||||
if (! permissionEvaluator.hasPermission(SecurityContextHolder.getContext().getAuthentication(), procedure, PermissionType.READ_WRITE)) {
|
||||
logger.warn("Zugriff auf Prozedur blockiert: {}", ((Procedure)procedure).getId());
|
||||
throw new IllegalSecuredObjectAccessException();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
14
src/main/java/dev/dnpm/security/FormSecured.java
Normal file
14
src/main/java/dev/dnpm/security/FormSecured.java
Normal file
@ -0,0 +1,14 @@
|
||||
package dev.dnpm.security;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface FormSecured {
|
||||
|
||||
PermissionType value() default PermissionType.READ_WRITE;
|
||||
|
||||
}
|
14
src/main/java/dev/dnpm/security/FormSecuredResult.java
Normal file
14
src/main/java/dev/dnpm/security/FormSecuredResult.java
Normal file
@ -0,0 +1,14 @@
|
||||
package dev.dnpm.security;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface FormSecuredResult {
|
||||
|
||||
PermissionType value() default PermissionType.READ_WRITE;
|
||||
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package dev.dnpm.security;
|
||||
|
||||
public class IllegalSecuredObjectAccessException extends RuntimeException {
|
||||
|
||||
public IllegalSecuredObjectAccessException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public IllegalSecuredObjectAccessException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
6
src/main/java/dev/dnpm/security/PermissionType.java
Normal file
6
src/main/java/dev/dnpm/security/PermissionType.java
Normal file
@ -0,0 +1,6 @@
|
||||
package dev.dnpm.security;
|
||||
|
||||
public enum PermissionType {
|
||||
READ,
|
||||
READ_WRITE
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
package dev.dnpm.security;
|
||||
|
||||
import de.itc.onkostar.api.IOnkostarApi;
|
||||
import de.itc.onkostar.api.Patient;
|
||||
import de.itc.onkostar.api.Procedure;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Permission-Evaluator zur Auswertung der Berechtigung auf Objekte aufgrund der Personenstammberechtigung
|
||||
*/
|
||||
@Component
|
||||
public class PersonPoolBasedPermissionEvaluator extends AbstractDelegatedPermissionEvaluator {
|
||||
|
||||
public PersonPoolBasedPermissionEvaluator(final IOnkostarApi onkostarApi, final SecurityService securityService) {
|
||||
super(onkostarApi, securityService);
|
||||
}
|
||||
|
||||
/**
|
||||
* Auswertung der Zugriffsberechtigung für authentifizierten Benutzer auf Zielobjekt mit angeforderter Berechtigung.
|
||||
* @param authentication Das Authentication Objekt
|
||||
* @param targetObject Das Zielobjekt
|
||||
* @param permissionType Die angeforderte Berechtigung
|
||||
* @return Gibt <code>true</code> zurück, wenn der Benutzer die Berechtigung hat
|
||||
*/
|
||||
@Override
|
||||
public boolean hasPermission(Authentication authentication, Object targetObject, Object permissionType) {
|
||||
if (permissionType instanceof PermissionType) {
|
||||
if (targetObject instanceof Patient) {
|
||||
return this.securityService.getPersonPoolIdsForPermission(authentication, (PermissionType)permissionType)
|
||||
.contains(((Patient)targetObject).getPersonPoolCode());
|
||||
} else if (targetObject instanceof Procedure) {
|
||||
return this.securityService.getPersonPoolIdsForPermission(authentication, (PermissionType)permissionType)
|
||||
.contains(((Procedure)targetObject).getPatient().getPersonPoolCode());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Auswertung anhand der ID und des Namens des Zielobjekts.
|
||||
* @param authentication Authentication-Object
|
||||
* @param targetId ID des Objekts
|
||||
* @param targetType Name der Zielobjektklasse
|
||||
* @param permissionType Die angeforderte Berechtigung
|
||||
* @return Gibt <code>true</code> zurück, wenn der Benutzer die Berechtigung hat
|
||||
*/
|
||||
@Override
|
||||
public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permissionType) {
|
||||
if (targetId instanceof Integer && permissionType instanceof PermissionType) {
|
||||
var personPoolCode = getPersonPoolCode((int)targetId, targetType);
|
||||
if (null != personPoolCode) {
|
||||
return this.securityService.getPersonPoolIdsForPermission(authentication, (PermissionType) permissionType).contains(personPoolCode);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private String getPersonPoolCode(int id, String type) {
|
||||
Patient patient = null;
|
||||
|
||||
if (PATIENT.equals(type)) {
|
||||
patient = onkostarApi.getPatient(id);
|
||||
} else if (PROCEDURE.equals(type)) {
|
||||
var procedure = onkostarApi.getProcedure(id);
|
||||
if (null != procedure) {
|
||||
patient = procedure.getPatient();
|
||||
}
|
||||
}
|
||||
|
||||
if (null != patient) {
|
||||
return patient.getPersonPoolCode();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
package dev.dnpm.security;
|
||||
|
||||
import de.itc.onkostar.api.Patient;
|
||||
import de.itc.onkostar.api.Procedure;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.annotation.AfterReturning;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Before;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@Component
|
||||
@Aspect
|
||||
public class PersonPoolBasedSecurityAspects {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
private final PersonPoolBasedPermissionEvaluator permissionEvaluator;
|
||||
|
||||
public PersonPoolBasedSecurityAspects(PersonPoolBasedPermissionEvaluator permissionEvaluator) {
|
||||
this.permissionEvaluator = permissionEvaluator;
|
||||
}
|
||||
|
||||
@AfterReturning(value = "@annotation(dev.dnpm.security.PersonPoolSecuredResult) ", returning = "patient")
|
||||
public void afterPatient(Patient patient) {
|
||||
if (
|
||||
null != patient
|
||||
&& ! permissionEvaluator.hasPermission(SecurityContextHolder.getContext().getAuthentication(), patient, PermissionType.READ_WRITE)
|
||||
) {
|
||||
logger.warn("Rückgabe von Patient blockiert: {}", patient.getId());
|
||||
throw new IllegalSecuredObjectAccessException();
|
||||
}
|
||||
}
|
||||
|
||||
@AfterReturning(value = "@annotation(dev.dnpm.security.PersonPoolSecuredResult)", returning = "procedure")
|
||||
public void afterProcedure(Procedure procedure) {
|
||||
if (
|
||||
null != procedure
|
||||
&& ! permissionEvaluator.hasPermission(SecurityContextHolder.getContext().getAuthentication(), procedure, PermissionType.READ_WRITE)
|
||||
) {
|
||||
logger.warn("Rückgabe von Prozedur blockiert: {}", procedure.getId());
|
||||
throw new IllegalSecuredObjectAccessException();
|
||||
}
|
||||
}
|
||||
|
||||
@Before(value = "@annotation(dev.dnpm.security.PersonPoolSecured)")
|
||||
public void beforePatient(JoinPoint jp) {
|
||||
Arrays.stream(jp.getArgs())
|
||||
.filter(arg -> arg instanceof Patient)
|
||||
.forEach(patient -> {
|
||||
if (! permissionEvaluator.hasPermission(SecurityContextHolder.getContext().getAuthentication(), patient, PermissionType.READ_WRITE)) {
|
||||
logger.warn("Zugriff auf Patient blockiert: {}", ((Patient)patient).getId());
|
||||
throw new IllegalSecuredObjectAccessException();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Before(value = "@annotation(dev.dnpm.security.PersonPoolSecured)")
|
||||
public void beforeProcedure(JoinPoint jp) {
|
||||
Arrays.stream(jp.getArgs())
|
||||
.filter(arg -> arg instanceof Procedure)
|
||||
.forEach(procedure -> {
|
||||
if (! permissionEvaluator.hasPermission(SecurityContextHolder.getContext().getAuthentication(), procedure, PermissionType.READ_WRITE)) {
|
||||
logger.warn("Zugriff auf Prozedur blockiert: {}", ((Procedure)procedure).getId());
|
||||
throw new IllegalSecuredObjectAccessException();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
14
src/main/java/dev/dnpm/security/PersonPoolSecured.java
Normal file
14
src/main/java/dev/dnpm/security/PersonPoolSecured.java
Normal file
@ -0,0 +1,14 @@
|
||||
package dev.dnpm.security;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface PersonPoolSecured {
|
||||
|
||||
PermissionType value() default PermissionType.READ_WRITE;
|
||||
|
||||
}
|
14
src/main/java/dev/dnpm/security/PersonPoolSecuredResult.java
Normal file
14
src/main/java/dev/dnpm/security/PersonPoolSecuredResult.java
Normal file
@ -0,0 +1,14 @@
|
||||
package dev.dnpm.security;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface PersonPoolSecuredResult {
|
||||
|
||||
PermissionType value() default PermissionType.READ_WRITE;
|
||||
|
||||
}
|
60
src/main/java/dev/dnpm/security/SecurityService.java
Normal file
60
src/main/java/dev/dnpm/security/SecurityService.java
Normal file
@ -0,0 +1,60 @@
|
||||
package dev.dnpm.security;
|
||||
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Service mit Methoden zum Feststellen von sicherheitsrelevanten Informationen eines Benutzers
|
||||
*/
|
||||
@Service
|
||||
public class SecurityService {
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
|
||||
public SecurityService(final DataSource dataSource) {
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
}
|
||||
|
||||
List<String> getPersonPoolIdsForPermission(Authentication authentication, PermissionType permissionType) {
|
||||
var sql = "SELECT p.kennung FROM personenstamm_zugriff " +
|
||||
" JOIN usergroup u ON personenstamm_zugriff.benutzergruppe_id = u.id " +
|
||||
" JOIN akteur_usergroup au ON u.id = au.usergroup_id " +
|
||||
" JOIN akteur a ON au.akteur_id = a.id " +
|
||||
" JOIN personenstamm p on personenstamm_zugriff.personenstamm_id = p.id " +
|
||||
" WHERE a.login = ? AND a.aktiv AND a.anmelden_moeglich ";
|
||||
|
||||
if (PermissionType.READ_WRITE == permissionType) {
|
||||
sql += " AND personenstamm_zugriff.bearbeiten ";
|
||||
}
|
||||
|
||||
var userDetails = (UserDetails)authentication.getPrincipal();
|
||||
|
||||
return jdbcTemplate
|
||||
.query(sql, new Object[]{userDetails.getUsername()}, (rs, rowNum) -> rs.getString("kennung"));
|
||||
}
|
||||
|
||||
List<String> getFormNamesForPermission(Authentication authentication, PermissionType permissionType) {
|
||||
|
||||
var sql = "SELECT df.name FROM formular_usergroup_zugriff " +
|
||||
" JOIN data_form df ON formular_usergroup_zugriff.formular_id = df.id " +
|
||||
" JOIN usergroup u ON formular_usergroup_zugriff.usergroup_id = u.id " +
|
||||
" JOIN akteur_usergroup au ON u.id = au.usergroup_id " +
|
||||
" JOIN akteur a on au.akteur_id = a.id " +
|
||||
" WHERE a.login = ? AND a.aktiv AND a.anmelden_moeglich ";
|
||||
|
||||
if (PermissionType.READ_WRITE == permissionType) {
|
||||
sql += " AND formular_usergroup_zugriff.bearbeiten ";
|
||||
}
|
||||
|
||||
var userDetails = (UserDetails)authentication.getPrincipal();
|
||||
|
||||
return jdbcTemplate
|
||||
.query(sql, new Object[]{userDetails.getUsername()}, (rs, rowNum) -> rs.getString("name"));
|
||||
}
|
||||
|
||||
}
|
37
src/main/java/dev/dnpm/services/DefaultFormService.java
Normal file
37
src/main/java/dev/dnpm/services/DefaultFormService.java
Normal file
@ -0,0 +1,37 @@
|
||||
package dev.dnpm.services;
|
||||
|
||||
import dev.dnpm.exceptions.FormException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Standardimplementierung zum Ermitteln von Unter- und Hauptformularen
|
||||
*
|
||||
* @since 0.0.2
|
||||
*/
|
||||
public class DefaultFormService implements FormService {
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
|
||||
public DefaultFormService(final DataSource dataSource) {
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMainFormProcedureId(int procedureId) throws FormException {
|
||||
var sql = "SELECT hauptprozedur_id FROM prozedur WHERE id = ?";
|
||||
try {
|
||||
return jdbcTemplate.queryForObject(sql, (resultSet, i) -> resultSet.getInt("hauptprozedur_id"), procedureId);
|
||||
} catch (Exception e) {
|
||||
throw new FormException(String.format("No main form found for subform with ID '%d'", procedureId));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Integer> getSubFormProcedureIds(int procedureId) {
|
||||
var sql = "SELECT id FROM prozedur WHERE hauptprozedur_id = ?";
|
||||
return jdbcTemplate.queryForList(sql, Integer.class, procedureId);
|
||||
}
|
||||
}
|
78
src/main/java/dev/dnpm/services/DefaultStudienService.java
Normal file
78
src/main/java/dev/dnpm/services/DefaultStudienService.java
Normal file
@ -0,0 +1,78 @@
|
||||
package dev.dnpm.services;
|
||||
|
||||
import dev.dnpm.dto.Studie;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Standardimplementierung zum Ermitteln von Studien
|
||||
*
|
||||
* @since 0.0.2
|
||||
*/
|
||||
public class DefaultStudienService implements StudienService {
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
|
||||
public DefaultStudienService(final DataSource dataSource) {
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Studie> findAll() {
|
||||
var sql = "SELECT pcc.name, pcv.version_number, TRIM(studie.studien_nummer) AS studien_nummer, studie.startdatum, studie.endedatum, pcve.code, pcve.shortdesc, pcve.description, studie.aktiv FROM studie "
|
||||
+ "LEFT JOIN category_entry ce ON ce.version_entry_id = studie.property_version_entry "
|
||||
+ "LEFT JOIN property_catalogue_category pcc ON pcc.id = ce.category_id "
|
||||
+ "JOIN property_catalogue_version_entry pcve ON pcve.id = studie.property_version_entry "
|
||||
+ "JOIN property_catalogue_version pcv ON pcv.id = pcve.property_version_id "
|
||||
+ "JOIN property_catalogue pc ON pc.id = pcv.datacatalog_id "
|
||||
+ "WHERE pc.name = 'OS.Studien'"
|
||||
+ "ORDER BY TRIM(studie.studien_nummer)";
|
||||
|
||||
return this.jdbcTemplate.query(sql, (resultSet, i) -> new Studie(
|
||||
resultSet.getString("name"),
|
||||
resultSet.getInt("version_number"),
|
||||
resultSet.getString("code"),
|
||||
resultSet.getString("studien_nummer"),
|
||||
resultSet.getString("shortdesc"),
|
||||
resultSet.getString("description"),
|
||||
resultSet.getBoolean("aktiv")
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Studie> findByQuery(String query) {
|
||||
var sql = "SELECT pcc.name, pcv.version_number, TRIM(studie.studien_nummer) AS studien_nummer, studie.startdatum, studie.endedatum, pcve.code, pcve.shortdesc, pcve.description, studie.aktiv FROM studie "
|
||||
+ "LEFT JOIN category_entry ce ON ce.version_entry_id = studie.property_version_entry "
|
||||
+ "LEFT JOIN property_catalogue_category pcc ON pcc.id = ce.category_id "
|
||||
+ "JOIN property_catalogue_version_entry pcve ON pcve.id = studie.property_version_entry "
|
||||
+ "JOIN property_catalogue_version pcv ON pcv.id = pcve.property_version_id "
|
||||
+ "JOIN property_catalogue pc ON pc.id = pcv.datacatalog_id "
|
||||
+ "WHERE pc.name = 'OS.Studien' AND (pcve.shortdesc LIKE ? OR pcve.description LIKE ? OR studie.studien_nummer LIKE ?)"
|
||||
+ "ORDER BY TRIM(studie.studien_nummer)";
|
||||
|
||||
var like = String.format("%%%s%%", query);
|
||||
|
||||
return this.jdbcTemplate.query(sql, new Object[]{like, like, like}, (resultSet, i) -> new Studie(
|
||||
resultSet.getString("name"),
|
||||
resultSet.getInt("version_number"),
|
||||
resultSet.getString("code"),
|
||||
resultSet.getString("studien_nummer"),
|
||||
resultSet.getString("shortdesc"),
|
||||
resultSet.getString("description"),
|
||||
resultSet.getBoolean("aktiv")
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Studie> findActive() {
|
||||
return findAll().stream().filter(Studie::isActive).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Studie> findActiveByQuery(String query) {
|
||||
return findByQuery(query).stream().filter(Studie::isActive).collect(Collectors.toList());
|
||||
}
|
||||
}
|
51
src/main/java/dev/dnpm/services/FormService.java
Normal file
51
src/main/java/dev/dnpm/services/FormService.java
Normal file
@ -0,0 +1,51 @@
|
||||
package dev.dnpm.services;
|
||||
|
||||
import dev.dnpm.exceptions.FormException;
|
||||
import de.itc.onkostar.api.Procedure;
|
||||
import de.itc.onkostar.api.constants.JaNeinUnbekannt;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface FormService {
|
||||
|
||||
/**
|
||||
* Diese Methode übergibt die Prozedur-ID des zugehörigen Hauptformulars zu einem Unterformular
|
||||
* Siehe auch: <a href="https://github.com/CCC-MF/onkostar-plugin-forminfo/blob/master/src/main/java/de/ukw/ccc/onkostar/forminfo/services/FormInfoService.java">FormInfoService.java</a>
|
||||
*
|
||||
* @param procedureId Die Prozedur-ID des Unterformulars
|
||||
* @return Die Prozedur-ID des zugehörigen Hauptformulars
|
||||
* @throws FormException Wird geworfen, wenn ein Fehler auftrat
|
||||
*/
|
||||
int getMainFormProcedureId(int procedureId) throws FormException;
|
||||
|
||||
/**
|
||||
* Diese Methode übergibt die Prozedur-IDs von Unterformularen zu einem Formular
|
||||
* Siehe auch: <a href="https://github.com/CCC-MF/onkostar-plugin-forminfo/blob/master/src/main/java/de/ukw/ccc/onkostar/forminfo/services/FormInfoService.java">FormInfoService.java</a>
|
||||
*
|
||||
* @param procedureId Die Prozedur-ID des Formulars
|
||||
* @return Eine Liste mit Prozedur-IDs der Unterformulare
|
||||
*/
|
||||
List<Integer> getSubFormProcedureIds(int procedureId);
|
||||
|
||||
/**
|
||||
* Prüft, ob ein Formularfeld in der Prozedur einen Wert hat oder null ist
|
||||
* @param procedure Die zu prüfende Prozedur
|
||||
* @param fieldName Der Formularfeldname
|
||||
* @return Gibt <code>true</code> zurück, wenn das Feld einen Wert hat
|
||||
*/
|
||||
static boolean hasValue(final Procedure procedure, final String fieldName) {
|
||||
return null != procedure.getValue(fieldName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prüft, ob ein Formularfeld mit Ja/Nein/Unbekannt den Wert Ja hat
|
||||
* @param procedure Die zu prüfende Prozedur
|
||||
* @param fieldName Der Formularfeldname
|
||||
* @return Gibt <code>true</code> zurück, wenn das Feld den Wert "Ja" hat
|
||||
*/
|
||||
static boolean isYes(final Procedure procedure, final String fieldName) {
|
||||
return hasValue(procedure, fieldName)
|
||||
&& procedure.getValue(fieldName).getString().equals(JaNeinUnbekannt.JA.getCode());
|
||||
}
|
||||
|
||||
}
|
47
src/main/java/dev/dnpm/services/SettingsService.java
Normal file
47
src/main/java/dev/dnpm/services/SettingsService.java
Normal file
@ -0,0 +1,47 @@
|
||||
package dev.dnpm.services;
|
||||
|
||||
import dev.dnpm.database.SettingsRepository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Implementiert den Dienst zur Ermittlung von Systemeinstellungen
|
||||
*/
|
||||
public class SettingsService {
|
||||
|
||||
private final SettingsRepository settingsRepository;
|
||||
|
||||
public SettingsService(final SettingsRepository settingsRepository) {
|
||||
this.settingsRepository = settingsRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Übergibt ein <code>Optional</code> für die Einstellung mit angegebenen Namen
|
||||
* @param name Name der Einstellung
|
||||
* @return Optional mit Wert der Einstellung oder ein leeres Optional, wenn Einstellung nicht gefunden
|
||||
*/
|
||||
public Optional<String> getSetting(String name) {
|
||||
var sid = settingsRepository.findByName(name);
|
||||
if (null == sid) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return Optional.of(sid.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Übergibt die SID als <code>Optional</code>
|
||||
* @return Optional mit Wert der SID
|
||||
*/
|
||||
public Optional<String> getSID() {
|
||||
return getSetting("SID");
|
||||
}
|
||||
|
||||
/**
|
||||
* Übergibt die Einstellung für <code>mehrere_mtb_in_mtbepisode</code>
|
||||
* @return Übergibt <code>true</code>, wenn <code>mehrere_mtb_in_mtbepisode</code> auf "Ja" gesetzt ist.
|
||||
*/
|
||||
public boolean multipleMtbsInMtbEpisode() {
|
||||
var setting = getSetting("mehrere_mtb_in_mtbepisode");
|
||||
return setting.isPresent() && setting.get().equals("true");
|
||||
}
|
||||
}
|
39
src/main/java/dev/dnpm/services/StudienService.java
Normal file
39
src/main/java/dev/dnpm/services/StudienService.java
Normal file
@ -0,0 +1,39 @@
|
||||
package dev.dnpm.services;
|
||||
|
||||
import dev.dnpm.dto.Studie;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface StudienService {
|
||||
|
||||
/**
|
||||
* Übergibt eine Liste mit allen Studien
|
||||
*
|
||||
* @return Liste mit allen Studien
|
||||
*/
|
||||
List<Studie> findAll();
|
||||
|
||||
/**
|
||||
* Übergibt eine Liste mit Studien, deren (Kurz-)Beschreibung oder Studiennummer den übergebenen Wert enthalten
|
||||
*
|
||||
* @param query Wert der enthalten sein muss
|
||||
* @return Gefilterte Liste mit Studien
|
||||
*/
|
||||
List<Studie> findByQuery(String query);
|
||||
|
||||
/**
|
||||
* Übergibt eine Liste mit aktiven Studien
|
||||
*
|
||||
* @return Liste mit aktiven Studien
|
||||
*/
|
||||
List<Studie> findActive();
|
||||
|
||||
/**
|
||||
* Übergibt eine Liste mit aktiven Studien, deren (Kurz-)Beschreibung oder Studiennummer den übergebenen Wert enthalten
|
||||
*
|
||||
* @param query Wert der enthalten sein muss
|
||||
* @return Gefilterte Liste mit aktiven Studien
|
||||
*/
|
||||
List<Studie> findActiveByQuery(String query);
|
||||
|
||||
}
|
30
src/main/java/dev/dnpm/services/TherapieMitEcogService.java
Normal file
30
src/main/java/dev/dnpm/services/TherapieMitEcogService.java
Normal file
@ -0,0 +1,30 @@
|
||||
package dev.dnpm.services;
|
||||
|
||||
import dev.dnpm.dto.EcogStatusWithDate;
|
||||
import de.itc.onkostar.api.Patient;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Schnittstelle zum Ermitteln von ECOG-Statusinformationen
|
||||
*
|
||||
* @since 0.6.0
|
||||
*/
|
||||
public interface TherapieMitEcogService {
|
||||
|
||||
/**
|
||||
* Ermittelt den letzten bekannten ECOG-Status aus allen Therapieformularen des Patienten
|
||||
* @param patient Der zu verwendende Patient
|
||||
* @return Der ECOG-Status als String oder leeres Optional
|
||||
*/
|
||||
Optional<String> latestEcogStatus(Patient patient);
|
||||
|
||||
/**
|
||||
* Ermittelt jeden bekannten ECOG-Status aus allen Therapieformularen des Patienten
|
||||
* @param patient Der zu verwendende Patient
|
||||
* @return Eine Liste mit Datum und ECOG-Status als String
|
||||
*/
|
||||
List<EcogStatusWithDate> ecogStatus(Patient patient);
|
||||
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package dev.dnpm.services.consent;
|
||||
|
||||
import de.itc.onkostar.api.Procedure;
|
||||
|
||||
/**
|
||||
* Schnittstelle für die Anwendung von Consent-Änderungen
|
||||
*
|
||||
* @since 0.2.0
|
||||
*/
|
||||
public interface ConsentManagerService {
|
||||
|
||||
/**
|
||||
* Wende Consent an, wenn dieses Consent-Formular gespeichert wird
|
||||
* @param procedure Prozedur des Consent-Formulars
|
||||
*/
|
||||
void applyConsent(Procedure procedure);
|
||||
|
||||
/**
|
||||
* Optionale Prüfung, ob die angegebene Prozedur angewendet werden kann.
|
||||
* @param procedure Anzuwendende Prozedur
|
||||
* @return Gibt <code>true</code> zurück, wenn die Prozedur angewendet werden kann.
|
||||
*/
|
||||
default boolean canApply(Procedure procedure) {
|
||||
return null != procedure;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package dev.dnpm.services.consent;
|
||||
|
||||
import de.itc.onkostar.api.IOnkostarApi;
|
||||
|
||||
public class ConsentManagerServiceFactory {
|
||||
|
||||
private final IOnkostarApi onkostarApi;
|
||||
|
||||
public ConsentManagerServiceFactory(
|
||||
final IOnkostarApi onkostarApi
|
||||
) {
|
||||
this.onkostarApi = onkostarApi;
|
||||
}
|
||||
|
||||
public ConsentManagerService currentUsableInstance() {
|
||||
var consentFormName = onkostarApi.getGlobalSetting("consentform");
|
||||
|
||||
switch (consentFormName) {
|
||||
case "Excel-Formular":
|
||||
return new UkwConsentManagerService(this.onkostarApi);
|
||||
case "MR.Consent":
|
||||
return new MrConsentManagerService(this.onkostarApi);
|
||||
default:
|
||||
return procedure -> {};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,126 @@
|
||||
package dev.dnpm.services.consent;
|
||||
|
||||
import dev.dnpm.VerweisVon;
|
||||
import de.itc.onkostar.api.IOnkostarApi;
|
||||
import de.itc.onkostar.api.Item;
|
||||
import de.itc.onkostar.api.Procedure;
|
||||
import org.hibernate.SQLQuery;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.transform.Transformers;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Detailimplementierung für das Formular `MR.Consent`
|
||||
*
|
||||
* @since 0.2.0
|
||||
*/
|
||||
public class MrConsentManagerService implements ConsentManagerService {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
private final IOnkostarApi onkostarApi;
|
||||
|
||||
public MrConsentManagerService(final IOnkostarApi onkostarApi) {
|
||||
this.onkostarApi = onkostarApi;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canApply(Procedure procedure) {
|
||||
return null != procedure && procedure.getFormName().equals("MR.Consent");
|
||||
}
|
||||
|
||||
/**
|
||||
* Wende Consent an, wenn dieses Consent-Formular gespeichert wird
|
||||
*
|
||||
* @param procedure Prozedur des Consent-Formulars
|
||||
*/
|
||||
@Override
|
||||
public void applyConsent(Procedure procedure) {
|
||||
int value = 0;
|
||||
try {
|
||||
SessionFactory sessionFactory = onkostarApi.getSessionFactory();
|
||||
Session session = sessionFactory.getCurrentSession();
|
||||
// geänderte Werte checken
|
||||
String sql1 = "select id, max(timestamp) AS datum from aenderungsprotokoll where entity_id = '" + procedure.getId() + "'";
|
||||
SQLQuery query1 = session.createSQLQuery(sql1)
|
||||
.addScalar("id", StandardBasicTypes.INTEGER)
|
||||
.addScalar("datum", StandardBasicTypes.TIMESTAMP);
|
||||
logger.info("Wert-Check: {}", query1.uniqueResult());
|
||||
|
||||
String sql = "SELECT prozedur.id AS procedure_id, prozedur.data_form_id, data_catalogue.name AS data_catalogue, data_catalogue_entry.name AS data_catalogue_entry, data_form.description AS formname, prozedur.beginndatum AS datum " +
|
||||
"FROM prozedur " +
|
||||
"LEFT JOIN data_form_data_catalogue ON data_form_data_catalogue.data_form_id = prozedur.data_form_id " +
|
||||
"LEFT JOIN data_catalogue_entry ON data_catalogue_entry.data_catalogue_id = data_form_data_catalogue.data_catalogue_id " +
|
||||
"LEFT JOIN data_catalogue ON data_catalogue.id = data_catalogue_entry.data_catalogue_id " +
|
||||
"LEFT JOIN data_form ON data_form.id = prozedur.data_form_id " +
|
||||
"WHERE patient_id = " + procedure.getPatientId() + " " +
|
||||
"AND geloescht = 0 " +
|
||||
"AND data_catalogue_entry.type = 'formReference' " +
|
||||
"GROUP BY prozedur.id, prozedur.data_form_id, data_catalogue.name, data_catalogue_entry.name";
|
||||
|
||||
SQLQuery query = session.createSQLQuery(sql)
|
||||
.addScalar("procedure_id", StandardBasicTypes.INTEGER)
|
||||
.addScalar("data_form_id", StandardBasicTypes.INTEGER)
|
||||
.addScalar("data_catalogue", StandardBasicTypes.STRING)
|
||||
.addScalar("data_catalogue_entry", StandardBasicTypes.STRING)
|
||||
.addScalar("formname", StandardBasicTypes.STRING)
|
||||
.addScalar("datum", StandardBasicTypes.DATE);
|
||||
|
||||
query.setResultTransformer(Transformers.aliasToBean(VerweisVon.class));
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<VerweisVon> result = query.list();
|
||||
|
||||
for (VerweisVon verweisVon : result) {
|
||||
sql = verweisVon.getSQL();
|
||||
query = session.createSQLQuery(sql)
|
||||
.addScalar("value", StandardBasicTypes.INTEGER);
|
||||
if (query.uniqueResult() != null) {
|
||||
value = (Integer) query.uniqueResult();
|
||||
}
|
||||
if (value == procedure.getId()) {
|
||||
saveReferencedProcedure(procedure, verweisVon);
|
||||
value = 0;
|
||||
}
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
logger.error("Sonstiger Fehler bei der Ausführung von analyze()", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void saveReferencedProcedure(Procedure prozedur, VerweisVon verweisVon) {
|
||||
Procedure andereprozedur = onkostarApi.getProcedure(verweisVon.getProcedure_id());
|
||||
try {
|
||||
Map<String, Item> felder = prozedur.getAllValues();
|
||||
for (Map.Entry<String, Item> feld : felder.entrySet()) {
|
||||
if (feld.getKey().startsWith("Consent")) {
|
||||
if (feld.getKey().equals("ConsentStatusEinwilligungDNPM")) {
|
||||
switch (feld.getValue().getValue().toString()) {
|
||||
case "z":
|
||||
andereprozedur.setValue(feld.getKey(), new Item(feld.getKey(), "active"));
|
||||
break;
|
||||
case "a":
|
||||
case "w":
|
||||
andereprozedur.setValue(feld.getKey(), new Item(feld.getKey(), "rejected"));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
andereprozedur.setValue(feld.getKey(), prozedur.getValue(feld.getKey()));
|
||||
}
|
||||
}
|
||||
}
|
||||
onkostarApi.saveProcedure(andereprozedur);
|
||||
} catch (Exception e) {
|
||||
logger.error("Kann Prozedur nicht speichern", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
package dev.dnpm.services.consent;
|
||||
|
||||
import de.itc.onkostar.api.IOnkostarApi;
|
||||
import de.itc.onkostar.api.Item;
|
||||
import de.itc.onkostar.api.Procedure;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* Detailimplementierung für das Formular `Excel-Formular`
|
||||
*
|
||||
* @since 0.2.0
|
||||
*/
|
||||
public class UkwConsentManagerService implements ConsentManagerService {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
private final IOnkostarApi onkostarApi;
|
||||
|
||||
public UkwConsentManagerService(final IOnkostarApi onkostarApi) {
|
||||
this.onkostarApi = onkostarApi;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canApply(Procedure procedure) {
|
||||
return null != procedure && procedure.getFormName().equals("Excel-Formular");
|
||||
}
|
||||
|
||||
/**
|
||||
* Wende Consent an, wenn dieses Consent-Formular gespeichert wird
|
||||
*
|
||||
* @param procedure Prozedur des Consent-Formulars
|
||||
*/
|
||||
@Override
|
||||
public void applyConsent(Procedure procedure) {
|
||||
var refdnpmklinikanamnese = procedure.getValue("refdnpmklinikanamnese").getInt();
|
||||
var dnpmKlinikAnamnese = this.onkostarApi.getProcedure(refdnpmklinikanamnese);
|
||||
|
||||
if (null == dnpmKlinikAnamnese) {
|
||||
return;
|
||||
}
|
||||
|
||||
var consents = procedure.getSubProceduresMap().get("ufdnpmconsent");
|
||||
|
||||
if (null == consents) {
|
||||
return;
|
||||
}
|
||||
|
||||
consents.stream()
|
||||
.max(Comparator.comparing(Procedure::getStartDate))
|
||||
.ifPresent(lastConsent -> {
|
||||
var date = lastConsent.getStartDate();
|
||||
var status = lastConsent.getValue("status");
|
||||
if (null == date || null == status || status.getString().isBlank()) {
|
||||
logger.warn("Kein DNPM-Einwilligungstatus angegeben");
|
||||
return;
|
||||
}
|
||||
|
||||
dnpmKlinikAnamnese.setValue("ConsentStatusEinwilligungDNPM", new Item("Einwilligung", status.getString()));
|
||||
dnpmKlinikAnamnese.setValue("ConsentDatumEinwilligungDNPM", new Item("DatumEinwilligung", date));
|
||||
|
||||
try {
|
||||
onkostarApi.saveProcedure(dnpmKlinikAnamnese, false);
|
||||
} catch (Exception e) {
|
||||
logger.error("Kann DNPM-Einwilligungstatus nicht aktualisieren", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package dev.dnpm.services.molekulargenetik;
|
||||
|
||||
import dev.dnpm.dto.Variant;
|
||||
import de.itc.onkostar.api.Procedure;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Schnittstellenbeschreibung für Methoden zum Formular "OS.Molekulargenetik"
|
||||
*/
|
||||
public interface MolekulargenetikFormService {
|
||||
|
||||
/**
|
||||
* Ermittelt alle (unterstützten) Varianten zur Prozedur eines Formulars "OS.Molekulargenetik"
|
||||
* @param procedure Die Prozedur zum Formular "OS.Molekulargenetik"
|
||||
* @return Die unterstützten Varianten oder eine leere Liste, wenn keine Varianten gefunden wurden.
|
||||
*/
|
||||
List<Variant> getVariants(Procedure procedure);
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package dev.dnpm.services.molekulargenetik;
|
||||
|
||||
import dev.dnpm.dto.Variant;
|
||||
import de.itc.onkostar.api.Procedure;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class OsMolekulargenetikFormService implements MolekulargenetikFormService {
|
||||
|
||||
/**
|
||||
* Ermittelt alle (unterstützten) Varianten zur Prozedur eines Formulars "OS.Molekulargenetik" (oder Variante)
|
||||
* Unterstützte Varianten sind:
|
||||
* <uL>
|
||||
* <li>Einfache Variante
|
||||
* <li>CNV
|
||||
* <li>Fusion
|
||||
* @param procedure Die Prozedur zum Formular "OS.Molekulargenetik" (oder Variante)
|
||||
* @return Die unterstützten Varianten oder eine leere Liste, wenn keine Varianten gefunden wurden.
|
||||
*/
|
||||
@Override
|
||||
public List<Variant> getVariants(Procedure procedure) {
|
||||
if (! procedureWithUsableFormVariant(procedure)) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
var subforms = procedure.getSubProceduresMap().get("MolekulargenetischeUntersuchung");
|
||||
if (null == subforms) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
return subforms.stream()
|
||||
.map(Variant::fromProcedure)
|
||||
.filter(Optional::isPresent)
|
||||
.map(Optional::get)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
}
|
||||
|
||||
private boolean procedureWithUsableFormVariant(Procedure procedure) {
|
||||
return "OS.Molekulargenetik".equals(procedure.getFormName())
|
||||
|| "UKER.Molekulargenetik".equals(procedure.getFormName());
|
||||
}
|
||||
}
|
70
src/main/java/dev/dnpm/services/mtb/DefaultMtbService.java
Normal file
70
src/main/java/dev/dnpm/services/mtb/DefaultMtbService.java
Normal file
@ -0,0 +1,70 @@
|
||||
package dev.dnpm.services.mtb;
|
||||
|
||||
import de.itc.onkostar.api.IOnkostarApi;
|
||||
import de.itc.onkostar.api.Procedure;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Standardimplementierung des MtbService
|
||||
*
|
||||
* @since 0.0.2
|
||||
*/
|
||||
public class DefaultMtbService implements MtbService {
|
||||
|
||||
private final IOnkostarApi onkostarApi;
|
||||
|
||||
public DefaultMtbService(final IOnkostarApi onkostarApi) {
|
||||
this.onkostarApi = onkostarApi;
|
||||
}
|
||||
|
||||
/**
|
||||
* Zusammenfassung der Prozeduren.
|
||||
* Dabei werden alle Prozeduren sortiert, mit ermitteltem Mapper in {@link Optional} eines {@link String}s
|
||||
* gewandelt und, wenn dies erfolgreich war, die Zeichenkette extrahiert.
|
||||
* Im Anschluss wird die Abfolge der Zeichenketten mit den einzelnen Prozedur-Zusammenfassungen in eine
|
||||
* einzige Zusammenfassung zusammengefügt.
|
||||
* @param procedures Prozeduren, die zusammen gefasst werden sollen
|
||||
* @return Text mit Zusammenfassung aller übergebenen Prozeduren
|
||||
*/
|
||||
@Override
|
||||
public String getProtocol(List<Procedure> procedures) {
|
||||
return this.sortedDistinctProcedureProtocolList(procedures.stream())
|
||||
.collect(Collectors.joining("\n\n"));
|
||||
}
|
||||
|
||||
private Stream<String> sortedDistinctProcedureProtocolList(Stream<Procedure> procedures) {
|
||||
return procedures
|
||||
.sorted(Comparator.comparing(Procedure::getStartDate))
|
||||
.map(this::selectAndApplyMapper)
|
||||
.filter(Optional::isPresent)
|
||||
.map(Optional::get)
|
||||
.distinct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Übergibt anzuwendenden Mapper für eine Prozedur.
|
||||
* Wurde keine Implementierung festgelegt, wird ein Mapper zurückgegeben, der eine
|
||||
* Prozedur in ein leeres {@link Optional} zurück gibt, übergeben.
|
||||
* @param procedure Prozedur, für die ein Mapper ermittelt werden soll
|
||||
* @return Mapper für diese Prozedur
|
||||
*/
|
||||
@Override
|
||||
public ProcedureToProtocolMapper procedureToProtocolMapper(Procedure procedure) {
|
||||
switch (procedure.getFormName()) {
|
||||
case "OS.Tumorkonferenz":
|
||||
return new OsTumorkonferenzToProtocolMapper();
|
||||
case "OS.Tumorkonferenz.VarianteUKW":
|
||||
return new OsTumorkonferenzVarianteUkwToProtocolMapper();
|
||||
case "MR.MTB_Anmeldung":
|
||||
return new MrMtbAnmeldungToProtocolMapper(this.onkostarApi);
|
||||
default:
|
||||
return p -> Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package dev.dnpm.services.mtb;
|
||||
|
||||
import de.itc.onkostar.api.IOnkostarApi;
|
||||
import de.itc.onkostar.api.Procedure;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.Optional;
|
||||
|
||||
public class MrMtbAnmeldungToProtocolMapper implements ProcedureToProtocolMapper {
|
||||
|
||||
private final IOnkostarApi onkostarApi;
|
||||
|
||||
public MrMtbAnmeldungToProtocolMapper(final IOnkostarApi onkostarApi) {
|
||||
this.onkostarApi = onkostarApi;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wandelt eine Prozedur mit Formularnamen "MR.MTB_Anmeldung" in ein {@link Optional} mit einer
|
||||
* Zeichenkette oder im Fehlerfall in ein leeres Optional um.
|
||||
*
|
||||
* @param procedure Die Prozedur, für die eine Zusammenfassung ermittelt werden soll.
|
||||
* @return Das {@link Optional} mit, im Erfolgsfall, der Zusammenfassung für die Prozedur.
|
||||
*/
|
||||
@Override
|
||||
public Optional<String> apply(Procedure procedure) {
|
||||
if ((!procedure.getFormName().equals("MR.MTB_Anmeldung"))) {
|
||||
throw new AssertionError("Procedure is not of form type 'MR.MTB_Anmeldung'");
|
||||
}
|
||||
|
||||
var resultParts = new ArrayList<String>();
|
||||
|
||||
var fragestellung = procedure.getValue("Fragestellung");
|
||||
if (null != fragestellung && !fragestellung.getString().isBlank()) {
|
||||
resultParts.add(String.format("Fragestellung:%n%s", fragestellung.getString()));
|
||||
}
|
||||
|
||||
var refEmpfehlung = procedure.getValue("Empfehlung");
|
||||
if (null != refEmpfehlung && refEmpfehlung.getInt() > 0) {
|
||||
var empfehlungsProzedur = onkostarApi.getProcedure(refEmpfehlung.getInt());
|
||||
var refEinzelempfehlungen = onkostarApi.getSubprocedures(empfehlungsProzedur.getId());
|
||||
|
||||
if (null != refEinzelempfehlungen) {
|
||||
refEinzelempfehlungen.stream()
|
||||
.sorted(Comparator.comparingInt(proc -> proc.getValue("Prioritaet").getInt()))
|
||||
.forEach(proc -> {
|
||||
if (proc.getFormName().equals("MR.MTB_Einzelempfehlung")) {
|
||||
var empfehlung = proc.getValue("Empfehlung");
|
||||
if (null != empfehlung && !empfehlung.getString().isBlank()) {
|
||||
resultParts.add(String.format("Empfehlung:%n%s", empfehlung.getString()));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (resultParts.isEmpty()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
return Optional.of(String.join("\n\n", resultParts));
|
||||
}
|
||||
}
|
31
src/main/java/dev/dnpm/services/mtb/MtbService.java
Normal file
31
src/main/java/dev/dnpm/services/mtb/MtbService.java
Normal file
@ -0,0 +1,31 @@
|
||||
package dev.dnpm.services.mtb;
|
||||
|
||||
import de.itc.onkostar.api.Procedure;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface MtbService {
|
||||
/**
|
||||
* Zusammenfassung der Prozeduren
|
||||
* @param procedures Prozeduren, die zusammen gefasst werden sollen
|
||||
* @return Text mit Zusammenfassung der Prozeduren
|
||||
*/
|
||||
String getProtocol(List<Procedure> procedures);
|
||||
|
||||
/**
|
||||
* Übergibt anzuwendenden Mapper für eine Prozedur
|
||||
* @param procedure Prozedur, für die ein Mapper ermittelt werden soll
|
||||
* @return Mapper für diese Prozedur
|
||||
*/
|
||||
ProcedureToProtocolMapper procedureToProtocolMapper(Procedure procedure);
|
||||
|
||||
/**
|
||||
* Select mapper using method {@link #procedureToProtocolMapper(Procedure)} and apply procedure
|
||||
* @param procedure The Procedure to select mapper for and apply
|
||||
* @return {@link Optional} with protocol or empty {@link Optional}
|
||||
*/
|
||||
default Optional<String> selectAndApplyMapper(Procedure procedure) {
|
||||
return this.procedureToProtocolMapper(procedure).apply(procedure);
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package dev.dnpm.services.mtb;
|
||||
|
||||
import de.itc.onkostar.api.Procedure;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
|
||||
/**
|
||||
* Mapper zum Ermitteln des Protokollauszugs für Formular "OS.Tumorkonferenz"
|
||||
*
|
||||
* @since 0.0.2
|
||||
*/
|
||||
public class OsTumorkonferenzToProtocolMapper implements ProcedureToProtocolMapper {
|
||||
|
||||
/**
|
||||
* Wandelt eine Prozedur mit Formularnamen "OS.Tumorkonferenz" in ein {@link Optional} mit einer
|
||||
* Zeichenkette oder im Fehlerfall in ein leeres Optional um.
|
||||
* @param procedure Die Prozedur, für die eine Zusammenfassung ermittelt werden soll.
|
||||
* @return Das {@link Optional} mit, im Erfolgsfall, der Zusammenfassung für die Prozedur.
|
||||
*/
|
||||
@Override
|
||||
public Optional<String> apply(Procedure procedure) {
|
||||
if ((!procedure.getFormName().equals("OS.Tumorkonferenz"))) {
|
||||
throw new AssertionError("Procedure is not of form type 'OS.Tumorkonferenz'");
|
||||
}
|
||||
|
||||
var fragestellung = procedure.getValue("Fragestellung");
|
||||
var empfehlung = procedure.getValue("Empfehlung");
|
||||
|
||||
if (
|
||||
null != fragestellung && !fragestellung.getString().isBlank()
|
||||
&& null != empfehlung && !empfehlung.getString().isBlank()
|
||||
) {
|
||||
return Optional.of(String.format("Fragestellung:%n%s%n%nEmpfehlung:%n%s", fragestellung.getString(), empfehlung.getString()));
|
||||
} else if (null != fragestellung && !fragestellung.getString().isBlank()) {
|
||||
return Optional.of(fragestellung.getString());
|
||||
} else if (null != empfehlung && !empfehlung.getString().isBlank()) {
|
||||
return Optional.of(empfehlung.getString());
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package dev.dnpm.services.mtb;
|
||||
|
||||
import de.itc.onkostar.api.Procedure;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Mapper zum Ermitteln des Protokollauszugs für Formular "OS.Tumorkonferenz.VarianteUKW"
|
||||
*
|
||||
* @since 0.0.2
|
||||
*/
|
||||
public class OsTumorkonferenzVarianteUkwToProtocolMapper implements ProcedureToProtocolMapper {
|
||||
|
||||
/**
|
||||
* Wandelt eine Prozedur mit Formularnamen "OS.Tumorkonferenz.VarianteUKW" in ein {@link Optional} mit einer
|
||||
* Zeichenkette oder im Fehlerfall in ein leeres Optional um.
|
||||
* @param procedure Die Prozedur, für die eine Zusammenfassung ermittelt werden soll.
|
||||
* @return Das {@link Optional} mit, im Erfolgsfall, der Zusammenfassung für die Prozedur.
|
||||
*/
|
||||
@Override
|
||||
public Optional<String> apply(Procedure procedure) {
|
||||
if ((!procedure.getFormName().equals("OS.Tumorkonferenz.VarianteUKW"))) {
|
||||
throw new AssertionError("Procedure is not of form type 'OS.Tumorkonferenz.VarianteUKW'");
|
||||
}
|
||||
|
||||
|
||||
var fragestellung = procedure.getValue("Fragestellung");
|
||||
var empfehlung = procedure.getValue("Empfehlung");
|
||||
|
||||
if (
|
||||
null != fragestellung && !fragestellung.getString().isBlank()
|
||||
&& null != empfehlung && !empfehlung.getString().isBlank()
|
||||
) {
|
||||
return Optional.of(String.format("Fragestellung:%n%s%n%nEmpfehlung:%n%s", fragestellung.getString().trim(), empfehlung.getString().trim()));
|
||||
} else if (null != fragestellung && !fragestellung.getString().isBlank()) {
|
||||
return Optional.of(fragestellung.getString().trim());
|
||||
} else if (null != empfehlung && !empfehlung.getString().isBlank()) {
|
||||
return Optional.of(empfehlung.getString().trim());
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package dev.dnpm.services.mtb;
|
||||
|
||||
import de.itc.onkostar.api.Procedure;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ProcedureToProtocolMapper extends Function<Procedure, Optional<String>> {}
|
@ -0,0 +1,74 @@
|
||||
package dev.dnpm.services.strahlentherapie;
|
||||
|
||||
import dev.dnpm.dto.EcogStatusWithDate;
|
||||
import dev.dnpm.services.SettingsService;
|
||||
import de.itc.onkostar.api.IOnkostarApi;
|
||||
import de.itc.onkostar.api.Patient;
|
||||
import de.itc.onkostar.api.Procedure;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Standardimplementierung des StrahlentherapieServices
|
||||
*
|
||||
* @since 0.6.0
|
||||
*/
|
||||
public class DefaultStrahlentherapieService implements StrahlentherapieService {
|
||||
|
||||
private static final String ECOG_FIELD = "ECOGvorTherapie";
|
||||
|
||||
private final IOnkostarApi onkostarApi;
|
||||
|
||||
private final SettingsService settingsService;
|
||||
|
||||
public DefaultStrahlentherapieService(final IOnkostarApi onkostarApi, final SettingsService settingsService) {
|
||||
this.onkostarApi = onkostarApi;
|
||||
this.settingsService = settingsService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ermittelt den letzten bekannten ECOG-Status aus allen Systemtherapieformularen des Patienten
|
||||
*
|
||||
* @param patient Der zu verwendende Patient
|
||||
* @return Der ECOG-Status als String oder leeres Optional
|
||||
*/
|
||||
@Override
|
||||
public Optional<String> latestEcogStatus(Patient patient) {
|
||||
return ecogStatus(patient).stream()
|
||||
.max(Comparator.comparing(EcogStatusWithDate::getDate))
|
||||
.map(EcogStatusWithDate::getStatus);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ermittelt jeden bekannten ECOG-Status aus allen Systemtherapieformularen des Patienten
|
||||
*
|
||||
* @param patient Der zu verwendende Patient
|
||||
* @return Eine Liste mit Datum und ECOG-Status als String
|
||||
*/
|
||||
@Override
|
||||
public List<EcogStatusWithDate> ecogStatus(Patient patient) {
|
||||
return patient.getDiseases().stream()
|
||||
.flatMap(disease -> onkostarApi.getProceduresForDiseaseByForm(disease.getId(), getFormName()).stream())
|
||||
.filter(procedure -> null != procedure.getStartDate())
|
||||
.sorted(Comparator.comparing(Procedure::getStartDate))
|
||||
.map(procedure -> {
|
||||
try {
|
||||
return new EcogStatusWithDate(procedure.getStartDate(), procedure.getValue(ECOG_FIELD).getString());
|
||||
} catch (IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private String getFormName() {
|
||||
return settingsService
|
||||
.getSetting("strahlentherapieform")
|
||||
.orElse("OS.Strahlentherapie");
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package dev.dnpm.services.strahlentherapie;
|
||||
|
||||
import dev.dnpm.services.TherapieMitEcogService;
|
||||
|
||||
/**
|
||||
* Service für Systemtherapieformulare
|
||||
*
|
||||
* @since 0.6.0
|
||||
*/
|
||||
public interface StrahlentherapieService extends TherapieMitEcogService {}
|
@ -0,0 +1,98 @@
|
||||
package dev.dnpm.services.systemtherapie;
|
||||
|
||||
import dev.dnpm.dto.EcogStatusWithDate;
|
||||
import dev.dnpm.services.SettingsService;
|
||||
import de.itc.onkostar.api.IOnkostarApi;
|
||||
import de.itc.onkostar.api.Patient;
|
||||
import de.itc.onkostar.api.Procedure;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Standardimplementierung des Systemtherapieservices
|
||||
*
|
||||
* @since 0.2.0
|
||||
*/
|
||||
public class DefaultSystemtherapieService implements SystemtherapieService {
|
||||
|
||||
private static final String ECOG_FIELD = "ECOGvorTherapie";
|
||||
|
||||
private final IOnkostarApi onkostarApi;
|
||||
|
||||
private final SettingsService settingsService;
|
||||
|
||||
public DefaultSystemtherapieService(final IOnkostarApi onkostarApi, final SettingsService settingsService) {
|
||||
this.onkostarApi = onkostarApi;
|
||||
this.settingsService = settingsService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ermittelt eine Zusammenfassung der systemischen Therapien für eine Erkrankung
|
||||
*
|
||||
* @param diseaseId Die ID der Erkrankung
|
||||
* @return Zusammenfassung der systemischen Therapien
|
||||
*/
|
||||
@Override
|
||||
public List<Map<String, String>> getSystemischeTherapienFromDiagnose(int diseaseId) {
|
||||
List<Map<String, String>> result = new ArrayList<>();
|
||||
for (Procedure prozedur : onkostarApi.getProceduresForDiseaseByForm(diseaseId, getFormName())) {
|
||||
prozedurToProzedurwerteMapper(prozedur).apply(prozedur).ifPresent(result::add);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Übergibt aktuell immer den Mapper für das Formular "OS.Systemische Therapie",
|
||||
* da beide bekannte Varianten damit gemappt werden können.
|
||||
*
|
||||
* @param procedure Die Prozedur für die ein Mapper erstellt werden soll
|
||||
* @return Der Mapper für die Prozedur
|
||||
*/
|
||||
@Override
|
||||
public ProzedurToProzedurwerteMapper prozedurToProzedurwerteMapper(Procedure procedure) {
|
||||
return new OsSystemischeTherapieToProzedurwerteMapper();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ermittelt den letzten bekannten ECOG-Status aus allen Systemtherapieformularen des Patienten
|
||||
*
|
||||
* @param patient Der zu verwendende Patient
|
||||
* @return Der ECOG-Status als String oder leeres Optional
|
||||
*/
|
||||
@Override
|
||||
public Optional<String> latestEcogStatus(Patient patient) {
|
||||
return ecogStatus(patient).stream()
|
||||
.max(Comparator.comparing(EcogStatusWithDate::getDate))
|
||||
.map(EcogStatusWithDate::getStatus);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ermittelt jeden bekannten ECOG-Status aus allen Systemtherapieformularen des Patienten
|
||||
*
|
||||
* @param patient Der zu verwendende Patient
|
||||
* @return Eine Liste mit Datum und ECOG-Status als String
|
||||
*/
|
||||
@Override
|
||||
public List<EcogStatusWithDate> ecogStatus(Patient patient) {
|
||||
return patient.getDiseases().stream()
|
||||
.flatMap(disease -> onkostarApi.getProceduresForDiseaseByForm(disease.getId(), getFormName()).stream())
|
||||
.filter(procedure -> null != procedure.getStartDate())
|
||||
.sorted(Comparator.comparing(Procedure::getStartDate))
|
||||
.map(procedure -> {
|
||||
try {
|
||||
return new EcogStatusWithDate(procedure.getStartDate(), procedure.getValue(ECOG_FIELD).getString());
|
||||
} catch (IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private String getFormName() {
|
||||
return settingsService
|
||||
.getSetting("systemtherapieform")
|
||||
.orElse("OS.Systemische Therapie");
|
||||
}
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
package dev.dnpm.services.systemtherapie;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.itc.onkostar.api.Item;
|
||||
import de.itc.onkostar.api.Procedure;
|
||||
import de.ukw.ccc.onkostar.atccodes.AtcCode;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Implementierung zum Mappen des Formulars "OS.Systemische Therapie" auf die Prozedurwerte
|
||||
*
|
||||
* @since 0.2.0
|
||||
*/
|
||||
public class OsSystemischeTherapieToProzedurwerteMapper implements ProzedurToProzedurwerteMapper {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(OsSystemischeTherapieToProzedurwerteMapper.class);
|
||||
|
||||
@Override
|
||||
public Optional<Map<String, String>> apply(Procedure procedure) {
|
||||
try {
|
||||
return Optional.of(getProzedurwerte(procedure));
|
||||
} catch (Exception e) {
|
||||
logger.error("Fehler beim Mappen der Prozedur auf Prozedurwerte", e);
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<String, String> getProzedurwerte(Procedure prozedur) {
|
||||
List<String> wirkstoffListe = new ArrayList<>();
|
||||
// SubstanzenCodesListe enthält die Liste der SubstanzenCodes
|
||||
List<Map<String, String>> substanzenCodesListe = new ArrayList<>();
|
||||
|
||||
// alle Werte der Prozedur auslesen
|
||||
Map<String, Item> alleWerte = prozedur.getAllValues();
|
||||
// Prozedurwerte enthält nur die interessanten Werte
|
||||
Map<String, String> prozedurwerte = new HashMap<>();
|
||||
// alle Werte durchgehen und die interessanten übernehmen
|
||||
if (alleWerte.containsKey("Beendigung")) {
|
||||
prozedurwerte.put("Beendigung", alleWerte.get("Beendigung").getValue());
|
||||
}
|
||||
if (alleWerte.containsKey("Ergebnis")) {
|
||||
prozedurwerte.put("Ergebnis", alleWerte.get("Ergebnis").getValue());
|
||||
}
|
||||
if (alleWerte.containsKey("Beginn")) {
|
||||
prozedurwerte.put("Beginn", alleWerte.get("Beginn").getString());
|
||||
}
|
||||
if (alleWerte.containsKey("Ende")) {
|
||||
prozedurwerte.put("Ende", alleWerte.get("Ende").getString());
|
||||
}
|
||||
if (alleWerte.containsKey("SubstanzenList")) {
|
||||
List<Map<String, String>> substanzList = alleWerte.get("SubstanzenList").getValue();
|
||||
for (var substanz : substanzList) {
|
||||
var substanzCodes = getSubstanzCode(substanz);
|
||||
substanzenCodesListe.add(substanzCodes);
|
||||
wirkstoffListe.add(substanzCodes.get("substance"));
|
||||
}
|
||||
}
|
||||
|
||||
prozedurwerte.put("Wirkstoffe", String.join(", ", wirkstoffListe));
|
||||
try {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
prozedurwerte.put("WirkstoffCodes", mapper.writeValueAsString(substanzenCodesListe));
|
||||
} catch (JsonProcessingException e) {
|
||||
logger.error("Kann 'WirkstoffCodes' nicht in JSON-String mappen", e);
|
||||
}
|
||||
|
||||
return prozedurwerte;
|
||||
}
|
||||
|
||||
private static Map<String, String> getSubstanzCode(Map<String, String> substanz) {
|
||||
Map<String, String> substanzCode = new HashMap<>();
|
||||
if (substanz.containsKey("Substanz")) {
|
||||
if (AtcCode.isAtcCode(substanz.get("Substanz"))) {
|
||||
substanzCode.put("system", "ATC");
|
||||
} else {
|
||||
substanzCode.put("system", "other");
|
||||
}
|
||||
substanzCode.put("code", substanz.get("Substanz"));
|
||||
|
||||
}
|
||||
if (substanz.containsKey("Substanz_shortDescription")) {
|
||||
substanzCode.put("substance", substanz.get("Substanz_shortDescription"));
|
||||
}
|
||||
return substanzCode;
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package dev.dnpm.services.systemtherapie;
|
||||
|
||||
import de.itc.onkostar.api.Procedure;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Mapper um ein Systemtherapieformular in eine Optional-Map mit Prozedurwerten umzuwandeln
|
||||
*
|
||||
* @since 0.2.0
|
||||
*/
|
||||
public interface ProzedurToProzedurwerteMapper extends Function<Procedure, Optional<Map<String, String>>> {}
|
@ -0,0 +1,29 @@
|
||||
package dev.dnpm.services.systemtherapie;
|
||||
|
||||
import dev.dnpm.services.TherapieMitEcogService;
|
||||
import de.itc.onkostar.api.Procedure;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Service für Systemtherapieformulare
|
||||
*
|
||||
* @since 0.2.0
|
||||
*/
|
||||
public interface SystemtherapieService extends TherapieMitEcogService {
|
||||
/**
|
||||
* Ermittelt eine Zusammenfassung der systemischen Therapien für eine Erkrankung
|
||||
* @param diseaseId Die ID der Erkrankung
|
||||
* @return Die Zusammenfassung der systemischen Therapien
|
||||
*/
|
||||
List<Map<String, String>> getSystemischeTherapienFromDiagnose(int diseaseId);
|
||||
|
||||
/**
|
||||
* Erstellt den Mapper for die Prozedur
|
||||
* @param procedure Die Prozedur für die ein Mapper erstellt werden soll
|
||||
* @return Der erstellte ProzedurToProzedurwerteMapper
|
||||
*/
|
||||
ProzedurToProzedurwerteMapper prozedurToProzedurwerteMapper(Procedure procedure);
|
||||
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package dev.dnpm.services.therapieplan;
|
||||
|
||||
import dev.dnpm.services.FormService;
|
||||
import de.itc.onkostar.api.IOnkostarApi;
|
||||
import de.itc.onkostar.api.Procedure;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public abstract class AbstractTherapieplanService implements TherapieplanService {
|
||||
|
||||
protected final IOnkostarApi onkostarApi;
|
||||
|
||||
protected final FormService formService;
|
||||
|
||||
protected AbstractTherapieplanService(final IOnkostarApi onkostarApi, final FormService formService) {
|
||||
this.onkostarApi = onkostarApi;
|
||||
this.formService = formService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Procedure> findReferencedFollowUpsForSubform(Procedure procedure) {
|
||||
if (null == procedure || !"DNPM UF Einzelempfehlung".equals(procedure.getFormName())) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
return procedure.getDiseaseIds().stream()
|
||||
.flatMap(diseaseId -> onkostarApi.getProceduresForDiseaseByForm(diseaseId, "DNPM FollowUp").stream())
|
||||
.filter(p -> p.getValue("LinkTherapieempfehlung").getInt() == procedure.getId())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Procedure> findReferencedFollowUpsForSubform(int procedureId) {
|
||||
var procedure = this.onkostarApi.getProcedure(procedureId);
|
||||
if (null == procedure || !"DNPM UF Einzelempfehlung".equals(procedure.getFormName())) {
|
||||
return List.of();
|
||||
}
|
||||
return findReferencedFollowUpsForSubform(procedure);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,196 @@
|
||||
package dev.dnpm.services.therapieplan;
|
||||
|
||||
import dev.dnpm.services.FormService;
|
||||
import de.itc.onkostar.api.IOnkostarApi;
|
||||
import de.itc.onkostar.api.Item;
|
||||
import de.itc.onkostar.api.Procedure;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static dev.dnpm.services.FormService.hasValue;
|
||||
import static dev.dnpm.services.FormService.isYes;
|
||||
|
||||
public class DefaultTherapieplanService extends AbstractTherapieplanService {
|
||||
|
||||
public static final String FORMFIELD_REFERSTEMTB = "referstemtb";
|
||||
public static final String FORMFIELD_HUMANGENBERATUNG = "humangenberatung";
|
||||
public static final String FORMFIELD_REEVALUATION = "reevaluation";
|
||||
public static final String FORMFIELD_DATUM = "datum";
|
||||
public static final String FORMFIELD_REFTKHUMANGENBER = "reftkhumangenber";
|
||||
public static final String FORMFIELD_DATUMTKHUMANGENBER = "datumtkhumangenber";
|
||||
public static final String FORMFIELD_REFTKREEVALUATION = "reftkreevaluation";
|
||||
public static final String FORMFIELD_DATUMTKREEVALUATION = "datumtkreevaluation";
|
||||
public static final String FORMFIELD_MTB = "mtb";
|
||||
public static final String FORMFIELD_UFEEDATUM = "ufeedatum";
|
||||
public static final String FORMFIELD_REFTUMORKONFERENZ = "reftumorkonferenz";
|
||||
public static final String FORMFIELD_UFRBDATUM = "ufrbdatum";
|
||||
|
||||
public static final String DATAFIELD_REF_TK_HUMANGENBER = "ref_tk_humangenber";
|
||||
public static final String DATAFIELD_DATUM_TK_HUMANGENBER = "datum_tk_humangenber";
|
||||
public static final String DATAFIELD_DATUM = "datum";
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
public DefaultTherapieplanService(final IOnkostarApi onkostarApi, final FormService formService) {
|
||||
super(onkostarApi, formService);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verlinke MTB und Übernahme Datum aus Hauptformular in weiteren Bereichen
|
||||
* "Humangenetische Beratung" und "Reevaluation" und Unterformularen, wenn erforderlich.
|
||||
*
|
||||
* @param procedure Die Prozedur mit Hauptformular
|
||||
*/
|
||||
@Override
|
||||
public void updateRequiredMtbEntries(Procedure procedure) {
|
||||
this.updateMtbInSections(procedure);
|
||||
this.updateMtbInSubforms(procedure);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finde verlinkte MTBs in Hauptformular und Unterformularen
|
||||
*
|
||||
* @param procedure Die Prozedur mit Hauptformular
|
||||
* @return Liste mit verlinkten MTBs
|
||||
*/
|
||||
@Override
|
||||
public List<Procedure> findReferencedMtbs(Procedure procedure) {
|
||||
if (!hasValue(procedure, FORMFIELD_REFERSTEMTB)) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
var mtbProcedure = this.onkostarApi.getProcedure(procedure.getValue(FORMFIELD_REFERSTEMTB).getInt());
|
||||
if (null == mtbProcedure) {
|
||||
return List.of();
|
||||
}
|
||||
return List.of(mtbProcedure);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finde verlinkte MTBs in Hauptformular und Unterformularen
|
||||
*
|
||||
* @param procedureId ID der Prozedur mit Hauptformular
|
||||
* @return Liste mit verlinkten MTBs
|
||||
*/
|
||||
@Override
|
||||
public List<Procedure> findReferencedMtbs(int procedureId) {
|
||||
var procedure = this.onkostarApi.getProcedure(procedureId);
|
||||
if (null == procedure) {
|
||||
return List.of();
|
||||
}
|
||||
return findReferencedMtbs(procedure);
|
||||
}
|
||||
|
||||
private void updateMtbInSections(Procedure procedure) {
|
||||
if (!isYes(procedure, FORMFIELD_HUMANGENBERATUNG) && !isYes(procedure, FORMFIELD_REEVALUATION)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var mtbReference = procedure.getValue(FORMFIELD_REFERSTEMTB).getInt();
|
||||
var mtbDate = procedure.getValue(FORMFIELD_DATUM).getDate();
|
||||
var noUpdateRequired = true;
|
||||
|
||||
if (
|
||||
isYes(procedure, FORMFIELD_HUMANGENBERATUNG) && (
|
||||
!hasValue(procedure, FORMFIELD_REFTKHUMANGENBER)
|
||||
|| mtbReference != procedure.getValue(FORMFIELD_REFTKHUMANGENBER).getInt()
|
||||
)
|
||||
) {
|
||||
procedure.setValue(FORMFIELD_REFTKHUMANGENBER, new Item(DATAFIELD_REF_TK_HUMANGENBER, mtbReference));
|
||||
noUpdateRequired = false;
|
||||
}
|
||||
|
||||
if (
|
||||
isYes(procedure, FORMFIELD_HUMANGENBERATUNG) && (
|
||||
!hasValue(procedure, FORMFIELD_DATUMTKHUMANGENBER)
|
||||
|| !mtbDate.equals(procedure.getValue(FORMFIELD_DATUMTKHUMANGENBER).getDate())
|
||||
)
|
||||
) {
|
||||
procedure.setValue(FORMFIELD_DATUMTKHUMANGENBER, new Item(DATAFIELD_DATUM_TK_HUMANGENBER, mtbDate));
|
||||
noUpdateRequired = false;
|
||||
}
|
||||
|
||||
if (
|
||||
isYes(procedure, FORMFIELD_REEVALUATION) && (
|
||||
!hasValue(procedure, FORMFIELD_REFTKREEVALUATION)
|
||||
|| mtbReference != procedure.getValue(FORMFIELD_REFTKREEVALUATION).getInt()
|
||||
)
|
||||
) {
|
||||
procedure.setValue(FORMFIELD_REFTKREEVALUATION, new Item("ref_tk_reevaluation", mtbReference));
|
||||
noUpdateRequired = false;
|
||||
}
|
||||
|
||||
if (
|
||||
isYes(procedure, FORMFIELD_REEVALUATION) && (
|
||||
!hasValue(procedure, FORMFIELD_DATUMTKREEVALUATION)
|
||||
|| !mtbDate.equals(procedure.getValue(FORMFIELD_DATUMTKREEVALUATION).getDate())
|
||||
)
|
||||
) {
|
||||
procedure.setValue(FORMFIELD_DATUMTKREEVALUATION, new Item("datum_tk_reevaluation", mtbDate));
|
||||
noUpdateRequired = false;
|
||||
}
|
||||
|
||||
if (noUpdateRequired) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
onkostarApi.saveProcedure(procedure, false);
|
||||
} catch (Exception e) {
|
||||
logger.error("Formular 'DNPM Therapieplan' konnte nicht aktualisiert werden", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateMtbInSubforms(Procedure procedure) {
|
||||
if (
|
||||
!hasValue(procedure, FORMFIELD_REFERSTEMTB) || !hasValue(procedure, FORMFIELD_DATUM)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
var mtbReference = procedure.getValue(FORMFIELD_REFERSTEMTB).getInt();
|
||||
var mtbDate = procedure.getValue(FORMFIELD_DATUM).getDate();
|
||||
|
||||
formService.getSubFormProcedureIds(procedure.getId()).stream()
|
||||
.map(onkostarApi::getProcedure)
|
||||
.filter(Objects::nonNull)
|
||||
.forEach(subform -> {
|
||||
if (isUsableEinzelempfehlung(subform, mtbReference, mtbDate)) {
|
||||
subform.setValue(FORMFIELD_MTB, new Item("ref_tumorkonferenz", mtbReference));
|
||||
subform.setValue(FORMFIELD_UFEEDATUM, new Item(DATAFIELD_DATUM, mtbDate));
|
||||
|
||||
try {
|
||||
onkostarApi.saveProcedure(subform, false);
|
||||
} catch (Exception e) {
|
||||
logger.error("Formular 'DNPM UF Einzelempfehlung' konnte nicht aktualisiert werden", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (isUsableRebiopsie(subform, mtbReference, mtbDate)) {
|
||||
subform.setValue(FORMFIELD_REFTUMORKONFERENZ, new Item("ref_tumorkonferenz", mtbReference));
|
||||
subform.setValue(FORMFIELD_UFRBDATUM, new Item(DATAFIELD_DATUM, mtbDate));
|
||||
|
||||
try {
|
||||
onkostarApi.saveProcedure(subform, false);
|
||||
} catch (Exception e) {
|
||||
logger.error("Formular 'DNPM UF Rebiopsie' konnte nicht aktualisiert werden", e);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private static boolean isUsableRebiopsie(Procedure subform, int mtbReference, Date mtbDate) {
|
||||
return subform.getFormName().equals("DNPM UF Rebiopsie") && mtbReference != subform.getValue(FORMFIELD_REFTUMORKONFERENZ).getInt() && !mtbDate.equals(subform.getValue(FORMFIELD_UFRBDATUM).getDate());
|
||||
}
|
||||
|
||||
private static boolean isUsableEinzelempfehlung(Procedure subform, int mtbReference, Date mtbDate) {
|
||||
return subform.getFormName().equals("DNPM UF Einzelempfehlung") && mtbReference != subform.getValue(FORMFIELD_MTB).getInt() && !mtbDate.equals(subform.getValue(FORMFIELD_UFEEDATUM).getDate());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
package dev.dnpm.services.therapieplan;
|
||||
|
||||
import dev.dnpm.services.FormService;
|
||||
import de.itc.onkostar.api.IOnkostarApi;
|
||||
import de.itc.onkostar.api.Procedure;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static dev.dnpm.services.FormService.hasValue;
|
||||
import static dev.dnpm.services.FormService.isYes;
|
||||
|
||||
public class MultipleMtbTherapieplanService extends AbstractTherapieplanService {
|
||||
|
||||
public MultipleMtbTherapieplanService(final IOnkostarApi onkostarApi, final FormService formService) {
|
||||
super(onkostarApi, formService);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateRequiredMtbEntries(Procedure procedure) {
|
||||
// No action required
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Procedure> findReferencedMtbs(Procedure procedure) {
|
||||
var procedureIds = new ArrayList<Integer>();
|
||||
|
||||
var mtbReference = procedure.getValue("referstemtb").getInt();
|
||||
procedureIds.add(mtbReference);
|
||||
|
||||
if (isYes(procedure, "humangenberatung") && hasValue(procedure, "reftkhumangenber")) {
|
||||
procedureIds.add(procedure.getValue("reftkhumangenber").getInt());
|
||||
}
|
||||
|
||||
if (isYes(procedure, "reevaluation") && hasValue(procedure, "reftkreevaluation")) {
|
||||
procedureIds.add(procedure.getValue("reftkreevaluation").getInt());
|
||||
}
|
||||
|
||||
formService.getSubFormProcedureIds(procedure.getId()).stream()
|
||||
.map(onkostarApi::getProcedure)
|
||||
.filter(Objects::nonNull)
|
||||
.forEach(subform -> {
|
||||
if (subform.getFormName().equals("DNPM UF Einzelempfehlung")) {
|
||||
procedureIds.add(subform.getValue("mtb").getInt());
|
||||
}
|
||||
|
||||
if (subform.getFormName().equals("DNPM UF Rebiopsie")) {
|
||||
procedureIds.add(subform.getValue("reftumorkonferenz").getInt());
|
||||
}
|
||||
});
|
||||
|
||||
return procedureIds.stream()
|
||||
.distinct()
|
||||
.map(onkostarApi::getProcedure)
|
||||
.filter(Objects::nonNull)
|
||||
.sorted(Comparator.comparing(Procedure::getStartDate))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Procedure> findReferencedMtbs(int procedureId) {
|
||||
var procedure = this.onkostarApi.getProcedure(procedureId);
|
||||
if (null == procedure) {
|
||||
return List.of();
|
||||
}
|
||||
return findReferencedMtbs(procedure);
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package dev.dnpm.services.therapieplan;
|
||||
|
||||
import de.itc.onkostar.api.Procedure;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface TherapieplanService {
|
||||
|
||||
/**
|
||||
* Verlinke MTB und Übernahme Datum aus Hauptformular in weiteren Bereichen
|
||||
* "Humangenetische Beratung" und "Reevaluation" und Unterformularen, wenn erforderlich.
|
||||
*
|
||||
* @param procedure Die Prozedur mit Hauptformular
|
||||
*/
|
||||
void updateRequiredMtbEntries(Procedure procedure);
|
||||
|
||||
/**
|
||||
* Finde verlinkte MTBs in Hauptformular und Unterformularen
|
||||
*
|
||||
* @param procedure Die Prozedur mit Hauptformular
|
||||
* @return Liste mit verlinkten MTBs
|
||||
*/
|
||||
List<Procedure> findReferencedMtbs(Procedure procedure);
|
||||
|
||||
/**
|
||||
* Finde verlinkte MTBs in Hauptformular und Unterformularen
|
||||
*
|
||||
* @param procedureId ID der Prozedur mit Hauptformular
|
||||
* @return Liste mit verlinkten MTBs
|
||||
*/
|
||||
List<Procedure> findReferencedMtbs(int procedureId);
|
||||
|
||||
/**
|
||||
* Finde verlinkte FollowUps für DNPM UF Einzelempfehlung
|
||||
*
|
||||
* @param procedure Die DNPM UF Einzelempfehlung Prozedur
|
||||
* @return Liste mit verlinkten FollowUps
|
||||
*/
|
||||
List<Procedure> findReferencedFollowUpsForSubform(Procedure procedure);
|
||||
|
||||
/**
|
||||
* Finde verlinkte FollowUps für DNPM UF Einzelempfehlung
|
||||
*
|
||||
* @param procedureId ID der Prozedur
|
||||
* @return Liste mit verlinkten FollowUps
|
||||
*/
|
||||
List<Procedure> findReferencedFollowUpsForSubform(int procedureId);
|
||||
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package dev.dnpm.services.therapieplan;
|
||||
|
||||
import dev.dnpm.services.FormService;
|
||||
import dev.dnpm.services.SettingsService;
|
||||
import de.itc.onkostar.api.IOnkostarApi;
|
||||
|
||||
public class TherapieplanServiceFactory {
|
||||
|
||||
private final IOnkostarApi onkostarApi;
|
||||
|
||||
private final SettingsService settingsService;
|
||||
|
||||
private final FormService formService;
|
||||
|
||||
public TherapieplanServiceFactory(
|
||||
final IOnkostarApi onkostarApi,
|
||||
final SettingsService settingsService,
|
||||
final FormService formService
|
||||
) {
|
||||
this.onkostarApi = onkostarApi;
|
||||
this.settingsService = settingsService;
|
||||
this.formService = formService;
|
||||
}
|
||||
|
||||
public TherapieplanService currentUsableInstance() {
|
||||
if (settingsService.multipleMtbsInMtbEpisode()) {
|
||||
return new MultipleMtbTherapieplanService(onkostarApi, formService);
|
||||
}
|
||||
|
||||
return new DefaultTherapieplanService(onkostarApi, formService);
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user