changeset 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 243558474334
children 5aefece89e86
files artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/FunctionResolver.java
diffstat 1 files changed, 60 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/FunctionResolver.java	Wed May 29 10:36:40 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/FunctionResolver.java	Thu May 30 06:04:00 2013 +0200
@@ -9,11 +9,11 @@
 package org.dive4elements.river.artifacts.datacage.templating;
 
 import java.text.SimpleDateFormat;
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
+import java.util.HashMap;
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
@@ -38,24 +38,32 @@
 
     public static final double FAR_AWAY = 99999d;
 
-    public static final class Entry {
+    protected static final class Entry {
 
-        String        name;
+        Entry         next;
         XPathFunction function;
         int           arity;
 
-        public Entry() {
+        public Entry(Entry next, XPathFunction function, int arity) {
+            this.next     = next;
+            this.function = function;
+            this.arity    = arity;
         }
 
-        public Entry(String name, XPathFunction function, int arity) {
-            this.name     = name;
-            this.function = function;
-            this.arity    = arity;
+        XPathFunction find(int arity) {
+            Entry current = this;
+            while (current != null) {
+                if (current.arity == arity) {
+                    return current.function;
+                }
+                current = current.next;
+            }
+            return null;
         }
     } // class Entry
 
     /** List of functions. */
-    protected List<Entry> functions;
+    protected Map<String, Entry> functions;
 
     protected Builder.BuildHelper buildHelper;
 
@@ -67,7 +75,7 @@
     public FunctionResolver(Builder.BuildHelper buildHelper) {
         this.buildHelper = buildHelper;
 
-        functions = new ArrayList<Entry>();
+        functions = new HashMap<String, Entry>();
 
         addFunction("contains", 2, new XPathFunction() {
             @Override
@@ -97,6 +105,13 @@
             }
         });
 
+        addFunction("replace-all", 3, new XPathFunction() {
+            @Override
+            public Object evaluate(List args) throws XPathFunctionException {
+                return replaceAll(args);
+            }
+        });
+
         addFunction("has-result", 0, new XPathFunction() {
             @Override
             public Object evaluate(List args) throws XPathFunctionException {
@@ -133,7 +148,15 @@
      * @param function the function itself.
      */
     public void addFunction(String name, int arity, XPathFunction function) {
-        functions.add(new Entry(name, function, arity));
+        Entry entry = functions.get(name);
+        if (entry == null) {
+            entry = new Entry(null, function, arity);
+            functions.put(name, entry);
+        }
+        else {
+            Entry newEntry = new Entry(entry.next, function, arity);
+            entry.next = newEntry;
+        }
     }
 
     @Override
@@ -143,14 +166,10 @@
             return null;
         }
 
-        String name = functionName.getLocalPart();
-        for (Entry entry: functions) {
-            if (entry.arity == arity && entry.name.equals(name)) {
-                return entry.function;
-            }
-        }
-
-        return null;
+        Entry entry = functions.get(functionName.getLocalPart());
+        return entry != null
+            ? entry.find(arity)
+            : null;
     }
 
     /** Implementation of case-ignoring dc:contains. */
@@ -291,7 +310,7 @@
                 try {
                     return Double.parseDouble(t);
                 }
-                catch(NumberFormatException nfe) {
+                catch (NumberFormatException nfe) {
                     return FAR_AWAY;
                 }
             }
@@ -309,14 +328,30 @@
         Object needle      = args.get(1);
         Object replacement = args.get(2);
 
-        if (needle instanceof String &&
-            haystack instanceof String &&
-            replacement instanceof String) {
+        if (needle      instanceof String
+        &&  haystack    instanceof String
+        &&  replacement instanceof String) {
             return ((String)haystack).replace(
                     (String)needle, (String)replacement);
-        } else {
-            return haystack;
         }
+        return haystack;
+    }
+
+    /** Implementation for doing a string replace
+     *  dc:replace-all
+     */
+    public Object replaceAll(List args) throws XPathFunctionException {
+        Object haystack    = args.get(0);
+        Object needle      = args.get(1);
+        Object replacement = args.get(2);
+
+        if (needle      instanceof String
+        &&  haystack    instanceof String
+        &&  replacement instanceof String) {
+            return ((String)haystack).replaceAll(
+                    (String)needle, (String)replacement);
+        }
+        return haystack;
     }
 
     public Object dateFormat(List args) throws XPathFunctionException {

http://dive4elements.wald.intevation.org