com.manydesigns.portofino.pageactions.chart.jfreechart.JFreeChartAction.java Source code

Java tutorial

Introduction

Here is the source code for com.manydesigns.portofino.pageactions.chart.jfreechart.JFreeChartAction.java

Source

/*
 * Copyright (C) 2005-2015 ManyDesigns srl.  All rights reserved.
 * http://www.manydesigns.com/
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 3 of
 * the License, or (at your option) any later version.
 *
 * This software 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.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package com.manydesigns.portofino.pageactions.chart.jfreechart;

import com.manydesigns.elements.ElementsThreadLocals;
import com.manydesigns.elements.fields.Field;
import com.manydesigns.elements.forms.Form;
import com.manydesigns.elements.forms.FormBuilder;
import com.manydesigns.elements.messages.SessionMessages;
import com.manydesigns.elements.options.DefaultSelectionProvider;
import com.manydesigns.elements.options.SelectionProvider;
import com.manydesigns.elements.util.RandomUtil;
import com.manydesigns.portofino.buttons.annotations.Button;
import com.manydesigns.portofino.chart.ChartGenerator;
import com.manydesigns.portofino.di.Inject;
import com.manydesigns.portofino.logic.SelectionProviderLogic;
import com.manydesigns.portofino.model.database.Database;
import com.manydesigns.portofino.modules.DatabaseModule;
import com.manydesigns.portofino.pageactions.AbstractPageAction;
import com.manydesigns.portofino.pageactions.PageActionName;
import com.manydesigns.portofino.pageactions.annotations.ConfigurationClass;
import com.manydesigns.portofino.pageactions.annotations.ScriptTemplate;
import com.manydesigns.portofino.pageactions.chart.jfreechart.configuration.JFreeChartConfiguration;
import com.manydesigns.portofino.persistence.Persistence;
import com.manydesigns.portofino.security.AccessLevel;
import com.manydesigns.portofino.security.RequiresPermissions;
import net.sourceforge.stripes.action.*;
import net.sourceforge.stripes.util.UrlBuilder;
import org.jfree.chart.JFreeChart;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;

/*
* @author Paolo Predonzani     - paolo.predonzani@manydesigns.com
* @author Angelo Lupo          - angelo.lupo@manydesigns.com
* @author Giampiero Granatella - giampiero.granatella@manydesigns.com
* @author Alessio Stalla       - alessio.stalla@manydesigns.com
*/
@RequiresPermissions(level = AccessLevel.VIEW)
@ScriptTemplate("script_template.groovy")
@ConfigurationClass(JFreeChartConfiguration.class)
@PageActionName("Chart (with JFreeChart)")
public class JFreeChartAction extends AbstractPageAction {
    public static final String copyright = "Copyright (c) 2005-2015, ManyDesigns srl";

    //**************************************************************************
    // Constants
    //**************************************************************************

    public static final String CHART_FILENAME_FORMAT = "chart-{0}.png";

    //**************************************************************************
    // Injections
    //**************************************************************************

    @Inject(DatabaseModule.PERSISTENCE)
    public Persistence persistence;

    //**************************************************************************
    // Web parameters
    //**************************************************************************

    public String chartId;

    public int width = 470;
    public int height = 354;
    public boolean antiAlias = true;
    public boolean borderVisible = true;

    //**************************************************************************
    // Model metadata
    //**************************************************************************

    public JFreeChartConfiguration chartConfiguration;

    //**************************************************************************
    // Presentation elements
    //**************************************************************************

    public Form form;
    public JFreeChart chart;
    public JFreeChartInstance jfreeChartInstance;
    public File file;

    public static final Logger logger = LoggerFactory.getLogger(JFreeChartAction.class);

    //**************************************************************************
    // Action default execute method
    //**************************************************************************

    @DefaultHandler
    public Resolution execute() {
        if (chartConfiguration == null) {
            return forwardToPageActionNotConfigured();
        }

        try {
            // Run/generate the chart
            try {
                Thread.currentThread().setContextClassLoader(Class.class.getClassLoader());
                generateChart();
            } finally {
                Thread.currentThread().setContextClassLoader(JFreeChartAction.class.getClassLoader());
            }

            chartId = RandomUtil.createRandomId();

            String actionurl = context.getActionPath();
            UrlBuilder chartResolution = new UrlBuilder(context.getLocale(), actionurl, false)
                    .addParameter("chartId", chartId).addParameter("chart", "");
            String url = context.getRequest().getContextPath() + chartResolution.toString();

            file = RandomUtil.getTempCodeFile(CHART_FILENAME_FORMAT, chartId);

            jfreeChartInstance = new JFreeChartInstance(chart, file, chartId,
                    "Chart: " + chartConfiguration.getName(), width, height, url);
        } catch (Throwable e) {
            logger.error("Chart exception", e);
            return forwardToPageActionError(e);
        }

        return new ForwardResolution("/m/chart/jfreechart/display.jsp");
    }

    public void generateChart() {
        ChartGenerator chartGenerator;

        if (chartConfiguration.getGeneratorClass() == null) {
            throw new IllegalStateException("Invalid chart type: " + chartConfiguration.getActualType());
        }
        try {
            chartGenerator = chartConfiguration.getGeneratorClass().newInstance();
        } catch (Exception e) {
            throw new RuntimeException("Invalid generator for chart", e);
        }

        chartGenerator.setAntiAlias(antiAlias);
        chartGenerator.setBorderVisible(borderVisible);
        chartGenerator.setHeight(height);
        chartGenerator.setWidth(width);
        chart = chartGenerator.generate(chartConfiguration, persistence, context.getLocale());
    }

    public Resolution chart() throws FileNotFoundException {
        final File file = RandomUtil.getTempCodeFile(CHART_FILENAME_FORMAT, chartId);
        if (!file.exists()) {
            return new ErrorResolution(404);
        }
        final InputStream inputStream = new FileInputStream(file);

        //Cache the file, expire after 12h
        int expiresAfter = 12 * 60 * 60 * 1000;
        long now = System.currentTimeMillis();
        HttpServletResponse response = context.getResponse();
        response.setHeader("Cache-Control", "max-age=" + expiresAfter);
        response.setDateHeader("Last-Modified", now);
        response.setDateHeader("Expires", now + expiresAfter);
        response.setHeader("Pragma", "");

        return new StreamingResolution("image/png", inputStream) {
            @Override
            protected void stream(HttpServletResponse response) throws Exception {
                super.stream(response);
                if (!file.delete()) {
                    logger.warn("Could not delete temporary file for chart: " + file.getAbsolutePath());
                }
            }
        };
    }

    //**************************************************************************
    // Configuration
    //**************************************************************************

    public static final String[][] CONFIGURATION_FIELDS = {
            { "name", "type", "orientation", "legend", "database", "query", "urlExpression" } };

    public static final String[] chartTypes1D = { JFreeChartConfiguration.Type.PIE.name(),
            JFreeChartConfiguration.Type.PIE3D.name(), JFreeChartConfiguration.Type.RING.name() };

    public static final String[] chartTypes2D = { JFreeChartConfiguration.Type.AREA.name(),
            JFreeChartConfiguration.Type.BAR.name(), JFreeChartConfiguration.Type.BAR3D.name(),
            JFreeChartConfiguration.Type.LINE.name(), JFreeChartConfiguration.Type.LINE3D.name(),
            JFreeChartConfiguration.Type.STACKED_BAR.name(), JFreeChartConfiguration.Type.STACKED_BAR_3D.name() };

    public final String[] chartTypeValues = new String[chartTypes1D.length + chartTypes2D.length + 2];
    public final String[] chartTypeLabels = new String[chartTypeValues.length];

    @Button(list = "pageHeaderButtons", titleKey = "configure", order = 1, icon = Button.ICON_WRENCH)
    @RequiresPermissions(level = AccessLevel.DEVELOP)
    public Resolution configure() {
        prepareConfigurationForms();
        return new ForwardResolution("/m/chart/jfreechart/configure.jsp");
    }

    @Override
    protected void prepareConfigurationForms() {
        super.prepareConfigurationForms();

        String prefix = "com.manydesigns.portofino.jfreechart.type.";
        chartTypeValues[0] = "--1D";
        chartTypeLabels[0] = "-- 1D charts --";
        for (int i = 0; i < chartTypes1D.length; i++) {
            chartTypeValues[i + 1] = chartTypes1D[i];
            chartTypeLabels[i + 1] = ElementsThreadLocals.getText(prefix + chartTypes1D[i], chartTypes1D[i]);
        }
        chartTypeValues[chartTypes1D.length + 1] = "--2D";
        chartTypeLabels[chartTypes1D.length + 1] = "-- 2D charts --";
        for (int i = 0; i < chartTypes2D.length; i++) {
            chartTypeValues[i + 2 + chartTypes1D.length] = chartTypes2D[i];
            chartTypeLabels[i + 2 + chartTypes1D.length] = ElementsThreadLocals.getText(prefix + chartTypes2D[i],
                    chartTypes2D[i]);
        }

        SelectionProvider databaseSelectionProvider = SelectionProviderLogic.createSelectionProvider("database",
                persistence.getModel().getDatabases(), Database.class, null, new String[] { "databaseName" });
        DefaultSelectionProvider typeSelectionProvider = new DefaultSelectionProvider("type");
        for (int i = 0; i < chartTypeValues.length; i++) {
            typeSelectionProvider.appendRow(chartTypeValues[i], chartTypeLabels[i], true);
        }
        String[] orientationValues = { JFreeChartConfiguration.Orientation.HORIZONTAL.name(),
                JFreeChartConfiguration.Orientation.VERTICAL.name() };
        String[] orientationLabels = { "Horizontal", "Vertical" };
        DefaultSelectionProvider orientationSelectionProvider = new DefaultSelectionProvider("orientation");
        for (int i = 0; i < orientationValues.length; i++) {
            orientationSelectionProvider.appendRow(orientationValues[i], orientationLabels[i], true);
        }
        form = new FormBuilder(JFreeChartConfiguration.class).configFields(CONFIGURATION_FIELDS)
                .configFieldSetNames("Chart").configSelectionProvider(typeSelectionProvider, "type")
                .configSelectionProvider(orientationSelectionProvider, "orientation")
                .configSelectionProvider(databaseSelectionProvider, "database").build();
        form.readFromObject(chartConfiguration);
    }

    @Button(list = "configuration", key = "update.configuration", order = 1, type = Button.TYPE_PRIMARY)
    @RequiresPermissions(level = AccessLevel.DEVELOP)
    public Resolution updateConfiguration() {
        prepareConfigurationForms();
        form.readFromObject(chartConfiguration);
        form.readFromRequest(context.getRequest());
        readPageConfigurationFromRequest();
        boolean valid = form.validate();
        valid = validatePageConfiguration() && valid;
        Field typeField = form.findFieldByPropertyName("type");
        String typeValue = typeField.getStringValue();
        boolean placeHolderValue = typeValue != null && typeValue.startsWith("--");
        if (placeHolderValue) {
            valid = false;
            String errorMessage = ElementsThreadLocals.getTextProvider().getText("elements.error.field.required");
            typeField.getErrors().add(errorMessage);
            SessionMessages.addErrorMessage("");
        }
        if (valid) {
            updatePageConfiguration();
            if (chartConfiguration == null) {
                chartConfiguration = new JFreeChartConfiguration();
            }
            form.writeToObject(chartConfiguration);
            saveConfiguration(chartConfiguration);

            SessionMessages.addInfoMessage(ElementsThreadLocals.getText("configuration.updated.successfully"));
            return cancel();
        } else {
            return new ForwardResolution("/m/chart/jfreechart/configure.jsp");
        }
    }

    public Resolution preparePage() {
        if (!pageInstance.getParameters().isEmpty()) {
            return new ErrorResolution(404);
        }
        chartConfiguration = (JFreeChartConfiguration) pageInstance.getConfiguration();
        return null;
    }

    //**************************************************************************
    // Getter/setter
    //**************************************************************************

    public String getChartId() {
        return chartId;
    }

    public void setChartId(String chartId) {
        this.chartId = chartId;
    }

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public boolean isAntiAlias() {
        return antiAlias;
    }

    public void setAntiAlias(boolean antiAlias) {
        this.antiAlias = antiAlias;
    }

    public boolean isBorderVisible() {
        return borderVisible;
    }

    public void setBorderVisible(boolean borderVisible) {
        this.borderVisible = borderVisible;
    }

    public JFreeChartConfiguration getChartConfiguration() {
        return chartConfiguration;
    }

    public void setChartConfiguration(JFreeChartConfiguration chartConfiguration) {
        this.chartConfiguration = chartConfiguration;
    }

    public Form getForm() {
        return form;
    }

    public void setForm(Form form) {
        this.form = form;
    }

    public JFreeChart getChart() {
        return chart;
    }

    public void setChart(JFreeChart chart) {
        this.chart = chart;
    }

    public JFreeChartInstance getJfreeChartInstance() {
        return jfreeChartInstance;
    }

    public void setJfreeChartInstance(JFreeChartInstance jfreeChartInstance) {
        this.jfreeChartInstance = jfreeChartInstance;
    }

}