    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}