View Javadoc
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.ri.compiler;
18  
19  import java.util.Arrays;
20  
21  import org.apache.commons.jxpath.Function;
22  import org.apache.commons.jxpath.JXPathFunctionNotFoundException;
23  import org.apache.commons.jxpath.NodeSet;
24  import org.apache.commons.jxpath.ri.EvalContext;
25  import org.apache.commons.jxpath.ri.QName;
26  import org.apache.commons.jxpath.ri.axes.NodeSetContext;
27  
28  /**
29   * Represents an element of the parse tree representing an extension function
30   * call.
31   *
32   * @author Dmitri Plotnikov
33   * @version $Revision: 652845 $ $Date: 2008-05-02 19:46:46 +0200 (Fr, 02 Mai 2008) $
34   */
35  public class ExtensionFunction extends Operation {
36  
37      private QName functionName;
38  
39      /**
40       * Create a new ExtensionFunction.
41       * @param functionName name of the function
42       * @param args Expression[] of function args
43       */
44      public ExtensionFunction(QName functionName, Expression[] args) {
45          super(args);
46          this.functionName = functionName;
47      }
48  
49      /**
50       * Get the function name
51       * @return QName
52       */
53      public QName getFunctionName() {
54          return functionName;
55      }
56  
57      /**
58       * An extension function gets the current context, therefore it MAY be
59       * context dependent.
60       * @return true
61       */
62      public boolean computeContextDependent() {
63          return true;
64      }
65  
66      public String toString() {
67          StringBuffer buffer = new StringBuffer();
68          buffer.append(functionName);
69          buffer.append('(');
70          Expression[] args = getArguments();
71          if (args != null) {
72              for (int i = 0; i < args.length; i++) {
73                  if (i > 0) {
74                      buffer.append(", ");
75                  }
76                  buffer.append(args[i]);
77              }
78          }
79          buffer.append(')');
80          return buffer.toString();
81      }
82  
83      public Object compute(EvalContext context) {
84          return computeValue(context);
85      }
86  
87      public Object computeValue(EvalContext context) {
88          Object[] parameters = null;
89          if (args != null) {
90              parameters = new Object[args.length];
91              for (int i = 0; i < args.length; i++) {
92                  parameters[i] = convert(args[i].compute(context));
93              }
94          }
95  
96          Function function =
97              context.getRootContext().getFunction(functionName, parameters);
98          if (function == null) {
99              throw new JXPathFunctionNotFoundException("No such function: "
100                     + functionName + Arrays.asList(parameters));
101         }
102         Object result = function.invoke(context, parameters);
103         return result instanceof NodeSet ? new NodeSetContext(context,
104                 (NodeSet) result) : result;
105     }
106 
107     /**
108      * Convert any incoming context to a value.
109      * @param object Object to convert
110      * @return context value or <code>object</code> unscathed.
111      */
112     private Object convert(Object object) {
113         return object instanceof EvalContext ? ((EvalContext) object).getValue() : object;
114     }
115 }