001 // Copyright 2011 The Apache Software Foundation
002 //
003 // Licensed under the Apache License, Version 2.0 (the "License");
004 // you may not use this file except in compliance with the License.
005 // You may obtain a copy of the License at
006 //
007 // http://www.apache.org/licenses/LICENSE-2.0
008 //
009 // Unless required by applicable law or agreed to in writing, software
010 // distributed under the License is distributed on an "AS IS" BASIS,
011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012 // See the License for the specific language governing permissions and
013 // limitations under the License.
014
015 package org.apache.tapestry5.plastic;
016
017 import java.util.List;
018
019 /**
020 * A method of a {@linkplain PlasticClass transformed class}.
021 * <p/>
022 * No methods of this object should be invoked after the class transformation is
023 * {@linkplain PlasticClassTransformation#createInstantiator() completed}.
024 */
025 public interface PlasticMethod extends AnnotationAccess
026 {
027 /**
028 * Returns the PlasticClass containing this method.
029 */
030 PlasticClass getPlasticClass();
031
032 /**
033 * Returns a representation of the method's name, return value, argument types, etc.
034 */
035 MethodDescription getDescription();
036
037 /**
038 * Returns a handle that can be used to invoke a method of a transformed class instance.
039 */
040 MethodHandle getHandle();
041
042 /**
043 * Clears the instructions for this method, and creates a new empty InstructionBuilder so that the implementation of
044 * the method can be specified. This may be considered a kind of last resort when no other approach is sufficient.
045 * <p/>
046 * If the method is currently abstract, it will have its abstract flag cleared.
047 * <p/>
048 * If the method has advice, the advice is <em>not</em> lost but will instead wrap around the new method
049 * implementation.
050 *
051 * @param callback passed the InstructionBuilder so that an implementation of the method can be created
052 * @return this method, for further configuration
053 */
054 PlasticMethod changeImplementation(InstructionBuilderCallback callback);
055
056 /**
057 * Adds advice to the method. Adding advice implicitly rewrites the implementation of the method (this occurs
058 * inside at the end of the class transformation). When the method is invoked, control will flow
059 * through the MethodAdvice <em>in the order they are added</em>. Each piece of advice will receive the
060 * {@link MethodInvocation} and should invoke {@link MethodInvocation#proceed()} to pass control to the next piece
061 * of advice (and ultimately, to the actual method invocation).
062 * <p/>
063 * If a method implementation is changed, using {@link #changeImplementation(InstructionBuilderCallback)}, that
064 * change will be honored, but the logic will only be invoked at the end of the chain of MethodAdvice. Internally, a
065 * new method is created with the same parameters, exceptions, return type and implementation (bytecode) as the
066 * advised method, <em>then</em> the advised method's implementation is changed.
067 * <p/>
068 * Note additionally that a recursive method invocation will still invoke the MethodAdvice chain on each recursive
069 * call (this is an intended side-effect of copying the exact bytecode of the method implementation.
070 *
071 * @param advice advice to add to the method
072 * @return this method, for further configuration
073 */
074 PlasticMethod addAdvice(MethodAdvice advice);
075
076 /**
077 * Changes the implementation of the method to delegate to the provided field. The field must implement the
078 * correct interface (or extend the correct class). The original implementation of the method is lost,
079 * though (as with {@link #changeImplementation(InstructionBuilderCallback)}), method advice is retained.
080 *
081 * @param field to delegate to
082 * @return this method, for further configuration
083 */
084 PlasticMethod delegateTo(PlasticField field);
085
086 /**
087 * Much like {@link #delegateTo(PlasticField)}, but the object to delegate to
088 * is dynamically computed by another method of the class. The method should take no parameters
089 * and must not return null, or throw any exceptions not compatible with the method being proxied.
090 *
091 * @param method to provide the dynamic delegate
092 * @return this method, for further configuration
093 */
094 PlasticMethod delegateTo(PlasticMethod method);
095
096 /**
097 * Returns access to the parameters of the method and, in particular,
098 * the visible annotations on those parameters.
099 */
100 List<MethodParameter> getParameters();
101
102 /**
103 * Returns true if the method is an override of a method from the parent class.
104 *
105 * @return true if the parent class contains a method with the name signature
106 */
107 boolean isOverride();
108
109 /**
110 * Returns a short identifier for the method that includes the class name, the method name,
111 * and the types of all parameters. This is often used when producing debugging output
112 * about the method.
113 *
114 * @return short identifier
115 * @see org.apache.tapestry5.plastic.MethodDescription#toShortString()
116 */
117 String getMethodIdentifier();
118
119 /**
120 * Returns true if this method is type void.
121 *
122 * @return true for void methods.
123 */
124 boolean isVoid();
125 }