/*******************************************************************************
* Copyright (c) 2006-2010, G. Weirich and Elexis
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* G. Weirich - initial implementation
*
*******************************************************************************/
package ch.elexis.data;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.Hashtable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.swt.widgets.Composite;
import ch.elexis.base.ch.diagnosecodes_schweiz.Messages;
import ch.elexis.core.data.events.ElexisEventDispatcher;
import ch.elexis.core.ui.util.ImporterPage;
import ch.elexis.core.ui.util.SWTHelper;
import ch.rgw.tools.Log;
/**
* Der ICDImporter importiert den ICD-Code, wie er beispielsweise von der WHO bereitgestellt wird.
* Die "EDV-Fassung" kann z.B. hier bezogen werden: http://www
* .dimdi.de/dynamic/de/klassi/downloadcenter/icd-10-who/version2006/systematik Sie benötigen die
* ICD-10-WHO 2006 Systematik EDV-Fassung ASCII (x1vea2006.zip) und die ICD-10-WHO 2006 Systematik
* Metadaten ASCII (x1vma2006.zip) Entpacken Sie beide in dieselbe Ebene desselben Verzeichnisses.
* (Die "liesmich.txt"-Datei wird dabei überschrieben, da sie in beiden Archiven vorhanden ist. Sie
* können die entsprechende Warung ignorieren)
*
* Dieser Importer liest aus den Metadaten "codes.txt" die einzelnen ICD-Ziffern zeilenweise ein und
* baut die kompletten Codes mithilfe der KAPxx-.asc - Kapiteldateien aus der Systematik auf.
*
* Aufbau von codes.txt: Feld 1 : Klassifikationsebene, 1 Zeichen 3 = Dreisteller 4 = Viersteller 5
* = Fünfsteller Feld 2 : Ort der Schlüsselnummer im Klassifikationsbaum, 1 Zeichen T = terminale
* Schlüsselnummer (kodierbarer Endpunkt) N = nichtterminale Schlüsselnummer (kein kodierbarer
* Endpunkt) Feld 3 : Generiert? X: explizit in der Klassifikation aufgeführt S: über
* Subklassifikation generiert Feld 4 : Art der Viersteller X = explizit aufgeführt (präkombiniert)
* S = per Subklassifikation (postkomibiniert) Feld 5 : Kapitelnummer, 2 Zeichen Feld 6 : erster
* Dreisteller der Gruppe, 3 Zeichen Feld 7 : Dreisteller zur Schlüsselnummer, 3 Zeichen Feld 8 :
* Schlüsselnummer ohne eventuelles Kreuzchen, bis zu 7 Zeichen Feld 9 : Schlüsselnummer ohne
* Strich, Sternchen und Ausrufezeichen, bis zu 6 Zeichen Feld 10: Schlüsselnummer ohne Punkt,
* Strich, Sternchen und Ausrufezeichen, bis zu 5 Zeichen Feld 11: Klassentitel, bis zu 255 Zeichen
* Feld 12: Bezug zur Mortalitätsliste 1 Feld 13: Bezug zur Mortalitätsliste 2 Feld 14: Bezug zur
* Mortalitätsliste 3 Feld 15: Bezug zur Mortalitätsliste 4 Feld 16: Bezug zur Morbiditätsliste Feld
* 17: Geschlechtsbezug der Schlüsselnummer 9 = kein Geschlechtsbezug M = maennlich W = weiblich
* Feld 18: Art des Fehlers bei Geschlechtsbezug 9 = irrelevant M = Muß-Fehler K = Kann-Fehler Feld
* 19: untere Altersgrenze für eine Schlüsselnummer 999 = irrelevant 000 = bis unter 1 Tag 001-006 =
* 1 Tag bis unter 7 Tage 011-013 = 7 Tage bis unter 28 Tage 101-111 = 28 Tage bis unter 1 Jahr
* 201-299 = 1 Jahr bis unter 100 Jahre 300-324 = 100 Jahre bis unter 124 Jahre Feld 20: obere
* Altersgrenze für eine Schlüsselnummer wie bei Feld 19 Feld 21: Art des Fehlers bei Altersbezug 9
* = irrelevant M = Muß-Fehler K = Kann-Fehler Feld 22: Krankheit in Mitteleuropa sehr selten? J =
* Ja (--> Kann-Fehler auslösen!) N = Nein Feld 23: Schlüsselnummer als Grundleiden in der
* Todesursachenkodierung zugelassen? J = Ja M = Nein
*
*
* @author gerry
*
*/
public class ICDImporter extends ImporterPage {
DirectoryBasedImporter dbi;
private Pattern pat_group;
// private final static String regex_chapter=".*Kapitel +([IV]+).*";
private final static String regex_group = "([A-Z][0-9][0-9]-[A-Z][0-9][0-9])(.+?):"; //$NON-NLS-1$
static Log log = Log.get("ICD Import"); //$NON-NLS-1$
@Override
public IStatus doImport(IProgressMonitor monitor) throws Exception{
monitor.beginTask(Messages.ICDImporter_icdImport, 15000);
monitor.subTask(Messages.ICDImporter_createTable);
ICD10.initialize();
monitor.worked(500);
if (monitor.isCanceled()) {
return Status.CANCEL_STATUS;
}
monitor.subTask(Messages.ICDImporter_readCodes);
pat_group = Pattern.compile(regex_group, Pattern.CASE_INSENSITIVE);
File codes = new File(results[0] + File.separator + "codes.txt"); //$NON-NLS-1$
InputStreamReader ir = new InputStreamReader(new FileInputStream(codes), "iso-8859-1"); //$NON-NLS-1$
BufferedReader br = new BufferedReader(ir);
String in;
ICD10 node;
Hashtable<String, ICD10> chapters = new Hashtable<String, ICD10>();
Hashtable<String, ICD10> groups = new Hashtable<String, ICD10>();
Hashtable<String, ICD10> supercodes = new Hashtable<String, ICD10>();
while ((in = br.readLine()) != null) {
String[] fields = in.split(";"); //$NON-NLS-1$
String kap = fields[ICD10.CHAPTER];
String group = fields[ICD10.GROUP];
String supercode = fields[ICD10.SUPERCODE];
ICD10 kapitel = chapters.get(kap);
if (kapitel == null) { // Neues Kapitel anlegen
kapitel =
new ICD10(
"NIL", kap, "1;N;X;X;" + kap + ";" + kap + ";" + kap + ";" + kap + ";" + kap + ";" + kap + ";Kapitel " + kap + ";;;;;"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$
chapters.put(kap, kapitel);
LineFeeder lf = new LineFeeder(results[0] + File.separator + "KAP" + kap + ".asc"); //$NON-NLS-1$ //$NON-NLS-2$
while (lf.peek() == '0') {
String t = lf.nextLine();
switch (t.charAt(1)) {
case 'T':
kapitel.set("Text", t.substring(2).replaceAll("\n", " - "));break; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
case 'I':
kapitel.setExt("Incl:", t.substring(2));break; //$NON-NLS-1$
case 'E':
kapitel.setExt("Excl:", t.substring(2));break; //$NON-NLS-1$
case 'G':
String gruppen = t.substring(2).replaceAll("\n", "::"); //$NON-NLS-1$ //$NON-NLS-2$
kapitel.setExt("Gruppen", t.substring(2)); //$NON-NLS-1$
Matcher match = pat_group.matcher(gruppen + "::"); //$NON-NLS-1$
while (match.find() == true) {
String code = match.group(1);
String[] gs = code.split("-"); //$NON-NLS-1$
if (groups.get(gs[0]) == null) {
ICD10 Group =
new ICD10(
kapitel.getId(),
code,
"1;N;X;X;" + kap + ";" + code + ";" + gs[0] + ";" + gs[0] + ";" + code + ";" + code + ";" + match.group(2)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$
groups.put(gs[0], Group);
}
}
break;
default:
kapitel.setExt("Zusatz", t.substring(2)); //$NON-NLS-1$
}
}
}
ICD10 mygroup = groups.get(group);
if (mygroup == null) {
node = new ICD10(kapitel.getId(), fields[ICD10.CODE], in);
} else {
if (fields[0].equals("3")) { //$NON-NLS-1$
node = new ICD10(mygroup.getId(), fields[ICD10.CODE], in);
supercodes.put(fields[ICD10.CODE], node);
} else {
ICD10 icdSuper = supercodes.get(supercode);
if (icdSuper == null) {
node = new ICD10(mygroup.getId(), fields[ICD10.CODE], in);
} else {
node = new ICD10(icdSuper.getId(), fields[ICD10.CODE], in);
}
}
}
monitor.worked(1);
if (monitor.isCanceled()) {
return Status.CANCEL_STATUS;
}
node = null;
kap = null;
}
ElexisEventDispatcher.reload(ICD10.class);
return Status.OK_STATUS;
}
@Override
public String getTitle(){
return "ICD-10"; //$NON-NLS-1$
}
@Override
public Composite createPage(Composite parent){
dbi = new ImporterPage.DirectoryBasedImporter(parent, this);
dbi.setLayoutData(SWTHelper.getFillGridData(1, true, 1, true));
return dbi;
}
@Override
public String getDescription(){
return Messages.ICDImporter_enterDirectory;
}
class LineFeeder {
String prev;
BufferedReader br;
LineFeeder(String fname) throws Exception{
br =
new BufferedReader(new InputStreamReader(new FileInputStream(fname), "iso-8859-1")); //$NON-NLS-1$
prev = br.readLine();
}
char peek(){
return prev.charAt(0);
}
String nextLine() throws Exception{
if (prev == null) {
return null;
}
String ret = prev;
prev = br.readLine();
if (prev == null) {
br.close();
return ret;
}
while (prev.startsWith(" ") || (prev.startsWith("P"))) { //$NON-NLS-1$ //$NON-NLS-2$
ret += "\n" + prev.trim(); //$NON-NLS-1$
prev = br.readLine();
if (prev == null) {
br.close();
return ret;
}
}
while (prev.substring(0, 2).equals(ret.substring(0, 2))) {
ret += "\n" + nextLine().substring(2); //$NON-NLS-1$
return ret;
}
while (prev.startsWith("LZ")) { //$NON-NLS-1$
prev = br.readLine();
if (prev == null) {
br.close();
break;
}
}
return ret;
}
boolean atEOF(){
return prev == null;
}
public void close() throws Exception{
br.close();
}
}
}