comparison artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/FunctionResolver.java @ 9299:4a6cc7c6716a

uinfo.inundation_duration veg'zone select
author gernotbelger
date Wed, 25 Jul 2018 14:42:44 +0200
parents 5030c46d8cb4
children e511eb935ccd
comparison
equal deleted inserted replaced
9298:0b1a51b0c42e 9299:4a6cc7c6716a
6 * documentation coming with Dive4Elements River for details. 6 * documentation coming with Dive4Elements River for details.
7 */ 7 */
8 8
9 package org.dive4elements.river.artifacts.datacage.templating; 9 package org.dive4elements.river.artifacts.datacage.templating;
10 10
11 import java.lang.reflect.InvocationTargetException;
12 import java.lang.reflect.Method;
11 import java.text.SimpleDateFormat; 13 import java.text.SimpleDateFormat;
12 import java.util.ArrayList; 14 import java.util.ArrayList;
13 import java.util.Collection; 15 import java.util.Collection;
14 import java.util.Collections; 16 import java.util.Collections;
15 import java.util.Date; 17 import java.util.Date;
18 import java.util.HashMap;
16 import java.util.List; 19 import java.util.List;
17 import java.util.Map; 20 import java.util.Map;
18 import java.util.HashMap;
19 import java.util.Set; 21 import java.util.Set;
20 import java.util.regex.Matcher; 22 import java.util.regex.Matcher;
21 import java.util.regex.Pattern; 23 import java.util.regex.Pattern;
22 24
23 import java.lang.reflect.InvocationTargetException;
24 import java.lang.reflect.Method;
25
26 import javax.xml.namespace.QName; 25 import javax.xml.namespace.QName;
27
28 import javax.xml.xpath.XPathFunction; 26 import javax.xml.xpath.XPathFunction;
29 import javax.xml.xpath.XPathFunctionException; 27 import javax.xml.xpath.XPathFunctionException;
30 import javax.xml.xpath.XPathFunctionResolver; 28 import javax.xml.xpath.XPathFunctionResolver;
31 29
32 import org.apache.log4j.Logger; 30 import org.apache.log4j.Logger;
33 import org.dive4elements.artifactdatabase.transition.TransitionEngine; 31 import org.dive4elements.artifactdatabase.transition.TransitionEngine;
34 import org.dive4elements.artifacts.GlobalContext; 32 import org.dive4elements.artifacts.GlobalContext;
35 import org.dive4elements.river.artifacts.context.RiverContext; 33 import org.dive4elements.river.artifacts.context.RiverContext;
36 import org.dive4elements.river.artifacts.context.RiverContextFactory; 34 import org.dive4elements.river.artifacts.context.RiverContextFactory;
37 35
38
39 /** Resolves functions (e.g. dc:contains) in Datacage/Meta-Data system. */ 36 /** Resolves functions (e.g. dc:contains) in Datacage/Meta-Data system. */
40 public class FunctionResolver 37 public class FunctionResolver implements XPathFunctionResolver {
41 implements XPathFunctionResolver
42 {
43 /** Home log. */ 38 /** Home log. */
44 private static Logger log = Logger.getLogger(FunctionResolver.class); 39 private static Logger log = Logger.getLogger(FunctionResolver.class);
45 40
46 public static final String FUNCTION_NAMESPACE_URI = "dc"; 41 public static final String FUNCTION_NAMESPACE_URI = "dc";
47 42
48 public static final double FAR_AWAY = 99999d; 43 public static final double FAR_AWAY = 99999d;
49 44
50 protected static final class Entry { 45 protected static final class Entry {
51 46
52 Entry next; 47 Entry next;
53 XPathFunction function; 48 XPathFunction function;
54 int arity; 49 int arity;
55 50
56 public Entry(Entry next, XPathFunction function, int arity) { 51 public Entry(final Entry next, final XPathFunction function, final int arity) {
57 this.next = next; 52 this.next = next;
58 this.function = function; 53 this.function = function;
59 this.arity = arity; 54 this.arity = arity;
60 } 55 }
61 56
62 XPathFunction find(int arity) { 57 XPathFunction find(final int arity) {
63 Entry current = this; 58 Entry current = this;
64 while (current != null) { 59 while (current != null) {
65 if (current.arity == arity) { 60 if (current.arity == arity) {
66 return current.function; 61 return current.function;
67 } 62 }
74 /** List of functions. */ 69 /** List of functions. */
75 protected Map<String, Entry> functions; 70 protected Map<String, Entry> functions;
76 71
77 protected Builder.BuildHelper buildHelper; 72 protected Builder.BuildHelper buildHelper;
78 73
79
80 public FunctionResolver() { 74 public FunctionResolver() {
81 this(null); 75 this(null);
82 } 76 }
83 77
84 public FunctionResolver(Builder.BuildHelper buildHelper) { 78 public FunctionResolver(final Builder.BuildHelper buildHelper) {
85 this.buildHelper = buildHelper; 79 this.buildHelper = buildHelper;
86 80
87 functions = new HashMap<String, Entry>(); 81 this.functions = new HashMap<>();
88 82
89 addFunction("coalesce", 2, new XPathFunction() { 83 addFunction("coalesce", 2, new XPathFunction() {
90 @Override 84 @Override
91 public Object evaluate(List args) throws XPathFunctionException { 85 public Object evaluate(final List args) throws XPathFunctionException {
92 return coalesce(args); 86 return coalesce(args);
93 } 87 }
94 }); 88 });
95 89
90 addFunction("toString", 1, new XPathFunction() {
91 @Override
92 public Object evaluate(final List args) throws XPathFunctionException {
93 final Object arg = args.get(0);
94 return arg == null ? null : arg.toString();
95 }
96 });
97
96 addFunction("lowercase", 1, new XPathFunction() { 98 addFunction("lowercase", 1, new XPathFunction() {
97 @Override 99 @Override
98 public Object evaluate(List args) throws XPathFunctionException { 100 public Object evaluate(final List args) throws XPathFunctionException {
99 return args.get(0).toString().toLowerCase(); 101 return args.get(0).toString().toLowerCase();
100 } 102 }
101 }); 103 });
102 104
103 addFunction("uppercase", 1, new XPathFunction() { 105 addFunction("uppercase", 1, new XPathFunction() {
104 @Override 106 @Override
105 public Object evaluate(List args) throws XPathFunctionException { 107 public Object evaluate(final List args) throws XPathFunctionException {
106 return args.get(0).toString().toUpperCase(); 108 return args.get(0).toString().toUpperCase();
107 } 109 }
108 }); 110 });
109 111
110 addFunction("contains", 2, new XPathFunction() { 112 addFunction("contains", 2, new XPathFunction() {
111 @Override 113 @Override
112 public Object evaluate(List args) throws XPathFunctionException { 114 public Object evaluate(final List args) throws XPathFunctionException {
113 return contains(args); 115 return contains(args);
114 } 116 }
115 }); 117 });
116 118
117 addFunction("fromValue", 3, new XPathFunction() { 119 addFunction("fromValue", 3, new XPathFunction() {
118 @Override 120 @Override
119 public Object evaluate(List args) throws XPathFunctionException { 121 public Object evaluate(final List args) throws XPathFunctionException {
120 return fromValue(args); 122 return fromValue(args);
121 } 123 }
122 }); 124 });
123 125
124 addFunction("toValue", 3, new XPathFunction() { 126 addFunction("toValue", 3, new XPathFunction() {
125 @Override 127 @Override
126 public Object evaluate(List args) throws XPathFunctionException { 128 public Object evaluate(final List args) throws XPathFunctionException {
127 return toValue(args); 129 return toValue(args);
128 } 130 }
129 }); 131 });
130 132
131 addFunction("replace", 3, new XPathFunction() { 133 addFunction("replace", 3, new XPathFunction() {
132 @Override 134 @Override
133 public Object evaluate(List args) throws XPathFunctionException { 135 public Object evaluate(final List args) throws XPathFunctionException {
134 return replace(args); 136 return replace(args);
135 } 137 }
136 }); 138 });
137 139
138 addFunction("replace-all", 3, new XPathFunction() { 140 addFunction("replace-all", 3, new XPathFunction() {
139 @Override 141 @Override
140 public Object evaluate(List args) throws XPathFunctionException { 142 public Object evaluate(final List args) throws XPathFunctionException {
141 return replaceAll(args); 143 return replaceAll(args);
142 } 144 }
143 }); 145 });
144 146
145 addFunction("has-result", 0, new XPathFunction() { 147 addFunction("has-result", 0, new XPathFunction() {
146 @Override 148 @Override
147 public Object evaluate(List args) throws XPathFunctionException { 149 public Object evaluate(final List args) throws XPathFunctionException {
148 return FunctionResolver.this.buildHelper.hasResult(); 150 return FunctionResolver.this.buildHelper.hasResult();
149 } 151 }
150 }); 152 });
151 153
152 addFunction("group-key", 0, new XPathFunction() { 154 addFunction("group-key", 0, new XPathFunction() {
153 @Override 155 @Override
154 public Object evaluate(List args) throws XPathFunctionException { 156 public Object evaluate(final List args) throws XPathFunctionException {
155 return FunctionResolver.this.buildHelper.getGroupKey(); 157 return FunctionResolver.this.buildHelper.getGroupKey();
156 } 158 }
157 }); 159 });
158 160
159 addFunction("date-format", 2, new XPathFunction() { 161 addFunction("date-format", 2, new XPathFunction() {
160 @Override 162 @Override
161 public Object evaluate(List args) throws XPathFunctionException { 163 public Object evaluate(final List args) throws XPathFunctionException {
162 return dateFormat(args); 164 return dateFormat(args);
163 } 165 }
164 }); 166 });
165 167
166 addFunction("dump-variables", 0, new XPathFunction() { 168 addFunction("dump-variables", 0, new XPathFunction() {
167 @Override 169 @Override
168 public Object evaluate(List args) throws XPathFunctionException { 170 public Object evaluate(final List args) throws XPathFunctionException {
169 return FunctionResolver.this.buildHelper.frames.dump(); 171 return FunctionResolver.this.buildHelper.frames.dump();
170 } 172 }
171 }); 173 });
172 174
173 addFunction("get", 1, new XPathFunction() { 175 addFunction("get", 1, new XPathFunction() {
174 @Override 176 @Override
175 public Object evaluate(List args) throws XPathFunctionException { 177 public Object evaluate(final List args) throws XPathFunctionException {
176 Object o = args.get(0); 178 final Object o = args.get(0);
177 if (o instanceof String) { 179 if (o instanceof String) {
178 return FunctionResolver.this.buildHelper.frames.getNull( 180 return FunctionResolver.this.buildHelper.frames.getNull((String) o, StackFrames.NULL);
179 (String)o, StackFrames.NULL);
180 } 181 }
181 return StackFrames.NULL; 182 return StackFrames.NULL;
182 } 183 }
183 }); 184 });
184 185
185 addFunction("all-state-successors", 2, new XPathFunction() { 186 addFunction("all-state-successors", 2, new XPathFunction() {
186 @Override 187 @Override
187 public Object evaluate(List args) throws XPathFunctionException { 188 public Object evaluate(final List args) throws XPathFunctionException {
188 Object artifactName = args.get(0); 189 final Object artifactName = args.get(0);
189 Object stateId = args.get(1); 190 final Object stateId = args.get(1);
190 191
191 return artifactName instanceof String 192 return artifactName instanceof String && stateId instanceof String ? allStateSuccessors((String) artifactName, (String) stateId)
192 && stateId instanceof String 193 : Collections.<String>emptySet();
193 ? allStateSuccessors((String)artifactName, (String)stateId)
194 : Collections.<String>emptySet();
195 } 194 }
196 }); 195 });
197 196
198 addFunction("find-all", 2, new XPathFunction() { 197 addFunction("find-all", 2, new XPathFunction() {
199 @Override 198 @Override
200 public Object evaluate(List args) throws XPathFunctionException { 199 public Object evaluate(final List args) throws XPathFunctionException {
201 Object needle = args.get(0); 200 final Object needle = args.get(0);
202 Object haystack = args.get(1); 201 final Object haystack = args.get(1);
203 return haystack instanceof String 202 return haystack instanceof String && needle instanceof String ? findAll((String) needle, (String) haystack) : Collections.<String>emptyList();
204 && needle instanceof String
205 ? findAll((String)needle, (String)haystack)
206 : Collections.<String>emptyList();
207 } 203 }
208 }); 204 });
209 205
210 addFunction("max-number", 1, new XPathFunction() { 206 addFunction("max-number", 1, new XPathFunction() {
211 @Override 207 @Override
212 public Object evaluate(List args) throws XPathFunctionException { 208 public Object evaluate(final List args) throws XPathFunctionException {
213 return maxNumber(args.get(0)); 209 return maxNumber(args.get(0));
214 } 210 }
215 }); 211 });
216 212
217 addFunction("min-number", 1, new XPathFunction() { 213 addFunction("min-number", 1, new XPathFunction() {
218 @Override 214 @Override
219 public Object evaluate(List args) throws XPathFunctionException { 215 public Object evaluate(final List args) throws XPathFunctionException {
220 return minNumber(args.get(0)); 216 return minNumber(args.get(0));
221 } 217 }
222 }); 218 });
223 219
224 addFunction("column", 1, new XPathFunction() { 220 addFunction("column", 1, new XPathFunction() {
225 @Override 221 @Override
226 public Object evaluate(List args) throws XPathFunctionException { 222 public Object evaluate(final List args) throws XPathFunctionException {
227 return column(args.get(0)); 223 return column(args.get(0));
228 } 224 }
229 }); 225 });
230 226
231 addFunction(FixAnalysisYearXPathFunction.ID, FixAnalysisYearXPathFunction.ARITY, new FixAnalysisYearXPathFunction(buildHelper.getContext())); 227 addFunction(FixAnalysisYearXPathFunction.ID, FixAnalysisYearXPathFunction.ARITY, new FixAnalysisYearXPathFunction(buildHelper.getContext()));
228
229 addFunction(DefaultVegetationZoneXPathFunction.ID, DefaultVegetationZoneXPathFunction.ARITY, new DefaultVegetationZoneXPathFunction());
230
231 addFunction(DataFromArtifactXPathFunction.ID, DataFromArtifactXPathFunction.ARITY, new DataFromArtifactXPathFunction(buildHelper.getContext()));
232 } 232 }
233 233
234 /** 234 /**
235 * Create a new function. 235 * Create a new function.
236 * @param name Name of the function. 236 *
237 * @param arity Number of arguments for function. 237 * @param name
238 * @param function the function itself. 238 * Name of the function.
239 * @param arity
240 * Number of arguments for function.
241 * @param function
242 * the function itself.
239 */ 243 */
240 public void addFunction(String name, int arity, XPathFunction function) { 244 public void addFunction(final String name, final int arity, final XPathFunction function) {
241 Entry entry = functions.get(name); 245 Entry entry = this.functions.get(name);
242 if (entry == null) { 246 if (entry == null) {
243 entry = new Entry(null, function, arity); 247 entry = new Entry(null, function, arity);
244 functions.put(name, entry); 248 this.functions.put(name, entry);
245 } 249 } else {
246 else { 250 final Entry newEntry = new Entry(entry.next, function, arity);
247 Entry newEntry = new Entry(entry.next, function, arity);
248 entry.next = newEntry; 251 entry.next = newEntry;
249 } 252 }
250 } 253 }
251 254
252 @Override 255 @Override
253 public XPathFunction resolveFunction(QName functionName, int arity) { 256 public XPathFunction resolveFunction(final QName functionName, final int arity) {
254 257
255 if (!functionName.getNamespaceURI().equals(FUNCTION_NAMESPACE_URI)) { 258 if (!functionName.getNamespaceURI().equals(FUNCTION_NAMESPACE_URI)) {
256 return null; 259 return null;
257 } 260 }
258 261
259 Entry entry = functions.get(functionName.getLocalPart()); 262 final Entry entry = this.functions.get(functionName.getLocalPart());
260 return entry != null 263 return entry != null ? entry.find(arity) : null;
261 ? entry.find(arity)
262 : null;
263 } 264 }
264 265
265 /** Implementation of case-ignoring dc:contains. */ 266 /** Implementation of case-ignoring dc:contains. */
266 public static Object contains(List args) throws XPathFunctionException { 267 public static Object contains(final List args) throws XPathFunctionException {
267 Object haystack = args.get(0); 268 final Object haystack = args.get(0);
268 Object needle = args.get(1); 269 Object needle = args.get(1);
269 270
270 if (needle instanceof String && !(haystack instanceof String)) { 271 if (needle instanceof String && !(haystack instanceof String)) {
271 needle = ((String)needle).toUpperCase(); 272 needle = ((String) needle).toUpperCase();
272 } 273 }
273 274
274 try { 275 try {
275 if (haystack instanceof Collection) { 276 if (haystack instanceof Collection) {
276 return Boolean.valueOf( 277 return Boolean.valueOf(((Collection) haystack).contains(needle));
277 ((Collection)haystack).contains(needle));
278 } 278 }
279 279
280 if (haystack instanceof Map) { 280 if (haystack instanceof Map) {
281 return Boolean.valueOf( 281 return Boolean.valueOf(((Map) haystack).containsKey(needle));
282 ((Map)haystack).containsKey(needle)); 282 }
283 } 283
284 284 if (haystack instanceof Object[]) {
285 if (haystack instanceof Object []) { 285 for (final Object straw : (Object[]) haystack) {
286 for (Object straw: (Object [])haystack) {
287 if (straw.equals(needle)) { 286 if (straw.equals(needle)) {
288 return Boolean.TRUE; 287 return Boolean.TRUE;
289 } 288 }
290 } 289 }
291 } 290 }
292 291
293 if (haystack instanceof String && needle instanceof String) { 292 if (haystack instanceof String && needle instanceof String) {
294 String h = (String)haystack; 293 final String h = (String) haystack;
295 String n = (String)needle; 294 final String n = (String) needle;
296 return h.contains(n); 295 return h.contains(n);
297 } 296 }
298 297
299 return Boolean.FALSE; 298 return Boolean.FALSE;
300 } 299 }
301 catch (Exception e) { 300 catch (final Exception e) {
302 log.error(e); 301 log.error(e);
303 throw new XPathFunctionException(e); 302 throw new XPathFunctionException(e);
304 } 303 }
305 } 304 }
306 305
307 /** Implementation for getting the minimum value of location or distance 306 /**
308 * dc:fromValue. 307 * Implementation for getting the minimum value of location or distance
308 * dc:fromValue.
309 */ 309 */
310 public static Object fromValue(List args) throws XPathFunctionException { 310 public static Object fromValue(final List args) throws XPathFunctionException {
311 Object mode = args.get(0); 311 final Object mode = args.get(0);
312 Object locations = args.get(1); 312 final Object locations = args.get(1);
313 Object from = args.get(2); 313 final Object from = args.get(2);
314 314
315 if ((mode instanceof String && mode.equals("location")) || 315 if ((mode instanceof String && mode.equals("location")) || (locations instanceof String && !((String) locations).isEmpty())) {
316 (locations instanceof String && !((String)locations).isEmpty())) {
317 if (!(locations instanceof String)) { 316 if (!(locations instanceof String)) {
318 return -FAR_AWAY; 317 return -FAR_AWAY;
319 } 318 }
320 String loc = ((String)locations).replace(" ", ""); 319 final String loc = ((String) locations).replace(" ", "");
321 String[] split = loc.split(","); 320 final String[] split = loc.split(",");
322 if (split.length < 1) { 321 if (split.length < 1) {
323 return -FAR_AWAY; 322 return -FAR_AWAY;
324 } 323 }
325 try { 324 try {
326 double min = Double.parseDouble(split[0]); 325 double min = Double.parseDouble(split[0]);
327 for (int i = 1; i < split.length; ++i) { 326 for (int i = 1; i < split.length; ++i) {
328 double v = Double.parseDouble(split[i]); 327 final double v = Double.parseDouble(split[i]);
329 if (v < min) { 328 if (v < min) {
330 min = v; 329 min = v;
331 } 330 }
332 } 331 }
333 return min; 332 return min;
334 } 333 }
335 catch (NumberFormatException nfe) { 334 catch (final NumberFormatException nfe) {
336 return -FAR_AWAY; 335 return -FAR_AWAY;
337 } 336 }
338 } 337 } else {
339 else {
340 if (!(from instanceof String)) { 338 if (!(from instanceof String)) {
341 return -FAR_AWAY; 339 return -FAR_AWAY;
342 } 340 }
343 String f = (String)from; 341 final String f = (String) from;
344 try { 342 try {
345 return Double.parseDouble(f); 343 return Double.parseDouble(f);
346 } 344 }
347 catch(NumberFormatException nfe) { 345 catch (final NumberFormatException nfe) {
348 return -FAR_AWAY; 346 return -FAR_AWAY;
349 } 347 }
350 } 348 }
351 } 349 }
352 350
353 /** Implementation for getting the maximum value of location or distance 351 /**
354 * dc:toValue. 352 * Implementation for getting the maximum value of location or distance
353 * dc:toValue.
355 */ 354 */
356 public static Object toValue(List args) throws XPathFunctionException { 355 public static Object toValue(final List args) throws XPathFunctionException {
357 Object mode = args.get(0); 356 final Object mode = args.get(0);
358 Object locations = args.get(1); 357 final Object locations = args.get(1);
359 Object to = args.get(2); 358 final Object to = args.get(2);
360 359
361 if ((mode instanceof String && mode.equals("location")) || 360 if ((mode instanceof String && mode.equals("location")) || (locations instanceof String && !((String) locations).isEmpty())) {
362 (locations instanceof String && !((String)locations).isEmpty())) {
363 if (!(locations instanceof String)) { 361 if (!(locations instanceof String)) {
364 return FAR_AWAY; 362 return FAR_AWAY;
365 } 363 }
366 try { 364 try {
367 String loc = ((String)locations).replace(" ", ""); 365 final String loc = ((String) locations).replace(" ", "");
368 String[] split = loc.split(","); 366 final String[] split = loc.split(",");
369 if (split.length < 1) { 367 if (split.length < 1) {
370 return FAR_AWAY; 368 return FAR_AWAY;
371 } 369 }
372 double max = Double.parseDouble(split[0]); 370 double max = Double.parseDouble(split[0]);
373 for (int i = 1; i < split.length; ++i) { 371 for (int i = 1; i < split.length; ++i) {
374 double v = Double.parseDouble(split[i]); 372 final double v = Double.parseDouble(split[i]);
375 if (v > max) { 373 if (v > max) {
376 max = v; 374 max = v;
377 } 375 }
378 } 376 }
379 return max; 377 return max;
380 } 378 }
381 catch (NumberFormatException nfe) { 379 catch (final NumberFormatException nfe) {
382 return FAR_AWAY; 380 return FAR_AWAY;
383 } 381 }
384 } 382 } else {
385 else {
386 if (!(to instanceof String)) { 383 if (!(to instanceof String)) {
387 return FAR_AWAY; 384 return FAR_AWAY;
388 } 385 } else {
389 else { 386 final String t = (String) to;
390 String t = (String)to;
391 try { 387 try {
392 return Double.parseDouble(t); 388 return Double.parseDouble(t);
393 } 389 }
394 catch (NumberFormatException nfe) { 390 catch (final NumberFormatException nfe) {
395 return FAR_AWAY; 391 return FAR_AWAY;
396 } 392 }
397 } 393 }
398 } 394 }
399 } 395 }
400 396
401 /** Implementation for doing a string replace 397 /**
402 * dc:replace . 398 * Implementation for doing a string replace
399 * dc:replace .
403 */ 400 */
404 public static Object replace(List args) throws XPathFunctionException { 401 public static Object replace(final List args) throws XPathFunctionException {
405 Object haystack = args.get(0); 402 final Object haystack = args.get(0);
406 Object needle = args.get(1); 403 final Object needle = args.get(1);
407 Object replacement = args.get(2); 404 final Object replacement = args.get(2);
408 405
409 if (needle instanceof String 406 if (needle instanceof String && haystack instanceof String && replacement instanceof String) {
410 && haystack instanceof String 407 return ((String) haystack).replace((String) needle, (String) replacement);
411 && replacement instanceof String) {
412 return ((String)haystack).replace(
413 (String)needle, (String)replacement);
414 } 408 }
415 return haystack; 409 return haystack;
416 } 410 }
417 411
418 /** Implementation for doing a string replace 412 /**
419 * dc:replace-all 413 * Implementation for doing a string replace
414 * dc:replace-all
420 */ 415 */
421 public static Object replaceAll(List args) throws XPathFunctionException { 416 public static Object replaceAll(final List args) throws XPathFunctionException {
422 Object haystack = args.get(0); 417 final Object haystack = args.get(0);
423 Object needle = args.get(1); 418 final Object needle = args.get(1);
424 Object replacement = args.get(2); 419 final Object replacement = args.get(2);
425 420
426 if (needle instanceof String 421 if (needle instanceof String && haystack instanceof String && replacement instanceof String) {
427 && haystack instanceof String 422 return ((String) haystack).replaceAll((String) needle, (String) replacement);
428 && replacement instanceof String) {
429 return ((String)haystack).replaceAll(
430 (String)needle, (String)replacement);
431 } 423 }
432 return haystack; 424 return haystack;
433 } 425 }
434 426
435 public static Object dateFormat(List args) throws XPathFunctionException { 427 public static Object dateFormat(final List args) throws XPathFunctionException {
436 Object pattern = args.get(0); 428 final Object pattern = args.get(0);
437 Object date = args.get(1); 429 Object date = args.get(1);
438 430
439 try { 431 try {
440 // TODO: Take locale into account. 432 // TODO: Take locale into account.
441 SimpleDateFormat format = new SimpleDateFormat((String)pattern); 433 final SimpleDateFormat format = new SimpleDateFormat((String) pattern);
442 434
443 if (date instanceof Number) { 435 if (date instanceof Number) {
444 return format.format(new Date(((Number)date).longValue())); 436 return format.format(new Date(((Number) date).longValue()));
445 } 437 }
446 438
447 try { 439 try {
448 /* Oracle does not return a date object but 440 /*
449 an oracle.sql.TIMESTAMP */ 441 * Oracle does not return a date object but
450 Method meth = date.getClass() 442 * an oracle.sql.TIMESTAMP
451 .getMethod("dateValue", new Class[] {}); 443 */
444 final Method meth = date.getClass().getMethod("dateValue", new Class[] {});
452 date = meth.invoke(date, new Object[] {}); 445 date = meth.invoke(date, new Object[] {});
453 } catch (IllegalArgumentException e) { 446 }
454 } catch (IllegalAccessException e) { 447 catch (final IllegalArgumentException e) {
455 } catch (InvocationTargetException e) { 448 }
456 } catch (NoSuchMethodException e) { 449 catch (final IllegalAccessException e) {
450 }
451 catch (final InvocationTargetException e) {
452 }
453 catch (final NoSuchMethodException e) {
457 } 454 }
458 455
459 if (date instanceof Date) { 456 if (date instanceof Date) {
460 return format.format((Date)date); 457 return format.format((Date) date);
461 } 458 }
462 } 459 }
463 catch (IllegalArgumentException iae) { 460 catch (final IllegalArgumentException iae) {
464 log.error(iae.getMessage()); 461 log.error(iae.getMessage());
465 } 462 }
466 463
467 return ""; 464 return "";
468 } 465 }
469 466
470 public static Set<String> allStateSuccessors( 467 public static Set<String> allStateSuccessors(final String artifactName, final String stateId) {
471 String artifactName, 468 final GlobalContext gc = RiverContextFactory.getGlobalContext();
472 String stateId
473 ) {
474 GlobalContext gc = RiverContextFactory.getGlobalContext();
475 if (gc == null) { 469 if (gc == null) {
476 return Collections.<String>emptySet(); 470 return Collections.<String>emptySet();
477 } 471 }
478 Object o = gc.get(RiverContext.TRANSITION_ENGINE_KEY); 472 final Object o = gc.get(RiverContext.TRANSITION_ENGINE_KEY);
479 if (o instanceof TransitionEngine) { 473 if (o instanceof TransitionEngine) {
480 TransitionEngine te = (TransitionEngine)o; 474 final TransitionEngine te = (TransitionEngine) o;
481 return te.allRecursiveSuccessorStateIds(artifactName, stateId); 475 return te.allRecursiveSuccessorStateIds(artifactName, stateId);
482 } 476 }
483 return Collections.<String>emptySet(); 477 return Collections.<String>emptySet();
484 } 478 }
485 479
486 public static Collection<String> findAll(String needle, String haystack) { 480 public static Collection<String> findAll(final String needle, final String haystack) {
487 481
488 ArrayList<String> result = new ArrayList<String>(); 482 final ArrayList<String> result = new ArrayList<>();
489 483
490 Pattern pattern = Pattern.compile(needle); 484 final Pattern pattern = Pattern.compile(needle);
491 Matcher matcher = pattern.matcher(haystack); 485 final Matcher matcher = pattern.matcher(haystack);
492 while (matcher.find()) { 486 while (matcher.find()) {
493 result.add(matcher.group()); 487 result.add(matcher.group());
494 } 488 }
495 return result; 489 return result;
496 } 490 }
497 491
498 public static Number maxNumber(Object list) { 492 public static Number maxNumber(final Object list) {
499 if (list instanceof Collection) { 493 if (list instanceof Collection) {
500 Collection collection = (Collection)list; 494 final Collection collection = (Collection) list;
501 double max = -Double.MAX_VALUE; 495 double max = -Double.MAX_VALUE;
502 for (Object x: collection) { 496 for (final Object x : collection) {
503 Number n; 497 Number n;
504 if (x instanceof Number) { 498 if (x instanceof Number) {
505 n = (Number)x; 499 n = (Number) x;
506 } 500 } else if (x instanceof String) {
507 else if (x instanceof String) {
508 try { 501 try {
509 n = Double.valueOf((String)x); 502 n = Double.valueOf((String) x);
510 } 503 }
511 catch (NumberFormatException nfe) { 504 catch (final NumberFormatException nfe) {
512 log.warn("'" + x + "' is not a number."); 505 log.warn("'" + x + "' is not a number.");
513 continue; 506 continue;
514 } 507 }
515 } 508 } else {
516 else {
517 log.warn("'" + x + "' is not a number."); 509 log.warn("'" + x + "' is not a number.");
518 continue; 510 continue;
519 } 511 }
520 512
521 double v = n.doubleValue(); 513 final double v = n.doubleValue();
522 514
523 if (v > max) { 515 if (v > max) {
524 max = v; 516 max = v;
525 } 517 }
526 } 518 }
527 519
528 return Double.valueOf(max == -Double.MAX_VALUE 520 return Double.valueOf(max == -Double.MAX_VALUE ? Double.MAX_VALUE : max);
529 ? Double.MAX_VALUE 521 }
530 : max); 522
531 } 523 return list instanceof Number ? (Number) list : Double.valueOf(Double.MAX_VALUE);
532 524 }
533 return list instanceof Number 525
534 ? (Number)list 526 public static Number minNumber(final Object list) {
535 : Double.valueOf(Double.MAX_VALUE);
536 }
537
538 public static Number minNumber(Object list) {
539 if (list instanceof Collection) { 527 if (list instanceof Collection) {
540 Collection collection = (Collection)list; 528 final Collection collection = (Collection) list;
541 double min = Double.MAX_VALUE; 529 double min = Double.MAX_VALUE;
542 for (Object x: collection) { 530 for (final Object x : collection) {
543 Number n; 531 Number n;
544 if (x instanceof Number) { 532 if (x instanceof Number) {
545 n = (Number)x; 533 n = (Number) x;
546 } 534 } else if (x instanceof String) {
547 else if (x instanceof String) {
548 try { 535 try {
549 n = Double.valueOf((String)x); 536 n = Double.valueOf((String) x);
550 } 537 }
551 catch (NumberFormatException nfe) { 538 catch (final NumberFormatException nfe) {
552 log.warn("'" + x + "' is not a number."); 539 log.warn("'" + x + "' is not a number.");
553 continue; 540 continue;
554 } 541 }
555 } 542 } else {
556 else {
557 log.warn("'" + x + "' is not a number."); 543 log.warn("'" + x + "' is not a number.");
558 continue; 544 continue;
559 } 545 }
560 546
561 double v = n.doubleValue(); 547 final double v = n.doubleValue();
562 548
563 if (v < min) { 549 if (v < min) {
564 min = v; 550 min = v;
565 } 551 }
566 } 552 }
567 553
568 return Double.valueOf(min == Double.MAX_VALUE 554 return Double.valueOf(min == Double.MAX_VALUE ? -Double.MAX_VALUE : min);
569 ? -Double.MAX_VALUE 555 }
570 : min); 556
571 } 557 return list instanceof Number ? (Number) list : Double.valueOf(-Double.MAX_VALUE);
572 558 }
573 return list instanceof Number 559
574 ? (Number)list 560 public static Object coalesce(final List list) {
575 : Double.valueOf(-Double.MAX_VALUE); 561 for (final Object x : list) {
576 } 562 if (x instanceof String && ((String) x).length() != 0) {
577
578 public static Object coalesce(List list) {
579 for (Object x: list) {
580 if (x instanceof String && ((String)x).length() != 0) {
581 return x; 563 return x;
582 } 564 }
583 if (x instanceof Number && ((Number)x).doubleValue() != 0.0) { 565 if (x instanceof Number && ((Number) x).doubleValue() != 0.0) {
584 return x; 566 return x;
585 } 567 }
586 } 568 }
587 return StackFrames.NULL; 569 return StackFrames.NULL;
588 } 570 }
589 571
590 private Object column(Object argument) { 572 private Object column(final Object argument) {
591 573
592 if( !(argument instanceof String) ) 574 if (!(argument instanceof String))
593 throw new IllegalArgumentException("Argument of 'column' function must be a string"); 575 throw new IllegalArgumentException("Argument of 'column' function must be a string");
594 576
595 String columnName = (String) argument; 577 final String columnName = (String) argument;
596 578
597 StackFrames frms = buildHelper.frames; 579 final StackFrames frms = this.buildHelper.frames;
598 580
599 return frms.getNull(columnName); 581 return frms.getNull(columnName);
600 } 582 }
601 } 583 }
602 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : 584 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org