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.hivemind.service;
016    
017    import java.lang.reflect.Method;
018    import java.util.ArrayList;
019    import java.util.HashMap;
020    import java.util.List;
021    import java.util.Map;
022    import java.util.NoSuchElementException;
023    
024    import org.apache.hivemind.util.Defense;
025    
026    /**
027     * Utility used to iterate over the visible methods of a class.
028     * 
029     * @author Howard Lewis Ship
030     */
031    public class MethodIterator
032    {
033        private boolean _toString;
034    
035        private int _index = 0;
036    
037        /** @since 1.1 */
038        private int _count;
039    
040        /** @since 1.1 */
041        private List _signatures;
042    
043        public MethodIterator(Class subjectClass)
044        {
045            Defense.notNull(subjectClass, "subjectClass");
046    
047            Method[] methods = subjectClass.getMethods();
048    
049            Map map = new HashMap();
050    
051            for (int i = 0; i < methods.length; i++)
052                processMethod(methods[i], map);
053    
054            _signatures = new ArrayList(map.values());
055            _count = _signatures.size();
056        }
057    
058        /** @since 1.1 */
059        private void processMethod(Method m, Map map)
060        {
061            _toString |= ClassFabUtils.isToString(m);
062    
063            MethodSignature sig = new MethodSignature(m);
064            String uid = sig.getUniqueId();
065    
066            MethodSignature existing = (MethodSignature) map.get(uid);
067    
068            if (existing == null || sig.isOverridingSignatureOf(existing))
069                map.put(uid, sig);
070        }
071    
072        public boolean hasNext()
073        {
074            return _index < _count;
075        }
076    
077        /**
078         * Returns the next method (as a {@link MethodSignature}, returning null when all are
079         * exhausted. Each method signature is returned exactly once (even if the same method signature
080         * is defined in multiple inherited classes or interfaces). The order in which method signatures
081         * are returned is not specified.
082         * 
083         * @throws NoSuchElementException
084         *             if there are no more signatures
085         */
086        public MethodSignature next()
087        {
088            if (_index >= _count)
089                throw new NoSuchElementException();
090    
091            return (MethodSignature) _signatures.get(_index++);
092        }
093    
094        /**
095         * Returns true if the method <code>public String toString()</code> is part of the interface.
096         */
097        public boolean getToString()
098        {
099            return _toString;
100        }
101    }