📄 graphengine.java
字号:
/**
* $RCSfile $
* $Revision $
* $Date $
*
* Copyright (C) 2008 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution, or a commercial license
* agreement with Jive.
*/
package org.jivesoftware.openfire.reporting.graph;
import org.jivesoftware.openfire.reporting.stats.StatsViewer;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.labels.StandardPieSectionLabelGenerator;
import org.jfree.chart.axis.*;
import org.jfree.chart.encoders.KeypointPNGEncoderAdapter;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.plot.PiePlot;
import org.jfree.chart.renderer.xy.XYAreaRenderer;
import org.jfree.chart.renderer.xy.XYBarRenderer;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.data.time.*;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.IntervalXYDataset;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.util.Rotation;
import org.jivesoftware.openfire.stats.Statistic;
import org.jivesoftware.util.JiveGlobals;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.text.NumberFormat;
/**
* Builds graphs off of statistics tracked in the <i>StatsEngine</i>.
*
* @author Alexander Wenckus
* @see StatsViewer
*/
public class GraphEngine {
private StatsViewer statsViewer;
private static final long YEAR = 31104000000L;
private static final long MONTH = 2592000000L;
private static final long WEEK = 604800000L;
private static final long DAY = 86400000L;
private TickUnits tickUnits;
private Locale oldLocale;
/**
* Default constructor used by the plugin container to construct the graph engine.
*
* @param statsViewer The viewer provides an mechanism to view the data being tracked by the <i>StatsEngine</i>.
*/
public GraphEngine(StatsViewer statsViewer) {
this.statsViewer = statsViewer;
}
/**
* Creates a graph in PNG format. The PNG graph is encoded by the KeypointPNGEncoderAdapter
* so that the resulting PNG is encoded with alpha transparency.
*
* @param key
* @param width
* @param height
* @param startTime
* @param endTime
* @param dataPoints
* @return
* @throws IOException
*/
public byte[] generateGraph(String key, int width, int height, String color, long startTime, long endTime,
int dataPoints) throws IOException
{
JFreeChart chart = generateChart(key, width, height, color, startTime, endTime,dataPoints);
KeypointPNGEncoderAdapter encoder = new KeypointPNGEncoderAdapter();
encoder.setEncodingAlpha(true);
return encoder.encode(chart.createBufferedImage(width, height, BufferedImage.BITMASK, null));
}
/**
* Creates a chart.
*
* @param key
* @param width
* @param height
* @param startTime
* @param endTime
* @param dataPoints
* @return
* @throws IOException
*/
public JFreeChart generateChart(String key, int width, int height, String color, long startTime, long endTime,
int dataPoints) throws IOException
{
Statistic[] def = statsViewer.getStatistic(key);
if (def == null) {
return null;
}
XYDataset data = populateData(key, def, startTime, endTime, dataPoints);
if (data == null) {
return null;
}
JFreeChart chart;
switch(def[0].getStatType()) {
case count:
chart = createTimeBarChart(null, color, def[0].getUnits(), data);
break;
default:
chart = createTimeAreaChart(null, color, def[0].getUnits(), data);
}
return chart;
}
/**
* Generates a Sparkline type graph. Sparkline graphs
* are "intense, simple, wordlike graphics" so named by Edward Tufte. The big
* difference between the graph produced by this method compared to the
* graph produced by the <code>generateGraph</code> method is that this one
* produces graphs with no x-axis and no y-axis and is usually smaller in size.
* @param key
* @param width
* @param height
* @param startTime
* @param endTime
* @param dataPoints
* @return
* @throws IOException
*/
public byte[] generateSparklinesGraph(String key, int width, int height, String color, long startTime,
long endTime, int dataPoints) throws IOException
{
Statistic[] def = statsViewer.getStatistic(key);
if (def == null) {
return null;
}
JFreeChart chart;
switch (def[0].getStatType()) {
case count:
chart = generateSparklineBarGraph(key, color, def, startTime, endTime, dataPoints);
break;
default:
chart = generateSparklineAreaChart(key, color, def, startTime, endTime, dataPoints);
}
KeypointPNGEncoderAdapter encoder = new KeypointPNGEncoderAdapter();
encoder.setEncodingAlpha(true);
return encoder.encode(chart.createBufferedImage(width, height, BufferedImage.BITMASK, null));
}
private XYDataset populateData(String key, Statistic[] def, long startTime, long endTime,
int dataPoints)
{
double[][] values = statsViewer.getData(key, startTime, endTime, dataPoints);
long timePeriod = endTime - startTime;
TimeSeries[] series = new TimeSeries[values.length];
TimeSeriesCollection dataSet = new TimeSeriesCollection();
for (int d = 0; d < values.length; d++) {
series[d] = new TimeSeries(def[d].getName(), getTimePeriodClass(timePeriod));
Statistic.Type type = def[d].getStatType();
long interval = timePeriod / values[d].length;
for (int i = 0; i < values[d].length; i++) {
series[d].addOrUpdate(
getTimePeriod(timePeriod, new Date(startTime + (i * interval)),
JiveGlobals.getTimeZone()), cleanData(type, values[d][i]));
}
dataSet.addSeries(series[d]);
}
return dataSet;
}
private Class<? extends RegularTimePeriod> getTimePeriodClass(long timePeriod) {
if (timePeriod > 86400000) {
return Day.class;
} else if (timePeriod > 3600000) {
return Hour.class;
} else {
return Minute.class;
}
}
private RegularTimePeriod getTimePeriod(long timePeriod, Date date, TimeZone zone) {
if (timePeriod > 86400000) {
return new Day(date, zone);
} else if (timePeriod > 3600000) {
return new Hour(date, zone);
} else {
return new Minute(date, zone);
}
}
/**
* Round up a defined value.
*
* @param type the type of Statistic.
* @param value the value.
* @return the rounded up value.
*/
private double cleanData(Statistic.Type type, double value) {
if(type == Statistic.Type.count) {
return Math.round(value);
}
return value;
}
/**
* Generates a generic Time Area Chart.
*
* @param title the title of the Chart.
* @param valueLabel the Y Axis label.
* @param data the data to populate with.
* @return the generated Chart.
*/
private JFreeChart createTimeAreaChart(String title, String color, String valueLabel, XYDataset data) {
PlotOrientation orientation = PlotOrientation.VERTICAL;
DateAxis xAxis = generateTimeAxis();
NumberAxis yAxis = new NumberAxis(valueLabel);
NumberFormat formatter = NumberFormat.getNumberInstance(JiveGlobals.getLocale());
formatter.setMaximumFractionDigits(2);
formatter.setMinimumFractionDigits(0);
yAxis.setNumberFormatOverride(formatter);
XYAreaRenderer renderer = new XYAreaRenderer(XYAreaRenderer.AREA);
renderer.setOutline(true);
return createChart(title, data, xAxis, yAxis, orientation, renderer,
GraphDefinition.getDefinition(color));
}
/**
* Generates a generic Time Bar Chart.
*
* @param title the title of the Chart.
* @param valueLabel the X Axis Label.
* @param data the data to populate with.
* @return the generated Chart.
*/
private JFreeChart createTimeBarChart(String title, String color, String valueLabel, XYDataset data) {
PlotOrientation orientation = PlotOrientation.VERTICAL;
DateAxis xAxis = generateTimeAxis();
NumberAxis yAxis = new NumberAxis(valueLabel);
NumberFormat formatter = NumberFormat.getNumberInstance(JiveGlobals.getLocale());
formatter.setMaximumFractionDigits(2);
formatter.setMinimumFractionDigits(0);
yAxis.setNumberFormatOverride(formatter);
yAxis.setAutoRangeIncludesZero(true);
return createChart(title, data, xAxis, yAxis, orientation, new XYBarRenderer(),
GraphDefinition.getDefinition(color));
}
/**
* Generates a Chart.
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -