001    // Copyright 2006, 2007 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.internal.services;
016    
017    import org.apache.tapestry5.ioc.services.MethodSignature;
018    
019    /**
020     * Used by {@link org.apache.tapestry5.ioc.internal.services.PipelineBuilderImpl} to analyze service interface methods
021     * against filter interface methods to find the position of the extra service parameter (in the filter method).
022     */
023    public class FilterMethodAnalyzer
024    {
025        private final Class serviceInterface;
026    
027        FilterMethodAnalyzer(Class serviceInterface)
028        {
029            this.serviceInterface = serviceInterface;
030        }
031    
032        public int findServiceInterfacePosition(MethodSignature ms, MethodSignature fms)
033        {
034            if (ms.getReturnType() != fms.getReturnType()) return -1;
035    
036            if (!ms.getName().equals(fms.getName())) return -1;
037    
038            Class[] filterParameters = fms.getParameterTypes();
039            int filterParameterCount = filterParameters.length;
040            Class[] serviceParameters = ms.getParameterTypes();
041    
042            if (filterParameterCount != (serviceParameters.length + 1)) return -1;
043    
044            // TODO: check compatible exceptions!
045    
046            // This needs work; it assumes the first occurance of the service interface
047            // in the filter interface method signature is the right match. That will suit
048            // most of the time.
049    
050            boolean found = false;
051            int result = -1;
052    
053            for (int i = 0; i < filterParameterCount; i++)
054            {
055                if (filterParameters[i] == serviceInterface)
056                {
057                    result = i;
058                    found = true;
059                    break;
060                }
061            }
062    
063            if (!found) return -1;
064    
065            // Check that all the parameters before and after the service interface still
066            // match.
067    
068            for (int i = 0; i < result; i++)
069            {
070                if (filterParameters[i] != serviceParameters[i]) return -1;
071            }
072    
073            for (int i = result + 1; i < filterParameterCount; i++)
074            {
075                if (filterParameters[i] != serviceParameters[i - 1]) return -1;
076            }
077    
078            return result;
079        }
080    
081    }