org.pentaho.plugin.jfreereport.reportcharts.BarLineChartExpression.java Source code

Java tutorial

Introduction

Here is the source code for org.pentaho.plugin.jfreereport.reportcharts.BarLineChartExpression.java

Source

/*!
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* 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 Lesser General Public License for more details.
*
* Copyright (c) 2002-2017 Hitachi Vantara..  All rights reserved.
*/

package org.pentaho.plugin.jfreereport.reportcharts;

import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.AxisLocation;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.DateTickUnit;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberAxis3D;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.DatasetRenderingOrder;
import org.jfree.chart.renderer.category.CategoryItemRenderer;
import org.jfree.chart.renderer.category.LineAndShapeRenderer;
import org.jfree.chart.renderer.category.LineRenderer3D;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.general.Dataset;
import org.pentaho.plugin.jfreereport.reportcharts.backport.FastNumberTickUnit;
import org.pentaho.reporting.engine.classic.core.ClassicEngineBoot;
import org.pentaho.reporting.engine.classic.core.function.Expression;
import org.pentaho.reporting.libraries.formatting.FastDecimalFormat;

import java.awt.*;
import java.text.DateFormatSymbols;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;

public class BarLineChartExpression extends BarChartExpression implements MultiPlotChartExpression {
    private static final long serialVersionUID = 7082583397390897215L;

    private String linesDataSource;
    private String secondValueAxisLabel; //$NON-NLS-1$
    private ArrayList<String> lineSeriesColor;

    private String linesLabelFont; //$NON-NLS-1$

    @Deprecated
    private String linesTickLabelFont; //$NON-NLS-1$
    private String lineTicksLabelFormat; //$NON-NLS-1$

    private String lineStyle; //$NON-NLS-1$
    private float lineWidth;

    private boolean markersVisible;
    private boolean sharedRangeAxis;

    private double linePeriodCount;
    private Class lineTimePeriod;
    private Font lineTitleFont;
    private Font lineTickFont;
    private double lineRangeMinimum;
    private double lineRangeMaximum;
    private boolean lineAxisAutoRange;
    private boolean lineAxisIncludesZero;
    private boolean lineAxisStickyZero;

    //constructor
    public BarLineChartExpression() {
        lineSeriesColor = new ArrayList<String>();
        secondValueAxisLabel = "";
        linesLabelFont = "SansSerif--8";
        linesTickLabelFont = "SansSerif--8";
        lineWidth = 1.0f;
        markersVisible = false;
        linePeriodCount = 0;

        lineRangeMinimum = 0;
        lineRangeMaximum = 1;
        lineAxisAutoRange = true;
        lineAxisIncludesZero = true;
        lineAxisStickyZero = true;
    }

    public boolean isLineAxisIncludesZero() {
        return lineAxisIncludesZero;
    }

    public void setLineAxisIncludesZero(final boolean lineAxisIncludesZero) {
        this.lineAxisIncludesZero = lineAxisIncludesZero;
    }

    public boolean isLineAxisStickyZero() {
        return lineAxisStickyZero;
    }

    public void setLineAxisStickyZero(final boolean lineAxisStickyZero) {
        this.lineAxisStickyZero = lineAxisStickyZero;
    }

    public Font getLineTitleFont() {
        return lineTitleFont;
    }

    public void setLineTitleFont(final Font lineTitleFont) {
        this.lineTitleFont = lineTitleFont;
    }

    public Font getLineTickFont() {
        return lineTickFont;
    }

    public void setLineTickFont(final Font lineTickFont) {
        this.lineTickFont = lineTickFont;
    }

    public double getLineRangeMinimum() {
        return lineRangeMinimum;
    }

    public void setLineRangeMinimum(final double lineRangeMinimum) {
        this.lineRangeMinimum = lineRangeMinimum;
    }

    public double getLineRangeMaximum() {
        return lineRangeMaximum;
    }

    public void setLineRangeMaximum(final double lineRangeMaximum) {
        this.lineRangeMaximum = lineRangeMaximum;
    }

    public double getLinePeriodCount() {
        return linePeriodCount;
    }

    public void setLinePeriodCount(final double linePeriodCount) {
        this.linePeriodCount = linePeriodCount;
    }

    public Class getLineTimePeriod() {
        return lineTimePeriod;
    }

    public void setLineTimePeriod(final Class lineTimePeriod) {
        this.lineTimePeriod = lineTimePeriod;
    }

    public boolean isSharedRangeAxis() {
        return sharedRangeAxis;
    }

    public void setSharedRangeAxis(final boolean sharedRangeAxis) {
        this.sharedRangeAxis = sharedRangeAxis;
    }

    /**
     * Return a completly separated copy of this function. The copy does no longer share any changeable objects with the
     * original function.
     *
     * @return a copy of this function.
     */
    public Expression getInstance() {
        final BarLineChartExpression chartExpression = (BarLineChartExpression) super.getInstance();
        chartExpression.lineSeriesColor = (ArrayList<String>) lineSeriesColor.clone();
        return chartExpression;
    }

    public String getLinesDataSource() {
        return linesDataSource;
    }

    public void setLinesDataSource(final String linesDataSource) {
        this.linesDataSource = linesDataSource;
    }

    public String getSecondaryDataSet() {
        return getLinesDataSource();
    }

    public void setSecondaryDataSet(final String dataset) {
        setLinesDataSource(dataset);
    }

    public String getLinesLabelFont() {
        return linesLabelFont;
    }

    public void setLinesLabelFont(final String linesLabelFont) {
        this.linesLabelFont = linesLabelFont;
    }

    @Deprecated
    public String getLinesTickLabelFont() {
        return linesTickLabelFont;
    }

    @Deprecated
    public void setLinesTickLabelFont(final String linesTickLabelFont) {
        this.linesTickLabelFont = linesTickLabelFont;
    }

    public String getSecondValueAxisLabel() {
        return secondValueAxisLabel;
    }

    public void setSecondValueAxisLabel(final String secondValueAxisLabel) {
        this.secondValueAxisLabel = secondValueAxisLabel;
    }

    public String getLineTicksLabelFormat() {
        return lineTicksLabelFormat;
    }

    public void setLineTicksLabelFormat(final String lineTicksLabelFormat) {
        this.lineTicksLabelFormat = lineTicksLabelFormat;
    }

    public void setLineSeriesColor(final int index, final String field) {
        if (lineSeriesColor.size() == index) {
            lineSeriesColor.add(field);
        } else {
            lineSeriesColor.set(index, field);
        }
    }

    public String getLineSeriesColor(final int index) {
        return (String) this.lineSeriesColor.get(index);
    }

    public int getLineSeriesColorCount() {
        return this.lineSeriesColor.size();
    }

    public String[] getLineSeriesColor() {
        final Object[] toArray = this.lineSeriesColor.toArray(new String[this.lineSeriesColor.size()]);
        return (String[]) toArray;
    }

    public void setLineSeriesColor(final String[] fields) {
        this.lineSeriesColor.clear();
        this.lineSeriesColor.addAll(Arrays.asList(fields));
    }

    /**
     * @return returns the style set for the lines
     */
    public String getLineStyle() {
        return lineStyle;
    }

    /**
     * @param value set the style for all line series
     */
    public void setLineStyle(final String value) {
        lineStyle = value;
    }

    /**
     * @return the width of all line series Valid values are float numbers zero or greater
     */
    public float getLineWidth() {
        return lineWidth;
    }

    /**
     * @param value set the width of all line series Valid values are float numbers zero or greater
     */
    public void setLineWidth(final float value) {
        lineWidth = value;
    }

    /**
     * @return boolean whether the markers (data points) for all series are displayed
     */
    public boolean isMarkersVisible() {
        return markersVisible;
    }

    /**
     * @param markersVisible set whether the markers (data points) for all series should be displayed
     */
    public void setMarkersVisible(final boolean markersVisible) {
        this.markersVisible = markersVisible;
    }

    /**
     * @deprecated
     */
    public String getBarsTickLabelFont() {
        return convertFontToString(getRangeTickFont());
    }

    /**
     * @deprecated
     */
    public void setBarsTickLabelFont(final String barsTickLabelFont) {
        setRangeTickFont(Font.decode(barsTickLabelFont));
    }

    /**
     * @deprecated
     */
    public String getCategoryTickLabelFont() {
        return getLabelFont();
    }

    /**
     * @deprecated
     */
    public void setCategoryTickLabelFont(final String categoryTickLabelFont) {
        this.setLabelFont(categoryTickLabelFont);
    }

    /**
     * @return
     * @deprecated duplicate property.
     */
    public String getBarTicksLabelFormat() {
        return getRangeTickFormatString();
    }

    /**
     * @param lineTicksLabelDateFormat
     * @deprecated duplicate property.
     */
    public void setBarTicksLabelFormat(final String lineTicksLabelDateFormat) {
        setRangeTickFormatString(lineTicksLabelDateFormat);
    }

    /**
     * @deprecated
     */
    public String getBarsLabelFont() {
        return convertFontToString(getRangeTitleFont());
    }

    /**
     * @deprecated
     */
    public void setBarsLabelFont(final String barsLabelFont) {
        setRangeTitleFont(Font.decode(barsLabelFont));
    }

    public boolean isLineAxisAutoRange() {
        return lineAxisAutoRange;
    }

    public void setLineAxisAutoRange(final boolean lineAxisAutoRange) {
        this.lineAxisAutoRange = lineAxisAutoRange;
    }

    public JFreeChart computeCategoryChart(final CategoryDataset barsDataset) {
        final JFreeChart chart = super.computeCategoryChart(barsDataset);
        final CategoryDataset linesDataset = createLinesDataset();

        //Create the renderer with the barchart, use a different bar renderer depending
        //if 3D chart or not
        final CategoryPlot plot = chart.getCategoryPlot();
        final CategoryItemRenderer lineRenderer;
        if (isThreeD()) {
            lineRenderer = new LineRenderer3D();
        } else {
            lineRenderer = new LineAndShapeRenderer();
        }

        //add lines dataset and axis to plot
        if (linesDataset != null) {

            //Create Axis Objects
            final ValueAxis linesAxis;
            if (isSharedRangeAxis()) {
                linesAxis = plot.getRangeAxis();
            } else if (isThreeD()) {
                linesAxis = new NumberAxis3D(getSecondValueAxisLabel());
            } else {
                linesAxis = new NumberAxis(getSecondValueAxisLabel());
            }

            plot.setRenderer(1, lineRenderer);
            plot.setDataset(1, linesDataset);
            plot.setRangeAxis(1, linesAxis);

            //map lines to second axis
            plot.mapDatasetToRangeAxis(1, 1);

            //set location of second axis
            plot.setRangeAxisLocation(1, AxisLocation.BOTTOM_OR_RIGHT);
        }

        //set rendering order
        plot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);

        return chart;
    }

    private CategoryDataset createLinesDataset() {
        final Object maybeCollector = getDataRow().get(getLinesDataSource());
        final Dataset dataset;
        if (maybeCollector instanceof ICollectorFunction) {
            final ICollectorFunction collector = (ICollectorFunction) maybeCollector;
            dataset = (Dataset) collector.getDatasourceValue();
        } else if (maybeCollector instanceof CollectorFunctionResult) {
            final CollectorFunctionResult collector = (CollectorFunctionResult) maybeCollector;
            dataset = collector.getDataSet();
        } else {
            dataset = null;
        }

        final CategoryDataset linesDataset;
        if (dataset instanceof CategoryDataset) {
            linesDataset = (CategoryDataset) dataset;
        } else {
            linesDataset = null;
        }
        return linesDataset;
    }

    protected void configureChart(final JFreeChart chart) {
        super.configureChart(chart);

        final CategoryPlot plot = chart.getCategoryPlot();

        if (isSharedRangeAxis() == false) {
            final ValueAxis linesAxis = plot.getRangeAxis(1);
            if (linesAxis instanceof NumberAxis) {
                final NumberAxis numberAxis = (NumberAxis) linesAxis;
                numberAxis.setAutoRangeIncludesZero(isLineAxisIncludesZero());
                numberAxis.setAutoRangeStickyZero(isLineAxisStickyZero());

                if (getLinePeriodCount() > 0) {
                    if (getLineTicksLabelFormat() != null) {
                        final FastDecimalFormat formatter = new FastDecimalFormat(getLineTicksLabelFormat(),
                                getResourceBundleFactory().getLocale());
                        numberAxis.setTickUnit(new FastNumberTickUnit(getLinePeriodCount(), formatter));
                    } else {
                        numberAxis.setTickUnit(new FastNumberTickUnit(getLinePeriodCount()));
                    }
                } else {
                    if (getLineTicksLabelFormat() != null) {
                        final DecimalFormat formatter = new DecimalFormat(getLineTicksLabelFormat(),
                                new DecimalFormatSymbols(getResourceBundleFactory().getLocale()));
                        numberAxis.setNumberFormatOverride(formatter);
                    }
                }
            } else if (linesAxis instanceof DateAxis) {
                final DateAxis numberAxis = (DateAxis) linesAxis;

                if (getLinePeriodCount() > 0 && getLineTimePeriod() != null) {
                    if (getLineTicksLabelFormat() != null) {
                        final SimpleDateFormat formatter = new SimpleDateFormat(getLineTicksLabelFormat(),
                                new DateFormatSymbols(getResourceBundleFactory().getLocale()));
                        numberAxis.setTickUnit(new DateTickUnit(getDateUnitAsInt(getLineTimePeriod()),
                                (int) getLinePeriodCount(), formatter));
                    } else {
                        numberAxis.setTickUnit(new DateTickUnit(getDateUnitAsInt(getLineTimePeriod()),
                                (int) getLinePeriodCount()));
                    }
                } else if (getRangeTickFormatString() != null) {
                    final SimpleDateFormat formatter = new SimpleDateFormat(getRangeTickFormatString(),
                            new DateFormatSymbols(getResourceBundleFactory().getLocale()));
                    numberAxis.setDateFormatOverride(formatter);
                }
            }

            if (linesAxis != null) {
                final Font labelFont = Font.decode(getLabelFont());
                linesAxis.setLabelFont(labelFont);
                linesAxis.setTickLabelFont(labelFont);

                if (getLineTitleFont() != null) {
                    linesAxis.setLabelFont(getLineTitleFont());
                }
                if (getLineTickFont() != null) {
                    linesAxis.setTickLabelFont(getLineTickFont());
                }
                final int level = getRuntime().getProcessingContext().getCompatibilityLevel();
                if (ClassicEngineBoot.isEnforceCompatibilityFor(level, 3, 8)) {
                    if (getRangeMinimum() != 0) {
                        linesAxis.setLowerBound(getLineRangeMinimum());
                    }
                    if (getRangeMaximum() != 1) {
                        linesAxis.setUpperBound(getLineRangeMaximum());
                    }
                    if (getLineRangeMinimum() == 0 && getLineRangeMaximum() == 1) {
                        linesAxis.setLowerBound(0);
                        linesAxis.setUpperBound(1);
                        linesAxis.setAutoRange(true);
                    }
                } else {
                    linesAxis.setLowerBound(getLineRangeMinimum());
                    linesAxis.setUpperBound(getLineRangeMaximum());
                    linesAxis.setAutoRange(isLineAxisAutoRange());
                }
            }
        }

        final LineAndShapeRenderer linesRenderer = (LineAndShapeRenderer) plot.getRenderer(1);
        if (linesRenderer != null) {
            //set stroke with line width
            linesRenderer.setStroke(translateLineStyle(lineWidth, lineStyle));
            //hide shapes on line
            linesRenderer.setShapesVisible(isMarkersVisible());
            linesRenderer.setBaseShapesFilled(isMarkersVisible());

            //set colors for each line
            for (int i = 0; i < lineSeriesColor.size(); i++) {
                final String s = (String) lineSeriesColor.get(i);
                linesRenderer.setSeriesPaint(i, parseColorFromString(s));
            }
        }
    }

    private String convertFontToString(final Font font) {
        if (font == null) {
            return null;
        }

        final String fontName = font.getFamily();
        final int fontSize = font.getSize();
        final int fontStyle = font.getStyle();
        final String fontStyleText;
        if ((fontStyle & (Font.BOLD | Font.ITALIC)) == (Font.BOLD | Font.ITALIC)) {
            fontStyleText = "BOLDITALIC";
        } else if ((fontStyle & Font.BOLD) == Font.BOLD) {
            fontStyleText = "BOLD";
        } else if ((fontStyle & Font.ITALIC) == Font.ITALIC) {
            fontStyleText = "ITALIC";
        } else {
            fontStyleText = "PLAIN";
        }
        return (fontName + "-" + fontStyleText + "-" + fontSize);
    }

    public void reconfigureForCompatibility(final int versionTag) {
        super.reconfigureForCompatibility(versionTag);

        if (ClassicEngineBoot.isEnforceCompatibilityFor(versionTag, 3, 8)) {
            setLineAxisAutoRange(getLineRangeMinimum() == 0 && getLineRangeMaximum() == 1);
        }
    }
}