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