package eu.dnetlib.enabling.tools.registration;

import java.lang.annotation.Annotation;

import javax.jws.WebService;

/**
 * This service name resolver tries to find the real service name through various heuristics based on the existence of the WebService
 * annotation on some interface the service implements.
 * 
 * <p>
 * NOTE: The search for the interface is depth first on interfaces and then on subclasses.
 * </p>
 * 
 * @author marko
 * 
 */
public class InterfaceServiceNameResolver implements ServiceNameResolver {

	/**
	 * {@inheritDoc}
	 * 
	 * @see eu.dnetlib.enabling.tools.registration.ServiceNameResolver#getName(java.lang.Object)
	 */
	@Override
	public String getName(final Object service) {

		Class<?> res = findInterface(WebService.class, service.getClass());
		if (res == null) {
			res = service.getClass();
		}

		return getName(res);
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see eu.dnetlib.enabling.tools.registration.ServiceNameResolver#getName(java.lang.Class)
	 */
	@Override
	public String getName(final Class<?> iface) {
		return iface.getSimpleName();
	}

	/**
	 * recursively searches a given annotation and returns the class/interface which contains it.
	 * 
	 * @param <T>
	 *            annotation type
	 * @param annotation
	 *            annotation to search
	 * @param clazz
	 *            root of the class hierarchy.
	 * @return class which contains annotation 'annotation'
	 */
	private <T extends Annotation> Class<?> findInterface(final Class<T> annotation, final Class<?> clazz) {
		if (clazz == null) return null;

		final T ann = clazz.getAnnotation(annotation);
		if ((ann != null) && clazz.isInterface()) return clazz;

		for (Class<?> iface : clazz.getInterfaces()) {
			final Class<?> ires = findInterface(annotation, iface);
			if (ires != null) return ires;
		}

		final Class<?> sres = findInterface(annotation, clazz.getSuperclass());
		if (sres != null) return sres;

		return null;
	}

}
