comparison artifacts/src/main/java/org/dive4elements/river/artifacts/services/FixingsKMChartService.java @ 9312:740d65e4aa14

Q [m³/s] one message
author gernotbelger
date Thu, 26 Jul 2018 15:54:20 +0200
parents fe7e9da6312a
children 9744ce3c3853
comparison
equal deleted inserted replaced
9311:7c7f73e5e01e 9312:740d65e4aa14
6 * documentation coming with Dive4Elements River for details. 6 * documentation coming with Dive4Elements River for details.
7 */ 7 */
8 8
9 package org.dive4elements.river.artifacts.services; 9 package org.dive4elements.river.artifacts.services;
10 10
11 import java.awt.BasicStroke;
12 import java.awt.Color;
13 import java.awt.Dimension;
14 import java.awt.Transparency;
15 import java.awt.geom.Rectangle2D;
16 import java.awt.image.BufferedImage;
17 import java.io.ByteArrayOutputStream;
18 import java.io.IOException;
19 import java.util.ArrayList;
20 import java.util.List;
21
22 import javax.imageio.ImageIO;
23
24 import org.apache.log4j.Logger;
11 import org.dive4elements.artifactdatabase.DefaultService; 25 import org.dive4elements.artifactdatabase.DefaultService;
12
13 import org.dive4elements.artifacts.CallMeta; 26 import org.dive4elements.artifacts.CallMeta;
14 import org.dive4elements.artifacts.GlobalContext; 27 import org.dive4elements.artifacts.GlobalContext;
15 import org.dive4elements.artifacts.Service; 28 import org.dive4elements.artifacts.Service;
16
17 import org.dive4elements.river.artifacts.model.FixingsColumn; 29 import org.dive4elements.river.artifacts.model.FixingsColumn;
18 import org.dive4elements.river.artifacts.model.FixingsColumnFactory; 30 import org.dive4elements.river.artifacts.model.FixingsColumnFactory;
19 import org.dive4elements.river.artifacts.model.FixingsFilterBuilder; 31 import org.dive4elements.river.artifacts.model.FixingsFilterBuilder;
20 32 import org.dive4elements.river.artifacts.model.FixingsOverview;
21 import org.dive4elements.river.artifacts.model.FixingsOverview.Fixing; 33 import org.dive4elements.river.artifacts.model.FixingsOverview.Fixing;
22
23 import org.dive4elements.river.artifacts.model.FixingsOverview;
24 import org.dive4elements.river.artifacts.model.FixingsOverviewFactory; 34 import org.dive4elements.river.artifacts.model.FixingsOverviewFactory;
25 import org.dive4elements.river.artifacts.model.GaugeFinder; 35 import org.dive4elements.river.artifacts.model.GaugeFinder;
26 import org.dive4elements.river.artifacts.model.GaugeFinderFactory; 36 import org.dive4elements.river.artifacts.model.GaugeFinderFactory;
27 import org.dive4elements.river.artifacts.model.GaugeRange; 37 import org.dive4elements.river.artifacts.model.GaugeRange;
28
29 import org.dive4elements.river.artifacts.model.fixings.QWI; 38 import org.dive4elements.river.artifacts.model.fixings.QWI;
30
31 import org.dive4elements.river.artifacts.resources.Resources; 39 import org.dive4elements.river.artifacts.resources.Resources;
32
33 import org.dive4elements.river.backend.SessionHolder; 40 import org.dive4elements.river.backend.SessionHolder;
34
35 import org.dive4elements.river.jfree.ShapeRenderer; 41 import org.dive4elements.river.jfree.ShapeRenderer;
36
37 import org.dive4elements.river.utils.Formatter; 42 import org.dive4elements.river.utils.Formatter;
38 import org.dive4elements.river.utils.Pair; 43 import org.dive4elements.river.utils.Pair;
39
40 import java.awt.BasicStroke;
41 import java.awt.Color;
42 import java.awt.Dimension;
43 import java.awt.Transparency;
44
45 import java.awt.geom.Rectangle2D;
46
47 import java.awt.image.BufferedImage;
48
49 import java.io.ByteArrayOutputStream;
50 import java.io.IOException;
51
52 import java.util.ArrayList;
53 import java.util.List;
54
55 import javax.imageio.ImageIO;
56
57 import org.apache.log4j.Logger;
58
59 import org.jfree.chart.ChartFactory; 44 import org.jfree.chart.ChartFactory;
60 import org.jfree.chart.JFreeChart; 45 import org.jfree.chart.JFreeChart;
61 import org.jfree.chart.LegendItemCollection; 46 import org.jfree.chart.LegendItemCollection;
62
63 import org.jfree.chart.axis.NumberAxis; 47 import org.jfree.chart.axis.NumberAxis;
64
65 import org.jfree.chart.plot.Marker; 48 import org.jfree.chart.plot.Marker;
66 import org.jfree.chart.plot.PlotOrientation; 49 import org.jfree.chart.plot.PlotOrientation;
67 import org.jfree.chart.plot.ValueMarker; 50 import org.jfree.chart.plot.ValueMarker;
68 import org.jfree.chart.plot.XYPlot; 51 import org.jfree.chart.plot.XYPlot;
69
70 import org.jfree.data.Range; 52 import org.jfree.data.Range;
71
72 import org.jfree.ui.RectangleAnchor; 53 import org.jfree.ui.RectangleAnchor;
73 import org.jfree.ui.TextAnchor; 54 import org.jfree.ui.TextAnchor;
74
75 import org.w3c.dom.Document; 55 import org.w3c.dom.Document;
76 import org.w3c.dom.Element; 56 import org.w3c.dom.Element;
77 import org.w3c.dom.NodeList; 57 import org.w3c.dom.NodeList;
78 58
79
80 /** Serve chart of Fixings at certain km. */ 59 /** Serve chart of Fixings at certain km. */
81 public class FixingsKMChartService 60 public class FixingsKMChartService extends DefaultService {
82 extends DefaultService 61 private static final Logger log = Logger.getLogger(FixingsKMChartService.class);
83 { 62
84 private static final Logger log = 63 public static final int DEFAULT_WIDTH = 240;
85 Logger.getLogger(FixingsKMChartService.class);
86
87 public static final int DEFAULT_WIDTH = 240;
88 public static final int DEFAULT_HEIGHT = 180; 64 public static final int DEFAULT_HEIGHT = 180;
89 65
90 public static final String [] I18N_Q_SECTOR_BOARDERS = { 66 public static final String[] I18N_Q_SECTOR_BOARDERS = { "fix.km.chart.q.sector.border0", "fix.km.chart.q.sector.border1", "fix.km.chart.q.sector.border2" };
91 "fix.km.chart.q.sector.border0", 67
92 "fix.km.chart.q.sector.border1", 68 public static final String[] DEFAULT_Q_SECTOR_BORDERS = { "(MNQ + MQ)/2", "(MQ + MHQ)/2", "HQ5" };
93 "fix.km.chart.q.sector.border2" 69
94 }; 70 public static final String I18N_CHART_LABEL_DATE = "fix.km.chart.label.date";
95 71
96 public static final String [] DEFAULT_Q_SECTOR_BORDERS = { 72 public static final String DEFAULT_CHART_LABEL_DATE = "yyyy/MM/dd";
97 "(MNQ + MQ)/2", 73
98 "(MQ + MHQ)/2", 74 public static final String I18N_CHART_TITLE = "fix.km.chart.title";
99 "HQ5" 75
100 }; 76 public static final String DEFAULT_CHART_TITLE = "Fixings {0} km {1,number,#.###}";
101 77
102 public static final String I18N_CHART_LABEL_DATE = 78 public static final String I18N_Q_AXIS = "common.export.csv.header.q";
103 "fix.km.chart.label.date"; 79
104 80 public static final String DEFAULT_Q_AXIS = "Q [m\u00b3/s]";
105 public static final String DEFAULT_CHART_LABEL_DATE = 81
106 "yyyy/MM/dd"; 82 public static final String I18N_W_AXIS = "fix.km.chart.w.axis";
107 83
108 public static final String I18N_CHART_TITLE = 84 public static final String DEFAULT_W_AXIS = "W [NN + m]";
109 "fix.km.chart.title"; 85
110 86 public static final String I18N_MEASURED = "fix.km.chart.measured";
111 public static final String DEFAULT_CHART_TITLE = 87
112 "Fixings {0} km {1,number,#.###}"; 88 public static final String DEFAULT_MEASURED = "measured";
113 89
114 public static final String I18N_Q_AXIS = 90 public static final String I18N_INTERPOLATED = "fix.km.chart.interpolated";
115 "fix.km.chart.q.axis"; 91
116 92 public static final String DEFAULT_INTERPOLATED = "interpolated";
117 public static final String DEFAULT_Q_AXIS =
118 "Q [m\u00b3/s]";
119
120 public static final String I18N_W_AXIS =
121 "fix.km.chart.w.axis";
122
123 public static final String DEFAULT_W_AXIS =
124 "W [NN + m]";
125
126 public static final String I18N_MEASURED =
127 "fix.km.chart.measured";
128
129 public static final String DEFAULT_MEASURED =
130 "measured";
131
132 public static final String I18N_INTERPOLATED =
133 "fix.km.chart.interpolated";
134
135 public static final String DEFAULT_INTERPOLATED =
136 "interpolated";
137 93
138 public static final String DEFAULT_FORMAT = "png"; 94 public static final String DEFAULT_FORMAT = "png";
139 95
140 // TODO: Load fancy image from resources. 96 // TODO: Load fancy image from resources.
141 public static final byte [] EMPTY = { 97 public static final byte[] EMPTY = { (byte) 0x89, (byte) 0x50, (byte) 0x4e, (byte) 0x47, (byte) 0x0d, (byte) 0x0a, (byte) 0x1a, (byte) 0x0a, (byte) 0x00,
142 (byte)0x89, (byte)0x50, (byte)0x4e, (byte)0x47, 98 (byte) 0x00, (byte) 0x00, (byte) 0x0d, (byte) 0x49, (byte) 0x48, (byte) 0x44, (byte) 0x52, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01,
143 (byte)0x0d, (byte)0x0a, (byte)0x1a, (byte)0x0a, 99 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x08, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x3a, (byte) 0x7e,
144 (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x0d, 100 (byte) 0x9b, (byte) 0x55, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x73, (byte) 0x52, (byte) 0x47, (byte) 0x42, (byte) 0x00,
145 (byte)0x49, (byte)0x48, (byte)0x44, (byte)0x52, 101 (byte) 0xae, (byte) 0xce, (byte) 0x1c, (byte) 0xe9, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x09, (byte) 0x70, (byte) 0x48, (byte) 0x59,
146 (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, 102 (byte) 0x73, (byte) 0x00, (byte) 0x00, (byte) 0x0b, (byte) 0x13, (byte) 0x00, (byte) 0x00, (byte) 0x0b, (byte) 0x13, (byte) 0x01, (byte) 0x00,
147 (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, 103 (byte) 0x9a, (byte) 0x9c, (byte) 0x18, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x07, (byte) 0x74, (byte) 0x49, (byte) 0x4d, (byte) 0x45,
148 (byte)0x08, (byte)0x00, (byte)0x00, (byte)0x00, 104 (byte) 0x07, (byte) 0xdc, (byte) 0x04, (byte) 0x04, (byte) 0x10, (byte) 0x30, (byte) 0x15, (byte) 0x7d, (byte) 0x77, (byte) 0x36, (byte) 0x0b,
149 (byte)0x00, (byte)0x3a, (byte)0x7e, (byte)0x9b, 105 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x08, (byte) 0x74, (byte) 0x45, (byte) 0x58, (byte) 0x74, (byte) 0x43, (byte) 0x6f, (byte) 0x6d,
150 (byte)0x55, (byte)0x00, (byte)0x00, (byte)0x00, 106 (byte) 0x6d, (byte) 0x65, (byte) 0x6e, (byte) 0x74, (byte) 0x00, (byte) 0xf6, (byte) 0xcc, (byte) 0x96, (byte) 0xbf, (byte) 0x00, (byte) 0x00,
151 (byte)0x01, (byte)0x73, (byte)0x52, (byte)0x47, 107 (byte) 0x00, (byte) 0x0a, (byte) 0x49, (byte) 0x44, (byte) 0x41, (byte) 0x54, (byte) 0x08, (byte) 0xd7, (byte) 0x63, (byte) 0xf8, (byte) 0x0f,
152 (byte)0x42, (byte)0x00, (byte)0xae, (byte)0xce, 108 (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x1b, (byte) 0xb6, (byte) 0xee, (byte) 0x56, (byte) 0x00, (byte) 0x00,
153 (byte)0x1c, (byte)0xe9, (byte)0x00, (byte)0x00, 109 (byte) 0x00, (byte) 0x00, (byte) 0x49, (byte) 0x45, (byte) 0x4e, (byte) 0x44, (byte) 0xae, (byte) 0x42, (byte) 0x60, (byte) 0x82 };
154 (byte)0x00, (byte)0x09, (byte)0x70, (byte)0x48,
155 (byte)0x59, (byte)0x73, (byte)0x00, (byte)0x00,
156 (byte)0x0b, (byte)0x13, (byte)0x00, (byte)0x00,
157 (byte)0x0b, (byte)0x13, (byte)0x01, (byte)0x00,
158 (byte)0x9a, (byte)0x9c, (byte)0x18, (byte)0x00,
159 (byte)0x00, (byte)0x00, (byte)0x07, (byte)0x74,
160 (byte)0x49, (byte)0x4d, (byte)0x45, (byte)0x07,
161 (byte)0xdc, (byte)0x04, (byte)0x04, (byte)0x10,
162 (byte)0x30, (byte)0x15, (byte)0x7d, (byte)0x77,
163 (byte)0x36, (byte)0x0b, (byte)0x00, (byte)0x00,
164 (byte)0x00, (byte)0x08, (byte)0x74, (byte)0x45,
165 (byte)0x58, (byte)0x74, (byte)0x43, (byte)0x6f,
166 (byte)0x6d, (byte)0x6d, (byte)0x65, (byte)0x6e,
167 (byte)0x74, (byte)0x00, (byte)0xf6, (byte)0xcc,
168 (byte)0x96, (byte)0xbf, (byte)0x00, (byte)0x00,
169 (byte)0x00, (byte)0x0a, (byte)0x49, (byte)0x44,
170 (byte)0x41, (byte)0x54, (byte)0x08, (byte)0xd7,
171 (byte)0x63, (byte)0xf8, (byte)0x0f, (byte)0x00,
172 (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x00,
173 (byte)0x1b, (byte)0xb6, (byte)0xee, (byte)0x56,
174 (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
175 (byte)0x49, (byte)0x45, (byte)0x4e, (byte)0x44,
176 (byte)0xae, (byte)0x42, (byte)0x60, (byte)0x82
177 };
178 110
179 private static final Output empty() { 111 private static final Output empty() {
180 return new Output(EMPTY, "image/png"); 112 return new Output(EMPTY, "image/png");
181 } 113 }
182 114
183 @Override 115 @Override
184 public Service.Output process( 116 public Service.Output process(final Document data, final GlobalContext globalContext, final CallMeta callMeta) {
185 Document data,
186 GlobalContext globalContext,
187 CallMeta callMeta
188 ) {
189 log.debug("FixingsKMChartService.process"); 117 log.debug("FixingsKMChartService.process");
190 118
191 SessionHolder.acquire(); 119 SessionHolder.acquire();
192 try { 120 try {
193 return doProcess(data, globalContext, callMeta); 121 return doProcess(data, globalContext, callMeta);
194 } 122 } finally {
195 finally {
196 SessionHolder.release(); 123 SessionHolder.release();
197 } 124 }
198 } 125 }
199 126
200 protected Service.Output doProcess( 127 protected Service.Output doProcess(final Document input, final GlobalContext globalContext, final CallMeta callMeta) {
201 Document input, 128 final String river = getRiverName(input);
202 GlobalContext globalContext, 129 final Double km = getKM(input);
203 CallMeta callMeta 130 final Dimension extent = getExtent(input);
204 ) { 131 final String format = getFormat(input);
205 String river = getRiverName(input);
206 Double km = getKM(input);
207 Dimension extent = getExtent(input);
208 String format = getFormat(input);
209 132
210 if (river == null || km == null) { 133 if (river == null || km == null) {
211 log.warn("River and/or km invalid."); 134 log.warn("River and/or km invalid.");
212 return empty(); 135 return empty();
213 } 136 }
214 137
215 FixingsOverview overview = FixingsOverviewFactory.getOverview(river); 138 final FixingsOverview overview = FixingsOverviewFactory.getOverview(river);
216 139
217 if (overview == null) { 140 if (overview == null) {
218 log.warn("No overview found for river '" + river + "'"); 141 log.warn("No overview found for river '" + river + "'");
219 return empty(); 142 return empty();
220 } 143 }
221 144
222 FixingsFilterBuilder ffb = new FixingsFilterBuilder(input); 145 final FixingsFilterBuilder ffb = new FixingsFilterBuilder(input);
223 146
224 List<Fixing.Column> columns = overview.filter( 147 final List<Fixing.Column> columns = overview.filter(ffb.getRange(), ffb.getFilter());
225 ffb.getRange(), 148
226 ffb.getFilter()); 149 final List<Pair<Fixing.Column, FixingsColumn>> cols = new ArrayList<>();
227 150
228 List<Pair<Fixing.Column, FixingsColumn>> cols = 151 for (final Fixing.Column col : columns) {
229 new ArrayList<Pair<Fixing.Column, FixingsColumn>>(); 152 final FixingsColumn data = FixingsColumnFactory.INSTANCE.getColumnData(col);
230
231 for (Fixing.Column col: columns) {
232 FixingsColumn data =
233 FixingsColumnFactory.INSTANCE.getColumnData(col);
234 if (data != null) { 153 if (data != null) {
235 cols.add(new Pair<Fixing.Column, FixingsColumn>(col, data)); 154 cols.add(new Pair<>(col, data));
236 } 155 }
237 } 156 }
238 157
239 JFreeChart chart = createChart(cols, river, km, callMeta); 158 final JFreeChart chart = createChart(cols, river, km, callMeta);
240 159
241 return encode(chart, extent, format); 160 return encode(chart, extent, format);
242 } 161 }
243 162
244 protected static Output encode( 163 protected static Output encode(final JFreeChart chart, final Dimension extent, final String format) {
245 JFreeChart chart, 164 final BufferedImage image = chart.createBufferedImage(extent.width, extent.height, Transparency.BITMASK, null);
246 Dimension extent, 165
247 String format 166 final ByteArrayOutputStream out = new ByteArrayOutputStream();
248 ) {
249 BufferedImage image = chart.createBufferedImage(
250 extent.width, extent.height,
251 Transparency.BITMASK,
252 null);
253
254 ByteArrayOutputStream out = new ByteArrayOutputStream();
255 167
256 try { 168 try {
257 ImageIO.write(image, format, out); 169 ImageIO.write(image, format, out);
258 } 170 }
259 catch (IOException ioe) { 171 catch (final IOException ioe) {
260 log.warn("writing image failed", ioe); 172 log.warn("writing image failed", ioe);
261 return empty(); 173 return empty();
262 } 174 }
263 175
264 return new Output(out.toByteArray(), "image/" + format); 176 return new Output(out.toByteArray(), "image/" + format);
265 } 177 }
266 178
267 protected static JFreeChart createChart( 179 protected static JFreeChart createChart(final List<Pair<Fixing.Column, FixingsColumn>> cols, final String river, final double km, final CallMeta callMeta) {
268 List<Pair<Fixing.Column, FixingsColumn>> cols, 180 final String labelFormat = Resources.getMsg(callMeta, I18N_CHART_LABEL_DATE, DEFAULT_CHART_LABEL_DATE);
269 String river, 181
270 double km, 182 final QWSeriesCollection.LabelGenerator lg = new QWSeriesCollection.DateFormatLabelGenerator(labelFormat);
271 CallMeta callMeta 183
272 ) { 184 final QWSeriesCollection dataset = new QWSeriesCollection(lg);
273 String labelFormat = Resources.getMsg( 185
274 callMeta, I18N_CHART_LABEL_DATE, DEFAULT_CHART_LABEL_DATE); 186 final double[] w = new double[1];
275 187 for (final Pair<Fixing.Column, FixingsColumn> col : cols) {
276 QWSeriesCollection.LabelGenerator lg = 188 final boolean interpolated = !col.getB().getW(km, w);
277 new QWSeriesCollection.DateFormatLabelGenerator(labelFormat); 189 final double q = col.getB().getQ(km);
278
279 QWSeriesCollection dataset = new QWSeriesCollection(lg);
280
281 double [] w = new double[1];
282 for (Pair<Fixing.Column, FixingsColumn> col: cols) {
283 boolean interpolated = !col.getB().getW(km, w);
284 double q = col.getB().getQ(km);
285 if (!Double.isNaN(w[0]) && !Double.isNaN(q)) { 190 if (!Double.isNaN(w[0]) && !Double.isNaN(q)) {
286 QWI qw = new QWI( 191 final QWI qw = new QWI(q, w[0], col.getA().getDescription(), col.getA().getStartTime(), interpolated, 0);
287 q, w[0],
288 col.getA().getDescription(),
289 col.getA().getStartTime(),
290 interpolated, 0);
291 dataset.add(qw); 192 dataset.add(qw);
292 } 193 }
293 } 194 }
294 195
295 String title = Resources.format( 196 final String title = Resources.format(callMeta, I18N_CHART_TITLE, DEFAULT_CHART_TITLE, river, km);
296 callMeta, I18N_CHART_TITLE, DEFAULT_CHART_TITLE, river, km); 197
297 198 final String qAxis = Resources.getMsg(callMeta, I18N_Q_AXIS, DEFAULT_Q_AXIS);
298 String qAxis = Resources.getMsg( 199
299 callMeta, I18N_Q_AXIS, DEFAULT_Q_AXIS); 200 final String wAxis = Resources.getMsg(callMeta, I18N_W_AXIS, DEFAULT_W_AXIS);
300 201
301 String wAxis = Resources.getMsg( 202 final JFreeChart chart = ChartFactory.createXYLineChart(title, qAxis, wAxis, null, PlotOrientation.VERTICAL, true, true, false);
302 callMeta, I18N_W_AXIS, DEFAULT_W_AXIS); 203
303 204 final XYPlot plot = (XYPlot) chart.getPlot();
304 JFreeChart chart = ChartFactory.createXYLineChart( 205
305 title, 206 final NumberAxis qA = (NumberAxis) plot.getDomainAxis();
306 qAxis,
307 wAxis,
308 null,
309 PlotOrientation.VERTICAL,
310 true,
311 true,
312 false);
313
314 XYPlot plot = (XYPlot)chart.getPlot();
315
316 NumberAxis qA = (NumberAxis)plot.getDomainAxis();
317 qA.setNumberFormatOverride(Formatter.getWaterlevelQ(callMeta)); 207 qA.setNumberFormatOverride(Formatter.getWaterlevelQ(callMeta));
318 208
319 NumberAxis wA = (NumberAxis)plot.getRangeAxis(); 209 final NumberAxis wA = (NumberAxis) plot.getRangeAxis();
320 wA.setNumberFormatOverride(Formatter.getWaterlevelW(callMeta)); 210 wA.setNumberFormatOverride(Formatter.getWaterlevelW(callMeta));
321 211
322 plot.setRenderer(0, dataset.createRenderer()); 212 plot.setRenderer(0, dataset.createRenderer());
323 plot.setDataset(0, dataset); 213 plot.setDataset(0, dataset);
324 214
325 Rectangle2D area = dataset.getArea(); 215 final Rectangle2D area = dataset.getArea();
326 216
327 if (area != null) { 217 if (area != null) {
328 double height = area.getHeight(); 218 final double height = area.getHeight();
329 double wInset = Math.max(height, 0.01) * 0.25d; 219 final double wInset = Math.max(height, 0.01) * 0.25d;
330 220
331 wA.setAutoRangeIncludesZero(false); 221 wA.setAutoRangeIncludesZero(false);
332 wA.setRange(new Range( 222 wA.setRange(new Range(area.getMinY() - wInset, area.getMaxY() + wInset));
333 area.getMinY() - wInset, 223 }
334 area.getMaxY() + wInset)); 224
335 } 225 final String measuredS = Resources.getMsg(callMeta, I18N_MEASURED, DEFAULT_MEASURED);
336 226
337 final String measuredS = Resources.getMsg( 227 final String interpolatedS = Resources.getMsg(callMeta, I18N_INTERPOLATED, DEFAULT_INTERPOLATED);
338 callMeta, I18N_MEASURED, DEFAULT_MEASURED); 228
339 229 final LegendItemCollection lic = plot.getLegendItems();
340 final String interpolatedS = Resources.getMsg(
341 callMeta, I18N_INTERPOLATED, DEFAULT_INTERPOLATED);
342
343 LegendItemCollection lic = plot.getLegendItems();
344 dataset.addLegendItems(lic, new ShapeRenderer.LabelGenerator() { 230 dataset.addLegendItems(lic, new ShapeRenderer.LabelGenerator() {
345 @Override 231 @Override
346 public String createLabel(ShapeRenderer.Entry entry) { 232 public String createLabel(final ShapeRenderer.Entry entry) {
347 return entry.getFilled() ? measuredS : interpolatedS; 233 return entry.getFilled() ? measuredS : interpolatedS;
348 } 234 }
349 }); 235 });
350 plot.setFixedLegendItems(lic); 236 plot.setFixedLegendItems(lic);
351 237
360 246
361 return chart; 247 return chart;
362 } 248 }
363 249
364 /** Add domain markers to plot that indicate Q-sectors. */ 250 /** Add domain markers to plot that indicate Q-sectors. */
365 protected static void applyQSectorMarkers( 251 protected static void applyQSectorMarkers(final XYPlot plot, final String river, final double km, final CallMeta meta) {
366 XYPlot plot, 252 final GaugeFinderFactory ggf = GaugeFinderFactory.getInstance();
367 String river, 253 final GaugeFinder gf = ggf.getGaugeFinder(river);
368 double km,
369 CallMeta meta
370 ) {
371 GaugeFinderFactory ggf = GaugeFinderFactory.getInstance();
372 GaugeFinder gf = ggf.getGaugeFinder(river);
373 254
374 if (gf == null) { 255 if (gf == null) {
375 log.warn("No gauge finder found for river '" + river + "'"); 256 log.warn("No gauge finder found for river '" + river + "'");
376 return; 257 return;
377 } 258 }
378 259
379 GaugeRange gr = gf.find(km); 260 final GaugeRange gr = gf.find(km);
380 if (gr == null) { 261 if (gr == null) {
381 log.debug("No gauge range found for km " 262 log.debug("No gauge range found for km " + km + " on river " + river + ".");
382 + km + " on river " + river + ".");
383 return; 263 return;
384 } 264 }
385 265
386 if (log.isDebugEnabled()) { 266 if (log.isDebugEnabled()) {
387 log.debug(gr); 267 log.debug(gr);
388 } 268 }
389 269
390 for (int i = 0; i < I18N_Q_SECTOR_BOARDERS.length; ++i) { 270 for (int i = 0; i < I18N_Q_SECTOR_BOARDERS.length; ++i) {
391 String key = I18N_Q_SECTOR_BOARDERS[i]; 271 final String key = I18N_Q_SECTOR_BOARDERS[i];
392 String def = DEFAULT_Q_SECTOR_BORDERS[i]; 272 final String def = DEFAULT_Q_SECTOR_BORDERS[i];
393 String label = Resources.getMsg(meta, key, def); 273 final String label = Resources.getMsg(meta, key, def);
394 274
395 Marker m = createQSectorMarker( 275 final Marker m = createQSectorMarker(gr.getSectorBorder(i), label);
396 gr.getSectorBorder(i),
397 label);
398 276
399 if (m != null) { 277 if (m != null) {
400 plot.addDomainMarker(m); 278 plot.addDomainMarker(m);
401 } 279 }
402 } 280 }
403 } 281 }
404 282
405 /** Create Marker at value with label. */ 283 /** Create Marker at value with label. */
406 protected static Marker createQSectorMarker( 284 protected static Marker createQSectorMarker(final double value, final String label) {
407 double value, String label
408 ) {
409 if (Double.isNaN(value)) { 285 if (Double.isNaN(value)) {
410 return null; 286 return null;
411 } 287 }
412 Marker m = new ValueMarker(value); 288 final Marker m = new ValueMarker(value);
413 m.setPaint(Color.black); 289 m.setPaint(Color.black);
414 m.setStroke(new BasicStroke()); 290 m.setStroke(new BasicStroke());
415 m.setLabel(label); 291 m.setLabel(label);
416 m.setLabelAnchor(RectangleAnchor.TOP_LEFT); 292 m.setLabelAnchor(RectangleAnchor.TOP_LEFT);
417 m.setLabelTextAnchor(TextAnchor.TOP_LEFT); 293 m.setLabelTextAnchor(TextAnchor.TOP_LEFT);
418 return m; 294 return m;
419 } 295 }
420 296
421 protected static String getRiverName(Document input) { 297 protected static String getRiverName(final Document input) {
422 NodeList rivers = input.getElementsByTagName("river"); 298 final NodeList rivers = input.getElementsByTagName("river");
423 299
424 if (rivers.getLength() == 0) { 300 if (rivers.getLength() == 0) {
425 return null; 301 return null;
426 } 302 }
427 303
428 String river = ((Element)rivers.item(0)).getAttribute("name"); 304 final String river = ((Element) rivers.item(0)).getAttribute("name");
429 305
430 return river.length() > 0 ? river : null; 306 return river.length() > 0 ? river : null;
431 } 307 }
432 308
433 protected static Double getKM(Document input) { 309 protected static Double getKM(final Document input) {
434 NodeList kms = input.getElementsByTagName("km"); 310 final NodeList kms = input.getElementsByTagName("km");
435 311
436 if (kms.getLength() == 0) { 312 if (kms.getLength() == 0) {
437 return null; 313 return null;
438 } 314 }
439 315
440 String km = ((Element)kms.item(0)).getAttribute("value"); 316 final String km = ((Element) kms.item(0)).getAttribute("value");
441 317
442 try { 318 try {
443 return Double.valueOf(km); 319 return Double.valueOf(km);
444 } 320 }
445 catch (NumberFormatException nfe) { 321 catch (final NumberFormatException nfe) {
446 log.warn("Km '" + km + " is not a valid number."); 322 log.warn("Km '" + km + " is not a valid number.");
447 return null; 323 return null;
448 } 324 }
449 } 325 }
450 326
451 protected static Dimension getExtent(Document input) { 327 protected static Dimension getExtent(final Document input) {
452 328
453 int width = DEFAULT_WIDTH; 329 int width = DEFAULT_WIDTH;
454 int height = DEFAULT_HEIGHT; 330 int height = DEFAULT_HEIGHT;
455 331
456 NodeList extents = input.getElementsByTagName("extent"); 332 final NodeList extents = input.getElementsByTagName("extent");
457 333
458 if (extents.getLength() > 0) { 334 if (extents.getLength() > 0) {
459 Element element = (Element)extents.item(0); 335 final Element element = (Element) extents.item(0);
460 String w = element.getAttribute("width"); 336 final String w = element.getAttribute("width");
461 String h = element.getAttribute("height"); 337 final String h = element.getAttribute("height");
462 338
463 try { 339 try {
464 width = Math.max(1, Integer.parseInt(w)); 340 width = Math.max(1, Integer.parseInt(w));
465 } 341 }
466 catch (NumberFormatException nfe) { 342 catch (final NumberFormatException nfe) {
467 log.warn("width '" + w + "' is not a valid."); 343 log.warn("width '" + w + "' is not a valid.");
468 } 344 }
469 345
470 try { 346 try {
471 height = Math.max(1, Integer.parseInt(h)); 347 height = Math.max(1, Integer.parseInt(h));
472 } 348 }
473 catch (NumberFormatException nfe) { 349 catch (final NumberFormatException nfe) {
474 log.warn("height '" + h + "' is not a valid"); 350 log.warn("height '" + h + "' is not a valid");
475 } 351 }
476 } 352 }
477 353
478 return new Dimension(width, height); 354 return new Dimension(width, height);
479 } 355 }
480 356
481 protected static String getFormat(Document input) { 357 protected static String getFormat(final Document input) {
482 String format = DEFAULT_FORMAT; 358 String format = DEFAULT_FORMAT;
483 359
484 NodeList formats = input.getElementsByTagName("format"); 360 final NodeList formats = input.getElementsByTagName("format");
485 361
486 if (formats.getLength() > 0) { 362 if (formats.getLength() > 0) {
487 String type = ((Element)formats.item(0)).getAttribute("type"); 363 final String type = ((Element) formats.item(0)).getAttribute("type");
488 if (type.length() > 0) { 364 if (type.length() > 0) {
489 format = type; 365 format = type;
490 } 366 }
491 } 367 }
492 368

http://dive4elements.wald.intevation.org