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 :

http://dive4elements.wald.intevation.org