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    
015    package org.apache.tapestry.enhance;
016    
017    import java.util.List;
018    
019    import org.apache.hivemind.Location;
020    import 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     */
029    public 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    }