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.lang.annotation.Annotation; 016import java.lang.reflect.Method; 017import java.util.List; 018import java.util.Set; 019 020/** 021 * The representation of a class while it is being instrumented and transformed. PlasticClass allows 022 * for an imperative style of development: the PlasticClass is provided to other objects; they can query it 023 * for relevant fields or methods, and invoke methods that modify the class in various ways. Ultimately, the 024 * end result is a {@link ClassInstantiator} used to create instances of the fully instrumented and transformed class. 025 * 026 * The terminology is that a class that is being transformed is "plastic", but the end result is a normal concrete class 027 * (albeit in a different class loader). 028 * 029 * Implements {@link AnnotationAccess} to provide access to annotations on the type itself. 030 * 031 * This class is expressly <em>not thread safe</em>; only a single thread should be responsible for operating on a 032 * PlasticClass. 033 * 034 * TODO: what about annotation inheritance? 035 */ 036@SuppressWarnings("rawtypes") 037public interface PlasticClass extends AnnotationAccess 038{ 039 /** 040 * Returns the fully qualified class name of the class being transformed. 041 */ 042 String getClassName(); 043 044 /** 045 * Matches all fields (claimed or not) that have the given annotation. Returns the fields in sorted order. 046 * 047 * @return Unmodifiable List of fields. 048 */ 049 <T extends Annotation> List<PlasticField> getFieldsWithAnnotation(Class<T> annotationType); 050 051 /** 052 * Returns all non-introduced fields, in sorted order by name. 053 * 054 * @return Unmodifiable list of fields. 055 */ 056 List<PlasticField> getAllFields(); 057 058 /** 059 * Returns all unclaimed fields, in sorted order by name. This does not include introduced fields. 060 * 061 * @return Unmodifiable list of fields. 062 * @see PlasticField#claim(Object) 063 */ 064 List<PlasticField> getUnclaimedFields(); 065 066 /** 067 * Introduces a new private field into the class. 068 * 069 * @param typeName the Java class name for the field, or (possibly) a primitive type name or an array 070 * @param suggestedName the suggested name for the field, which may be modified to ensure that the field name 071 * is unique 072 * @return PlasticField for the introduced field 073 */ 074 PlasticField introduceField(String typeName, String suggestedName); 075 076 /** 077 * Convenience method that uses a Java class rather than a type name. 078 */ 079 PlasticField introduceField(Class fieldType, String suggestedName); 080 081 /** 082 * Introduces a new private method into the class, ensuring that the method name is unique. 083 * 084 * @param typeName return type of method 085 * @param suggestedName suggested name for the method; the actual method name may be modified to ensure uniqueness 086 * @param argumentTypes types of any arguments (may be null) 087 * @param exceptionTypes type of any checked exceptions (may be null) 088 * @return new method, with default implementation 089 */ 090 PlasticMethod introducePrivateMethod(String typeName, String suggestedName, String[] argumentTypes, 091 String[] exceptionTypes); 092 093 /** 094 * Matches methods with the given annotation. 095 * 096 * @return Unmodifiable list of methods, in sorted order. 097 */ 098 <T extends Annotation> List<PlasticMethod> getMethodsWithAnnotation(Class<T> annotationType); 099 100 /** 101 * Returns all methods of the class, in sorted order. This does not include static methods, 102 * or any {@linkplain #introduceMethod(MethodDescription) introduced methods}. 103 * 104 * @return Unmodifiable list of methods. 105 */ 106 List<PlasticMethod> getMethods(); 107 108 /** 109 * Returns an existing method declared in this class, or introduces a new method into this class. 110 * The method is created with default behavior. If the method overrides a non-private, non-abstract method 111 * implemented in a <em>transformed</em> super class, the the default behavior is to invoke that method and return 112 * its value. Otherwise, the default behavior is to ignore parameters and return 0, false, or null. Void methods 113 * will invoke the super-class implementation (if it exists) and return no value. 114 * 115 * It is allowed for the method description to indicate an abstract method; however the abstract flag will be 116 * removed, and a non-abstract method will be created. 117 * 118 * @param description describes the method name, visibility, return value, etc. 119 * @return a new (or previously created) PlasticMethod for the method 120 * @throws IllegalArgumentException if the method is abstract or static 121 */ 122 PlasticMethod introduceMethod(MethodDescription description); 123 124 /** 125 * Returns an existing method declared in this class, or introduces a new method into this class. 126 * The method is created with default behavior. 127 * 128 * It is allowed for the method description to indicate an abstract method; however the abstract flag will be 129 * removed, and a non-abstract method will be created. 130 * 131 * @param description describes the method name, visibility, return value, etc. 132 * @param callback used to create the implementation of the method 133 * @return a new (or previously created) PlasticMethod for the method 134 * @throws IllegalArgumentException if the method is abstract or static 135 */ 136 PlasticMethod introduceMethod(MethodDescription description, InstructionBuilderCallback callback); 137 138 /** 139 * A convenience that creates a {@link MethodDescription} from the Method and introduces that. This is often 140 * invoked when walking the methods of an interface and introducing each of those methods. 141 * 142 * Introduced methods are always concrete, not abstract. The abstract flag on the method modifiers will always be 143 * stripped off, which is handy when {@linkplain #introduceInterface(Class) introducing methods from an interface}. 144 * 145 * @param method to introduce 146 * @return new (or previously created) PlasticMethod 147 */ 148 PlasticMethod introduceMethod(Method method); 149 150 /** 151 * Introduces each method defined by the interface into the class. Determines which new methods must 152 * be introduced in order to ensure that all methods of the interface are implemented. The newly introduced methods, 153 * if any, are returned. 154 */ 155 Set<PlasticMethod> introduceInterface(Class interfaceType); 156 157 /** 158 * Introduces the interface, and then invokes {@link PlasticMethod#delegateTo(PlasticField)} on each method 159 * defined by the interface. 160 * 161 * @param interfaceType defines the interface to proxy 162 * @param field field containing an object to delegate to 163 * @return this plastic class, for further configuration 164 */ 165 PlasticClass proxyInterface(Class interfaceType, PlasticField field); 166 167 /** 168 * Introduces the interface, and then invokes {@link PlasticMethod#delegateTo(PlasticMethod)} on each method 169 * defined by the interface. 170 * 171 * @param interfaceType defines the interface to proxy 172 * @param method method to delegate to 173 * @return this plastic class, for further configuration 174 * @since 5.4.4 175 */ 176 PlasticClass proxyInterface(Class interfaceType, PlasticMethod method); 177 178 /** 179 * Conditionally adds an implementation of <code>toString()</code> to the class, but only if it is not already 180 * present in the class, or in a (transformed) super-class. 181 * 182 * @param toStringValue the fixed value to be returned from invoking toString() 183 * @return this plastic class, for further configuration 184 */ 185 PlasticClass addToString(String toStringValue); 186 187 /** 188 * Returns true if this class has an implementation of the indicated method, or a super-class provides 189 * a non-abstract implementation. 190 */ 191 boolean isMethodImplemented(MethodDescription description); 192 193 /** 194 * Returns true if this class, or a super-class, implements the indicated interface. 195 * 196 * @param interfaceType 197 * @return true if the interface is implemented 198 */ 199 boolean isInterfaceImplemented(Class interfaceType); 200 201 /** 202 * Returns the name of the super-class of the class being transformed. 203 */ 204 String getSuperClassName(); 205 206 /** 207 * Adds the callback for execution when an instance of the class is instantiated. 208 * 209 * @param callback to execute at instance construction time 210 */ 211 PlasticClass onConstruct(ConstructorCallback callback); 212}