Mercurial > dive4elements > river
comparison flys-artifacts/src/main/java/de/intevation/flys/utils/FLYSUtils.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 | 0cf60d64895c |
children | aa9cc91c8193 |
comparison
equal
deleted
inserted
replaced
1491:2a00f4849738 | 3814:8083f6384023 |
---|---|
1 package de.intevation.flys.utils; | |
2 | |
3 import org.apache.log4j.Logger; | |
4 | |
5 import java.text.NumberFormat; | |
6 import java.util.HashMap; | |
7 import java.util.List; | |
8 import java.util.Map; | |
9 import java.util.regex.Matcher; | |
10 import java.util.regex.Pattern; | |
11 | |
12 import javax.xml.xpath.XPathConstants; | |
13 | |
14 import org.w3c.dom.Document; | |
15 | |
16 import org.hibernate.SessionFactory; | |
17 import org.hibernate.impl.SessionFactoryImpl; | |
18 | |
19 import gnu.trove.TDoubleArrayList; | |
20 | |
21 import de.intevation.artifacts.Artifact; | |
22 import de.intevation.artifacts.CallContext; | |
23 | |
24 import de.intevation.artifacts.common.utils.Config; | |
25 import de.intevation.artifacts.common.utils.XMLUtils; | |
26 | |
27 import de.intevation.flys.backend.SessionFactoryProvider; | |
28 | |
29 import de.intevation.flys.artifacts.context.FLYSContext; | |
30 import de.intevation.flys.artifacts.FLYSArtifact; | |
31 import de.intevation.flys.artifacts.WINFOArtifact; | |
32 import de.intevation.flys.artifacts.model.RiverFactory; | |
33 import de.intevation.flys.artifacts.model.LocationProvider; | |
34 import de.intevation.flys.artifacts.model.WQ; | |
35 import de.intevation.flys.model.Gauge; | |
36 import de.intevation.flys.model.MainValue; | |
37 import de.intevation.flys.model.River; | |
38 | |
39 public class FLYSUtils { | |
40 | |
41 /** The logger that is used in this utility. */ | |
42 private static Logger logger = Logger.getLogger(FLYSUtils.class); | |
43 | |
44 public static enum KM_MODE { RANGE, LOCATIONS, NONE }; | |
45 | |
46 /** | |
47 * An enum that represents the 5 possible WQ modes in FLYS. The 5 values are | |
48 * <i>QFREE</i> <i>QGAUGE</i> <i>WGAUGE</i> <i>WFREE</i> and <i>NONE</i>. | |
49 */ | |
50 public static enum WQ_MODE { QFREE, QGAUGE, WFREE, WGAUGE, NONE }; | |
51 | |
52 | |
53 public static final Pattern NUMBERS_PATTERN = | |
54 Pattern.compile("\\D*(\\d++.\\d*)\\D*"); | |
55 | |
56 public static final String XPATH_RIVER_PROJECTION = | |
57 "/artifact-database/floodmap/river[@name=$name]/srid/@value"; | |
58 | |
59 public static final String XPATH_SHAPEFILE_DIR = | |
60 "/artifact-database/floodmap/shapefile-path/@value"; | |
61 | |
62 public static final String XPATH_VELOCITY_LOGFILE = | |
63 "/artifact-database/floodmap/velocity/logfile/@path"; | |
64 | |
65 public static final String XPATH_MAPSERVER_URL = | |
66 "/artifact-database/floodmap/mapserver/server/@path"; | |
67 | |
68 public static final String XPATH_MAPFILE_PATH = | |
69 "/artifact-database/floodmap/mapserver/mapfile/@path"; | |
70 | |
71 public static final String XPATH_MAPFILE_TEMPLATE = | |
72 "/artifact-database/floodmap/mapserver/map-template/@path"; | |
73 | |
74 public static final String XPATH_MAPSERVER_TEMPLATE_PATH = | |
75 "/artifact-database/floodmap/mapserver/templates/@path"; | |
76 | |
77 | |
78 private FLYSUtils() { | |
79 } | |
80 | |
81 | |
82 /** | |
83 * Pulls Artifact with given UUID fromm database. | |
84 * @return FLYSArtifact with given UUID or null (in case of errors). | |
85 */ | |
86 public static FLYSArtifact getArtifact(String uuid, CallContext context) { | |
87 try { | |
88 Artifact artifact = context.getDatabase().getRawArtifact(uuid); | |
89 | |
90 if (artifact == null) { | |
91 logger.error("Artifact '" + uuid + "' does not exist."); | |
92 return null; | |
93 } | |
94 | |
95 if (!(artifact instanceof FLYSArtifact)) { | |
96 logger.error("Artifact '" +uuid+ "' is no valid FLYSArtifact."); | |
97 return null; | |
98 } | |
99 | |
100 return (FLYSArtifact) artifact; | |
101 } | |
102 // TODO: catch more selective | |
103 catch (Exception e) { | |
104 logger.error("Cannot get FLYSArtifact " + uuid | |
105 + " from database (" + e.getMessage() + ")."); | |
106 return null; | |
107 } | |
108 } | |
109 | |
110 | |
111 /** | |
112 * Returns the FLYSContext from context object. | |
113 * | |
114 * @param context The CallContext or the FLYSContext. | |
115 * | |
116 * @return the FLYSContext. | |
117 */ | |
118 public static FLYSContext getFlysContext(Object context) { | |
119 return context instanceof FLYSContext | |
120 ? (FLYSContext) context | |
121 : (FLYSContext) ((CallContext) context).globalContext(); | |
122 } | |
123 | |
124 | |
125 /** | |
126 * Convinience function to retrieve an XPath as string with replaced config | |
127 * directory. | |
128 * | |
129 * @param xpath The XPath expression. | |
130 * | |
131 * @return a string with replaced config directory. | |
132 */ | |
133 public static String getXPathString(String xpath) { | |
134 String tmp = Config.getStringXPath(xpath); | |
135 tmp = Config.replaceConfigDir(tmp); | |
136 | |
137 return tmp; | |
138 } | |
139 | |
140 | |
141 public static boolean isUsingOracle() { | |
142 SessionFactory sf = SessionFactoryProvider.getSessionFactory(); | |
143 | |
144 String d = SessionFactoryProvider.getDriver((SessionFactoryImpl) sf); | |
145 | |
146 return d != null ? d.indexOf("Oracle") >= 0 : false; | |
147 } | |
148 | |
149 | |
150 /** | |
151 * This method returns an WQ_MODE enum which is based on the parameters | |
152 * stored in <i>flys</i> Artifact. If there is no <i>wq_mode</i> parameter | |
153 * existing, WQ_MODE.NONE is returned. | |
154 * | |
155 * @param flys The FLYSArtifact that stores wq mode relevant parameters. | |
156 * | |
157 * @return an enum WQ_MODE. | |
158 */ | |
159 public static WQ_MODE getWQMode(FLYSArtifact flys) { | |
160 String mode = flys.getDataAsString("wq_mode"); | |
161 boolean free = flys.getDataAsBoolean("wq_free"); | |
162 | |
163 if (mode != null && mode.equals("Q")) { | |
164 return free ? WQ_MODE.QFREE : WQ_MODE.QGAUGE; | |
165 } | |
166 else if (mode != null && mode.equals("W")) { | |
167 return free ? WQ_MODE.WFREE : WQ_MODE.WGAUGE; | |
168 } | |
169 else { | |
170 return WQ_MODE.NONE; | |
171 } | |
172 } | |
173 | |
174 | |
175 public static KM_MODE getKmRangeMode(FLYSArtifact flys) { | |
176 String mode = flys.getDataAsString("ld_mode"); | |
177 | |
178 if (mode == null || mode.length() == 0) { | |
179 return KM_MODE.NONE; | |
180 } | |
181 else if (mode.equals("distance")) { | |
182 return KM_MODE.RANGE; | |
183 } | |
184 else if (mode.equals("locations")) { | |
185 return KM_MODE.LOCATIONS; | |
186 } | |
187 else { | |
188 return KM_MODE.NONE; | |
189 } | |
190 } | |
191 | |
192 /** | |
193 * Get min and max kilometer, independent of parametization | |
194 * (ld_from/to vs ld_locations). | |
195 */ | |
196 public static double[] getKmRange(FLYSArtifact flys) { | |
197 switch (getKmRangeMode(flys)) { | |
198 case RANGE: { | |
199 return getKmFromTo(flys); | |
200 } | |
201 | |
202 case LOCATIONS: { | |
203 double[] locs = getLocations(flys); | |
204 return new double[] { locs[0], locs[locs.length-1] }; | |
205 } | |
206 | |
207 case NONE: { | |
208 double[] locs = getLocations(flys); | |
209 if (locs != null) { | |
210 return new double[] { locs[0], locs[locs.length-1] }; | |
211 } | |
212 else { | |
213 return getKmFromTo(flys); | |
214 } | |
215 } | |
216 } | |
217 | |
218 return new double[] { Double.NaN, Double.NaN }; | |
219 } | |
220 | |
221 | |
222 public static double[] getKmFromTo(FLYSArtifact flys) { | |
223 String strFrom = flys.getDataAsString("ld_from"); | |
224 String strTo = flys.getDataAsString("ld_to"); | |
225 | |
226 if (strFrom == null || strTo == null) { | |
227 return null; | |
228 } | |
229 | |
230 try { | |
231 return new double[] { | |
232 Double.parseDouble(strFrom), | |
233 Double.parseDouble(strTo) }; | |
234 } | |
235 catch (NumberFormatException nfe) { | |
236 return null; | |
237 } | |
238 } | |
239 | |
240 | |
241 /** | |
242 * Return sorted array of locations at which stuff was calculated | |
243 * (from ld_locations data), null if not parameterized this way. | |
244 */ | |
245 public static double[] getLocations(FLYSArtifact flys) { | |
246 String locationStr = flys.getDataAsString("ld_locations"); | |
247 | |
248 if (locationStr == null || locationStr.length() == 0) { | |
249 return null; | |
250 } | |
251 | |
252 String[] tmp = locationStr.split(" "); | |
253 TDoubleArrayList locations = new TDoubleArrayList(); | |
254 | |
255 for (String l: tmp) { | |
256 try { | |
257 locations.add(Double.parseDouble(l)); | |
258 } | |
259 catch (NumberFormatException nfe) { | |
260 } | |
261 } | |
262 | |
263 locations.sort(); | |
264 | |
265 return locations.toNativeArray(); | |
266 } | |
267 | |
268 | |
269 /** | |
270 * Returns the Qs for a given FLYSArtifact. This method currently accepts | |
271 * only instances of WINFOArtifact. | |
272 * | |
273 * @param flys A FLYSArtifact. | |
274 * | |
275 * @return the Qs. | |
276 */ | |
277 public static double[] getQs(FLYSArtifact flys) { | |
278 double[] kmRange = getKmRange(flys); | |
279 | |
280 // XXX this is not nice! | |
281 if (flys instanceof WINFOArtifact) { | |
282 return ((WINFOArtifact) flys).getQs(kmRange); | |
283 } | |
284 | |
285 logger.warn("This method currently supports WINFOArtifact only!"); | |
286 | |
287 return null; | |
288 } | |
289 | |
290 | |
291 /** | |
292 * Returns the Ws for a given FLYSArtifact. This method currently accepts | |
293 * only instances of WINFOArtifact. | |
294 * | |
295 * @param flys A FLYSArtifact. | |
296 * | |
297 * @return the Ws. | |
298 */ | |
299 public static double[] getWs(FLYSArtifact flys) { | |
300 double[] kmRange = getKmRange(flys); | |
301 | |
302 // XXX this is not nice! | |
303 if (flys instanceof WINFOArtifact) { | |
304 return ((WINFOArtifact) flys).getWs(kmRange); | |
305 } | |
306 | |
307 logger.warn("This method currently supports WINFOArtifact only!"); | |
308 | |
309 return null; | |
310 } | |
311 | |
312 | |
313 /** | |
314 * Returns the selected River object based on the 'river' data that might | |
315 * have been inserted by the user. | |
316 * | |
317 * @return the selected River or null if no river has been chosen yet. | |
318 */ | |
319 public static River getRiver(FLYSArtifact flys) { | |
320 String sRiver = getRivername(flys); | |
321 | |
322 return (sRiver != null) | |
323 ? RiverFactory.getRiver(sRiver) | |
324 : null; | |
325 } | |
326 | |
327 | |
328 /** | |
329 * Returns the name of the river specified in the given <i>flys</i> | |
330 * Artifact. | |
331 * | |
332 * @param flys The FLYSArtifact that stores a river relevant information. | |
333 * | |
334 * @return the name of the specified river or null. | |
335 */ | |
336 public static String getRivername(FLYSArtifact flys) { | |
337 return flys != null ? flys.getDataAsString("river") : null; | |
338 } | |
339 | |
340 | |
341 /** | |
342 * Extracts the SRID defined in the global configuration for the river | |
343 * specified in <i>artifact</i>. | |
344 * | |
345 * @param artifact The FLYSArtifact that stores the name of the river. | |
346 * | |
347 * @return the SRID as string (e.g. "31466"). | |
348 */ | |
349 public static String getRiverSrid(FLYSArtifact artifact) { | |
350 String river = artifact.getDataAsString("river"); | |
351 | |
352 if (river == null || river.length() == 0) { | |
353 return null; | |
354 } | |
355 | |
356 return getRiverSrid(river); | |
357 } | |
358 | |
359 | |
360 public static String getRiverSrid(String rivername) { | |
361 Map<String, String> variables = new HashMap<String, String>(1); | |
362 variables.put("name", rivername); | |
363 | |
364 Document cfg = Config.getConfig(); | |
365 | |
366 return (String) XMLUtils.xpath( | |
367 cfg, | |
368 XPATH_RIVER_PROJECTION, | |
369 XPathConstants.STRING, | |
370 null, | |
371 variables); | |
372 } | |
373 | |
374 | |
375 public static Gauge getGauge(FLYSArtifact flys) { | |
376 River river = getRiver(flys); | |
377 | |
378 if (river == null) { | |
379 logger.debug("no river found"); | |
380 return null; | |
381 } | |
382 | |
383 double[] dist = getKmRange(flys); | |
384 | |
385 if (dist == null) { | |
386 logger.debug("no range found"); | |
387 return null; | |
388 } | |
389 | |
390 if (logger.isDebugEnabled()) { | |
391 logger.debug("Determine gauge for:"); | |
392 logger.debug("... river: " + river.getName()); | |
393 logger.debug("... distance: " + dist[0] + " - " + dist[1]); | |
394 } | |
395 | |
396 Gauge gauge = river.determineGauge(dist[0], dist[1]); | |
397 | |
398 String name = gauge != null ? gauge.getName() : "'n/a"; | |
399 logger.debug("Found gauge: " + name); | |
400 | |
401 return gauge; | |
402 } | |
403 | |
404 | |
405 public static String getGaugename(FLYSArtifact flys) { | |
406 Gauge gauge = getGauge(flys); | |
407 | |
408 return gauge != null ? gauge.getName() : null; | |
409 } | |
410 | |
411 | |
412 public static Double getValueFromWQ(WQ wq) { | |
413 if (wq == null) { | |
414 return null; | |
415 } | |
416 | |
417 Matcher m = NUMBERS_PATTERN.matcher(wq.getName()); | |
418 | |
419 if (m.matches()) { | |
420 logger.debug("Found a number."); | |
421 | |
422 String raw = m.group(1); | |
423 | |
424 try { | |
425 return Double.valueOf(raw); | |
426 } | |
427 catch (NumberFormatException nfe) { | |
428 } | |
429 } | |
430 | |
431 return null; | |
432 } | |
433 | |
434 | |
435 public static String createWspWTitle( | |
436 WINFOArtifact winfo, | |
437 CallContext cc, | |
438 String name | |
439 ) { | |
440 String[] parts = name.split("="); | |
441 | |
442 NumberFormat nf = Formatter.getWaterlevelW(cc); | |
443 | |
444 String namedMainValue = null; | |
445 | |
446 boolean isQ = winfo.isQ(); | |
447 boolean isFree = winfo.isFreeQ(); | |
448 | |
449 double v; | |
450 | |
451 try { | |
452 v = Double.valueOf(parts[1]); | |
453 | |
454 namedMainValue = getNamedMainValue(winfo.getGauge(), v); | |
455 } | |
456 catch (NumberFormatException nfe) { | |
457 logger.warn("Cannot parse Double of: '" + parts[1] + "'"); | |
458 return name; | |
459 } | |
460 | |
461 String prefix = null; | |
462 | |
463 if (isQ && !isFree && namedMainValue != null) { | |
464 return "W (" + namedMainValue + ")"; | |
465 } | |
466 | |
467 if (isQ) { | |
468 prefix = "Q="; | |
469 } | |
470 | |
471 return prefix == null | |
472 ? "W(" + nf.format(v) + ")" | |
473 : "W(" + prefix + nf.format(v) + ")"; | |
474 } | |
475 | |
476 | |
477 public static String createWspQTitle( | |
478 WINFOArtifact winfo, | |
479 CallContext cc, | |
480 String name | |
481 ) { | |
482 String[] parts = name.split("="); | |
483 | |
484 NumberFormat nf = Formatter.getWaterlevelQ(cc); | |
485 | |
486 String namedMainValue = null; | |
487 | |
488 boolean isQ = winfo.isQ(); | |
489 boolean isFree = winfo.isFreeQ(); | |
490 | |
491 double v; | |
492 | |
493 try { | |
494 v = Double.valueOf(parts[1]); | |
495 | |
496 namedMainValue = getNamedMainValue(winfo.getGauge(), v); | |
497 } | |
498 catch (NumberFormatException nfe) { | |
499 logger.warn("Cannot parse Double of: '" + parts[1] + "'"); | |
500 return name; | |
501 } | |
502 | |
503 String prefix = null; | |
504 | |
505 if (isQ && !isFree && namedMainValue != null) { | |
506 return namedMainValue; | |
507 } | |
508 | |
509 if (!isQ) { | |
510 prefix = "W="; | |
511 } | |
512 | |
513 return prefix == null | |
514 ? "Q(" + nf.format(v) + ")" | |
515 : "Q(" + prefix + nf.format(v) + ")"; | |
516 } | |
517 | |
518 | |
519 /** | |
520 * Returns the named main value if a Q was selected and if this Q fits to a | |
521 * named main value. Otherwise, this function returns null. | |
522 * | |
523 * @param winfo The WINFO Artifact. | |
524 * @param value The Q (or W) value. | |
525 * | |
526 * @return a named main value or null. | |
527 */ | |
528 public static String getNamedMainValue(WINFOArtifact winfo, double value) { | |
529 WQ_MODE wqmode = getWQMode(winfo); | |
530 | |
531 if (wqmode != WQ_MODE.QGAUGE) { | |
532 return null; | |
533 } | |
534 else { | |
535 return getNamedMainValue(winfo.getGauge(), value); | |
536 } | |
537 } | |
538 | |
539 | |
540 public static String getNamedMainValue(Gauge gauge, double value) { | |
541 List<MainValue> mainValues = gauge.getMainValues(); | |
542 logger.debug("Search named main value for: " + value); | |
543 | |
544 for (MainValue mv: mainValues) { | |
545 if (mv.getValue().doubleValue() == value) { | |
546 logger.debug("Found named main value: " + mv.getMainValue().getName()); | |
547 return mv.getMainValue().getName(); | |
548 } | |
549 } | |
550 | |
551 logger.debug("Did not find a named main value for: " + value); | |
552 return null; | |
553 } | |
554 | |
555 | |
556 /** | |
557 * | |
558 * @param nmv A string that represents a named main value. | |
559 * | |
560 * @throws NullPointerException if nmv is null. | |
561 */ | |
562 public static String stripNamedMainValue(String nmv) { | |
563 int startIndex = nmv.indexOf("("); | |
564 int endIndex = nmv.indexOf(")"); | |
565 | |
566 if (startIndex > 0 && endIndex > 0 && startIndex < endIndex) { | |
567 return nmv.substring(0, startIndex); | |
568 } | |
569 | |
570 return nmv; | |
571 } | |
572 | |
573 | |
574 /** | |
575 * Returns the URL of user mapfile for the owner of Artifact | |
576 * <i>artifactId</i>. | |
577 * | |
578 * @param artifactId The UUID of an artifact. | |
579 * | |
580 * @return the URL of the user wms. | |
581 */ | |
582 public static String getUserWMSUrl(String artifactId) { | |
583 String url = getXPathString(XPATH_MAPSERVER_URL); | |
584 url = url + "user-wms"; | |
585 | |
586 return url; | |
587 } | |
588 | |
589 | |
590 /** | |
591 * This method returns the description for a given <i>km</i> for a specific | |
592 * river. The river is provided by the FLYSArtifact <i>flys</i>. | |
593 * | |
594 * @param flys The FLYSArtifact that provides a river. | |
595 * @param km The kilometer. | |
596 * | |
597 * @return the description for <i>km</i> or an empty string if no | |
598 * description was found. | |
599 */ | |
600 public static String getLocationDescription(FLYSArtifact flys, double km) { | |
601 String river = getRivername(flys); | |
602 | |
603 if (river == null) { | |
604 return ""; | |
605 } | |
606 | |
607 return LocationProvider.getLocation(river, km); | |
608 } | |
609 } | |
610 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : |