All Downloads are FREE. Search and download functionalities are using the official Maven repository.

hudson.util.ChartUtil Maven / Gradle / Ivy

package hudson.util;

import hudson.model.AbstractBuild;
import org.jfree.chart.ChartRenderingInfo;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.data.category.CategoryDataset;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import java.awt.Font;
import java.awt.HeadlessException;
import java.awt.image.BufferedImage;
import java.io.IOException;

/**
 * Chart generation utility code around JFreeChart.
 *
 * @see StackedAreaRenderer2
 * @see DataSetBuilder
 * @see ShiftedCategoryAxis
 * @author Kohsuke Kawaguchi
 */
public class ChartUtil {
    /**
     * Can be used as a graph label. Only displays numbers.
     */
    public static final class NumberOnlyBuildLabel implements Comparable {
        public final AbstractBuild build;

        public NumberOnlyBuildLabel(AbstractBuild build) {
            this.build = build;
        }

        public int compareTo(NumberOnlyBuildLabel that) {
            return this.build.number-that.build.number;
        }

        public boolean equals(Object o) {
            if(!(o instanceof NumberOnlyBuildLabel))    return false;
            NumberOnlyBuildLabel that = (NumberOnlyBuildLabel) o;
            return build==that.build;
        }

        public int hashCode() {
            return build.hashCode();
        }

        public String toString() {
            return build.getDisplayName();
        }
    }

    /**
     * See issue 93. Detect an error in X11 and handle it gracefully.
     */
    public static boolean awtProblem = false;

    /**
     * Generates the graph in PNG format and sends that to the response.
     *
     * @param defaultSize
     *      The size of the picture to be generated. These values can be overridden
     *      by the query paramter 'width' and 'height' in the request.
     */
    public static void generateGraph(StaplerRequest req, StaplerResponse rsp, JFreeChart chart, Area defaultSize) throws IOException {
        generateGraph(req,rsp,chart,defaultSize.width, defaultSize.height);
    }

    /**
     * Generates the graph in PNG format and sends that to the response.
     *
     * @param defaultW
     * @param defaultH
     *      The size of the picture to be generated. These values can be overridden
     *      by the query paramter 'width' and 'height' in the request.
     */
    public static void generateGraph(StaplerRequest req, StaplerResponse rsp, JFreeChart chart, int defaultW, int defaultH) throws IOException {
        try {
            String w = req.getParameter("width");
            if(w==null)     w=String.valueOf(defaultW);
            String h = req.getParameter("height");
            if(h==null)     h=String.valueOf(defaultH);
            BufferedImage image = chart.createBufferedImage(Integer.parseInt(w),Integer.parseInt(h));
            rsp.setContentType("image/png");
            ServletOutputStream os = rsp.getOutputStream();
            ImageIO.write(image, "PNG", os);
            os.close();
        } catch(HeadlessException e) {
            // not available. send out error message
            rsp.sendRedirect2(req.getContextPath()+"/images/headless.png");
        }
    }

    /**
     * Generates the clickable map info and sends that to the response.
     */
    public static void generateClickableMap(StaplerRequest req, StaplerResponse rsp, JFreeChart chart, Area defaultSize) throws IOException {
        generateClickableMap(req,rsp,chart,defaultSize.width,defaultSize.height);
    }

    /**
     * Generates the clickable map info and sends that to the response.
     */
    public static void generateClickableMap(StaplerRequest req, StaplerResponse rsp, JFreeChart chart, int defaultW, int defaultH) throws IOException {
        String w = req.getParameter("width");
        if(w==null)     w=String.valueOf(defaultW);
        String h = req.getParameter("height");
        if(h==null)     h=String.valueOf(defaultH);

        ChartRenderingInfo info = new ChartRenderingInfo();
        chart.createBufferedImage(Integer.parseInt(w),Integer.parseInt(h),info);

        rsp.setContentType("text/plain;charset=UTF-8");
        rsp.getWriter().println(ChartUtilities.getImageMap( "map", info ));
    }

    /**
     * Adjusts the Y-axis so that abnormally large value won't spoil the whole chart
     * by making everything look virtually 0.
     *
     * 

* The algorithm is based on Chebyshev's inequality, * which states that given any number sequence, nore more than 1/(N^2) values are more than N x stddev away * from the average. * *

* So the algorithm is to set Y-axis range so that we can see all data points that are within N x stddev * of the average. Most of the time, Cebyshev's inequality is very conservative, so it shouldn't do * much harm. * *

* When the algorithm does kick in, however, we can kick out at most 1 in N^2 data points. * (So for example if N=3 then we can "fix" the graph as long as we only have less than 1/(3*3)=11.111...% bad data. * *

* Also see issue #1246. */ public static void adjustChebyshev(CategoryDataset dataset, NumberAxis yAxis) { // first compute E(X) and Var(X) double sum=0,sum2=0; final int nColumns = dataset.getColumnCount(); final int nRows = dataset.getRowCount(); for (int i=0; i





© 2015 - 2025 Weber Informatics LLC | Privacy Policy