class Drawers {

	@SuppressWarnings("unchecked")
	@Pure
	public static synchronized <T> Drawer<T> getDrawerFor(Class<? extends T> type) {
		assert type != null : AssertMessages.notNullParameter();
		try {
			assert getLock();
			final Drawer<?> bufferedType = buffer.get(type);
			Drawer<T> choice = null;
			if (bufferedType != null) {
				choice = (Drawer<T>) bufferedType;
			} else {
				final Iterator<Drawer<?>> iterator = getAllDrawers();
				Drawer<?> exactMatcherDrawer = null;
				Drawer<?> superMatcherDrawer = null;
				while (iterator.hasNext()) {
					final Drawer<?> drawer = iterator.next();
					final Class<?> drawerType = drawer.getPrimitiveType();
					if (exactMatcherDrawer != null) {
						// Drawer that is exactly matching the element type is already found.
						// If the new drawer is a subtype of the previous one, the new drawer is used.
						if (drawerType.equals(type)
							&& exactMatcherDrawer.getClass().isAssignableFrom(drawer.getClass())) {
							exactMatcherDrawer = drawer;
						}
					} else if (drawerType.equals(type)) {
						// First time a drawer that is exactly matching the element type was found.
						exactMatcherDrawer = drawer;
					} else if (drawerType.isAssignableFrom(type)) {
						// The new drawer is able to support the element type because it could
						// draw elements with a super type of the expected element type.
						// The best choice is the drawer that supports the lowest type into the type hierarchy.
						if (superMatcherDrawer == null
							|| (superMatcherDrawer.getPrimitiveType().isAssignableFrom(drawerType))) {
							superMatcherDrawer = drawer;
						}
					}
				}
				if (exactMatcherDrawer != null) {
					choice = (Drawer<T>) exactMatcherDrawer;
				} else if (superMatcherDrawer != null) {
					choice = (Drawer<T>) superMatcherDrawer;
				}
				// Memorize for further use.
				if (choice != null) {
					buffer.put(type, choice);
				}
			}
			return choice;
		} finally {
			assert releaseLock();
		}
	}

	private  Drawers();

}