001: /*
002: * Copyright 1999-2004 The Apache Software Foundation
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.apache.commons.jxpath;
017:
018: import java.lang.reflect.Constructor;
019: import java.lang.reflect.Method;
020: import java.util.Collections;
021: import java.util.Set;
022:
023: import org.apache.commons.jxpath.functions.ConstructorFunction;
024: import org.apache.commons.jxpath.functions.MethodFunction;
025: import org.apache.commons.jxpath.util.MethodLookupUtils;
026:
027: /**
028: * Extension functions provided by a Java class.
029: *
030: * Let's say, we declared a ClassFunction like this:
031: * <blockquote><pre>
032: * new ClassFunctions(Integer.class, "int")
033: * </pre></blockquote>
034: *
035: * We can now use XPaths like:
036: * <dl>
037: * <dt><code>"int:new(3)"</code></dt>
038: * <dd>Equivalent to <code>new Integer(3)</code></dd>
039: * <dt><code>"int:getInteger('foo')"</code></dt>
040: * <dd>Equivalent to <code>Integer.getInteger("foo")</code></dd>
041: * <dt><code>"int:floatValue(int:new(4))"</code></dt>
042: * <dd>Equivalent to <code>new Integer(4).floatValue()</code></dd>
043: * </dl>
044: *
045: * <p>
046: * If the first argument of a method is ExpressionContext, the
047: * expression context in which the function is evaluated is passed to
048: * the method.
049: *
050: * @author Dmitri Plotnikov
051: * @version $Revision: 1.9 $ $Date: 2004/02/29 14:17:42 $
052: */
053: public class ClassFunctions implements Functions {
054: private Class functionClass;
055: private String namespace;
056: private static final Object[] EMPTY_ARRAY = new Object[0];
057:
058: public ClassFunctions(Class functionClass, String namespace) {
059: this .functionClass = functionClass;
060: this .namespace = namespace;
061: }
062:
063: /**
064: * Returns a set of one namespace - the one specified in the constructor.
065: *
066: * @returns a singleton
067: */
068: public Set getUsedNamespaces() {
069: return Collections.singleton(namespace);
070: }
071:
072: /**
073: * Returns a Function, if any, for the specified namespace,
074: * name and parameter types.
075: *
076: * @param namespace if it is not the namespace specified in the constructor,
077: * the method returns null
078: * @param name is a function name or "new" for a constructor.
079: *
080: * @return a MethodFunction, a ConstructorFunction or null if there is no
081: * such function.
082: */
083: public Function getFunction(String namespace, String name,
084: Object[] parameters) {
085: if (!namespace.equals(this .namespace)) {
086: return null;
087: }
088:
089: if (parameters == null) {
090: parameters = EMPTY_ARRAY;
091: }
092:
093: if (name.equals("new")) {
094: Constructor constructor = MethodLookupUtils
095: .lookupConstructor(functionClass, parameters);
096: if (constructor != null) {
097: return new ConstructorFunction(constructor);
098: }
099: } else {
100: Method method = MethodLookupUtils.lookupStaticMethod(
101: functionClass, name, parameters);
102: if (method != null) {
103: return new MethodFunction(method);
104: }
105:
106: method = MethodLookupUtils.lookupMethod(functionClass,
107: name, parameters);
108: if (method != null) {
109: return new MethodFunction(method);
110: }
111: }
112:
113: return null;
114: }
115: }
|