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 /** 018 * Represents a field of a class being {@linkplain PlasticClass transformed}. 019 * <p> 020 * No methods of this object should be invoked after the class transformation is completed. 021 */ 022 public interface PlasticField extends AnnotationAccess 023 { 024 /** Returns the class containing this field. */ 025 PlasticClass getPlasticClass(); 026 027 /** 028 * Returns a handle that can be used to directly access a private field of a 029 * transformed class instance. 030 */ 031 FieldHandle getHandle(); 032 033 /** 034 * Returns the name of the field. 035 */ 036 String getName(); 037 038 /** 039 * Returns the fully qualified class name for the field's type or (for a primitive type) 040 * the primitive type name ("int", "char", etc.). For array types, the returned name includes 041 * a "[]" suffix. 042 */ 043 String getTypeName(); 044 045 /** 046 * Claims the field, used to indicate that the field is "processed". A field may only 047 * be claimed once. Claiming a field is intended as a mechanism to detect or prevent 048 * conflicts between different isolated transformations of the field. The tag value used does not matter, and is 049 * typically either an annotation (that drove the transformation) or the instance of {@link PlasticClassTransformer} 050 * that performed the transformation. That tag value is only used when generating the error message for the case 051 * where a field is claimed for than once. 052 * 053 * @throws RuntimeException 054 * if the field is claimed a second time 055 * @throws AssertionError 056 * if tag is null 057 * @see PlasticClass#getUnclaimedFields() 058 * @return the field for further manipulation 059 */ 060 PlasticField claim(Object tag); 061 062 /** 063 * Returns true if the field has already been {@linkplain #claim(Object) claimed}. 064 * 065 * @see PlasticClass#getUnclaimedFields() 066 */ 067 boolean isClaimed(); 068 069 /** 070 * Converts the field to be read-only, and provide the indicated value. The field's value will be 071 * set inside the class' constructor. 072 * 073 * @param value 074 * to inject, which must be type compatible with the field (possibly, a wrapper type if the field is 075 * a primitive value). The value may not be null. 076 * @return the field for further manipulation 077 * @throws IllegalStateException 078 * if the field already has an injection, or the field has a conduit 079 */ 080 PlasticField inject(Object value); 081 082 /** 083 * Converts the field to be read-only, and provide the value, which is computed 084 * indirectly inside the class' constructor. 085 * 086 * @param computedValue 087 * provides the actual value to be injected, and must return a value type compatible 088 * with the field (possibly a wrapper type if the field is a primitive value). The computedValue may not 089 * be null. 090 * @return the field for further manipulation 091 * @throws IllegalStateException 092 * if the field already has an injection, or the field has a conduit 093 */ 094 PlasticField injectComputed(ComputedValue<?> computedValue); 095 096 /** 097 * As with {@link #inject(Object)}, but the value is extracted from the {@link InstanceContext}. 098 * 099 * @return this field for further manipulation 100 */ 101 PlasticField injectFromInstanceContext(); 102 103 /** 104 * Intercepts all access to the field, replacing such access with calls on the conduit. Even access via 105 * the FieldHandle will instead delegate to the conduit. Once a conduit is provided, it is not possible 106 * to inject a value into the field. 107 * <p> 108 * Normally, once a conduit is in place, the field will never be actually read or written. This is problematic for 109 * debugging, so {@link TransformationOption#FIELD_WRITEBEHIND} is useful when operating in a non-production mode. 110 * 111 * @return the field for further manipulation 112 * @throws IllegalStateException 113 * if the field already has an injection or a conduit 114 * @return this field for further manipulation 115 */ 116 <F> PlasticField setConduit(FieldConduit<F> conduit); 117 118 /** 119 * Sets the conduit for the field to a value computed when the class is instantiated 120 * 121 * @param computedConduit 122 * object that will compute the actual conduit to be used 123 * @return this field for further manipulation 124 */ 125 <F> PlasticField setComputedConduit(ComputedValue<FieldConduit<F>> computedConduit); 126 127 /** 128 * Creates access to the field, using the default property name derived from the name of the field. 129 * The default property name is the same as the name of the field, but with any leading or trailing underscore 130 * characters removed (a common convention among some programmers). Also, strips leading "m_" from the field name 131 * (another common convention). 132 * 133 * @param accessType 134 * which methods to create 135 * @return the field for further manipulation 136 * @throws IllegalArgumentException 137 * if an accessor method to be created already exists (possibly inherited from a base class) 138 */ 139 PlasticField createAccessors(PropertyAccessType accessType); 140 141 /** 142 * Creates accessors, possibly replacing existing methods (or overriding methods from a super class). 143 * The method names consist of the property name, with its first character converted to upper-case, prefixed 144 * with "get" or "set". The accessor methods must not already exist. 145 * 146 * @param accessType 147 * which methods to create 148 * @param propertyName 149 * the name of the property (from which the names of the methods are generated) 150 * @return the field for further manipulation 151 * @throws IllegalArgumentException 152 * if an accessor method to be created already exists (possibly inherited from a base class) 153 */ 154 PlasticField createAccessors(PropertyAccessType accessType, String propertyName); 155 156 /** Returns the field's fully qualified generic type, or null if not defined. */ 157 String getGenericSignature(); 158 159 /** Returns the modifiers on the field. */ 160 int getModifiers(); 161 }