teichmann@5863: /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde teichmann@5863: * Software engineering by Intevation GmbH teichmann@5863: * teichmann@5994: * This file is Free Software under the GNU AGPL (>=v3) teichmann@5863: * and comes with ABSOLUTELY NO WARRANTY! Check out the teichmann@5994: * documentation coming with Dive4Elements River for details. teichmann@5863: */ teichmann@5863: teichmann@5831: package org.dive4elements.river.artifacts.datacage.templating; sascha@998: gernotbelger@9299: import java.lang.reflect.InvocationTargetException; gernotbelger@9299: import java.lang.reflect.Method; teichmann@5608: import java.text.SimpleDateFormat; teichmann@7382: import java.util.ArrayList; sascha@998: import java.util.Collection; teichmann@6933: import java.util.Collections; teichmann@5608: import java.util.Date; gernotbelger@9299: import java.util.HashMap; teichmann@4949: import java.util.List; sascha@998: import java.util.Map; teichmann@6933: import java.util.Set; teichmann@7382: import java.util.regex.Matcher; teichmann@7382: import java.util.regex.Pattern; sascha@998: teichmann@4949: import javax.xml.namespace.QName; sascha@998: import javax.xml.xpath.XPathFunction; sascha@998: import javax.xml.xpath.XPathFunctionException; teichmann@4949: import javax.xml.xpath.XPathFunctionResolver; sascha@998: sascha@998: import org.apache.log4j.Logger; teichmann@6933: import org.dive4elements.artifactdatabase.transition.TransitionEngine; teichmann@6933: import org.dive4elements.artifacts.GlobalContext; teichmann@6933: import org.dive4elements.river.artifacts.context.RiverContext; teichmann@6933: import org.dive4elements.river.artifacts.context.RiverContextFactory; sascha@998: felix@4594: /** Resolves functions (e.g. dc:contains) in Datacage/Meta-Data system. */ gernotbelger@9299: public class FunctionResolver implements XPathFunctionResolver { teichmann@8202: /** Home log. */ sascha@998: private static Logger log = Logger.getLogger(FunctionResolver.class); sascha@998: sascha@998: public static final String FUNCTION_NAMESPACE_URI = "dc"; sascha@998: teichmann@5604: public static final double FAR_AWAY = 99999d; teichmann@5604: teichmann@6126: protected static final class Entry { sascha@998: gernotbelger@9299: Entry next; sascha@998: XPathFunction function; gernotbelger@9299: int arity; sascha@998: gernotbelger@9299: public Entry(final Entry next, final XPathFunction function, final int arity) { gernotbelger@9299: this.next = next; teichmann@6126: this.function = function; gernotbelger@9299: this.arity = arity; sascha@998: } sascha@998: gernotbelger@9299: XPathFunction find(final int arity) { teichmann@6126: Entry current = this; teichmann@6126: while (current != null) { teichmann@6126: if (current.arity == arity) { teichmann@6126: return current.function; teichmann@6126: } teichmann@6126: current = current.next; teichmann@6126: } teichmann@6126: return null; sascha@998: } sascha@998: } // class Entry sascha@998: felix@4594: /** List of functions. */ teichmann@6126: protected Map functions; sascha@998: teichmann@5432: protected Builder.BuildHelper buildHelper; teichmann@5430: sascha@998: public FunctionResolver() { teichmann@5432: this(null); teichmann@5432: } teichmann@5432: gernotbelger@9299: public FunctionResolver(final Builder.BuildHelper buildHelper) { teichmann@5432: this.buildHelper = buildHelper; teichmann@5432: gernotbelger@9299: this.functions = new HashMap<>(); teichmann@5430: teichmann@7968: addFunction("coalesce", 2, new XPathFunction() { teichmann@7968: @Override gernotbelger@9299: public Object evaluate(final List args) throws XPathFunctionException { teichmann@7968: return coalesce(args); teichmann@7968: } teichmann@7968: }); teichmann@7968: gernotbelger@9299: addFunction("toString", 1, new XPathFunction() { gernotbelger@9299: @Override gernotbelger@9299: public Object evaluate(final List args) throws XPathFunctionException { gernotbelger@9299: final Object arg = args.get(0); gernotbelger@9299: return arg == null ? null : arg.toString(); gernotbelger@9299: } gernotbelger@9299: }); gernotbelger@9299: teichmann@7967: addFunction("lowercase", 1, new XPathFunction() { teichmann@7967: @Override gernotbelger@9299: public Object evaluate(final List args) throws XPathFunctionException { teichmann@7967: return args.get(0).toString().toLowerCase(); teichmann@7967: } teichmann@7967: }); teichmann@7967: teichmann@7967: addFunction("uppercase", 1, new XPathFunction() { teichmann@7967: @Override gernotbelger@9299: public Object evaluate(final List args) throws XPathFunctionException { teichmann@7967: return args.get(0).toString().toUpperCase(); teichmann@7967: } teichmann@7967: }); teichmann@7967: teichmann@5430: addFunction("contains", 2, new XPathFunction() { teichmann@5430: @Override gernotbelger@9299: public Object evaluate(final List args) throws XPathFunctionException { teichmann@5430: return contains(args); teichmann@5430: } teichmann@5430: }); teichmann@5430: teichmann@5430: addFunction("fromValue", 3, new XPathFunction() { teichmann@5430: @Override gernotbelger@9299: public Object evaluate(final List args) throws XPathFunctionException { teichmann@5430: return fromValue(args); teichmann@5430: } teichmann@5430: }); teichmann@5430: teichmann@5430: addFunction("toValue", 3, new XPathFunction() { teichmann@5430: @Override gernotbelger@9299: public Object evaluate(final List args) throws XPathFunctionException { teichmann@5430: return toValue(args); teichmann@5430: } teichmann@5430: }); teichmann@5433: aheinecke@5561: addFunction("replace", 3, new XPathFunction() { aheinecke@5561: @Override gernotbelger@9299: public Object evaluate(final List args) throws XPathFunctionException { aheinecke@5561: return replace(args); aheinecke@5561: } aheinecke@5561: }); aheinecke@5561: teichmann@6126: addFunction("replace-all", 3, new XPathFunction() { teichmann@6126: @Override gernotbelger@9299: public Object evaluate(final List args) throws XPathFunctionException { teichmann@6126: return replaceAll(args); teichmann@6126: } teichmann@6126: }); teichmann@6126: teichmann@5433: addFunction("has-result", 0, new XPathFunction() { teichmann@5433: @Override gernotbelger@9299: public Object evaluate(final List args) throws XPathFunctionException { teichmann@5433: return FunctionResolver.this.buildHelper.hasResult(); teichmann@5433: } teichmann@5433: }); teichmann@5608: teichmann@5890: addFunction("group-key", 0, new XPathFunction() { teichmann@5890: @Override gernotbelger@9299: public Object evaluate(final List args) throws XPathFunctionException { teichmann@5890: return FunctionResolver.this.buildHelper.getGroupKey(); teichmann@5890: } teichmann@5890: }); teichmann@5890: teichmann@5608: addFunction("date-format", 2, new XPathFunction() { teichmann@5608: @Override gernotbelger@9299: public Object evaluate(final List args) throws XPathFunctionException { teichmann@5608: return dateFormat(args); teichmann@5608: } teichmann@5608: }); teichmann@6080: teichmann@6080: addFunction("dump-variables", 0, new XPathFunction() { teichmann@6080: @Override gernotbelger@9299: public Object evaluate(final List args) throws XPathFunctionException { teichmann@6080: return FunctionResolver.this.buildHelper.frames.dump(); teichmann@6080: } teichmann@6080: }); teichmann@6180: teichmann@6180: addFunction("get", 1, new XPathFunction() { teichmann@6180: @Override gernotbelger@9299: public Object evaluate(final List args) throws XPathFunctionException { gernotbelger@9299: final Object o = args.get(0); teichmann@6180: if (o instanceof String) { gernotbelger@9299: return FunctionResolver.this.buildHelper.frames.getNull((String) o, StackFrames.NULL); teichmann@6180: } teichmann@6180: return StackFrames.NULL; teichmann@6180: } teichmann@6180: }); teichmann@6933: teichmann@6933: addFunction("all-state-successors", 2, new XPathFunction() { teichmann@6933: @Override gernotbelger@9299: public Object evaluate(final List args) throws XPathFunctionException { gernotbelger@9299: final Object artifactName = args.get(0); gernotbelger@9299: final Object stateId = args.get(1); teichmann@6933: gernotbelger@9299: return artifactName instanceof String && stateId instanceof String ? allStateSuccessors((String) artifactName, (String) stateId) gernotbelger@9299: : Collections.emptySet(); teichmann@6933: } teichmann@6933: }); teichmann@7382: teichmann@7382: addFunction("find-all", 2, new XPathFunction() { teichmann@7382: @Override gernotbelger@9299: public Object evaluate(final List args) throws XPathFunctionException { gernotbelger@9299: final Object needle = args.get(0); gernotbelger@9299: final Object haystack = args.get(1); gernotbelger@9299: return haystack instanceof String && needle instanceof String ? findAll((String) needle, (String) haystack) : Collections.emptyList(); teichmann@7382: } teichmann@7382: }); teichmann@7383: teichmann@7383: addFunction("max-number", 1, new XPathFunction() { teichmann@7383: @Override gernotbelger@9299: public Object evaluate(final List args) throws XPathFunctionException { teichmann@7383: return maxNumber(args.get(0)); teichmann@7383: } teichmann@7383: }); teichmann@7383: teichmann@7383: addFunction("min-number", 1, new XPathFunction() { teichmann@7383: @Override gernotbelger@9299: public Object evaluate(final List args) throws XPathFunctionException { teichmann@7383: return minNumber(args.get(0)); teichmann@7383: } teichmann@7383: }); teichmann@7384: gernotbelger@8960: addFunction("column", 1, new XPathFunction() { gernotbelger@8960: @Override gernotbelger@9299: public Object evaluate(final List args) throws XPathFunctionException { gernotbelger@8960: return column(args.get(0)); gernotbelger@8960: } gernotbelger@8960: }); gernotbelger@9232: gernotbelger@9232: addFunction(FixAnalysisYearXPathFunction.ID, FixAnalysisYearXPathFunction.ARITY, new FixAnalysisYearXPathFunction(buildHelper.getContext())); gernotbelger@9299: gernotbelger@9299: addFunction(DefaultVegetationZoneXPathFunction.ID, DefaultVegetationZoneXPathFunction.ARITY, new DefaultVegetationZoneXPathFunction()); gernotbelger@9299: gernotbelger@9299: addFunction(DataFromArtifactXPathFunction.ID, DataFromArtifactXPathFunction.ARITY, new DataFromArtifactXPathFunction(buildHelper.getContext())); sascha@998: } sascha@998: felix@4594: /** felix@4594: * Create a new function. gernotbelger@9299: * gernotbelger@9299: * @param name gernotbelger@9299: * Name of the function. gernotbelger@9299: * @param arity gernotbelger@9299: * Number of arguments for function. gernotbelger@9299: * @param function gernotbelger@9299: * the function itself. felix@4594: */ gernotbelger@9299: public void addFunction(final String name, final int arity, final XPathFunction function) { gernotbelger@9299: Entry entry = this.functions.get(name); teichmann@6126: if (entry == null) { teichmann@6126: entry = new Entry(null, function, arity); gernotbelger@9299: this.functions.put(name, entry); gernotbelger@9299: } else { gernotbelger@9299: final Entry newEntry = new Entry(entry.next, function, arity); teichmann@6126: entry.next = newEntry; teichmann@6126: } sascha@998: } sascha@998: sascha@998: @Override gernotbelger@9299: public XPathFunction resolveFunction(final QName functionName, final int arity) { sascha@998: sascha@998: if (!functionName.getNamespaceURI().equals(FUNCTION_NAMESPACE_URI)) { sascha@998: return null; sascha@998: } sascha@998: gernotbelger@9299: final Entry entry = this.functions.get(functionName.getLocalPart()); gernotbelger@9299: return entry != null ? entry.find(arity) : null; sascha@998: } teichmann@5430: teichmann@5430: /** Implementation of case-ignoring dc:contains. */ gernotbelger@9299: public static Object contains(final List args) throws XPathFunctionException { gernotbelger@9299: final Object haystack = args.get(0); gernotbelger@9299: Object needle = args.get(1); teichmann@5430: teichmann@5630: if (needle instanceof String && !(haystack instanceof String)) { gernotbelger@9299: needle = ((String) needle).toUpperCase(); teichmann@5430: } teichmann@5430: teichmann@5430: try { teichmann@5430: if (haystack instanceof Collection) { gernotbelger@9299: return Boolean.valueOf(((Collection) haystack).contains(needle)); teichmann@5430: } teichmann@5430: teichmann@5430: if (haystack instanceof Map) { gernotbelger@9299: return Boolean.valueOf(((Map) haystack).containsKey(needle)); teichmann@5430: } teichmann@5430: gernotbelger@9299: if (haystack instanceof Object[]) { gernotbelger@9299: for (final Object straw : (Object[]) haystack) { teichmann@5430: if (straw.equals(needle)) { teichmann@5430: return Boolean.TRUE; teichmann@5430: } teichmann@5430: } teichmann@5430: } teichmann@5430: teichmann@5629: if (haystack instanceof String && needle instanceof String) { gernotbelger@9299: final String h = (String) haystack; gernotbelger@9299: final String n = (String) needle; teichmann@5629: return h.contains(n); teichmann@5629: } teichmann@5629: teichmann@5430: return Boolean.FALSE; teichmann@5430: } gernotbelger@9299: catch (final Exception e) { teichmann@5430: log.error(e); teichmann@5430: throw new XPathFunctionException(e); teichmann@5430: } teichmann@5430: } teichmann@5430: gernotbelger@9299: /** gernotbelger@9299: * Implementation for getting the minimum value of location or distance gernotbelger@9299: * dc:fromValue. teichmann@5430: */ gernotbelger@9299: public static Object fromValue(final List args) throws XPathFunctionException { gernotbelger@9299: final Object mode = args.get(0); gernotbelger@9299: final Object locations = args.get(1); gernotbelger@9299: final Object from = args.get(2); teichmann@5430: gernotbelger@9299: if ((mode instanceof String && mode.equals("location")) || (locations instanceof String && !((String) locations).isEmpty())) { teichmann@5430: if (!(locations instanceof String)) { teichmann@5604: return -FAR_AWAY; teichmann@5430: } gernotbelger@9299: final String loc = ((String) locations).replace(" ", ""); gernotbelger@9299: final String[] split = loc.split(","); teichmann@5430: if (split.length < 1) { teichmann@5604: return -FAR_AWAY; teichmann@5430: } teichmann@5430: try { teichmann@5430: double min = Double.parseDouble(split[0]); teichmann@5430: for (int i = 1; i < split.length; ++i) { gernotbelger@9299: final double v = Double.parseDouble(split[i]); teichmann@5430: if (v < min) { teichmann@5430: min = v; teichmann@5430: } teichmann@5430: } teichmann@5430: return min; teichmann@5430: } gernotbelger@9299: catch (final NumberFormatException nfe) { teichmann@5604: return -FAR_AWAY; teichmann@5430: } gernotbelger@9299: } else { teichmann@5430: if (!(from instanceof String)) { teichmann@5604: return -FAR_AWAY; teichmann@5430: } gernotbelger@9299: final String f = (String) from; teichmann@5430: try { teichmann@5430: return Double.parseDouble(f); teichmann@5430: } gernotbelger@9299: catch (final NumberFormatException nfe) { teichmann@5604: return -FAR_AWAY; teichmann@5430: } teichmann@5430: } teichmann@5430: } teichmann@5430: gernotbelger@9299: /** gernotbelger@9299: * Implementation for getting the maximum value of location or distance gernotbelger@9299: * dc:toValue. teichmann@5430: */ gernotbelger@9299: public static Object toValue(final List args) throws XPathFunctionException { gernotbelger@9299: final Object mode = args.get(0); gernotbelger@9299: final Object locations = args.get(1); gernotbelger@9299: final Object to = args.get(2); teichmann@5430: gernotbelger@9299: if ((mode instanceof String && mode.equals("location")) || (locations instanceof String && !((String) locations).isEmpty())) { teichmann@5430: if (!(locations instanceof String)) { teichmann@5604: return FAR_AWAY; teichmann@5430: } teichmann@5430: try { gernotbelger@9299: final String loc = ((String) locations).replace(" ", ""); gernotbelger@9299: final String[] split = loc.split(","); teichmann@5430: if (split.length < 1) { teichmann@5604: return FAR_AWAY; teichmann@5430: } teichmann@5430: double max = Double.parseDouble(split[0]); teichmann@5430: for (int i = 1; i < split.length; ++i) { gernotbelger@9299: final double v = Double.parseDouble(split[i]); teichmann@5430: if (v > max) { teichmann@5430: max = v; teichmann@5430: } teichmann@5430: } teichmann@5430: return max; teichmann@5430: } gernotbelger@9299: catch (final NumberFormatException nfe) { teichmann@5604: return FAR_AWAY; teichmann@5430: } gernotbelger@9299: } else { teichmann@5430: if (!(to instanceof String)) { teichmann@5604: return FAR_AWAY; gernotbelger@9299: } else { gernotbelger@9299: final String t = (String) to; teichmann@5430: try { teichmann@5430: return Double.parseDouble(t); teichmann@5430: } gernotbelger@9299: catch (final NumberFormatException nfe) { teichmann@5604: return FAR_AWAY; teichmann@5430: } teichmann@5430: } teichmann@5430: } teichmann@5430: } aheinecke@5561: gernotbelger@9299: /** gernotbelger@9299: * Implementation for doing a string replace gernotbelger@9299: * dc:replace . aheinecke@5561: */ gernotbelger@9299: public static Object replace(final List args) throws XPathFunctionException { gernotbelger@9299: final Object haystack = args.get(0); gernotbelger@9299: final Object needle = args.get(1); gernotbelger@9299: final Object replacement = args.get(2); aheinecke@5561: gernotbelger@9299: if (needle instanceof String && haystack instanceof String && replacement instanceof String) { gernotbelger@9299: return ((String) haystack).replace((String) needle, (String) replacement); aheinecke@5561: } teichmann@6126: return haystack; teichmann@6126: } teichmann@6126: gernotbelger@9299: /** gernotbelger@9299: * Implementation for doing a string replace gernotbelger@9299: * dc:replace-all teichmann@6126: */ gernotbelger@9299: public static Object replaceAll(final List args) throws XPathFunctionException { gernotbelger@9299: final Object haystack = args.get(0); gernotbelger@9299: final Object needle = args.get(1); gernotbelger@9299: final Object replacement = args.get(2); teichmann@6126: gernotbelger@9299: if (needle instanceof String && haystack instanceof String && replacement instanceof String) { gernotbelger@9299: return ((String) haystack).replaceAll((String) needle, (String) replacement); teichmann@6126: } teichmann@6126: return haystack; aheinecke@5561: } teichmann@5608: gernotbelger@9299: public static Object dateFormat(final List args) throws XPathFunctionException { gernotbelger@9299: final Object pattern = args.get(0); gernotbelger@9299: Object date = args.get(1); aheinecke@5784: aheinecke@5784: try { tom@8460: // TODO: Take locale into account. gernotbelger@9299: final SimpleDateFormat format = new SimpleDateFormat((String) pattern); tom@8460: tom@8460: if (date instanceof Number) { gernotbelger@9299: return format.format(new Date(((Number) date).longValue())); tom@8460: } tom@8460: teichmann@5608: try { gernotbelger@9299: /* gernotbelger@9299: * Oracle does not return a date object but gernotbelger@9299: * an oracle.sql.TIMESTAMP gernotbelger@9299: */ gernotbelger@9299: final Method meth = date.getClass().getMethod("dateValue", new Class[] {}); tom@8460: date = meth.invoke(date, new Object[] {}); gernotbelger@9299: } gernotbelger@9299: catch (final IllegalArgumentException e) { gernotbelger@9299: } gernotbelger@9299: catch (final IllegalAccessException e) { gernotbelger@9299: } gernotbelger@9299: catch (final InvocationTargetException e) { gernotbelger@9299: } gernotbelger@9299: catch (final NoSuchMethodException e) { teichmann@5608: } tom@8460: tom@8460: if (date instanceof Date) { gernotbelger@9299: return format.format((Date) date); teichmann@5608: } teichmann@5608: } gernotbelger@9299: catch (final IllegalArgumentException iae) { tom@8460: log.error(iae.getMessage()); tom@8460: } tom@8460: teichmann@5608: return ""; teichmann@5608: } teichmann@6933: gernotbelger@9299: public static Set allStateSuccessors(final String artifactName, final String stateId) { gernotbelger@9299: final GlobalContext gc = RiverContextFactory.getGlobalContext(); teichmann@6933: if (gc == null) { teichmann@6933: return Collections.emptySet(); teichmann@6933: } gernotbelger@9299: final Object o = gc.get(RiverContext.TRANSITION_ENGINE_KEY); teichmann@6933: if (o instanceof TransitionEngine) { gernotbelger@9299: final TransitionEngine te = (TransitionEngine) o; teichmann@6933: return te.allRecursiveSuccessorStateIds(artifactName, stateId); teichmann@6933: } teichmann@6933: return Collections.emptySet(); teichmann@6933: } teichmann@7382: gernotbelger@9299: public static Collection findAll(final String needle, final String haystack) { teichmann@7382: gernotbelger@9299: final ArrayList result = new ArrayList<>(); teichmann@7382: gernotbelger@9299: final Pattern pattern = Pattern.compile(needle); gernotbelger@9299: final Matcher matcher = pattern.matcher(haystack); teichmann@7382: while (matcher.find()) { teichmann@7382: result.add(matcher.group()); teichmann@7382: } teichmann@7382: return result; teichmann@7382: } teichmann@7383: gernotbelger@9299: public static Number maxNumber(final Object list) { teichmann@7383: if (list instanceof Collection) { gernotbelger@9299: final Collection collection = (Collection) list; teichmann@7383: double max = -Double.MAX_VALUE; gernotbelger@9299: for (final Object x : collection) { teichmann@7383: Number n; teichmann@7383: if (x instanceof Number) { gernotbelger@9299: n = (Number) x; gernotbelger@9299: } else if (x instanceof String) { teichmann@7383: try { gernotbelger@9299: n = Double.valueOf((String) x); teichmann@7383: } gernotbelger@9299: catch (final NumberFormatException nfe) { teichmann@7383: log.warn("'" + x + "' is not a number."); teichmann@7383: continue; teichmann@7383: } gernotbelger@9299: } else { teichmann@7383: log.warn("'" + x + "' is not a number."); teichmann@7383: continue; teichmann@7383: } teichmann@7383: gernotbelger@9299: final double v = n.doubleValue(); teichmann@7383: teichmann@7383: if (v > max) { teichmann@7383: max = v; teichmann@7383: } teichmann@7383: } teichmann@7383: gernotbelger@9299: return Double.valueOf(max == -Double.MAX_VALUE ? Double.MAX_VALUE : max); teichmann@7383: } teichmann@7383: gernotbelger@9299: return list instanceof Number ? (Number) list : Double.valueOf(Double.MAX_VALUE); teichmann@7383: } teichmann@7383: gernotbelger@9299: public static Number minNumber(final Object list) { teichmann@7383: if (list instanceof Collection) { gernotbelger@9299: final Collection collection = (Collection) list; teichmann@7383: double min = Double.MAX_VALUE; gernotbelger@9299: for (final Object x : collection) { teichmann@7383: Number n; teichmann@7383: if (x instanceof Number) { gernotbelger@9299: n = (Number) x; gernotbelger@9299: } else if (x instanceof String) { teichmann@7383: try { gernotbelger@9299: n = Double.valueOf((String) x); teichmann@7383: } gernotbelger@9299: catch (final NumberFormatException nfe) { teichmann@7383: log.warn("'" + x + "' is not a number."); teichmann@7383: continue; teichmann@7383: } gernotbelger@9299: } else { teichmann@7383: log.warn("'" + x + "' is not a number."); teichmann@7383: continue; teichmann@7383: } teichmann@7383: gernotbelger@9299: final double v = n.doubleValue(); teichmann@7383: teichmann@7383: if (v < min) { teichmann@7383: min = v; teichmann@7383: } teichmann@7383: } teichmann@7383: gernotbelger@9299: return Double.valueOf(min == Double.MAX_VALUE ? -Double.MAX_VALUE : min); teichmann@7383: } teichmann@7383: gernotbelger@9299: return list instanceof Number ? (Number) list : Double.valueOf(-Double.MAX_VALUE); teichmann@7383: } teichmann@7968: gernotbelger@9299: public static Object coalesce(final List list) { gernotbelger@9299: for (final Object x : list) { gernotbelger@9299: if (x instanceof String && ((String) x).length() != 0) { teichmann@7968: return x; teichmann@7968: } gernotbelger@9299: if (x instanceof Number && ((Number) x).doubleValue() != 0.0) { teichmann@7968: return x; teichmann@7968: } teichmann@7968: } teichmann@7968: return StackFrames.NULL; teichmann@7968: } gernotbelger@8960: gernotbelger@9299: private Object column(final Object argument) { gernotbelger@9299: gernotbelger@9299: if (!(argument instanceof String)) gernotbelger@8960: throw new IllegalArgumentException("Argument of 'column' function must be a string"); gernotbelger@8960: gernotbelger@9299: final String columnName = (String) argument; gernotbelger@9299: gernotbelger@9299: final StackFrames frms = this.buildHelper.frames; gernotbelger@9299: gernotbelger@8960: return frms.getNull(columnName); gernotbelger@8960: } sascha@998: } sascha@998: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :