view gnv-artifacts/src/main/java/de/intevation/gnv/chart/ChartFactory.java @ 356:3eee1369c79b

Added the Unit of the Parameter to the Query for Parameters in all Parameterqueries where it was still missing. Now the Unit will be displaied in the Combobox and in the Diagramm-Axis-Description gnv-artifacts/trunk@429 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Tim Englich <tim.englich@intevation.de>
date Tue, 15 Dec 2009 14:55:42 +0000
parents e964a3d8f7bc
children
line wrap: on
line source
/**
 * Title:           ChartFactory, $Header: /share/gdi/SDI-Suite/Repository/projekte/BSH-GDI/genericViewer/src/main/java/de/conterra/bsh/gdi/gnviewer/output/chart/ChartFactory.java,v 1.8 2007/12/21 12:31:15 blume Exp $
 * Source:          $Source: /share/gdi/SDI-Suite/Repository/projekte/BSH-GDI/genericViewer/src/main/java/de/conterra/bsh/gdi/gnviewer/output/chart/ChartFactory.java,v $
 * created by:      Stefan Blume (blume)
 * erstellt am:     06.12.2007
 * Copyright:       con terra GmbH, 2005
 *
 * modified by:     $Author: blume $
 * modified on:     $Date: 2007/12/21 12:31:15 $
 * Version:         $Revision: 1.8 $
 * TAG:             $Name:  $
 * locked from:     $Locker:  $
 * CVS State:       $State: Exp $
 * Project:         $ProjectName$
 */
package de.intevation.gnv.chart;

import java.awt.Color;
import java.awt.Font;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;

import org.apache.log4j.Logger;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.AxisLocation;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.encoders.KeypointPNGEncoderAdapter;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.StandardXYItemRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.time.Minute;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.xy.XYDataset;
import org.jfree.ui.RectangleInsets;

import de.intevation.gnv.chart.exception.TechnicalChartException;
import de.intevation.gnv.geobackend.base.Result;
import de.intevation.gnv.state.describedata.KeyValueDescibeData;
import de.intevation.gnv.timeseries.gap.TimeGap;

/**
 * The class <code>ChartFactory</code> fulfills the following purposes:
 * <ol>
 * <li></li>
 * </ol>
 * 
 * @author blume
 * @version 1.0
 * @serial 1.0
 * @see
 * @since 06.12.2007 17:25:59
 */
public class ChartFactory {

    /**
     * Default Logging instance
     */
    private static Logger sLogger = Logger.getLogger(ChartFactory.class);
    private static boolean sDebug = sLogger.isDebugEnabled();
    
    private final static long NOTIMEGAP = Long.MAX_VALUE - 1000; 
    // Minus 1000 damit es bei Additionen keinen �berlauf gibt

    public synchronized void createSimpleTimeSeriesChart(
                                                         ChartLabels pLabels,
                                                         ChartStyle pStyle,
                                                         Collection<KeyValueDescibeData> parameters,
                                                         Collection<KeyValueDescibeData> measurements,
                                                         OutputStream outputStream,
                                                         Collection<Result> resultSet,
                                                         Collection<TimeGap> timeGaps)
                                                                                      throws IOException,
                                                                                      TechnicalChartException {
        if (sDebug)
            sLogger.debug("createSimpleTimeSeriesChart()");
        int lLowerLevel = Integer.MIN_VALUE;
        int lUpperLevel = Integer.MAX_VALUE;
        if (pStyle.isUseUpperDataLevel()
            && pStyle.getUpperLevel() < Integer.MAX_VALUE) {
            lUpperLevel = pStyle.getUpperLevel();
        }
        if (pStyle.isUseLowerDataLevel()
            && pStyle.getLowerLevel() > Integer.MIN_VALUE) {
            lLowerLevel = pStyle.getLowerLevel();
        }
        if (sDebug)
            sLogger.debug("  vor createDataset()");
        XYDataset lSet = this.createDataset(resultSet, lUpperLevel,
                lLowerLevel, parameters, measurements,timeGaps);
        if (sDebug)
            sLogger.debug("  nach createDataset()");
        final Color[] color = { Color.black, Color.red, Color.green, Color.blue };
        DateAxis domain = new DateAxis(pLabels.getDomainAxisLabel());
        NumberAxis axis;
        StandardXYItemRenderer renderer = new StandardXYItemRenderer();
        XYPlot plot = new XYPlot();
        // Global settings

        plot.setOrientation(PlotOrientation.VERTICAL);
        plot.setBackgroundPaint(Color.lightGray);
        plot.setDomainGridlinePaint(Color.white);
        plot.setRangeGridlinePaint(Color.white);
        plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 5.0));
        // plot.getRangeAxis().setFixedDimension(10.0);
        plot.setDomainAxis(domain);
        plot.setDomainAxisLocation(AxisLocation.BOTTOM_OR_LEFT);
        if (parameters.size() == 1) {
            KeyValueDescibeData parameter = parameters.iterator().next();
            axis = new NumberAxis(parameter.getValue());
            if (parameter.getValue().contains("richtung")) {
                NumberAxis axis1 = new NumberAxis((parameter
                        .getValue()));// ,new Range(0.0,360.0));
                axis1.setTickUnit(new NumberTickUnit(30.0));
                axis1.setUpperBound(360.0);
                axis1.setLowerBound(0.0);
                // axis1.setDisplayRange(0.0,360.0);
                plot.setRangeAxis(axis1);
            } else {
                axis.setFixedDimension(10.0);
                axis.setAutoRangeIncludesZero(false);
                plot.setRangeAxis(axis);
            }
            axis.configure();
            plot.setRangeAxisLocation(AxisLocation.BOTTOM_OR_LEFT);
            plot.setRenderer(renderer);
            plot.setDataset(lSet);
        } else {
            // Individual settings for different parameters
            for (int i = 0; i < lSet.getSeriesCount(); i++) {

                plot.setDataset(i, getDataset((TimeSeriesCollection) lSet, i));
                Color mColor = color[i % color.length]; // zyklische Farbvergabe
                mColor = color[0];
                // if ( pParameterId.length==1){

                if (((String) lSet.getSeriesKey(i)).contains("richtung")) {
                    NumberAxis axis1 = new NumberAxis(((String) lSet
                            .getSeriesKey(i)));// ,new Range(0.0,360.0));
                    axis1.setTickUnit(new NumberTickUnit(30.0));
                    // axis1.setDisplayRange(0.0,360.0);
                    axis1.setLabelPaint(mColor);
                    axis1.setTickLabelPaint(mColor);
                    axis1.setUpperBound(360.0);
                    axis1.setLowerBound(0.0);
                    plot.setRangeAxis(i, axis1);

                } else {
                    axis = new NumberAxis((String) lSet.getSeriesKey(i));
                    axis.setFixedDimension(10.0);
                    axis.setAutoRangeIncludesZero(false);
                    axis.setLabelPaint(mColor);
                    axis.setTickLabelPaint(mColor);
                    plot.setRangeAxis(i, axis);
                    axis.configure();
                }
                if (i % 2 != 0)
                    plot.setRangeAxisLocation(i, AxisLocation.BOTTOM_OR_RIGHT);
                else
                    plot.setRangeAxisLocation(i, AxisLocation.BOTTOM_OR_LEFT);
                plot.mapDatasetToRangeAxis(i, i);
                // }
                renderer = new StandardXYItemRenderer();
                renderer.setSeriesPaint(i, mColor);
                // renderer.setSeriesStroke(i,stroke[j]);
                plot.setRenderer(i, renderer);
            }
        }
        JFreeChart chart = new JFreeChart(pLabels.getTitle(), new Font(
                "SansSerif", Font.BOLD, 24), plot, true);

        setStyle(chart, pStyle);
        configureRenderingOptions(chart);
        if (sDebug)
            sLogger.debug("  vor encodeChart()");

        encodeChart(chart, pStyle, outputStream);
    }

    private static XYDataset getDataset(TimeSeriesCollection T, int pIndex) { // throws
                                                                              // TechnicalChartException{
        // if (T.getSeriesCount() < pIndex) throw TechnicalChartException();
        TimeSeriesCollection TSC = new TimeSeriesCollection();
        TSC.addSeries(T.getSeries(pIndex));
        return TSC;
    }

    private void configureRenderingOptions(JFreeChart pJfreechart) {
        org.jfree.chart.renderer.xy.XYItemRenderer xyitemrenderer = ((XYPlot) pJfreechart
                .getPlot()).getRenderer();
        if (xyitemrenderer instanceof XYLineAndShapeRenderer) {
            XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer) xyitemrenderer;
            xylineandshaperenderer.setBaseShapesVisible(true);
            xylineandshaperenderer.setBaseShapesFilled(true);
        }
    }

    private void setStyle(JFreeChart pJfreechart, ChartStyle pStyle) {
        if (sDebug)
            sLogger.debug("setStyle()");
        pJfreechart.setBackgroundPaint(pStyle.getCanvasColor());
        XYPlot xyplot = (XYPlot) pJfreechart.getPlot();
        xyplot.setBackgroundPaint(pStyle.getPlotBackgroundColor());
        xyplot.setDomainGridlinePaint(pStyle.getDomainGridlineColor());
        xyplot.setRangeGridlinePaint(pStyle.getRangeGridlineColor());

        Insets lOffsets = pStyle.getAxisOffset();
        RectangleInsets lRectangleInsets = new RectangleInsets(lOffsets.mUpper,
                lOffsets.mLeft, lOffsets.mLower, lOffsets.mRight);
        xyplot.setAxisOffset(lRectangleInsets);
        xyplot.setDomainCrosshairVisible(pStyle.isDomainCrosshairVisible());
        xyplot.setRangeCrosshairVisible(pStyle.isRangeCrosshairVisible());

    }

    private TimeSeries createTimeSeries(String pTimeSeriesName,
                                        Collection<Result> resultSet,
                                        int lUpperCut, int lLowerCut,
                                        int pStart, int pEnd, long maxGap)
                                                  throws TechnicalChartException {
        if (sDebug)
            sLogger.debug("createTimeSeries()");
        Result lRow0, lRow1;

        Date lDate = null, lDate0 = null;

        TimeSeries lTimeseries = new TimeSeries(pTimeSeriesName,
                org.jfree.data.time.Minute.class);
        try {
            long lDateDiff = 0;
            double lValue = 0;
            
            int i = 0;
            Iterator<Result> resultIterator = resultSet.iterator();
            while (resultIterator.hasNext()) {
                Result lRow = resultIterator.next();
                if (i >= pStart + 1 && i <= pEnd) {
                    if (i == pStart + 1) {
                        lRow0 = lRow;//
                        lDate = lRow0.getDate("XORDINATE");
                        lDate0 = lDate;
                        lValue = lRow0.getDouble("YORDINATE");
                        if (lValue > lLowerCut && lValue < lUpperCut) {
                            // lTimeseries.addOrUpdate(new Minute(lDate),
                            // lValue);
                            lTimeseries.add(new Minute(lDate), lValue);
                        }
                    }
                    // for (int i = pStart+1; i <= pEnd; i++) {
                    lRow1 = lRow;
                    lDate = lRow1.getDate("XORDINATE");
                    lValue = lRow1.getDouble("YORDINATE");
                    lDateDiff = lDate.getTime() - lDate0.getTime();
                    if (lDateDiff > maxGap) {
                        // add 1 minute in millisecs to left hand side Date
                        // and insert Dummy to break line
                        lDate0.setTime((lDate0.getTime() + 60000));
                        lTimeseries.addOrUpdate(new Minute(lDate0), null);
                        lTimeseries.addOrUpdate(new Minute(lDate), lValue);
                        // lTimeseries.add(new Minute(lDate0), null);
                    } else if (lDateDiff == 0) {
                        if (sDebug)
                            sLogger.debug("Datediff: " + lDateDiff
                                          + " bei index : " + i + " Datum : "
                                          + lDate + " " + lDate0);
                    } else if (lValue > lLowerCut && lValue < lUpperCut) {
                        lTimeseries.addOrUpdate(new Minute(lDate), lValue);
                        // lTimeseries.add(new Minute(lDate), lValue);
                    }
                    lRow0 = lRow1;
                    lDate0 = lDate;
                } else if (i > pEnd) {
                    return lTimeseries;
                }
                i++;
            }

        } catch (OutOfMemoryError e) {
            sLogger.error(e.getMessage(), e);
            return lTimeseries;

        } catch (Exception e) { // TechnicalChartException
            sLogger.error(e.getMessage(), e);
        } finally {
        }

        return lTimeseries;
    }

    private XYDataset createDataset(Collection<Result> resultSet,
                                    int lUpperCut, int lLowerCut,
                                    Collection<KeyValueDescibeData> parameters,
                                    Collection<KeyValueDescibeData> measurements,
                                    Collection<TimeGap> timeGaps)
                                                                                 throws TechnicalChartException {

        TimeSeriesCollection lTimeSeriesCollection = new TimeSeriesCollection();
        try {
            Date dStart = null, dEnd = null;
            String break1, break2, break3;
            int mStart = 0;
            int mEnd = 0;

            Iterator<Result> resultIterator = resultSet.iterator();
            if (resultIterator.hasNext()) {
                Result row = resultIterator.next();

                break1 = row.getString("GROUP1"); // 2
                break2 = row.getString("GROUP2"); // 3
                break3 = row.getString("GROUP3"); // 4
                dStart = row.getDate("XORDINATE");
                int i = 1;
                Integer gapID = -1;
                while (resultIterator.hasNext()) {
                    row = resultIterator.next();
                    if (!break1.equals(row.getString("GROUP1"))
                        || !break2.equals(row.getString("GROUP2"))
                        || !break3.equals(row.getString("GROUP3"))) {
                        String mTimeSeriesName = findValueTitle(parameters,
                                break1)
                                                 + " "
                                                 + findValueTitle(measurements,
                                                         break2) + "m";
                        long maxGap = this.calculateMaxGap(dStart, dEnd,mStart,
                                                           mEnd, gapID.intValue(),
                                                           timeGaps);
                        
                        
                        lTimeSeriesCollection.addSeries(createTimeSeries(
                                mTimeSeriesName, resultSet, lUpperCut,
                                lLowerCut, mStart, mEnd,maxGap));
                        mStart = i;
                        dStart = row.getDate("XORDINATE");
                        break1 = row.getString("GROUP1");
                        break2 = row.getString("GROUP2"); // 3
                        break3 = row.getString("GROUP3"); // 4

                    }
                    mEnd = i;
                    dEnd = row.getDate("XORDINATE");
                    gapID = row.getInteger("GAPID");
                    i = i + 1;
                }

                String mTimeSeriesName = findValueTitle(parameters, break1)
                                         + " "
                                         + findValueTitle(measurements, break2)
                                         + "m";
                long maxGap = this.calculateMaxGap(dStart, dEnd,mStart, 
                                                   mEnd,gapID.intValue(),
                                                   timeGaps);
                lTimeSeriesCollection.addSeries(createTimeSeries(
                        mTimeSeriesName, resultSet, lUpperCut, lLowerCut,
                        mStart, mEnd, maxGap));
            }else{
                // Es sind keine Daten vorhanden: Es wird eine Zeitserie eingef�gt.
                lTimeSeriesCollection.addSeries(createTimeSeries(
                        "", resultSet, lUpperCut, lLowerCut,
                        mStart, mEnd, 999999));
            }
        } catch (Exception e) {
            sLogger.error(e.getMessage(), e);
        } finally {
        }
        return lTimeSeriesCollection;
    }

    /**
     * @param dStart
     * @param dEnd
     */
    private long calculateMaxGap(Date dStart, Date dEnd, int pStart ,
                                 int pEnd, int gapID, 
                                 Collection<TimeGap> timeGaps) {
        
           // umgesetzt nach issue 45
            // Handle Gaps > 0.5% timeserieslength, 
            // i.e do not draw here
            long maxGap = (dEnd.getTime() - dStart.getTime()) / 200; 
            // 0,5 prozent der L�nge
            long timeInterval = this.getTimeGapValue(dStart, dEnd, pStart, 
                                                     pEnd, gapID, timeGaps);
            
            if (maxGap < timeInterval){
                maxGap = timeInterval + 10;
            }
//            if (maxGap < (dEnd.getTime() - dStart.getTime())
//                         / (pEnd - pStart))
//                maxGap = (dEnd.getTime() - dStart.getTime())
//                         / (pEnd - pStart) + 1000;
            
            return maxGap;
    }
    
    private long getTimeGapValue(Date dStart, Date dEnd, 
                                 int pStart ,int pEnd, 
                                 int gapID, Collection<TimeGap> timeGaps){
        long gap = 0;
        
        if (gapID < 0 || gapID >= 99){
            
            if (gapID == -1){ // Mesh
                gap = NOTIMEGAP; // Es gibt keine L�cken in Netzen.
            }else if (pEnd-pStart < 60){
                gap = (3/(pEnd-pStart)) * (dEnd.getTime() - dStart.getTime());
            }
        }else{
            
            Iterator<TimeGap> it = timeGaps.iterator();
           
            while (it.hasNext()){
                TimeGap tempTimeGap = it.next();
                if (tempTimeGap.getKey() == gapID){
                    int gapValue = tempTimeGap.getValue();
                    String unit = tempTimeGap.getUnit();
                    
                    if (unit.equals(TimeGap.TIME_UNIT_MINUTE)){
                        gap = gapValue * TimeGap.MINUTE_IN_MILLIS;
                    }else if (unit.equals(TimeGap.TIME_UNIT_HOUR)){
                        gap = gapValue * TimeGap.HOUR_IN_MILLIS;
                    }else if (unit.equals(TimeGap.TIME_UNIT_DAY)){
                        gap = gapValue * TimeGap.DAY_IN_MILLIS;
                    }else if (unit.equals(TimeGap.TIME_UNIT_WEEK)){
                        gap = gapValue * TimeGap.WEEK_IN_MILLIS;
                    }else if (unit.equals(TimeGap.TIME_UNIT_MONTH)){
                        // TODO wie soll das laufen
                        gap = gapValue * (TimeGap.DAY_IN_MILLIS *30);
                    }else if (unit.equals(TimeGap.TIME_UNIT_YEAR)){
                        // TODO wie soll das laufen f�r schaltjahre
                        gap = gapValue * (TimeGap.DAY_IN_MILLIS *365);
                    }
                    break;
                }
            }
        }
        
        return gap;
    }

    private void encodeChart(JFreeChart pChart, ChartStyle pStyle,
                             OutputStream outputStream) throws IOException {
        if (sDebug)
            sLogger.debug("encodeChart()");
        KeypointPNGEncoderAdapter lEncoder = new KeypointPNGEncoderAdapter();
        lEncoder.setEncodingAlpha(true);

        int lWidth = (int) pStyle.getChartSize().getWidth();
        int lHeight = (int) pStyle.getChartSize().getHeight();

        BufferedImage lImage = pChart.createBufferedImage(lWidth, lHeight,
                Transparency.BITMASK, null);

        lEncoder.encode(lImage, outputStream);

    }

    private String findValueTitle(Collection<KeyValueDescibeData> values,
                                  String pMmtId) {
        int id = 0;
        try {
            id = Integer.parseInt(pMmtId);
        } catch (NumberFormatException e) {
            sLogger.warn(e, e);
            return pMmtId;
        }

        Iterator<KeyValueDescibeData> it = values.iterator();
        while (it.hasNext()) {
            KeyValueDescibeData data = it.next();
            if (id == Integer.parseInt(data.getKey())) {
                return data.getValue();
            }
        }
        return "";
    }
}

http://dive4elements.wald.intevation.org