package gnu.xml.xpath;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.xml.namespace.QName;
import javax.xml.xpath.XPathFunction;
import javax.xml.xpath.XPathFunctionException;
import javax.xml.xpath.XPathFunctionResolver;
import org.w3c.dom.Node;
public final class FunctionCall
extends Expr
{
final XPathFunctionResolver resolver;
final String name;
final List args;
public FunctionCall(XPathFunctionResolver resolver, String name)
{
this(resolver, name, Collections.EMPTY_LIST);
}
public FunctionCall(XPathFunctionResolver resolver, String name, List args)
{
this.resolver = resolver;
this.name = name;
this.args = args;
}
public Object evaluate(Node context, int pos, int len)
{
if (resolver != null)
{
QName qname = QName.valueOf(name);
int arity = args.size();
XPathFunction function = resolver.resolveFunction(qname, arity);
if (function != null)
{
if (function instanceof Expr)
{
if (function instanceof Function)
{
((Function) function).setArguments(args);
}
return ((Expr) function).evaluate(context, pos, len);
}
else
{
List values = new ArrayList(arity);
for (int i = 0; i < arity; i++)
{
Expr arg = (Expr) args.get(i);
values.add(arg.evaluate(context, pos, len));
}
try
{
return function.evaluate(values);
}
catch (XPathFunctionException e)
{
e.printStackTrace(System.err); throw new RuntimeException(e.getMessage(), e);
}
}
}
}
throw new IllegalArgumentException("Invalid function call: " +
toString());
}
public Expr clone(Object context)
{
int len = args.size();
List args2 = new ArrayList(len);
for (int i = 0; i < len; i++)
{
args2.add(((Expr) args.get(i)).clone(context));
}
XPathFunctionResolver r = resolver;
if (context instanceof XPathFunctionResolver)
{
r = (XPathFunctionResolver) context;
}
return new FunctionCall(r, name, args2);
}
public String toString()
{
StringBuffer buf = new StringBuffer();
buf.append(name);
buf.append('(');
int len = args.size();
for (int i = 0; i < len; i++)
{
if (i > 0)
{
buf.append(',');
}
buf.append(args.get(i));
}
buf.append(')');
return buf.toString();
}
}