view flys-artifacts/src/main/java/de/intevation/flys/exports/fixings/FixDeltaWtGenerator.java @ 3234:1aec30e75bcb

Very basic point labels in DeltaWt-diagrams. flys-artifacts/trunk@4865 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Felix Wolfsteller <felix.wolfsteller@intevation.de>
date Tue, 03 Jul 2012 14:39:56 +0000
parents abc2db630815
children 1cad94fa0817
line wrap: on
line source
package de.intevation.flys.exports.fixings;

import de.intevation.artifactdatabase.state.ArtifactAndFacet;

import de.intevation.artifacts.ArtifactNamespaceContext;
import de.intevation.artifacts.CallContext;

import de.intevation.artifacts.common.utils.XMLUtils;

import de.intevation.flys.artifacts.FLYSArtifact;

import de.intevation.flys.artifacts.model.DateRange;
import de.intevation.flys.artifacts.model.FacetTypes;

import de.intevation.flys.artifacts.model.fixings.QWD;

import de.intevation.flys.exports.TimeseriesChartGenerator;

import de.intevation.flys.jfree.CollisionFreeXYTextAnnotation;
import de.intevation.flys.jfree.FLYSAnnotation;
import de.intevation.flys.jfree.StyledTimeSeries;

import de.intevation.flys.utils.FLYSUtils;

import java.awt.BasicStroke;
import java.awt.Color;

import java.io.OutputStream;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.xpath.XPathConstants;

import org.apache.log4j.Logger;

import org.jfree.chart.JFreeChart;

import org.jfree.chart.annotations.XYTextAnnotation;

import org.jfree.chart.plot.IntervalMarker;
import org.jfree.chart.plot.ValueMarker;

import org.jfree.chart.title.TextTitle;

import org.jfree.data.time.Day;
import org.jfree.data.time.Month;
import org.jfree.data.time.RegularTimePeriod;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

/**
 * @author <a href="mailto:raimund.renkert@intevation.de">Raimund Renkert</a>
 */
public class FixDeltaWtGenerator
extends      TimeseriesChartGenerator
implements   FacetTypes
{
    private static Logger logger =
        Logger.getLogger(FixDeltaWtGenerator.class);

    public static final String XPATH_CHART_CURRENTKM =
        "/art:action/art:attributes/art:currentKm";

    public static final String I18N_CHART_TITLE =
        "chart.fix.deltawt.title";

    public static final String I18N_CHART_SUBTITLE =
        "chart.fix.deltawt.subtitle";

    public static final String I18N_XAXIS_LABEL =
        "chart.fix.deltawt.xaxis.label";

    public static final String I18N_YAXIS_LABEL =
        "chart.fix.deltawt.yaxis.label";

    public static final String I18N_YAXIS_SECOND_LABEL =
        "chart.fix.deltawt.yaxis.second.label";


    public static enum YAXIS {
        dW(0);
        protected int idx;
        private YAXIS(int c) {
            idx = c;
        }
    }


    @Override
    protected YAxisWalker getYAxisWalker() {
        return new YAxisWalker() {
            @Override
            public int length() {
                return YAXIS.values().length;
            }

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


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


    @Override
    protected String getDefaultChartSubtitle() {
        String[] args = new String[] {
            FLYSUtils.getReferenceGaugeName((FLYSArtifact) master)
        };

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


    /**
     * Empty (suppress subtitle).
     */
    @Override
    protected void addSubtitles(JFreeChart chart) {
        String subtitle = getChartSubtitle();

        if (subtitle != null && subtitle.length() > 0) {
            chart.addSubtitle(new TextTitle(subtitle));
        }
    }


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

    @Override
    protected String getDefaultYAxisLabel(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;
        }
    }


    public void doOut(
        ArtifactAndFacet artifactFacet,
        Document         theme,
        boolean          visible
    ) {
        String name = artifactFacet.getFacetName();
        logger.debug("FixDeltaWtGenerator.doOut: " + name);
        logger.debug("Theme description is: " + artifactFacet.getFacetDescription());

        if (name.contains(FIX_SECTOR_AVERAGE_DWT)) {
            doSectorAverageOut(
                (FLYSArtifact) artifactFacet.getArtifact(),
                artifactFacet.getData(context),
                artifactFacet.getFacetDescription(),
                theme,
                visible);
        }
        else if (name.equals(FIX_REFERENCE_EVENTS_DWT)) {
            doReferenceEventsOut(
                (FLYSArtifact) artifactFacet.getArtifact(),
                artifactFacet.getData(context),
                artifactFacet.getFacetDescription(),
                theme,
                visible);
        }
        else if (name.equals(FIX_ANALYSIS_EVENTS_DWT)) {
            doAnalysisEventsOut(
                (FLYSArtifact) artifactFacet.getArtifact(),
                artifactFacet.getData(context),
                artifactFacet.getFacetDescription(),
                theme,
                visible);
        }
        else if (name.equals(FIX_DEVIATION_DWT)) {
            doDeviationOut(
                (FLYSArtifact) artifactFacet.getArtifact(),
                artifactFacet.getData(context),
                artifactFacet.getFacetDescription(),
                theme,
                visible);
        }
        else if (name.equals(FIX_ANALYSIS_PERIODS_DWT)) {
            doAnalysisPeriodsOut(
                (FLYSArtifact) artifactFacet.getArtifact(),
                artifactFacet.getData(context),
                artifactFacet.getFacetDescription(),
                theme,
                visible);
        }
        else {
           logger.warn("doOut(): unknown facet name: " + name);
           return;
        }
    }


    protected void doSectorAverageOut(
        FLYSArtifact artifact,
        Object       data,
        String       desc,
        Document     theme,
        boolean      visible)
    {
        logger.debug("doSectorAverageOut(): description = " + desc);

        QWD qwd = (QWD) data;
        TimeSeriesCollection tsc = new TimeSeriesCollection();
        TimeSeries        series = new StyledTimeSeries(desc, theme);

        if (qwd == null) {
            return;
        }
        RegularTimePeriod rtp = new Day(qwd.getDate());
        double value = qwd.getDeltaW();
        series.add(rtp, value);
        tsc.addSeries(series);

        addAxisDataset(tsc, 0, visible);
        addAttribute(desc, "outline");
        Map<Integer, int[]> annoIdxMap = new HashMap<Integer, int[]>();
        annoIdxMap.put (0, new int[]{0,0});
        doQWDTextAnnotations(annoIdxMap, tsc, new QWD[]{qwd}, theme, visible);
    }


    protected void doAnalysisEventsOut(
        FLYSArtifact artifact,
        Object       data,
        String       desc,
        Document     theme,
        boolean      visible
    ) {
        logger.debug("doAnalysisEventsOut: desc = " + desc);

        QWD[] qwds = (QWD[]) data;
        TimeSeriesCollection tsc = new TimeSeriesCollection();

        TimeSeries   series = new StyledTimeSeries(desc, theme);
        TimeSeries interpol = new StyledTimeSeries(desc + "interpol", theme);

        if (qwds == null) {
            logger.debug("doAnalysisEventsOut: qwds == null");
            return;
        }

        if (qwds.length == 0) {
            logger.debug("doAnalysisEventsOut: qwds.length == 0");
            return;
        }

        Map<Integer, int[]> annoIdxMap = new HashMap<Integer, int[]>();

        for (int i = 0; i < qwds.length; i++) {
            if (qwds[i] == null) {
                logger.debug("doAnalysisEventsOut: qwds[" + i + "] == null");
                continue;
            }
            RegularTimePeriod rtp = new Day(qwds[i].getDate());
            double value =  qwds[i].getDeltaW();
            boolean interpolate = qwds[i].getInterpolated();
            if (interpolate) {
                interpol.add(rtp, value);
                annoIdxMap.put(
                    i,
                    new int[]{1, i});
            }
            else {
                series.add(rtp, value);
                annoIdxMap.put(
                    i,
                    new int[]{0, i});
            }
        }
        tsc.addSeries(series);
        tsc.addSeries(interpol);
        addAxisDataset(tsc, 0, visible);
        addAttribute(desc + "interpol", "interpolate");
        addAttribute(desc, "outline");

        doQWDTextAnnotations(annoIdxMap, tsc, qwds, theme, visible);
    }


    /**
     * @param annoIdxMap map of index in qwds to series/dataitem indices in tsc.
     */
    protected void doQWDTextAnnotations(Map<Integer, int[]> annoIdxMap,
            TimeSeriesCollection tsc, QWD[] qwds, Document theme,
            boolean visible) {
        List<XYTextAnnotation> textAnnos = new ArrayList<XYTextAnnotation>();
        Set<Map.Entry<Integer, int[]>> entries = annoIdxMap.entrySet();
        for(Map.Entry<Integer, int[]> entry : entries) {
            QWD qwd = qwds[entry.getKey()];
            int[] idxs = entry.getValue();
            double x = tsc.getXValue(idxs[0], idxs[1]);
            XYTextAnnotation anno = new CollisionFreeXYTextAnnotation(
                qwd.getQ() + " m\u00B3/s",
                x,
                qwd.getDeltaW());
            textAnnos.add(anno);
            logger.debug("annotation: " + x + "/" + qwd.getDeltaW());
        }

        FLYSAnnotation flysAnno = new FLYSAnnotation(null, null, null, theme);
        flysAnno.setTextAnnotations(textAnnos);
        addAnnotations(flysAnno, visible);
    }


    protected void doReferenceEventsOut(
        FLYSArtifact artifact,
        Object       data,
        String       desc,
        Document     theme,
        boolean      visible
    ) {
        logger.debug("doReferenceEventsOut: desc = " + desc);

        QWD[] qwds = (QWD[]) data;
        TimeSeriesCollection tsc = new TimeSeriesCollection();

        TimeSeries   series = new StyledTimeSeries(desc, theme);
        TimeSeries interpol = new StyledTimeSeries(desc + "interpol", theme);

        if (qwds == null) {
            return;
        }

        Map<Integer, int[]> annoIdxMap = new HashMap<Integer, int[]>();

        for (int i = 0; i < qwds.length; i++) {
            if (qwds[i] == null) {
                continue;
            }
            RegularTimePeriod rtp = new Day(qwds[i].getDate());
            double value =  qwds[i].getDeltaW();
            boolean interpolate = qwds[i].getInterpolated();
            if (interpolate) {
                interpol.addOrUpdate(rtp, value);
                annoIdxMap.put(
                    i,
                    new int[]{1, i});
            }
            else {
                annoIdxMap.put(
                    i,
                    new int[]{0, i});
                series.addOrUpdate(rtp, value);
            }

        }
        tsc.addSeries(series);
        tsc.addSeries(interpol);

        addAxisDataset(tsc, 0, visible);
        addAttribute(desc + "interpol", "interpolate");
        addAttribute(desc, "outline");

        doQWDTextAnnotations(annoIdxMap, tsc, qwds, theme, visible);
    }


    protected void doDeviationOut(
        FLYSArtifact artifact,
        Object       data,
        String       desc,
        Document     theme,
        boolean      visible
    ) {
        logger.debug("doDeviationOut: desc = " + desc);

        if (data == null || !visible) {
            logger.debug("no standard deviation");
            return;
        }
        double[] value = (double[]) data;
        IntervalMarker lower = new IntervalMarker((value[0] * -1), 0);
        lower.setAlpha(0.2f);
        lower.setPaint(Color.BLACK);
        IntervalMarker upper = new IntervalMarker(0, value[0]);
        upper.setAlpha(0.2f);
        upper.setPaint(Color.BLACK);

        valueMarker.add(lower);
        valueMarker.add(upper);
    }


    protected void doAnalysisPeriodsOut(
        FLYSArtifact artifact,
        Object       data,
        String       desc,
        Document     theme,
        boolean      visible
    ) {
        logger.debug("doHistoricalDischargeDifferenceOut: desc = " + desc);

        DateRange[] ranges = (DateRange[]) data;
        if (ranges == null || !visible) {
            return;
        }
        for (int i = 0; i < ranges.length; i++) {
            logger.debug("creating domain marker");
            RegularTimePeriod start = new Month(ranges[i].getFrom());
            RegularTimePeriod end = new Month(ranges[i].getTo());
            IntervalMarker marker =
                new IntervalMarker(start.getMiddleMillisecond(),
                                   end.getMiddleMillisecond());
            marker.setAlpha(0.3f);
            if ((i % 2) == 0) {
                marker.setPaint(Color.RED);
            }
            else {
                marker.setPaint(Color.BLUE);
            }
            domainMarker.add(marker);
        }
        logger.debug("domainmarkers: " + domainMarker.size());
    }


    @Override
    public void init(Document request, OutputStream out, CallContext context) {
        super.init(request, out, context);

        logger.debug("currentKm = " + new Double(getCurrentKmFromRequest()));
        context.putContextValue("currentKm", new Double(getCurrentKmFromRequest()));

        ValueMarker marker = new ValueMarker(0);
        marker.setPaint(Color.black);
        marker.setStroke(new BasicStroke(2));
        valueMarker.add(marker);
    }

    public double getCurrentKmFromRequest() {
        Element km = (Element)XMLUtils.xpath(
            request,
            XPATH_CHART_CURRENTKM,
            XPathConstants.NODE,
            ArtifactNamespaceContext.INSTANCE);

        if (km == null) {
            return -1d;
        }

        String uri = ArtifactNamespaceContext.NAMESPACE_URI;

        String currentKm = km.getAttributeNS(uri, "km");
        try {
            double d = Double.valueOf(currentKm).doubleValue();
            return d;
        }
        catch(NumberFormatException nfe) {
            return -1d;
        }
    }


}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :

http://dive4elements.wald.intevation.org