Okay, my annotation is called @Once and if put on accessor will make
sure that the method is only executed once and then the return value is
cached. Any further calls to the method will just return the saved
value. I've got pretty far but I think I'm stuck as I want to do
something that I could do with javassist but I'm not sure how to do
within the tapestry enhancement classes. I've attached what I have so
far and I would greatly appreciated it if someone could give me some
suggestions on what to do. My big problem is:

- I could add code at the beginning and end of the method with javassit
but can't see a way to do that
- Perhaps I could somehow rename the old method to something else and
put in a new method that calls it?

Thanks a lot.

On Thu, 2006-05-25 at 07:11 -0400, James Carman wrote:
> I'd look at the one that injects messages, or beans, or even the one that I
> wrote for "autowiring" (available in SVN on the 4.1 branch).
> 
> -----Original Message-----
> From: Dan Adams [mailto:[EMAIL PROTECTED] 
> Sent: Wednesday, May 24, 2006 10:44 PM
> To: Tapestry users
> Subject: Help in writing a custom annotation
> 
> I want to write an annotation that will intercept a method and add a
> property to the class. I've started digging around in some of the
> annotation sources but it's going pretty slow. Can someone point me at
> the right place to look for where to start?
> 
-- 
Dan Adams
Software Engineer
Interactive Factory
617.235.5857
package com.ifactory.cms.annotations;

import static java.lang.String.format;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;

import org.apache.hivemind.ApplicationRuntimeException;
import org.apache.hivemind.Location;
import org.apache.hivemind.Resource;
import org.apache.hivemind.service.MethodSignature;
import org.apache.tapestry.annotations.AnnotationUtils;
import org.apache.tapestry.annotations.SecondaryAnnotationWorker;
import org.apache.tapestry.enhance.EnhanceUtils;
import org.apache.tapestry.enhance.EnhancementOperation;
import org.apache.tapestry.enhance.EnhancementWorker;
import org.apache.tapestry.event.PageDetachListener;
import org.apache.tapestry.spec.IComponentSpecification;

public class OnceAnnotationWorker implements EnhancementWorker {

	public OnceAnnotationWorker() {
		super();
	}

	public void performEnhancement(EnhancementOperation op, IComponentSpecification spec) {
		// find all methods that have the once annotation and process them
		for (Method method : getAnnotatedMethods(op)) {
			// method must have a return type
			if (method.getReturnType().equals(void.class))
				throw new ApplicationRuntimeException("Method must have a return type: " + method.getName());

			String propertyName = AnnotationUtils.getPropertyName(method);
			
			// add a property to store whether or not the method has been called
			String fieldName = "_$" + propertyName;
			String calledField = fieldName + "$called";
			
			op.addField(fieldName, method.getReturnType());
			op.addField(calledField, boolean.class);
			
			// on page detach, reset the field values
			op.extendMethodImplementation(
					PageDetachListener.class, 
					EnhanceUtils.PAGE_DETACHED_SIGNATURE, 
					format("%s = null; %s = false;", fieldName, calledField));

			// how to override the method or add to it? 
		}
	}

	/** Returns all the methods that are annotated with Once */
	private List<Method> getAnnotatedMethods(EnhancementOperation op) {
		List<Method> methods = new ArrayList<Method>();
		for(Method m : op.getBaseClass().getMethods()) {
			if (m.getAnnotation(Once.class) != null)
				methods.add(m);
		}
		return methods;
	}
}

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to