org.kalypso.ogc.sensor.diagview.DiagViewUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.kalypso.ogc.sensor.diagview.DiagViewUtils.java

Source

/*--------------- Kalypso-Header --------------------------------------------------------------------
    
 This file is part of kalypso.
 Copyright (C) 2004, 2005 by:
    
 Technical University Hamburg-Harburg (TUHH)
 Institute of River and coastal engineering
 Denickestr. 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.ogc.sensor.diagview;

import java.awt.BasicStroke;
import java.awt.Stroke;
import java.io.BufferedWriter;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TimeZone;
import java.util.logging.Logger;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.kalypso.commons.bind.JaxbUtilities;
import org.kalypso.commons.java.util.StringUtilities;
import org.kalypso.commons.xml.NS;
import org.kalypso.contribs.eclipse.core.runtime.StatusUtilities;
import org.kalypso.ogc.sensor.IAxis;
import org.kalypso.ogc.sensor.IObservation;
import org.kalypso.ogc.sensor.metadata.ITimeseriesConstants;
import org.kalypso.ogc.sensor.template.ObsView;
import org.kalypso.ogc.sensor.template.ObsViewItem;
import org.kalypso.ogc.sensor.template.ObsViewUtils;
import org.kalypso.ogc.sensor.timeseries.TimeseriesUtils;
import org.kalypso.template.obsdiagview.ObjectFactory;
import org.kalypso.template.obsdiagview.Obsdiagview;
import org.kalypso.template.obsdiagview.Obsdiagview.Legend;
import org.kalypso.template.obsdiagview.TypeAxis;
import org.kalypso.template.obsdiagview.TypeCurve;
import org.kalypso.template.obsdiagview.TypeCurve.Mapping;
import org.kalypso.template.obsdiagview.TypeDirection;
import org.kalypso.template.obsdiagview.TypeObservation;
import org.kalypso.template.obsdiagview.TypePosition;
import org.kalypso.ui.internal.i18n.Messages;
import org.xml.sax.InputSource;

/**
 * Observation Diagramm Template Handling made easy.
 * 
 * @author schlienger
 */
public class DiagViewUtils {
    public final static String ODT_FILE_EXTENSION = "odt"; //$NON-NLS-1$

    private final static ObjectFactory ODT_OF = new ObjectFactory();

    private final static JAXBContext ODT_JC = JaxbUtilities.createQuiet(ObjectFactory.class);

    /**
     * Not to be instanciated
     */
    private DiagViewUtils() {
        // empty
    }

    /**
     * Saves the given template (binding). Closes the stream.
     */
    public static void saveDiagramTemplateXML(final Obsdiagview xml, final BufferedWriter outDiag)
            throws JAXBException {
        try {
            final Marshaller m = createMarshaller();
            m.marshal(xml, outDiag);
        } finally {
            IOUtils.closeQuietly(outDiag);
        }
    }

    protected static Marshaller createMarshaller() throws JAXBException {
        final Map<String, String> prefixMapping = new HashMap<>();
        prefixMapping.put(NS.KALYPSO_OBSVIEW, ""); //$NON-NLS-1$
        return JaxbUtilities.createMarshaller(ODT_JC, true, prefixMapping);
    }

    /**
     * Saves the given template (binding). Closes the writer.
     */
    public static void saveDiagramTemplateXML(final Obsdiagview tpl, final OutputStreamWriter writer)
            throws JAXBException {
        try {

            final Marshaller m = createMarshaller();
            String encoding = writer.getEncoding();
            // HACK: rename utf8 encoding, esle xml editor will not validate
            if ("UTF8".equals(encoding)) //$NON-NLS-1$
                encoding = "UTF-8"; //$NON-NLS-1$

            m.setProperty(Marshaller.JAXB_ENCODING, encoding);

            m.marshal(tpl, writer);
        } finally {
            IOUtils.closeQuietly(writer);
        }
    }

    /**
     * Loads a binding template. Closes the stream.
     * 
     * @return diagram template object parsed from the file
     */
    public static Obsdiagview loadDiagramTemplateXML(final InputStream ins) throws JAXBException {
        try {
            return loadDiagramTemplateXML(new InputSource(ins));
        } finally {
            IOUtils.closeQuietly(ins);
        }
    }

    /**
     * Loads a binding template. Closes the stream.
     * 
     * @return diagram template object parsed from the file
     */
    public static Obsdiagview loadDiagramTemplateXML(final Reader reader) throws JAXBException {
        try {
            return loadDiagramTemplateXML(new InputSource(reader));
        } finally {
            IOUtils.closeQuietly(reader);
        }
    }

    /**
     * Loads a binding template. Closes the stream.
     * 
     * @return diagram template object parsed from the file
     */
    private static Obsdiagview loadDiagramTemplateXML(final InputSource ins) throws JAXBException {
        return (Obsdiagview) ODT_JC.createUnmarshaller().unmarshal(ins);
    }

    /**
     * Builds the xml binding object using the given diagram view template
     * 
     * @return xml binding object (ready for marshalling for instance)
     */
    public static Obsdiagview buildDiagramTemplateXML(final DiagView view, final IContainer context) {
        final Obsdiagview xmlTemplate = ODT_OF.createObsdiagview();

        final Legend xmlLegend = ODT_OF.createObsdiagviewLegend();
        xmlLegend.setTitle(view.getLegendName());
        xmlLegend.setVisible(view.isShowLegend());

        xmlTemplate.setLegend(xmlLegend);
        xmlTemplate.setTitle(view.getTitle());
        xmlTemplate.setTitleFormat(view.getTitleFormat());

        // only set timezone if defined
        final TimeZone timezone = view.getTimezone();
        if (timezone != null)
            xmlTemplate.setTimezone(timezone.getID());

        final List<TypeAxis> xmlAxes = xmlTemplate.getAxis();

        final DiagramAxis[] diagramAxes = view.getDiagramAxes();
        for (final DiagramAxis axis : diagramAxes) {
            final TypeAxis xmlAxis = ODT_OF.createTypeAxis();
            xmlAxis.setDatatype(axis.getDataType());
            xmlAxis.setDirection(TypeDirection.fromValue(axis.getDirection()));
            xmlAxis.setId(axis.getIdentifier());
            xmlAxis.setInverted(axis.isInverted());
            xmlAxis.setLabel(axis.getLabel());
            xmlAxis.setPosition(TypePosition.fromValue(axis.getPosition()));
            xmlAxis.setUnit(axis.getUnit());

            xmlAxes.add(xmlAxis);
        }

        xmlTemplate.setFeatures(StringUtils.join(view.getEnabledFeatures(), ';'));

        int ixCurve = 1;

        final List<TypeObservation> xmlThemes = xmlTemplate.getObservation();
        final Map<IObservation, ArrayList<ObsViewItem>> map = ObsView.mapItems(view.getItems());
        for (final Entry<IObservation, ArrayList<ObsViewItem>> entry : map.entrySet()) {
            final IObservation obs = entry.getKey();
            if (obs == null)
                continue;

            final TypeObservation xmlTheme = ODT_OF.createTypeObservation();

            final String href = obs.getHref();
            final String xmlHref = ObsViewUtils.makeRelativ(context, href);
            xmlTheme.setHref(xmlHref);

            xmlTheme.setLinktype("zml"); //$NON-NLS-1$

            final List<TypeCurve> xmlCurves = xmlTheme.getCurve();

            final Iterator<ObsViewItem> itCurves = ((List<ObsViewItem>) entry.getValue()).iterator();
            while (itCurves.hasNext()) {
                final DiagViewCurve curve = (DiagViewCurve) itCurves.next();

                final TypeCurve xmlCurve = ODT_OF.createTypeCurve();
                xmlCurve.setId("C" + ixCurve++); //$NON-NLS-1$
                xmlCurve.setName(curve.getName());
                xmlCurve.setColor(StringUtilities.colorToString(curve.getColor()));
                xmlCurve.setShown(curve.isShown());
                final Stroke stroke = curve.getStroke();
                if (stroke instanceof BasicStroke) {
                    final BasicStroke bs = (BasicStroke) stroke;
                    final TypeCurve.Stroke strokeType = ODT_OF.createTypeCurveStroke();
                    xmlCurve.setStroke(strokeType);
                    strokeType.setWidth(bs.getLineWidth());
                    final float[] dashArray = bs.getDashArray();
                    if (dashArray != null) {
                        final List<Float> dashList = strokeType.getDash();
                        for (final float element : dashArray)
                            dashList.add(new Float(element));
                    }
                }

                final List<Mapping> xmlMappings = xmlCurve.getMapping();

                final AxisMapping[] mappings = curve.getMappings();
                for (final AxisMapping mapping : mappings) {
                    final Mapping xmlMapping = ODT_OF.createTypeCurveMapping();
                    xmlMapping.setDiagramAxis(mapping.getDiagramAxis().getIdentifier());
                    xmlMapping.setObservationAxis(mapping.getObservationAxis().getName());

                    xmlMappings.add(xmlMapping);
                }

                xmlCurves.add(xmlCurve);
            }

            xmlThemes.add(xmlTheme);
        }

        return xmlTemplate;
    }

    /**
     * Creates a diagram axis according to the given IObservation axis
     * 
     * @return diagram axis
     */
    public static DiagramAxis createAxisFor(final IAxis axis) {
        return createAxisFor(axis.getType(), axis.getName(), axis.getUnit(), axis.isKey());
    }

    /**
     * Creates a diagram axis according to the given IObservation axis
     * 
     * @return diagram axis
     */
    public static DiagramAxis createAxisFor(final String axisType, final String label, final String unit,
            final boolean isKey) {
        final String direction = isKey == true ? DiagramAxis.DIRECTION_HORIZONTAL : DiagramAxis.DIRECTION_VERTICAL;
        String position = isKey == true ? DiagramAxis.POSITION_BOTTOM : DiagramAxis.POSITION_LEFT;

        // TODO: move this stuff into config.properties as everything else

        if (axisType.equals(ITimeseriesConstants.TYPE_DATE))
            return new DiagramAxis(axisType, "date", null, unit, direction, position, false); //$NON-NLS-1$

        if (axisType.equals(ITimeseriesConstants.TYPE_HOURS))
            return new DiagramAxis(axisType, "double", label, unit, direction, position, false); //$NON-NLS-1$

        if (axisType.equals(ITimeseriesConstants.TYPE_WATERLEVEL))
            return new DiagramAxis(axisType, "double", label, unit, direction, position, false); //$NON-NLS-1$

        if (axisType.equals(ITimeseriesConstants.TYPE_NORMNULL))
            return new DiagramAxis(axisType, "double", label, unit, direction, position, false); //$NON-NLS-1$

        if (axisType.equals(ITimeseriesConstants.TYPE_RUNOFF))
            return new DiagramAxis(axisType, "double", label, unit, direction, position, false); //$NON-NLS-1$

        if (axisType.equals(ITimeseriesConstants.TYPE_RUNOFF_RHB))
            return new DiagramAxis(axisType, "double", label, unit, direction, position, false); //$NON-NLS-1$

        if (axisType.equals(ITimeseriesConstants.TYPE_VOLUME))
            return new DiagramAxis(axisType, "double", label, unit, direction, position, false); //$NON-NLS-1$

        if (axisType.equals(ITimeseriesConstants.TYPE_NORM))
            return new DiagramAxis(axisType, "double", label, unit, direction, position, false); //$NON-NLS-1$

        if (axisType.equals(ITimeseriesConstants.TYPE_POLDER_CONTROL))
            return new DiagramAxis(axisType, "boolean", label, unit, direction, position, false); //$NON-NLS-1$

        position = isKey == true ? DiagramAxis.POSITION_BOTTOM : DiagramAxis.POSITION_RIGHT;

        if (axisType.equals(ITimeseriesConstants.TYPE_RAINFALL))
            return new DiagramAxis(axisType, "double", label, unit, direction, position, true, null, TimeseriesUtils //$NON-NLS-1$
                    .getTopMargin(axisType)); //$NON-NLS-1$

        if (axisType.equals(ITimeseriesConstants.TYPE_TEMPERATURE))
            return new DiagramAxis(axisType, "double", label, unit, direction, position, false); //$NON-NLS-1$

        if (axisType.equals(ITimeseriesConstants.TYPE_EVAPORATION))
            return new DiagramAxis(axisType, "double", label, unit, direction, position, false); //$NON-NLS-1$

        position = isKey == true ? DiagramAxis.POSITION_BOTTOM : DiagramAxis.POSITION_LEFT;

        // default axis
        return new DiagramAxis(axisType, "double", label, unit, direction, position, false); //$NON-NLS-1$
    }

    /**
     * Apply the given xml-template representation to the diagview.
     * 
     * @param ignoreHref
     *          [optional] tricky, used in the context of the wizard where token replace takes place. If a href could not
     *          be replaced, it is set to a specific tag-value and the ignoreHref parameter if specified denotes is
     *          compared to each href found in the template. If it is found, then the href is ignored and the
     *          corresponding observation isn't loaded.
     */
    public static IStatus applyXMLTemplate(final DiagView view, final Obsdiagview xml, final URL context,
            final boolean synchron, final String ignoreHref) {
        view.removeAllItems();

        view.setTitle(xml.getTitle(), xml.getTitleFormat());
        view.setLegendName(xml.getLegend() == null ? "" : xml.getLegend().getTitle()); //$NON-NLS-1$
        view.setShowLegend(xml.getLegend() == null ? false : xml.getLegend().isVisible());

        // features-list is optional
        if (xml.getFeatures() != null) {
            // features list specified, so clear before enabling the ones sepcified
            view.clearFeatures();

            final String[] featureNames = xml.getFeatures().split(";"); //$NON-NLS-1$
            for (final String featureName : featureNames)
                view.setFeatureEnabled(featureName, true);
        }

        // timezone is optional
        final String xmlTz = xml.getTimezone();
        if (xmlTz != null && xmlTz.length() > 0) {
            final TimeZone timeZone = TimeZone.getTimeZone(xmlTz);
            view.setTimezone(timeZone);
        }

        // axes spec is optional
        if (xml.getAxis() != null) {
            for (final TypeAxis baseAxis : xml.getAxis()) {
                view.addAxis(new DiagramAxis(baseAxis));
            }
        }

        final List<IStatus> stati = new ArrayList<>();

        final List<TypeObservation> list = xml.getObservation();
        for (final TypeObservation tobs : list) {
            // check, if href is ok
            final String href = tobs.getHref();

            // Hack: elemente, die durch token-replace nicht richtig aufgelst werden einfach bergehen
            if (ignoreHref != null && href.indexOf(ignoreHref) != -1) {
                Logger.getLogger(DiagViewUtils.class.getName())
                        .warning(Messages.getString("org.kalypso.ogc.sensor.diagview.DiagViewUtils.16") + href); //$NON-NLS-1$
                continue;
            }

            final DiagViewCurveXMLLoader loader = new DiagViewCurveXMLLoader(view, tobs, context, synchron);
            final IStatus result = loader.getResult();
            if (!result.isOK())
                stati.add(result);
        }

        if (stati.size() == 0)
            return Status.OK_STATUS;
        else if (stati.size() == 1)
            return stati.get(0);
        else
            return StatusUtilities.createStatus(stati,
                    Messages.getString("org.kalypso.ogc.sensor.diagview.DiagViewUtils.17")); //$NON-NLS-1$
    }

    /**
     * Return the first axis of the mappings list which is not a key axis.
     * 
     * @param mappings
     *          array of obs-diag axes mappings
     * @return obs axis (not a key axis) or null if not found
     */
    public static IAxis getValueAxis(final AxisMapping[] mappings) {
        for (int i = 0; i < mappings.length; i++) {
            if (!mappings[i].getObservationAxis().isKey())
                return mappings[i].getObservationAxis();
        }

        return null;
    }
}