org.n52.io.img.ChartRenderer.java Source code

Java tutorial

Introduction

Here is the source code for org.n52.io.img.ChartRenderer.java

Source

/**
 * Copyright (C) 2013-2014 52North Initiative for Geospatial Open Source
 * Software GmbH
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License version 2 as publishedby the Free
 * Software Foundation.
 *
 * If the program is linked with libraries which are licensed under one of the
 * following licenses, the combination of the program with the linked library is
 * not considered a "derivative work" of the program:
 *
 *     - Apache License, version 2.0
 *     - Apache Software License, version 1.0
 *     - GNU Lesser General Public License, version 3
 *     - Mozilla Public License, versions 1.0, 1.1 and 2.0
 *     - Common Development and Distribution License (CDDL), version 1.0
 *
 * Therefore the distribution of the program linked with libraries licensed under
 * the aforementioned licenses, is permitted by the copyright holders if the
 * distribution is compliant with both the GNU General Public License version 2
 * and the aforementioned licenses.
 *
 * 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.
 */
package org.n52.io.img;

import static java.awt.Color.BLACK;
import static java.awt.Color.LIGHT_GRAY;
import static java.awt.Color.WHITE;
import static java.awt.Font.BOLD;
import static java.awt.Font.PLAIN;
import static java.awt.image.BufferedImage.TYPE_INT_RGB;
import static javax.imageio.ImageIO.write;
import static org.jfree.chart.ChartFactory.createTimeSeriesChart;
import static org.n52.io.I18N.getDefaultLocalizer;
import static org.n52.io.I18N.getMessageLocalizer;
import static org.n52.io.img.BarRenderer.BAR_CHART_TYPE;
import static org.n52.io.img.ChartRenderer.LabelConstants.COLOR;
import static org.n52.io.img.ChartRenderer.LabelConstants.FONT_LABEL;
import static org.n52.io.img.LineRenderer.LINE_CHART_TYPE;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.imageio.plugins.jpeg.JPEGImageWriteParam;

import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.ui.RectangleInsets;
import org.joda.time.Interval;
import org.n52.io.I18N;
import org.n52.io.IoHandler;
import org.n52.io.IoParseException;
import org.n52.io.MimeType;
import org.n52.io.format.TvpDataCollection;
import org.n52.io.v1.data.DesignedParameterSet;
import org.n52.io.v1.data.PhenomenonOutput;
import org.n52.io.v1.data.StyleProperties;
import org.n52.io.v1.data.TimeseriesMetadataOutput;
import org.n52.io.v1.data.TimeseriesOutput;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class ChartRenderer implements IoHandler {

    private static final Logger LOGGER = LoggerFactory.getLogger(ChartRenderer.class);

    protected I18N i18n = getDefaultLocalizer();

    private RenderingContext context;

    private boolean showTooltips;

    private MimeType mimeType;

    private boolean drawLegend;

    private boolean generalize;

    private boolean showGrid;

    private JFreeChart chart;

    private XYPlot xyPlot;

    public ChartRenderer(RenderingContext context, String locale) {
        if (locale != null) {
            i18n = getMessageLocalizer(locale);
        }
        this.context = context;
    }

    public abstract void generateOutput(TvpDataCollection data) throws IoParseException;

    public void encodeAndWriteTo(OutputStream stream) throws IoParseException {
        try {
            JPEGImageWriteParam p = new JPEGImageWriteParam(null);
            p.setCompressionMode(JPEGImageWriteParam.MODE_DEFAULT);
            write(drawChartToImage(), mimeType.getFormatName(), stream);
        } catch (IOException e) {
            throw new IoParseException("Could not write image to output stream.", e);
        } finally {
            try {
                stream.flush();
                stream.close();
            } catch (IOException e) {
                LOGGER.debug("Stream already flushed and closed.", e);
            }
        }
    }

    private BufferedImage drawChartToImage() {
        int width = getChartStyleDefinitions().getWidth();
        int height = getChartStyleDefinitions().getHeight();
        BufferedImage chartImage = new BufferedImage(width, height, TYPE_INT_RGB);
        Graphics2D chartGraphics = chartImage.createGraphics();
        chartGraphics.fillRect(0, 0, width, height);
        chartGraphics.setColor(WHITE);

        chart.setTextAntiAlias(true);
        chart.setAntiAlias(true);
        chart.draw(chartGraphics, new Rectangle2D.Float(0, 0, width, height));
        return chartImage;
    }

    public XYPlot getXYPlot() {
        if (xyPlot == null) {
            xyPlot = createChart(context);
        }
        return xyPlot;
    }

    public RenderingContext getRenderingContext() {
        return context;
    }

    public MimeType getMimeType() {
        return mimeType;
    }

    public void setMimeType(MimeType mimeType) {
        this.mimeType = mimeType;
    }

    public boolean isDrawLegend() {
        return drawLegend;
    }

    public void setDrawLegend(boolean drawLegend) {
        this.drawLegend = drawLegend;
    }

    public boolean isGeneralize() {
        return generalize;
    }

    public void setGeneralize(boolean generalize) {
        this.generalize = generalize;
    }

    public boolean isShowGrid() {
        return showGrid;
    }

    public void setShowGrid(boolean showGrid) {
        this.showGrid = showGrid;
    }

    public boolean isShowTooltips() {
        return showTooltips;
    }

    public void setShowTooltips(boolean showTooltips) {
        this.showTooltips = showTooltips;
    }

    private XYPlot createChart(RenderingContext context) {
        this.chart = createTimeSeriesChart(null, i18n.get("time"), i18n.get("value"), null, drawLegend,
                showTooltips, true);
        return createPlotArea(chart);
    }

    private XYPlot createPlotArea(JFreeChart chart) {
        XYPlot xyPlot = chart.getXYPlot();
        xyPlot.setBackgroundPaint(WHITE);
        xyPlot.setDomainGridlinePaint(LIGHT_GRAY);
        xyPlot.setRangeGridlinePaint(LIGHT_GRAY);
        xyPlot.setAxisOffset(new RectangleInsets(2.0, 2.0, 2.0, 2.0));
        showCrosshairsOnAxes(xyPlot);
        configureDomainAxis(xyPlot);
        showGridlinesOnChart(xyPlot);
        configureTimeAxis(xyPlot);
        return xyPlot;
    }

    private void configureDomainAxis(XYPlot xyPlot) {
        ValueAxis domainAxis = xyPlot.getDomainAxis();
        domainAxis.setTickLabelFont(FONT_LABEL);
        domainAxis.setLabelFont(FONT_LABEL);
        domainAxis.setTickLabelPaint(COLOR);
        domainAxis.setLabelPaint(COLOR);
    }

    private void showCrosshairsOnAxes(XYPlot xyPlot) {
        xyPlot.setDomainCrosshairVisible(true);
        xyPlot.setRangeCrosshairVisible(true);
    }

    private void showGridlinesOnChart(XYPlot xyPlot) {
        xyPlot.setDomainGridlinesVisible(showGrid);
        xyPlot.setRangeGridlinesVisible(showGrid);
    }

    private void configureTimeAxis(XYPlot xyPlot) {
        String timespan = getChartStyleDefinitions().getTimespan();
        DateAxis timeAxis = (DateAxis) xyPlot.getDomainAxis();
        timeAxis.setRange(getStartTime(timespan), getEndTime(timespan));
        timeAxis.setDateFormatOverride(new SimpleDateFormat());
    }

    public ValueAxis createRangeAxis(TimeseriesMetadataOutput metadata) {
        NumberAxis axis = new NumberAxis(createRangeLabel(metadata));
        axis.setTickLabelFont(FONT_LABEL);
        axis.setLabelFont(FONT_LABEL);
        axis.setTickLabelPaint(COLOR);
        axis.setLabelPaint(COLOR);
        return axis;
    }

    protected String createRangeLabel(TimeseriesMetadataOutput timeseriesMetadata) {
        TimeseriesOutput parameters = timeseriesMetadata.getParameters();
        PhenomenonOutput phenomenon = parameters.getPhenomenon();
        StringBuilder uom = new StringBuilder();
        uom.append(phenomenon.getLabel());
        String uomLabel = timeseriesMetadata.getUom();
        if (uomLabel != null && !uomLabel.isEmpty()) {
            uom.append(" [").append(uomLabel).append("]");
        }
        return uom.toString();
    }

    protected TimeseriesMetadataOutput[] getTimeseriesMetadataOutputs() {
        return context.getTimeseriesMetadatas();
    }

    protected StyleProperties getTimeseriesStyleFor(String timeseriesId) {
        return getChartStyleDefinitions().getStyleOptions(timeseriesId);
    }

    protected StyleProperties getTimeseriesStyleFor(String timeseriesId, String referenceValueSeriesId) {
        return getChartStyleDefinitions().getReferenceSeriesStyleOptions(timeseriesId, referenceValueSeriesId);
    }

    protected DesignedParameterSet getChartStyleDefinitions() {
        return context.getChartStyleDefinitions();
    }

    protected boolean isLineStyle(StyleProperties properties) {
        return isLineStyleDefault(properties) || LINE_CHART_TYPE.equals(properties.getChartType());
    }

    protected boolean isBarStyle(StyleProperties properties) {
        return !isLineStyleDefault(properties) && BAR_CHART_TYPE.equals(properties.getChartType());
    }

    private boolean isLineStyleDefault(StyleProperties properties) {
        return properties == null;
    }

    protected Date getStartTime(String timespan) {
        Interval interval = Interval.parse(timespan);
        return interval.getStart().toDate();
    }

    protected Date getEndTime(String timespan) {
        Interval interval = Interval.parse(timespan);
        return interval.getEnd().toDate();
    }

    static class LabelConstants {
        static final Color COLOR = BLACK;
        static final int FONT_SIZE = 12;
        static final int FONT_SIZE_TICKS = 10;
        static final String LOGICAL_FONT = "Sans-serif";
        static final Font FONT_LABEL = new Font(LOGICAL_FONT, BOLD, FONT_SIZE);
        static final Font FONT_DOMAIN = new Font(LOGICAL_FONT, PLAIN, FONT_SIZE_TICKS);
    }

}