comparison flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/WQAdapted.java @ 3814:8083f6384023

merged flys-artifacts/pre2.6-2012-01-04
author Thomas Arendsen Hein <thomas@intevation.de>
date Fri, 28 Sep 2012 12:14:56 +0200
parents e0243627ba62
children 44dc117aa2b7
comparison
equal deleted inserted replaced
1491:2a00f4849738 3814:8083f6384023
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.WINFOArtifact;
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
41 public static final String FIELD_WQ_MODE = "wq_mode";
42
43 public static final String FIELD_WQ_VALUES = "wq_values";
44
45 public static final class GaugeOrder implements Comparator<Gauge> {
46 private int order;
47
48 public GaugeOrder(boolean up) {
49 order = up ? 1 : -1;
50 }
51
52 public int compare(Gauge a, Gauge b) {
53 return order * a.getRange().getA().compareTo(b.getRange().getA());
54 }
55 } // class GaugeOrder
56
57 public static final GaugeOrder GAUGE_UP = new GaugeOrder(true);
58 public static final GaugeOrder GAUGE_DOWN = new GaugeOrder(false);
59
60 public WQAdapted() {
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 WINFOArtifact flysArtifact = (WINFOArtifact) artifact;
124
125 double[] dist = FLYSUtils.getKmRange(flysArtifact);
126 River river = FLYSUtils.getRiver(flysArtifact);
127 Wst wst = WstFactory.getWst(river);
128 List<Gauge> gauges = flysArtifact.getGauges();
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 WINFOArtifact flys = (WINFOArtifact) artifact;
282 StateData data = getData(flys, FIELD_WQ_MODE);
283
284 String mode = data != null ? (String) data.getValue() : null;
285
286 if (mode != null && mode.equals("W")) {
287 return validateW(artifact);
288 }
289 else if (mode != null && mode.equals("Q")) {
290 return validateQ(artifact);
291 }
292 else {
293 throw new IllegalArgumentException("error_feed_no_wq_mode_selected");
294 }
295 }
296
297
298 protected boolean validateW(Artifact artifact)
299 throws IllegalArgumentException
300 {
301 logger.debug("WQAdapted.validateW");
302 WINFOArtifact flys = (WINFOArtifact) artifact;
303
304 RangeWithValues[] rwvs = extractInput(getData(flys, "wq_values"));
305
306 if (rwvs == null) {
307 throw new IllegalArgumentException("error_missing_wq_data");
308 }
309
310 List<Gauge> gauges = ((WINFOArtifact) artifact).getGauges();
311
312 for (Gauge gauge: gauges) {
313 Range range = gauge.getRange();
314 double lower = range.getA().doubleValue();
315 double upper = range.getB().doubleValue();
316
317 for (RangeWithValues rwv: rwvs) {
318 if (lower <= rwv.getLower() && upper >= rwv.getUpper()) {
319 compareWsWithGauge(gauge, rwv.getValues());
320 }
321 }
322 }
323
324 return true;
325 }
326
327
328 protected boolean validateQ(Artifact artifact)
329 throws IllegalArgumentException
330 {
331 logger.debug("WQAdapted.validateQ");
332 WINFOArtifact flys = (WINFOArtifact) artifact;
333
334 RangeWithValues[] rwvs = extractInput(getData(flys, "wq_values"));
335
336 if (rwvs == null) {
337 throw new IllegalArgumentException("error_missing_wq_data");
338 }
339
340 List<Gauge> gauges = flys.getGauges();
341 River river = FLYSUtils.getRiver(flys);
342 Wst wst = WstFactory.getWst(river);
343
344 for (Gauge gauge: gauges) {
345 Range range = gauge.getRange();
346 double lower = range.getA().doubleValue();
347 double upper = range.getB().doubleValue();
348
349 for (RangeWithValues rwv: rwvs) {
350 if (lower <= rwv.getLower() && upper >= rwv.getUpper()) {
351 compareQsWithGauge(wst, gauge, rwv.getValues());
352 }
353 }
354 }
355
356 return true;
357 }
358
359
360 protected boolean compareQsWithGauge(Wst wst, Gauge gauge, double[] qs)
361 throws IllegalArgumentException
362 {
363 double[] minmax = gauge != null
364 ? wst.determineMinMaxQ(gauge.getRange())
365 : null;
366
367 if (minmax == null) {
368 logger.warn("Could not determine min/max Q of gauge.");
369 return true;
370 }
371
372 if (logger.isDebugEnabled()) {
373 logger.debug("Validate Qs with:");
374 logger.debug("-- Gauge: " + gauge.getName());
375 logger.debug("-- Gauge min: " + minmax[0]);
376 logger.debug("-- Gauge max: " + minmax[1]);
377 }
378
379 for (double q: qs) {
380 if (q < minmax[0] || q > minmax[1]) {
381 throw new IllegalArgumentException(
382 "error_feed_q_values_invalid");
383 }
384 }
385
386 return true;
387 }
388
389
390 protected boolean compareWsWithGauge(Gauge gauge, double[] ws)
391 throws IllegalArgumentException
392 {
393 double[] minmax = gauge != null
394 ? gauge.determineMinMaxW()
395 : null;
396
397 if (minmax == null) {
398 logger.warn("Could not determine min/max W of gauge.");
399 return true;
400 }
401
402 if (logger.isDebugEnabled()) {
403 logger.debug("Validate Ws with:");
404 logger.debug("-- Gauge: " + gauge.getName());
405 logger.debug("-- Gauge min: " + minmax[0]);
406 logger.debug("-- Gauge max: " + minmax[1]);
407 }
408
409 for (double w: ws) {
410 if (w < minmax[0] || w > minmax[1]) {
411 throw new IllegalArgumentException(
412 "error_feed_w_values_invalid");
413 }
414 }
415
416 return true;
417 }
418
419
420 protected RangeWithValues[] extractInput(StateData data) {
421 if (data == null) {
422 return null;
423 }
424
425 String dataString = (String) data.getValue();
426 String[] ranges = dataString.split(":");
427
428 List<RangeWithValues> rwv = new ArrayList<RangeWithValues>();
429
430 for (String range: ranges) {
431 String[] parts = range.split(";");
432
433 double lower = Double.parseDouble(parts[0]);
434 double upper = Double.parseDouble(parts[1]);
435
436 String[] values = parts[2].split(",");
437
438 int num = values.length;
439 double[] res = new double[num];
440
441 for (int i = 0; i < num; i++) {
442 try {
443 res[i] = Double.parseDouble(values[i]);
444 }
445 catch (NumberFormatException nfe) {
446 logger.warn(nfe, nfe);
447 }
448 }
449
450 rwv.add(new RangeWithValues(lower, upper, res));
451 }
452
453 return (RangeWithValues[]) rwv.toArray(new RangeWithValues[rwv.size()]);
454 }
455 }
456 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :

http://dive4elements.wald.intevation.org