/*******************************************************************************
* Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
* Copyright (c) 2011 The OpenNMS Group, Inc.
*
* This library 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 2.1 of the License, or (at your option) any later version.
*
* This library 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 library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*******************************************************************************/
package org.jrobin.graph;
import org.jrobin.core.RrdException;
import org.jrobin.core.Util;
import org.jrobin.data.Plottable;
import java.awt.*;
import java.io.File;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
/**
* Class which should be used to define new JRobin graph. Once constructed and populated with data
* object of this class should be passed to the constructor of the {@link RrdGraph} class which
* will actually create the graph.
*
* The text printed below the actual graph can be formated by appending
* special escaped characters at the end of a text. When ever such a
* character occurs, all pending text is pushed onto the graph according to
* the character specified.
*
* Valid markers are: \j for justified, \l for left aligned, \r for right
* aligned and \c for centered.
*
* Normally there are two space characters inserted between every two
* items printed into the graph. The space following a string can be
* suppressed by putting a \g at the end of the string. The \g also squashes
* any space inside the string if it is at the very end of the string.
* This can be used in connection with %s to suppress empty unit strings.
*
* A special case is COMMENT:\s this inserts some additional vertical
* space before placing the next row of legends.
*
* When text has to be formated without special instructions from your
* side, RRDTool will automatically justify the text as soon as one string
* goes over the right edge. If you want to prevent the justification
* without forcing a newline, you can use the special tag \J at the end of
* the string to disable the auto justification.
*/
public class RrdGraphDef implements RrdGraphConstants {
boolean poolUsed = false; // ok
boolean antiAliasing = false; // ok
String filename = RrdGraphConstants.IN_MEMORY_IMAGE; // ok
long startTime, endTime; // ok
TimeAxisSetting timeAxisSetting = null; // ok
ValueAxisSetting valueAxisSetting = null; // ok
boolean altYGrid = false; // ok
boolean noMinorGrid = false; // ok
boolean altYMrtg = false; // ok
boolean altAutoscale = false; // ok
boolean altAutoscaleMax = false; // ok
int unitsExponent = Integer.MAX_VALUE; // ok
int unitsLength = DEFAULT_UNITS_LENGTH; // ok
String verticalLabel = null; // ok
int width = DEFAULT_WIDTH, height = DEFAULT_HEIGHT; // ok
boolean interlaced = false; // ok
String imageInfo = null; // ok
String imageFormat = DEFAULT_IMAGE_FORMAT; // ok
float imageQuality = DEFAULT_IMAGE_QUALITY; // ok
String backgroundImage = null; // ok
String overlayImage = null; // ok
String unit = null; // ok
String signature = "Created with JRobin"; // ok
boolean lazy = false; // ok
double minValue = Double.NaN; // ok
double maxValue = Double.NaN; // ok
boolean rigid = false; // ok
double base = DEFAULT_BASE; // ok
boolean logarithmic = false; // ok
Paint[] colors = new Paint[]{
// ok
DEFAULT_CANVAS_COLOR,
DEFAULT_BACK_COLOR,
DEFAULT_SHADEA_COLOR,
DEFAULT_SHADEB_COLOR,
DEFAULT_GRID_COLOR,
DEFAULT_MGRID_COLOR,
DEFAULT_FONT_COLOR,
DEFAULT_FRAME_COLOR,
DEFAULT_ARROW_COLOR
};
boolean noLegend = false; // ok
boolean onlyGraph = false; // ok
boolean forceRulesLegend = false; // ok
String title = null; // ok
long step = 0; // ok
Font[] fonts = new Font[FONTTAG_NAMES.length];
boolean drawXGrid = true; // ok
boolean drawYGrid = true; // ok
int firstDayOfWeek = FIRST_DAY_OF_WEEK; // ok
boolean showSignature = true;
File fontDir = null;
List sources = new ArrayList();
List comments = new ArrayList();
List plotElements = new ArrayList();
/**
* Creates RrdGraphDef object and sets default time span (default ending time is 'now',
* default starting time is 'end-1day'.
*/
public RrdGraphDef() {
try {
setTimeSpan(Util.getTimestamps(DEFAULT_START, DEFAULT_END));
} catch (RrdException e) {
throw new RuntimeException(e);
}
String fontdirProperty = System.getProperty("jrobin.fontdir");
if (fontdirProperty != null && fontdirProperty.length() != 0) {
fontDir = new File(fontdirProperty);
}
fonts[FONTTAG_DEFAULT] = new Font(DEFAULT_FONT_NAME, Font.PLAIN, 8);
fonts[FONTTAG_TITLE] = new Font(DEFAULT_FONT_NAME, Font.PLAIN, 9);
fonts[FONTTAG_AXIS] = new Font(DEFAULT_FONT_NAME, Font.PLAIN, 7);
fonts[FONTTAG_UNIT] = new Font(DEFAULT_FONT_NAME, Font.PLAIN, 8);
fonts[FONTTAG_LEGEND] = new Font(DEFAULT_FONT_NAME, Font.PLAIN, 8);
fonts[FONTTAG_WATERMARK] = new Font(DEFAULT_FONT_NAME, Font.PLAIN, 1).deriveFont(5.5F);
}
protected Font getFontFromResourceName(String name) {
Font font = null;
Exception exception = null;
URL file = null;
if (fontDir != null) {
try {
file = new URL("file://" + new File(fontDir, name).getAbsolutePath());
} catch (MalformedURLException e) {
// fall through to the jar
exception = e;
}
}
if (file == null) {
file = this.getClass().getResource(name);
}
if (file != null) {
// System.err.println("Found a font URL: " + file.toExternalForm());
try {
InputStream fontStream = file.openStream();
font = Font.createFont(Font.TRUETYPE_FONT, fontStream);
fontStream.close();
} catch (Exception e) {
exception = e;
}
}
else {
// we can't find our fonts, fall back to the system font
System.err.println("An error occurred loading the font '" + name + "'. Falling back to the default.");
if (exception != null) {
System.err.println(exception.getLocalizedMessage());
}
font = new Font(DEFAULT_FONT_NAME, Font.PLAIN, 10);
}
if (font == null) {
font = new Font(null, Font.PLAIN, 10);
}
return font;
}
/**
* Sets the signature string that runs along the right-side of the graph.
* Defaults to "Created with JRobin".
*
* @param signature the string to print
*/
public void setSignature(String signature) {
this.signature = signature;
}
/**
* Gets the signature string that runs along the right-side of the graph.
*
* @return the signature string
*/
public String getSignature() {
return this.signature;
}
/**
* Sets the time when the graph should begin. Time in seconds since epoch
* (1970-01-01) is required. Negative numbers are relative to the current time.
*
* @param time Starting time for the graph in seconds since epoch
*/
public void setStartTime(long time) {
this.startTime = time;
if (time <= 0) {
this.startTime += Util.getTime();
}
}
/**
* Sets the time when the graph should end. Time in seconds since epoch
* (1970-01-01) is required. Negative numbers are relative to the current time.
*
* @param time Ending time for the graph in seconds since epoch
*/
public void setEndTime(long time) {
this.endTime = time;
if (time <= 0) {
this.endTime += Util.getTime();
}
}
/**
* Sets starting and ending time for the for the graph. Timestamps in seconds since epoch are
* required. Negative numbers are relative to the current time.
*
* @param startTime Starting time in seconds since epoch
* @param endTime Ending time in seconds since epoch
*/
public void setTimeSpan(long startTime, long endTime) {
setStartTime(startTime);
setEndTime(endTime);
}
/**
* Sets starting and ending time for the for the graph. Timestamps in seconds since epoch are
* required.
*
* @param timestamps Array of timestamps. The first array item will be chosen for the starting
* timestamp. The last array item will be chosen for the ending timestamp.
*/
public void setTimeSpan(long[] timestamps) {
setTimeSpan(timestamps[0], timestamps[timestamps.length - 1]);
}
/**
* Sets RrdDbPool usage policy (defaults to true). If set to true,
* {@link org.jrobin.core.RrdDbPool RrdDbPool} will be used to
* access individual RRD files. If set to false, RRD files will be accessed directly.
*
* @param poolUsed true, if RrdDbPool class should be used. False otherwise.
*/
public void setPoolUsed(boolean poolUsed) {
this.poolUsed = poolUsed;
}
/**
* Sets the name of the graph to generate. Since JRobin outputs GIFs, PNGs,
* and JPEGs it's recommended that the filename end in either .gif,
* .png or .jpg. JRobin does not enforce this, however. If the filename is
* set to '-' the image will be created only in memory (no file will be created).
* PNG and GIF formats are recommended but JPEGs should be avoided.
*
* @param filename Path to the image file
*/
public void setFilename(String filename) {
this.filename = filename;
}
/**
* Configures x-axis grid and labels. The x-axis label is quite complex to configure.
* So if you don't have very special needs, you can rely on the autoconfiguration to
* get this right.
*
* Otherwise, you have to configure three elements making up the x-axis labels
* and grid. The base grid, the major grid and the labels.
* The configuration is based on the idea that you first specify a well
* known amount of time and then say how many times
* it has to pass between each minor/major grid line or label. For the label
* you have to define two additional items: The precision of the label
* in seconds and the format used to generate the text
* of the label.
*
* For example, if you wanted a graph with a base grid every 10 minutes and a major
* one every hour, with labels every hour you would use the following
* x-axis definition.
*
*
* setTimeAxis(RrdGraphConstants.MINUTE, 10,
* RrdGraphConstants.HOUR, 1,
* RrdGraphConstants.HOUR, 1,
* 0, "%H:%M")
*
*
* The precision in this example is 0 because the %X format is exact.
* If the label was the name of the day, we would have had a precision
* of 24 hours, because when you say something like 'Monday' you mean
* the whole day and not Monday morning 00:00. Thus the label should
* be positioned at noon. By defining a precision of 24 hours or
* rather 86400 seconds, you make sure that this happens.
*
* @param minorUnit Minor grid unit. Minor grid, major grid and label units
* can be one of the following constants defined in
* {@link RrdGraphConstants}: {@link RrdGraphConstants#SECOND SECOND},
* {@link RrdGraphConstants#MINUTE MINUTE}, {@link RrdGraphConstants#HOUR HOUR},
* {@link RrdGraphConstants#DAY DAY}, {@link RrdGraphConstants#WEEK WEEK},
* {@link RrdGraphConstants#MONTH MONTH}, {@link RrdGraphConstants#YEAR YEAR}.
* @param minorUnitCount Number of minor grid units between minor grid lines.
* @param majorUnit Major grid unit.
* @param majorUnitCount Number of major grid units between major grid lines.
* @param labelUnit Label unit.
* @param labelUnitCount Number of label units between labels.
* @param labelSpan Label precision
* @param simpleDateFormat Date format (SimpleDateFormat pattern of strftime-like pattern)
*/
public void setTimeAxis(int minorUnit, int minorUnitCount, int majorUnit, int majorUnitCount,
int labelUnit, int labelUnitCount, int labelSpan, String simpleDateFormat) {
timeAxisSetting = new TimeAxisSetting(minorUnit, minorUnitCount, majorUnit, majorUnitCount,
labelUnit, labelUnitCount, labelSpan, simpleDateFormat);
}
/**
* Sets vertical axis grid and labels. Makes vertical grid lines appear
* at gridStep interval. Every labelFactor*gridStep, a major grid line is printed,
* along with label showing the value of the grid line.
*
* @param gridStep Minor grid step
* @param labelFactor Specifies how many minor minor grid steps will appear between labels
* (major grid lines)
*/
public void setValueAxis(double gridStep, int labelFactor) {
valueAxisSetting = new ValueAxisSetting(gridStep, labelFactor);
}
/**
* Places Y grid dynamically based on graph Y range. Algorithm ensures
* that you always have grid, that there are enough but not too many
* grid lines and the grid is metric. That is grid lines are placed
* every 1, 2, 5 or 10 units.
*
* @param altYGrid true, if Y grid should be calculated dynamically (defaults to false)
*/
public void setAltYGrid(boolean altYGrid) {
this.altYGrid = altYGrid;
}
/**
* Use this method to turn off minor grid lines (printed by default)
*
* @param noMinorGrid true, to turn off, false to turn on (default)
*/
public void setNoMinorGrid(boolean noMinorGrid) {
this.noMinorGrid = noMinorGrid;
}
/**
* Use this method to request MRTG-like graph (false by default)
*
* @param altYMrtg true, to create MRTG-like graph, false otherwise (default)
*/
public void setAltYMrtg(boolean altYMrtg) {
this.altYMrtg = altYMrtg;
}
/**
* Computes Y range based on function absolute minimum and maximum
* values. Default algorithm uses predefined set of ranges. This is
* good in many cases but it fails miserably when you need to graph
* something like 260 + 0.001 * sin(x). Default algorithm will use Y
* range from 250 to 300 and on the graph you will see almost straight
* line. With --alt-autoscale Y range will be from slightly less the
* 260 - 0.001 to slightly more then 260 + 0.001 and periodic behavior
* will be seen.
*
* @param altAutoscale true to request alternative autoscaling, false otherwise
* (default).
*/
public void setAltAutoscale(boolean altAutoscale) {
this.altAutoscale = altAutoscale;
}
/**
* Computes Y range based on function absolute minimum and maximum
* values. Where setAltAutoscale(true) will modify both the absolute maximum AND
* minimum values, this option will only affect the maximum value. The
* minimum value, if not defined elsewhere, will be 0. This
* option can be useful when graphing router traffic when the WAN line
* uses compression, and thus the throughput may be higher than the
* WAN line speed.
*
* @param altAutoscaleMax true to request alternative autoscaling, false
* otherwise (default)
*/
public void setAltAutoscaleMax(boolean altAutoscaleMax) {
this.altAutoscaleMax = altAutoscaleMax;
}
/**
* Sets the 10**unitsExponent scaling of the y-axis values. Normally
* values will be scaled to the appropriate units (k, M, etc.). However
* you may wish to display units always in k (Kilo, 10e3) even if
* the data is in the M (Mega, 10e6) range for instance. Value should
* be an integer which is a multiple of 3 between -18 and 18, inclu-
* sive. It is the exponent on the units you which to use. For example,
* use 3 to display the y-axis values in k (Kilo, 10e3, thou-
* sands), use -6 to display the y-axis values in u (Micro, 10e-6,
* millionths). Use a value of 0 to prevent any scaling of the y-axis
* values.
*
* @param unitsExponent the 10**unitsExponent value for scaling y-axis values.
*/
public void setUnitsExponent(int unitsExponent) {
this.unitsExponent = unitsExponent;
}
/**
* Sets the character width on the left side of the graph for
* y-axis values.
*
* @param unitsLength Number of characters on the left side of the graphs
* reserved for vertical axis labels.
*/
public void setUnitsLength(int unitsLength) {
this.unitsLength = unitsLength;
}
/**
* Sets vertical label on the left side of the graph. This is normally used
* to specify the units used.
*
* @param verticalLabel Vertical axis label
*/
public void setVerticalLabel(String verticalLabel) {
this.verticalLabel = verticalLabel;
}
/**
* Sets width of the drawing area within the graph. This affects the total
* size of the image.
*
* @param width Width of the drawing area.
*/
public void setWidth(int width) {
this.width = width;
}
/**
* Sets height of the drawing area within the graph. This affects the total
* size of the image.
*
* @param height Height of the drawing area.
*/
public void setHeight(int height) {
this.height = height;
}
/**
* Creates interlaced GIF image (currently not supported,
* method is present only for RRDTool comaptibility).
*
* @param interlaced true, if GIF image should be interlaced.
*/
public void setInterlaced(boolean interlaced) {
this.interlaced = interlaced;
}
/**
* Creates additional image information.
* After the image has been created, the graph function uses imageInfo
* format string (printf-like) to create output similar to
* the {@link #print(String, String, String)} function.
* The format string is supplied with the following parameters:
* filename, xsize and ysize (in that particular order).
*
* For example, in order to generate an IMG tag
* suitable for including the graph into a web page, the command
* would look like this:
*
* setImageInfo("<IMG SRC='/img/%s' WIDTH='%d' HEIGHT='%d' ALT='Demo'>");
*
*
* @param imageInfo Image info format. Use %s placeholder for filename, %d placeholder for
* image width and height.
*/
public void setImageInfo(String imageInfo) {
this.imageInfo = imageInfo;
}
/**
* Sets image format.
*
* @param imageFormat "PNG", "GIF" or "JPG".
*/
public void setImageFormat(String imageFormat) {
this.imageFormat = imageFormat;
}
/**
* Sets background image - currently, only PNG images can be used as background.
*
* @param backgroundImage Path to background image
*/
public void setBackgroundImage(String backgroundImage) {
this.backgroundImage = backgroundImage;
}
/**
* Sets overlay image - currently, only PNG images can be used as overlay. Overlay image is
* printed on the top of the image, once it is completely created.
*
* @param overlayImage Path to overlay image
*/
public void setOverlayImage(String overlayImage) {
this.overlayImage = overlayImage;
}
/**
* Sets unit to be displayed on y axis. It is wise to use only short units on graph, however.
*
* @param unit Unit description
*/
public void setUnit(String unit) {
this.unit = unit;
}
/**
* Creates graph only if the current graph is out of date or not existent.
*
* @param lazy true, if graph should be 'lazy', false otherwise (defualt)
*/
public void setLazy(boolean lazy) {
this.lazy = lazy;
}
/**
* Sets the lower limit of a graph. But rather, this is the
* maximum lower bound of a graph. For example, the value -100 will
* result in a graph that has a lower limit of -100 or less. Use this
* method to expand graphs down.
*
* @param minValue Minimal value displayed on the graph
*/
public void setMinValue(double minValue) {
this.minValue = minValue;
}
/**
* Defines the value normally located at the upper border of the
* graph. If the graph contains higher values, the upper border will
* move upwards to accommodate these values as well.
*
* If you want to define an upper-limit which will not move in any
* event you have to use {@link #setRigid(boolean)} method as well.
*
* @param maxValue Maximal value displayed on the graph.
*/
public void setMaxValue(double maxValue) {
this.maxValue = maxValue;
}
/**
* Sets rigid boundaries mode. Normally JRObin will automatically expand
* the lower and upper limit if the graph contains a value outside the
* valid range. With the true
argument you can disable this behavior.
*
* @param rigid true if uper and lower limits should not be expanded to accomodate
* values outside of the specified range. False otherwise (default).
*/
public void setRigid(boolean rigid) {
this.rigid = rigid;
}
/**
* Sets default base for magnitude scaling. If you are graphing memory
* (and NOT network traffic) this switch should be set to 1024 so that 1Kb is 1024 byte.
* For traffic measurement, 1 kb/s is 1000 b/s.
*
* @param base Base value (defaults to 1000.0)
*/
public void setBase(double base) {
this.base = base;
}
/**
* Sets logarithmic y-axis scaling.
*
* @param logarithmic true, for logarithmic scaling, false otherwise (default).
*/
public void setLogarithmic(boolean logarithmic) {
this.logarithmic = logarithmic;
}
/**
* Overrides the colors for the standard elements of the graph. The colorTag
* must be one of the following constants defined in the
* {@link RrdGraphConstants}:
* {@link RrdGraphConstants#COLOR_BACK COLOR_BACK} background,
* {@link RrdGraphConstants#COLOR_CANVAS COLOR_CANVAS} canvas,
* {@link RrdGraphConstants#COLOR_SHADEA COLOR_SHADEA} left/top border,
* {@link RrdGraphConstants#COLOR_SHADEB COLOR_SHADEB} right/bottom border,
* {@link RrdGraphConstants#COLOR_GRID COLOR_GRID} major grid,
* {@link RrdGraphConstants#COLOR_MGRID COLOR_MGRID} minor grid,
* {@link RrdGraphConstants#COLOR_FONT COLOR_FONT} font,
* {@link RrdGraphConstants#COLOR_FRAME COLOR_FRAME} axis of the graph,
* {@link RrdGraphConstants#COLOR_ARROW COLOR_ARROW} arrow. This method can
* be called multiple times to set several colors.
*
* @param colorTag Color tag, as explained above.
* @param color Any color (paint) you like
* @throws RrdException Thrown if invalid colorTag is supplied.
*/
public void setColor(int colorTag, Paint color) throws RrdException {
if (colorTag >= 0 && colorTag < colors.length) {
colors[colorTag] = color;
}
else {
throw new RrdException("Invalid color index specified: " + colorTag);
}
}
/**
* Overrides the colors for the standard elements of the graph by element name.
* See {@link #setColor(int, java.awt.Paint)} for full explanation.
*
* @param colorName One of the following strings: "BACK", "CANVAS", "SHADEA", "SHADEB",
* "GRID", "MGRID", "FONT", "FRAME", "ARROW"
* @param color Any color (paint) you like
* @throws RrdException Thrown if invalid element name is supplied.
*/
public void setColor(String colorName, Paint color) throws RrdException {
setColor(getColorTagByName(colorName), color);
}
private static int getColorTagByName(String colorName) throws RrdException {
for (int i = 0; i < COLOR_NAMES.length; i++) {
if (COLOR_NAMES[i].equalsIgnoreCase(colorName)) {
return i;
}
}
throw new RrdException("Unknown color name specified: " + colorName);
}
/**
* Suppress generation of legend, only render the graph.
*
* @param noLegend true if graph legend should be omitted. False otherwise (default).
*/
public void setNoLegend(boolean noLegend) {
this.noLegend = noLegend;
}
/**
* Suppresses anything but the graph, works only for height < 64.
*
* @param onlyGraph true if only graph should be created, false otherwise (default).
*/
public void setOnlyGraph(boolean onlyGraph) {
this.onlyGraph = onlyGraph;
}
/**
* Force the generation of HRULE and VRULE legend even if those HRULE
* or VRULE will not be drawn because out of graph boundaries.
*
* @param forceRulesLegend true if rule legend should be always printed,
* false otherwise (default).
*/
public void setForceRulesLegend(boolean forceRulesLegend) {
this.forceRulesLegend = forceRulesLegend;
}
/**
* Defines a title to be written into the graph.
*
* @param title Graph title.
*/
public void setTitle(String title) {
this.title = title;
}
/**
* Suggests which time step should be used by JRobin while processing data from RRD files.
*
* @param step Desired time step (don't use this method if you don't know what you're doing).
*/
public void setStep(long step) {
this.step = step;
}
/**
* Get the default small font for graphing.
*
* @return the font
*/
public Font getSmallFont() {
return this.fonts[FONTTAG_DEFAULT];
}
/**
* Get the default large font for graphing.
*
* @return the font
*/
public Font getLargeFont() {
return this.fonts[FONTTAG_TITLE];
}
/**
* Sets default font for graphing. Note that JRobin will behave unpredictably if proportional
* font is selected.
*
* @param smallFont Default font for graphing. Use only monospaced fonts.
* @throws RrdException Thrown if invalid fontTag is supplied.
*/
public void setSmallFont(final Font smallFont) throws RrdException{
this.setFont(FONTTAG_DEFAULT, smallFont);
}
/**
* Sets title font.
*
* @param largeFont Font to be used for graph title.
* @throws RrdException Thrown if invalid fontTag is supplied.
*/
public void setLargeFont(final Font largeFont) throws RrdException {
this.setFont(FONTTAG_TITLE, largeFont);
}
/**
* Sets font to be used for a specific font tag. The fontTag
* must be one of the following constants defined in the
* {@link RrdGraphConstants}:
* {@link RrdGraphConstants#FONTTAG_DEFAULT FONTTAG_DEFAULT} default font,,
* {@link RrdGraphConstants#FONTTAG_TITLE FONTTAG_TITLE} title,
* {@link RrdGraphConstants#FONTTAG_AXIS FONTTAG_AXIS} grid axis,,
* {@link RrdGraphConstants#FONTTAG_UNIT FONTTAG_UNIT} vertical unit label,,
* {@link RrdGraphConstants#FONTTAG_LEGEND FONTTAG_LEGEND} legend,
* {@link RrdGraphConstants#FONTTAG_WATERMARK FONTTAG_WATERMARK} watermark.
* This method can be called multiple times to set several fonts.
*
* @param fontTag Font tag, as explained above.
* @param font Font to be used for tag
* @throws RrdException Thrown if invalid fontTag is supplied.
*/
public void setFont(final int fontTag, final Font font) throws RrdException {
this.setFont(fontTag, font, false);
}
/**
* Sets font.
*
* @param fontTag Font tag, as explained above.
* @param font Font to be used for tag
* @param setAll Boolean to flag whether to set all fonts if fontTag == FONTTAG_DEFAULT
* @throws RrdException Thrown if invalid fontTag is supplied.
*/
public void setFont(final int fontTag, final Font font, final boolean setAll) throws RrdException {
this.setFont(fontTag, font, setAll, false);
}
/**
* Sets font.
*
* @param fontTag Font tag, as explained above.
* @param font Font to be used for tag
* @param setAll Boolean to flag whether to set all fonts if fontTag == FONTTAG_DEFAULT
* @param keepSizes Boolean to flag whether to keep original font sizes if setting all fonts.
*/
public void setFont(final int fontTag, final Font font, final boolean setAll, final boolean keepSizes) {
if (fontTag == FONTTAG_DEFAULT && setAll) {
if (keepSizes) {
this.fonts[FONTTAG_DEFAULT] = font.deriveFont(this.fonts[FONTTAG_DEFAULT].getSize());
this.fonts[FONTTAG_TITLE] = font.deriveFont(this.fonts[FONTTAG_TITLE].getSize());
this.fonts[FONTTAG_AXIS] = font.deriveFont(this.fonts[FONTTAG_AXIS].getSize());
this.fonts[FONTTAG_UNIT] = font.deriveFont(this.fonts[FONTTAG_UNIT].getSize());
this.fonts[FONTTAG_LEGEND] = font.deriveFont(this.fonts[FONTTAG_LEGEND].getSize());
this.fonts[FONTTAG_WATERMARK] = font.deriveFont(this.fonts[FONTTAG_WATERMARK].getSize());
} else {
this.fonts[FONTTAG_DEFAULT] = font;
this.fonts[FONTTAG_TITLE] = null;
this.fonts[FONTTAG_AXIS] = null;
this.fonts[FONTTAG_UNIT] = null;
this.fonts[FONTTAG_LEGEND] = null;
this.fonts[FONTTAG_WATERMARK] = null;
}
} else {
this.fonts[fontTag] = font;
}
}
/**
* Sets font.
*
* @param fontTag Font tag as String, as explained in {@link RrdGraphDef#setFont setFont(int, java.awt.Font)}.
* @param font Font to be used for tag
* @throws RrdException Thrown if invalid fontTag is supplied.
*/
public void setFont(final String fontTag, final Font font) throws RrdException {
this.setFont(getFontTagByName(fontTag), font);
}
/**
* Sets font.
*
* @param fontTag Font tag as String, as explained in {@link RrdGraphDef#setFont setFont(int, java.awt.Font)}.
* @param font Font to be used for tag
* @param setAll Boolean to flag whether to set all fonts if fontTag == FONTTAG_DEFAULT
* @throws RrdException Thrown if invalid fontTag is supplied.
*/
public void setFont(final String fontTag, final Font font, final boolean setAll) throws RrdException {
this.setFont(getFontTagByName(fontTag), font, setAll);
}
/**
* Sets font.
*
* @param fontTag Font tag as String, as explained in {@link RrdGraphDef#setFont setFont(int, java.awt.Font)}.
* @param font Font to be used for tag
* @param setAll Boolean to flag whether to set all fonts if fontTag == FONTTAG_DEFAULT
* @param keepSizes Boolean to flag whether to keep original font sizes if setting all fonts.
* @throws RrdException Thrown if invalid fontTag is supplied.
*/
public void setFont(final String fontTag, final Font font, final boolean setAll, final boolean keepSizes) throws RrdException {
this.setFont(getFontTagByName(fontTag), font, setAll, keepSizes);
}
private static int getFontTagByName(String tagName) throws RrdException {
for (int i = 0; i < FONTTAG_NAMES.length; i++) {
if (FONTTAG_NAMES[i].equalsIgnoreCase(tagName)) {
return i;
}
}
throw new RrdException("Unknown tag name specified: " + tagName);
}
public Font getFont(int tag) {
return this.fonts[tag] == null ? this.fonts[FONTTAG_DEFAULT] : this.fonts[tag];
}
/**
* Defines virtual datasource. This datasource can then be used
* in other methods like {@link #datasource(String, String)} or
* {@link #gprint(String, String, String)}.
*
* @param name Source name
* @param rrdPath Path to RRD file
* @param dsName Datasource name in the specified RRD file
* @param consolFun Consolidation function (AVERAGE, MIN, MAX, LAST)
*/
public void datasource(String name, String rrdPath, String dsName, String consolFun) {
sources.add(new Def(name, rrdPath, dsName, consolFun));
}
/**
* Defines virtual datasource. This datasource can then be used
* in other methods like {@link #datasource(String, String)} or
* {@link #gprint(String, String, String)}.
*
* @param name Source name
* @param rrdPath Path to RRD file
* @param dsName Datasource name in the specified RRD file
* @param consolFun Consolidation function (AVERAGE, MIN, MAX, LAST)
* @param backend Backend to be used while fetching data from a RRD file.
*/
public void datasource(String name, String rrdPath, String dsName, String consolFun, String backend) {
sources.add(new Def(name, rrdPath, dsName, consolFun, backend));
}
/**
* Create a new virtual datasource by evaluating a mathematical
* expression, specified in Reverse Polish Notation (RPN).
*
* @param name Source name
* @param rpnExpression RPN expression.
*/
public void datasource(String name, String rpnExpression) {
sources.add(new CDef(name, rpnExpression));
}
/**
* Creates a new (static) virtual datasource. The value of the datasource is constant. This value is
* evaluated by applying the given consolidation function to another virtual datasource.
*
* @param name Source name
* @param defName Other source name
* @param consolFun Consolidation function to be applied to other datasource.
*/
public void datasource(String name, String defName, String consolFun) {
sources.add(new SDef(name, defName, consolFun));
}
/**
* Creates a new (plottable) datasource. Datasource values are obtained from the given plottable
* object.
*
* @param name Source name.
* @param plottable Plottable object.
*/
public void datasource(String name, Plottable plottable) {
sources.add(new PDef(name, plottable));
}
/**
* Creates a new static virtual datasource that performs a percentile calculation on an
* another named datasource to yield a single value.
*
* Requires that the other datasource has already been defined otherwise it throws an exception
* (we need to look at the existing data source to extract the required data)
*
* @param name - the new virtual datasource name
* @param sourceName - the datasource from which to extract the percentile. Must be a previously
* defined virtula datasource
* @param percentile - the percentile to extract from the source datasource
*/
public void datasource(String name, String sourceName, double percentile) {
sources.add(new PercentileDef(name, sourceName, percentile));
}
/**
* Creates a new static virtual datasource that performs a percentile calculation on an
* another named datasource to yield a single value.
*
* Requires that the other datasource has already been defined otherwise it throws an exception
* (we need to look at the existing data source to extract the required data)
*
* @param name - the new virtual datasource name
* @param sourceName - the datasource from which to extract the percentile. Must be a previously
* defined virtula datasource
* @param percentile - the percentile to extract from the source datasource
* @param includenan - whether to include NaNs in the percentile calculations.
*/
public void datasource(String name, String sourceName, double percentile, boolean includenan) {
sources.add(new PercentileDef(name, sourceName, percentile, includenan));
}
/**
* Calculates the chosen consolidation function CF over the given datasource
* and creates the result by using the given format string. In
* the format string there should be a '%[l]f', '%[l]g' or '%[l]e' marker in
* the place where the number should be printed.
*
* If an additional '%s' is found AFTER the marker, the value will be
* scaled and an appropriate SI magnitude unit will be printed in
* place of the '%s' marker. The scaling will take the '--base' argument
* into consideration!
*
* If a '%S' is used instead of a '%s', then instead of calculating
* the appropriate SI magnitude unit for this value, the previously
* calculated SI magnitude unit will be used. This is useful if you
* want all the values in a print statement to have the same SI magnitude
* unit. If there was no previous SI magnitude calculation made,
* then '%S' behaves like a '%s', unless the value is 0, in which case
* it does not remember a SI magnitude unit and a SI magnitude unit
* will only be calculated when the next '%s' is seen or the next '%S'
* for a non-zero value.
*
* Print results are collected in the {@link RrdGraphInfo} object which is retrieved
* from the {@link RrdGraph object} once the graph is created.
*
* @param srcName Virtual source name
* @param consolFun Consolidation function to be applied to the source
* @param format Format string (like "average = %10.3f %s")
*/
public void print(String srcName, String consolFun, String format) {
comments.add(new PrintText(srcName, consolFun, format, false));
}
/**
* This method does basically the same thing as {@link #print(String, String, String)},
* but the result is printed on the graph itself, below the chart area.
*
* @param srcName Virtual source name
* @param consolFun Consolidation function to be applied to the source
* @param format Format string (like "average = %10.3f %s")
*/
public void gprint(String srcName, String consolFun, String format) {
comments.add(new PrintText(srcName, consolFun, format, true));
}
/**
* Comment to be printed on the graph.
*
* @param text Comment text
*/
public void comment(String text) {
comments.add(new CommentText(text));
}
/**
* Draws a horizontal rule into the graph and optionally adds a legend
*
* @param value Position of the rule
* @param color Rule color
* @param legend Legend text. If null, legend text will be omitted.
*/
public void hrule(double value, Paint color, String legend) {
hrule(value, color, legend, 1.0F);
}
/**
* Draws a horizontal rule into the graph and optionally adds a legend
*
* @param value Position of the rule
* @param color Rule color
* @param legend Legend text. If null, legend text will be omitted.
* @param width Rule width
*/
public void hrule(double value, Paint color, String legend, float width) {
LegendText legendText = new LegendText(color, legend);
comments.add(legendText);
plotElements.add(new HRule(value, color, legendText, width));
}
/**
* Draws a vertical rule into the graph and optionally adds a legend
*
* @param timestamp Position of the rule (seconds since epoch)
* @param color Rule color
* @param legend Legend text. Use null to omit the text.
*/
public void vrule(long timestamp, Paint color, String legend) {
vrule(timestamp, color, legend, 1.0F);
}
/**
* Draws a vertical rule into the graph and optionally adds a legend
*
* @param timestamp Position of the rule (seconds since epoch)
* @param color Rule color
* @param legend Legend text. Use null to omit the text.
* @param width Rule width
*/
public void vrule(long timestamp, Paint color, String legend, float width) {
LegendText legendText = new LegendText(color, legend);
comments.add(legendText);
plotElements.add(new VRule(timestamp, color, legendText, width));
}
/**
* Plots requested data as a line, using the color and the line width specified.
*
* @param srcName Virtual source name
* @param color Line color
* @param legend Legend text
* @param width Line width (default: 1.0F)
*/
public void line(String srcName, Paint color, String legend, float width) {
if (legend != null) {
comments.add(new LegendText(color, legend));
}
plotElements.add(new Line(srcName, color, width));
}
/**
* Plots requested data as a line, using the color specified. Line width is assumed to be
* 1.0F.
*
* @param srcName Virtual source name
* @param color Line color
* @param legend Legend text
*/
public void line(String srcName, Paint color, String legend) {
line(srcName, color, legend, 1F);
}
/**
* Plots requested data in the form of the filled area starting from zero,
* using the color specified.
*
* @param srcName Virtual source name.
* @param color Color of the filled area.
* @param legend Legend text.
*/
public void area(String srcName, Paint color, String legend) {
area(srcName, color);
if ((legend != null) && (legend.length() > 0)) {
LegendText legendText = new LegendText(color, legend);
comments.add(legendText);
}
}
/**
* Plots requested data in the form of the filled area starting from zero,
* using the color specified.
*
* @param srcName Virtual source name.
* @param color Color of the filled area.
*/
public void area(String srcName, Paint color) {
plotElements.add(new Area(srcName, color));
}
/**
* Does the same as {@link #line(String, java.awt.Paint, String)},
* but the graph gets stacked on top of the
* previous LINE, AREA or STACK graph. Depending on the type of the
* previous graph, the STACK will be either a LINE or an AREA. This
* obviously implies that the first STACK must be preceded by an AREA
* or LINE.
*
* Note, that when you STACK onto *UNKNOWN* data, JRobin will not
* draw any graphics ... *UNKNOWN* is not zero.
*
* @param srcName Virtual source name
* @param color Stacked graph color
* @param legend Legend text
* @throws RrdException Thrown if this STACK has no previously defined AREA, STACK or LINE
* graph bellow it.
*/
public void stack(String srcName, Paint color, String legend) throws RrdException {
// find parent AREA or LINE
SourcedPlotElement parent = null;
for (int i = plotElements.size() - 1; i >= 0; i--) {
PlotElement plotElement = plotElements.get(i);
if (plotElement instanceof SourcedPlotElement) {
parent = (SourcedPlotElement) plotElement;
break;
}
}
if (parent == null) {
throw new RrdException("You have to stack graph onto something (line or area)");
}
else {
LegendText legendText = new LegendText(color, legend);
comments.add(legendText);
plotElements.add(new Stack(parent, srcName, color));
}
}
/**
* Sets visibility of the X-axis grid.
*
* @param drawXGrid True if X-axis grid should be created (default), false otherwise.
*/
public void setDrawXGrid(boolean drawXGrid) {
this.drawXGrid = drawXGrid;
}
/**
* Sets visibility of the Y-axis grid.
*
* @param drawYGrid True if Y-axis grid should be created (default), false otherwise.
*/
public void setDrawYGrid(boolean drawYGrid) {
this.drawYGrid = drawYGrid;
}
/**
* Sets image quality. Relevant only for JPEG images.
*
* @param imageQuality (0F=worst, 1F=best).
*/
public void setImageQuality(float imageQuality) {
this.imageQuality = imageQuality;
}
/**
* Controls if the chart area of the image should be antialiased or not.
*
* @param antiAliasing use true to turn antialiasing on, false to turn it off (default)
*/
public void setAntiAliasing(boolean antiAliasing) {
this.antiAliasing = antiAliasing;
}
/**
* Shows or hides graph signature (gator) in the top right corner of the graph
*
* @param showSignature true, if signature should be seen (default), false otherwise
*/
public void setShowSignature(boolean showSignature) {
this.showSignature = showSignature;
}
/**
* Sets first day of the week.
*
* @param firstDayOfWeek One of the following constants:
* {@link RrdGraphConstants#MONDAY MONDAY},
* {@link RrdGraphConstants#TUESDAY TUESDAY},
* {@link RrdGraphConstants#WEDNESDAY WEDNESDAY},
* {@link RrdGraphConstants#THURSDAY THURSDAY},
* {@link RrdGraphConstants#FRIDAY FRIDAY},
* {@link RrdGraphConstants#SATURDAY SATURDAY},
* {@link RrdGraphConstants#SUNDAY SUNDAY}
*/
public void setFirstDayOfWeek(int firstDayOfWeek) {
this.firstDayOfWeek = firstDayOfWeek;
}
// helper methods
int printStatementCount() {
int count = 0;
for (CommentText comment : comments) {
if (comment instanceof PrintText) {
if (comment.isPrint()) {
count++;
}
}
}
return count;
}
boolean shouldPlot() {
if (plotElements.size() > 0) {
return true;
}
for (CommentText comment : comments) {
if (comment.isValidGraphElement()) {
return true;
}
}
return false;
}
}