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    }