comparison flys-artifacts/src/main/java/de/intevation/flys/utils/FLYSUtils.java @ 3818:dc18457b1cef

merged flys-artifacts/pre2.7-2012-03-16
author Thomas Arendsen Hein <thomas@intevation.de>
date Fri, 28 Sep 2012 12:14:59 +0200
parents efb2038783f9
children 3f1cc396d253
comparison
equal deleted inserted replaced
2456:60ab1054069d 3818:dc18457b1cef
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 import gnu.trove.TIntArrayList;
21
22 import de.intevation.artifacts.Artifact;
23 import de.intevation.artifacts.CallContext;
24
25 import de.intevation.artifacts.common.utils.Config;
26 import de.intevation.artifacts.common.utils.XMLUtils;
27
28 import de.intevation.flys.backend.SessionFactoryProvider;
29
30 import de.intevation.flys.artifacts.context.FLYSContext;
31 import de.intevation.flys.artifacts.FLYSArtifact;
32 import de.intevation.flys.artifacts.WINFOArtifact;
33 import de.intevation.flys.artifacts.StaticWKmsArtifact;
34 import de.intevation.flys.artifacts.model.RiverFactory;
35 import de.intevation.flys.artifacts.model.LocationProvider;
36 import de.intevation.flys.artifacts.model.WQ;
37 import de.intevation.flys.artifacts.model.WKms;
38 import de.intevation.flys.artifacts.model.WQKms;
39
40 import de.intevation.artifactdatabase.state.State;
41 import de.intevation.flys.artifacts.states.WaterlevelSelectState;
42 import de.intevation.flys.artifacts.states.WDifferencesState;
43 import de.intevation.flys.model.Gauge;
44 import de.intevation.flys.model.MainValue;
45 import de.intevation.flys.model.River;
46
47 public class FLYSUtils {
48
49 /** The logger that is used in this utility. */
50 private static Logger logger = Logger.getLogger(FLYSUtils.class);
51
52 public static enum KM_MODE { RANGE, LOCATIONS, NONE };
53
54 /**
55 * An enum that represents the 5 possible WQ modes in FLYS. The 5 values are
56 * <i>QFREE</i> <i>QGAUGE</i> <i>WGAUGE</i> <i>WFREE</i> and <i>NONE</i>.
57 */
58 public static enum WQ_MODE { QFREE, QGAUGE, WFREE, WGAUGE, NONE };
59
60 /**
61 * An enum that represents the 4 possible WQ input modes in FLYS. The 4
62 * values are
63 * <i>ADAPTED</i> <i>SINGLE</i> <i>RANGE</i> and <i>NONE</i>.
64 */
65 public static enum WQ_INPUT { ADAPTED, SINGLE, RANGE, NONE };
66
67 public static final Pattern NUMBERS_PATTERN =
68 Pattern.compile("\\D*(\\d++.\\d*)\\D*");
69
70 public static final String XPATH_RIVER_PROJECTION =
71 "/artifact-database/floodmap/river[@name=$name]/srid/@value";
72
73 public static final String XPATH_SHAPEFILE_DIR =
74 "/artifact-database/floodmap/shapefile-path/@value";
75
76 public static final String XPATH_VELOCITY_LOGFILE =
77 "/artifact-database/floodmap/velocity/logfile/@path";
78
79 public static final String XPATH_MAPSERVER_URL =
80 "/artifact-database/floodmap/mapserver/server/@path";
81
82 public static final String XPATH_MAPFILE_PATH =
83 "/artifact-database/floodmap/mapserver/mapfile/@path";
84
85 public static final String XPATH_MAPFILE_TEMPLATE =
86 "/artifact-database/floodmap/mapserver/map-template/@path";
87
88 public static final String XPATH_MAPSERVER_TEMPLATE_PATH =
89 "/artifact-database/floodmap/mapserver/templates/@path";
90
91
92 private FLYSUtils() {
93 }
94
95
96 /**
97 * Pulls Artifact with given UUID fromm database.
98 * @return FLYSArtifact with given UUID or null (in case of errors).
99 */
100 public static FLYSArtifact getArtifact(String uuid, CallContext context) {
101 try {
102 Artifact artifact = context.getDatabase().getRawArtifact(uuid);
103
104 if (artifact == null) {
105 logger.error("Artifact '" + uuid + "' does not exist.");
106 return null;
107 }
108
109 if (!(artifact instanceof FLYSArtifact)) {
110 logger.error("Artifact '" +uuid+ "' is no valid FLYSArtifact.");
111 return null;
112 }
113
114 return (FLYSArtifact) artifact;
115 }
116 // TODO: catch more selective
117 catch (Exception e) {
118 logger.error("Cannot get FLYSArtifact " + uuid
119 + " from database (" + e.getMessage() + ").");
120 return null;
121 }
122 }
123
124
125 /**
126 * Returns the FLYSContext from context object.
127 *
128 * @param context The CallContext or the FLYSContext.
129 *
130 * @return the FLYSContext.
131 */
132 public static FLYSContext getFlysContext(Object context) {
133 return context instanceof FLYSContext
134 ? (FLYSContext) context
135 : (FLYSContext) ((CallContext) context).globalContext();
136 }
137
138
139 /**
140 * Convinience function to retrieve an XPath as string with replaced config
141 * directory.
142 *
143 * @param xpath The XPath expression.
144 *
145 * @return a string with replaced config directory.
146 */
147 public static String getXPathString(String xpath) {
148 String tmp = Config.getStringXPath(xpath);
149 tmp = Config.replaceConfigDir(tmp);
150
151 return tmp;
152 }
153
154
155 public static boolean isUsingOracle() {
156 SessionFactory sf = SessionFactoryProvider.getSessionFactory();
157
158 String d = SessionFactoryProvider.getDriver((SessionFactoryImpl) sf);
159
160 return d != null ? d.indexOf("Oracle") >= 0 : false;
161 }
162
163
164 /**
165 * This method returns an WQ_MODE enum which is based on the parameters
166 * stored in <i>flys</i> Artifact. If there is no <i>wq_isq</i> parameter
167 * existing, WQ_MODE.NONE is returned.
168 *
169 * @param flys The FLYSArtifact that stores wq mode relevant parameters.
170 *
171 * @return an enum WQ_MODE.
172 */
173 public static WQ_MODE getWQMode(FLYSArtifact flys) {
174 if (flys == null) {
175 return WQ_MODE.NONE;
176 }
177
178 String values = flys.getDataAsString("wq_values");
179 Boolean isQ = flys.getDataAsBoolean("wq_isq");
180
181 if (values != null) {
182 return isQ ? WQ_MODE.QGAUGE : WQ_MODE.WGAUGE;
183 }
184
185 Boolean isFree = flys.getDataAsBoolean("wq_isfree");
186
187 if (isQ) {
188 return isFree ? WQ_MODE.QFREE : WQ_MODE.QGAUGE;
189 }
190 else if (!isQ) {
191 return isFree ? WQ_MODE.WFREE : WQ_MODE.WGAUGE;
192 }
193 else {
194 return WQ_MODE.NONE;
195 }
196 }
197
198
199 public static WQ_INPUT getWQInputMode(FLYSArtifact flys) {
200 if (flys == null) {
201 return WQ_INPUT.NONE;
202 }
203
204 Boolean selection = flys.getDataAsBoolean("wq_isrange");
205 String adapted = flys.getDataAsString("wq_values");
206
207 if(adapted != null && adapted.length() > 0) {
208 return WQ_INPUT.ADAPTED;
209 }
210
211 if (selection != null && selection) {
212 return WQ_INPUT.RANGE;
213 }
214 else {
215 return WQ_INPUT.SINGLE;
216 }
217 }
218
219 public static KM_MODE getKmRangeMode(FLYSArtifact flys) {
220 String mode = flys.getDataAsString("ld_mode");
221
222 if (mode == null || mode.length() == 0) {
223 return KM_MODE.NONE;
224 }
225 else if (mode.equals("distance")) {
226 return KM_MODE.RANGE;
227 }
228 else if (mode.equals("locations")) {
229 return KM_MODE.LOCATIONS;
230 }
231 else {
232 return KM_MODE.NONE;
233 }
234 }
235
236 /**
237 * Get min and max kilometer, independent of parametization
238 * (ld_from/to vs ld_locations).
239 */
240 public static double[] getKmRange(FLYSArtifact flys) {
241 switch (getKmRangeMode(flys)) {
242 case RANGE: {
243 return getKmFromTo(flys);
244 }
245
246 case LOCATIONS: {
247 double[] locs = getLocations(flys);
248 return new double[] { locs[0], locs[locs.length-1] };
249 }
250
251 case NONE: {
252 double[] locs = getLocations(flys);
253 if (locs != null) {
254 return new double[] { locs[0], locs[locs.length-1] };
255 }
256 else {
257 return getKmFromTo(flys);
258 }
259 }
260 }
261
262 return new double[] { Double.NaN, Double.NaN };
263 }
264
265
266 /**
267 * Get bounds for river of artifact.
268 * @param flysArtifact artifact which has a "river" data.
269 * @return double array. min is at[0], max at[1]. null if given artifact is null
270 */
271 public static double[] getRiverMinMax(FLYSArtifact flysArtifact) {
272 if (flysArtifact == null) {
273 return null;
274 }
275
276 String riverName = flysArtifact.getDataAsString("river");
277
278 if (riverName == null) {
279 riverName = "";
280 }
281
282 logger.debug("Search for the min/max distances of '" + riverName + "'");
283
284 River river = RiverFactory.getRiver(riverName);
285
286 return river != null
287 ? river.determineMinMaxDistance()
288 : null;
289 }
290
291
292 public static double[] getKmFromTo(FLYSArtifact flys) {
293 String strFrom = flys.getDataAsString("ld_from");
294 String strTo = flys.getDataAsString("ld_to");
295
296 if (strFrom == null || strTo == null) {
297 return null;
298 }
299
300 try {
301 return new double[] {
302 Double.parseDouble(strFrom),
303 Double.parseDouble(strTo) };
304 }
305 catch (NumberFormatException nfe) {
306 return null;
307 }
308 }
309
310
311 /**
312 * Return sorted array of locations at which stuff was calculated
313 * (from ld_locations data), null if not parameterized this way.
314 */
315 public static double[] getLocations(FLYSArtifact flys) {
316 String locationStr = flys.getDataAsString("ld_locations");
317
318 if (locationStr == null || locationStr.length() == 0) {
319 return null;
320 }
321
322 String[] tmp = locationStr.split(" ");
323 TDoubleArrayList locations = new TDoubleArrayList();
324
325 for (String l: tmp) {
326 try {
327 locations.add(Double.parseDouble(l));
328 }
329 catch (NumberFormatException nfe) {
330 }
331 }
332
333 locations.sort();
334
335 return locations.toNativeArray();
336 }
337
338
339 /**
340 * Returns the Qs for a given FLYSArtifact. This method currently accepts
341 * only instances of WINFOArtifact.
342 *
343 * @param flys A FLYSArtifact.
344 *
345 * @return the Qs.
346 */
347 public static double[] getQs(FLYSArtifact flys) {
348 // XXX this is not nice!
349 if (flys instanceof WINFOArtifact) {
350 return ((WINFOArtifact) flys).getQs();
351 }
352
353 logger.warn("This method currently supports WINFOArtifact only!");
354
355 return null;
356 }
357
358
359 /**
360 * Returns the Ws for a given FLYSArtifact. This method currently accepts
361 * only instances of WINFOArtifact.
362 *
363 * @param flys A FLYSArtifact.
364 *
365 * @return the Ws.
366 */
367 public static double[] getWs(FLYSArtifact flys) {
368 // XXX this is not nice!
369 if (flys instanceof WINFOArtifact) {
370 return ((WINFOArtifact) flys).getWs();
371 }
372
373 logger.warn("This method currently supports WINFOArtifact only!");
374
375 return null;
376 }
377
378
379 /**
380 * Returns the selected River object based on the 'river' data that might
381 * have been inserted by the user.
382 *
383 * @return the selected River or null if no river has been chosen yet.
384 */
385 public static River getRiver(FLYSArtifact flys) {
386 String sRiver = getRivername(flys);
387
388 return (sRiver != null)
389 ? RiverFactory.getRiver(sRiver)
390 : null;
391 }
392
393
394 /**
395 * Returns the name of the river specified in the given <i>flys</i>
396 * Artifact.
397 *
398 * @param flys The FLYSArtifact that stores a river relevant information.
399 *
400 * @return the name of the specified river or null.
401 */
402 public static String getRivername(FLYSArtifact flys) {
403 return flys != null ? flys.getDataAsString("river") : null;
404 }
405
406
407 /**
408 * Extracts the SRID defined in the global configuration for the river
409 * specified in <i>artifact</i>.
410 *
411 * @param artifact The FLYSArtifact that stores the name of the river.
412 *
413 * @return the SRID as string (e.g. "31466").
414 */
415 public static String getRiverSrid(FLYSArtifact artifact) {
416 String river = artifact.getDataAsString("river");
417
418 if (river == null || river.length() == 0) {
419 return null;
420 }
421
422 return getRiverSrid(river);
423 }
424
425
426 public static String getRiverSrid(String rivername) {
427 Map<String, String> variables = new HashMap<String, String>(1);
428 variables.put("name", rivername);
429
430 Document cfg = Config.getConfig();
431
432 return (String) XMLUtils.xpath(
433 cfg,
434 XPATH_RIVER_PROJECTION,
435 XPathConstants.STRING,
436 null,
437 variables);
438 }
439
440
441 public static Gauge getGauge(FLYSArtifact flys) {
442 River river = getRiver(flys);
443
444 if (river == null) {
445 logger.debug("no river found");
446 return null;
447 }
448
449 double[] dist = getKmRange(flys);
450
451 if (dist == null) {
452 logger.debug("no range found");
453 return null;
454 }
455
456 if (logger.isDebugEnabled()) {
457 logger.debug("Determine gauge for:");
458 logger.debug("... river: " + river.getName());
459 logger.debug("... distance: " + dist[0] + " - " + dist[1]);
460 }
461
462 Gauge gauge = river.determineGauge(dist[0], dist[1]);
463
464 String name = gauge != null ? gauge.getName() : "'n/a";
465 logger.debug("Found gauge: " + name);
466
467 return gauge;
468 }
469
470
471 public static String getGaugename(FLYSArtifact flys) {
472 Gauge gauge = getGauge(flys);
473
474 return gauge != null ? gauge.getName() : null;
475 }
476
477
478 public static Gauge getReferenceGauge(FLYSArtifact flys) {
479 Long officialNumber = flys.getDataAsLong("reference_gauge");
480
481 return officialNumber != null
482 ? Gauge.getGaugeByOfficialNumber(officialNumber)
483 : null;
484 }
485
486
487 public static String getReferenceGaugeName(FLYSArtifact flys) {
488 Gauge refGauge = getReferenceGauge(flys);
489
490 return refGauge != null
491 ? refGauge.getName()
492 : "-- not found --";
493 }
494
495
496 public static Double getValueFromWQ(WQ wq) {
497 if (wq == null) {
498 return null;
499 }
500
501 Matcher m = NUMBERS_PATTERN.matcher(wq.getName());
502
503 if (m.matches()) {
504 logger.debug("Found a number.");
505
506 String raw = m.group(1);
507
508 try {
509 return Double.valueOf(raw);
510 }
511 catch (NumberFormatException nfe) {
512 }
513 }
514
515 return null;
516 }
517
518
519 public static String createWspWTitle(
520 WINFOArtifact winfo,
521 CallContext cc,
522 String name
523 ) {
524 String[] parts = name.split("=");
525
526 NumberFormat nf = Formatter.getWaterlevelW(cc);
527
528 String namedMainValue = null;
529
530 boolean isQ = winfo.isQ();
531 boolean isFree = winfo.isFreeQ();
532
533 double v;
534
535 try {
536 v = Double.valueOf(parts[1]);
537
538 namedMainValue = getNamedMainValue(winfo.getGauge(), v);
539 }
540 catch (NumberFormatException nfe) {
541 logger.warn("Cannot parse Double of: '" + parts[1] + "'");
542 return name;
543 }
544
545 String prefix = null;
546
547 if (isQ && !isFree && namedMainValue != null) {
548 return "W (" + namedMainValue + ")";
549 }
550
551 if (isQ) {
552 prefix = "Q=";
553 }
554
555 return prefix == null
556 ? "W(" + nf.format(v) + ")"
557 : "W(" + prefix + nf.format(v) + ")";
558 }
559
560
561 public static String createWspQTitle(
562 WINFOArtifact winfo,
563 CallContext cc,
564 String name
565 ) {
566 String[] parts = name.split("=");
567
568 NumberFormat nf = Formatter.getWaterlevelQ(cc);
569
570 String namedMainValue = null;
571
572 boolean isQ = winfo.isQ();
573 boolean isFree = winfo.isFreeQ();
574
575 double v;
576
577 try {
578 v = Double.valueOf(parts[1]);
579
580 namedMainValue = getNamedMainValue(winfo.getGauge(), v);
581 }
582 catch (NumberFormatException nfe) {
583 logger.warn("Cannot parse Double of: '" + parts[1] + "'");
584 return name;
585 }
586
587 String prefix = null;
588
589 if (isQ && !isFree && namedMainValue != null) {
590 return namedMainValue;
591 }
592
593 if (!isQ) {
594 prefix = "W=";
595 }
596
597 return prefix == null
598 ? "Q(" + nf.format(v) + ")"
599 : "Q(" + prefix + nf.format(v) + ")";
600 }
601
602
603 /**
604 * Returns the named main value if a Q was selected and if this Q fits to a
605 * named main value. Otherwise, this function returns null.
606 *
607 * @param winfo The WINFO Artifact.
608 * @param value The Q (or W) value.
609 *
610 * @return a named main value or null.
611 */
612 public static String getNamedMainValue(WINFOArtifact winfo, double value) {
613 WQ_MODE wqmode = getWQMode(winfo);
614
615 if (wqmode != WQ_MODE.QGAUGE) {
616 return null;
617 }
618 else {
619 return getNamedMainValue(winfo.getGauge(), value);
620 }
621 }
622
623
624 public static String getNamedMainValue(Gauge gauge, double value) {
625 List<MainValue> mainValues = gauge.getMainValues();
626 logger.debug("Search named main value for: " + value);
627
628 for (MainValue mv: mainValues) {
629 if (mv.getValue().doubleValue() == value) {
630 logger.debug("Found named main value: " + mv.getMainValue().getName());
631 return mv.getMainValue().getName();
632 }
633 }
634
635 logger.debug("Did not find a named main value for: " + value);
636 return null;
637 }
638
639
640 /**
641 *
642 * @param nmv A string that represents a named main value.
643 *
644 * @throws NullPointerException if nmv is null.
645 */
646 public static String stripNamedMainValue(String nmv) {
647 int startIndex = nmv.indexOf("(");
648 int endIndex = nmv.indexOf(")");
649
650 if (startIndex > 0 && endIndex > 0 && startIndex < endIndex) {
651 return nmv.substring(0, startIndex);
652 }
653
654 return nmv;
655 }
656
657
658 /**
659 * Returns the URL of user mapfile for the owner of Artifact
660 * <i>artifactId</i>.
661 *
662 * @param artifactId The UUID of an artifact.
663 *
664 * @return the URL of the user wms.
665 */
666 public static String getUserWMSUrl(String artifactId) {
667 String url = getXPathString(XPATH_MAPSERVER_URL);
668 url = url.endsWith("/") ? url + "user-wms" : url + "/" + "user-wms";
669
670 return url;
671 }
672
673
674 /**
675 * This method returns the description for a given <i>km</i> for a specific
676 * river. The river is provided by the FLYSArtifact <i>flys</i>.
677 *
678 * @param flys The FLYSArtifact that provides a river.
679 * @param km The kilometer.
680 *
681 * @return the description for <i>km</i> or an empty string if no
682 * description was found.
683 */
684 public static String getLocationDescription(FLYSArtifact flys, double km) {
685 String river = getRivername(flys);
686
687 if (river == null) {
688 return "";
689 }
690
691 return LocationProvider.getLocation(river, km);
692 }
693
694
695 /**
696 * This method returns the differences for a w-differences calculation.
697 *
698 * @param winfo The WINFOArtifact.
699 * @param context The context.
700 *
701 * @return The differences as string separated by semicolon and linebreak.
702 */
703 public static String getWDifferences(
704 WINFOArtifact winfo,
705 CallContext context)
706 {
707 State state = winfo.getCurrentState(context);
708 if(state instanceof WDifferencesState) {
709 String diffids = winfo.getDataAsString("diffids");
710 String datas[] = diffids.split("#");
711
712 // Validate the Data-Strings.
713 for (String s: datas) {
714 if (!WaterlevelSelectState.isValueValid(winfo.getDataAsString("diffids"))) {
715 return "";
716 }
717 }
718
719 if (datas.length < 2) {
720 return "";
721 }
722
723 String diffs = "";
724 for(int i = 0; i < datas.length; i+=2) {
725 // e.g.:
726 // 42537f1e-3522-42ef-8968-635b03d8e9c6;longitudinal_section.w;1
727 WKms minuendWKms = getWKms(StringUtil.unbracket(datas[i+0]),
728 context);
729 WKms subtrahendWKms = getWKms(StringUtil.unbracket(datas[i+1]),
730 context);
731 if (minuendWKms != null && subtrahendWKms != null) {
732 diffs += StringUtil.wWrap(minuendWKms.getName())
733 + " - " + StringUtil.wWrap(subtrahendWKms.getName());
734 }
735 diffs += ";\n";
736 }
737 return diffs;
738 }
739 else {
740 logger.warn("Not a valid state for differences.");
741 return "";
742 }
743 }
744
745
746 protected static WKms getWKms(String mingle, CallContext context) {
747 String[] def = mingle.split(";");
748 String uuid = def[0];
749 String name = def[1];
750 int idx = Integer.parseInt(def[2]);
751
752 if (name.startsWith("staticwkms")) {
753 StaticWKmsArtifact staticWKms =
754 (StaticWKmsArtifact) FLYSUtils.getArtifact(
755 uuid,
756 context);
757 WKms wkms = staticWKms.getWKms(idx);
758 if (wkms == null)
759 logger.error("No WKms from artifact.");
760 return wkms;
761 }
762
763 WINFOArtifact flys = (WINFOArtifact) FLYSUtils.getArtifact(
764 uuid,
765 context);
766
767 if (flys == null) {
768 logger.warn("One of the artifacts (1) for diff calculation could not be loaded");
769 return null;
770 }
771 else{
772 WQKms[] wqkms = (WQKms[]) flys.getWaterlevelData().
773 getData();
774 if (wqkms == null)
775 logger.warn("not waterlevels in artifact");
776 else if (wqkms.length < idx)
777 logger.warn("not enough waterlevels in artifact");
778 return wqkms[idx];
779 }
780 }
781
782
783 /**
784 * This method transform a string into an int array. Therefore, the string
785 * <i>raw</i> must consist of int values separated by a <i>';'</i>.
786 *
787 * @param raw The raw integer array as string separated by a ';'.
788 *
789 * @return an array of int values.
790 */
791 public static int[] intArrayFromString(String raw) {
792 String[] splitted = raw != null ? raw.split(";") : null;
793
794 if (splitted == null || splitted.length == 0) {
795 logger.warn("No integer values found in '" + raw + "'");
796 return new int[0];
797 }
798
799 TIntArrayList integers = new TIntArrayList(splitted.length);
800
801 for (String value: splitted) {
802 try {
803 integers.add(Integer.valueOf(value));
804 }
805 catch (NumberFormatException nfe) {
806 logger.warn("Parsing integer failed: " + nfe);
807 }
808 }
809
810 return integers.toNativeArray();
811 }
812
813
814 /**
815 * This method transform a string into an double array. Therefore, the
816 * string <i>raw</i> must consist of double values separated by a
817 * <i>';'</i>.
818 *
819 * @param raw The raw double array as string separated by a ';'.
820 *
821 * @return an array of double values.
822 */
823 public static double[] doubleArrayFromString(String raw) {
824 String[] splitted = raw != null ? raw.split(";") : null;
825
826 if (splitted == null || splitted.length == 0) {
827 logger.warn("No double values found in '" + raw + "'");
828 return new double[0];
829 }
830
831 TDoubleArrayList doubles = new TDoubleArrayList(splitted.length);
832
833 for (String value: splitted) {
834 try {
835 doubles.add(Double.valueOf(value));
836 }
837 catch (NumberFormatException nfe) {
838 logger.warn("Parsing double failed: " + nfe);
839 }
840 }
841
842 return doubles.toNativeArray();
843 }
844 }
845 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org