/*******************************************************************************
* Copyright (c) 2010, Oliver Egger, visionary ag
*
* 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
*
*******************************************************************************/
package ch.docbox.elexis;
import static ch.elexis.core.constants.XidConstants.DOMAIN_EAN;
import java.io.Serializable;
import java.util.GregorianCalendar;
import java.util.List;
import javax.xml.bind.JAXBElement;
import javax.xml.ws.Holder;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.ToolTip;
import org.eclipse.swt.widgets.Tray;
import org.eclipse.swt.widgets.TrayItem;
import org.hl7.v3.AD;
import org.hl7.v3.AdxpCity;
import org.hl7.v3.AdxpPostalCode;
import org.hl7.v3.AdxpStreetAddressLine;
import org.hl7.v3.ClinicalDocumentType;
import org.hl7.v3.EnFamily;
import org.hl7.v3.EnGiven;
import org.hl7.v3.EnPrefix;
import org.hl7.v3.II;
import org.hl7.v3.ON;
import org.hl7.v3.PN;
import org.hl7.v3.POCDMT000040IntendedRecipient;
import org.hl7.v3.POCDMT000040Organization;
import org.hl7.v3.POCDMT000040Person;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ch.docbox.cdach.CdaChXPath;
import ch.docbox.cdach.DocboxCDA;
import ch.docbox.model.CdaMessage;
import ch.docbox.model.DocboxContact;
import ch.docbox.ws.cdachservices.AppointmentType;
import ch.docbox.ws.cdachservices.CDACHServices;
import ch.docbox.ws.cdachservices.DocumentInfoType;
import ch.elexis.core.constants.StringConstants;
import ch.elexis.core.data.activator.CoreHub;
import ch.elexis.core.data.events.ElexisEventDispatcher;
import ch.elexis.core.ui.UiDesk;
import ch.elexis.data.Kontakt;
import ch.elexis.data.Mandant;
import ch.elexis.data.PersistentObject;
import ch.elexis.data.Person;
import ch.rgw.tools.ExHandler;
import ch.rgw.tools.StringTool;
public class DocboxBackgroundJob extends Job {
private static Logger log = LoggerFactory.getLogger(DocboxBackgroundJob.class);
public DocboxBackgroundJob(){
super(Messages.DocboxBackgroundJob_Title);
this.setUser(false);
this.setPriority(Job.LONG);
}
public synchronized int fetchAppointments(final IProgressMonitor monitor){
CDACHServices port = UserDocboxPreferences.getPort();
int count = 0;
List<DocboxTermin> docboxTermine = DocboxTermin.getDocboxTermine();
monitor.worked(20);
List<AppointmentType> appointments = port.getCalendar();
if (appointments != null) {
for (AppointmentType appointment : appointments) {
DocboxTermin docboxTermin = new DocboxTermin();
if (appointment.getState() != null
&& ((appointment.getState().contains("salesrepresentative") //$NON-NLS-1$
&& UserDocboxPreferences.isAppointmentsPharmaVisits())
|| (appointment.getState().contains("emergencyservice")
&& UserDocboxPreferences.isAppointmentsEmergencyService())
|| (appointment.getState().contains("terminierung") //$NON-NLS-1$
&& UserDocboxPreferences.isAppointmentsTerminvereinbarung()))) {
++count;
docboxTermin.create(appointment,
UserDocboxPreferences.getAppointmentsBereich());
if (docboxTermine.contains(docboxTermin)) {
docboxTermine.remove(docboxTermin);
}
}
}
monitor.worked(20);
for (DocboxTermin docboxTermin : docboxTermine) {
docboxTermin.delete();
}
}
monitor.worked(20);
return count;
}
public synchronized int updateDoctorDirectory(final IProgressMonitor monitor){
CDACHServices port = UserDocboxPreferences.getPort();
int count = 0;
String myDocboxId = (String) CoreHub.actMandant.getInfoElement("docboxId");
if (myDocboxId == null || "".equals(myDocboxId)) {
updateDoctorDirectoryByApp(port, count, "self");
}
count = updateDoctorDirectoryByApp(port, count, "doctodoc");
monitor.worked(30);
count += updateDoctorDirectoryByApp(port, count, "terminvereinbarung");
monitor.worked(30);
return count;
}
private int updateDoctorDirectoryByApp(CDACHServices port, int count, String application){
List<POCDMT000040IntendedRecipient> recipients = port.getRecipients(application);
if (recipients != null) {
for (POCDMT000040IntendedRecipient recipient : recipients) {
String docboxId = "";
String ean = "";
String given = "";
String family = "";
String prefix = "";
List<II> iis = recipient.getId();
for (II ii : iis) {
if ("1.3.88".equals(ii.getRoot())) {
ean = ii.getExtension();
}
if (CdaChXPath.getOidUserDocboxId().equals(ii.getRoot())) {
docboxId = ii.getExtension();
}
}
POCDMT000040Person person = recipient.getInformationRecipient();
POCDMT000040Organization organization = recipient.getReceivedOrganization();
List<PN> pns = person.getName();
for (PN pn : pns) {
List<Serializable> ens = pn.getContent();
for (Serializable en : ens) {
if (ens != null) {
JAXBElement<?> t = (JAXBElement<?>) en;
if (t.getDeclaredType().getName().equals(EnGiven.class.getName())) {
given = ((EnGiven) t.getValue()).content();
}
if (t.getDeclaredType().getName().equals(EnFamily.class.getName())) {
family = ((EnFamily) t.getValue()).content();
}
if (t.getDeclaredType().getName().equals(EnPrefix.class.getName())) {
prefix = ((EnPrefix) t.getValue()).content();
if (prefix != null && prefix.length() > 20) {
prefix = prefix.substring(0, 19);
}
}
}
}
}
String organizationName = "";
List<ON> ons = organization.getName();
if (ons != null) {
for (ON on : ons) {
if (on != null) {
List<Serializable> ens = on.getContent();
if (ens != null) {
for (Serializable en : ens) {
organizationName = en.toString();
}
}
}
}
}
boolean first = false;
String streetAdressLine = "";
String city = "";
String plz = "";
List<AD> ads = organization.getAddr();
for (AD ad : ads) {
List<Serializable> ens = ad.getContent();
if (ens != null) {
for (Serializable en : ens) {
JAXBElement<?> t = (JAXBElement<?>) en;
if (t.getDeclaredType().getName()
.equals(AdxpStreetAddressLine.class.getName())) {
if (!first) {
streetAdressLine =
((AdxpStreetAddressLine) t.getValue()).content();
first = true;
} else {
String content =
((AdxpStreetAddressLine) t.getValue()).content();
if (content != null && content.length() > 0) {
streetAdressLine += content;
}
}
}
if (t.getDeclaredType().getName().equals(AdxpCity.class.getName())) {
city = ((AdxpCity) t.getValue()).content();
}
if (t.getDeclaredType().getName()
.equals(AdxpPostalCode.class.getName())) {
plz = ((AdxpPostalCode) t.getValue()).content();
}
}
}
}
if (docboxId.length() > 0) {
++count;
Person p = null;
Kontakt cMatching = DocboxContact.findContactForDocboxId(docboxId);
if (cMatching != null) {
p = (Person) cMatching;
}
if (p == null && "self".equals(application)) {
p = (Person) ElexisEventDispatcher.getSelected(Mandant.class);
new DocboxContact(docboxId, p);
}
if (p == null || UserDocboxPreferences.isDocboxTest()) {
boolean newPerson = p == null;
if (newPerson) {
p = new Person(family, given, "", "");
new DocboxContact(docboxId, p);
} else {
log.warn("newPerson is false, skipping intialization cMatching: "
+ cMatching+"/ docboxId: "+docboxId);
continue;
}
p.set(Person.NAME, family);
p.set(Person.FIRSTNAME, given);
p.set(Person.TITLE, prefix);
if (!PersistentObject.checkNull(p.get(Person.FLD_IS_USER))
.equals(StringConstants.ONE)) {
p.set(Kontakt.FLD_NAME3, organizationName);
}
p.set(Kontakt.FLD_STREET, streetAdressLine);
p.set(Kontakt.FLD_ZIP, plz);
p.set(Kontakt.FLD_PLACE, city);
p.addXid(DOMAIN_EAN, ean, true);
}
p.setInfoElement(application, true);
}
}
}
return count;
}
/**
*
* @return true if everything successful, false if a warning or error occurred
*/
public synchronized int fetchInboxClinicalDocuments(final IProgressMonitor monitor){
log.debug("fetchInboxClinicalDocuments");//$NON-NLS-1$
boolean result = true;
int count = 0;
CDACHServices port = UserDocboxPreferences.getPort();
List<DocumentInfoType> documentInfoTypes = port.getInboxClinicalDocuments(null);
int maxworked = 60;
int worked = 0;
if (documentInfoTypes != null) {
DocboxCDA docboxCDA = new DocboxCDA();
for (int j = 0; j < documentInfoTypes.size(); ++j) {
DocumentInfoType documentInfoType = documentInfoTypes.get(j);
String id = documentInfoType.getDocumentID();
CdaMessage cdaMessage = CdaMessage.getCdaMessageEvenIfDocsDeleted(id);
if (cdaMessage == null || (!cdaMessage.isDownloaded() && !cdaMessage.isDeleted())) {
if (cdaMessage == null) {
GregorianCalendar cal = (GregorianCalendar) GregorianCalendar.getInstance();
if (documentInfoType.getCreationDate() != null) {
cal.setTimeInMillis(documentInfoType.getCreationDate()
.toGregorianCalendar().getTimeInMillis());
} else {
cal = null;
}
cdaMessage = new CdaMessage(id, documentInfoType.getTitle(), cal);
log.debug("creating messseage with id " + id);//$NON-NLS-1$
} else {
log.debug("redo download for document id " + id);//$NON-NLS-1$
}
Holder<ClinicalDocumentType> clincialDocumentTypeHolder =
new Holder<ClinicalDocumentType>();
Holder<byte[]> attachmentHolder = new Holder<byte[]>();
port.getClinicalDocument(id, clincialDocumentTypeHolder, attachmentHolder);
boolean unzipSuccessful = true;
if (attachmentHolder.value != null) {
if (!cdaMessage.unzipAttachment(attachmentHolder.value)) {
log.debug("unzip of attachment failed" + id);//$NON-NLS-1$
unzipSuccessful = false;
}
}
if (clincialDocumentTypeHolder.value != null && unzipSuccessful) {
String receivedCDA = docboxCDA.marshallIntoString(
clincialDocumentTypeHolder.value.getClinicalDocument());
CdaChXPath cdaChXPath = new CdaChXPath();
cdaChXPath.setPatientDocument(receivedCDA);
if (cdaMessage.setCda(receivedCDA)) {
String firstName = cdaChXPath.getPatientFirstName();
String lastName = cdaChXPath.getPatientLastName();
boolean first = !StringTool.isNothing(firstName);
boolean last = !StringTool.isNothing(firstName);
String patient = (first ? firstName : "") //$NON-NLS-1$
+ (first && last ? " " : "")//$NON-NLS-1$ //$NON-NLS-2$
+ (last ? lastName : "");//$NON-NLS-1$
firstName = cdaChXPath.getAuthorFirstName();
lastName = cdaChXPath.getAuthorLastName();
String organization = cdaChXPath.getCustodianHospitalName();
boolean org = !StringTool.isNothing(organization);
first = !StringTool.isNothing(firstName);
last = !StringTool.isNothing(lastName);
String sender = (first ? firstName : "")//$NON-NLS-1$
+ (first && last ? " " : "")//$NON-NLS-1$ //$NON-NLS-2$
+ (last ? lastName : "")//$NON-NLS-1$
+ (org && (first || last) ? ", " : "")//$NON-NLS-1$ //$NON-NLS-2$
+ (org ? organization : "");//$NON-NLS-1$
if (!cdaMessage.setDownloaded(sender, patient)) {
log.debug("failed to set cda message downloaded with id " + id);//$NON-NLS-1$
result = false;
} else {
ElexisEventDispatcher.update(cdaMessage);
++count;
}
} else {
log.debug("failed to set cda message downloaded with id " + id);//$NON-NLS-1$
result = false;
}
}
}
double tmpWorked = (maxworked * (j + 1)) / documentInfoTypes.size();
int newWorked = (int) tmpWorked - worked;
if (newWorked > 0) {
if (newWorked > 0) {
monitor.worked(newWorked);
worked += newWorked;
}
}
}
}
ElexisEventDispatcher.reload(CdaMessage.class);
int newWorked = maxworked - worked;
if (newWorked > 0) {
monitor.worked(newWorked);
}
return result ? count : -1;
}
public static void showResultInPopup(final String message){
Display display = UiDesk.getDisplay();
display.asyncExec(new Runnable() {
public void run(){
Display display = UiDesk.getDisplay();
Shell shell = UiDesk.getTopShell();
if (shell != null) {
final ToolTip tip = new ToolTip(shell, SWT.BALLOON | SWT.ICON_INFORMATION);
tip.setMessage(message);
Tray tray = display.getSystemTray();
TrayItem item = null;
if (tray != null) {
item = new TrayItem(tray, SWT.NONE);
item.setImage(
Activator.getImageDescriptor("icons/docbox16.png").createImage());//$NON-NLS-1$
tip.setText("docbox");//$NON-NLS-1$
item.setToolTip(tip);
} else {
tip.setText("docbox");//$NON-NLS-1$
tip.setLocation(400, 400);
}
tip.setVisible(true);
try {
// delay for five seconds
Thread.sleep(5000L);
} catch (InterruptedException e) {
ExHandler.handle(e);
}
tip.setVisible(false);
tip.dispose();
if (item != null) {
item.setVisible(false);
item.dispose();
}
}
}
});
}
@Override
protected IStatus run(IProgressMonitor monitor){
boolean success = true;
String msg = ""; //$NON-NLS-1$
log.debug("running");
if (CoreHub.actUser != null) {
try {
if (CoreHub.actUser != null && UserDocboxPreferences.hasValidDocboxCredentials()) {
log.debug("beginTask");
monitor.beginTask(Messages.DocboxBackgroundJob_Title, 200);
monitor.worked(10);
if (!monitor.isCanceled()) {
log.debug("fetchInboxClinicalDocuments");
int downloadedDocuments = fetchInboxClinicalDocuments(monitor);
if (downloadedDocuments > 0) {
msg += String.format(Messages.DocboxBackgroundJob_DocumentsDownloaded,
downloadedDocuments);
}
log.debug(msg);
}
if (UserDocboxPreferences.hasAgendaPlugin()
&& UserDocboxPreferences.downloadAppointments() && !monitor.isCanceled()) {
log.debug("fetchAppointments");
int downloadedAppointments = fetchAppointments(monitor);
if (!"".equals(msg)) { //$NON-NLS-1$
msg += "\n"; //$NON-NLS-1$
}
msg += String.format(Messages.DocboxBackgroundJob_AppointmentsUpdated,
downloadedAppointments);
log.debug(msg);
} else {
monitor.worked(60);
}
if (!monitor.isCanceled()) {
log.debug("updateDoctorDirectory");
int count = updateDoctorDirectory(monitor);
if (!"".equals(msg)) { //$NON-NLS-1$
msg += "\n"; //$NON-NLS-1$
}
msg += String.format(Messages.DocboxBackgroundJob_DoctorDirecotoryUpdated,
count);
log.debug(msg);
} else {
monitor.worked(60);
}
monitor.worked(10);
monitor.done();
if (msg != null && msg.length() > 0) {
showResultInPopup(msg);
}
} else {}
} catch (Exception e) {
ExHandler.handle(e);
log.debug("error in task", e);
}
}
log.debug("stopped");
return (success ? Status.OK_STATUS : Status.CANCEL_STATUS);
}
}