Mercurial > jhg
diff src/org/tmatesoft/hg/util/Adaptable.java @ 356:91d75e1bac9f
Consistent approach to deal with adaptable objects. Give adaptable precedence over instanceof to allow conditional response when classes do implement desired interface
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Tue, 06 Dec 2011 14:25:52 +0100 |
parents | 1a7a9a20e1f9 |
children |
line wrap: on
line diff
--- a/src/org/tmatesoft/hg/util/Adaptable.java Tue Dec 06 12:57:21 2011 +0100 +++ b/src/org/tmatesoft/hg/util/Adaptable.java Tue Dec 06 14:25:52 2011 +0100 @@ -25,4 +25,44 @@ public interface Adaptable { <T> T getAdapter(Class<T> adapterClass); + + class Factory<T> { + + private final Class<T> adapterClass; + + public Factory(Class<T> adapterClass) { + assert adapterClass != null; + this.adapterClass = adapterClass; + } + + public T get(Object target) { + return getAdapter(target, adapterClass, null); + } + + public T get(Object target, T defaultValue) { + return getAdapter(target, adapterClass, defaultValue); + } + + /** + * Try to adapt target to specified class, resort to defaultValue when not possible. + * Instance lookup order is as follows: first, target is checked for being {@link Adaptable} and, if yes, + * consulted for adapter. Then, plain {@link Class#isInstance(Object) instanceof} checks if target itself is + * of desired type. {@link Adaptable} check comes first to allow classed that are in fact <code>instanceof</code> + * desired type to respond to the demand conditionally + * + * @param target object to adapt, <code>null</code> value, although meaningless, is tolerable. + * @param adapterClass desired target class + * @param defaultValue value to use if target cannot be adapted to desired class, may be <code>null</code> + * @return instance of the desired class + */ + public static <C> C getAdapter(Object target, Class<C> adapterClass, C defaultValue) { + if (target instanceof Adaptable) { + return ((Adaptable) target).getAdapter(adapterClass); + } + if (adapterClass.isInstance(target)) { + return adapterClass.cast(target); + } + return defaultValue; + } + } }