/**
*
* Copyright 2015 Patrick Ahlbrecht
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.onyxbits.jbee;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.List;
/**
* A {@link ReflectedMathLib} automatically registers its methods as functions.
* <p>
* To register as a function, a method only needs to have {@link BigDecimal} as
* return type and accept zero or more {@link BigDecimal}S as it's parameters.
* It may not declare a throws clause with checked exceptions (throwing
* {@link RuntimeException}S is acceptable).
*
* @author patrick
*
*/
public abstract class ReflectedMathLib extends DefaultMathLib {
/**
* {@inheritDoc}
*/
public final BigDecimal onCall(String name, List<BigDecimal> args) {
Method[] methods = getClass().getDeclaredMethods();
int len = args.size();
for (Method m : methods) {
if (name.equals(m.getName()) && m.getReturnType().equals(BigDecimal.class)) {
Class<?>[] params = m.getParameterTypes();
boolean fits = true;
if (params.length == len) {
for (Class<?> cl : params) {
if (!cl.equals(BigDecimal.class)) {
fits = false;
break;
}
}
}
if (fits) {
Object[] pass = new BigDecimal[len];
for (int i = 0; i < pass.length; i++) {
pass[i] = args.get(i);
}
try {
return (BigDecimal) m.invoke(this, pass);
}
catch (IllegalAccessException e) {
// e.printStackTrace();
}
catch (IllegalArgumentException e) {
// e.printStackTrace();
}
catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
}
// We should NEVER get here! If we do, the implementator
// deliberately messed up by adding a throws clause for checked
// exceptions. In that case we treat the function as not defined
throw new NotDefinedException(name);
// e.printStackTrace();
}
}
}
}
return super.onCall(name, args);
}
}