Mercurial > dive4elements > river
comparison flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/WQAdapted.java @ 3468:f37e7e8907cb
merged flys-artifacts/2.8.1
author | Thomas Arendsen Hein <thomas@intevation.de> |
---|---|
date | Fri, 28 Sep 2012 12:14:39 +0200 |
parents | 200e70f31f6f |
children | 6342166ccdef |
comparison
equal
deleted
inserted
replaced
3387:5ffad8bde8ad | 3468:f37e7e8907cb |
---|---|
1 package de.intevation.flys.artifacts.states; | |
2 | |
3 import java.util.ArrayList; | |
4 import java.util.List; | |
5 import java.util.Comparator; | |
6 import java.util.Collections; | |
7 | |
8 import org.apache.log4j.Logger; | |
9 | |
10 import org.w3c.dom.Element; | |
11 | |
12 import de.intevation.artifacts.Artifact; | |
13 import de.intevation.artifacts.CallContext; | |
14 | |
15 import de.intevation.artifactdatabase.ProtocolUtils; | |
16 import de.intevation.artifactdatabase.data.StateData; | |
17 | |
18 import de.intevation.artifacts.common.utils.XMLUtils; | |
19 | |
20 import de.intevation.flys.model.Gauge; | |
21 import de.intevation.flys.model.Range; | |
22 import de.intevation.flys.model.River; | |
23 import de.intevation.flys.model.Wst; | |
24 | |
25 import de.intevation.flys.artifacts.FLYSArtifact; | |
26 | |
27 import de.intevation.flys.artifacts.model.RangeWithValues; | |
28 import de.intevation.flys.artifacts.model.WstFactory; | |
29 import de.intevation.flys.utils.FLYSUtils; | |
30 | |
31 | |
32 /** | |
33 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> | |
34 */ | |
35 public class WQAdapted extends DefaultState { | |
36 | |
37 /** The logger used in this state.*/ | |
38 private static Logger logger = Logger.getLogger(WQAdapted.class); | |
39 | |
40 public static final String FIELD_WQ_MODE = "wq_isq"; | |
41 | |
42 public static final String FIELD_WQ_VALUES = "wq_values"; | |
43 | |
44 public static final class GaugeOrder implements Comparator<Gauge> { | |
45 private int order; | |
46 | |
47 public GaugeOrder(boolean up) { | |
48 order = up ? 1 : -1; | |
49 } | |
50 | |
51 public int compare(Gauge a, Gauge b) { | |
52 return order * a.getRange().getA().compareTo(b.getRange().getA()); | |
53 } | |
54 } // class GaugeOrder | |
55 | |
56 public static final GaugeOrder GAUGE_UP = new GaugeOrder(true); | |
57 public static final GaugeOrder GAUGE_DOWN = new GaugeOrder(false); | |
58 | |
59 public WQAdapted() { | |
60 } | |
61 | |
62 | |
63 /** | |
64 * This method creates one element for each gauge of the selected river that | |
65 * is intersected by the given kilometer range. Each element is a tuple of | |
66 * (from;to) where <i>from</i> is the lower bounds of the gauge or the lower | |
67 * kilometer range. <i>to</i> is the upper bounds of the gauge or the upper | |
68 * kilometer range. | |
69 * | |
70 * @param cr The ElementCreator. | |
71 * @param artifact The FLYS artifact. | |
72 * @param name The name of the data item. | |
73 * @param context The CallContext. | |
74 * | |
75 * @return a list of elements that consist of tuples of the intersected | |
76 * gauges of the selected river. | |
77 */ | |
78 @Override | |
79 protected Element[] createItems( | |
80 XMLUtils.ElementCreator cr, | |
81 Artifact artifact, | |
82 String name, | |
83 CallContext context) | |
84 { | |
85 logger.debug("WQAdapted.createItems"); | |
86 | |
87 if (name != null && name.equals(FIELD_WQ_MODE)) { | |
88 return createModeItems(cr, artifact, name, context); | |
89 } | |
90 else if (name != null && name.equals(FIELD_WQ_VALUES)) { | |
91 return createValueItems(cr, artifact, name, context); | |
92 } | |
93 else { | |
94 logger.warn("Unknown data object: " + name); | |
95 return null; | |
96 } | |
97 } | |
98 | |
99 | |
100 protected Element[] createModeItems( | |
101 XMLUtils.ElementCreator cr, | |
102 Artifact artifact, | |
103 String name, | |
104 CallContext context) | |
105 { | |
106 logger.debug("WQAdapted.createModeItems"); | |
107 | |
108 Element w = createItem(cr, new String[] { "w", "W" }); | |
109 Element q = createItem(cr, new String[] { "q", "Q" }); | |
110 | |
111 return new Element[] { w, q }; | |
112 } | |
113 | |
114 | |
115 protected Element[] createValueItems( | |
116 XMLUtils.ElementCreator cr, | |
117 Artifact artifact, | |
118 String name, | |
119 CallContext context) | |
120 { | |
121 logger.debug("WQAdapted.createValueItems"); | |
122 | |
123 FLYSArtifact flysArtifact = (FLYSArtifact) artifact; | |
124 | |
125 double[] dist = FLYSUtils.getKmRange(flysArtifact); | |
126 River river = FLYSUtils.getRiver(flysArtifact); | |
127 Wst wst = WstFactory.getWst(river); | |
128 List<Gauge> gauges = FLYSUtils.getGauges(flysArtifact); | |
129 | |
130 int num = gauges != null ? gauges.size() : 0; | |
131 | |
132 if (num == 0) { | |
133 logger.warn("Selected distance matches no gauges."); | |
134 return null; | |
135 } | |
136 | |
137 Element[] elements = new Element[num]; | |
138 | |
139 double rangeFrom = dist[0]; | |
140 double rangeTo = dist[1]; | |
141 | |
142 int idx = 0; | |
143 | |
144 if (rangeFrom < rangeTo) { | |
145 Collections.sort(gauges, GAUGE_UP); | |
146 for (Gauge gauge: gauges) { | |
147 Range range = gauge.getRange(); | |
148 double lower = range.getA().doubleValue(); | |
149 double upper = range.getB().doubleValue(); | |
150 | |
151 double from = lower < rangeFrom ? rangeFrom : lower; | |
152 double to = upper > rangeTo ? rangeTo : upper; | |
153 | |
154 double[] mmQ = determineMinMaxQ(gauge, wst); | |
155 double[] mmW = gauge.determineMinMaxW(); | |
156 | |
157 elements[idx++] = createItem( | |
158 cr, new String[] { from + ";" + to, ""}, mmQ, mmW); | |
159 } | |
160 } | |
161 else { | |
162 Collections.sort(gauges, GAUGE_DOWN); | |
163 rangeFrom = dist[1]; | |
164 rangeTo = dist[0]; | |
165 for (Gauge gauge: gauges) { | |
166 Range range = gauge.getRange(); | |
167 double lower = range.getA().doubleValue(); | |
168 double upper = range.getB().doubleValue(); | |
169 | |
170 double from = lower < rangeFrom ? rangeFrom : lower; | |
171 double to = upper > rangeTo ? rangeTo : upper; | |
172 | |
173 double[] mmQ = determineMinMaxQ(gauge, wst); | |
174 double[] mmW = gauge.determineMinMaxW(); | |
175 | |
176 elements[idx++] = createItem( | |
177 cr, new String[] { to + ";" + from, ""}, mmQ, mmW); | |
178 } | |
179 } | |
180 | |
181 return elements; | |
182 } | |
183 | |
184 | |
185 protected Element createItem(XMLUtils.ElementCreator cr, Object obj) { | |
186 return createItem(cr, obj, null, null); | |
187 } | |
188 | |
189 | |
190 protected Element createItem( | |
191 XMLUtils.ElementCreator cr, | |
192 Object obj, | |
193 double[] q, | |
194 double[] w) | |
195 { | |
196 Element item = ProtocolUtils.createArtNode(cr, "item", null, null); | |
197 Element label = ProtocolUtils.createArtNode(cr, "label", null, null); | |
198 Element value = ProtocolUtils.createArtNode(cr, "value", null, null); | |
199 | |
200 String[] arr = (String[]) obj; | |
201 | |
202 label.setTextContent(arr[0]); | |
203 value.setTextContent(arr[1]); | |
204 | |
205 item.appendChild(label); | |
206 item.appendChild(value); | |
207 | |
208 if (q != null) { | |
209 Element qRange = createRangeElement(cr, q, "Q"); | |
210 item.appendChild(qRange); | |
211 } | |
212 | |
213 if (w != null) { | |
214 Element wRange = createRangeElement(cr, w, "W"); | |
215 item.appendChild(wRange); | |
216 } | |
217 | |
218 return item; | |
219 } | |
220 | |
221 | |
222 protected Element createRangeElement( | |
223 XMLUtils.ElementCreator cr, | |
224 double[] mm, | |
225 String type) | |
226 { | |
227 Element range = ProtocolUtils.createArtNode( | |
228 cr, "range", | |
229 new String[] {"type"}, | |
230 new String[] {type}); | |
231 | |
232 Element min = ProtocolUtils.createArtNode(cr, "min", null, null); | |
233 min.setTextContent(String.valueOf(mm[0])); | |
234 | |
235 Element max = ProtocolUtils.createArtNode(cr, "max", null, null); | |
236 max.setTextContent(String.valueOf(mm[1])); | |
237 | |
238 range.appendChild(min); | |
239 range.appendChild(max); | |
240 | |
241 return range; | |
242 } | |
243 | |
244 | |
245 /** | |
246 * Determines the min and max Q value for the given gauge. If no min and | |
247 * max values could be determined, this method will return | |
248 * [Double.MIN_VALUE, Double.MAX_VALUE]. | |
249 * | |
250 * @param gauge | |
251 * @param wst | |
252 * | |
253 * @return the min and max Q values for the given gauge. | |
254 */ | |
255 protected double[] determineMinMaxQ(Gauge gauge, Wst wst) { | |
256 logger.debug("WQAdapted.determineMinMaxQ"); | |
257 | |
258 double[] minmaxQ = gauge != null | |
259 ? wst.determineMinMaxQ(gauge.getRange()) | |
260 : null; | |
261 | |
262 double minQ = minmaxQ != null ? minmaxQ[0] : Double.MIN_VALUE; | |
263 double maxQ = minmaxQ != null ? minmaxQ[1] : Double.MAX_VALUE; | |
264 | |
265 return new double[] { minQ, maxQ }; | |
266 } | |
267 | |
268 | |
269 @Override | |
270 protected String getUIProvider() { | |
271 return "wq_panel_adapted"; | |
272 } | |
273 | |
274 | |
275 @Override | |
276 public boolean validate(Artifact artifact) | |
277 throws IllegalArgumentException | |
278 { | |
279 logger.debug("WQAdapted.validate"); | |
280 | |
281 FLYSArtifact flys = (FLYSArtifact) artifact; | |
282 StateData data = getData(flys, FIELD_WQ_MODE); | |
283 | |
284 String mode = data != null ? (String) data.getValue() : null; | |
285 boolean isQ = mode != null | |
286 ? Boolean.valueOf(mode) | |
287 : false; | |
288 | |
289 if (!isQ) { | |
290 return validateW(artifact); | |
291 } | |
292 else if (isQ) { | |
293 return validateQ(artifact); | |
294 } | |
295 else { | |
296 throw new IllegalArgumentException("error_feed_no_wq_mode_selected"); | |
297 } | |
298 } | |
299 | |
300 | |
301 protected boolean validateW(Artifact artifact) | |
302 throws IllegalArgumentException | |
303 { | |
304 logger.debug("WQAdapted.validateW"); | |
305 FLYSArtifact flys = (FLYSArtifact) artifact; | |
306 | |
307 RangeWithValues[] rwvs = extractInput(getData(flys, "wq_values")); | |
308 | |
309 if (rwvs == null) { | |
310 throw new IllegalArgumentException("error_missing_wq_data"); | |
311 } | |
312 | |
313 List<Gauge> gauges = FLYSUtils.getGauges((FLYSArtifact) artifact); | |
314 | |
315 for (Gauge gauge: gauges) { | |
316 Range range = gauge.getRange(); | |
317 double lower = range.getA().doubleValue(); | |
318 double upper = range.getB().doubleValue(); | |
319 | |
320 for (RangeWithValues rwv: rwvs) { | |
321 if (lower <= rwv.getLower() && upper >= rwv.getUpper()) { | |
322 compareWsWithGauge(gauge, rwv.getValues()); | |
323 } | |
324 } | |
325 } | |
326 | |
327 return true; | |
328 } | |
329 | |
330 | |
331 protected boolean validateQ(Artifact artifact) | |
332 throws IllegalArgumentException | |
333 { | |
334 logger.debug("WQAdapted.validateQ"); | |
335 FLYSArtifact flys = (FLYSArtifact) artifact; | |
336 | |
337 RangeWithValues[] rwvs = extractInput(getData(flys, "wq_values")); | |
338 | |
339 if (rwvs == null) { | |
340 throw new IllegalArgumentException("error_missing_wq_data"); | |
341 } | |
342 | |
343 List<Gauge> gauges = FLYSUtils.getGauges(flys); | |
344 River river = FLYSUtils.getRiver(flys); | |
345 Wst wst = WstFactory.getWst(river); | |
346 | |
347 for (Gauge gauge: gauges) { | |
348 Range range = gauge.getRange(); | |
349 double lower = range.getA().doubleValue(); | |
350 double upper = range.getB().doubleValue(); | |
351 | |
352 for (RangeWithValues rwv: rwvs) { | |
353 if (lower <= rwv.getLower() && upper >= rwv.getUpper()) { | |
354 compareQsWithGauge(wst, gauge, rwv.getValues()); | |
355 } | |
356 } | |
357 } | |
358 | |
359 return true; | |
360 } | |
361 | |
362 | |
363 protected boolean compareQsWithGauge(Wst wst, Gauge gauge, double[] qs) | |
364 throws IllegalArgumentException | |
365 { | |
366 double[] minmax = gauge != null | |
367 ? wst.determineMinMaxQ(gauge.getRange()) | |
368 : null; | |
369 | |
370 if (minmax == null) { | |
371 logger.warn("Could not determine min/max Q of gauge."); | |
372 return true; | |
373 } | |
374 | |
375 if (logger.isDebugEnabled()) { | |
376 logger.debug("Validate Qs with:"); | |
377 logger.debug("-- Gauge: " + gauge.getName()); | |
378 logger.debug("-- Gauge min: " + minmax[0]); | |
379 logger.debug("-- Gauge max: " + minmax[1]); | |
380 } | |
381 | |
382 for (double q: qs) { | |
383 if (q < minmax[0] || q > minmax[1]) { | |
384 throw new IllegalArgumentException( | |
385 "error_feed_q_values_invalid"); | |
386 } | |
387 } | |
388 | |
389 return true; | |
390 } | |
391 | |
392 | |
393 protected boolean compareWsWithGauge(Gauge gauge, double[] ws) | |
394 throws IllegalArgumentException | |
395 { | |
396 double[] minmax = gauge != null | |
397 ? gauge.determineMinMaxW() | |
398 : null; | |
399 | |
400 if (minmax == null) { | |
401 logger.warn("Could not determine min/max W of gauge."); | |
402 return true; | |
403 } | |
404 | |
405 if (logger.isDebugEnabled()) { | |
406 logger.debug("Validate Ws with:"); | |
407 logger.debug("-- Gauge: " + gauge.getName()); | |
408 logger.debug("-- Gauge min: " + minmax[0]); | |
409 logger.debug("-- Gauge max: " + minmax[1]); | |
410 } | |
411 | |
412 for (double w: ws) { | |
413 if (w < minmax[0] || w > minmax[1]) { | |
414 throw new IllegalArgumentException( | |
415 "error_feed_w_values_invalid"); | |
416 } | |
417 } | |
418 | |
419 return true; | |
420 } | |
421 | |
422 | |
423 protected RangeWithValues[] extractInput(StateData data) { | |
424 if (data == null) { | |
425 return null; | |
426 } | |
427 | |
428 String dataString = (String) data.getValue(); | |
429 String[] ranges = dataString.split(":"); | |
430 | |
431 List<RangeWithValues> rwv = new ArrayList<RangeWithValues>(); | |
432 | |
433 for (String range: ranges) { | |
434 String[] parts = range.split(";"); | |
435 | |
436 double lower = Double.parseDouble(parts[0]); | |
437 double upper = Double.parseDouble(parts[1]); | |
438 | |
439 String[] values = parts[2].split(","); | |
440 | |
441 int num = values.length; | |
442 double[] res = new double[num]; | |
443 | |
444 for (int i = 0; i < num; i++) { | |
445 try { | |
446 res[i] = Double.parseDouble(values[i]); | |
447 } | |
448 catch (NumberFormatException nfe) { | |
449 logger.warn(nfe, nfe); | |
450 } | |
451 } | |
452 | |
453 rwv.add(new RangeWithValues(lower, upper, res)); | |
454 } | |
455 | |
456 return rwv.toArray(new RangeWithValues[rwv.size()]); | |
457 } | |
458 } | |
459 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : |