1 /* ============================================================
2 * JRobin : Pure java implementation of RRDTool's functionality
3 * ============================================================
4 *
5 * Project Info: http://www.jrobin.org
6 * Project Lead: Sasa Markovic (saxon@jrobin.org)
7 *
8 * Developers: Sasa Markovic (saxon@jrobin.org)
9 *
10 *
11 * (C) Copyright 2003-2005, by Sasa Markovic.
12 *
13 * This library is free software; you can redistribute it and/or modify it under the terms
14 * of the GNU Lesser General Public License as published by the Free Software Foundation;
15 * either version 2.1 of the License, or (at your option) any later version.
16 *
17 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
18 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 * See the GNU Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public License along with this
22 * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
23 * Boston, MA 02111-1307, USA.
24 */
25 package org.jrobin.graph;
26
27 import java.awt.Font;
28 import java.awt.Paint;
29 import java.io.File;
30 import java.io.InputStream;
31 import java.net.MalformedURLException;
32 import java.net.URL;
33 import java.util.ArrayList;
34 import java.util.List;
35
36 import org.jrobin.core.RrdException;
37 import org.jrobin.core.Util;
38 import org.jrobin.data.Plottable;
39
40 /**
41 * Class which should be used to define new JRobin graph. Once constructed and populated with data
42 * object of this class should be passed to the constructor of the {@link RrdGraph} class which
43 * will actually create the graph.
44 * <p/>
45 * The text printed below the actual graph can be formated by appending
46 * special escaped characters at the end of a text. When ever such a
47 * character occurs, all pending text is pushed onto the graph according to
48 * the character specified.
49 * <p/>
50 * Valid markers are: \j for justified, \l for left aligned, \r for right
51 * aligned and \c for centered.
52 * <p/>
53 * Normally there are two space characters inserted between every two
54 * items printed into the graph. The space following a string can be
55 * suppressed by putting a \g at the end of the string. The \g also squashes
56 * any space inside the string if it is at the very end of the string.
57 * This can be used in connection with %s to suppress empty unit strings.
58 * <p/>
59 * A special case is COMMENT:\s this inserts some additional vertical
60 * space before placing the next row of legends.
61 * <p/>
62 * When text has to be formated without special instructions from your
63 * side, RRDTool will automatically justify the text as soon as one string
64 * goes over the right edge. If you want to prevent the justification
65 * without forcing a newline, you can use the special tag \J at the end of
66 * the string to disable the auto justification.
67 */
68 public class RrdGraphDef implements RrdGraphConstants {
69 boolean poolUsed = false; // ok
70 boolean antiAliasing = false; // ok
71 String filename = RrdGraphConstants.IN_MEMORY_IMAGE; // ok
72 long startTime, endTime; // ok
73 TimeAxisSetting timeAxisSetting = null; // ok
74 ValueAxisSetting valueAxisSetting = null; // ok
75 boolean altYGrid = false; // ok
76 boolean noMinorGrid = false; // ok
77 boolean altYMrtg = false; // ok
78 boolean altAutoscale = false; // ok
79 boolean altAutoscaleMax = false; // ok
80 int unitsExponent = Integer.MAX_VALUE; // ok
81 int unitsLength = DEFAULT_UNITS_LENGTH; // ok
82 String verticalLabel = null; // ok
83 int width = DEFAULT_WIDTH, height = DEFAULT_HEIGHT; // ok
84 boolean interlaced = false; // ok
85 String imageInfo = null; // ok
86 String imageFormat = DEFAULT_IMAGE_FORMAT; // ok
87 float imageQuality = DEFAULT_IMAGE_QUALITY; // ok
88 String backgroundImage = null; // ok
89 String overlayImage = null; // ok
90 String unit = null; // ok
91 String signature = "Created with JRobin"; // ok
92 boolean lazy = false; // ok
93 double minValue = Double.NaN; // ok
94 double maxValue = Double.NaN; // ok
95 boolean rigid = false; // ok
96 double base = DEFAULT_BASE; // ok
97 boolean logarithmic = false; // ok
98 Paint[] colors = new Paint[] {
99 // ok
100 DEFAULT_CANVAS_COLOR,
101 DEFAULT_BACK_COLOR,
102 DEFAULT_SHADEA_COLOR,
103 DEFAULT_SHADEB_COLOR,
104 DEFAULT_GRID_COLOR,
105 DEFAULT_MGRID_COLOR,
106 DEFAULT_FONT_COLOR,
107 DEFAULT_FRAME_COLOR,
108 DEFAULT_ARROW_COLOR
109 };
110 boolean noLegend = false; // ok
111 boolean onlyGraph = false; // ok
112 boolean forceRulesLegend = false; // ok
113 String title = null; // ok
114 long step = 0; // ok
115 protected Font smallFont;
116 protected Font largeFont;
117 boolean drawXGrid = true; // ok
118 boolean drawYGrid = true; // ok
119 int firstDayOfWeek = FIRST_DAY_OF_WEEK; // ok
120 boolean showSignature = true;
121 File fontDir = null;
122
123 List<Source> sources = new ArrayList<Source>();
124 List<CommentText> comments = new ArrayList<CommentText>();
125 List<PlotElement> plotElements = new ArrayList<PlotElement>();
126
127 /**
128 * Creates RrdGraphDef object and sets default time span (default ending time is 'now',
129 * default starting time is 'end-1day'.
130 */
131 public RrdGraphDef() {
132 try {
133 setTimeSpan(Util.getTimestamps(DEFAULT_START, DEFAULT_END));
134 } catch (RrdException e) {
135 throw new RuntimeException(e);
136 }
137
138 String fontdirProperty = System.getProperty("jrobin.fontdir");
139 if (fontdirProperty != null && fontdirProperty.length() != 0) {
140 fontDir = new File(fontdirProperty);
141 }
142
143 // smallFont = this.getFontFromResourceName(RrdGraphConstants.DEFAULT_MONOSPACE_FONT_FILE).deriveFont(10);
144 // largeFont = this.getFontFromResourceName(RrdGraphConstants.DEFAULT_MONOSPACE_FONT_FILE).deriveFont(12);
145 smallFont = new Font(DEFAULT_FONT_NAME, Font.PLAIN, 10);
146 largeFont = new Font(DEFAULT_FONT_NAME, Font.BOLD, 12);
147 }
148
149 protected Font getFontFromResourceName(String name) {
150 Font font = null;
151 Exception exception = null;
152 URL file = null;
153
154 if (fontDir != null) {
155 try {
156 file = new URL("file://" + new File(fontDir, name).getAbsolutePath());
157 } catch (MalformedURLException e) {
158 // fall through to the jar
159 exception = e;
160 }
161 }
162 if (file == null) {
163 file = this.getClass().getResource(name);
164 }
165
166 if (file != null) {
167 // System.err.println("Found a font URL: " + file.toExternalForm());
168 try {
169 InputStream fontStream = file.openStream();
170 font = Font.createFont(Font.TRUETYPE_FONT, fontStream);
171 fontStream.close();
172 } catch (Exception e) {
173 exception = e;
174 }
175 } else {
176 // we can't find our fonts, fall back to the system font
177 System.err.println("An error occurred loading the font '" + name + "'. Falling back to the default.");
178 if (exception != null) {
179 System.err.println(exception.getLocalizedMessage());
180 }
181 font = new Font(DEFAULT_FONT_NAME, Font.PLAIN, 10);
182 }
183
184 if (font == null) {
185 font = new Font(null, Font.PLAIN, 10);
186 }
187 return font;
188 }
189
190 /**
191 * Sets the signature string that runs along the right-side of the graph.
192 * Defaults to "Created with JRobin".
193 *
194 * @param signature the string to print
195 */
196 public void setSignature(String signature) {
197 this.signature = signature;
198 }
199
200 /**
201 * Gets the signature string that runs along the right-side of the graph.
202 * @return the signature string
203 */
204 public String getSignature() {
205 return this.signature;
206 }
207
208 /**
209 * Sets the time when the graph should begin. Time in seconds since epoch
210 * (1970-01-01) is required. Negative numbers are relative to the current time.
211 *
212 * @param time Starting time for the graph in seconds since epoch
213 */
214 public void setStartTime(long time) {
215 this.startTime = time;
216 if (time <= 0) {
217 this.startTime += Util.getTime();
218 }
219 }
220
221 /**
222 * Sets the time when the graph should end. Time in seconds since epoch
223 * (1970-01-01) is required. Negative numbers are relative to the current time.
224 *
225 * @param time Ending time for the graph in seconds since epoch
226 */
227 public void setEndTime(long time) {
228 this.endTime = time;
229 if (time <= 0) {
230 this.endTime += Util.getTime();
231 }
232 }
233
234 /**
235 * Sets starting and ending time for the for the graph. Timestamps in seconds since epoch are
236 * required. Negative numbers are relative to the current time.
237 *
238 * @param startTime Starting time in seconds since epoch
239 * @param endTime Ending time in seconds since epoch
240 */
241 public void setTimeSpan(long startTime, long endTime) {
242 setStartTime(startTime);
243 setEndTime(endTime);
244 }
245
246 /**
247 * Sets starting and ending time for the for the graph. Timestamps in seconds since epoch are
248 * required.
249 *
250 * @param timestamps Array of timestamps. The first array item will be chosen for the starting
251 * timestamp. The last array item will be chosen for the ending timestamp.
252 */
253 public void setTimeSpan(long[] timestamps) {
254 setTimeSpan(timestamps[0], timestamps[timestamps.length - 1]);
255 }
256
257 /**
258 * Sets RrdDbPool usage policy (defaults to true). If set to true,
259 * {@link org.jrobin.core.RrdDbPool RrdDbPool} will be used to
260 * access individual RRD files. If set to false, RRD files will be accessed directly.
261 *
262 * @param poolUsed true, if RrdDbPool class should be used. False otherwise.
263 */
264 public void setPoolUsed(boolean poolUsed) {
265 this.poolUsed = poolUsed;
266 }
267
268 /**
269 * Sets the name of the graph to generate. Since JRobin outputs GIFs, PNGs,
270 * and JPEGs it's recommended that the filename end in either .gif,
271 * .png or .jpg. JRobin does not enforce this, however. If the filename is
272 * set to '-' the image will be created only in memory (no file will be created).
273 * PNG and GIF formats are recommended but JPEGs should be avoided.
274 *
275 * @param filename Path to the image file
276 */
277 public void setFilename(String filename) {
278 this.filename = filename;
279 }
280
281 /**
282 * Configures x-axis grid and labels. The x-axis label is quite complex to configure.
283 * So if you don't have very special needs, you can rely on the autoconfiguration to
284 * get this right.
285 * <p/>
286 * Otherwise, you have to configure three elements making up the x-axis labels
287 * and grid. The base grid, the major grid and the labels.
288 * The configuration is based on the idea that you first specify a well
289 * known amount of time and then say how many times
290 * it has to pass between each minor/major grid line or label. For the label
291 * you have to define two additional items: The precision of the label
292 * in seconds and the format used to generate the text
293 * of the label.
294 * <p/>
295 * For example, if you wanted a graph with a base grid every 10 minutes and a major
296 * one every hour, with labels every hour you would use the following
297 * x-axis definition.
298 * <p/>
299 * <pre>
300 * setTimeAxis(RrdGraphConstants.MINUTE, 10,
301 * RrdGraphConstants.HOUR, 1,
302 * RrdGraphConstants.HOUR, 1,
303 * 0, "%H:%M")
304 * </pre>
305 * <p/>
306 * The precision in this example is 0 because the %X format is exact.
307 * If the label was the name of the day, we would have had a precision
308 * of 24 hours, because when you say something like 'Monday' you mean
309 * the whole day and not Monday morning 00:00. Thus the label should
310 * be positioned at noon. By defining a precision of 24 hours or
311 * rather 86400 seconds, you make sure that this happens.
312 *
313 * @param minorUnit Minor grid unit. Minor grid, major grid and label units
314 * can be one of the following constants defined in
315 * {@link RrdGraphConstants}: {@link RrdGraphConstants#SECOND SECOND},
316 * {@link RrdGraphConstants#MINUTE MINUTE}, {@link RrdGraphConstants#HOUR HOUR},
317 * {@link RrdGraphConstants#DAY DAY}, {@link RrdGraphConstants#WEEK WEEK},
318 * {@link RrdGraphConstants#MONTH MONTH}, {@link RrdGraphConstants#YEAR YEAR}.
319 * @param minorUnitCount Number of minor grid units between minor grid lines.
320 * @param majorUnit Major grid unit.
321 * @param majorUnitCount Number of major grid units between major grid lines.
322 * @param labelUnit Label unit.
323 * @param labelUnitCount Number of label units between labels.
324 * @param labelSpan Label precision
325 * @param simpleDateFormat Date format (SimpleDateFormat pattern of strftime-like pattern)
326 */
327 public void setTimeAxis(int minorUnit, int minorUnitCount, int majorUnit, int majorUnitCount,
328 int labelUnit, int labelUnitCount, int labelSpan, String simpleDateFormat) {
329 timeAxisSetting = new TimeAxisSetting(minorUnit, minorUnitCount, majorUnit, majorUnitCount,
330 labelUnit, labelUnitCount, labelSpan, simpleDateFormat);
331 }
332
333 /**
334 * Sets vertical axis grid and labels. Makes vertical grid lines appear
335 * at gridStep interval. Every labelFactor*gridStep, a major grid line is printed,
336 * along with label showing the value of the grid line.
337 *
338 * @param gridStep Minor grid step
339 * @param labelFactor Specifies how many minor minor grid steps will appear between labels
340 * (major grid lines)
341 */
342 public void setValueAxis(double gridStep, int labelFactor) {
343 valueAxisSetting = new ValueAxisSetting(gridStep, labelFactor);
344 }
345
346 /**
347 * Places Y grid dynamically based on graph Y range. Algorithm ensures
348 * that you always have grid, that there are enough but not too many
349 * grid lines and the grid is metric. That is grid lines are placed
350 * every 1, 2, 5 or 10 units.
351 *
352 * @param altYGrid true, if Y grid should be calculated dynamically (defaults to false)
353 */
354 public void setAltYGrid(boolean altYGrid) {
355 this.altYGrid = altYGrid;
356 }
357
358 /**
359 * Use this method to turn off minor grid lines (printed by default)
360 *
361 * @param noMinorGrid true, to turn off, false to turn on (default)
362 */
363 public void setNoMinorGrid(boolean noMinorGrid) {
364 this.noMinorGrid = noMinorGrid;
365 }
366
367 /**
368 * Use this method to request MRTG-like graph (false by default)
369 *
370 * @param altYMrtg true, to create MRTG-like graph, false otherwise (default)
371 */
372 public void setAltYMrtg(boolean altYMrtg) {
373 this.altYMrtg = altYMrtg;
374 }
375
376 /**
377 * Computes Y range based on function absolute minimum and maximum
378 * values. Default algorithm uses predefined set of ranges. This is
379 * good in many cases but it fails miserably when you need to graph
380 * something like 260 + 0.001 * sin(x). Default algorithm will use Y
381 * range from 250 to 300 and on the graph you will see almost straight
382 * line. With --alt-autoscale Y range will be from slightly less the
383 * 260 - 0.001 to slightly more then 260 + 0.001 and periodic behavior
384 * will be seen.
385 *
386 * @param altAutoscale true to request alternative autoscaling, false otherwise
387 * (default).
388 */
389 public void setAltAutoscale(boolean altAutoscale) {
390 this.altAutoscale = altAutoscale;
391 }
392
393 /**
394 * Computes Y range based on function absolute minimum and maximum
395 * values. Where setAltAutoscale(true) will modify both the absolute maximum AND
396 * minimum values, this option will only affect the maximum value. The
397 * minimum value, if not defined elsewhere, will be 0. This
398 * option can be useful when graphing router traffic when the WAN line
399 * uses compression, and thus the throughput may be higher than the
400 * WAN line speed.
401 *
402 * @param altAutoscaleMax true to request alternative autoscaling, false
403 * otherwise (default)
404 */
405 public void setAltAutoscaleMax(boolean altAutoscaleMax) {
406 this.altAutoscaleMax = altAutoscaleMax;
407 }
408
409 /**
410 * Sets the 10**unitsExponent scaling of the y-axis values. Normally
411 * values will be scaled to the appropriate units (k, M, etc.). However
412 * you may wish to display units always in k (Kilo, 10e3) even if
413 * the data is in the M (Mega, 10e6) range for instance. Value should
414 * be an integer which is a multiple of 3 between -18 and 18, inclu-
415 * sive. It is the exponent on the units you which to use. For example,
416 * use 3 to display the y-axis values in k (Kilo, 10e3, thou-
417 * sands), use -6 to display the y-axis values in u (Micro, 10e-6,
418 * millionths). Use a value of 0 to prevent any scaling of the y-axis
419 * values.
420 *
421 * @param unitsExponent
422 */
423 public void setUnitsExponent(int unitsExponent) {
424 this.unitsExponent = unitsExponent;
425 }
426
427 /**
428 * Sets the character width on the left side of the graph for
429 * y-axis values.
430 *
431 * @param unitsLength Number of characters on the left side of the graphs
432 * reserved for vertical axis labels.
433 */
434 public void setUnitsLength(int unitsLength) {
435 this.unitsLength = unitsLength;
436 }
437
438 /**
439 * Sets vertical label on the left side of the graph. This is normally used
440 * to specify the units used.
441 *
442 * @param verticalLabel Vertical axis label
443 */
444 public void setVerticalLabel(String verticalLabel) {
445 this.verticalLabel = verticalLabel;
446 }
447
448 /**
449 * Sets width of the drawing area within the graph. This affects the total
450 * size of the image.
451 *
452 * @param width Width of the drawing area.
453 */
454 public void setWidth(int width) {
455 this.width = width;
456 }
457
458 /**
459 * Sets height of the drawing area within the graph. This affects the total
460 * size of the image.
461 *
462 * @param height Height of the drawing area.
463 */
464 public void setHeight(int height) {
465 this.height = height;
466 }
467
468 /**
469 * Creates interlaced GIF image (currently not supported,
470 * method is present only for RRDTool comaptibility).
471 *
472 * @param interlaced true, if GIF image should be interlaced.
473 */
474 public void setInterlaced(boolean interlaced) {
475 this.interlaced = interlaced;
476 }
477
478 /**
479 * Creates additional image information.
480 * After the image has been created, the graph function uses imageInfo
481 * format string (printf-like) to create output similar to
482 * the {@link #print(String, String, String)} function.
483 * The format string is supplied with the following parameters:
484 * filename, xsize and ysize (in that particular order).
485 * <p/>
486 * For example, in order to generate an IMG tag
487 * suitable for including the graph into a web page, the command
488 * would look like this:
489 * <pre>
490 * setImageInfo("<IMG SRC='/img/%s' WIDTH='%d' HEIGHT='%d' ALT='Demo'>");
491 * </pre>
492 *
493 * @param imageInfo Image info format. Use %s placeholder for filename, %d placeholder for
494 * image width and height.
495 */
496 public void setImageInfo(String imageInfo) {
497 this.imageInfo = imageInfo;
498 }
499
500 /**
501 * Sets image format.
502 *
503 * @param imageFormat "PNG", "GIF" or "JPG".
504 */
505 public void setImageFormat(String imageFormat) {
506 this.imageFormat = imageFormat;
507 }
508
509 /**
510 * Sets background image - currently, only PNG images can be used as background.
511 *
512 * @param backgroundImage Path to background image
513 */
514 public void setBackgroundImage(String backgroundImage) {
515 this.backgroundImage = backgroundImage;
516 }
517
518 /**
519 * Sets overlay image - currently, only PNG images can be used as overlay. Overlay image is
520 * printed on the top of the image, once it is completely created.
521 *
522 * @param overlayImage Path to overlay image
523 */
524 public void setOverlayImage(String overlayImage) {
525 this.overlayImage = overlayImage;
526 }
527
528 /**
529 * Sets unit to be displayed on y axis. It is wise to use only short units on graph, however.
530 *
531 * @param unit Unit description
532 */
533 public void setUnit(String unit) {
534 this.unit = unit;
535 }
536
537 /**
538 * Creates graph only if the current graph is out of date or not existent.
539 *
540 * @param lazy true, if graph should be 'lazy', false otherwise (defualt)
541 */
542 public void setLazy(boolean lazy) {
543 this.lazy = lazy;
544 }
545
546 /**
547 * Sets the lower limit of a graph. But rather, this is the
548 * maximum lower bound of a graph. For example, the value -100 will
549 * result in a graph that has a lower limit of -100 or less. Use this
550 * method to expand graphs down.
551 *
552 * @param minValue Minimal value displayed on the graph
553 */
554 public void setMinValue(double minValue) {
555 this.minValue = minValue;
556 }
557
558 /**
559 * Defines the value normally located at the upper border of the
560 * graph. If the graph contains higher values, the upper border will
561 * move upwards to accommodate these values as well.
562 * <p/>
563 * If you want to define an upper-limit which will not move in any
564 * event you have to use {@link #setRigid(boolean)} method as well.
565 *
566 * @param maxValue Maximal value displayed on the graph.
567 */
568 public void setMaxValue(double maxValue) {
569 this.maxValue = maxValue;
570 }
571
572 /**
573 * Sets rigid boundaries mode. Normally JRObin will automatically expand
574 * the lower and upper limit if the graph contains a value outside the
575 * valid range. With the <code>true</code> argument you can disable this behavior.
576 *
577 * @param rigid true if uper and lower limits should not be expanded to accomodate
578 * values outside of the specified range. False otherwise (default).
579 */
580 public void setRigid(boolean rigid) {
581 this.rigid = rigid;
582 }
583
584 /**
585 * Sets default base for magnitude scaling. If you are graphing memory
586 * (and NOT network traffic) this switch should be set to 1024 so that 1Kb is 1024 byte.
587 * For traffic measurement, 1 kb/s is 1000 b/s.
588 *
589 * @param base Base value (defaults to 1000.0)
590 */
591 public void setBase(double base) {
592 this.base = base;
593 }
594
595 /**
596 * Sets logarithmic y-axis scaling.
597 *
598 * @param logarithmic true, for logarithmic scaling, false otherwise (default).
599 */
600 public void setLogarithmic(boolean logarithmic) {
601 this.logarithmic = logarithmic;
602 }
603
604 /**
605 * Overrides the colors for the standard elements of the graph. The colorTag
606 * must be one of the following constants defined in the
607 * {@link RrdGraphConstants}:
608 * {@link RrdGraphConstants#COLOR_BACK COLOR_BACK} background,
609 * {@link RrdGraphConstants#COLOR_CANVAS COLOR_CANVAS} canvas,
610 * {@link RrdGraphConstants#COLOR_SHADEA COLOR_SHADEA} left/top border,
611 * {@link RrdGraphConstants#COLOR_SHADEB COLOR_SHADEB} right/bottom border,
612 * {@link RrdGraphConstants#COLOR_GRID COLOR_GRID} major grid,
613 * {@link RrdGraphConstants#COLOR_MGRID COLOR_MGRID} minor grid,
614 * {@link RrdGraphConstants#COLOR_FONT COLOR_FONT} font,
615 * {@link RrdGraphConstants#COLOR_FRAME COLOR_FRAME} axis of the graph,
616 * {@link RrdGraphConstants#COLOR_ARROW COLOR_ARROW} arrow. This method can
617 * be called multiple times to set several colors.
618 *
619 * @param colorTag
620 * Color tag, as explained above.
621 * @param color
622 * Any color (paint) you like
623 * @throws RrdException
624 * Thrown if invalid colorTag is supplied.
625 */
626 public void setColor(int colorTag, Paint color) throws RrdException {
627 if (colorTag >= 0 && colorTag < colors.length) {
628 colors[colorTag] = color;
629 } else {
630 throw new RrdException("Invalid color index specified: " + colorTag);
631 }
632 }
633
634 /**
635 * Overrides the colors for the standard elements of the graph by element name.
636 * See {@link #setColor(int, java.awt.Paint)} for full explanation.
637 *
638 * @param colorName One of the following strings: "BACK", "CANVAS", "SHADEA", "SHADEB",
639 * "GRID", "MGRID", "FONT", "FRAME", "ARROW"
640 * @param color Any color (paint) you like
641 * @throws RrdException Thrown if invalid element name is supplied.
642 */
643 public void setColor(String colorName, Paint color) throws RrdException {
644 setColor(getColorTagByName(colorName), color);
645 }
646
647 private static int getColorTagByName(String colorName) throws RrdException {
648 for (int i = 0; i < COLOR_NAMES.length; i++) {
649 if (COLOR_NAMES[i].equalsIgnoreCase(colorName)) {
650 return i;
651 }
652 }
653 throw new RrdException("Unknown color name specified: " + colorName);
654 }
655
656 /**
657 * Suppress generation of legend, only render the graph.
658 *
659 * @param noLegend true if graph legend should be omitted. False otherwise (default).
660 */
661 public void setNoLegend(boolean noLegend) {
662 this.noLegend = noLegend;
663 }
664
665 /**
666 * Suppresses anything but the graph, works only for height < 64.
667 *
668 * @param onlyGraph true if only graph should be created, false otherwise (default).
669 */
670 public void setOnlyGraph(boolean onlyGraph) {
671 this.onlyGraph = onlyGraph;
672 }
673
674 /**
675 * Force the generation of HRULE and VRULE legend even if those HRULE
676 * or VRULE will not be drawn because out of graph boundaries.
677 *
678 * @param forceRulesLegend true if rule legend should be always printed,
679 * false otherwise (default).
680 */
681 public void setForceRulesLegend(boolean forceRulesLegend) {
682 this.forceRulesLegend = forceRulesLegend;
683 }
684
685 /**
686 * Defines a title to be written into the graph.
687 *
688 * @param title Graph title.
689 */
690 public void setTitle(String title) {
691 this.title = title;
692 }
693
694 /**
695 * Suggests which time step should be used by JRobin while processing data from RRD files.
696 *
697 * @param step Desired time step (don't use this method if you don't know what you're doing).
698 */
699 public void setStep(long step) {
700 this.step = step;
701 }
702
703 /**
704 * Get the default small font for graphing.
705 * @return the font
706 */
707 public Font getSmallFont() {
708 return this.smallFont;
709 }
710
711 /**
712 * Get the default large font for graphing.
713 * @return the font
714 */
715 public Font getLargeFont() {
716 return this.largeFont;
717 }
718
719
720 /**
721 * Sets default font for graphing. Note that JRobin will behave unpredictably if proportional
722 * font is selected.
723 *
724 * @param smallFont Default font for graphing. Use only monospaced fonts.
725 */
726 public void setSmallFont(Font smallFont) {
727 this.smallFont = smallFont;
728 }
729
730 /**
731 * Sets title font.
732 *
733 * @param largeFont Font to be used for graph title.
734 */
735 public void setLargeFont(Font largeFont) {
736 this.largeFont = largeFont;
737 }
738
739 /**
740 * Defines virtual datasource. This datasource can then be used
741 * in other methods like {@link #datasource(String, String)} or
742 * {@link #gprint(String, String, String)}.
743 *
744 * @param name Source name
745 * @param rrdPath Path to RRD file
746 * @param dsName Datasource name in the specified RRD file
747 * @param consolFun Consolidation function (AVERAGE, MIN, MAX, LAST)
748 */
749 public void datasource(String name, String rrdPath, String dsName, String consolFun) {
750 sources.add(new Def(name, rrdPath, dsName, consolFun));
751 }
752
753 /**
754 * Defines virtual datasource. This datasource can then be used
755 * in other methods like {@link #datasource(String, String)} or
756 * {@link #gprint(String, String, String)}.
757 *
758 * @param name Source name
759 * @param rrdPath Path to RRD file
760 * @param dsName Datasource name in the specified RRD file
761 * @param consolFun Consolidation function (AVERAGE, MIN, MAX, LAST)
762 * @param backend Backend to be used while fetching data from a RRD file.
763 */
764 public void datasource(String name, String rrdPath, String dsName, String consolFun, String backend) {
765 sources.add(new Def(name, rrdPath, dsName, consolFun, backend));
766 }
767
768 /**
769 * Create a new virtual datasource by evaluating a mathematical
770 * expression, specified in Reverse Polish Notation (RPN).
771 *
772 * @param name Source name
773 * @param rpnExpression RPN expression.
774 */
775 public void datasource(String name, String rpnExpression) {
776 sources.add(new CDef(name, rpnExpression));
777 }
778
779 /**
780 * Creates a new (static) virtual datasource. The value of the datasource is constant. This value is
781 * evaluated by applying the given consolidation function to another virtual datasource.
782 *
783 * @param name Source name
784 * @param defName Other source name
785 * @param consolFun Consolidation function to be applied to other datasource.
786 */
787 public void datasource(String name, String defName, String consolFun) {
788 sources.add(new SDef(name, defName, consolFun));
789 }
790
791 /**
792 * Creates a new (plottable) datasource. Datasource values are obtained from the given plottable
793 * object.
794 *
795 * @param name Source name.
796 * @param plottable Plottable object.
797 */
798 public void datasource(String name, Plottable plottable) {
799 sources.add(new PDef(name, plottable));
800 }
801
802 /**
803 * Calculates the chosen consolidation function CF over the given datasource
804 * and creates the result by using the given format string. In
805 * the format string there should be a '%[l]f', '%[l]g' or '%[l]e' marker in
806 * the place where the number should be printed.
807 * <p/>
808 * If an additional '%s' is found AFTER the marker, the value will be
809 * scaled and an appropriate SI magnitude unit will be printed in
810 * place of the '%s' marker. The scaling will take the '--base' argument
811 * into consideration!
812 * <p/>
813 * If a '%S' is used instead of a '%s', then instead of calculating
814 * the appropriate SI magnitude unit for this value, the previously
815 * calculated SI magnitude unit will be used. This is useful if you
816 * want all the values in a print statement to have the same SI magnitude
817 * unit. If there was no previous SI magnitude calculation made,
818 * then '%S' behaves like a '%s', unless the value is 0, in which case
819 * it does not remember a SI magnitude unit and a SI magnitude unit
820 * will only be calculated when the next '%s' is seen or the next '%S'
821 * for a non-zero value.
822 * <p/>
823 * Print results are collected in the {@link RrdGraphInfo} object which is retrieved
824 * from the {@link RrdGraph object} once the graph is created.
825 *
826 * @param srcName Virtual source name
827 * @param consolFun Consolidation function to be applied to the source
828 * @param format Format string (like "average = %10.3f %s")
829 */
830 public void print(String srcName, String consolFun, String format) {
831 comments.add(new PrintText(srcName, consolFun, format, false));
832 }
833
834 /**
835 * This method does basically the same thing as {@link #print(String, String, String)},
836 * but the result is printed on the graph itself, below the chart area.
837 *
838 * @param srcName Virtual source name
839 * @param consolFun Consolidation function to be applied to the source
840 * @param format Format string (like "average = %10.3f %s")
841 */
842 public void gprint(String srcName, String consolFun, String format) {
843 comments.add(new PrintText(srcName, consolFun, format, true));
844 }
845
846 /**
847 * Comment to be printed on the graph.
848 *
849 * @param text Comment text
850 */
851 public void comment(String text) {
852 comments.add(new CommentText(text));
853 }
854
855 /**
856 * Draws a horizontal rule into the graph and optionally adds a legend
857 *
858 * @param value Position of the rule
859 * @param color Rule color
860 * @param legend Legend text. If null, legend text will be omitted.
861 */
862 public void hrule(double value, Paint color, String legend) {
863 hrule(value, color, legend, 1.0F);
864 }
865
866 /**
867 * Draws a horizontal rule into the graph and optionally adds a legend
868 *
869 * @param value Position of the rule
870 * @param color Rule color
871 * @param legend Legend text. If null, legend text will be omitted.
872 * @param width Rule width
873 */
874 public void hrule(double value, Paint color, String legend, float width) {
875 LegendText legendText = new LegendText(color, legend);
876 comments.add(legendText);
877 plotElements.add(new HRule(value, color, legendText, width));
878 }
879
880 /**
881 * Draws a vertical rule into the graph and optionally adds a legend
882 *
883 * @param timestamp Position of the rule (seconds since epoch)
884 * @param color Rule color
885 * @param legend Legend text. Use null to omit the text.
886 */
887 public void vrule(long timestamp, Paint color, String legend) {
888 vrule(timestamp, color, legend, 1.0F);
889 }
890
891 /**
892 * Draws a vertical rule into the graph and optionally adds a legend
893 *
894 * @param timestamp Position of the rule (seconds since epoch)
895 * @param color Rule color
896 * @param legend Legend text. Use null to omit the text.
897 * @param width Rule width
898 */
899 public void vrule(long timestamp, Paint color, String legend, float width) {
900 LegendText legendText = new LegendText(color, legend);
901 comments.add(legendText);
902 plotElements.add(new VRule(timestamp, color, legendText, width));
903 }
904
905 /**
906 * Plots requested data as a line, using the color and the line width specified.
907 *
908 * @param srcName Virtual source name
909 * @param color Line color
910 * @param legend Legend text
911 * @param width Line width (default: 1.0F)
912 */
913 public void line(String srcName, Paint color, String legend, float width) {
914 LegendText legendText = new LegendText(color, legend);
915 comments.add(legendText);
916 plotElements.add(new Line(srcName, color, width));
917 }
918
919 /**
920 * Plots requested data as a line, using the color specified. Line width is assumed to be
921 * 1.0F.
922 *
923 * @param srcName Virtual source name
924 * @param color Line color
925 * @param legend Legend text
926 */
927 public void line(String srcName, Paint color, String legend) {
928 line(srcName, color, legend, 1F);
929 }
930
931 /**
932 * Plots requested data in the form of the filled area starting from zero,
933 * using the color specified.
934 *
935 * @param srcName
936 * Virtual source name.
937 * @param color
938 * Color of the filled area.
939 * @param legend
940 * Legend text.
941 */
942 public void area(String srcName, Paint color, String legend) {
943 area(srcName, color);
944 if (legend.length() > 0) {
945 LegendText legendText = new LegendText(color, legend);
946 comments.add(legendText);
947 }
948 }
949
950 /**
951 * Plots requested data in the form of the filled area starting from zero,
952 * using the color specified.
953 *
954 * @param srcName
955 * Virtual source name.
956 * @param color
957 * Color of the filled area.
958 */
959 public void area(String srcName, Paint color) {
960 plotElements.add(new Area(srcName, color));
961 }
962
963 /**
964 * Does the same as {@link #line(String, java.awt.Paint, String)},
965 * but the graph gets stacked on top of the
966 * previous LINE, AREA or STACK graph. Depending on the type of the
967 * previous graph, the STACK will be either a LINE or an AREA. This
968 * obviously implies that the first STACK must be preceded by an AREA
969 * or LINE.
970 * <p/>
971 * Note, that when you STACK onto *UNKNOWN* data, JRobin will not
972 * draw any graphics ... *UNKNOWN* is not zero.
973 *
974 * @param srcName Virtual source name
975 * @param color Stacked graph color
976 * @param legend Legend text
977 * @throws RrdException Thrown if this STACK has no previously defined AREA, STACK or LINE
978 * graph bellow it.
979 */
980 public void stack(String srcName, Paint color, String legend) throws RrdException {
981 // find parent AREA or LINE
982 SourcedPlotElement parent = null;
983 for (int i = plotElements.size() - 1; i >= 0; i--) {
984 PlotElement plotElement = plotElements.get(i);
985 if (plotElement instanceof SourcedPlotElement) {
986 parent = (SourcedPlotElement) plotElement;
987 break;
988 }
989 }
990 if (parent == null) {
991 throw new RrdException("You have to stack graph onto something (line or area)");
992 }
993 else {
994 LegendText legendText = new LegendText(color, legend);
995 comments.add(legendText);
996 plotElements.add(new Stack(parent, srcName, color));
997 }
998 }
999
1000 /**
1001 * Sets visibility of the X-axis grid.
1002 *
1003 * @param drawXGrid True if X-axis grid should be created (default), false otherwise.
1004 */
1005 public void setDrawXGrid(boolean drawXGrid) {
1006 this.drawXGrid = drawXGrid;
1007 }
1008
1009 /**
1010 * Sets visibility of the Y-axis grid.
1011 *
1012 * @param drawYGrid True if Y-axis grid should be created (default), false otherwise.
1013 */
1014 public void setDrawYGrid(boolean drawYGrid) {
1015 this.drawYGrid = drawYGrid;
1016 }
1017
1018 /**
1019 * Sets image quality. Relevant only for JPEG images.
1020 *
1021 * @param imageQuality (0F=worst, 1F=best).
1022 */
1023 public void setImageQuality(float imageQuality) {
1024 this.imageQuality = imageQuality;
1025 }
1026
1027 /**
1028 * Controls if the chart area of the image should be antialiased or not.
1029 *
1030 * @param antiAliasing use true to turn antialiasing on, false to turn it off (default)
1031 */
1032 public void setAntiAliasing(boolean antiAliasing) {
1033 this.antiAliasing = antiAliasing;
1034 }
1035
1036 /**
1037 * Shows or hides graph signature (gator) in the top right corner of the graph
1038 *
1039 * @param showSignature true, if signature should be seen (default), false otherwise
1040 */
1041 public void setShowSignature(boolean showSignature) {
1042 this.showSignature = showSignature;
1043 }
1044
1045 /**
1046 * Sets first day of the week.
1047 *
1048 * @param firstDayOfWeek One of the following constants:
1049 * {@link RrdGraphConstants#MONDAY MONDAY},
1050 * {@link RrdGraphConstants#TUESDAY TUESDAY},
1051 * {@link RrdGraphConstants#WEDNESDAY WEDNESDAY},
1052 * {@link RrdGraphConstants#THURSDAY THURSDAY},
1053 * {@link RrdGraphConstants#FRIDAY FRIDAY},
1054 * {@link RrdGraphConstants#SATURDAY SATURDAY},
1055 * {@link RrdGraphConstants#SUNDAY SUNDAY}
1056 */
1057 public void setFirstDayOfWeek(int firstDayOfWeek) {
1058 this.firstDayOfWeek = firstDayOfWeek;
1059 }
1060
1061 // helper methods
1062
1063 int printStatementCount() {
1064 int count = 0;
1065 for (CommentText comment : comments) {
1066 if (comment instanceof PrintText) {
1067 if (comment.isPrint()) {
1068 count++;
1069 }
1070 }
1071 }
1072 return count;
1073 }
1074
1075 boolean shouldPlot() {
1076 if (plotElements.size() > 0) {
1077 return true;
1078 }
1079 for (CommentText comment : comments) {
1080 if (comment.isValidGraphElement()) {
1081 return true;
1082 }
1083 }
1084 return false;
1085 }
1086 }
1087