view artifacts/src/main/java/org/dive4elements/river/exports/HistoricalDischargeCurveGenerator.java @ 9556:9b8e8fc1f408

Use facetName in all processors as themeType for legend aggregation.
author gernotbelger
date Tue, 23 Oct 2018 16:26:58 +0200
parents 740d65e4aa14
children
line wrap: on
line source
/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
 * Software engineering by Intevation GmbH
 *
 * This file is Free Software under the GNU AGPL (>=v3)
 * and comes with ABSOLUTELY NO WARRANTY! Check out the
 * documentation coming with Dive4Elements River for details.
 */

package org.dive4elements.river.exports;

import java.util.Date;

import org.apache.log4j.Logger;
import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
import org.dive4elements.artifacts.CallContext;
import org.dive4elements.river.artifacts.D4EArtifact;
import org.dive4elements.river.artifacts.access.HistoricalDischargeAccess;
import org.dive4elements.river.artifacts.model.FacetTypes;
import org.dive4elements.river.artifacts.model.HistoricalWQTimerange;
import org.dive4elements.river.artifacts.model.Timerange;
import org.dive4elements.river.artifacts.model.WQTimerange;
import org.dive4elements.river.jfree.StyledTimeSeries;
import org.dive4elements.river.themes.ThemeDocument;
import org.dive4elements.river.utils.RiverUtils;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.general.SeriesException;
import org.jfree.data.time.FixedMillisecond;
import org.jfree.data.time.RegularTimePeriod;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;

/**
 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
 */
public class HistoricalDischargeCurveGenerator extends TimeseriesChartGenerator implements FacetTypes {

    private static Logger log = Logger.getLogger(HistoricalDischargeCurveGenerator.class);

    public static final String I18N_CHART_TITLE = "chart.historical.discharge.title";

    public static final String I18N_CHART_SUBTITLE = "chart.historical.discharge.subtitle";

    public static final String I18N_XAXIS_LABEL = "chart.historical.discharge.xaxis.label";

    public static final String I18N_YAXIS_LABEL = "chart.historical.discharge.yaxis.label";

    public static final String I18N_YAXIS_SECOND_LABEL = "common.export.csv.header.q";

    public static enum YAXIS {
        W(0), Q(1);

        protected int idx;

        private YAXIS(final int c) {
            this.idx = c;
        }
    }

    @Override
    protected YAxisWalker getYAxisWalker() {
        return new YAxisWalker() {

            @Override
            public int length() {
                return YAXIS.values().length;
            }

            @Override
            public String getId(final int idx) {
                final YAXIS[] yaxes = YAXIS.values();
                return yaxes[idx].toString();
            }
        };
    }

    @Override
    protected String getDefaultChartTitle(final CallContext context) {
        return msg(I18N_CHART_TITLE, I18N_CHART_TITLE);
    }

    @Override
    protected String getDefaultChartSubtitle(final CallContext context) {
        final D4EArtifact flys = getArtifact();
        final Timerange evalTime = new HistoricalDischargeAccess(flys).getEvaluationTimerange();

        final Object[] args = new Object[] { RiverUtils.getReferenceGaugeName(flys), evalTime.getStart(), evalTime.getEnd() };

        return msg(I18N_CHART_SUBTITLE, "", args);
    }

    @Override
    protected String getDefaultXAxisLabel(final CallContext context) {
        return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL);
    }

    @Override
    protected String getDefaultYAxisLabel(final int pos) {
        if (pos == 0) {
            return msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL);
        } else if (pos == 1) {
            return msg(I18N_YAXIS_SECOND_LABEL, I18N_YAXIS_SECOND_LABEL);
        } else {
            return "NO TITLE FOR Y AXIS: " + pos;
        }
    }

    @Override
    protected void adjustPlot(final XYPlot plot) {
        super.adjustPlot(plot);
        plot.setRangeZeroBaselineVisible(true);
    }

    @Override
    public void doOut(final ArtifactAndFacet artifactFacet, final ThemeDocument theme, final boolean visible) {
        final String name = artifactFacet.getFacetName();
        String facetDescription = artifactFacet.getFacetDescription(); 

        log.debug("HistoricalDischargeCurveGenerator.doOut: " + name);
        log.debug("Theme description is: " + facetDescription);

        final CallContext context = getContext();

        if (name.equals(HISTORICAL_DISCHARGE_Q)) {
            doHistoricalDischargeOutQ(name, (D4EArtifact) artifactFacet.getArtifact(), artifactFacet.getData(context), facetDescription, theme,
                    visible);
        } else if (name.equals(HISTORICAL_DISCHARGE_W)) {
            doHistoricalDischargeOutW(name, (D4EArtifact) artifactFacet.getArtifact(), artifactFacet.getData(context), facetDescription, theme,
                    visible);
        } else if (name.equals(HISTORICAL_DISCHARGE_Q_DIFF)) {
            doHistoricalDischargeDifferenceOutQ(name, (D4EArtifact) artifactFacet.getArtifact(), artifactFacet.getData(context), facetDescription,
                    theme, visible);
        } else if (name.equals(HISTORICAL_DISCHARGE_W_DIFF)) {
            doHistoricalDischargeDifferenceOutW(name, (D4EArtifact) artifactFacet.getArtifact(), artifactFacet.getData(context), facetDescription,
                    theme, visible);
        } else if (FacetTypes.IS.MANUALPOINTS(name)) {
            final HistoricalDischargeAccess.EvaluationMode mode = new HistoricalDischargeAccess((D4EArtifact) getMaster()).getEvaluationMode();
            final int axis = mode == HistoricalDischargeAccess.EvaluationMode.W ? YAXIS.Q.idx : YAXIS.W.idx;

            doPoints(artifactFacet.getData(context), artifactFacet, theme, visible, axis);
        } else {
            log.warn("doOut(): unknown facet name: " + name);
            return;
        }
    }

    protected void doHistoricalDischargeOutQ(final String facetName, final D4EArtifact artifact, final Object data, final String desc, final ThemeDocument theme,
            final boolean visible) {
        log.debug("doHistoricalDischargeOut(): description = " + desc);

        final WQTimerange wqt = (WQTimerange) data;

        final TimeSeriesCollection tsc = newTimeSeriesCollection(facetName, wqt.getTimeranges(), wqt.getQs(), theme, desc);

        addAxisDataset(tsc, YAXIS.Q.idx, visible);
    }

    protected void doHistoricalDischargeOutW(final String facetName, final D4EArtifact artifact, final Object data, final String desc, final ThemeDocument theme,
            final boolean visible) {
        log.debug("doHistoricalDischargeOut(): description = " + desc);

        final WQTimerange wqt = (WQTimerange) data;

        final TimeSeriesCollection tsc = newTimeSeriesCollection(facetName, wqt.getTimeranges(), wqt.getWs(), theme, desc);

        addAxisDataset(tsc, YAXIS.W.idx, visible);
    }

    protected void doHistoricalDischargeDifferenceOutQ(final String facetName, final D4EArtifact artifact, final Object data, final String desc, final ThemeDocument theme,
            final boolean visible) {
        log.debug("doHistoricalDischargeDifferenceOut: desc = " + desc);

        final HistoricalWQTimerange wqt = (HistoricalWQTimerange) data;

        final TimeSeriesCollection tsc = newTimeSeriesCollection(facetName, wqt.getTimeranges(), wqt.getDiffs(), theme, desc);

        addAxisDataset(tsc, YAXIS.Q.idx, visible);
    }

    protected void doHistoricalDischargeDifferenceOutW(final String facetName, final D4EArtifact artifact, final Object data, final String desc, final ThemeDocument theme,
            final boolean visible) {
        log.debug("doHistoricalDischargeDifferenceOut: desc = " + desc);

        final HistoricalWQTimerange wqt = (HistoricalWQTimerange) data;

        final TimeSeriesCollection tsc = newTimeSeriesCollection(facetName, wqt.getTimeranges(), wqt.getDiffs(), theme, desc);

        addAxisDataset(tsc, YAXIS.W.idx, visible);
    }

    /**
     * Creates a new TimeSeriesCollection with a single TimeSeries. The
     * TimeSeries will consist of two RegularTimePeriods for each W/Q value
     * provided by <i>wqt</i>. This has the effect, that the line in the chart
     * looks like a "step chart".
     */
    protected TimeSeriesCollection newTimeSeriesCollection(final String facetName, final Timerange[] timeranges, final double[] values, final ThemeDocument theme, final String desc) {
        log.debug("Create new TimeSeriesCollection for: " + desc);

        final TimeSeriesCollection tsc = new TimeSeriesCollection();
        final TimeSeries series = new StyledTimeSeries(facetName, desc, theme);

        for (int i = 0, n = timeranges.length; i < n; i++) {
            final RegularTimePeriod[] rtp = newRegularTimePeriod(timeranges[i]);

            try {
                if (Double.isNaN(values[i])) {
                    log.warn("Skip TimePeriod because value is NaN.");
                    continue;
                }

                series.add(rtp[0], values[i]);
                series.add(rtp[1], values[i]);

                if (log.isDebugEnabled()) {
                    log.debug("added Item to TimeSeries:");
                    log.debug("   TimePeriod: " + rtp[0] + " - " + rtp[1]);
                    log.debug("   Value:      " + values[i]);
                }
            }
            catch (final SeriesException se) {
                log.warn("Error while adding TimePeriod: " + se);
            }
        }

        tsc.addSeries(series);

        return tsc;
    }

    /**
     * Create array that consists of two
     * <i>FixedMillisecond</i> periods [start, end].
     *
     * @param timerange
     *            Supports start and end time.
     *
     * @return an array with two <i>FixedMillisecond</i> periods [start, end].
     */
    protected RegularTimePeriod[] newRegularTimePeriod(final Timerange timerange) {
        final Date start = new Date(timerange.getStart());
        final Date end = new Date(timerange.getEnd() - 1000 * 60 * 60 * 24);

        return new RegularTimePeriod[] { new FixedMillisecond(start), new FixedMillisecond(end) };
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :

http://dive4elements.wald.intevation.org