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