Mercurial > dive4elements > river
comparison flys-artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/FunctionResolver.java @ 5831:bd047b71ab37
Repaired internal references
author | Sascha L. Teichmann <teichmann@intevation.de> |
---|---|
date | Thu, 25 Apr 2013 12:06:39 +0200 |
parents | flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/templating/FunctionResolver.java@efbbfe32e9fe |
children |
comparison
equal
deleted
inserted
replaced
5830:160f53ee0870 | 5831:bd047b71ab37 |
---|---|
1 package org.dive4elements.river.artifacts.datacage.templating; | |
2 | |
3 import java.text.SimpleDateFormat; | |
4 import java.util.ArrayList; | |
5 import java.util.Collection; | |
6 import java.util.Date; | |
7 import java.util.List; | |
8 import java.util.Map; | |
9 | |
10 import java.lang.reflect.InvocationTargetException; | |
11 import java.lang.reflect.Method; | |
12 | |
13 import javax.xml.namespace.QName; | |
14 | |
15 import javax.xml.xpath.XPathFunction; | |
16 import javax.xml.xpath.XPathFunctionException; | |
17 import javax.xml.xpath.XPathFunctionResolver; | |
18 | |
19 import org.apache.log4j.Logger; | |
20 | |
21 | |
22 /** Resolves functions (e.g. dc:contains) in Datacage/Meta-Data system. */ | |
23 public class FunctionResolver | |
24 implements XPathFunctionResolver | |
25 { | |
26 /** Home logger. */ | |
27 private static Logger log = Logger.getLogger(FunctionResolver.class); | |
28 | |
29 public static final String FUNCTION_NAMESPACE_URI = "dc"; | |
30 | |
31 public static final double FAR_AWAY = 99999d; | |
32 | |
33 public static final class Entry { | |
34 | |
35 String name; | |
36 XPathFunction function; | |
37 int arity; | |
38 | |
39 public Entry() { | |
40 } | |
41 | |
42 public Entry(String name, XPathFunction function, int arity) { | |
43 this.name = name; | |
44 this.function = function; | |
45 this.arity = arity; | |
46 } | |
47 } // class Entry | |
48 | |
49 /** List of functions. */ | |
50 protected List<Entry> functions; | |
51 | |
52 protected Builder.BuildHelper buildHelper; | |
53 | |
54 | |
55 public FunctionResolver() { | |
56 this(null); | |
57 } | |
58 | |
59 public FunctionResolver(Builder.BuildHelper buildHelper) { | |
60 this.buildHelper = buildHelper; | |
61 | |
62 functions = new ArrayList<Entry>(); | |
63 | |
64 addFunction("contains", 2, new XPathFunction() { | |
65 @Override | |
66 public Object evaluate(List args) throws XPathFunctionException { | |
67 return contains(args); | |
68 } | |
69 }); | |
70 | |
71 addFunction("fromValue", 3, new XPathFunction() { | |
72 @Override | |
73 public Object evaluate(List args) throws XPathFunctionException { | |
74 return fromValue(args); | |
75 } | |
76 }); | |
77 | |
78 addFunction("toValue", 3, new XPathFunction() { | |
79 @Override | |
80 public Object evaluate(List args) throws XPathFunctionException { | |
81 return toValue(args); | |
82 } | |
83 }); | |
84 | |
85 addFunction("replace", 3, new XPathFunction() { | |
86 @Override | |
87 public Object evaluate(List args) throws XPathFunctionException { | |
88 return replace(args); | |
89 } | |
90 }); | |
91 | |
92 addFunction("has-result", 0, new XPathFunction() { | |
93 @Override | |
94 public Object evaluate(List args) throws XPathFunctionException { | |
95 return FunctionResolver.this.buildHelper.hasResult(); | |
96 } | |
97 }); | |
98 | |
99 addFunction("date-format", 2, new XPathFunction() { | |
100 @Override | |
101 public Object evaluate(List args) throws XPathFunctionException { | |
102 return dateFormat(args); | |
103 } | |
104 }); | |
105 } | |
106 | |
107 /** | |
108 * Create a new function. | |
109 * @param name Name of the function. | |
110 * @param arity Number of arguments for function. | |
111 * @param function the function itself. | |
112 */ | |
113 public void addFunction(String name, int arity, XPathFunction function) { | |
114 functions.add(new Entry(name, function, arity)); | |
115 } | |
116 | |
117 @Override | |
118 public XPathFunction resolveFunction(QName functionName, int arity) { | |
119 | |
120 if (!functionName.getNamespaceURI().equals(FUNCTION_NAMESPACE_URI)) { | |
121 return null; | |
122 } | |
123 | |
124 String name = functionName.getLocalPart(); | |
125 for (Entry entry: functions) { | |
126 if (entry.arity == arity && entry.name.equals(name)) { | |
127 return entry.function; | |
128 } | |
129 } | |
130 | |
131 return null; | |
132 } | |
133 | |
134 /** Implementation of case-ignoring dc:contains. */ | |
135 public Object contains(List args) throws XPathFunctionException { | |
136 Object haystack = args.get(0); | |
137 Object needle = args.get(1); | |
138 | |
139 if (needle instanceof String && !(haystack instanceof String)) { | |
140 needle = ((String)needle).toUpperCase(); | |
141 } | |
142 | |
143 try { | |
144 if (haystack instanceof Collection) { | |
145 return Boolean.valueOf( | |
146 ((Collection)haystack).contains(needle)); | |
147 } | |
148 | |
149 if (haystack instanceof Map) { | |
150 return Boolean.valueOf( | |
151 ((Map)haystack).containsKey(needle)); | |
152 } | |
153 | |
154 if (haystack instanceof Object []) { | |
155 for (Object straw: (Object [])haystack) { | |
156 if (straw.equals(needle)) { | |
157 return Boolean.TRUE; | |
158 } | |
159 } | |
160 } | |
161 | |
162 if (haystack instanceof String && needle instanceof String) { | |
163 String h = (String)haystack; | |
164 String n = (String)needle; | |
165 return h.contains(n); | |
166 } | |
167 | |
168 return Boolean.FALSE; | |
169 } | |
170 catch (Exception e) { | |
171 log.error(e); | |
172 throw new XPathFunctionException(e); | |
173 } | |
174 } | |
175 | |
176 /** Implementation for getting the minimum value of location or distance | |
177 * dc:fromValue. | |
178 */ | |
179 public Object fromValue(List args) throws XPathFunctionException { | |
180 Object mode = args.get(0); | |
181 Object locations = args.get(1); | |
182 Object from = args.get(2); | |
183 | |
184 if (!(mode instanceof String)){ | |
185 return -FAR_AWAY; | |
186 } | |
187 | |
188 if (mode.equals("locations")) { | |
189 if (!(locations instanceof String)) { | |
190 return -FAR_AWAY; | |
191 } | |
192 String loc = ((String)locations).replace(" ", ""); | |
193 String[] split = loc.split(","); | |
194 if (split.length < 1) { | |
195 return -FAR_AWAY; | |
196 } | |
197 try { | |
198 double min = Double.parseDouble(split[0]); | |
199 for (int i = 1; i < split.length; ++i) { | |
200 double v = Double.parseDouble(split[i]); | |
201 if (v < min) { | |
202 min = v; | |
203 } | |
204 } | |
205 return min; | |
206 } | |
207 catch (NumberFormatException nfe) { | |
208 return -FAR_AWAY; | |
209 } | |
210 } | |
211 else if (mode.equals("distance")) { | |
212 if (!(from instanceof String)) { | |
213 return -FAR_AWAY; | |
214 } | |
215 String f = (String)from; | |
216 try { | |
217 return Double.parseDouble(f); | |
218 } | |
219 catch(NumberFormatException nfe) { | |
220 return -FAR_AWAY; | |
221 } | |
222 } | |
223 else { | |
224 return -FAR_AWAY; | |
225 } | |
226 } | |
227 | |
228 /** Implementation for getting the maximum value of location or distance | |
229 * dc:toValue. | |
230 */ | |
231 public Object toValue(List args) throws XPathFunctionException { | |
232 Object mode = args.get(0); | |
233 Object locations = args.get(1); | |
234 Object to = args.get(2); | |
235 | |
236 if (!(mode instanceof String)){ | |
237 return FAR_AWAY; | |
238 } | |
239 | |
240 if (mode.equals("locations")) { | |
241 if (!(locations instanceof String)) { | |
242 return FAR_AWAY; | |
243 } | |
244 try { | |
245 String loc = ((String)locations).replace(" ", ""); | |
246 String[] split = loc.split(","); | |
247 if (split.length < 1) { | |
248 return FAR_AWAY; | |
249 } | |
250 double max = Double.parseDouble(split[0]); | |
251 for (int i = 1; i < split.length; ++i) { | |
252 double v = Double.parseDouble(split[i]); | |
253 if (v > max) { | |
254 max = v; | |
255 } | |
256 } | |
257 return max; | |
258 } | |
259 catch (NumberFormatException nfe) { | |
260 return FAR_AWAY; | |
261 } | |
262 } | |
263 else if (mode.equals("distance")) { | |
264 if (!(to instanceof String)) { | |
265 return FAR_AWAY; | |
266 } | |
267 else { | |
268 String t = (String)to; | |
269 try { | |
270 return Double.parseDouble(t); | |
271 } | |
272 catch(NumberFormatException nfe) { | |
273 return FAR_AWAY; | |
274 } | |
275 } | |
276 } | |
277 else { | |
278 return FAR_AWAY; | |
279 } | |
280 } | |
281 | |
282 /** Implementation for doing a string replace | |
283 * dc:replace | |
284 */ | |
285 public Object replace(List args) throws XPathFunctionException { | |
286 Object haystack = args.get(0); | |
287 Object needle = args.get(1); | |
288 Object replacement = args.get(2); | |
289 | |
290 if (needle instanceof String && | |
291 haystack instanceof String && | |
292 replacement instanceof String) { | |
293 return ((String)haystack).replace( | |
294 (String)needle, (String)replacement); | |
295 } else { | |
296 return haystack; | |
297 } | |
298 } | |
299 | |
300 public Object dateFormat(List args) throws XPathFunctionException { | |
301 Object pattern = args.get(0); | |
302 Object date = args.get(1); | |
303 | |
304 try { | |
305 // Oracle does not return a date object but an oracle.sql.TIMESTAMP | |
306 Method meth = date.getClass().getMethod("dateValue", new Class[] {}); | |
307 date = meth.invoke(date, new Object [] {}); | |
308 } catch (IllegalArgumentException e) { | |
309 } catch (IllegalAccessException e) { | |
310 } catch (InvocationTargetException e) { | |
311 } catch (NoSuchMethodException e) { | |
312 } | |
313 if (pattern instanceof String && date instanceof Date) { | |
314 try { | |
315 // TODO: Take locale into account. | |
316 return new SimpleDateFormat((String)pattern).format((Date)date); | |
317 } | |
318 catch (IllegalArgumentException iae) { | |
319 throw new XPathFunctionException(iae); | |
320 } | |
321 } | |
322 return ""; | |
323 } | |
324 } | |
325 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : |