001 // Copyright 2004, 2005 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.tapestry.enhance; 016 017 import org.apache.hivemind.Location; 018 import org.apache.hivemind.service.MethodSignature; 019 import org.apache.tapestry.spec.IComponentSpecification; 020 021 import java.util.List; 022 023 /** 024 * A process object representing enhancements to a component class. The 025 * operation is passed to {@link org.apache.tapestry.enhance.EnhancementWorker}objects 026 * that perform enhancements. 027 * 028 * @author Howard M. Lewis Ship 029 * @since 4.0 030 */ 031 public interface EnhancementOperation 032 { 033 034 /** 035 * Claims a property. Most enhancements are concerned with adding 036 * properties. Some enhancement workers exist to fill in defaults, and they 037 * need to know what properties have already been spoken for by eariler 038 * enhancement works. 039 * 040 * @throws org.apache.hivemind.ApplicationRuntimeException 041 * if the property was previously claimed 042 */ 043 044 void claimProperty(String propertyName); 045 046 /** 047 * Claims a property as read-only. This will check to see if the property 048 * has an abstract setter method. 049 * 050 * @throws org.apache.hivemind.ApplicationRuntimeException 051 * if the property was previously claimed, or if the property 052 * includes an accessor method. 053 */ 054 055 void claimReadonlyProperty(String propertyName); 056 057 /** 058 * Checks to see if the specified property can be claimed as read only. 059 * 060 * @param propertyName 061 * The property to check. 062 * 063 * @return True, if no setter method has been created for the specified property and 064 * the property hasn't been claimed by someone else. 065 */ 066 boolean canClaimAsReadOnlyProperty(String propertyName); 067 068 /** 069 * Returns a list of the names of existing properties that are not claimed 070 * and which have abstract accessor methods. 071 */ 072 073 List findUnclaimedAbstractProperties(); 074 075 /** 076 * Adds a field to the enhanced class; the field will be private and use the 077 * provided name and type. 078 */ 079 080 void addField(String name, Class type); 081 082 /** 083 * Adds a field containing an initial value, which is injected into the 084 * class via its fabricated constructor. This method may be called multiple 085 * times with the same value and will return the same variable name (an 086 * identity map is kept internally). 087 * 088 * @param fieldName 089 * The default name for the field, used if a new field (and 090 * contructor argument) is being created. Only used if a field 091 * for the value doesn't exist. 092 * @param fieldType 093 * The type of the field to be created. 094 * @param value 095 * the value to be referenced, which may not be null 096 * @return the name of the field containing the value. This may or may not 097 * match fieldName. The provided fieldName may be modified to 098 * prevent naming conflicts. 099 */ 100 101 String addInjectedField(String fieldName, Class fieldType, Object value); 102 103 /** 104 * Converts a type name (an object class name, a primtive name, or an array) 105 * into the corresponding Class object. 106 */ 107 108 Class convertTypeName(String type); 109 110 /** 111 * Confirms that the named property either doesn't exist (in the component 112 * base class), or that the type of the property exactly matches the 113 * indicated type. 114 */ 115 116 void validateProperty(String name, Class expectedType); 117 118 /** 119 * Returns the name of the accessor method for the given property (if it 120 * exists in the component base class), or fabricates a new name if it does 121 * not. 122 * 123 * @param propertyName 124 * The property to get an accessor method name of. 125 * 126 * @return The existing/future name of an appropriate accessor method for the property. 127 */ 128 129 String getAccessorMethodName(String propertyName); 130 131 /** 132 * Adds a method to the enhanced class. 133 * 134 * @param modifier 135 * as defined by {@link java.lang.reflect.Modifier}, typically 136 * {@link java.lang.reflect.Modifier#PUBLIC} 137 * @param sig 138 * the method signature (defining name, return type, etc.) 139 * @param methodBody 140 * a Javassist code snippet for the method body 141 * @param location 142 * a location used to identify "why" the method was added; the 143 * location may later be used to describe conflicts. May not be 144 * null. 145 */ 146 void addMethod(int modifier, MethodSignature sig, String methodBody, Location location); 147 148 /** 149 * Returns the base component class, as defined in the specification (or 150 * defaulted). An enhaced subclass of the component class will usually be 151 * created. 152 * 153 * @return The class this enhancement operation is operating on. 154 */ 155 Class getBaseClass(); 156 157 /** 158 * Returns a reference to a particular class. This will, effectively, by the 159 * name of a private field. 160 * 161 * @param clazz The class to get a string equivalent reference of. 162 * 163 * @return The enhancement (javassist) compatiable string version of the specified class. 164 */ 165 166 String getClassReference(Class clazz); 167 168 /** 169 * Returns the type of an existing property of the base component class. If 170 * the property does not exist, then returns null. 171 * 172 * @param name 173 * The property name. 174 * 175 * @return The property type, or null if it doesn't exist. 176 */ 177 178 Class getPropertyType(String name); 179 180 /** 181 * Allows for a kind of distributed construction of a particular method, 182 * within a particular interface. Code can be appended to the method's 183 * implementation throughout the course of the enhancement operation. When 184 * the enhanced class is finialized, the method is added with whatever 185 * contents are in its body. If the base class implements the method, then 186 * the method body will include an initial call to that implementation. 187 * <p> 188 * At this time, this works best for void methods (since there isn't an easy 189 * way to ensure code would be inserted before a final return statement). 190 * 191 * @param interfaceClass 192 * the interface containing the method. If the base class does 193 * not implement the interface, then the enhanced class will have 194 * the interface added. 195 * @param methodSignature 196 * the signature of the method to be added. 197 * @param code 198 * the Javassist markup to be added to the body of the method. 199 */ 200 void extendMethodImplementation(Class interfaceClass, MethodSignature methodSignature, String code); 201 202 /** 203 * Returns true if the class implements the specified interface. Checks the 204 * base class (as identified in the specification), but <em>also</em> 205 * accounts for any additional interfaces that may be added by 206 * {@link #extendMethodImplementation(Class, MethodSignature, String)}. 207 * 208 * @param interfaceClass 209 * The class to check if the base class implements. 210 * 211 * @return Whether or not the specified interface is implemented by the base class 212 * being enhanced. 213 */ 214 215 boolean implementsInterface(Class interfaceClass); 216 217 /** 218 * The specification defined for the component class being enhanced. 219 * 220 * @return The specification for the component being enhanced. 221 */ 222 IComponentSpecification getSpecification(); 223 }