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    }