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;
+		}
+	}
 }