Java tutorial
/*---------------- FILE HEADER KALYPSO ------------------------------------------ * * This file is part of kalypso. * Copyright (C) 2004 by: * * Technical University Hamburg-Harburg (TUHH) * Institute of River and coastal engineering * Denickestrae 22 * 21073 Hamburg, Germany * http://www.tuhh.de/wb * * and * * Bjoernsen Consulting Engineers (BCE) * Maria Trost 3 * 56070 Koblenz, Germany * http://www.bjoernsen.de * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: * * E-Mail: * belger@bjoernsen.de * schlienger@bjoernsen.de * v.doemming@tuhh.de * * ---------------------------------------------------------------------------*/ package org.kalypso.kalypsomodel1d2d.ui.map.flowrel; import java.math.BigDecimal; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.TimeZone; import javax.xml.datatype.XMLGregorianCalendar; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.dialogs.DialogPage; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.ComboViewer; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.window.Window; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import org.kalypso.commons.math.LinearEquation; import org.kalypso.commons.math.LinearEquation.SameXValuesException; import org.kalypso.contribs.eclipse.core.runtime.StatusUtilities; import org.kalypso.contribs.eclipse.jface.dialog.DialogPageUtilitites; import org.kalypso.contribs.java.util.CalendarUtilities.FIELD; import org.kalypso.contribs.java.util.DateUtilities; import org.kalypso.core.KalypsoCorePlugin; import org.kalypso.kalypsomodel1d2d.KalypsoModel1D2DPlugin; import org.kalypso.kalypsomodel1d2d.ui.i18n.Messages; import org.kalypso.observation.IObservation; import org.kalypso.observation.phenomenon.Phenomenon; import org.kalypso.observation.result.IComponent; import org.kalypso.observation.result.IRecord; import org.kalypso.observation.result.TupleResult; import org.kalypso.util.swtcalendar.SWTCalendarDialog; /** * Constructs a simple timeserie with a time column and a value column. * * @author Gernot Belger */ public class TimeserieStepDescriptor implements IBoundaryConditionDescriptor { private final DateFormat m_dateTimeFormat = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss.SSS"); //$NON-NLS-1$ private final DateFormat m_dateFormat = new SimpleDateFormat("dd.MM.yyyy 00:00:00.000"); //$NON-NLS-1$ private static final String DEFAULTSTEP = "1"; //$NON-NLS-1$ private static final String DEFAULT_VALUE = "20.0"; //$NON-NLS-1$ protected final Date[] m_dates = new Date[2]; private Integer m_stepValue; private BigDecimal m_fromValue; private BigDecimal m_toValue; private WizardPage m_page; private final String m_domainComponentUrn; private final String m_valueComponentUrn; private final String m_name; private int m_field = Calendar.MINUTE; private static final String MSG_PAGE = Messages .getString("org.kalypso.kalypsomodel1d2d.ui.map.flowrel.TimeserieStepDescriptor.4"); //$NON-NLS-1$ private final int m_valueScale; public TimeserieStepDescriptor(final String name, final String domainComponentUrn, final String valueComponentUrn, final int valueScale) { m_name = name; m_domainComponentUrn = domainComponentUrn; m_valueComponentUrn = valueComponentUrn; m_valueScale = valueScale; final TimeZone timeZone = KalypsoCorePlugin.getDefault().getTimeZone(); m_dateTimeFormat.setTimeZone(timeZone); m_dateFormat.setTimeZone(timeZone); } @Override public Control createControl(final Composite parent, final WizardPage page) { m_page = page; final Composite container = new Composite(parent, SWT.NULL); final GridLayout gridLayout = new GridLayout(3, false); container.setLayout(gridLayout); createDateEntryLine(container, Messages.getString("org.kalypso.kalypsomodel1d2d.ui.map.flowrel.TimeserieStepDescriptor.5"), 0, 0); //$NON-NLS-1$ createDateEntryLine(container, Messages.getString("org.kalypso.kalypsomodel1d2d.ui.map.flowrel.TimeserieStepDescriptor.6"), 1, 24); //$NON-NLS-1$ final Label stepLabel = new Label(container, SWT.NONE); stepLabel.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false)); stepLabel.setText( Messages.getString("org.kalypso.kalypsomodel1d2d.ui.map.flowrel.TimeserieStepDescriptor.7")); //$NON-NLS-1$ final Text dateTimeStep = new Text(container, SWT.BORDER); dateTimeStep.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); dateTimeStep.addModifyListener(new ModifyListener() { @Override public void modifyText(final ModifyEvent e) { final String text = dateTimeStep.getText(); handleStepChanged(text); } }); dateTimeStep.setText(DEFAULTSTEP); final ComboViewer comboViewer = new ComboViewer(container, SWT.DROP_DOWN | SWT.READ_ONLY); comboViewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); comboViewer.setContentProvider(new ArrayContentProvider()); comboViewer.setLabelProvider(new LabelProvider() { @Override public String getText(final Object element) { return ((FIELD) element).getAddLabel(); } }); comboViewer.setInput(new Object[] { FIELD.WEEK_OF_YEAR, FIELD.DAY_OF_YEAR, FIELD.HOUR, FIELD.MINUTE, FIELD.SECOND, FIELD.MILLISECOND }); comboViewer.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(final SelectionChangedEvent event) { final int field = ((FIELD) ((IStructuredSelection) event.getSelection()).getFirstElement()) .getField(); handleFieldChanged(field); } }); comboViewer.setSelection(new StructuredSelection(FIELD.MINUTE), true); final Label labelFromValue = new Label(container, SWT.NONE); labelFromValue.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false)); labelFromValue.setText( Messages.getString("org.kalypso.kalypsomodel1d2d.ui.map.flowrel.TimeserieStepDescriptor.8")); //$NON-NLS-1$ final Text defaultFromValue = new Text(container, SWT.BORDER); defaultFromValue.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); defaultFromValue.addModifyListener(new ModifyListener() { @Override public void modifyText(final ModifyEvent e) { final String text = defaultFromValue.getText(); handleFromValueChanged(text); } }); defaultFromValue.setText(DEFAULT_VALUE); new Label(container, SWT.NONE).setText(""); //$NON-NLS-1$ final Label labelToValue = new Label(container, SWT.NONE); labelToValue.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false)); labelToValue.setText( Messages.getString("org.kalypso.kalypsomodel1d2d.ui.map.flowrel.TimeserieStepDescriptor.10")); //$NON-NLS-1$ final Text defaultToValue = new Text(container, SWT.BORDER); defaultToValue.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); defaultToValue.addModifyListener(new ModifyListener() { @Override public void modifyText(final ModifyEvent e) { final String text = defaultToValue.getText(); handleToValueChanged(text); } }); defaultToValue.setText(DEFAULT_VALUE); new Label(container, SWT.NONE).setText(""); //$NON-NLS-1$ updatePageState(Status.OK_STATUS); return container; } private void createDateEntryLine(final Composite parent, final String label, final int index, final int dateOffset) { final Label labelFrom = new Label(parent, SWT.NONE); labelFrom.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false)); labelFrom.setText(label); final Text dateText = new Text(parent, SWT.BORDER); dateText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); dateText.addModifyListener(new ModifyListener() { @Override public void modifyText(final ModifyEvent e) { final String text = dateText.getText(); handleDateChanged(index, text); } }); final Calendar cal = Calendar.getInstance(); cal.add(Calendar.HOUR, dateOffset); dateText.setText(m_dateFormat.format(cal.getTime())); final Button buttonDateTimeFrom = new Button(parent, SWT.NONE); buttonDateTimeFrom.setText("..."); //$NON-NLS-1$ buttonDateTimeFrom.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { onDateTimeFromPressed(dateText, parent.getShell(), index); } }); } protected void onDateTimeFromPressed(final Text dateText, final Shell shell, final int index) { final SWTCalendarDialog calendarDialog = new SWTCalendarDialog(shell, m_dates[index]); if (calendarDialog.open() == Window.OK) { final Date date = calendarDialog.getDate(); dateText.setText(m_dateFormat.format(date)); } } protected void updatePageState(final IStatus status) { final IStatus pageStatus = status.isOK() ? checkPageComplete() : status; if (pageStatus.isOK()) m_page.setMessage(MSG_PAGE, DialogPage.NONE); else m_page.setMessage(pageStatus.getMessage(), DialogPageUtilitites.severityToMessagecode(pageStatus)); m_page.setPageComplete(pageStatus.isOK()); } private IStatus checkPageComplete() { if (m_dates[0] == null) return new Status(IStatus.WARNING, KalypsoModel1D2DPlugin.PLUGIN_ID, Messages.getString("org.kalypso.kalypsomodel1d2d.ui.map.flowrel.TimeserieStepDescriptor.13")); //$NON-NLS-1$ if (m_dates[1] == null) return new Status(IStatus.WARNING, KalypsoModel1D2DPlugin.PLUGIN_ID, Messages.getString("org.kalypso.kalypsomodel1d2d.ui.map.flowrel.TimeserieStepDescriptor.14")); //$NON-NLS-1$ if (m_stepValue == null) return new Status(IStatus.WARNING, KalypsoModel1D2DPlugin.PLUGIN_ID, Messages.getString("org.kalypso.kalypsomodel1d2d.ui.map.flowrel.TimeserieStepDescriptor.15")); //$NON-NLS-1$ if (m_fromValue == null) return new Status(IStatus.WARNING, KalypsoModel1D2DPlugin.PLUGIN_ID, Messages.getString("org.kalypso.kalypsomodel1d2d.ui.map.flowrel.TimeserieStepDescriptor.16")); //$NON-NLS-1$ if (m_toValue == null) return new Status(IStatus.WARNING, KalypsoModel1D2DPlugin.PLUGIN_ID, Messages.getString("org.kalypso.kalypsomodel1d2d.ui.map.flowrel.TimeserieStepDescriptor.17")); //$NON-NLS-1$ if (!m_dates[0].before(m_dates[1])) return new Status(IStatus.WARNING, KalypsoModel1D2DPlugin.PLUGIN_ID, Messages.getString("org.kalypso.kalypsomodel1d2d.ui.map.flowrel.TimeserieStepDescriptor.18")); //$NON-NLS-1$ return Status.OK_STATUS; } protected BigDecimal interpolateValue(final GregorianCalendar calendar) { /* Linear interpolation */ final XMLGregorianCalendar from = DateUtilities.toXMLGregorianCalendar(m_dates[0]); final XMLGregorianCalendar to = DateUtilities.toXMLGregorianCalendar(m_dates[1]); final long before = from.toGregorianCalendar().getTimeInMillis(); final long after = to.toGregorianCalendar().getTimeInMillis(); final long dom = calendar.getTimeInMillis(); final double valBefore = ((Number) m_fromValue).doubleValue(); final double valAfter = ((Number) m_toValue).doubleValue(); try { final LinearEquation equation = new LinearEquation(before, valBefore, after, valAfter); final double value = equation.computeY(dom); // IMPORTANT: we use a specific scale here! The scale must be the same, as used in the user interface (observation table). Else // we get hidden digits, that will be truncated as soon as the user clicks a cell -> calculation result changes and it is not clear why.... return new BigDecimal(value).setScale(m_valueScale, BigDecimal.ROUND_HALF_UP); } catch (final SameXValuesException e) { e.printStackTrace(); return null; } } @Override public void activate() { m_page.setTitle( Messages.getString("org.kalypso.kalypsomodel1d2d.ui.map.flowrel.TimeserieStepDescriptor.19")); //$NON-NLS-1$ m_page.setDescription(MSG_PAGE); updatePageState(Status.OK_STATUS); } @Override public void fillObservation(final IObservation<TupleResult> obs) { final TupleResult result = obs.getResult(); obs.setName(getName()); obs.setPhenomenon(new Phenomenon( "urn:ogc:gml:dict:kalypso:model:1d2d:timeserie:phenomenons#TimeserieBorderCondition1D", null, //$NON-NLS-1$ null)); final IComponent[] components = result.getComponents(); final IComponent domainComponent = components[0]; final IComponent valueComponent = components[1]; result.setSortComponents(new IComponent[] { domainComponent }); final GregorianCalendar calendarFrom = new GregorianCalendar(); final GregorianCalendar calendarTo = new GregorianCalendar(); calendarFrom.setTime(m_dates[0]); calendarTo.setTime(m_dates[1]); while (!calendarFrom.after(calendarTo)) { final IRecord record = result.createRecord(); record.setValue(domainComponent, DateUtilities.toXMLGregorianCalendar(calendarFrom)); // TODO: interpolate value final BigDecimal value = interpolateValue(calendarFrom); if (value != null) { record.setValue(valueComponent, value); result.add(record); } calendarFrom.add(m_field, m_stepValue); } } @Override public String getName() { return m_name; } protected void handleStepChanged(final String text) throws NumberFormatException { IStatus status = Status.OK_STATUS; try { m_stepValue = new Integer(text); } catch (final Throwable t) { status = StatusUtilities.statusFromThrowable(t, Messages.getString("org.kalypso.kalypsomodel1d2d.ui.map.flowrel.TimeserieStepDescriptor.21")); //$NON-NLS-1$ m_stepValue = null; } updatePageState(status); } protected void handleFromValueChanged(final String text) throws NumberFormatException { IStatus status = Status.OK_STATUS; try { m_fromValue = new BigDecimal(text); } catch (final Throwable t) { status = StatusUtilities.statusFromThrowable(t, Messages.getString("org.kalypso.kalypsomodel1d2d.ui.map.flowrel.TimeserieStepDescriptor.22")); //$NON-NLS-1$ m_fromValue = null; } updatePageState(status); } protected void handleToValueChanged(final String text) throws NumberFormatException { IStatus status = Status.OK_STATUS; try { m_toValue = new BigDecimal(text); } catch (final Throwable t) { status = StatusUtilities.statusFromThrowable(t, Messages.getString("org.kalypso.kalypsomodel1d2d.ui.map.flowrel.TimeserieStepDescriptor.23")); //$NON-NLS-1$ m_toValue = null; } updatePageState(status); } protected void handleDateChanged(final int index, final String text) { IStatus status = Status.OK_STATUS; try { m_dates[index] = m_dateTimeFormat.parse(text); } catch (final Throwable t) { status = StatusUtilities.statusFromThrowable(t, Messages.getString("org.kalypso.kalypsomodel1d2d.ui.map.flowrel.TimeserieStepDescriptor.24") //$NON-NLS-1$ + m_dateFormat.format(new Date())); m_dates[index] = null; } updatePageState(status); } protected void handleFieldChanged(final int field) { m_field = field; updatePageState(Status.OK_STATUS); } @Override public String getDomainComponentUrn() { return m_domainComponentUrn; } @Override public String getValueComponentUrn() { return m_valueComponentUrn; } }