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

brooklyn.entity.drivers.RegistryEntityDriverFactory Maven / Gradle / Ivy

There is a newer version: 0.7.0-M1
Show newest version
package brooklyn.entity.drivers;

import static com.google.common.base.Preconditions.checkNotNull;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.LinkedHashMap;
import java.util.Map;

import brooklyn.entity.Entity;
import brooklyn.location.Location;

import com.google.common.base.Objects;
import com.google.common.base.Throwables;

/**
 * A registry of driver classes, keyed off the driver-interface + location type it is for.
 * 
 * @author Aled Sage
 */
public class RegistryEntityDriverFactory implements EntityDriverManager {

    private final Map> registry = new LinkedHashMap>();

    @Override
    public  D build(DriverDependentEntity entity, Location location) {
        Class driverClass = lookupDriver(entity.getDriverInterface(), location);
        return newDriverInstance(driverClass, entity, location);
    }

    public boolean hasDriver(DriverDependentEntity entity, Location location) {
        return lookupDriver(entity.getDriverInterface(), location) != null;
    }

    public  void registerDriver(Class driverInterface, Class locationClazz, Class driverClazz) {
        synchronized (registry) {
            registry.put(new DriverLocationTuple(driverInterface, locationClazz), driverClazz);
        }
    }

    @SuppressWarnings("unchecked")
    private  Class lookupDriver(Class driverInterface, Location location) {
        synchronized (registry) {
            for (DriverLocationTuple contender : registry.keySet()) {
                if (contender.matches(driverInterface, location)) {
                    return (Class) registry.get(contender);
                }
            }
        }
        return null;
    }
    
    @SuppressWarnings({ "unchecked", "rawtypes" })
    private  Constructor getConstructor(Class driverClass) {
        for (Constructor constructor : driverClass.getConstructors()) {
            if (constructor.getParameterTypes().length == 2) {
                return constructor;
            }
        }

        //TODO:
        throw new RuntimeException(String.format("Class [%s] has no constructor with 2 arguments",driverClass.getName()));
    }

    private  D newDriverInstance(Class driverClass, Entity entity, Location location) {
        Constructor constructor = getConstructor(driverClass);
        try {
            constructor.setAccessible(true);
            return constructor.newInstance(entity, location);
        } catch (InstantiationException e) {
            throw Throwables.propagate(e);
        } catch (IllegalAccessException e) {
            throw Throwables.propagate(e);
        } catch (InvocationTargetException e) {
            throw Throwables.propagate(e);
        }
    }

    private static class DriverLocationTuple {
        private final Class driverInterface;
        private final Class locationClazz;
        
        public DriverLocationTuple(Class driverInterface, Class locationClazz) {
            this.driverInterface = checkNotNull(driverInterface, "driver interface");
            this.locationClazz = checkNotNull(locationClazz, "location class");
        }
        
        public boolean matches(Class driver, Location location) {
            return driverInterface.isAssignableFrom(driver) && locationClazz.isInstance(location);
        }
        
        @Override
        public int hashCode() {
            return Objects.hashCode(driverInterface, locationClazz);
        }
        
        @Override
        public boolean equals(Object other) {
            if (!(other instanceof DriverLocationTuple)) {
                return false;
            }
            DriverLocationTuple o = (DriverLocationTuple) other;
            return driverInterface.equals(o.driverInterface) && locationClazz.equals(o.locationClazz);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy