001    // Copyright 2004, 2005, 2006, 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    
015    package org.apache.tapestry5.ioc.services;
016    
017    import static org.apache.tapestry5.ioc.internal.util.CollectionFactory.newList;
018    import static org.apache.tapestry5.ioc.internal.util.CollectionFactory.newMap;
019    
020    import java.lang.reflect.Method;
021    import java.util.*;
022    
023    /**
024     * Utility used to iterate over the publically visible methods of a class or interface. The MethodIterator understands
025     * some complications that can occur when a class inherits the same method from multiple interfaces and with slightly
026     * different signatures (due to the fact that declared thrown exceptions can vary slightly for the "same" method).
027     * 
028     * @see org.apache.tapestry5.ioc.services.MethodSignature#isOverridingSignatureOf(MethodSignature)
029     * @deprecated In 5.3, to be removed in a later release
030     */
031    public class MethodIterator
032    {
033        private boolean toString;
034    
035        private int index = 0;
036    
037        private final int count;
038    
039        private final List<MethodSignature> signatures;
040    
041        private static final Comparator<MethodSignature> COMPARATOR = new Comparator<MethodSignature>()
042        {
043            public int compare(MethodSignature o1, MethodSignature o2)
044            {
045    
046                return o1.getName().compareTo(o2.getName());
047            }
048        };
049    
050        public MethodIterator(Class subjectClass)
051        {
052            Method[] methods = subjectClass.getMethods();
053    
054            Map<String, MethodSignature> map = newMap();
055    
056            for (int i = 0; i < methods.length; i++)
057                processMethod(methods[i], map);
058    
059            signatures = newList(map.values());
060            count = signatures.size();
061    
062            Collections.sort(signatures, COMPARATOR);
063        }
064    
065        private void processMethod(Method m, Map<String, MethodSignature> map)
066        {
067            toString |= ClassFabUtils.isToString(m);
068    
069            MethodSignature sig = new MethodSignature(m);
070            String uid = sig.getUniqueId();
071    
072            MethodSignature existing = map.get(uid);
073    
074            if (existing == null || sig.isOverridingSignatureOf(existing))
075                map.put(uid, sig);
076        }
077    
078        public boolean hasNext()
079        {
080            return index < count;
081        }
082    
083        /**
084         * Returns the next method (as a {@link MethodSignature}, returning null when all are exhausted. Each method
085         * signature is returned exactly once (even if the same method signature is defined in multiple inherited classes or
086         * interfaces). The method signatures returned in ascending order, according to the "natural ordering".
087         * 
088         * @throws NoSuchElementException
089         *             if there are no more signatures
090         */
091        public MethodSignature next()
092        {
093            if (index >= count)
094                throw new NoSuchElementException();
095    
096            return signatures.get(index++);
097        }
098    
099        /**
100         * Returns true if the method <code>public String toString()</code> is part of the interface. This will be known
101         * immediately after iterator contruction (it is not necessary to iterate the methods first).
102         */
103        public boolean getToString()
104        {
105            return toString;
106        }
107    }