package org.basex.query.func; import org.basex.io.serial.Serializer; import org.basex.query.QueryException; import org.basex.query.QueryModule; import static org.basex.query.QueryText.*; import org.basex.query.expr.Expr; import org.basex.query.item.Value; import static org.basex.query.util.Err.JAVAERR; import static org.basex.query.util.Err.JAVAMOD; import org.basex.util.InputInfo; import org.basex.util.Token; import org.basex.util.TokenBuilder; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * Java function binding. * * @author BaseX Team 2005-12, BSD License * @author Christian Gruen */ public final class JavaModuleFunc extends JavaMapping { /** Java module. */ private final QueryModule module; /** Java method. */ private final Method mth; /** * Constructor. * @param ii input info * @param jm Java module * @param m Java method/field * @param a arguments */ JavaModuleFunc(final InputInfo ii, final QueryModule jm, final Method m, final Expr[] a) { super(ii, a); module = jm; mth = m; } @Override protected Object eval(final Value[] args) throws QueryException { try { try { return mth.invoke(module, (Object[]) args); } catch(final IllegalArgumentException iae) { final Object[] ar = new Object[args.length]; for(int a = 0; a < args.length; a++) ar[a] = args[a].toJava(); return mth.invoke(module, ar); } } catch(final InvocationTargetException ex) { throw JAVAERR.thrw(input, ex.getCause()); } catch(final Throwable ex) { final TokenBuilder found = new TokenBuilder(); for(final Value a : args) { if(found.size() != 0) found.add(", "); found.addExt(a.type); } throw JAVAMOD.thrw(input, signature(), name() + '(' + found + ')'); } } @Override public void plan(final Serializer ser) throws IOException { ser.openElement(this, NAM, Token.token(name())); for(final Expr arg : expr) arg.plan(ser); ser.closeElement(); } @Override public String description() { return name() + " method"; } /** * Returns the function descriptor. * @return string */ private String name() { return module.getClass().getSimpleName() + '.' + mth.getName(); } /** * Returns the function signature. * @return string */ private String signature() { final TokenBuilder exp = new TokenBuilder(); for(final Class<?> c : mth.getParameterTypes()) { if(exp.size() != 0) exp.add(", "); exp.add(c.getSimpleName()); } return name() + '(' + exp + ')'; } @Override public String toString() { return name() + PAR1 + toString(SEP) + PAR2; } }