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 :

http://dive4elements.wald.intevation.org