Im Rahmen der Veranstaltung "CS3330 - Projektpraktikum MedizinischeInformatik" an der Universität zu Lübeck entstandenes Krankenhausinformationssystem (KIS).
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

306 行
13 KiB

  1. package de.uniluebeck.mi.projmi6.hapi;
  2. import ca.uhn.hl7v2.AcknowledgmentCode;
  3. import ca.uhn.hl7v2.ErrorCode;
  4. import ca.uhn.hl7v2.HL7Exception;
  5. import ca.uhn.hl7v2.model.AbstractMessage;
  6. import ca.uhn.hl7v2.model.Message;
  7. import ca.uhn.hl7v2.model.v251.group.BAR_P05_PROCEDURE;
  8. import ca.uhn.hl7v2.model.v251.group.BAR_P05_VISIT;
  9. import ca.uhn.hl7v2.model.v251.message.ADT_A01;
  10. import ca.uhn.hl7v2.model.v251.message.BAR_P05;
  11. import ca.uhn.hl7v2.model.v251.segment.*;
  12. import ca.uhn.hl7v2.protocol.ReceivingApplication;
  13. import ca.uhn.hl7v2.protocol.ReceivingApplicationException;
  14. import de.uniluebeck.mi.projmi6.controller.MainController;
  15. import de.uniluebeck.mi.projmi6.db.DBHandler;
  16. import de.uniluebeck.mi.projmi6.model.*;
  17. import javafx.application.Platform;
  18. import java.io.IOException;
  19. import java.sql.SQLException;
  20. import java.time.LocalDateTime;
  21. import java.util.ArrayList;
  22. import java.util.List;
  23. import java.util.Map;
  24. /**
  25. * Manages all HL7 receiving tasks
  26. *
  27. * @param <T>
  28. */
  29. public class HL7Receiver<T extends AbstractMessage> implements ReceivingApplication {
  30. private final Class<T> type;
  31. private final MainController mainctrl;
  32. public HL7Receiver(Class<T> type, MainController mainctrl) {
  33. this.type = type;
  34. this.mainctrl = mainctrl;
  35. }
  36. @Override
  37. public Message processMessage(Message message, Map<String, Object> metadata) throws ReceivingApplicationException, HL7Exception {
  38. if (type == ADT_A01.class) {
  39. return processADT_A01(message, metadata);
  40. }
  41. if (type == BAR_P05.class) {
  42. return processBAR_P05(message, metadata);
  43. }
  44. // TODO: Handle unknown Messages, maybe write to database, send ACK and go on.
  45. try {
  46. return message.generateACK();
  47. } catch (IOException e) {
  48. throw new HL7Exception(e);
  49. }
  50. }
  51. @Override
  52. public boolean canProcess(Message message) {
  53. return type.isInstance(message);
  54. }
  55. /**
  56. * generates an ACK of received message, throws Exception otherwise
  57. *
  58. * @param message to generate ACK
  59. * @return ACK of message
  60. * @throws HL7Exception
  61. */
  62. private Message generateACK(Message message) throws HL7Exception {
  63. try {
  64. return message.generateACK();
  65. } catch (IOException e) {
  66. throw new HL7Exception(e);
  67. }
  68. }
  69. /**
  70. * generates an ACK with error code and log
  71. *
  72. * @param message to generate ACK
  73. * @param s error string
  74. * @return ACK with error code
  75. * @throws HL7Exception
  76. */
  77. private Message generateACKWithAR(Message message, String s) throws HL7Exception {
  78. try {
  79. Message returnMessage = message.generateACK(AcknowledgmentCode.AR, new HL7Exception(s, ErrorCode.UNKNOWN_KEY_IDENTIFIER));
  80. HL7LogEntry entry = new HL7LogEntry();
  81. entry.setMessage(returnMessage.encode());
  82. entry.setSource("127.0.0.1:1234"); // TODO: Naja...
  83. entry.setTimestamp(LocalDateTime.now());
  84. entry.setDirection(HL7LogEntry.Direction.OUT);
  85. HL7Utils.logHL7MessageToDatabase(entry);
  86. return returnMessage;
  87. } catch (IOException e) {
  88. throw new HL7Exception(e);
  89. }
  90. }
  91. /**
  92. * encodes incoming message and save changes in database
  93. *
  94. * @param message received
  95. * @param metadata //TODO
  96. * @return ACK of message
  97. * @throws HL7Exception
  98. */
  99. private Message processBAR_P05(Message message, Map<String, Object> metadata) throws HL7Exception {
  100. BAR_P05 bar_p05 = (BAR_P05) message;
  101. MSH msh = bar_p05.getMSH();
  102. PID pid = bar_p05.getPID();
  103. //get patient of the message
  104. int patid = Integer.parseInt(pid.getPatientID().encode());
  105. Patient patient = mainctrl.getStammdaten().getPatienten().stream().filter(p -> p.getPatID() == patid).findFirst().orElse(null);
  106. //error by unknown patient
  107. if (patient == null) {
  108. HL7Utils.logInHL7MessageToDatabase(message, msh, metadata);
  109. updateUI(new HL7Message(null, -1, LocalDateTime.now(), "Patient nicht gefunden.", true));
  110. return generateACKWithAR(message, "Patient nicht gefunden.");
  111. }
  112. List<BAR_P05_VISIT> visits = bar_p05.getVISITAll();
  113. List<Integer> updatedFallIDs = new ArrayList<>();
  114. for (BAR_P05_VISIT visit : visits) {
  115. //get current fall
  116. PV1 pv1 = visit.getPV1();
  117. int fallid = Integer.parseInt(pv1.getVisitNumber().getIDNumber().encode());
  118. List<Integer> fallids = new ArrayList<>();
  119. try {
  120. fallids = DBHandler.getAlleFallIdsByPatID(patient.getPatID());
  121. } catch (SQLException e) {
  122. e.printStackTrace();
  123. }
  124. //log error by unknown fall
  125. if (fallids.isEmpty() || !fallids.contains(fallid)) {
  126. HL7Utils.logInHL7MessageToDatabase(message, msh, metadata);
  127. updateUI(new HL7Message(patient, -1, LocalDateTime.now(), "Fall nicht gefunden.?", true));
  128. return generateACKWithAR(message, "Fall nicht gefunden.");
  129. }
  130. Fall fall = new Fall();
  131. fall.setFallID(fallid);
  132. fall.setPatient(patient);
  133. List<Diagnose> diagnosen = new ArrayList<>();
  134. List<Untersuchung> untersuchungen = new ArrayList<>();
  135. // Station(PV1-3-1), Fachabteilung(PV1-3-4), Aufnahmedatum(PV1-44), Entlassungsdatum(PV1-45), Fallnummer(PV1-19)
  136. String stat = pv1.getAssignedPatientLocation().getPointOfCare().encode();
  137. Station station = mainctrl.getStammdaten().getStationen().stream().filter(s -> s.getStation().equals(stat)).findFirst().orElse(null);
  138. //TODO ATTENTION wrong abteilungen may write down here
  139. //error message when station not exists
  140. if (station == null) {
  141. HL7Utils.logInHL7MessageToDatabase(message, msh, metadata);
  142. updateUI(new HL7Message(patient, -1, LocalDateTime.now(), "Station nicht gefunden.", true));
  143. return generateACKWithAR(message, "Station nicht gefunden.");
  144. }
  145. StationsHistorie hist = new StationsHistorie();
  146. hist.setStationKey(station.getStation());
  147. if (pv1.getAdmitDateTime().isEmpty()) {
  148. HL7Utils.logInHL7MessageToDatabase(message, msh, metadata);
  149. updateUI(new HL7Message(patient, -1, LocalDateTime.now(), "Visit ohne Aufnahmedatum.", true));
  150. return generateACKWithAR(message, "Visit ohne Aufnahmedatum.");
  151. }
  152. hist.setAufnahmeDatum(HL7Utils.parseLocalDateTime(pv1.getAdmitDateTime().getTime()));
  153. if (pv1.getDischargeDateTime().length >= 1) {
  154. hist.setEntlassungsDatum(HL7Utils.parseLocalDateTime(pv1.getDischargeDateTime()[0].getTime()));
  155. }
  156. hist.setFallID(fallid);
  157. //diagnosis
  158. List<DG1> dg1s = visit.getDG1All();
  159. for (DG1 dg1 : dg1s) {
  160. Diagnose diagnose = new Diagnose();
  161. //default value by OPS ersteller and bearbeiter
  162. diagnose.setErsteller(99999);
  163. diagnose.setBearbeiter(99999);
  164. diagnose.setFall(fall);
  165. String icd10 = dg1.getDiagnosisCodeDG1().getIdentifier().encode();
  166. Icd10Code icd10code = mainctrl.getStammdaten().getIcd10Codes().stream().filter(i -> i.getCode().equals(icd10)).findFirst().orElse(null);
  167. if (icd10code == null) {
  168. // TODO: Oder einfach ueberspringen?
  169. continue;
  170. // TODO: Behandeln von sonder Codes. K35.9V (Verdacht...)
  171. // logInHL7MessageToDatabase(message, msh, metadata);
  172. // updateUI(new HL7Message(patient, -1, LocalDateTime.now(), "ICD10 Code nicht gefunden.", true));
  173. // return generateACKWithAR(message, "ICD10 Code nicht gefunden.");
  174. }
  175. diagnose.setIcd10code(icd10code);
  176. // Mitarbeiter ID anhand von EinweisenderArzt erkennen.
  177. Mitarbeiter mitarbeiter;
  178. if (dg1.getDiagnosingClinician().length != 0) {
  179. String einweisenderarzt = dg1.getDiagnosingClinician(0).encode(); // Wir holen uns immer den ersten der verantwortlichen Aerzte... // (DG1-16)
  180. mitarbeiter = mainctrl.getStammdaten().getMitarbeiter().stream().filter(m -> m.getEinweisenderArzt().equals(einweisenderarzt)).findFirst().orElse(null);
  181. if (mitarbeiter == null) {
  182. HL7Utils.logInHL7MessageToDatabase(message, msh, metadata);
  183. updateUI(new HL7Message(patient, -1, LocalDateTime.now(), "Mitarbeiter nicht gefunden.", true));
  184. return generateACKWithAR(message, "Mitarbeiter nicht gefunden.");
  185. }
  186. } else {
  187. mitarbeiter = new Mitarbeiter(99999);
  188. }
  189. diagnose.setArzt(mitarbeiter);
  190. // (DG1-6) // TODO: Enum umstellen? Neeee...
  191. String diagart = dg1.getDiagnosisType().encode();
  192. diagnose.setDiagID(DiagArt.parseString(diagart).id());
  193. diagnose.setFreiText(dg1.getDiagnosisDescription().encode());
  194. diagnosen.add(diagnose);
  195. }
  196. List<BAR_P05_PROCEDURE> procedures = visit.getPROCEDUREAll();
  197. for (BAR_P05_PROCEDURE procedure : procedures) {
  198. PR1 pr1 = procedure.getPR1();
  199. Untersuchung untersuchung = new Untersuchung();
  200. untersuchung.setErsteller(99999);
  201. untersuchung.setBearbeiter(99999);
  202. untersuchung.setFall(fall);
  203. String ops = pr1.getProcedureCode().encode();
  204. OpsCode opscode = mainctrl.getStammdaten().getOpsCodes().stream().filter(o -> o.getOpsCode().equals(ops)).findFirst().orElse(null);
  205. if (opscode == null) {
  206. // TODO: Oder einfach ueberspringen?
  207. continue;
  208. // TODO: Behandeln von sonder Codes.
  209. // logInHL7MessageToDatabase(message, msh, metadata);
  210. // updateUI(new HL7Message(patient, -1, LocalDateTime.now(), "OPS Code nicht gefunden.", true));
  211. // return generateACKWithAR(message, "OPS Code nicht gefunden.");
  212. }
  213. untersuchung.setOpscode(opscode);
  214. untersuchung.setUntersuchungsdatum(HL7Utils.parseLocalDateTime(pr1.getProcedureDateTime().getTime()));
  215. // Mitarbeiter ID anhand von EinweisenderArzt erkennen.
  216. Mitarbeiter mitarbeiter;
  217. if (pr1.getProcedurePractitioner().length != 0) {
  218. String einweisenderarzt = pr1.getProcedurePractitioner(0).encode(); // Wir holen uns immer den ersten der verantwortlichen Aerzte...
  219. mitarbeiter = mainctrl.getStammdaten().getMitarbeiter().stream().filter(m -> m.getEinweisenderArzt().equals(einweisenderarzt)).findFirst().orElse(null);
  220. if (mitarbeiter == null) {
  221. HL7Utils.logInHL7MessageToDatabase(message, msh, metadata);
  222. updateUI(new HL7Message(patient, -1, LocalDateTime.now(), "Mitarbeiter nicht gefunden.", true));
  223. return generateACKWithAR(message, "Mitarbeiter nicht gefunden.");
  224. }
  225. } else {
  226. mitarbeiter = new Mitarbeiter(99999);
  227. }
  228. untersuchung.setDurchfuehrenderArzt(mitarbeiter);
  229. untersuchungen.add(untersuchung);
  230. }
  231. // Hier jeweils Untersuchung und Diagnose in die Datenbank schreiben.
  232. diagnosen.forEach(d -> {
  233. try {
  234. DBHandler.setDiagnose(d);
  235. } catch (SQLException e) {
  236. e.printStackTrace();
  237. }
  238. });
  239. untersuchungen.forEach(u -> {
  240. try {
  241. DBHandler.setUntersuchung(u, 99999, false);
  242. } catch (SQLException e) {
  243. e.printStackTrace();
  244. }
  245. });
  246. try {
  247. // TODO: keine Updates moeglich, man muesste dazu viel implementieren.
  248. DBHandler.setStationsHistorie(hist, false);
  249. } catch (SQLException e) {
  250. e.printStackTrace();
  251. }
  252. // Remember welche Faelle geaendert wurden
  253. updatedFallIDs.add(fallid);
  254. }
  255. // HL7 Nachricht loggen.
  256. HL7Utils.logInHL7MessageToDatabase(message, msh, metadata);
  257. updatedFallIDs.forEach(id -> updateUI(new HL7Message(patient, id, LocalDateTime.now(), "", false)));
  258. return generateACK(message);
  259. }
  260. private Message processADT_A01(Message message, Map<String, Object> metadata) throws HL7Exception {
  261. return generateACK(message);
  262. }
  263. private void updateUI(HL7Message hl7message) {
  264. Platform.runLater(() -> mainctrl.getMessageController().addMessage(hl7message));
  265. }
  266. }