package org.apache.maven.shared.utils.introspection;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Hashtable;
import java.util.Map;

/**
 * A cache of introspection information for a specific class instance.
 * Keys {@link java.lang.reflect.Method} objects by a concatenation of the
 * method name and the names of classes that make up the parameters.
 *
 * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
 * @author <a href="mailto:bob@werken.com">Bob McWhirter</a>
 * @author <a href="mailto:szegedia@freemail.hu">Attila Szegedi</a>
 * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
 * @version $Id$
 */
public class ClassMap
{
    private static final class CacheMiss
    {
    }

    private static final CacheMiss CACHE_MISS = new CacheMiss();

    private static final Object OBJECT = new Object();

    /**
     * Class passed into the constructor used to as
     * the basis for the Method map.
     */

    private final Class<?> clazz;

    /**
     * Cache of Methods, or CACHE_MISS, keyed by method
     * name and actual arguments used to find it.
     */
    private final Map<String, Object> methodCache = new Hashtable<String, Object>();

    private MethodMap methodMap = new MethodMap();

    /**
     * Standard constructor
     * @param clazz The class.
     */
    public ClassMap( Class<?> clazz )
    {
        this.clazz = clazz;
        populateMethodCache();
    }

    /**
     * @return the class object whose methods are cached by this map.
     */
    Class<?> getCachedClass()
    {
        return clazz;
    }

    /**
     * Find a Method using the methodKey
     * provided.
     * <p/>
     * Look in the methodMap for an entry.  If found,
     * it'll either be a CACHE_MISS, in which case we
     * simply give up, or it'll be a Method, in which
     * case, we return it.
     * <p/>
     * If nothing is found, then we must actually go
     * and introspect the method from the MethodMap.
     * @param name Method name.
     * @param params Method parameters.
     * @return The found method.
     * @throws MethodMap.AmbiguousException in case of duplicate methods.
     */
    public Method findMethod( String name, Object... params )
        throws MethodMap.AmbiguousException
    {
        String methodKey = makeMethodKey( name, params );
        Object cacheEntry = methodCache.get( methodKey );

        if ( cacheEntry == CACHE_MISS )
        {
            return null;
        }

        if ( cacheEntry == null )
        {
            try
            {
                cacheEntry = methodMap.find( name, params );
            }
            catch ( MethodMap.AmbiguousException ae )
            {
                /*
                 *  that's a miss :)
                 */

                methodCache.put( methodKey, CACHE_MISS );

                throw ae;
            }

            if ( cacheEntry == null )
            {
                methodCache.put( methodKey, CACHE_MISS );
            }
            else
            {
                methodCache.put( methodKey, cacheEntry );
            }
        }

        // Yes, this might just be null.

        return (Method) cacheEntry;
    }

    /**
     * Populate the Map of direct hits. These
     * are taken from all the public methods
     * that our class provides.
     */
    private void populateMethodCache()
    {

        /*
         *  get all publicly accessible methods
         */

        Method[] methods = getAccessibleMethods( clazz );

        /*
         * map and cache them
         */

        for ( Method method : methods )
        {
            /*
             *  now get the 'public method', the method declared by a
             *  public interface or class. (because the actual implementing
             *  class may be a facade...
             */

            Method publicMethod = getPublicMethod( method );

            /*
             *  it is entirely possible that there is no public method for
             *  the methods of this class (i.e. in the facade, a method
             *  that isn't on any of the interfaces or superclass
             *  in which case, ignore it.  Otherwise, map and cache
             */

            if ( publicMethod != null )
            {
                methodMap.add( publicMethod );
                methodCache.put( makeMethodKey( publicMethod ), publicMethod );
            }
        }
    }

    /**
     * Make a methodKey for the given method using
     * the concatenation of the name and the
     * types of the method parameters.
     */
    private String makeMethodKey( Method method )
    {
        Class<?>[] parameterTypes = method.getParameterTypes();

        StringBuilder methodKey = new StringBuilder( method.getName() );

        for ( Class<?> parameterType : parameterTypes )
        {
            /*
             * If the argument type is primitive then we want
             * to convert our primitive type signature to the
             * corresponding Object type so introspection for
             * methods with primitive types will work correctly.
             */
            if ( parameterType.isPrimitive() )
            {
                if ( parameterType.equals( Boolean.TYPE ) )
                {
                    methodKey.append( "java.lang.Boolean" );
                }
                else if ( parameterType.equals( Byte.TYPE ) )
                {
                    methodKey.append( "java.lang.Byte" );
                }
                else if ( parameterType.equals( Character.TYPE ) )
                {
                    methodKey.append( "java.lang.Character" );
                }
                else if ( parameterType.equals( Double.TYPE ) )
                {
                    methodKey.append( "java.lang.Double" );
                }
                else if ( parameterType.equals( Float.TYPE ) )
                {
                    methodKey.append( "java.lang.Float" );
                }
                else if ( parameterType.equals( Integer.TYPE ) )
                {
                    methodKey.append( "java.lang.Integer" );
                }
                else if ( parameterType.equals( Long.TYPE ) )
                {
                    methodKey.append( "java.lang.Long" );
                }
                else if ( parameterType.equals( Short.TYPE ) )
                {
                    methodKey.append( "java.lang.Short" );
                }
            }
            else
            {
                methodKey.append( parameterType.getName() );
            }
        }

        return methodKey.toString();
    }

    private static String makeMethodKey( String method, Object... params )
    {
        StringBuilder methodKey = new StringBuilder().append( method );

        for ( Object param : params )
        {
            Object arg = param;

            if ( arg == null )
            {
                arg = OBJECT;
            }

            methodKey.append( arg.getClass().getName() );
        }

        return methodKey.toString();
    }

    /**
     * Retrieves public methods for a class. In case the class is not
     * public, retrieves methods with same signature as its public methods
     * from public superclasses and interfaces (if they exist). Basically
     * upcasts every method to the nearest acccessible method.
     */
    private static Method[] getAccessibleMethods( Class<?> clazz )
    {
        Method[] methods = clazz.getMethods();

        /*
         *  Short circuit for the (hopefully) majority of cases where the
         *  clazz is public
         */

        if ( Modifier.isPublic( clazz.getModifiers() ) )
        {
            return methods;
        }

        /*
         *  No luck - the class is not public, so we're going the longer way.
         */

        MethodInfo[] methodInfos = new MethodInfo[methods.length];

        for ( int i = methods.length; i-- > 0; )
        {
            methodInfos[i] = new MethodInfo( methods[i] );
        }

        int upcastCount = getAccessibleMethods( clazz, methodInfos, 0 );

        /*
         *  Reallocate array in case some method had no accessible counterpart.
         */

        if ( upcastCount < methods.length )
        {
            methods = new Method[upcastCount];
        }

        int j = 0;
        for ( MethodInfo methodInfo : methodInfos )
        {
            if ( methodInfo.upcast )
            {
                methods[j++] = methodInfo.method;
            }
        }
        return methods;
    }

    /**
     * Recursively finds a match for each method, starting with the class, and then
     * searching the superclass and interfaces.
     *
     * @param clazz       Class to check
     * @param methodInfos array of methods we are searching to match
     * @param upcastCount current number of methods we have matched
     * @return count of matched methods
     */
    private static int getAccessibleMethods( Class<?> clazz, MethodInfo[] methodInfos, int upcastCount )
    {
        int l = methodInfos.length;

        /*
         *  if this class is public, then check each of the currently
         *  'non-upcasted' methods to see if we have a match
         */

        if ( Modifier.isPublic( clazz.getModifiers() ) )
        {
            for ( int i = 0; i < l && upcastCount < l; ++i )
            {
                try
                {
                    MethodInfo methodInfo = methodInfos[i];

                    if ( !methodInfo.upcast )
                    {
                        methodInfo.tryUpcasting( clazz );
                        upcastCount++;
                    }
                }
                catch ( NoSuchMethodException e )
                {
                    /*
                     *  Intentionally ignored - it means
                     *  it wasn't found in the current class
                     */
                }
            }

            /*
             *  Short circuit if all methods were upcast
             */

            if ( upcastCount == l )
            {
                return upcastCount;
            }
        }

        /*
         *   Examine superclass
         */

        Class<?> superclazz = clazz.getSuperclass();

        if ( superclazz != null )
        {
            upcastCount = getAccessibleMethods( superclazz, methodInfos, upcastCount );

            /*
             *  Short circuit if all methods were upcast
             */

            if ( upcastCount == l )
            {
                return upcastCount;
            }
        }

        /*
         *  Examine interfaces. Note we do it even if superclazz == null.
         *  This is redundant as currently java.lang.Object does not implement
         *  any interfaces, however nothing guarantees it will not in future.
         */

        Class<?>[] interfaces = clazz.getInterfaces();

        for ( int i = interfaces.length; i-- > 0; )
        {
            upcastCount = getAccessibleMethods( interfaces[i], methodInfos, upcastCount );

            /*
             *  Short circuit if all methods were upcast
             */

            if ( upcastCount == l )
            {
                return upcastCount;
            }
        }

        return upcastCount;
    }

    /**
     * For a given method, retrieves its publicly accessible counterpart.
     * This method will look for a method with same name
     * and signature declared in a public superclass or implemented interface of this
     * method's declaring class. This counterpart method is publicly callable.
     *
     * @param method a method whose publicly callable counterpart is requested.
     * @return the publicly callable counterpart method. Note that if the parameter
     *         method is itself declared by a public class, this method is an identity
     *         function.
     */
    private static Method getPublicMethod( Method method )
    {
        Class<?> clazz = method.getDeclaringClass();

        /*
         *   Short circuit for (hopefully the majority of) cases where the declaring
         *   class is public.
         */

        if ( ( clazz.getModifiers() & Modifier.PUBLIC ) != 0 )
        {
            return method;
        }

        return getPublicMethod( clazz, method.getName(), method.getParameterTypes() );
    }

    /**
     * Looks up the method with specified name and signature in the first public
     * superclass or implemented interface of the class.
     *
     * @param clazz      the class whose method is sought
     * @param name       the name of the method
     * @param paramTypes the classes of method parameters
     */
    private static Method getPublicMethod( Class<?> clazz, String name, Class<?>... paramTypes )
    {
        /*
         *  if this class is public, then try to get it
         */

        if ( ( clazz.getModifiers() & Modifier.PUBLIC ) != 0 )
        {
            try
            {
                return clazz.getMethod( name, paramTypes );
            }
            catch ( NoSuchMethodException e )
            {
                /*
                 *  If the class does not have the method, then neither its
                 *  superclass nor any of its interfaces has it so quickly return
                 *  null.
                 */
                return null;
            }
        }

        /*
         *  try the superclass
         */

        Class<?> superclazz = clazz.getSuperclass();

        if ( superclazz != null )
        {
            Method superclazzMethod = getPublicMethod( superclazz, name, paramTypes );

            if ( superclazzMethod != null )
            {
                return superclazzMethod;
            }
        }

        /*
         *  and interfaces
         */

        Class<?>[] interfaces = clazz.getInterfaces();

        for ( Class<?> anInterface : interfaces )
        {
            Method interfaceMethod = getPublicMethod( anInterface, name, paramTypes );

            if ( interfaceMethod != null )
            {
                return interfaceMethod;
            }
        }

        return null;
    }

    /**
     * Used for the iterative discovery process for public methods.
     */
    private static final class MethodInfo
    {
        Method method;

        String name;

        Class<?>[] parameterTypes;

        boolean upcast;

        MethodInfo( Method method )
        {
            this.method = null;
            name = method.getName();
            parameterTypes = method.getParameterTypes();
            upcast = false;
        }

        void tryUpcasting( Class<?> clazz )
            throws NoSuchMethodException
        {
            method = clazz.getMethod( name, parameterTypes );
            name = null;
            parameterTypes = null;
            upcast = true;
        }
    }
}
