org.operamasks.faces.render.graph.CompositeChartRenderer.java Source code

Java tutorial

Introduction

Here is the source code for org.operamasks.faces.render.graph.CompositeChartRenderer.java

Source

/*
 * $Id: CompositeChartRenderer.java,v 1.5 2007/07/02 07:37:44 jacky Exp $
 *
 * Copyright (C) 2006 Operamasks Community.
 * Copyright (C) 2000-2006 Apusic Systems, Inc.
 *
 * This program 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 3 of the License, or
 * 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, see http://www.gnu.org/licenses.
 */

package org.operamasks.faces.render.graph;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.FacesException;
import java.util.List;
import java.util.ArrayList;
import java.io.IOException;

import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.plot.DatasetRenderingOrder;
import org.jfree.chart.plot.Plot;
import org.jfree.data.general.Dataset;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.time.TimeSeriesCollection;

import org.operamasks.faces.component.graph.UIChart;
import org.operamasks.faces.component.graph.UIAxis;
import org.operamasks.faces.util.FacesUtils;
import static org.operamasks.resources.Resources.*;

public class CompositeChartRenderer extends ChartRenderer {
    @Override
    public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
        if (context == null || component == null)
            throw new NullPointerException();
        if (!component.isRendered())
            return;

        // Create subcharts
        UIChart c = (UIChart) component;
        List<UIChart> kids = getSubchartComponents(c);
        List<JFreeChart> subcharts = createSubcharts(context, kids);

        // Create composite chart
        JFreeChart compositeChart;
        if (subcharts.size() == 0) {
            return;
        } else if (subcharts.size() == 1) {
            compositeChart = subcharts.get(0);
        } else {
            Class type = getComonDatasetType(subcharts);
            if (XYDataset.class.isAssignableFrom(type)) {
                compositeChart = createXYCompositeChart(subcharts, c);
            } else {
                compositeChart = createCategoryCompositeChart(subcharts, c);
            }
        }

        // Initialize composite chart
        initChart(compositeChart, c);

        // Initialize individual subcharts
        for (int i = 0; i < subcharts.size(); i++) {
            UIChart kid = kids.get(i);
            JFreeChart subchart = subcharts.get(i);
            ChartRenderer cr = (ChartRenderer) FacesUtils.getRenderer(context, kid);
            cr.initChart(subchart, kid);
        }

        // Encode composite chart image
        encodeChartImage(context, c, compositeChart);
    }

    protected JFreeChart createChart(UIChart comp) {
        throw new AssertionError();
    }

    private List<UIChart> getSubchartComponents(UIChart comp) {
        List<UIChart> result = new ArrayList<UIChart>();
        for (UIComponent kid : comp.getChildren()) {
            if (kid.isRendered() && (kid instanceof UIChart)) {
                result.add((UIChart) kid);
            }
        }
        return result;
    }

    private List<JFreeChart> createSubcharts(FacesContext context, List<UIChart> kids) {
        List<JFreeChart> result = new ArrayList<JFreeChart>(kids.size());
        for (UIChart kid : kids) {
            ChartRenderer cr = (ChartRenderer) FacesUtils.getRenderer(context, kid);
            result.add(cr.createChart(kid));
        }
        return result;
    }

    private Class getComonDatasetType(List<JFreeChart> subcharts) {
        Class commonType = null;

        for (JFreeChart c : subcharts) {
            Plot plot = c.getPlot();
            Class type = null;

            if (plot instanceof CategoryPlot) {
                Dataset ds = ((CategoryPlot) plot).getDataset();
                if (ds instanceof CategoryDataset) {
                    type = CategoryDataset.class;
                }
            } else if (plot instanceof XYPlot) {
                Dataset ds = ((XYPlot) plot).getDataset();
                if (ds instanceof TimeSeriesCollection) {
                    type = TimeSeriesCollection.class;
                } else if (ds instanceof XYDataset) {
                    type = XYDataset.class;
                }
            }

            if (type != null && commonType == null) {
                commonType = type;
            } else if (type == null || type != commonType) {
                throw new FacesException(_T(UI_CHART_INCOMPATIBLE_COMMON_DATA_SERIES));
            }
        }

        return commonType;
    }

    private JFreeChart createCategoryCompositeChart(List<JFreeChart> subcharts, UIChart comp) {
        CategoryPlot compositePlot = new CategoryPlot();
        compositePlot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);
        compositePlot.setOrientation(getChartOrientation(comp));

        for (int i = 0; i < subcharts.size(); i++) {
            CategoryPlot subplot = (CategoryPlot) subcharts.get(i).getPlot();
            compositePlot.setDataset(i, subplot.getDataset());
            compositePlot.setRenderer(i, subplot.getRenderer());

            if (i == 0) {
                // Axis zero is always available.
                compositePlot.setDomainAxis(0, subplot.getDomainAxis());
                compositePlot.setRangeAxis(0, subplot.getRangeAxis());
            } else {
                int yAxisMap = getRangeAxisMap(comp, i);
                ValueAxis yAxis = null;
                if (yAxisMap == -1) {
                    yAxisMap = 0; // map to axis zero by default
                } else if (yAxisMap == i) {
                    yAxis = subplot.getRangeAxis(); // add subplot axis to composite plot
                }
                compositePlot.setRangeAxis(i, yAxis);
                compositePlot.mapDatasetToRangeAxis(i, yAxisMap);
            }
        }

        return new JFreeChart(null, null, compositePlot, false);
    }

    private JFreeChart createXYCompositeChart(List<JFreeChart> subcharts, UIChart comp) {
        XYPlot compositePlot = new XYPlot();
        compositePlot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);
        compositePlot.setOrientation(getChartOrientation(comp));

        for (int i = 0; i < subcharts.size(); i++) {
            XYPlot subplot = (XYPlot) subcharts.get(i).getPlot();
            compositePlot.setDataset(i, subplot.getDataset());
            compositePlot.setRenderer(i, subplot.getRenderer());

            if (i == 0) {
                compositePlot.setDomainAxis(0, subplot.getDomainAxis());
                compositePlot.setRangeAxis(0, subplot.getRangeAxis());
            } else {
                int yAxisMap = getRangeAxisMap(comp, i);
                ValueAxis yAxis = null;
                if (yAxisMap == -1) {
                    yAxisMap = 0; // map to axis zero by default
                } else if (yAxisMap == i) {
                    yAxis = subplot.getRangeAxis(); // add subplot axis to composite plot
                }
                compositePlot.setRangeAxis(i, yAxis);
                compositePlot.mapDatasetToRangeAxis(i, yAxisMap);
            }
        }

        return new JFreeChart(null, null, compositePlot, false);
    }

    private int getRangeAxisMap(UIChart comp, int index) {
        UIChart subcomp = getSubchartComponent(comp, index);
        int yAxisMap = -1;

        if (subcomp != null) {
            // Does subchart's y axis is mapped?
            UIAxis yAxis = subcomp.getyAxis();
            if (yAxis != null) {
                String mapId = (String) yAxis.getAttributes().get("mapTo");
                if (mapId != null) {
                    yAxisMap = getSubchartIndexById(comp, mapId);
                }
            }

            // If the subhcart has it's own y axis the map it.
            if (yAxisMap == -1) {
                if (yAxis != null || subcomp.getyAxisLabel() != null) {
                    yAxisMap = index;
                }
            }
        }

        return yAxisMap;
    }

    private UIChart getSubchartComponent(UIChart parent, int index) {
        for (UIComponent kid : parent.getChildren()) {
            if (kid.isRendered() && (kid instanceof UIChart)) {
                if (index == 0) {
                    return ((UIChart) kid);
                }
                index--;
            }
        }
        return null;
    }

    private int getSubchartIndexById(UIChart parent, String id) {
        int index = 0;
        for (UIComponent kid : parent.getChildren()) {
            if (kid.isRendered() && (kid instanceof UIChart)) {
                if (kid.getId().equals(id)) {
                    return index;
                }
                index++;
            }
        }
        return index;
    }
}