package com.googlecode.totallylazy.xml; import com.googlecode.totallylazy.reflection.Methods; import javax.xml.namespace.QName; import javax.xml.xpath.XPathFunction; import javax.xml.xpath.XPathFunctionResolver; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import static com.googlecode.totallylazy.reflection.Methods.annotation; import static com.googlecode.totallylazy.reflection.Methods.modifier; import static com.googlecode.totallylazy.predicates.Predicates.and; import static com.googlecode.totallylazy.predicates.Predicates.is; import static com.googlecode.totallylazy.predicates.Predicates.notNullValue; import static com.googlecode.totallylazy.Sequences.sequence; import static com.googlecode.totallylazy.predicates.WherePredicate.where; import static com.googlecode.totallylazy.xml.XPathFunction.functions.value; import static java.lang.reflect.Modifier.STATIC; import static java.util.Collections.newSetFromMap; public enum FunctionResolver implements XPathFunctionResolver { resolver(XPathFunctions.class, XPathLookups.class); private final Set<Method> methods = newSetFromMap(new ConcurrentHashMap<Method, Boolean>()); FunctionResolver(Class<?>... defaultXpathFunctions) { for (Class<?> functions : defaultXpathFunctions) { add(functions); } } @Override public XPathFunction resolveFunction(final QName functionName, int arity) { return args -> { String name = functionName.getLocalPart(); Method method = sequence(methods). find(where(annotation(com.googlecode.totallylazy.xml.XPathFunction.class).then(value()), is(name))).get(); try { return Methods.invoke(method, null, args.toArray()); } catch (Exception e) { return Methods.invoke(method, null, args); } }; } public void add(Class<?> aClassWithStaticMethods) { methods.addAll(sequence(aClassWithStaticMethods.getMethods()). filter(and(modifier(Modifier.PUBLIC), modifier(STATIC), where(annotation(com.googlecode.totallylazy.xml.XPathFunction.class), is(notNullValue())))).toList()); } }