    1   /*
    2    * Copyright 1999-2004 The Apache Software Foundation
    3    *
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    *
    8    *     http://www.apache.org/licenses/LICENSE-2.0
    9    *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    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 }