1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 package org.jrobin.cmd;
27
28 import org.jrobin.core.RrdException;
29 import org.jrobin.core.Util;
30 import org.jrobin.graph.RrdGraph;
31 import org.jrobin.graph.RrdGraphConstants;
32 import org.jrobin.graph.RrdGraphDef;
33 import org.jrobin.graph.RrdGraphInfo;
34
35 import java.awt.*;
36 import java.io.IOException;
37
38 class RrdGraphCmd extends RrdToolCmd implements RrdGraphConstants {
39 static final Color BLIND_COLOR = new Color(0, 0, 0, 0);
40 private RrdGraphDef gdef;
41
42 String getCmdType() {
43 return "graph";
44 }
45
46 Object execute() throws RrdException, IOException {
47 gdef = getGraphDef();
48
49
50 RrdGraphInfo info = new RrdGraph(gdef).getRrdGraphInfo();
51 if (info.getFilename().equals(RrdGraphConstants.IN_MEMORY_IMAGE)) {
52 println(new String(info.getBytes()));
53 }
54 else {
55 println(info.getWidth() + "x" + info.getHeight());
56 String[] plines = info.getPrintLines();
57 for (String pline : plines) {
58 println(pline);
59 }
60 if (info.getImgInfo() != null && info.getImgInfo().length() > 0) {
61 println(info.getImgInfo());
62 }
63 }
64 return info;
65 }
66
67
68
69
70
71 public RrdGraphDef getGraphDef() throws RrdException {
72 RrdGraphDef gdef = new RrdGraphDef();
73
74
75
76
77 String t1 = getOptionValue("s", "start", DEFAULT_START), t2 = getOptionValue("e", "end", DEFAULT_END);
78 gdef.setTimeSpan(Util.getTimestamps(t1, t2));
79
80 parseXGrid(getOptionValue("x", "x-grid"));
81
82 parseYGrid(getOptionValue("y", "y-grid"));
83
84 gdef.setAltYGrid(getBooleanOption("Y", "alt-y-grid"));
85
86 gdef.setNoMinorGrid(getBooleanOption(null, "no-minor"));
87
88 gdef.setAltYMrtg(getBooleanOption("R", "alt-y-mrtg"));
89
90 gdef.setAltAutoscale(getBooleanOption("A", "alt-autoscale"));
91
92 gdef.setAltAutoscaleMax(getBooleanOption("M", "alt-autoscale-max"));
93
94 String opt = getOptionValue("X", "units-exponent");
95 if (opt != null) {
96 gdef.setUnitsExponent(parseInt(opt));
97 }
98
99 opt = getOptionValue("L", "units-length");
100 if (opt != null) {
101 gdef.setUnitsLength(parseInt(opt));
102 }
103
104 opt = getOptionValue("v", "vertical-label");
105 if (opt != null) {
106 gdef.setVerticalLabel(opt);
107 }
108
109 opt = getOptionValue("w", "width");
110 if (opt != null) {
111 gdef.setWidth(parseInt(opt));
112 }
113
114 opt = getOptionValue("h", "height");
115 if (opt != null) {
116 gdef.setHeight(parseInt(opt));
117 }
118
119 gdef.setInterlaced(getBooleanOption("i", "interlaced"));
120
121 opt = getOptionValue("f", "imginfo");
122 if (opt != null) {
123 gdef.setImageInfo(opt);
124 }
125
126 opt = getOptionValue("a", "imgformat");
127 if (opt != null) {
128 gdef.setImageFormat(opt);
129 }
130
131 opt = getOptionValue("B", "background");
132 if (opt != null) {
133 gdef.setBackgroundImage(opt);
134 }
135
136 opt = getOptionValue("O", "overlay");
137 if (opt != null) {
138 gdef.setOverlayImage(opt);
139 }
140
141 opt = getOptionValue("U", "unit");
142 if (opt != null) {
143 gdef.setUnit(opt);
144 }
145
146 gdef.setLazy(getBooleanOption("z", "lazy"));
147
148 opt = getOptionValue("u", "upper-limit");
149 if (opt != null) {
150 gdef.setMaxValue(parseDouble(opt));
151 }
152
153 opt = getOptionValue("l", "lower-limit");
154 if (opt != null) {
155 gdef.setMinValue(parseDouble(opt));
156 }
157
158 gdef.setRigid(getBooleanOption("r", "rigid"));
159
160 opt = getOptionValue("b", "base");
161 if (opt != null) {
162 gdef.setBase(parseDouble(opt));
163 }
164
165 gdef.setLogarithmic(getBooleanOption("o", "logarithmic"));
166
167 parseColors(getMultipleOptionValues("c", "color"));
168
169 gdef.setNoLegend(getBooleanOption("g", "no-legend"));
170
171 gdef.setOnlyGraph(getBooleanOption("j", "only-graph"));
172
173 gdef.setForceRulesLegend(getBooleanOption("F", "force-rules-legend"));
174
175 opt = getOptionValue("t", "title");
176 if (opt != null) {
177 gdef.setTitle(opt);
178 }
179
180 opt = getOptionValue("S", "step");
181 if (opt != null) {
182 gdef.setStep(parseLong(opt));
183 }
184
185
186
187 String[] words = getRemainingWords();
188
189 if (words.length < 2) {
190 throw new RrdException("Image filename must be specified");
191 }
192 gdef.setFilename(words[1]);
193
194 for (int i = 2; i < words.length; i++) {
195 if (words[i].startsWith("DEF:")) {
196 parseDef(words[i]);
197 }
198 else if (words[i].startsWith("CDEF:")) {
199 parseCDef(words[i]);
200 }
201 else if (words[i].startsWith("PRINT:")) {
202 parsePrint(words[i]);
203 }
204 else if (words[i].startsWith("GPRINT:")) {
205 parseGPrint(words[i]);
206 }
207 else if (words[i].startsWith("COMMENT:")) {
208 parseComment(words[i]);
209 }
210 else if (words[i].startsWith("HRULE:")) {
211 parseHRule(words[i]);
212 }
213 else if (words[i].startsWith("VRULE:")) {
214 parseVRule(words[i]);
215 }
216 else if (words[i].startsWith("LINE1:") || words[i].startsWith("LINE2:") || words[i].startsWith("LINE3:")) {
217 parseLine(words[i]);
218 }
219 else if (words[i].startsWith("AREA:")) {
220 parseArea(words[i]);
221 }
222 else if (words[i].startsWith("STACK:")) {
223 parseStack(words[i]);
224 }
225 else {
226 throw new RrdException("Unexpected GRAPH token encountered: " + words[i]);
227 }
228 }
229
230 return gdef;
231 }
232
233 private void parseLine(String word) throws RrdException {
234 String[] tokens1 = new ColonSplitter(word).split();
235 if (tokens1.length != 2 && tokens1.length != 3) {
236 throw new RrdException("Invalid LINE statement: " + word);
237 }
238 String[] tokens2 = tokens1[1].split("#");
239 if (tokens2.length != 1 && tokens2.length != 2) {
240 throw new RrdException("Invalid LINE statement: " + word);
241 }
242 float width = Integer.parseInt(tokens1[0].substring(tokens1[0].length() - 1));
243 String name = tokens2[0];
244 Paint color = tokens2.length == 2 ? Util.parseColor(tokens2[1]) : BLIND_COLOR;
245 String legend = tokens1.length == 3 ? tokens1[2] : null;
246 gdef.line(name, color, legend, width);
247 }
248
249 private void parseArea(String word) throws RrdException {
250 String[] tokens1 = new ColonSplitter(word).split();
251 if (tokens1.length != 2 && tokens1.length != 3) {
252 throw new RrdException("Invalid AREA statement: " + word);
253 }
254 String[] tokens2 = tokens1[1].split("#");
255 if (tokens2.length != 1 && tokens2.length != 2) {
256 throw new RrdException("Invalid AREA statement: " + word);
257 }
258 String name = tokens2[0];
259 Paint color = tokens2.length == 2 ? Util.parseColor(tokens2[1]) : BLIND_COLOR;
260 String legend = tokens1.length == 3 ? tokens1[2] : null;
261 gdef.area(name, color, legend);
262 }
263
264 private void parseStack(String word) throws RrdException {
265 String[] tokens1 = new ColonSplitter(word).split();
266 if (tokens1.length != 2 && tokens1.length != 3) {
267 throw new RrdException("Invalid STACK statement: " + word);
268 }
269 String[] tokens2 = tokens1[1].split("#");
270 if (tokens2.length != 1 && tokens2.length != 2) {
271 throw new RrdException("Invalid STACK statement: " + word);
272 }
273 String name = tokens2[0];
274 Paint color = tokens2.length == 2 ? Util.parseColor(tokens2[1]) : BLIND_COLOR;
275 String legend = tokens1.length == 3 ? tokens1[2] : null;
276 gdef.stack(name, color, legend);
277 }
278
279 private void parseHRule(String word) throws RrdException {
280 String[] tokens1 = new ColonSplitter(word).split();
281 if (tokens1.length < 2 || tokens1.length > 3) {
282 throw new RrdException("Invalid HRULE statement: " + word);
283 }
284 String[] tokens2 = tokens1[1].split("#");
285 if (tokens2.length != 2) {
286 throw new RrdException("Invalid HRULE statement: " + word);
287 }
288 double value = parseDouble(tokens2[0]);
289 Paint color = Util.parseColor(tokens2[1]);
290 gdef.hrule(value, color, tokens1.length == 3 ? tokens1[2] : null);
291 }
292
293 private void parseVRule(String word) throws RrdException {
294 String[] tokens1 = new ColonSplitter(word).split();
295 if (tokens1.length < 2 || tokens1.length > 3) {
296 throw new RrdException("Invalid VRULE statement: " + word);
297 }
298 String[] tokens2 = tokens1[1].split("#");
299 if (tokens2.length != 2) {
300 throw new RrdException("Invalid VRULE statement: " + word);
301 }
302 long timestamp = Util.getTimestamp(tokens2[0]);
303 Paint color = Util.parseColor(tokens2[1]);
304 gdef.vrule(timestamp, color, tokens1.length == 3 ? tokens1[2] : null);
305 }
306
307 private void parseComment(String word) throws RrdException {
308 String[] tokens = new ColonSplitter(word).split();
309 if (tokens.length != 2) {
310 throw new RrdException("Invalid COMMENT specification: " + word);
311 }
312 gdef.comment(tokens[1]);
313 }
314
315
316 private void parseDef(String word) throws RrdException {
317 String[] tokens1 = new ColonSplitter(word).split();
318 if (tokens1.length != 4) {
319 throw new RrdException("Invalid DEF specification: " + word);
320 }
321 String[] tokens2 = tokens1[1].split("=");
322 if (tokens2.length != 2) {
323 throw new RrdException("Invalid DEF specification: " + word);
324 }
325 gdef.datasource(tokens2[0], tokens2[1], tokens1[2], tokens1[3]);
326 }
327
328 private void parseCDef(String word) throws RrdException {
329 String[] tokens1 = new ColonSplitter(word).split();
330 if (tokens1.length != 2) {
331 throw new RrdException("Invalid CDEF specification: " + word);
332 }
333 String[] tokens2 = tokens1[1].split("=");
334 if (tokens2.length != 2) {
335 throw new RrdException("Invalid DEF specification: " + word);
336 }
337 gdef.datasource(tokens2[0], tokens2[1]);
338 }
339
340 private void parsePrint(String word) throws RrdException {
341 String[] tokens = new ColonSplitter(word).split();
342 if (tokens.length != 4) {
343 throw new RrdException("Invalid PRINT specification: " + word);
344 }
345 gdef.print(tokens[1], tokens[2], tokens[3]);
346 }
347
348 private void parseGPrint(String word) throws RrdException {
349 String[] tokens = new ColonSplitter(word).split();
350 if (tokens.length != 4) {
351 throw new RrdException("Invalid GPRINT specification: " + word);
352 }
353 gdef.gprint(tokens[1], tokens[2], tokens[3]);
354 }
355
356 private void parseColors(String[] colorOptions) throws RrdException {
357 if (colorOptions == null) {
358 return;
359 }
360 for (String colorOption : colorOptions) {
361 String[] tokens = colorOption.split("#");
362 if (tokens.length != 2) {
363 throw new RrdException("Invalid COLOR specification: " + colorOption);
364 }
365 String colorName = tokens[0];
366 Paint paint = Util.parseColor(tokens[1]);
367 gdef.setColor(colorName, paint);
368 }
369 }
370
371 private void parseYGrid(String ygrid) throws RrdException {
372 if (ygrid == null) {
373 return;
374 }
375 if (ygrid.equalsIgnoreCase("none")) {
376 gdef.setDrawYGrid(false);
377 return;
378 }
379 String[] tokens = new ColonSplitter(ygrid).split();
380 if (tokens.length != 2) {
381 throw new RrdException("Invalid YGRID settings: " + ygrid);
382 }
383 double gridStep = parseDouble(tokens[0]);
384 int labelFactor = parseInt(tokens[1]);
385 gdef.setValueAxis(gridStep, labelFactor);
386 }
387
388 private void parseXGrid(String xgrid) throws RrdException {
389 if (xgrid == null) {
390 return;
391 }
392 if (xgrid.equalsIgnoreCase("none")) {
393 gdef.setDrawXGrid(false);
394 return;
395 }
396 String[] tokens = new ColonSplitter(xgrid).split();
397 if (tokens.length != 8) {
398 throw new RrdException("Invalid XGRID settings: " + xgrid);
399 }
400 int minorUnit = resolveUnit(tokens[0]), majorUnit = resolveUnit(tokens[2]),
401 labelUnit = resolveUnit(tokens[4]);
402 int minorUnitCount = parseInt(tokens[1]), majorUnitCount = parseInt(tokens[3]),
403 labelUnitCount = parseInt(tokens[5]);
404 int labelSpan = parseInt(tokens[6]);
405 String fmt = tokens[7];
406 gdef.setTimeAxis(minorUnit, minorUnitCount, majorUnit, majorUnitCount,
407 labelUnit, labelUnitCount, labelSpan, fmt);
408 }
409
410 private int resolveUnit(String unitName) throws RrdException {
411 final String[] unitNames = {"SECOND", "MINUTE", "HOUR", "DAY", "WEEK", "MONTH", "YEAR"};
412 final int[] units = {SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, YEAR};
413 for (int i = 0; i < unitNames.length; i++) {
414 if (unitName.equalsIgnoreCase(unitNames[i])) {
415 return units[i];
416 }
417 }
418 throw new RrdException("Unknown time unit specified: " + unitName);
419 }
420 }