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 }