/**
 *        Licensed to the Apache Software Foundation (ASF) under one
 *        or more contributor license agreements.  See the NOTICE file
 *        distributed with this work for additional information
 *        regarding copyright ownership.  The ASF licenses this file
 *        to you under the Apache License, Version 2.0 (the
 *        "License"); you may not use this file except in compliance
 *        with the License.  You may obtain a copy of the License at
 *
 *          http://www.apache.org/licenses/LICENSE-2.0
 *
 *        Unless required by applicable law or agreed to in writing,
 *        software distributed under the License is distributed on an
 *        "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *        KIND, either express or implied.  See the License for the
 *        specific language governing permissions and limitations
 *        under the License.
 *
 */
package com.intelligentsia.dowsers.entity.reference;

import java.lang.reflect.Proxy;
import java.util.Iterator;
import java.util.ServiceLoader;

import com.intelligentsia.dowsers.entity.Entity;
import com.intelligentsia.dowsers.entity.EntityProxy;

/**
 * References generate {@link Entity} or attribute's {@link Entity} reference.
 * 
 * @author <a href="mailto:jguibert@intelligents-ia.com" >Jerome Guibert</a>
 */
public enum References {
	;

	/**
	 * {@link ReferenceFactory} instance.
	 */
	private static ReferenceFactory REFERENCE_FACTORY = lookup(Thread.currentThread().getContextClassLoader());

	/**
	 * Generate new References using configured {@link ReferenceFactory}
	 * provider.
	 * 
	 * @param clazz
	 *            entity class name
	 * @return an new {@link Reference} for specified class name
	 */
	public static Reference newReference(final Class<?> clazz) {
		return REFERENCE_FACTORY.newReference(clazz);
	}

	/**
	 * Obtain a {@link Reference} on an {@link Entity} representation
	 * 
	 * @param any
	 * @return an new {@link Reference} on specified entity
	 * @throws {@link IllegalArgumentException} if any is not an entity
	 *         representation
	 */
	public static Reference identify(final Object any) throws IllegalArgumentException {
		if (Proxy.isProxyClass(any.getClass())) {
			final EntityProxy entityProxy = (EntityProxy) Proxy.getInvocationHandler(any);
			return entityProxy.identity();
		}
		if (EntityProxy.class.isAssignableFrom(any.getClass())) {
			final EntityProxy entityProxy = (EntityProxy) any;
			return entityProxy.identity();
		}
		if (Entity.class.isAssignableFrom(any.getClass())) {
			final Entity entity = (Entity) any;
			return entity.identity();
		}
		throw new IllegalArgumentException("Argument is not an entity");
	}

	/**
	 * Try to locate a ReferenceFactory implementation using specific class
	 * loader.
	 * 
	 * @param classLoader
	 * @return a ReferenceFactory instance or null or none was found.
	 */
	private static ReferenceFactory lookup(final ClassLoader classLoader) {
		final ServiceLoader<ReferenceFactory> loader = ServiceLoader.load(ReferenceFactory.class, classLoader);
		final Iterator<ReferenceFactory> iterator = loader.iterator();
		ReferenceFactory factory = null;
		while ((factory == null) && iterator.hasNext()) {
			try {
				factory = iterator.next();
			} catch (final Throwable e) {
			}
		}
		if (factory == null) {
			throw new RuntimeException("No ReferenceFactory Implementation found");
			// factory = new ReferenceFactoryProvider();
		}
		return factory;
	}
}

@@ -1926,16 +1926,64 @@
 ram any%0A
+%09 *            an %7B@link Entity%7D representation%0A
 %09 * @ret
@@ -2027,24 +2027,24 @@
 fied entity%0A
-
 %09 * @throws 
@@ -2218,16 +2218,396 @@
 ption %7B%0A
+%09%09return discover(any).identity();%0A%09%7D%0A%0A%09/**%0A%09 * Discover underlying %7B@link Entity%7D instance.%0A%09 * %0A%09 * @param any%0A%09 *            an %7B@link Entity%7D representation%0A%09 * @return an %7B@link Entity%7D instance%0A%09 * @throws IllegalArgumentException%0A%09 *             if any is not an entity representation%0A%09 */%0A%09public static Entity discover(final Object any) throws IllegalArgumentException %7B%0A
 %09%09if (Pr
@@ -2741,35 +2741,24 @@
  entityProxy
-.identity()
 ;%0A%09%09%7D%0A%09%09if (
@@ -2886,27 +2886,16 @@
 ityProxy
-.identity()
 ;%0A%09%09%7D%0A%09%09
@@ -2978,32 +2978,32 @@
 = (Entity) any;%0A
+
 %09%09%09return entity
@@ -3002,27 +3002,16 @@
 n entity
-.identity()
 ;%0A%09%09%7D%0A%09%09

add discover on References