    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
    015package 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 */
    022public 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}