package com.github.mustachejava;
import com.github.mustachejava.reflect.Guard;
import com.github.mustachejava.reflect.ReflectionObjectHandler;
import com.github.mustachejava.reflect.ReflectionWrapper;
import com.github.mustachejava.util.GuardException;
import com.github.mustachejava.util.Wrapper;
import com.google.common.base.Function;
import org.junit.BeforeClass;
import org.junit.Test;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import static junit.framework.Assert.assertEquals;
public class ConvertMethodsToFunctionsTest {
private static ReflectionObjectHandler roh;
@Retention(RetentionPolicy.RUNTIME)
@interface TemplateMethod {
}
@BeforeClass
public static void setup() {
roh = new ReflectionObjectHandler() {
/**
* Find a wrapper given the current context. If not found, return null.
*
* @param scopeIndex the index into the scope array
* @param wrappers the current set of wrappers to get here
* @param guards the list of guards used to find this
* @param scope the current scope
* @param name the name in the scope
* @return null if not found, otherwise a wrapper for this scope and name
*/
@Override
protected Wrapper findWrapper(int scopeIndex, Wrapper[] wrappers, List<Guard> guards, Object scope, String name) {
Wrapper wrapper = super.findWrapper(scopeIndex, wrappers, guards, scope, name);
if (wrapper == null) {
// Now check to see if there is a method that takes a string
return getWrapper(scopeIndex, wrappers, guards, scope, name, scope.getClass());
}
return wrapper;
}
private Wrapper getWrapper(final int scopeIndex, final Wrapper[] wrappers, final List<Guard> guards, Object scope, String name, Class<?> aClass) {
try {
Method method = aClass.getDeclaredMethod(name, String.class);
method.setAccessible(true);
return new ReflectionWrapper(scopeIndex, wrappers, guards.toArray(new Guard[guards.size()]), method, null, this) {
@Override
public Object call(Object[] scopes) throws GuardException {
guardCall(scopes);
final Object scope1 = unwrap(scopes);
if (scope1 == null) return null;
if (method.getAnnotation(TemplateMethod.class) == null) {
return new Function<String, String>() {
@Override
public String apply(String input) {
return getString(input, scope1);
}
};
} else {
return new TemplateFunction() {
@Override
public String apply(String input) {
return getString(input, scope1);
}
};
}
}
private String getString(String input, Object scope1) {
try {
Object invoke = method.invoke(scope1, input);
return invoke == null ? null : String.valueOf(invoke);
} catch (InvocationTargetException e) {
throw new MustacheException("Failed to execute method: " + method, e.getTargetException());
} catch (IllegalAccessException e) {
throw new MustacheException("Failed to execute method: " + method, e);
}
}
};
} catch (NoSuchMethodException e) {
Class<?> superclass = aClass.getSuperclass();
return superclass == Object.class ? null : getWrapper(scopeIndex, wrappers, guards, scope, name, superclass);
}
}
};
}
@Test
public void testConvert() throws IOException {
DefaultMustacheFactory dmf = new DefaultMustacheFactory();
dmf.setObjectHandler(roh);
Mustache uppertest = dmf.compile(new StringReader("{{#upper}}{{test}}{{/upper}}"), "uppertest");
StringWriter sw = new StringWriter();
uppertest.execute(sw, new Object() {
String test = "test";
String upper(String s) {
return s.toUpperCase();
}
}).close();
assertEquals("TEST", sw.toString());
sw = new StringWriter();
uppertest.execute(sw, new Object() {
String test2 = "test";
@TemplateMethod
String upper(String s) {
return "{{test2}}";
}
}).close();
assertEquals("test", sw.toString());
}
}