/*
@license.text@
 */
package com.hammurapi.common;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;

/**
 * Visits class hierarchy in the order: class, implemented
 * interfaces, superclass, superclass implemented interfaces, ...
 * java.lang.Object is always visited last.
 * @author Pavel Vlasov
 * @revision $Revision$
 */
public class ClassHierarchyVisitable implements Visitable<Class<?>> {
	private Class<?> clazz;
	
	public ClassHierarchyVisitable(Class<?> clazz) {
		this.clazz=clazz;
	}
	
	public boolean accept(Visitor<Class<?>> visitor) {
		LinkedList<Class<?>> queue=new LinkedList<Class<?>>();
		queue.add(clazz);
		Set<Class<?>> visited=new HashSet<Class<?>>();
		visited.add(Object.class);
		
		while (!queue.isEmpty()) {
			Class<?> currentClazz = queue.removeFirst();
			if (visitor.visit(currentClazz)) {
				Class<?>[] interfaces = currentClazz.getInterfaces();
				for (int i=0; i<interfaces.length; i++) {
					if (visited.add(interfaces[i])) {
						queue.add(interfaces[i]);
					}
				}
				
				Class<?> superclass = currentClazz.getSuperclass();
				if (superclass!=null && visited.add(superclass)) {
					queue.add(superclass);
				}
			} else {
				return false;
			}
		}
		
		return visitor.visit(Object.class);
	}

}
