1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.commons.jxpath;
17
18 import java.lang.reflect.Constructor;
19 import java.lang.reflect.Method;
20 import java.util.Collections;
21 import java.util.Set;
22
23 import org.apache.commons.jxpath.functions.ConstructorFunction;
24 import org.apache.commons.jxpath.functions.MethodFunction;
25 import org.apache.commons.jxpath.util.MethodLookupUtils;
26
27 /***
28 * Extension functions provided by a Java class.
29 *
30 * Let's say, we declared a ClassFunction like this:
31 * <blockquote><pre>
32 * new ClassFunctions(Integer.class, "int")
33 * </pre></blockquote>
34 *
35 * We can now use XPaths like:
36 * <dl>
37 * <dt><code>"int:new(3)"</code></dt>
38 * <dd>Equivalent to <code>new Integer(3)</code></dd>
39 * <dt><code>"int:getInteger('foo')"</code></dt>
40 * <dd>Equivalent to <code>Integer.getInteger("foo")</code></dd>
41 * <dt><code>"int:floatValue(int:new(4))"</code></dt>
42 * <dd>Equivalent to <code>new Integer(4).floatValue()</code></dd>
43 * </dl>
44 *
45 * <p>
46 * If the first argument of a method is ExpressionContext, the
47 * expression context in which the function is evaluated is passed to
48 * the method.
49 *
50 * @author Dmitri Plotnikov
51 * @version $Revision: 1.9 $ $Date: 2004/02/29 14:17:42 $
52 */
53 public class ClassFunctions implements Functions {
54 private Class functionClass;
55 private String namespace;
56 private static final Object[] EMPTY_ARRAY = new Object[0];
57
58 public ClassFunctions(Class functionClass, String namespace) {
59 this.functionClass = functionClass;
60 this.namespace = namespace;
61 }
62
63 /***
64 * Returns a set of one namespace - the one specified in the constructor.
65 *
66 * @returns a singleton
67 */
68 public Set getUsedNamespaces() {
69 return Collections.singleton(namespace);
70 }
71
72 /***
73 * Returns a Function, if any, for the specified namespace,
74 * name and parameter types.
75 *
76 * @param namespace if it is not the namespace specified in the constructor,
77 * the method returns null
78 * @param name is a function name or "new" for a constructor.
79 *
80 * @return a MethodFunction, a ConstructorFunction or null if there is no
81 * such function.
82 */
83 public Function getFunction(
84 String namespace,
85 String name,
86 Object[] parameters)
87 {
88 if (!namespace.equals(this.namespace)) {
89 return null;
90 }
91
92 if (parameters == null) {
93 parameters = EMPTY_ARRAY;
94 }
95
96 if (name.equals("new")) {
97 Constructor constructor =
98 MethodLookupUtils.lookupConstructor(functionClass, parameters);
99 if (constructor != null) {
100 return new ConstructorFunction(constructor);
101 }
102 }
103 else {
104 Method method = MethodLookupUtils.
105 lookupStaticMethod(functionClass, name, parameters);
106 if (method != null) {
107 return new MethodFunction(method);
108 }
109
110 method = MethodLookupUtils.
111 lookupMethod(functionClass, name, parameters);
112 if (method != null) {
113 return new MethodFunction(method);
114 }
115 }
116
117 return null;
118 }
119 }