package com.revolsys.beans; import java.lang.reflect.Constructor; import java.util.HashMap; import java.util.Map; public class ClassClassRegistry<T> { /** The cache for super class matches. */ private final Map<Class<?>, Class<?>> findCache = new HashMap<>(); /** The registry of classes to values. */ private final Map<Class<?>, Class<?>> registry = new HashMap<>(); /** * Clear the cache used by the {@link ClassClassRegistry#findClass(Class)} * method. */ private void clearFindCache() { this.findCache.clear(); } /** * Find the value by class. If no direct match was found, a match for the * super class will be found until a match is found. Returns null if no match * was found on any super class. * * @param clazz The class. * @return The class if a match was found for this class or one of the super * classes or null if no match was found. */ public Class<?> findClass(final Class<?> clazz) { if (clazz == null) { return null; } else { Class<?> value = getClass(clazz); if (value == null) { value = this.findCache.get(clazz); if (value == null) { final Class<?> superClass = clazz.getSuperclass(); value = findClass(superClass); if (value != null) { this.findCache.put(clazz, value); } } } return value; } } /** * Get the value from the registry using the key. Returns null if an exact * match by class is not found. * * @param clazz The class. * @return The value, or null if no value has been registered for this class. */ public Class<?> getClass(final Class<?> clazz) { return this.registry.get(clazz); } public T newInstance(final Class<?> clazz, final Object... parameters) { final Class<?> instanceClazz = findClass(clazz); if (instanceClazz == null) { return null; } else { final Class<?>[] parameterClasses = new Class<?>[parameters.length]; for (int i = 0; i < parameters.length; i++) { final Object parameter = parameters[i]; final Class<?> paramaterClass = parameter.getClass(); parameterClasses[i] = paramaterClass; } try { final Constructor<?> constructor = instanceClazz.getConstructor(parameterClasses); return (T)constructor.newInstance(parameters); } catch (final Throwable t) { t.printStackTrace(); return null; } } } /** * Register the value for the specified class. * * @param clazz The class. * @param value The value. */ public void put(final Class<?> clazz, final Class<?> value) { if (getClass(clazz) != value) { this.registry.put(clazz, value); clearFindCache(); } } }