package com.googlecode.tawus.addons.internal.transform; import java.lang.reflect.Modifier; import java.util.List; import org.apache.tapestry5.ioc.internal.util.InternalUtils; import org.apache.tapestry5.ioc.services.PropertyAccess; import org.apache.tapestry5.ioc.services.TypeCoercer; import org.apache.tapestry5.model.MutableComponentModel; import org.apache.tapestry5.services.ClassTransformation; import org.apache.tapestry5.services.ComponentClassTransformWorker; import org.apache.tapestry5.services.ComponentMethodAdvice; import org.apache.tapestry5.services.ComponentMethodInvocation; import org.apache.tapestry5.services.FieldAccess; import org.apache.tapestry5.services.TransformField; import org.apache.tapestry5.services.TransformMethod; import org.apache.tapestry5.services.TransformMethodSignature; import com.googlecode.tawus.addons.annotations.InjectSelectSupport; import com.googlecode.tawus.addons.internal.SelectSupport; public class InjectSelectSupportWorker implements ComponentClassTransformWorker { private PropertyAccess propertyAccess; private TypeCoercer typeCoercer; public InjectSelectSupportWorker(PropertyAccess propertyAccess, TypeCoercer typeCoercer) { this.propertyAccess = propertyAccess; this.typeCoercer = typeCoercer; } public void transform(ClassTransformation transform, MutableComponentModel model) { for (final TransformField field : transform.matchFieldsWithAnnotation(InjectSelectSupport.class)) { final InjectSelectSupport annotation = field.getAnnotation(InjectSelectSupport.class); String selectSupportPropertyName = field.getName() + annotation.methodSuffix(); String methodName = "get" + InternalUtils.capitalize(selectSupportPropertyName); TransformMethodSignature sig = new TransformMethodSignature(Modifier.PUBLIC, SelectSupport.class.getName(), methodName, null, null); final TransformMethod method = transform.getOrCreateMethod(sig); // Add a field to cache the result final TransformField selectSupportField = transform.createField(Modifier.PRIVATE, SelectSupport.class.getName(), "_$" + selectSupportPropertyName); final FieldAccess selectSupportFieldAccess = selectSupportField.getAccess(); final FieldAccess access = field.getAccess(); method.addAdvice(new ComponentMethodAdvice() { @SuppressWarnings({ "unchecked", "rawtypes" }) public void advise(ComponentMethodInvocation invocation) { Object instance = invocation.getInstance(); if (selectSupportFieldAccess.read(instance) == null) { selectSupportFieldAccess.write( instance, new SelectSupport((List) access.read(invocation.getInstance()), annotation.label(), annotation.index(), annotation.type(), propertyAccess, typeCoercer)); } invocation.overrideResult(selectSupportFieldAccess.read(instance)); } }); } } }