com.ewcms.plugin.report.generate.factory.ChartFactory.java Source code

Java tutorial

Introduction

Here is the source code for com.ewcms.plugin.report.generate.factory.ChartFactory.java

Source

/**
 * Copyright (c)2010-2011 Enterprise Website Content Management System(EWCMS), All rights reserved.
 * EWCMS PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 * http://www.ewcms.com
 */
package com.ewcms.plugin.report.generate.factory;

import java.io.ByteArrayOutputStream;
import java.sql.Connection;
import java.sql.Date;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.NumberFormat;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import javax.sql.DataSource;

import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryLabelPosition;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.axis.CategoryLabelWidthType;
import org.jfree.chart.labels.AbstractCategoryItemLabelGenerator;
import org.jfree.chart.labels.CategoryItemLabelGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.MultiplePiePlot;
import org.jfree.chart.plot.PiePlot;
import org.jfree.chart.plot.PiePlot3D;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.CategoryItemRenderer;
import org.jfree.chart.renderer.category.LineAndShapeRenderer;
import org.jfree.chart.title.LegendTitle;
import org.jfree.chart.urls.CategoryURLGenerator;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.text.TextBlockAnchor;
import org.jfree.ui.RectangleAnchor;
import org.jfree.ui.RectangleEdge;
import org.jfree.ui.TextAnchor;
import org.jfree.util.TableOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import com.ewcms.common.convert.ConvertException;
import com.ewcms.common.convert.ConvertFactory;
import com.ewcms.plugin.BaseException;
import com.ewcms.plugin.externalds.generate.factory.DataSourceFactoryable;
import com.ewcms.plugin.externalds.generate.factory.init.EwcmsDataSourceFactoryable;
import com.ewcms.plugin.externalds.generate.service.EwcmsDataSourceServiceable;
import com.ewcms.plugin.externalds.model.BaseDS;
import com.ewcms.plugin.report.generate.service.chart.ChartGenerationService;
import com.ewcms.plugin.report.generate.util.ParamConversionPage;
import com.ewcms.plugin.report.generate.vo.PageShowParam;
import com.ewcms.plugin.report.model.ChartReport;
import com.ewcms.plugin.report.model.Parameter;

/**
 * @author ?
 */
@Service
public class ChartFactory implements ChartFactoryable {

    private static final Logger logger = LoggerFactory.getLogger(ChartFactory.class);
    @Autowired
    private EwcmsDataSourceFactoryable ewcmsDataSourceFactory;
    @Autowired
    private DataSource dataSource;

    public void setAlqcDataSourceFactory(EwcmsDataSourceFactoryable alqcDataSourceFactory) {
        this.ewcmsDataSourceFactory = alqcDataSourceFactory;
    }

    public EwcmsDataSourceFactoryable getAlqcDataSourceFactory() {
        return this.ewcmsDataSourceFactory;
    }

    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    /**
     * ??
     */
    static class LabelGenerator extends AbstractCategoryItemLabelGenerator implements CategoryItemLabelGenerator {

        private static final long serialVersionUID = -4769271989622322803L;

        /**  */
        private double threshold;

        /**
         * ??
         *
         * @param threshold 
         */
        public LabelGenerator(double threshold) {
            super("", NumberFormat.getInstance());
            this.threshold = threshold;
        }

        /**
         * ????
         *
         * @param dataset ?? (<code>null</code> ??).
         * @param series
         * @param category
         *
         * @return  (? <code>null</code>).
         */
        public String generateLabel(CategoryDataset dataset, int series, int category) {
            String result = null;
            Number value = dataset.getValue(series, category);
            if (value != null) {
                double v = value.doubleValue();
                if (v > this.threshold) {
                    result = value.toString(); // ??
                }
            }
            return result;
        }
    }

    public byte[] export(ChartReport report, Map<String, String> pageParams) throws Exception {
        if (report == null) {
            return null;
        }
        DefaultCategoryDataset dataset = buildDataset(report, pageParams);
        java.awt.Font titleFont = new java.awt.Font(report.getFontName(), report.getFontStyle(),
                report.getFontSize());
        String chartTitle = report.getChartTitle();
        chartTitle = replaceParam(pageParams, report.getParameters(), chartTitle, false);
        String horizAxisLabel = report.getHorizAxisLabel();
        horizAxisLabel = replaceParam(pageParams, report.getParameters(), horizAxisLabel, false);
        String vertAxisLabel = report.getVertAxisLabel();
        vertAxisLabel = replaceParam(pageParams, report.getParameters(), vertAxisLabel, false);
        Boolean showLegend = report.getShowLegend();
        Boolean showTooltips = report.getShowTooltips();
        Boolean drillThroughEnabled = false;
        ChartReport.Type chartType = report.getType();

        CategoryURLGenerator urlGenerator = null;

        JFreeChart chart = null;
        switch (chartType) {
        case VERTBAR:
            chart = ChartGenerationService.createBarChart(chartTitle, titleFont, horizAxisLabel, vertAxisLabel,
                    dataset, PlotOrientation.VERTICAL, showLegend, showTooltips, drillThroughEnabled, urlGenerator);
            break;
        case VERTBAR3D:
            chart = ChartGenerationService.createBarChart3D(chartTitle, titleFont, horizAxisLabel, vertAxisLabel,
                    dataset, PlotOrientation.VERTICAL, showLegend, showTooltips, drillThroughEnabled, urlGenerator);
            break;
        case HORIZBAR:
            chart = ChartGenerationService.createBarChart(chartTitle, titleFont, horizAxisLabel, vertAxisLabel,
                    dataset, PlotOrientation.HORIZONTAL, showLegend, showTooltips, drillThroughEnabled,
                    urlGenerator);
            break;
        case HORIZBAR3D:
            chart = ChartGenerationService.createBarChart3D(chartTitle, titleFont, horizAxisLabel, vertAxisLabel,
                    dataset, PlotOrientation.HORIZONTAL, showLegend, showTooltips, drillThroughEnabled,
                    urlGenerator);
            break;
        case STACKEDVERTBAR:
            chart = ChartGenerationService.createStackedBarChart(chartTitle, titleFont, horizAxisLabel,
                    vertAxisLabel, dataset, PlotOrientation.VERTICAL, showLegend, showTooltips, drillThroughEnabled,
                    urlGenerator);
            break;
        case STACKEDVERTBAR3D:
            chart = ChartGenerationService.createStackedBarChart3D(chartTitle, titleFont, horizAxisLabel,
                    vertAxisLabel, dataset, PlotOrientation.VERTICAL, showLegend, showTooltips, drillThroughEnabled,
                    urlGenerator);
            break;
        case STACKEDHORIZBAR:
            chart = ChartGenerationService.createStackedBarChart(chartTitle, titleFont, horizAxisLabel,
                    vertAxisLabel, dataset, PlotOrientation.HORIZONTAL, showLegend, showTooltips,
                    drillThroughEnabled, urlGenerator);
            break;
        case STACKEDHORIZBAR3D:
            chart = ChartGenerationService.createStackedBarChart3D(chartTitle, titleFont, horizAxisLabel,
                    vertAxisLabel, dataset, PlotOrientation.HORIZONTAL, showLegend, showTooltips,
                    drillThroughEnabled, urlGenerator);
            break;
        case VERTLINE:
            chart = ChartGenerationService.createLineChart(chartTitle, titleFont, horizAxisLabel, vertAxisLabel,
                    dataset, PlotOrientation.VERTICAL, showLegend, showTooltips, drillThroughEnabled, urlGenerator);
            break;
        case HORIZLINE:
            chart = ChartGenerationService.createLineChart(chartTitle, titleFont, horizAxisLabel, vertAxisLabel,
                    dataset, PlotOrientation.HORIZONTAL, showLegend, showTooltips, drillThroughEnabled,
                    urlGenerator);
            break;
        case VERTAREA:
            chart = ChartGenerationService.createAreaChart(chartTitle, titleFont, horizAxisLabel, vertAxisLabel,
                    dataset, PlotOrientation.VERTICAL, showLegend, showTooltips, drillThroughEnabled, urlGenerator);
            break;
        case HORIZAREA:
            chart = ChartGenerationService.createAreaChart(chartTitle, titleFont, horizAxisLabel, vertAxisLabel,
                    dataset, PlotOrientation.HORIZONTAL, showLegend, showTooltips, drillThroughEnabled,
                    urlGenerator);
            break;
        case VERTSTACKEDAREA:
            chart = ChartGenerationService.createStackedAreaChart(chartTitle, titleFont, horizAxisLabel,
                    vertAxisLabel, dataset, PlotOrientation.VERTICAL, showLegend, showTooltips, drillThroughEnabled,
                    urlGenerator);
            break;
        case HORIZSTACKEDAREA:
            chart = ChartGenerationService.createStackedAreaChart(chartTitle, titleFont, horizAxisLabel,
                    vertAxisLabel, dataset, PlotOrientation.HORIZONTAL, showLegend, showTooltips,
                    drillThroughEnabled, urlGenerator);
            break;
        case PIEBYCOLUMN:
            chart = ChartGenerationService.createPieChart(chartTitle, titleFont, dataset, TableOrder.BY_COLUMN,
                    showLegend, showTooltips, drillThroughEnabled, null);
            break;
        case PIEBYROW:
            chart = ChartGenerationService.createPieChart(chartTitle, titleFont, dataset, TableOrder.BY_ROW,
                    showLegend, showTooltips, drillThroughEnabled, null);
            break;
        case PIEBYCOLUMN3D:
            chart = ChartGenerationService.create3DPieChart(chartTitle, titleFont, dataset, TableOrder.BY_COLUMN,
                    showLegend, showTooltips, drillThroughEnabled, null);

            break;
        case PIEBYROW3D:
            chart = ChartGenerationService.create3DPieChart(chartTitle, titleFont, dataset, TableOrder.BY_ROW,
                    showLegend, showTooltips, drillThroughEnabled, null);
            break;
        default:
            throw new BaseException("", "");
        }
        try {
            Integer bgColorR = report.getBgColorR();
            Integer bgColorG = report.getBgColorG();
            Integer bgColorB = report.getBgColorB();
            chart.setBackgroundPaint(new java.awt.Color(bgColorR, bgColorG, bgColorB));

            String axisFontName = report.getAxisFontName();
            Integer axisFontStyle = report.getAxisFontStyle();
            Integer axisFontSize = report.getAxisFontSize();
            java.awt.Font axisFont = new java.awt.Font(axisFontName, axisFontStyle, axisFontSize);

            String axisTickFontName = report.getAxisTickFontName();
            Integer axisTickFontStyle = report.getAxisTickFontStyle();
            Integer axisTickFontSize = report.getAxisTickFontSize();
            java.awt.Font axisTickFont = new java.awt.Font(axisTickFontName, axisTickFontStyle, axisTickFontSize);

            String legendFontName = report.getLegendFontName();
            Integer legendFontStyle = report.getLegendFontStyle();
            Integer legendFontSize = report.getLegendFontSize();
            java.awt.Font legendFont = new java.awt.Font(legendFontName, legendFontStyle, legendFontSize);
            Integer tickLabelRotate = report.getTickLabelRotate();

            String dataFontName = report.getDataFontName();
            Integer dataFontStyle = report.getDataFontStyle();
            Integer dataFontSize = report.getDataFontSize();
            java.awt.Font dataFont = new java.awt.Font(dataFontName, dataFontStyle, dataFontSize);

            Plot plot = chart.getPlot();
            if (!(plot instanceof MultiplePiePlot)) {
                CategoryPlot categoryPlot = chart.getCategoryPlot();
                CategoryItemRenderer renderer = categoryPlot.getRenderer();
                renderer.setBaseItemLabelGenerator(new LabelGenerator(0.0));
                renderer.setBaseItemLabelFont(dataFont);
                renderer.setBaseItemLabelsVisible(true);
                if (chartType == ChartReport.Type.VERTLINE || chartType == ChartReport.Type.HORIZLINE) {
                    LineAndShapeRenderer lineRenderer = (LineAndShapeRenderer) categoryPlot.getRenderer();
                    lineRenderer.setBaseShapesVisible(true);
                    lineRenderer.setDrawOutlines(true);
                    lineRenderer.setUseFillPaint(true);
                }
            }

            if (plot instanceof CategoryPlot) {
                CategoryPlot catPlot = (CategoryPlot) plot;
                catPlot.getDomainAxis().setLabelFont(axisFont);
                catPlot.getRangeAxis().setLabelFont(axisFont);
                catPlot.getDomainAxis().setTickLabelFont(axisTickFont);
                catPlot.getRangeAxis().setTickLabelFont(axisTickFont);
                catPlot.getDomainAxis().setMaximumCategoryLabelWidthRatio(100.0f);
                double angle = -2.0 * Math.PI / 360.0 * (double) tickLabelRotate;
                CategoryLabelPositions oldp = catPlot.getDomainAxis().getCategoryLabelPositions();
                CategoryLabelPositions newp = new CategoryLabelPositions(oldp.getLabelPosition(RectangleEdge.TOP),
                        new CategoryLabelPosition(RectangleAnchor.TOP, TextBlockAnchor.TOP_RIGHT,
                                TextAnchor.TOP_RIGHT, angle, CategoryLabelWidthType.RANGE, 0.0f),
                        oldp.getLabelPosition(RectangleEdge.LEFT), oldp.getLabelPosition(RectangleEdge.RIGHT));
                catPlot.getDomainAxis().setCategoryLabelPositions(newp);
            } else if (plot instanceof PiePlot3D) {
                PiePlot3D piePlot = (PiePlot3D) plot;
                piePlot.setLabelFont(axisFont);
                piePlot.setDirection(org.jfree.util.Rotation.CLOCKWISE);
                piePlot.setForegroundAlpha(0.5f);
                piePlot.setNoDataMessage("?");
            } else if (plot instanceof PiePlot) {
                PiePlot piePlot = (PiePlot) plot;
                piePlot.setLabelFont(axisFont);
            }
            LegendTitle legend = (LegendTitle) chart.getLegend();
            if (legend != null) {
                legend.setItemFont(legendFont);
                RectangleEdge legendRectEdge = RectangleEdge.BOTTOM;
                Integer legendPosition = report.getLegendPosition();
                switch (legendPosition) {
                case 0:
                    legendRectEdge = RectangleEdge.LEFT;
                    break;
                case 1:
                    legendRectEdge = RectangleEdge.TOP;
                    break;
                case 2:
                    legendRectEdge = RectangleEdge.RIGHT;
                    break;
                case 3:
                    legendRectEdge = RectangleEdge.BOTTOM;
                    break;
                }
                legend.setPosition(legendRectEdge);
            }
        } catch (Exception e) {
            logger.error("Chart Export Exception", e);
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ChartUtilities.writeChartAsPNG(out, chart, report.getChartWidth(), report.getChartHeight());
        return out.toByteArray();
    }

    public List<PageShowParam> chartParameters(ChartReport report) {
        Assert.notNull(report);
        Set<Parameter> paramSet = report.getParameters();
        return ParamConversionPage.conversion(paramSet);
    }

    /**
     * ?
     *
     * @param reportDataSet ??
     * @param sql SQL?
     * @return DefaultCategoryDataset
     * @throws BaseException
     */
    @SuppressWarnings("rawtypes")
    private DefaultCategoryDataset buildDataset(ChartReport report, Map<String, String> pageParams)
            throws BaseException {
        DefaultCategoryDataset dataset = new DefaultCategoryDataset();
        Connection con = null;
        EwcmsDataSourceServiceable service = null;
        int colCount;
        try {
            BaseDS dataSet = report.getBaseDS();
            String executableSQL = report.getChartSql();

            executableSQL = replaceParam(pageParams, report.getParameters(), executableSQL, true);

            if (dataSet == null) {
                con = dataSource.getConnection();
            } else {
                DataSourceFactoryable factory = (DataSourceFactoryable) getAlqcDataSourceFactory()
                        .getBean(dataSet.getClass());
                service = factory.createService(dataSet);
                con = service.openConnection();
            }

            Statement st = con.createStatement();
            ResultSet rs = st.executeQuery(executableSQL);

            colCount = rs.getMetaData().getColumnCount();

            if (colCount == 2) {
                while (rs.next()) {
                    try {
                        try {
                            dataset.addValue(rs.getDouble(1), "", (Comparable) rs.getObject(2));
                        } catch (Exception e) {
                            dataset.addValue(rs.getDouble(2), "", (Comparable) rs.getObject(1));
                        }
                        //                       if (rs.getMetaData().getColumnType(1) == Types.NUMERIC){
                        //                            dataset.addValue(rs.getDouble(1), "", (Comparable) rs.getObject(2));
                        //                       }else if (rs.getMetaData().getColumnType(2) == Types.NUMERIC) {
                        //                            dataset.addValue(rs.getDouble(2), "", (Comparable) rs.getObject(1));
                        //                       }
                    } catch (Exception e) {
                        logger.error("SQL?", e);
                        throw new BaseException("SQL?", "SQL?");
                    }
                }
            } else if (colCount == 3) {
                while (rs.next()) {
                    try {
                        //                       log.info(rs.getMetaData().getColumnType(1));
                        //                       log.info(rs.getMetaData().getColumnType(2));
                        //                       log.info(rs.getMetaData().getColumnType(3));
                        //                       if (rs.getMetaData().getColumnType(1) == Types.NUMERIC){
                        //                            dataset.addValue(rs.getDouble(1), (Comparable) rs.getObject(2), (Comparable) rs.getObject(3));
                        //                       }else if (rs.getMetaData().getColumnType(2) == Types.NUMERIC){
                        //                          dataset.addValue(rs.getDouble(2), (Comparable) rs.getObject(1), (Comparable) rs.getObject(3));
                        //                       }else if (rs.getMetaData().getColumnType(3) == Types.NUMERIC){
                        //                          dataset.addValue(rs.getDouble(3), (Comparable) rs.getObject(1), (Comparable) rs.getObject(2));
                        //                       }
                        try {
                            dataset.addValue(rs.getDouble(3), (Comparable) rs.getObject(1),
                                    (Comparable) rs.getObject(2));
                        } catch (Exception e) {
                            try {
                                dataset.addValue(rs.getDouble(2), (Comparable) rs.getObject(1),
                                        (Comparable) rs.getObject(3));
                            } catch (Exception ex) {
                                dataset.addValue(rs.getDouble(1), (Comparable) rs.getObject(2),
                                        (Comparable) rs.getObject(3));
                            }
                        }
                    } catch (Exception e) {
                        logger.error("SQL?", e);
                        throw new BaseException("SQL?", "SQL?");
                    }
                }
            } else {
                logger.error("SQL??12");
                throw new BaseException("?12", "?12");
            }
            st.close();
            rs.close();
        } catch (SQLException e) {
            throw new BaseException(e.toString(), e.toString());
        } catch (ConvertException e) {
            throw new BaseException(e.toString(), e.toString());
        } catch (ClassNotFoundException e) {
            throw new BaseException(e.toString(), e.toString());
        } finally {
            if (service != null) {
                service.closeConnection();
            }
            if (con != null) {
                try {
                    con.close();
                } catch (SQLException e) {
                }
                con = null;
            }
        }
        return dataset;
    }

    /**
     * ??
     *
     * @param chartParam
     * @param sql
     * @return
     * @throws ConvertException 
     * @throws ClassNotFoundException 
     * @throws TypeHandlerException
     */
    @SuppressWarnings("unchecked")
    private String replaceParam(Map<String, String> pageParams, Set<Parameter> paramSets, String expression,
            Boolean isSql) throws ConvertException, ClassNotFoundException {
        if (paramSets == null || paramSets.size() == 0) {
            return expression;
        }
        Map<String, Object> chartParam = new HashMap<String, Object>();
        if (pageParams == null || pageParams.size() == 0) {
            for (Parameter param : paramSets) {
                String value = param.getDefaultValue();
                if (value == null) {
                    continue;
                }

                String className = param.getClassName();
                Class<Object> forName = (Class<Object>) Class.forName(className);
                Object paramValue = ConvertFactory.instance.convertHandler(forName).parse(value);
                chartParam.put(param.getEnName(), paramValue);
            }
        } else {
            for (Parameter param : paramSets) {
                String value = pageParams.get(param.getEnName());
                if (value == null) {
                    continue;
                }
                String className = param.getClassName();
                Class<Object> forName = (Class<Object>) Class.forName(className);
                Object paramValue = ConvertFactory.instance.convertHandler(forName).parse(value);
                chartParam.put(param.getEnName(), paramValue);
            }
        }
        int beginIndex = 0;
        int endIndex = 0;
        StringBuffer sb = new StringBuffer(expression);
        for (int i = 0; i < sb.length(); i++) {
            String p = sb.substring(i, i + 1);
            if (p.equals("$")) {
                beginIndex = i;
                continue;
            }
            if (p.equals("}")) {
                endIndex = i;
            }
            if (endIndex > beginIndex) {
                String temp = sb.substring(beginIndex, endIndex + 1);
                Iterator<Entry<String, Object>> iterator = chartParam.entrySet().iterator();
                while (iterator.hasNext()) {
                    Map.Entry<String, Object> e = (Map.Entry<String, Object>) iterator.next();
                    if (temp.indexOf(e.getKey(), 0) != -1) {
                        Object value = e.getValue();
                        if (isSql) {
                            if (value instanceof String) {
                                sb = sb.replace(beginIndex, endIndex + 1, "'" + value + "'");
                            } else if (value instanceof Date) {
                                sb = sb.replace(beginIndex, endIndex + 1, "'" + value + "'");
                            } else {
                                sb = sb.replace(beginIndex, endIndex + 1, "" + value + "");
                            }
                        } else {
                            sb = sb.replace(beginIndex, endIndex + 1, "" + value + "");
                        }
                    }
                }
                beginIndex = endIndex;
            }
        }
        return sb.toString();
    }
}