Mercurial > dive4elements > river
comparison flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/WQSelect.java @ 3812:f788d2d901d6
merged flys-artifacts/pre2.6-2011-12-05
author | Thomas Arendsen Hein <thomas@intevation.de> |
---|---|
date | Fri, 28 Sep 2012 12:14:53 +0200 |
parents | 8a2cbf947395 |
children | 6762f54b23b1 |
comparison
equal
deleted
inserted
replaced
3808:5fab0fe3c445 | 3812:f788d2d901d6 |
---|---|
1 package de.intevation.flys.artifacts.states; | |
2 | |
3 import java.text.NumberFormat; | |
4 | |
5 import gnu.trove.TDoubleArrayList; | |
6 | |
7 import org.apache.log4j.Logger; | |
8 | |
9 import org.w3c.dom.Element; | |
10 | |
11 import de.intevation.artifacts.Artifact; | |
12 import de.intevation.artifacts.CallContext; | |
13 | |
14 import de.intevation.artifacts.common.utils.XMLUtils; | |
15 import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; | |
16 | |
17 import de.intevation.artifactdatabase.ProtocolUtils; | |
18 import de.intevation.artifactdatabase.data.StateData; | |
19 | |
20 import de.intevation.flys.model.Gauge; | |
21 import de.intevation.flys.model.River; | |
22 import de.intevation.flys.model.Wst; | |
23 | |
24 import de.intevation.flys.artifacts.FLYSArtifact; | |
25 import de.intevation.flys.artifacts.WINFOArtifact; | |
26 | |
27 import de.intevation.flys.artifacts.model.WstFactory; | |
28 import de.intevation.flys.artifacts.resources.Resources; | |
29 | |
30 import de.intevation.flys.utils.FLYSUtils; | |
31 | |
32 | |
33 /** | |
34 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> | |
35 */ | |
36 public class WQSelect extends DefaultState { | |
37 | |
38 /** The logger used in this class. */ | |
39 private static Logger logger = Logger.getLogger(WQSelect.class); | |
40 | |
41 | |
42 /** The default step width for Qs. */ | |
43 public static final String DEFAULT_STEP_Q = "50"; | |
44 | |
45 /** The default step width for Qs. */ | |
46 public static final String DEFAULT_STEP_W = "30"; | |
47 | |
48 /** The name of the 'mode' field. */ | |
49 public static final String WQ_MODE = "wq_mode"; | |
50 | |
51 /** Them name fo the 'free' field. */ | |
52 public static final String WQ_FREE = "wq_free"; | |
53 | |
54 /** The name of the 'selection' field. */ | |
55 public static final String WQ_SELECTION = "wq_selection"; | |
56 | |
57 /** The name of the 'from' field. */ | |
58 public static final String WQ_FROM = "wq_from"; | |
59 | |
60 /** The name of the 'to' field. */ | |
61 public static final String WQ_TO = "wq_to"; | |
62 | |
63 /** The name of the 'step' field. */ | |
64 public static final String WQ_STEP = "wq_step"; | |
65 | |
66 /** The name of the 'single' field. */ | |
67 public static final String WQ_SINGLE = "wq_single"; | |
68 | |
69 | |
70 /** | |
71 * The default constructor that initializes an empty State object. | |
72 */ | |
73 public WQSelect() { | |
74 } | |
75 | |
76 | |
77 @Override | |
78 protected Element createStaticData( | |
79 FLYSArtifact flys, | |
80 ElementCreator creator, | |
81 CallContext cc, | |
82 String name, | |
83 String value, | |
84 String type | |
85 ) { | |
86 if (!name.equals(WQ_SINGLE)) { | |
87 return super.createStaticData(flys, creator, cc, name, value, type); | |
88 } | |
89 | |
90 String mode = flys.getDataAsString(WQ_MODE); | |
91 String free = flys.getDataAsString(WQ_FREE); | |
92 if (mode == null || mode.equals("W") || Boolean.valueOf(free)) { | |
93 return super.createStaticData(flys, creator, cc, name, value, type); | |
94 } | |
95 | |
96 WINFOArtifact winfo = (WINFOArtifact) flys; | |
97 | |
98 Element dataElement = creator.create("data"); | |
99 creator.addAttr(dataElement, "name", name, true); | |
100 creator.addAttr(dataElement, "type", type, true); | |
101 | |
102 Element itemElement = creator.create("item"); | |
103 creator.addAttr(itemElement, "value", value, true); | |
104 creator.addAttr(itemElement, "label", getLabel(winfo, cc, value), true); | |
105 | |
106 dataElement.appendChild(itemElement); | |
107 | |
108 return dataElement; | |
109 } | |
110 | |
111 | |
112 protected static String getLabel( | |
113 WINFOArtifact winfo, | |
114 CallContext cc, | |
115 String raw | |
116 ) { | |
117 String[] values = raw.split(" "); | |
118 String label = null; | |
119 | |
120 NumberFormat nf = NumberFormat.getInstance( | |
121 Resources.getLocale(cc.getMeta())); | |
122 | |
123 for (String value: values) { | |
124 try { | |
125 double v = Double.valueOf(value.trim()); | |
126 | |
127 String tmp = nf.format(v); | |
128 String mv = FLYSUtils.getNamedMainValue(winfo.getGauge(),v); | |
129 | |
130 if (mv != null && mv.length() > 0) { | |
131 String add = mv + ": " + tmp; | |
132 label = label != null ? label + ", " + add : add; | |
133 } | |
134 else { | |
135 label = label != null ? label + ", " + tmp : tmp; | |
136 } | |
137 } | |
138 catch (NumberFormatException nfe) { | |
139 // do nothing here | |
140 } | |
141 } | |
142 | |
143 return label; | |
144 } | |
145 | |
146 | |
147 @Override | |
148 protected Element createData( | |
149 XMLUtils.ElementCreator cr, | |
150 Artifact artifact, | |
151 StateData data, | |
152 CallContext context) | |
153 { | |
154 Element select = ProtocolUtils.createArtNode( | |
155 cr, "select", null, null); | |
156 | |
157 cr.addAttr(select, "name", data.getName(), true); | |
158 | |
159 Element label = ProtocolUtils.createArtNode( | |
160 cr, "label", null, null); | |
161 | |
162 Element choices = ProtocolUtils.createArtNode( | |
163 cr, "choices", null, null); | |
164 | |
165 label.setTextContent(Resources.getMsg( | |
166 context.getMeta(), | |
167 data.getName(), | |
168 data.getName())); | |
169 | |
170 select.appendChild(label); | |
171 | |
172 return select; | |
173 } | |
174 | |
175 | |
176 @Override | |
177 protected Element[] createItems( | |
178 XMLUtils.ElementCreator cr, | |
179 Artifact artifact, | |
180 String name, | |
181 CallContext context) | |
182 { | |
183 // TODO Insert correct min/max values! | |
184 double[] minmaxW = determineMinMaxW(artifact); | |
185 double[] minmaxQ = determineMinMaxQ(artifact); | |
186 | |
187 if (name.equals("wq_from")) { | |
188 Element minW = createItem( | |
189 cr, new String[] {"minW", new Double(minmaxW[0]).toString()}); | |
190 Element minQ = createItem( | |
191 cr, new String[] {"minQ", new Double(minmaxQ[0]).toString()}); | |
192 return new Element[] { minW, minQ }; | |
193 } | |
194 else if (name.equals("wq_to")) { | |
195 Element maxW = createItem( | |
196 cr, new String[] {"maxW", new Double(minmaxW[1]).toString()}); | |
197 Element maxQ = createItem( | |
198 cr, new String[] {"maxQ", new Double(minmaxQ[1]).toString()}); | |
199 return new Element[] { maxW, maxQ }; | |
200 } | |
201 else { | |
202 Element stepW = createItem( | |
203 cr, new String[] {"stepW", DEFAULT_STEP_W}); | |
204 Element stepQ = createItem( | |
205 cr, new String[] {"stepQ", DEFAULT_STEP_Q}); | |
206 return new Element[] { stepW, stepQ }; | |
207 } | |
208 } | |
209 | |
210 | |
211 protected Element createItem(XMLUtils.ElementCreator cr, Object obj) { | |
212 Element item = ProtocolUtils.createArtNode(cr, "item", null, null); | |
213 Element label = ProtocolUtils.createArtNode(cr, "label", null, null); | |
214 Element value = ProtocolUtils.createArtNode(cr, "value", null, null); | |
215 | |
216 String[] arr = (String[]) obj; | |
217 | |
218 label.setTextContent(arr[0]); | |
219 value.setTextContent(arr[1]); | |
220 | |
221 item.appendChild(label); | |
222 item.appendChild(value); | |
223 | |
224 return item; | |
225 } | |
226 | |
227 | |
228 @Override | |
229 protected String getUIProvider() { | |
230 return "wq_panel"; | |
231 } | |
232 | |
233 | |
234 /** | |
235 * Determines the min and max W value for the current gauge. If no min and | |
236 * max values could be determined, this method will return | |
237 * [Double.MIN_VALUE, Double.MAX_VALUE]. | |
238 * | |
239 * @param artifact The FLYSArtifact. | |
240 * | |
241 * @return the min and max W values for the current gauge. | |
242 */ | |
243 protected double[] determineMinMaxW(Artifact artifact) { | |
244 logger.debug("WQSelect.determineCurrentGauge"); | |
245 | |
246 Gauge gauge = ((WINFOArtifact) artifact).getGauge(); | |
247 double[] minmaxW = gauge != null ? gauge.determineMinMaxW() : null; | |
248 | |
249 double minW = minmaxW != null ? minmaxW[0] : Double.MIN_VALUE; | |
250 double maxW = minmaxW != null ? minmaxW[1] : Double.MAX_VALUE; | |
251 | |
252 return new double[] { minW, maxW }; | |
253 } | |
254 | |
255 | |
256 /** | |
257 * Determines the min and max Q value for the current gauge. If no min and | |
258 * max values could be determined, this method will return | |
259 * [Double.MIN_VALUE, Double.MAX_VALUE]. | |
260 * | |
261 * @param artifact The FLYSArtifact. | |
262 * | |
263 * @return the min and max Q values for the current gauge. | |
264 */ | |
265 protected double[] determineMinMaxQ(Artifact artifact) { | |
266 logger.debug("WQSelect.determineMinMaxQ"); | |
267 | |
268 WINFOArtifact flysArtifact = (WINFOArtifact) artifact; | |
269 | |
270 River river = FLYSUtils.getRiver(flysArtifact); | |
271 Gauge gauge = flysArtifact.getGauge(); | |
272 Wst wst = WstFactory.getWst(river); | |
273 | |
274 double[] minmaxQ = gauge != null | |
275 ? wst.determineMinMaxQ(gauge.getRange()) | |
276 : null; | |
277 | |
278 double minQ = minmaxQ != null ? minmaxQ[0] : Double.MIN_VALUE; | |
279 double maxQ = minmaxQ != null ? minmaxQ[1] : Double.MAX_VALUE; | |
280 | |
281 return new double[] { minQ, maxQ }; | |
282 } | |
283 | |
284 | |
285 @Override | |
286 public boolean validate(Artifact artifact) | |
287 throws IllegalArgumentException | |
288 { | |
289 logger.debug("WQSelect.validate"); | |
290 | |
291 WINFOArtifact flys = (WINFOArtifact) artifact; | |
292 | |
293 StateData data = getData(flys, WQ_SELECTION); | |
294 String selectionMode = data != null ? (String) data.getValue() : null; | |
295 | |
296 if (selectionMode == null || selectionMode.equals("single")) { | |
297 return validateSingle(artifact); | |
298 } | |
299 else { | |
300 return validateRange(artifact); | |
301 } | |
302 } | |
303 | |
304 | |
305 protected boolean validateBounds( | |
306 double fromValid, double toValid, | |
307 double from, double to, double step) | |
308 throws IllegalArgumentException | |
309 { | |
310 logger.debug("RangeState.validateRange"); | |
311 | |
312 if (from < fromValid) { | |
313 logger.error( | |
314 "Invalid 'from'. " + from + " is smaller than " + fromValid); | |
315 throw new IllegalArgumentException("error_feed_from_out_of_range"); | |
316 } | |
317 else if (to > toValid) { | |
318 logger.error( | |
319 "Invalid 'to'. " + to + " is bigger than " + toValid); | |
320 throw new IllegalArgumentException("error_feed_to_out_of_range"); | |
321 } | |
322 | |
323 return true; | |
324 } | |
325 | |
326 | |
327 protected boolean validateSingle(Artifact artifact) | |
328 throws IllegalArgumentException | |
329 { | |
330 logger.debug("WQSelect.validateSingle"); | |
331 | |
332 WINFOArtifact flys = (WINFOArtifact) artifact; | |
333 StateData data = getData(flys, WQ_SINGLE); | |
334 | |
335 String tmp = data != null ? (String) data.getValue() : null; | |
336 | |
337 if (tmp == null || tmp.length() == 0) { | |
338 throw new IllegalArgumentException("error_empty_state"); | |
339 } | |
340 | |
341 String[] strValues = tmp.split(" "); | |
342 TDoubleArrayList all = new TDoubleArrayList(); | |
343 | |
344 for (String strValue: strValues) { | |
345 try { | |
346 all.add(Double.parseDouble(strValue)); | |
347 } | |
348 catch (NumberFormatException nfe) { | |
349 logger.warn(nfe, nfe); | |
350 } | |
351 } | |
352 | |
353 all.sort(); | |
354 | |
355 StateData dMode = getData(flys, WQ_MODE); | |
356 String mode = dMode != null ? (String) data.getValue() : null; | |
357 | |
358 logger.debug("WQ Mode: " + mode); | |
359 | |
360 double[] minmax = null; | |
361 | |
362 if (mode != null && mode.trim().toLowerCase().equals("w")) { | |
363 minmax = determineMinMaxW(artifact); | |
364 } | |
365 else { | |
366 minmax = determineMinMaxQ(artifact); | |
367 } | |
368 | |
369 double min = all.get(0); | |
370 double max = all.get(all.size()-1); | |
371 | |
372 logger.debug("Inserted min value = " + min); | |
373 logger.debug("Inserted max value = " + max); | |
374 | |
375 return validateBounds(minmax[0], minmax[1], min, max, 0d); | |
376 } | |
377 | |
378 | |
379 protected boolean validateRange(Artifact artifact) | |
380 throws IllegalArgumentException | |
381 { | |
382 logger.debug("WQSelect.validateRange"); | |
383 WINFOArtifact flys = (WINFOArtifact) artifact; | |
384 | |
385 StateData data = flys.getData(WQ_MODE); | |
386 String mode = data != null ? (String) data.getValue() : null; | |
387 logger.debug("WQ Mode: " + mode); | |
388 | |
389 if (mode == null || mode.length() == 0) { | |
390 throw new IllegalArgumentException("error_feed_invalid_wq_mode"); | |
391 } | |
392 | |
393 StateData dFrom = flys.getData(WQ_FROM); | |
394 StateData dTo = flys.getData(WQ_TO); | |
395 StateData dStep = flys.getData(WQ_STEP); | |
396 | |
397 String fromStr = dFrom != null ? (String) dFrom.getValue() : null; | |
398 String toStr = dTo != null ? (String) dTo.getValue() : null; | |
399 String stepStr = dStep != null ? (String) dStep.getValue() : null; | |
400 | |
401 if (fromStr == null || toStr == null || stepStr == null) { | |
402 throw new IllegalArgumentException("error_empty_state"); | |
403 } | |
404 | |
405 try { | |
406 double from = Double.parseDouble(fromStr); | |
407 double to = Double.parseDouble(toStr); | |
408 double step = Double.parseDouble(stepStr); | |
409 | |
410 if (mode != null && mode.trim().toLowerCase().equals("w")) { | |
411 return validateW(artifact, from, to, step); | |
412 } | |
413 else if (mode != null && mode.trim().toLowerCase().equals("q")) { | |
414 return validateQ(artifact, from, to, step); | |
415 } | |
416 else { | |
417 throw new IllegalArgumentException( | |
418 "error_feed_invalid_wq_mode"); | |
419 } | |
420 } | |
421 catch (NumberFormatException nfe) { | |
422 throw new IllegalArgumentException("error_feed_number_format"); | |
423 } | |
424 } | |
425 | |
426 | |
427 /** | |
428 * Validates the inserted W values. | |
429 * | |
430 * @param artifact The owner artifact. | |
431 * @param from The lower value of the W range. | |
432 * @param to The upper value of the W range. | |
433 * @param step The step width. | |
434 * | |
435 * @return true, if everything was fine, otherwise an exception is thrown. | |
436 */ | |
437 protected boolean validateW( | |
438 Artifact artifact, | |
439 double from, | |
440 double to, | |
441 double step) | |
442 throws IllegalArgumentException | |
443 { | |
444 logger.debug("WQSelect.validateW"); | |
445 | |
446 double[] minmaxW = determineMinMaxW(artifact); | |
447 | |
448 return validateBounds(minmaxW[0], minmaxW[1], from, to, step); | |
449 } | |
450 | |
451 | |
452 /** | |
453 * Validates the inserted Q values. | |
454 * | |
455 * @param artifact The owner artifact. | |
456 * @param from The lower value of the Q range. | |
457 * @param to The upper value of the Q range. | |
458 * @param step The step width. | |
459 * | |
460 * @return true, if everything was fine, otherwise an exception is thrown. | |
461 */ | |
462 protected boolean validateQ( | |
463 Artifact artifact, | |
464 double from, | |
465 double to, | |
466 double step) | |
467 throws IllegalArgumentException | |
468 { | |
469 logger.debug("WQSelect.validateQ"); | |
470 | |
471 double[] minmaxQ = determineMinMaxQ(artifact); | |
472 | |
473 return validateBounds(minmaxQ[0], minmaxQ[1], from, to, step); | |
474 } | |
475 } | |
476 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : |