org.posterita.core.TimeSeriesChart.java Source code

Java tutorial

Introduction

Here is the source code for org.posterita.core.TimeSeriesChart.java

Source

/**
 *  Product: Posterita Web-Based POS and Adempiere Plugin
 *  Copyright (C) 2007  Posterita Ltd
 *  This file is part of POSterita
 *  
 *  POSterita is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 * 13-Jul-2006 09:59:29 by praveen
 *
 */

package org.posterita.core;

import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;

import org.compiere.util.DB;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.labels.StandardXYItemLabelGenerator;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.time.Day;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;

import org.posterita.businesslogic.performanceanalysis.ReportManager;
import org.posterita.exceptions.OperationException;

/**
 * @author praveen
 *
 */
public class TimeSeriesChart extends AbstractChart {
    public static final String CHART_TYPE = "TimeSeries";

    TimeSeriesCollection dataset = null;
    boolean showShapes = false;

    public TimeSeriesChart() {
    };

    public TimeSeriesChart(TimeSeriesCollection dataset, String title) {
        this.dataset = dataset;
        this.title = title;
    }

    public TimeSeriesChart(TimeSeriesCollection dataset, String title, String xLabel, String yLabel) {
        this.dataset = dataset;
        this.title = title;
        this.xLabel = xLabel;
        this.yLabel = yLabel;
    }

    public JFreeChart createChart() throws OperationException {
        if (dataset == null) {
            throw new OperationException("Cannot create Time series chart: cause -> dataset null!");
        }

        chart = ChartFactory.createTimeSeriesChart(title, xLabel, yLabel, dataset, showLegend, showTooltip, false);

        if (showShapes) {
            XYPlot plot = (XYPlot) chart.getPlot();
            XYLineAndShapeRenderer render = (XYLineAndShapeRenderer) plot.getRenderer();
            render.setBaseShapesVisible(true);
        }

        //setting subtitle
        if (subtitle != null) {
            TextTitle title = new TextTitle(subtitle);
            chart.addSubtitle(title);
        }

        //displaying labels
        if (showLabels) {
            XYPlot plot = (XYPlot) chart.getPlot();
            XYLineAndShapeRenderer render = (XYLineAndShapeRenderer) plot.getRenderer();
            render.setItemLabelGenerator(new StandardXYItemLabelGenerator());
            render.setItemLabelsVisible(true);
        }

        return chart;

    }

    /**
     * Takes a sql as input and generates a Timeseries that is added to
     * the dataset.    
     * Note: The sql must return 3 columns only Series, date & value
     * Column 1: Type -> String
     * Column 2: Type -> String or Date. For String the format must be as dd-MM-yyyy
     * Column 3: Type -> BigDecimal
     * 
     * @param sql
     */
    public void getDataSetFromSQL(String sql) throws OperationException {
        PreparedStatement pstmt = DB.prepareStatement(sql, null);

        ArrayList<Object[]> dataSource = ReportManager.getReportData(pstmt);
        int count = 0;

        String seriesName = null;
        TimeSeries series = null;
        BigDecimal value = null;
        int day = 0;
        int month = 0;
        int year = 0;

        TimeSeriesCollection timeSeriesCollection = new TimeSeriesCollection();

        for (Object[] data : dataSource) {
            if (data.length != 3)
                throw new OperationException(
                        "Unable to generate timeseries. Cause:Invalid sql, the return resultset must have 3 columns only");

            count++;
            if (count == 1) {
                continue;
            }

            seriesName = (String) data[0];
            String date = (String) data[1];
            value = (BigDecimal) data[2];
            String s[] = date.split("-");

            if (s.length != 3)
                throw new OperationException("Unable to generate timeseries. "
                        + "Cause:Invalid date format, the date returned should have the following format 'DD-MM-YYYY'");

            SimpleDateFormat sdf = new SimpleDateFormat();
            Calendar cal = Calendar.getInstance();
            Date d = null;

            try {
                sdf.applyPattern("DD-MM-YYYY");
                d = sdf.parse(date);
            } catch (ParseException e1) {
                try {
                    sdf.applyPattern("DD-MMM-YYYY");
                    d = sdf.parse(date);
                } catch (ParseException e) {
                    throw new OperationException("Unable to generate timeseries. "
                            + "Cause:Invalid date format, the date returned should have one of the following formats 'DD-MM-YYYY' or 'DD-MMM-YYYY'",
                            e);
                }
            }

            cal.setTime(d);

            day = cal.get(Calendar.DATE);
            month = cal.get(Calendar.MONTH) + 1;
            year = cal.get(Calendar.YEAR);

            series = timeSeriesCollection.getSeries(seriesName);

            if (series == null) {
                series = new TimeSeries(seriesName, Day.class);
                series.add(new Day(day, month, year), value);

                timeSeriesCollection.addSeries(series);
            } else {
                series.add(new Day(day, month, year), value);
            } //if   

        } //for

        dataset = timeSeriesCollection;
    }

    public void getTimeSeriesFromSQL(String sql, String key) throws OperationException {
        PreparedStatement pstmt = DB.prepareStatement(sql, null);

        ArrayList<Object[]> dataSource = ReportManager.getReportData(pstmt);
        TimeSeries series = new TimeSeries(key, Day.class);
        int count = 0;

        for (Object[] data : dataSource) {
            if (data.length != 2)
                throw new OperationException(
                        "Unable to generate timeseries. Cause:Invalid sql, the return resultset must have 2 columns only");

            count++;
            if (count == 1)
                continue;

            series.add(new Day((Date) data[0]), (BigDecimal) data[1]);
        }

        pstmt = null;
        addSeries(series);
    }

    public void addSeries(TimeSeries series) {
        if (dataset == null)
            dataset = new TimeSeriesCollection();

        dataset.addSeries(series);
    }

    public TimeSeriesCollection getDataset() {
        return dataset;
    }

    public void setDataset(TimeSeriesCollection dataset) {
        this.dataset = dataset;
    }

    public boolean isShowShapes() {
        return showShapes;
    }

    public void setShowShapes(boolean showShapes) {
        this.showShapes = showShapes;
    }

}