How do I generate a class which takes a Person instance and returns the birthday as a String instead of a Date formatted with the value of the @MyFormat annotation, without writing that subclass by hand?
The purpose is the use the generated instances for HTML page generation
class Person {
@MyFormat("%td.%<tm.%<tY")
public Date getBirthday() { return birthday; }
}
// Usage somewhere in the code
...
List<Person> people = people.parallelStream()
.map(p -> MyFormatInterceptor.wrap(p))
.collect(toCollection(ArrayList::new));
System.out.println(people.iterator().next().getBirtday()) // 31.Mai.2015
I have this (see below).
It doesn't matter that the return type changes from Date to String because the call is made by reflection from evaluating the expression "person.birthday".
new ByteBuddy()
.subclass(person.getClass())
.method(isAnnotatedWith(MyFormat.class))
.intercept(MethodDelegation.to(MyFormatInterceptor.class))
.make()
.load(person.getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
class MyFormatInterceptor {
@RuntimeType
public static Object format(@Origin Method m, @SuperCall Callable<?> zuper) {
MyFormat formatAnnotation = m.getAnnotation(MyFormat.class);
return String.format(formatAnnotation.value(), zuper.call());
}
}
So the new class would have the same methode name "String getBirthday()" but with String as return value.