/** * */ package cz.cuni.mff.peckam.java.origamist.services; import java.util.Hashtable; import java.util.concurrent.Callable; import org.apache.log4j.Logger; /** * This class serves as a pool of implementations of available services * * This is a "static" class - no instance can be created * * @author Martin Pecka * */ public class ServiceLocator { /** * Disables instance creation */ private ServiceLocator() { } /** * Storage for the implementations */ protected final static Hashtable<Class<?>, Object> services = new Hashtable<Class<?>, Object>(); /** Storage for callbacks returning the services. */ protected final static Hashtable<Class<?>, Callable<?>> serviceGetters = new Hashtable<Class<?>, Callable<?>>(); /** * Adds a new service for type T and stores its implementation. * * @param <T> The service type. * @param service The Class of the service to add. * @param implementation Its implementation. */ public static <T> void add(Class<T> service, T implementation) { services.put(service, implementation); } /** * Adds a new service for type T and saves the callback to instantiate the service. * * @param <T> The service type. * @param service The Class of the service to add. * @param serviceGetter The callback returning the service. */ public static <T> void add(Class<T> service, Callable<? extends T> serviceGetter) { serviceGetters.put(service, serviceGetter); } /** * Returns the implementation of the service. * * @param <T> The service type * @param service The Class of the service to get * @return Implementation of the service */ @SuppressWarnings("unchecked") public static <T> T get(Class<T> service) { try { Object found = services.get(service); if (found != null) return (T) found; Callable<?> getter = serviceGetters.get(service); if (getter != null) { try { found = getter.call(); services.put(service, found); } catch (Exception e) { Logger.getLogger(ServiceLocator.class).error("Service getting callback threw exception.", e); } finally { serviceGetters.remove(getter); } return (T) found; } return null; } catch (ClassCastException e) { return null; } } /** * Removes implementation of the given service * * @param <T> The service type * @param service The service to remove */ public static <T> void remove(Class<T> service) { if (services.remove(service) == null) serviceGetters.remove(service); } }