comparison artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/FunctionResolver.java @ 6126:57fb50f8c9fc

Datacage: Added function dc:replace-all(haystack, needle, replacement) to do regular expression replacements. Mapped to Java's String haystack.replaceAll(needle, replacement).
author Sascha L. Teichmann <teichmann@intevation.de>
date Thu, 30 May 2013 06:04:00 +0200
parents 4bd8bbbcdf68
children 4edad3e414cb
comparison
equal deleted inserted replaced
6125:243558474334 6126:57fb50f8c9fc
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.text.SimpleDateFormat; 11 import java.text.SimpleDateFormat;
12 import java.util.ArrayList;
13 import java.util.Collection; 12 import java.util.Collection;
14 import java.util.Date; 13 import java.util.Date;
15 import java.util.List; 14 import java.util.List;
16 import java.util.Map; 15 import java.util.Map;
16 import java.util.HashMap;
17 17
18 import java.lang.reflect.InvocationTargetException; 18 import java.lang.reflect.InvocationTargetException;
19 import java.lang.reflect.Method; 19 import java.lang.reflect.Method;
20 20
21 import javax.xml.namespace.QName; 21 import javax.xml.namespace.QName;
36 36
37 public static final String FUNCTION_NAMESPACE_URI = "dc"; 37 public static final String FUNCTION_NAMESPACE_URI = "dc";
38 38
39 public static final double FAR_AWAY = 99999d; 39 public static final double FAR_AWAY = 99999d;
40 40
41 public static final class Entry { 41 protected static final class Entry {
42 42
43 String name; 43 Entry next;
44 XPathFunction function; 44 XPathFunction function;
45 int arity; 45 int arity;
46 46
47 public Entry() { 47 public Entry(Entry next, XPathFunction function, int arity) {
48 } 48 this.next = next;
49
50 public Entry(String name, XPathFunction function, int arity) {
51 this.name = name;
52 this.function = function; 49 this.function = function;
53 this.arity = arity; 50 this.arity = arity;
54 } 51 }
52
53 XPathFunction find(int arity) {
54 Entry current = this;
55 while (current != null) {
56 if (current.arity == arity) {
57 return current.function;
58 }
59 current = current.next;
60 }
61 return null;
62 }
55 } // class Entry 63 } // class Entry
56 64
57 /** List of functions. */ 65 /** List of functions. */
58 protected List<Entry> functions; 66 protected Map<String, Entry> functions;
59 67
60 protected Builder.BuildHelper buildHelper; 68 protected Builder.BuildHelper buildHelper;
61 69
62 70
63 public FunctionResolver() { 71 public FunctionResolver() {
65 } 73 }
66 74
67 public FunctionResolver(Builder.BuildHelper buildHelper) { 75 public FunctionResolver(Builder.BuildHelper buildHelper) {
68 this.buildHelper = buildHelper; 76 this.buildHelper = buildHelper;
69 77
70 functions = new ArrayList<Entry>(); 78 functions = new HashMap<String, Entry>();
71 79
72 addFunction("contains", 2, new XPathFunction() { 80 addFunction("contains", 2, new XPathFunction() {
73 @Override 81 @Override
74 public Object evaluate(List args) throws XPathFunctionException { 82 public Object evaluate(List args) throws XPathFunctionException {
75 return contains(args); 83 return contains(args);
92 100
93 addFunction("replace", 3, new XPathFunction() { 101 addFunction("replace", 3, new XPathFunction() {
94 @Override 102 @Override
95 public Object evaluate(List args) throws XPathFunctionException { 103 public Object evaluate(List args) throws XPathFunctionException {
96 return replace(args); 104 return replace(args);
105 }
106 });
107
108 addFunction("replace-all", 3, new XPathFunction() {
109 @Override
110 public Object evaluate(List args) throws XPathFunctionException {
111 return replaceAll(args);
97 } 112 }
98 }); 113 });
99 114
100 addFunction("has-result", 0, new XPathFunction() { 115 addFunction("has-result", 0, new XPathFunction() {
101 @Override 116 @Override
131 * @param name Name of the function. 146 * @param name Name of the function.
132 * @param arity Number of arguments for function. 147 * @param arity Number of arguments for function.
133 * @param function the function itself. 148 * @param function the function itself.
134 */ 149 */
135 public void addFunction(String name, int arity, XPathFunction function) { 150 public void addFunction(String name, int arity, XPathFunction function) {
136 functions.add(new Entry(name, function, arity)); 151 Entry entry = functions.get(name);
152 if (entry == null) {
153 entry = new Entry(null, function, arity);
154 functions.put(name, entry);
155 }
156 else {
157 Entry newEntry = new Entry(entry.next, function, arity);
158 entry.next = newEntry;
159 }
137 } 160 }
138 161
139 @Override 162 @Override
140 public XPathFunction resolveFunction(QName functionName, int arity) { 163 public XPathFunction resolveFunction(QName functionName, int arity) {
141 164
142 if (!functionName.getNamespaceURI().equals(FUNCTION_NAMESPACE_URI)) { 165 if (!functionName.getNamespaceURI().equals(FUNCTION_NAMESPACE_URI)) {
143 return null; 166 return null;
144 } 167 }
145 168
146 String name = functionName.getLocalPart(); 169 Entry entry = functions.get(functionName.getLocalPart());
147 for (Entry entry: functions) { 170 return entry != null
148 if (entry.arity == arity && entry.name.equals(name)) { 171 ? entry.find(arity)
149 return entry.function; 172 : null;
150 }
151 }
152
153 return null;
154 } 173 }
155 174
156 /** Implementation of case-ignoring dc:contains. */ 175 /** Implementation of case-ignoring dc:contains. */
157 public Object contains(List args) throws XPathFunctionException { 176 public Object contains(List args) throws XPathFunctionException {
158 Object haystack = args.get(0); 177 Object haystack = args.get(0);
289 else { 308 else {
290 String t = (String)to; 309 String t = (String)to;
291 try { 310 try {
292 return Double.parseDouble(t); 311 return Double.parseDouble(t);
293 } 312 }
294 catch(NumberFormatException nfe) { 313 catch (NumberFormatException nfe) {
295 return FAR_AWAY; 314 return FAR_AWAY;
296 } 315 }
297 } 316 }
298 } 317 }
299 else { 318 else {
307 public Object replace(List args) throws XPathFunctionException { 326 public Object replace(List args) throws XPathFunctionException {
308 Object haystack = args.get(0); 327 Object haystack = args.get(0);
309 Object needle = args.get(1); 328 Object needle = args.get(1);
310 Object replacement = args.get(2); 329 Object replacement = args.get(2);
311 330
312 if (needle instanceof String && 331 if (needle instanceof String
313 haystack instanceof String && 332 && haystack instanceof String
314 replacement instanceof String) { 333 && replacement instanceof String) {
315 return ((String)haystack).replace( 334 return ((String)haystack).replace(
316 (String)needle, (String)replacement); 335 (String)needle, (String)replacement);
317 } else { 336 }
318 return haystack; 337 return haystack;
319 } 338 }
339
340 /** Implementation for doing a string replace
341 * dc:replace-all
342 */
343 public Object replaceAll(List args) throws XPathFunctionException {
344 Object haystack = args.get(0);
345 Object needle = args.get(1);
346 Object replacement = args.get(2);
347
348 if (needle instanceof String
349 && haystack instanceof String
350 && replacement instanceof String) {
351 return ((String)haystack).replaceAll(
352 (String)needle, (String)replacement);
353 }
354 return haystack;
320 } 355 }
321 356
322 public Object dateFormat(List args) throws XPathFunctionException { 357 public Object dateFormat(List args) throws XPathFunctionException {
323 Object pattern = args.get(0); 358 Object pattern = args.get(0);
324 Object date = args.get(1); 359 Object date = args.get(1);

http://dive4elements.wald.intevation.org