edu.cudenver.bios.chartsvc.resource.LegendResource.java Source code

Java tutorial

Introduction

Here is the source code for edu.cudenver.bios.chartsvc.resource.LegendResource.java

Source

/*
 * Chart Service for the GLIMMPSE Software System.  Creates
 * publishable quality scatter plots.
 * 
 * Copyright (C) 2010 Regents of the University of Colorado.  
 *
 * 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 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.
 */
package edu.cudenver.bios.chartsvc.resource;

import java.awt.BasicStroke;
import java.awt.Color;
import java.io.IOException;
import java.util.List;

import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYSplineRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.restlet.data.Form;
import org.restlet.data.Status;
import org.restlet.representation.Representation;
import org.restlet.representation.Variant;
import org.restlet.resource.Get;
import org.restlet.resource.ResourceException;
import org.restlet.resource.ServerResource;

import edu.cudenver.bios.chartsvc.application.ChartLogger;
import edu.cudenver.bios.chartsvc.domain.Axis;
import edu.cudenver.bios.chartsvc.domain.Chart;
import edu.cudenver.bios.chartsvc.domain.Series;
import edu.cudenver.bios.chartsvc.representation.ErrorXMLRepresentation;
import edu.cudenver.bios.chartsvc.representation.LegendImageRepresentation;

/**
 * Creates a legend for a scatter plot as a separate image.
 * Used for plots with several data series resulting in a large
 * legend.
 * @author Sarah Kreidler
 *
 */
public class LegendResource extends ServerResource {
    private static final int DEFAULT_WIDTH = 300;
    private static final int DEFAULT_HEIGHT = 300;

    private static final String FORM_TAG_CHART = "chart";
    private static final String FORM_TAG_SAVE = "save";

    private Form queryParams = null;

    /**
     * Disallow GET requests
     */

    @Get
    public Representation represent(Variant variant) {
        queryParams = getRequest().getResourceRef().getQueryAsForm();
        LegendImageRepresentation rep = null;
        try {
            // parse the chart parameters from the entity body
            Chart chartSpecification = ChartResourceHelper.chartFromQueryString(queryParams, false);

            // build a JFreeChart from the specs
            XYPlot renderedChart = buildScatterPlot(chartSpecification);
            // write to an image representation
            rep = new LegendImageRepresentation(renderedChart, chartSpecification.getWidth(),
                    chartSpecification.getHeight());

            // Add file save headers if requested
            String saveStr = queryParams.getFirstValue(FORM_TAG_SAVE);
            boolean save = Boolean.parseBoolean(saveStr);
            if (save) {
                Form responseHeaders = (Form) getResponse().getAttributes().get("org.restlet.http.headers");
                if (responseHeaders == null) {
                    responseHeaders = new Form();
                    getResponse().getAttributes().put("org.restlet.http.headers", responseHeaders);
                }
                responseHeaders.add("Content-type", "application/force-download");
                responseHeaders.add("Content-disposition", "attachment; filename=chart.jpg");
            }

            getResponse().setEntity(rep);
            getResponse().setStatus(Status.SUCCESS_CREATED);
        } catch (IllegalArgumentException iae) {
            ChartLogger.getInstance().error(iae.getMessage());
            try {
                getResponse().setEntity(new ErrorXMLRepresentation(iae.getMessage()));
            } catch (IOException e) {
            }
            getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
        } catch (ResourceException re) {
            ChartLogger.getInstance().error(re.getMessage());
            try {
                getResponse().setEntity(new ErrorXMLRepresentation(re.getMessage()));
            } catch (IOException e) {
            }
            getResponse().setStatus(re.getStatus());
        }

        return rep;
    }

    private XYPlot buildScatterPlot(Chart chart) throws ResourceException {
        // the first series is treated as the x values
        if (chart.getSeries() == null || chart.getSeries().size() <= 0)
            throw new ResourceException(Status.CLIENT_ERROR_BAD_REQUEST, "No data series specified");

        // create the jfree chart series
        XYSeriesCollection chartData = new XYSeriesCollection();
        // use a spline renderer to make the connecting lines smooth
        XYSplineRenderer rend = new XYSplineRenderer();

        int seriesIdx = 0;
        for (Series series : chart.getSeries()) {
            XYSeries xySeries = new XYSeries(series.getLabel());

            List<Double> xList = series.getXCoordinates();
            List<Double> yList = series.getYCoordinates();
            if (xList != null && yList != null && xList.size() == yList.size()) {
                for (int i = 0; i < xList.size(); i++) {
                    xySeries.add(xList.get(i), yList.get(i));
                }
            }

            // set the line style
            rend.setSeriesPaint(seriesIdx, Color.BLACK);
            if (seriesIdx > 0) {
                rend.setSeriesStroke(seriesIdx, new BasicStroke(1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
                        1.0f, new float[] { (float) seriesIdx, (float) 2 * seriesIdx }, 0.0f));
            }
            // add the series to the data set
            chartData.addSeries(xySeries);
            seriesIdx++;
        }

        // turn off shapes displayed at each data point to make a smooth curve
        rend.setBaseShapesVisible(false);

        // Create the line chart
        NumberAxis xAxis = new NumberAxis();
        xAxis.setAutoRangeIncludesZero(false);
        if (chart.getXAxis() != null) {
            Axis xAxisSpec = chart.getXAxis();
            xAxis.setLabel(xAxisSpec.getLabel());
            if (!Double.isNaN(xAxisSpec.getRangeMin()) && !Double.isNaN(xAxisSpec.getRangeMax())) {
                xAxis.setRange(xAxisSpec.getRangeMin(), xAxisSpec.getRangeMax());
            }
        }
        NumberAxis yAxis = new NumberAxis();
        if (chart.getYAxis() != null) {
            Axis yAxisSpec = chart.getYAxis();
            yAxis.setLabel(chart.getYAxis().getLabel());
            if (!Double.isNaN(yAxisSpec.getRangeMin()) && !Double.isNaN(yAxisSpec.getRangeMax())) {
                xAxis.setRange(yAxisSpec.getRangeMin(), yAxisSpec.getRangeMax());
            }
        }
        XYPlot plot = new XYPlot((XYDataset) chartData, xAxis, yAxis, rend);
        plot.setDomainGridlinesVisible(false);
        plot.setRangeGridlinesVisible(false);

        return plot;
    }

}