/******************************************************************************* * Copyright (c) 2014 MEDEVIT. * 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: * T. Huster - initial API and implementation *******************************************************************************/ package at.medevit.elexis.ehc.ui.model; import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.MalformedURLException; import java.net.URL; import java.util.List; import org.ehealth_connector.cda.ch.AbstractCdaCh; import org.openhealthtools.mdht.uml.cda.ClinicalDocument; import org.openhealthtools.mdht.uml.cda.util.CDAUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import at.medevit.elexis.ehc.core.EhcCoreMapper; import at.medevit.elexis.ehc.ui.service.ServiceComponent; import ch.elexis.data.Patient; import ch.elexis.data.PersistentObject; import ch.elexis.data.Query; import ch.rgw.tools.JdbcLink; import ch.rgw.tools.TimeTool; import ch.rgw.tools.VersionInfo; public class EhcDocument extends PersistentObject { private static Logger logger = LoggerFactory.getLogger(EhcDocument.class); public enum EhcDocType { CLINICALDOCUMENT, XDM } public static final String TABLENAME = "at_medevit_elexis_ehc_document"; //$NON-NLS-1$ public static final String VERSION = "1.0.0"; //$NON-NLS-1$ public static final String VERSIONID = "VERSION"; //$NON-NLS-1$ public static final String FLD_NAME = "name"; //$NON-NLS-1$ public static final String FLD_TIMESTAMP = "timestamp"; //$NON-NLS-1$ public static final String FLD_PATIENT = "patient"; //$NON-NLS-1$ public static final String FLD_LOCATION = "location"; //$NON-NLS-1$ // @formatter:off static final String create = "CREATE TABLE " + TABLENAME + " (" + //$NON-NLS-1$ "ID VARCHAR(25) primary key, " + //$NON-NLS-1$ "lastupdate BIGINT," + "deleted CHAR(1) default '0'," + //$NON-NLS-1$ "name VARCHAR(255)," + //$NON-NLS-1$ "timestamp VARCHAR(16)," + //$NON-NLS-1$ "patient VARCHAR(128)," + //$NON-NLS-1$ "location VARCHAR(255)" + //$NON-NLS-1$ ");" + //$NON-NLS-1$ "CREATE INDEX ehcdoc1 ON " + TABLENAME + " (" + FLD_PATIENT + ");" + //$NON-NLS-1$ "INSERT INTO " + TABLENAME + " (ID," + FLD_PATIENT + ") VALUES (" + JdbcLink.wrap(VERSIONID) + "," + JdbcLink.wrap(VERSION) + ");"; //$NON-NLS-1$ // @formatter:on static { addMapping(TABLENAME, FLD_NAME, FLD_TIMESTAMP, FLD_PATIENT, FLD_LOCATION); if (!tableExists(TABLENAME)) { createOrModifyTable(create); } else { EhcDocument version = load(VERSIONID); VersionInfo vi = new VersionInfo(version.get(FLD_PATIENT)); if (vi.isOlder(VERSION)) { // we should update eg. with createOrModifyTable(update.sql); // And then set the new version version.set(FLD_PATIENT, VERSION); } } } public EhcDocument(){ // TODO Auto-generated constructor stub } public EhcDocument(String id){ super(id); } public static EhcDocument load(final String id){ return new EhcDocument(id); } public EhcDocument(String name, URL location, TimeTool creation){ create(null); String[] fields = { FLD_NAME, FLD_TIMESTAMP, FLD_LOCATION }; String[] vals = new String[] { name, creation.toString(TimeTool.TIMESTAMP), location.toString() }; set(fields, vals); Patient patient = null; if (isEhcType(EhcDocType.CLINICALDOCUMENT)) { patient = getPatientFromDocument(location); } if (patient != null) { setPatient(patient); } } public boolean isEhcType(EhcDocType type){ return getName().contains("[" + type + "]"); } private Patient getPatientFromDocument(URL location){ Patient ret = null; try { if (EhcDocument.isEhcXml(location)) { ClinicalDocument clinicalDocument = ServiceComponent.getEhcService().loadDocument(location.openStream()); AbstractCdaCh<?> cdaCh = ServiceComponent.getEhcService().getAsCdaChDocument(clinicalDocument); if (cdaCh != null) { org.ehealth_connector.common.Patient patient = cdaCh.getPatient(); if (patient != null) { ret = EhcCoreMapper.getElexisPatient(patient); } } } } catch (IOException e) { logger.error("Could not open location.", e); } return ret; } public String getName(){ return get(FLD_NAME); } public void setName(String name){ set(FLD_NAME, name); } public URL getLocation(){ try { return new URL(get(FLD_LOCATION)); } catch (MalformedURLException e) { logger.error("Could create URL for location.", e); } return null; } public void setLocation(URL location){ set(FLD_LOCATION, location.toString()); } public Patient getPatient(){ String id = get(FLD_PATIENT); if (id != null && !id.isEmpty()) { Patient patient = Patient.load(id); if (patient.exists()) { return patient; } } return null; } public void setPatient(Patient patient){ set(FLD_PATIENT, patient.getId()); } public static boolean documentExists(URL url){ Query<EhcDocument> qd = new Query<EhcDocument>(EhcDocument.class); qd.add(FLD_LOCATION, Query.EQUALS, url.toString()); List<EhcDocument> existing = qd.execute(); return !existing.isEmpty(); } public static boolean isEhcXml(URL url){ if (url.getPath().endsWith(".xml")) { try (InputStream stream = url.openStream(); BufferedReader br = new BufferedReader(new InputStreamReader(stream));) { String line = null; for (int i = 0; i < 100; i++) { line = br.readLine(); if (line != null) { if (line.contains("<ClinicalDocument")) { return true; } } else { break; } } } catch (IOException e) { // just fall through to returning false } } return false; } public static boolean isEhcXdm(URL url){ if (url.getPath().endsWith(".zip") || url.getPath().endsWith(".xdm")) { String fileName = url.getFile(); if (fileName != null && !fileName.isEmpty()) { File file = new File(fileName); if (file.exists()) { List<org.ehealth_connector.common.Patient> patients = ServiceComponent.getEhcService().getXdmPatients(file); return patients != null; } } } return false; } /** * Factory Method for creating an EhcDocument entry from an CDA ClinicalDocument XML. * * @param fileUrl * @return */ public static EhcDocument createFromXml(URL fileUrl){ File file = new File(fileUrl.getFile()); return new EhcDocument(file.getName() + " [" + EhcDocType.CLINICALDOCUMENT + "]", fileUrl, new TimeTool()); } /** * Factory Method for EhcDocument entry from an XDM. The ClinicalDocuments contained in the XDM * file are extracted. The InboxWatcher will handle them separately. * * @param fileUrl * @return */ public static EhcDocument createFromXdm(URL fileUrl){ File xdmFile = new File(fileUrl.getPath()); EhcDocument ret = new EhcDocument(xdmFile.getName() + " [" + EhcDocType.XDM + "]", fileUrl, new TimeTool()); List<ClinicalDocument> documents = ServiceComponent.getEhcService().getXdmDocuments(xdmFile); for (ClinicalDocument clinicalDocument : documents) { File documentFile = getXdmDocumentFile(clinicalDocument, xdmFile); try (FileOutputStream outputStream = new FileOutputStream(documentFile)) { CDAUtil.save(clinicalDocument, outputStream); } catch (Exception e) { logger.error("Could not create EhcDocument from xdm.", e); } } return ret; } private static File getXdmDocumentFile(ClinicalDocument clinicalDocument, File xdmFile){ String rootPath = xdmFile.getParent(); String rootName = xdmFile.getName(); rootName = rootName.replaceAll("\\.", ""); File file = null; for (int i = 0; i < 100; i++) { file = new File(rootPath + File.separator + rootName + "_" + i + ".xml"); if (!file.exists()) { break; } } return file; } @Override public String getLabel(){ return getName().replaceAll("\\[[A-Z]+\\]", ""); } @Override protected String getTableName(){ return TABLENAME; } }