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    package org.apache.tapestry.enhance;
015    
016    import org.apache.hivemind.ApplicationRuntimeException;
017    
018    import java.beans.Introspector;
019    import java.lang.reflect.Method;
020    
021    
022    /**
023     * Implementation of {@link ClassInspector} that can properly handle
024     * jre 1.5 generic types.
025     */
026    public class GenericsClassInspectorImpl implements ClassInspector
027    {
028    
029        /**
030         * {@inheritDoc}
031         */
032        public MethodSignature getMethodSignature(Class implementing, Method m)
033        {
034            return new GenericsMethodSignatureImpl(implementing, m);
035        }
036        
037        /**
038         * {@inheritDoc}
039         */
040        public MethodSignature getPropertyAccessor(Class type, String propertyName)
041        {
042            try {
043                Method[] props = type.getMethods();
044                Method match = null;
045                
046                for (int i=0; i < props.length; i++) {
047    
048                    String propName = getPropertyName(props[i]);
049    
050                    if (!propertyName.equals(propName)) {
051                        continue;
052                    }
053    
054                    // store for later retrieval if necessary
055                    if (match == null)
056                        match = props[i];
057                    
058                    // try to find read methods before resorting to write
059                    if (props[i].getReturnType() == void.class) {
060                        continue;
061                    }
062    
063                    return new GenericsMethodSignatureImpl(type, props[i]);
064                } 
065    
066                if (match != null)
067                    return new GenericsMethodSignatureImpl(type, match);
068    
069            } catch (Throwable t) {
070                
071                throw new ApplicationRuntimeException("Error reading property " + propertyName + " from base class : " + type, t);
072            }
073            
074            return null;
075        }
076    
077        static String getPropertyName(Method m)
078        {
079            String name = m.getName();
080    
081            if (name.startsWith("get"))
082                name = name.substring(3);
083            else if (name.startsWith("set"))
084                name = name.substring(3);
085            else if (name.startsWith("is"))
086                name = name.substring(2);
087    
088            return Introspector.decapitalize(name);
089        }
090    }