Mercurial > dive4elements > river
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 :