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 :

http://dive4elements.wald.intevation.org