diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/FunctionResolver.java	Thu Apr 25 12:06:39 2013 +0200
@@ -0,0 +1,325 @@
+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.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import javax.xml.namespace.QName;
+
+import javax.xml.xpath.XPathFunction;
+import javax.xml.xpath.XPathFunctionException;
+import javax.xml.xpath.XPathFunctionResolver;
+
+import org.apache.log4j.Logger;
+
+
+/** Resolves functions (e.g. dc:contains) in Datacage/Meta-Data system. */
+public class FunctionResolver
+implements   XPathFunctionResolver
+{
+    /** Home logger. */
+    private static Logger log = Logger.getLogger(FunctionResolver.class);
+
+    public static final String FUNCTION_NAMESPACE_URI = "dc";
+
+    public static final double FAR_AWAY = 99999d;
+
+    public static final class Entry {
+
+        String        name;
+        XPathFunction function;
+        int           arity;
+
+        public Entry() {
+        }
+
+        public Entry(String name, XPathFunction function, int arity) {
+            this.name     = name;
+            this.function = function;
+            this.arity    = arity;
+        }
+    } // class Entry
+
+    /** List of functions. */
+    protected List<Entry> functions;
+
+    protected Builder.BuildHelper buildHelper;
+
+
+    public FunctionResolver() {
+        this(null);
+    }
+
+    public FunctionResolver(Builder.BuildHelper buildHelper) {
+        this.buildHelper = buildHelper;
+
+        functions = new ArrayList<Entry>();
+
+        addFunction("contains", 2, new XPathFunction() {
+            @Override
+            public Object evaluate(List args) throws XPathFunctionException {
+                return contains(args);
+            }
+        });
+
+        addFunction("fromValue", 3, new XPathFunction() {
+            @Override
+            public Object evaluate(List args) throws XPathFunctionException {
+                return fromValue(args);
+            }
+        });
+
+        addFunction("toValue", 3, new XPathFunction() {
+            @Override
+            public Object evaluate(List args) throws XPathFunctionException {
+                return toValue(args);
+            }
+        });
+
+        addFunction("replace", 3, new XPathFunction() {
+            @Override
+            public Object evaluate(List args) throws XPathFunctionException {
+                return replace(args);
+            }
+        });
+
+        addFunction("has-result", 0, new XPathFunction() {
+            @Override
+            public Object evaluate(List args) throws XPathFunctionException {
+                return FunctionResolver.this.buildHelper.hasResult();
+            }
+        });
+
+        addFunction("date-format", 2, new XPathFunction() {
+            @Override
+            public Object evaluate(List args) throws XPathFunctionException {
+                return dateFormat(args);
+            }
+        });
+    }
+
+    /**
+     * Create a new function.
+     * @param name  Name of the function.
+     * @param arity Number of arguments for function.
+     * @param function the function itself.
+     */
+    public void addFunction(String name, int arity, XPathFunction function) {
+        functions.add(new Entry(name, function, arity));
+    }
+
+    @Override
+    public XPathFunction resolveFunction(QName functionName, int arity) {
+
+        if (!functionName.getNamespaceURI().equals(FUNCTION_NAMESPACE_URI)) {
+            return null;
+        }
+
+        String name = functionName.getLocalPart();
+        for (Entry entry: functions) {
+            if (entry.arity == arity && entry.name.equals(name)) {
+                return entry.function;
+            }
+        }
+
+        return null;
+    }
+
+    /** Implementation of case-ignoring dc:contains. */
+    public Object contains(List args) throws XPathFunctionException {
+        Object haystack = args.get(0);
+        Object needle   = args.get(1);
+
+        if (needle instanceof String && !(haystack instanceof String)) {
+            needle = ((String)needle).toUpperCase();
+        }
+
+        try {
+            if (haystack instanceof Collection) {
+                return Boolean.valueOf(
+                    ((Collection)haystack).contains(needle));
+            }
+
+            if (haystack instanceof Map) {
+                return Boolean.valueOf(
+                    ((Map)haystack).containsKey(needle));
+            }
+
+            if (haystack instanceof Object []) {
+                for (Object straw: (Object [])haystack) {
+                    if (straw.equals(needle)) {
+                        return Boolean.TRUE;
+                    }
+                }
+            }
+
+            if (haystack instanceof String && needle instanceof String) {
+                String h = (String)haystack;
+                String n = (String)needle;
+                return h.contains(n);
+            }
+
+            return Boolean.FALSE;
+        }
+        catch (Exception e) {
+            log.error(e);
+            throw new XPathFunctionException(e);
+        }
+    }
+
+    /** Implementation for getting the minimum value of location or distance
+     *  dc:fromValue.
+     */
+    public Object fromValue(List args) throws XPathFunctionException {
+        Object mode      = args.get(0);
+        Object locations = args.get(1);
+        Object from      = args.get(2);
+
+        if (!(mode instanceof String)){
+            return -FAR_AWAY;
+        }
+
+        if (mode.equals("locations")) {
+            if (!(locations instanceof String)) {
+                return -FAR_AWAY;
+            }
+            String loc = ((String)locations).replace(" ", "");
+            String[] split = loc.split(",");
+            if (split.length < 1) {
+                return -FAR_AWAY;
+            }
+            try {
+                double min = Double.parseDouble(split[0]);
+                for (int i = 1; i < split.length; ++i) {
+                    double v = Double.parseDouble(split[i]);
+                    if (v < min) {
+                        min = v;
+                    }
+                }
+                return min;
+            }
+            catch (NumberFormatException nfe) {
+                return -FAR_AWAY;
+            }
+        }
+        else if (mode.equals("distance")) {
+            if (!(from instanceof String)) {
+                return -FAR_AWAY;
+            }
+            String f = (String)from;
+            try {
+                return Double.parseDouble(f);
+            }
+            catch(NumberFormatException nfe) {
+                return -FAR_AWAY;
+            }
+        }
+        else {
+            return -FAR_AWAY;
+        }
+    }
+
+    /** Implementation for getting the maximum value of location or distance
+     *  dc:toValue.
+     */
+    public Object toValue(List args) throws XPathFunctionException {
+        Object mode      = args.get(0);
+        Object locations = args.get(1);
+        Object to        = args.get(2);
+
+        if (!(mode instanceof String)){
+            return FAR_AWAY;
+        }
+
+        if (mode.equals("locations")) {
+            if (!(locations instanceof String)) {
+                return FAR_AWAY;
+            }
+            try {
+                String loc = ((String)locations).replace(" ", "");
+                String[] split = loc.split(",");
+                if (split.length < 1) {
+                    return FAR_AWAY;
+                }
+                double max = Double.parseDouble(split[0]);
+                for (int i = 1; i < split.length; ++i) {
+                    double v = Double.parseDouble(split[i]);
+                    if (v > max) {
+                        max = v;
+                    }
+                }
+                return max;
+            }
+            catch (NumberFormatException nfe) {
+                return FAR_AWAY;
+            }
+        }
+        else if (mode.equals("distance")) {
+            if (!(to instanceof String)) {
+                return FAR_AWAY;
+            }
+            else {
+                String t = (String)to;
+                try {
+                    return Double.parseDouble(t);
+                }
+                catch(NumberFormatException nfe) {
+                    return FAR_AWAY;
+                }
+            }
+        }
+        else {
+            return FAR_AWAY;
+        }
+    }
+
+    /** Implementation for doing a string replace
+     *  dc:replace
+     */
+    public Object replace(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).replace(
+                    (String)needle, (String)replacement);
+        } else {
+            return haystack;
+        }
+    }
+
+    public Object dateFormat(List args) throws XPathFunctionException {
+        Object pattern = args.get(0);
+        Object date    = args.get(1);
+
+        try {
+            // Oracle does not return a date object but an oracle.sql.TIMESTAMP
+            Method meth = date.getClass().getMethod("dateValue", new Class[] {});
+            date = meth.invoke(date, new Object [] {});
+        } catch (IllegalArgumentException e) {
+        } catch (IllegalAccessException e) {
+        } catch (InvocationTargetException e) {
+        } catch (NoSuchMethodException e) {
+        }
+        if (pattern instanceof String && date instanceof Date) {
+            try {
+                // TODO: Take locale into account.
+                return new SimpleDateFormat((String)pattern).format((Date)date);
+            }
+            catch (IllegalArgumentException iae) {
+                throw new XPathFunctionException(iae);
+            }
+        }
+        return "";
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org