/**
* Copyright (c) 2012-2015 Edgar Espina
*
* This file is part of Handlebars.java.
*
* 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 com.github.jknack.handlebars.context;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.LinkedHashSet;
import java.util.Set;
import com.github.jknack.handlebars.ValueResolver;
/**
* A specialization of {@link MemberValueResolver} with lookup and invocation
* support for {@link Method}.
* It matches a public method.
*
* @author edgar.espina
* @since 0.1.1
*/
public class MethodValueResolver extends MemberValueResolver<Method> {
/**
* The default instance.
*/
public static final ValueResolver INSTANCE = new MethodValueResolver();
/**
* Args for getters.
*/
private static final Object[] EMPTY_ARGS = new Object[0];
@Override
public boolean matches(final Method method, final String name) {
int parameterCount = method.getParameterTypes().length;
return isPublic(method) && method.getName().equals(name) && parameterCount == 0;
}
@Override
protected Object invokeMember(final Method member, final Object context) {
try {
return member.invoke(context, EMPTY_ARGS);
} catch (InvocationTargetException ex) {
Throwable cause = ex.getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
}
throw new IllegalStateException("Execution of '" + member.getName() + "' failed", cause);
} catch (IllegalAccessException ex) {
throw new IllegalStateException(
"Could not access method: '" + member.getName() + "'", ex);
}
}
@Override
protected Set<Method> members(final Class<?> clazz) {
Set<Method> members = new LinkedHashSet<Method>();
members(clazz, members);
return members;
}
/**
* Collect all the method from the given class.
*
* @param clazz The base class.
* @param members The members result set.
*/
protected void members(final Class<?> clazz, final Set<Method> members) {
if (clazz != Object.class) {
// Keep backing up the inheritance hierarchy.
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
if (matches(method, memberName(method))) {
members.add(method);
}
}
if (clazz.getSuperclass() != null) {
members(clazz.getSuperclass(), members);
}
for (Class<?> superIfc : clazz.getInterfaces()) {
members(superIfc, members);
}
}
}
@Override
protected String memberName(final Method member) {
return member.getName();
}
}