/*******************************************************************************
* Copyright (c) 2007-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.agenda.data;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.text.MessageFormat;
import java.util.List;
import net.fortuna.ical4j.data.CalendarBuilder;
import net.fortuna.ical4j.data.CalendarOutputter;
import net.fortuna.ical4j.data.ParserException;
import net.fortuna.ical4j.model.Calendar;
import net.fortuna.ical4j.model.Component;
import net.fortuna.ical4j.model.Date;
import net.fortuna.ical4j.model.DateTime;
import net.fortuna.ical4j.model.TimeZone;
import net.fortuna.ical4j.model.TimeZoneRegistry;
import net.fortuna.ical4j.model.TimeZoneRegistryFactory;
import net.fortuna.ical4j.model.component.VEvent;
import net.fortuna.ical4j.model.component.VTimeZone;
import net.fortuna.ical4j.model.property.CalScale;
import net.fortuna.ical4j.model.property.Description;
import net.fortuna.ical4j.model.property.DtEnd;
import net.fortuna.ical4j.model.property.DtStart;
import net.fortuna.ical4j.model.property.ProdId;
import net.fortuna.ical4j.model.property.Summary;
import net.fortuna.ical4j.model.property.Uid;
import net.fortuna.ical4j.model.property.Version;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ch.elexis.agenda.Messages;
import ch.elexis.agenda.preferences.PreferenceConstants;
import ch.elexis.core.data.activator.CoreHub;
import ch.elexis.core.ui.UiDesk;
import ch.elexis.core.ui.util.SWTHelper;
import ch.elexis.data.PersistentObject;
import ch.elexis.data.Query;
import ch.rgw.tools.ExHandler;
import ch.rgw.tools.StringTool;
import ch.rgw.tools.TimeTool;
import com.tiff.common.ui.datepicker.DatePickerCombo;
/**
* Convert appointments to and frim ICal-Format
*
* @author gerry
*
*/
public class ICalTransfer {
String[] bereiche;
final String NOFILESELECTED = Messages.ICalTransfer_noFileSelected;
String typ = Termin.typStandard();
String status = Termin.statusStandard();
Button bFile;
Combo cbTypes, cbStates;
Button bAll;
Label lFilename;
private static Logger log = LoggerFactory.getLogger(ICalTransfer.class);
public ICalTransfer(){
bereiche =
CoreHub.globalCfg.get(PreferenceConstants.AG_BEREICHE, Messages.TagesView_14).split(","); //$NON-NLS-1$
}
/**
* Export a range of appointments to ICal. The Method ends with a Call to an ICalExportDialog to
* let the user decide where to store the resulting file.
*
* @param von
* Begin of the range to export (null: today)
* @param bis
* end of the range to export (null: today)
* @param bereich
* agenda mandator whose appointments should be exported
*/
public void doExport(TimeTool von, TimeTool bis, String bereich){
if (von == null) {
von = new TimeTool();
}
if (bis == null) {
bis = new TimeTool();
}
if (bereich == null) {
bereich = bereiche[0];
}
new ICalExportDlg(von, bis, bereich).open();
}
/**
* Import an ICal-File
*
* @param bereich
* agenda mandator to whom the ical should be imported
*/
public void doImport(String bereich){
if (bereich == null) {
bereich = bereiche[0];
}
new ICalImportDlg(bereich).open();
}
class ICalImportDlg extends TitleAreaDialog {
String m;
FileDialog fileDialog;
public ICalImportDlg(String bereich){
super(UiDesk.getTopShell());
m = bereich;
}
@Override
protected Control createDialogArea(Composite parent){
Composite ret = new Composite(parent, SWT.NONE);
ret.setLayoutData(SWTHelper.getFillGridData(1, true, 1, true));
ret.setLayout(new GridLayout(2, false));
bFile = new Button(ret, SWT.PUSH);
lFilename = new Label(ret, SWT.NONE);
lFilename.setLayoutData(SWTHelper.getFillGridData(1, true, 1, false));
lFilename.setText(NOFILESELECTED);
bFile.setLayoutData(SWTHelper.getFillGridData(1, true, 1, false));
bFile.setText(Messages.ICalTransfer_fileToImport);
bFile.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e){
fileDialog = new FileDialog(getShell(), SWT.OPEN);
fileDialog.setFilterExtensions(new String[] {
"*.ics"}); //$NON-NLS-1$
fileDialog.setFilterNames(new String[] {
Messages.ICalTransfer_iCalFiles
});
String file = fileDialog.open();
if (file == null) {
lFilename.setText(NOFILESELECTED);
getButton(IDialogConstants.OK_ID).setEnabled(false);
} else {
lFilename.setText(file);
getButton(IDialogConstants.OK_ID).setEnabled(true);
}
}
});
new Label(ret, SWT.NONE).setText(Messages.ICalTransfer_preselectType);
cbTypes = new Combo(ret, SWT.SINGLE | SWT.READ_ONLY);
new Label(ret, SWT.NONE).setText(Messages.ICalTransfer_preselectState);
cbStates = new Combo(ret, SWT.SINGLE | SWT.READ_ONLY);
bAll = new Button(ret, SWT.CHECK);
bAll.setText(Messages.ICalTransfer_newAppForAllMandators);
bAll.setLayoutData(SWTHelper.getFillGridData(2, true, 1, false));
cbTypes.setItems(Termin.TerminTypes);
cbStates.setItems(Termin.TerminStatus);
cbTypes.setText(Termin.typStandard());
cbStates.setText(Termin.statusStandard());
cbTypes.setLayoutData(SWTHelper.getFillGridData(1, true, 1, false));
cbStates.setLayoutData(SWTHelper.getFillGridData(1, true, 1, false));
return ret;
}
@Override
public void create(){
super.create();
getShell().setText(Messages.ICalTransfer_importAppointments);
setTitle(Messages.ICalTransfer_ICalToAgenda);
setMessage(Messages.ICalTransfer_pleaseSelectIcalFile);
getButton(IDialogConstants.OK_ID).setEnabled(false);
}
@SuppressWarnings("unchecked")
@Override
protected void okPressed(){
if (!lFilename.getText().equals(NOFILESELECTED)) {
CalendarBuilder cb = new CalendarBuilder();
String[] b = new String[1];
b[0] = m;
if (bAll.getSelection()) {
b = bereiche;
}
try {
Calendar cal = cb.build(new FileInputStream(lFilename.getText()));
TimeTool ttFrom = new TimeTool();
TimeTool ttUntil = new TimeTool();
Date dt = null;
List<Component> comps = cal.getComponents();
for (Component comp : comps) {
if (comp instanceof VEvent) { // TimeZone not supported
VEvent event = (VEvent) comp;
// PropertyList props = event.getProperties();
DtStart start = event.getStartDate();
DtEnd end = event.getEndDate();
if (start != null) {
dt = start.getDate();
ttFrom.setTimeInMillis(dt.getTime());
} else {
ttFrom.set(new TimeTool());
}
if (end != null) {
dt = end.getDate();
ttUntil.setTimeInMillis(dt.getTime());
} else {
ttUntil.set(ttFrom);
}
Termin termin = null;
Uid uid = event.getUid();
String uuid = StringTool.unique("agendaimport"); //$NON-NLS-1$
if (uid != null) {
uuid = uid.getValue();
termin = Termin.load(uuid);
}
if (termin == null || (!termin.exists())) {
for (String ber : b) {
termin =
new Termin(uuid, ber,
ttFrom.toString(TimeTool.DATE_COMPACT),
Termin.TimeInMinutes(ttFrom),
Termin.TimeInMinutes(ttUntil), typ, status);
uuid = StringTool.unique("agendaimport"); //$NON-NLS-1$
}
} else {
termin.set(
new String[] {
Termin.FLD_BEREICH, Termin.FLD_TAG, Termin.FLD_BEGINN,
Termin.FLD_DAUER, Termin.FLD_TERMINTYP,
Termin.FLD_TERMINSTATUS
},
new String[] {
m, ttFrom.toString(TimeTool.DATE_COMPACT),
Integer.toString(Termin.TimeInMinutes(ttFrom)),
Integer.toString(ttFrom.secondsTo(ttUntil) / 60), typ,
status
});
}
if(termin==null) {
throw new IllegalStateException("termin is null");
}
Summary summary = event.getSummary();
if (summary != null) {
termin.setText(summary.getValue());
}
Description desc = event.getDescription();
if (desc != null) {
termin.setGrund(desc.getValue());
}
}
}
} catch (ParserException e) {
ExHandler.handle(e);
SWTHelper.showError(Messages.ICalTransfer_badFileFormat,
Messages.ICalTransfer_noValidICal);
} catch (Exception ex) {
ExHandler.handle(ex);
SWTHelper.showError(
Messages.ICalTransfer_readError,
MessageFormat.format(Messages.ICalTransfer_couldNotReadFile,
bFile.getText()));
}
}
super.okPressed();
}
}
class ICalExportDlg extends TitleAreaDialog {
TimeTool von, bis;
String m;
DatePickerCombo dpVon, dpBis;
Combo cbBereiche;
FileDialog fileDialog;
Label lFile;
public ICalExportDlg(TimeTool from, TimeTool until, String bereich){
super(UiDesk.getTopShell());
von = new TimeTool(from);
bis = new TimeTool(until);
m = bereich;
}
@Override
protected Control createDialogArea(Composite parent){
Composite ret = new Composite(parent, SWT.NONE);
ret.setLayoutData(SWTHelper.getFillGridData(1, true, 1, true));
ret.setLayout(new GridLayout(3, false));
new Label(ret, SWT.NONE).setText(Messages.ICalTransfer_from);
new Label(ret, SWT.NONE).setText(Messages.ICalTransfer_until);
new Label(ret, SWT.NONE).setText(Messages.ICalTransfer_mandator);
dpVon = new DatePickerCombo(ret, SWT.NONE);
dpBis = new DatePickerCombo(ret, SWT.NONE);
cbBereiche = new Combo(ret, SWT.NONE);
cbBereiche.setItems(bereiche);
cbBereiche.setText(m);
Button bChose = new Button(ret, SWT.PUSH);
bChose.setText(Messages.ICalTransfer_file);
bChose.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e){
fileDialog = new FileDialog(getShell(), SWT.SAVE);
fileDialog.setFilterExtensions(new String[] {
"*.ics", //$NON-NLS-1$
"*.csv"}); //$NON-NLS-1$
fileDialog.setFilterNames(new String[] {
Messages.ICalTransfer_iCalFiles2, Messages.ICalTransfer_csvFIles
});
String fileName = fileDialog.open();
if (fileName == null) {
lFile.setText(NOFILESELECTED);
getButton(IDialogConstants.OK_ID).setEnabled(false);
} else {
lFile.setText(fileName);
getButton(IDialogConstants.OK_ID).setEnabled(true);
}
}
});
lFile = new Label(ret, SWT.NONE);
lFile.setLayoutData(SWTHelper.getFillGridData(2, true, 1, false));
lFile.setText(NOFILESELECTED);
dpVon.setDate(von.getTime());
dpBis.setDate(bis.getTime());
return ret;
}
@Override
public void create(){
super.create();
getShell().setText(Messages.ICalTransfer_exportAgenda);
setTitle(Messages.ICalTransfer_exportAgendaMandator);
setMessage(Messages.ICalTransfer_pleaseSelectDateAndMandator);
getButton(IDialogConstants.OK_ID).setEnabled(false);
}
@Override
protected void okPressed(){
von.setTimeInMillis(dpVon.getDate().getTime());
bis.setTimeInMillis(dpBis.getDate().getTime());
Query<Termin> qbe = new Query<Termin>(Termin.class);
qbe.add(Termin.FLD_TAG, Query.GREATER_OR_EQUAL, von.toString(TimeTool.DATE_COMPACT));
qbe.add(Termin.FLD_TAG, Query.LESS_OR_EQUAL, bis.toString(TimeTool.DATE_COMPACT));
qbe.add(Termin.FLD_BEREICH, Query.EQUALS, m);
List<Termin> termine = qbe.execute();
String fname = lFile.getText();
if (fname.toLowerCase().endsWith(".csv")) { //$NON-NLS-1$
new CSVExporter().doExport(fname, termine);
} else {
TimeZoneRegistry registry = TimeZoneRegistryFactory.getInstance().createRegistry();
TimeZone timezone = registry.getTimeZone("Europe/Zurich"); //$NON-NLS-1$
VTimeZone tz = timezone.getVTimeZone();
Calendar calendar = new Calendar();
calendar.getProperties().add(new ProdId("-//ch.elexis//Elexis v" + CoreHub.Version)); //$NON-NLS-1$
calendar.getProperties().add(Version.VERSION_2_0);
calendar.getProperties().add(CalScale.GREGORIAN);
for (Termin t : termine) {
if ((t.getStartMinute() == 0) && (t.getType().equals(Termin.typReserviert()))) {
continue;
}
if ((t.getStartMinute() + t.getDurationInMinutes() == (23 * 60) + 59)
&& (t.getType().equals(Termin.typReserviert()))) {
continue;
}
TimeTool tt = new TimeTool(t.getStartTime());
DateTime start = new DateTime(tt.getTime());
tt.addMinutes(t.getDurationInMinutes());
DateTime end = new DateTime(tt.getTime());
VEvent vTermin = new VEvent(start, end, t.getPersonalia());
vTermin.getProperties().add(tz.getTimeZoneId());
Uid uid = new Uid(t.getId());
vTermin.getProperties().add(uid);
Description desc = new Description(t.getGrund());
vTermin.getProperties().add(desc);
calendar.getComponents().add(vTermin);
}
try {
FileOutputStream fout = new FileOutputStream(lFile.getText());
CalendarOutputter outputter = new CalendarOutputter();
outputter.output(calendar, fout);
} catch (Exception ex) {
ExHandler.handle(ex);
SWTHelper.alert(
Messages.ICalTransfer_iOError,
MessageFormat.format(Messages.ICalTransfer_couldNotWriteFile,
lFile.getText()));
}
}
super.okPressed();
}
}
}