001// Copyright 2004, 2005 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.tapestry.enhance;
016
017import java.util.List;
018
019import org.apache.hivemind.Location;
020import org.apache.hivemind.service.MethodSignature;
021
022/**
023 * A process object representing enhancements to a component class. The operation is passed to
024 * {@link org.apache.tapestry.enhance.EnhancementWorker}objects that perform enhancements.
025 * 
026 * @author Howard M. Lewis Ship
027 * @since 4.0
028 */
029public interface EnhancementOperation
030{
031    /**
032     * Claims a property. Most enhancements are concerned with adding properties. Some enhancement
033     * workers exist to fill in defaults, and they need to know what properties have already been
034     * spoken for by eariler enhancement works.
035     * 
036     * @throws org.apache.hivemind.ApplicationRuntimeException
037     *             if the property was previously claimed
038     */
039
040    public void claimProperty(String propertyName);
041
042    /**
043     * Claims a property as read-only. This will check to see if the property has an abstract setter
044     * method.
045     * 
046     * @throws org.apache.hivemind.ApplicationRuntimeException
047     *             if the property was previously claimed, or if the property includes an accessor
048     *             method.
049     */
050    
051    public void claimReadonlyProperty(String propertyName);
052
053    /**
054     * Returns a list of the names of existing properties that are not claimed and which have
055     * abstract accessor methods.
056     */
057
058    public List findUnclaimedAbstractProperties();
059
060    /**
061     * Adds a field to the enhanced class; the field will be private and use the provided name and
062     * type.
063     */
064
065    public void addField(String name, Class type);
066
067    /**
068     * Adds a field containing an initial value, which is injected into the class via its fabricated
069     * constructor. This method may be called multiple times with the same value and will return the
070     * same variable name (an identity map is kept internally).
071     * 
072     * @param fieldName
073     *            The default name for the field, used if a new field (and contructor argument) is
074     *            being created. Only used if a field for the value doesn't exist.
075     * @param fieldType
076     *            The type of the field to be created.
077     * @param value
078     *            the value to be referenced, which may not be null
079     * @return the name of the field containing the value. This may or may not match fieldName. The
080     *         provided fieldName may be modified to prevent naming conflicts.
081     */
082
083    public String addInjectedField(String fieldName, Class fieldType, Object value);
084
085    /**
086     * Converts a type name (an object class name, a primtive name, or an array) into the
087     * corresponding Class object.
088     */
089
090    public Class convertTypeName(String type);
091
092    /**
093     * Confirms that the named property either doesn't exist (in the component base class), or that
094     * the type of the property exactly matches the indicated type.
095     */
096
097    public void validateProperty(String name, Class expectedType);
098
099    /**
100     * Returns the name of the accessor method for the given property (if it exists in the component
101     * base class), or fabricates a new name if it does not.
102     */
103
104    public String getAccessorMethodName(String propertyName);
105
106    /**
107     * Adds a method to the enhanced class.
108     * 
109     * @param modifier
110     *            as defined by {@link java.lang.reflect.Modifier}, typically
111     *            {@link java.lang.reflect.Modifier#PUBLIC}
112     * @param sig
113     *            the method signature (defining name, return type, etc.)
114     * @param methodBody
115     *            a Javassist code snippet for the method body
116     * @param location
117     *            a location used to identify "why" the method was added; the location may later be
118     *            used to describe conflicts. May not be null.
119     */
120    public void addMethod(int modifier, MethodSignature sig, String methodBody, Location location);
121
122    /**
123     * Returns the base component class, as defined in the specification (or defaulted). An enhaced
124     * subclass of the component class will usually be created.
125     */
126    public Class getBaseClass();
127
128    /**
129     * Returns a reference to a particular class. This will, effectively, by the name of a private
130     * field.
131     */
132
133    public String getClassReference(Class clazz);
134
135    /**
136     * Returns the type of an existing property of the base component class. If the property does
137     * not exist, then returns null.
138     */
139
140    public Class getPropertyType(String name);
141
142    /**
143     * Allows for a kind of distributed construction of a particular method, within a particular
144     * interface. Code can be appended to the method's implementation throughout the course of the
145     * enhancement operation. When the enhanced class is finialized, the method is added with
146     * whatever contents are in its body. If the base class implements the method, then the method
147     * body will include an initial call to that implementation.
148     * <p>
149     * At this time, this works best for void methods (since there isn't an easy way to ensure code
150     * would be inserted before a final return statement).
151     * 
152     * @param interfaceClass
153     *            the interface containing the method. If the base class does not implement the
154     *            interface, then the enhanced class will have the interface added.
155     * @param methodSignature
156     *            the signature of the method to be added.
157     * @param code
158     *            the Javassist markup to be added to the body of the method.
159     */
160    public void extendMethodImplementation(Class interfaceClass, MethodSignature methodSignature,
161            String code);
162
163    /**
164     * Returns true if the class implements the specified interface. Checks the base class (as
165     * identified in the specification), but <em>also</em> accounts for any additional interfaces
166     * that may be added by {@link #extendMethodImplementation(Class, MethodSignature, String)}.
167     */
168
169    public boolean implementsInterface(Class interfaceClass);
170}