view gnv-artifacts/src/main/java/de/intevation/gnv/chart/ChartFactory.java @ 75:9345835e2bc1

Make the Interfaces Serializable to make them usable in the Artifactdatabase gnv-artifacts/trunk@82 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Tim Englich <tim.englich@intevation.de>
date Mon, 14 Sep 2009 13:38:20 +0000
parents d117fd4b82e5
children 5eb62df21f9a
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.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.transition.describedata.KeyValueDescibeData;

/**
 * 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();


	public synchronized void createSimpleTimeSeriesChart(ChartLabels pLabels, ChartStyle pStyle, String pTimeSeriesName, Collection<KeyValueDescibeData> parameters, Collection<KeyValueDescibeData> measurements, OutputStream outputStream, Collection<Result> resultSet) 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 = createDataset(pTimeSeriesName, resultSet, lUpperLevel,
				lLowerLevel,parameters,measurements);
		if (sDebug)
			sLogger.debug("  nach createDataset()");
		final Color[] color = {Color.black, Color.red, Color.green, Color.blue};
		DateAxis domain = new DateAxis("Zeit [UTC]");
        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(
						((String) 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 (XYDataset) 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, Date dStart, Date dEnd) throws TechnicalChartException{
		if (sDebug)
			sLogger.debug("createTimeSeries()");
		Result lRow0, lRow1, lRowVorEnd;
		
		Date lDate=null, lDate0=null;
        
        TimeSeries lTimeseries = new TimeSeries(pTimeSeriesName,   
				org.jfree.data.time.Minute.class);
		try {
			long maxGap=0, 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;//
            			
            			// Handle Gaps > 0.5% timeserieslength, i.e do not draw here
            			// +TODO mache maxGap variabel �ber diagram options
            			maxGap = (dEnd.getTime() - dStart.getTime()) / 200; // 0,5 prozent der L�nge
            			if (maxGap < 3600000) maxGap=3600010;
            			if (maxGap <(dEnd.getTime() - dStart.getTime())/(pEnd-pStart))
            				maxGap = (dEnd.getTime() - dStart.getTime())/(pEnd-pStart) + 1000;
            			
            			if (sDebug)
            				sLogger.debug("MaxGap : "+maxGap/1000+" L�nge : "+(dEnd.getTime() - dStart.getTime())/1000+
            						      "Intervall "+(dEnd.getTime() - dStart.getTime())/(pEnd-pStart)/1000);
            			lDate = lRow0.getDate("TIMEVALUE");
            			lDate0 = lDate;
            			lValue = lRow0.getDouble("DATAVALUE");
            			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("TIMEVALUE");
					lValue = lRow1.getDouble("DATAVALUE");
					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;
				}
				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(String pTimeseriesName, Collection<Result> resultSet,
			int lUpperCut, int lLowerCut,Collection<KeyValueDescibeData> parameters, Collection<KeyValueDescibeData> measurements) throws TechnicalChartException {
		
		TimeSeriesCollection lTimeSeriesCollection = new TimeSeriesCollection();
		try{
			Date dStart = null, dEnd= null;
			int break1, break2, break3;
			int mStart = 0;
			int mEnd = 0;
			
	
			Iterator<Result> resultIterator = resultSet.iterator();
			if (resultIterator.hasNext()){
    //			Row row = new Row(sArrayStrLine);
    			Result row = resultIterator.next();
    			
    			break1 = row.getInteger("PARAMETERID").intValue(); // 2
    			break2 = row.getInteger("MEASUREMENTID").intValue();  //3
    			break3 = row.getInteger("TIMESERIESID").intValue(); // 4
    			dStart = row.getDate("TIMEVALUE");
    			int i = 1;
    			while (resultIterator.hasNext()) {
    			    row = resultIterator.next();
    				if (break1 != row.getInteger("PARAMETERID").intValue()
    						|| break2 != row.getInteger("MEASUREMENTID").intValue()
    					    || break3 != row.getInteger("TIMESERIESID").intValue()){
    					String mTimeSeriesName = findValueTitle(parameters,break1)+" "+
    					                         findValueTitle(measurements,break2)+"m";
    					
    					lTimeSeriesCollection.addSeries(createTimeSeries(mTimeSeriesName,
    							resultSet, lUpperCut, lLowerCut, mStart, mEnd, dStart, dEnd));
    					mStart = i;
    					dStart = row.getDate("TIMEVALUE");
    					break1 = row.getInteger("PARAMETERID").intValue();
    					break2 = row.getInteger("MEASUREMENTID").intValue();  //3
    					break3 = row.getInteger("TIMESERIESID").intValue(); // 4
    	
    				}
    				mEnd = i;
    				//mEnd ++;
    				dEnd = row.getDate("TIMEVALUE");
    				i = i + 1;
    			}
			
			String mTimeSeriesName = findValueTitle(parameters,break1)+" "+
	                                 findValueTitle(measurements,break2)+"m";
			lTimeSeriesCollection.addSeries(createTimeSeries(mTimeSeriesName,
					resultSet, lUpperCut, lLowerCut, mStart, mEnd, dStart, dEnd));
			}
		}
		catch (Exception e){
			sLogger.error(e.getMessage(), e);
		}
		finally{
		}
		return lTimeSeriesCollection;
	}



	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,
				BufferedImage.BITMASK, null);
	
		lEncoder.encode(lImage, outputStream);
	
}

    private String findValueTitle(Collection<KeyValueDescibeData> values,int pMmtId){
    	Iterator<KeyValueDescibeData> it = values.iterator();
    	while(it.hasNext()){
    	    KeyValueDescibeData data = it.next();
    		if ((long) pMmtId ==data.getKey()){
    		    return data.getValue();
    		}
    	}
    	return "";
    }
}

http://dive4elements.wald.intevation.org