    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    }