From 981d8808d2aa997024fef45c7186b637f85c4ebd Mon Sep 17 00:00:00 2001 From: Nils Dittberner Date: Sat, 21 Nov 2015 00:15:37 +0100 Subject: [PATCH] HL7Server mittels HAPI implementiert und BAR_P05 Nachricht eingelesen. --- pom.xml | 12 +- .../mi/projmi6/hapi2/HL7ConnectionListener2.java | 20 +++ .../mi/projmi6/hapi2/HL7ExceptionHandler2.java | 16 +++ .../uniluebeck/mi/projmi6/hapi2/HL7Recever2.java | 150 +++++++++++++++++++++ .../de/uniluebeck/mi/projmi6/hapi2/HL7Server2.java | 62 +++++++++ .../de/uniluebeck/mi/projmi6/hapi2/HL7Util2.java | 33 +++++ src/main/resources/log4j.properties | 8 ++ 7 files changed, 300 insertions(+), 1 deletion(-) create mode 100644 src/main/java/de/uniluebeck/mi/projmi6/hapi2/HL7ConnectionListener2.java create mode 100644 src/main/java/de/uniluebeck/mi/projmi6/hapi2/HL7ExceptionHandler2.java create mode 100644 src/main/java/de/uniluebeck/mi/projmi6/hapi2/HL7Recever2.java create mode 100644 src/main/java/de/uniluebeck/mi/projmi6/hapi2/HL7Server2.java create mode 100644 src/main/java/de/uniluebeck/mi/projmi6/hapi2/HL7Util2.java create mode 100644 src/main/resources/log4j.properties diff --git a/pom.xml b/pom.xml index b8b8785..0a4031c 100644 --- a/pom.xml +++ b/pom.xml @@ -1,4 +1,4 @@ - 4.0.0 imi @@ -67,5 +67,15 @@ hapi-structures-v251 2.2 + + org.slf4j + slf4j-log4j12 + 1.6.6 + + + log4j + log4j + 1.2.17 + \ No newline at end of file diff --git a/src/main/java/de/uniluebeck/mi/projmi6/hapi2/HL7ConnectionListener2.java b/src/main/java/de/uniluebeck/mi/projmi6/hapi2/HL7ConnectionListener2.java new file mode 100644 index 0000000..a0dbac6 --- /dev/null +++ b/src/main/java/de/uniluebeck/mi/projmi6/hapi2/HL7ConnectionListener2.java @@ -0,0 +1,20 @@ +package de.uniluebeck.mi.projmi6.hapi2; + +import ca.uhn.hl7v2.app.Connection; +import ca.uhn.hl7v2.app.ConnectionListener; + +/** + * Created by nils on 20.11.2015. + */ +class HL7ConnectionListener2 implements ConnectionListener { + + @Override + public void connectionReceived(Connection c) { + // System.out.println("New connection: " + c.getRemoteAddress().toString()); + } + + @Override + public void connectionDiscarded(Connection c) { + // System.out.println("Lost connection: " + c.getRemoteAddress().toString()); + } +} diff --git a/src/main/java/de/uniluebeck/mi/projmi6/hapi2/HL7ExceptionHandler2.java b/src/main/java/de/uniluebeck/mi/projmi6/hapi2/HL7ExceptionHandler2.java new file mode 100644 index 0000000..b746016 --- /dev/null +++ b/src/main/java/de/uniluebeck/mi/projmi6/hapi2/HL7ExceptionHandler2.java @@ -0,0 +1,16 @@ +package de.uniluebeck.mi.projmi6.hapi2; + +import ca.uhn.hl7v2.HL7Exception; +import ca.uhn.hl7v2.protocol.ReceivingApplicationExceptionHandler; + +import java.util.Map; + +/** + * Created by nils on 20.11.2015. + */ +public class HL7ExceptionHandler2 implements ReceivingApplicationExceptionHandler { + @Override + public String processException(String incomingMessage, Map incomingMetadata, String outgoingMessage, Exception e) throws HL7Exception { + return outgoingMessage; + } +} diff --git a/src/main/java/de/uniluebeck/mi/projmi6/hapi2/HL7Recever2.java b/src/main/java/de/uniluebeck/mi/projmi6/hapi2/HL7Recever2.java new file mode 100644 index 0000000..0312971 --- /dev/null +++ b/src/main/java/de/uniluebeck/mi/projmi6/hapi2/HL7Recever2.java @@ -0,0 +1,150 @@ +package de.uniluebeck.mi.projmi6.hapi2; + +import ca.uhn.hl7v2.HL7Exception; +import ca.uhn.hl7v2.model.AbstractMessage; +import ca.uhn.hl7v2.model.Message; +import ca.uhn.hl7v2.model.v251.group.BAR_P05_PROCEDURE; +import ca.uhn.hl7v2.model.v251.group.BAR_P05_VISIT; +import ca.uhn.hl7v2.model.v251.message.ADT_A01; +import ca.uhn.hl7v2.model.v251.message.BAR_P05; +import ca.uhn.hl7v2.model.v251.segment.*; +import ca.uhn.hl7v2.protocol.ReceivingApplication; +import ca.uhn.hl7v2.protocol.ReceivingApplicationException; +import de.uniluebeck.mi.projmi6.model.*; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Created by nils on 20.11.2015. + */ +public class HL7Recever2 implements ReceivingApplication { + private final Class type; + + public HL7Recever2(Class type) { + this.type = type; + } + + + @Override + public Message processMessage(Message message, Map metadata) throws ReceivingApplicationException, HL7Exception { + + if (type == ADT_A01.class) { + return processADT_A01(message, metadata); + } + if (type == BAR_P05.class) { + return processBAR_P05(message, metadata); + } + + // TODO: Handle unknown Messages, maybe write to database, sen ACK and go on. + try { + return message.generateACK(); + } catch (IOException e) { + throw new HL7Exception(e); + } + } + + @Override + public boolean canProcess(Message message) { + // TODO: Erstmal alles processen. + return true; + } + + private Message generateACK(Message message) throws HL7Exception { + try { + return message.generateACK(); + } catch (IOException e) { + throw new HL7Exception(e); + } + } + + private Message processBAR_P05(Message message, Map metadata) throws HL7Exception { + Patient patient = new Patient(); + List faelle = new ArrayList<>(); + List ALLE_UNTERSUCHUNGEN = new ArrayList<>(); + List ALLE_DIAGNOSEN = new ArrayList<>(); + + BAR_P05 bar_p05 = (BAR_P05) message; + + MSH msh = bar_p05.getMSH(); + PID pid = bar_p05.getPID(); + + patient.setPatID(Integer.parseInt(pid.getPatientID().encode())); + + List visits = bar_p05.getVISITAll(); + + // Ab hier wird es dirty. + for (BAR_P05_VISIT visit : visits) { + + Fall fall = new Fall(); + fall.setPatient(patient); + + List diagnosen = new ArrayList<>(); + List untersuchungen = new ArrayList<>(); + + PV1 pv1 = visit.getPV1(); + // TODO: Extract Station(PV1-3-1),Fachabteilung(PV1-3-4),Aufnahmedatum(PV1-44),Entlassungsdatum(PV1-45),Fallnummer(PV1-19) + Station station = new Station(); + station.setStation(pv1.getAssignedPatientLocation().getPointOfCare().encode()); + station.setAbteilung(pv1.getAssignedPatientLocation().getFacility().encode()); + StationsHistorie hist = new StationsHistorie(); + hist.setStationKey(station.getStation()); + hist.setAufnahmeDatum(HL7Util2.parseLocalDateTime(pv1.getAdmitDateTime().getTime())); + hist.setEntlassungsDatum(HL7Util2.parseLocalDateTime(pv1.getDischargeDateTime()[0].getTime())); + fall.setFallID(Integer.parseInt(pv1.getVisitNumber().encode())); + + List dg1s = visit.getDG1All(); + for (DG1 dg1 : dg1s) { + Icd10Code icd10code = new Icd10Code(dg1.getDiagnosisCodeDG1().getIdentifier().encode(), "", 20); // TODO: Version hard gecoded. + // TODO: Mitarbeiter ID anhand von EinweisenderArzt erkennen! + String einweisenderarzt = dg1.getDiagnosingClinician(0).encode(); // TODO: Wir holen uns immer den ersten der verantwortlichen Aerzte... + int mitarbid = 1000; // TODO: SQL: SELECT * FROM Mitarbeiter WHERE einweisenderarzt = ... + Mitarbeiter mitarbeiter = new Mitarbeiter(mitarbid); + + Diagnose diagnose = new Diagnose(); + diagnose.setIcd10code(icd10code); + diagnose.setArzt(mitarbeiter); // TODO: (DG1-16) + diagnose.setFall(fall); + // diagnose.setDiagArt(); // TODO: (DG1-6) // Enum umstellen???? + + diagnosen.add(diagnose); + } + List procedures = visit.getPROCEDUREAll(); + for (BAR_P05_PROCEDURE procedure : procedures) { + PR1 pr1 = procedure.getPR1(); + Untersuchung untersuchung = new Untersuchung(); + untersuchung.setFall(fall); + + OpsCode opscode = new OpsCode(pr1.getProcedureCode().encode(), "", 20); // TODO: Version hardcoded... + untersuchung.setOpscode(opscode); + untersuchung.setUntersuchungsdatum(HL7Util2.parseLocalDateTime(pr1.getProcedureDateTime().getTime())); + + String einweisenderarzt = pr1.getPr112_ProcedurePractitioner(0).encode(); // TODO: Wieder nur den ersten Arzt.. + int mitarbid = 1000; // TODO: Siehe oben + untersuchung.setDurchfuehrenderArzt(new Mitarbeiter(mitarbid)); + + // TODO: Extract OPS(3), Zeitpunkt(5), Arzt(12) + + untersuchungen.add(untersuchung); + } + + // TODO: hier jeweils Fall, Untersuchung und Diagnosen in die Datenbank schreiben... + faelle.add(fall); + ALLE_DIAGNOSEN.addAll(diagnosen); + ALLE_UNTERSUCHUNGEN.addAll(untersuchungen); + } + + return generateACK(message); + } + + + private Message processADT_A01(Message message, Map metadata) throws HL7Exception { + ADT_A01 adt_a01 = (ADT_A01) message; + System.out.println(adt_a01.toString()); + + return generateACK(message); + } + +} diff --git a/src/main/java/de/uniluebeck/mi/projmi6/hapi2/HL7Server2.java b/src/main/java/de/uniluebeck/mi/projmi6/hapi2/HL7Server2.java new file mode 100644 index 0000000..f302d4e --- /dev/null +++ b/src/main/java/de/uniluebeck/mi/projmi6/hapi2/HL7Server2.java @@ -0,0 +1,62 @@ +package de.uniluebeck.mi.projmi6.hapi2; + +import ca.uhn.hl7v2.DefaultHapiContext; +import ca.uhn.hl7v2.HapiContext; +import ca.uhn.hl7v2.app.HL7Service; +import ca.uhn.hl7v2.model.v251.message.ADT_A01; +import ca.uhn.hl7v2.model.v251.message.BAR_P05; + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +/** + * Created by nils on 20.11.2015. + */ +public class HL7Server2 { + + private static final int PORT = 1111; + private final HapiContext context; + private final HL7Service server; + private final ThreadPoolExecutor executor; + + public HL7Server2() throws InterruptedException { + executor = new ThreadPoolExecutor(10, 100, 30, TimeUnit.SECONDS, new ArrayBlockingQueue(100)); + executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); + + context = new DefaultHapiContext(); + context.setExecutorService(executor); + server = context.newServer(PORT, false); + + server.registerApplication("ADT", "A01", new HL7Recever2(ADT_A01.class)); + server.registerApplication("BAR", "P05", new HL7Recever2(BAR_P05.class)); + + server.registerConnectionListener(new HL7ConnectionListener2()); + server.setExceptionHandler(new HL7ExceptionHandler2()); + + //server.startAndWait(); + server.start(); + } + + // TODO: Remove, for testing purpose only! + public static void main(String[] args) throws InterruptedException { + HL7Server2 srv = new HL7Server2(); + for (; ; ) { + + } + //srv.stop(); + //srv.shutdown(); + } + + public void stop() { + if (server != null && server.isRunning()) { + server.stop(); + } + } + + public void shutdown() { + if (executor != null && !executor.isTerminated()) { + executor.shutdown(); + } + } +} diff --git a/src/main/java/de/uniluebeck/mi/projmi6/hapi2/HL7Util2.java b/src/main/java/de/uniluebeck/mi/projmi6/hapi2/HL7Util2.java new file mode 100644 index 0000000..b323e5e --- /dev/null +++ b/src/main/java/de/uniluebeck/mi/projmi6/hapi2/HL7Util2.java @@ -0,0 +1,33 @@ +package de.uniluebeck.mi.projmi6.hapi2; + +import ca.uhn.hl7v2.model.DataTypeException; +import ca.uhn.hl7v2.model.v251.datatype.DTM; + +import java.time.LocalDateTime; +import java.time.ZoneId; + +/** + * Created by nils on 20.11.2015. + */ +public class HL7Util2 { + public static LocalDateTime parseLocalDateTime(DTM dtm) { + try { + return LocalDateTime.ofInstant(dtm.getValueAsDate().toInstant(), ZoneId.systemDefault()); + } catch (DataTypeException e) { + e.printStackTrace(); + } + return null; + } + + public static String parseIcd10Code(String icd10code) { + return removeWhitespaces(icd10code).substring(0, 5); + } + + public static String parseOpsCode(String opscode) { + return removeWhitespaces(opscode).substring(0, 7); + } + + private static String removeWhitespaces(String s) { + return s.replaceAll("\\s", ""); + } +} diff --git a/src/main/resources/log4j.properties b/src/main/resources/log4j.properties new file mode 100644 index 0000000..393e087 --- /dev/null +++ b/src/main/resources/log4j.properties @@ -0,0 +1,8 @@ +# Root logger option +log4j.rootLogger=INFO, stdout + +# Direct log messages to stdout +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target=System.out +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n \ No newline at end of file