All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.technophobia.substeps.execution.ImplementationCache Maven / Gradle / Ivy

package com.technophobia.substeps.execution;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import com.google.common.base.Functions;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.Maps;

/*
 *	Copyright Technophobia Ltd 2012
 *
 *   This file is part of Substeps.
 *
 *    Substeps is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU Lesser General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    Substeps is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public License
 *    along with Substeps.  If not, see .
 */
public class ImplementationCache implements MethodExecutor {

    private final Map, Object> instanceMap;


    public ImplementationCache() {
        instanceMap = Maps.newHashMap();
    }


    public void addImplementationClasses(final Class... implementationClasses) {

        if (implementationClasses != null) {
            for (final Class implementationClass : implementationClasses) {
                if (!instanceMap.containsKey(implementationClass)) {
                    instanceMap.put(implementationClass, instantiate(implementationClass));
                }
            }
        }
    }


    private Object instantiate(final Class implementationClass) {

        try {
            return implementationClass.newInstance();
        } catch (final InstantiationException ex) {
            throw new IllegalStateException("Could not create instance of " + implementationClass,
                    ex);
        } catch (final IllegalAccessException ex) {
            throw new IllegalStateException("Could not create instance of " + implementationClass,
                    ex);
        }
    }


    /*
     * (non-Javadoc)
     * 
     * @see
     * com.technophobia.substeps.execution.MethodExecutor#executeMethods(java
     * .util.List)
     */
    public void executeMethods(final List methods) throws Exception {

        for (final Method method : methods) {

            // TODO - curious about the findSuitableInstancesOf ? won't
            // method.getDeclaringClass be ok??

            for (final Object object : findSuitableInstancesOf(method.getDeclaringClass())) {

                method.invoke(object);

            }
        }
    }


    private Collection findSuitableInstancesOf(final Class methodClass) {
        final Collection> suitableClassDefs = Collections2.filter(instanceMap.keySet(),
                new Predicate>() {

                    public boolean apply(final Class instanceClass) {
                        return methodClass.isAssignableFrom(instanceClass);
                    }
                });

        return Collections2.transform(suitableClassDefs, Functions.forMap(instanceMap));
    }


    /*
     * (non-Javadoc)
     * 
     * @see
     * com.technophobia.substeps.execution.MethodExecutor#executeMethod(java
     * .lang.Class, java.lang.reflect.Method, java.lang.Object[])
     */
    public void executeMethod(final Class targetClass, final Method targetMethod,
            final Object[] methodArgs) throws IllegalArgumentException, IllegalAccessException,
            InvocationTargetException {

        addImplementationClasses(targetClass);

        if (methodArgs != null) {
            targetMethod.invoke(instanceMap.get(targetClass), methodArgs);
        } else {
            targetMethod.invoke(instanceMap.get(targetClass));
        }
    }

}