package plasticdemo.transforms;
import org.apache.tapestry5.plastic.FieldHandle;
import org.apache.tapestry5.plastic.MethodAdvice;
import org.apache.tapestry5.plastic.MethodDescription;
import org.apache.tapestry5.plastic.MethodInvocation;
import org.apache.tapestry5.plastic.PlasticClass;
import org.apache.tapestry5.plastic.PlasticClassTransformer;
import org.apache.tapestry5.plastic.PlasticField;
import org.apache.tapestry5.plastic.PlasticMethod;
import plasticdemo.annotations.Property;
/**
* A class transformer that checks for {@link plasticdemo.annotations.Property}
* annotation on fields and generates getter and setter methods for that field
*/
public class PropertyTransformer implements PlasticClassTransformer {
/**
* Transform class
*/
public void transform(PlasticClass plasticClass) {
for (PlasticField field : plasticClass.getFieldsWithAnnotation(Property.class)) {
introduceGetter(plasticClass, field);
Property annotation = field.getAnnotation(Property.class);
if (annotation.write()) {
introduceSetter(plasticClass, field);
}
}
}
/**
* Introduce a getter method
*
* @param plasticClass plastic class
* @param field field for which getter is to be generated
*/
private void introduceGetter(PlasticClass plasticClass, final PlasticField field) {
String methodName = toMethodName("get", field.getName());
MethodDescription getterDescription = new MethodDescription(field.getTypeName(), methodName);
PlasticMethod method = plasticClass.introduceMethod(getterDescription);
final FieldHandle fieldHandle = field.getHandle();
method.addAdvice(new MethodAdvice() {
public void advise(MethodInvocation invocation) {
invocation.setReturnValue(fieldHandle.get(invocation.getInstance()));
}
});
}
/**
* Introduce a setter method
*
* @param plasticClass plastic class
* @param field field for which setter is to be generated
*/
private void introduceSetter(PlasticClass plasticClass, final PlasticField field) {
String methodName = toMethodName("set", field.getName());
MethodDescription setterDescription = new MethodDescription("void", methodName,
field.getTypeName());
PlasticMethod method = plasticClass.introduceMethod(setterDescription);
final FieldHandle fieldHandle = field.getHandle();
method.addAdvice(new MethodAdvice(){
public void advise(MethodInvocation invocation) {
fieldHandle.set(invocation.getInstance(), invocation.getParameter(0));
}
});
}
/**
* Creates a method name
*
* @param prefix prefix to append to the method name
* @param name field name
* @return method name
*/
private String toMethodName(String prefix, String name) {
String methodName = name.replaceAll("^_*", "");
return prefix + Character.toUpperCase(methodName.charAt(0)) + methodName.substring(1);
}
}