1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.jxpath;
18
19 import java.lang.reflect.Constructor;
20 import java.lang.reflect.Method;
21 import java.util.Collections;
22 import java.util.Set;
23
24 import org.apache.commons.jxpath.functions.ConstructorFunction;
25 import org.apache.commons.jxpath.functions.MethodFunction;
26 import org.apache.commons.jxpath.util.MethodLookupUtils;
27
28 /**
29 * Extension functions provided by a Java class.
30 *
31 * Let's say we declared a ClassFunction like this:
32 * <blockquote><pre>
33 * new ClassFunctions(Integer.class, "int")
34 * </pre></blockquote>
35 *
36 * We can now use XPaths like:
37 * <dl>
38 * <dt><code>"int:new(3)"</code></dt>
39 * <dd>Equivalent to <code>new Integer(3)</code></dd>
40 * <dt><code>"int:getInteger('foo')"</code></dt>
41 * <dd>Equivalent to <code>Integer.getInteger("foo")</code></dd>
42 * <dt><code>"int:floatValue(int:new(4))"</code></dt>
43 * <dd>Equivalent to <code>new Integer(4).floatValue()</code></dd>
44 * </dl>
45 *
46 * <p>
47 * If the first argument of a method is {@link ExpressionContext}, the
48 * expression context in which the function is evaluated is passed to
49 * the method.
50 *
51 * @author Dmitri Plotnikov
52 * @version $Revision: 652845 $ $Date: 2008-05-02 19:46:46 +0200 (Fr, 02 Mai 2008) $
53 */
54 public class ClassFunctions implements Functions {
55 private static final Object[] EMPTY_ARRAY = new Object[0];
56
57 private Class functionClass;
58 private String namespace;
59
60 /**
61 * Create a new ClassFunctions.
62 * @param functionClass Class providing the functions
63 * @param namespace assigned ns
64 */
65 public ClassFunctions(Class functionClass, String namespace) {
66 this.functionClass = functionClass;
67 this.namespace = namespace;
68 }
69
70 /**
71 * Returns a set of one namespace - the one specified in the constructor.
72 *
73 * @return a singleton
74 */
75 public Set getUsedNamespaces() {
76 return Collections.singleton(namespace);
77 }
78
79 /**
80 * Returns a {@link Function}, if any, for the specified namespace,
81 * name and parameter types.
82 *
83 * @param namespace if it is not the namespace specified in the constructor,
84 * the method returns null
85 * @param name is a function name or "new" for a constructor.
86 * @param parameters Object[] of parameters
87 *
88 * @return a MethodFunction, a ConstructorFunction or null if there is no
89 * such function.
90 */
91 public Function getFunction(
92 String namespace,
93 String name,
94 Object[] parameters) {
95 if (namespace == null) {
96 if (this.namespace != null) {
97 return null;
98 }
99 }
100 else if (!namespace.equals(this.namespace)) {
101 return null;
102 }
103
104 if (parameters == null) {
105 parameters = EMPTY_ARRAY;
106 }
107
108 if (name.equals("new")) {
109 Constructor constructor =
110 MethodLookupUtils.lookupConstructor(functionClass, parameters);
111 if (constructor != null) {
112 return new ConstructorFunction(constructor);
113 }
114 }
115 else {
116 Method method = MethodLookupUtils.
117 lookupStaticMethod(functionClass, name, parameters);
118 if (method != null) {
119 return new MethodFunction(method);
120 }
121
122 method = MethodLookupUtils.
123 lookupMethod(functionClass, name, parameters);
124 if (method != null) {
125 return new MethodFunction(method);
126 }
127 }
128
129 return null;
130 }
131 }