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