    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
    015import java.util.List;
    016
    017/**
    018 * A method of a {@linkplain PlasticClass transformed class}.
    019 *
    020 * No methods of this object should be invoked after the class transformation is
    021 * {@linkplain PlasticClassTransformation#createInstantiator() completed}.
    022 */
    023public interface PlasticMethod extends AnnotationAccess
    024{
    025    /**
    026     * Returns the PlasticClass containing this method.
    027     */
    028    PlasticClass getPlasticClass();
    029
    030    /**
    031     * Returns a representation of the method's name, return value, argument types, etc.
    032     */
    033    MethodDescription getDescription();
    034
    035    /**
    036     * Returns a handle that can be used to invoke a method of a transformed class instance.
    037     */
    038    MethodHandle getHandle();
    039
    040    /**
    041     * Clears the instructions for this method, and creates a new empty InstructionBuilder so that the implementation of
    042     * the method can be specified. This may be considered a kind of last resort when no other approach is sufficient.
    043     *
    044     * If the method is currently abstract, it will have its abstract flag cleared.
    045     *
    046     * If the method has advice, the advice is <em>not</em> lost but will instead wrap around the new method
    047     * implementation.
    048     *
    049     * @param callback
    050     *         passed the InstructionBuilder so that an implementation of the method can be created
    051     * @return this method, for further configuration
    052     */
    053    PlasticMethod changeImplementation(InstructionBuilderCallback callback);
    054
    055    /**
    056     * Adds advice to the method. Adding advice implicitly rewrites the implementation of the method (this occurs
    057     * inside at the end of the class transformation). When the method is invoked, control will flow
    058     * through the MethodAdvice <em>in the order they are added</em>. Each piece of advice will receive the
    059     * {@link MethodInvocation} and should invoke {@link MethodInvocation#proceed()} to pass control to the next piece
    060     * of advice (and ultimately, to the actual method invocation).
    061     *
    062     * If a method implementation is changed, using {@link #changeImplementation(InstructionBuilderCallback)}, that
    063     * change will be honored, but the logic will only be invoked at the end of the chain of MethodAdvice. Internally, a
    064     * new method is created with the same parameters, exceptions, return type and implementation (bytecode) as the
    065     * advised method, <em>then</em> the advised method's implementation is changed.
    066     *
    067     * Note additionally that a recursive method invocation will still invoke the MethodAdvice chain on each recursive
    068     * call (this is an intended side-effect of copying the exact bytecode of the method implementation.
    069     *
    070     * @param advice
    071     *         advice to add to the method
    072     * @return this method, for further configuration
    073     */
    074    PlasticMethod addAdvice(MethodAdvice advice);
    075
    076    /**
    077     * Changes the implementation of the method to delegate to the provided field. The field must implement the
    078     * correct interface (or extend the correct class). The original implementation of the method is lost,
    079     * though (as with {@link #changeImplementation(InstructionBuilderCallback)}), method advice is retained.
    080     *
    081     * @param field
    082     *         to delegate to
    083     * @return this method, for further configuration
    084     */
    085    PlasticMethod delegateTo(PlasticField field);
    086
    087    /**
    088     * Much like {@link #delegateTo(PlasticField)}, but the object to delegate to
    089     * is dynamically computed by another method of the class. The method should take no parameters
    090     * and must not return null, or throw any exceptions not compatible with the method being proxied.
    091     *
    092     * @param method
    093     *         to provide the dynamic delegate
    094     * @return this method, for further configuration
    095     */
    096    PlasticMethod delegateTo(PlasticMethod method);
    097
    098    /**
    099     * Returns access to the parameters of the method and, in particular,
    100     * the visible annotations on those parameters.
    101     */
    102    List<MethodParameter> getParameters();
    103
    104    /**
    105     * Returns true if the method is an override of a method from the parent class.
    106     *
    107     * @return true if the parent class contains a method with the name signature
    108     */
    109    boolean isOverride();
    110
    111    /**
    112     * Returns true if the method is abstract.
    113     *
    114     * @since 5.4
    115     */
    116    boolean isAbstract();
    117
    118    /**
    119     * Returns a short identifier for the method that includes the class name, the method name,
    120     * and the types of all parameters. This is often used when producing debugging output
    121     * about the method.
    122     *
    123     * @return short identifier
    124     * @see org.apache.tapestry5.plastic.MethodDescription#toShortString()
    125     */
    126    String getMethodIdentifier();
    127
    128    /**
    129     * Returns true if this method is type void.
    130     *
    131     * @return true for void methods.
    132     */
    133    boolean isVoid();
    134}