/*
* Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* bstefanescu
*/
package org.eclipse.ecr.testlib.runner;
import java.lang.annotation.Annotation;
import java.lang.annotation.Inherited;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
*/
public class AnnotationScanner {
protected final Map<Class<?>, List<Annotation>> classes = new Hashtable<Class<?>, List<Annotation>>();
public synchronized void scan(Class<?> clazz) {
if (classes.containsKey(clazz)) {
return;
}
List<Annotation> result = new ArrayList<Annotation>();
Set<Class<?>> visitedClasses = new HashSet<Class<?>>();
collectAnnotations(clazz, result, visitedClasses);
}
public List<? extends Annotation> getAnnotations(Class<?> clazz) {
return classes.get(clazz);
}
public <T extends Annotation> T getFirstAnnotation(Class<?> clazz, Class<T> annotationType) {
List<T> result = getAnnotations(clazz, annotationType);
if (result != null && !result.isEmpty()) {
return result.get(0);
}
return null;
}
@SuppressWarnings("unchecked")
public <T extends Annotation> List<T> getAnnotations(Class<?> clazz, Class<T> annotationType) {
List<Annotation> list = classes.get(clazz);
if (list != null) {
List<T> result = new ArrayList<T>();
for (Annotation anno : list) {
if (anno.annotationType() == annotationType) {
result.add((T)anno);
}
}
return result;
}
return null;
}
/**
* TODO when collecting annotations annotated with {@link Inherited} they will be collected twice.
* @param clazz
* @param result
* @param visitedClasses
*/
protected void collectAnnotations(Class<?> clazz, List<Annotation> result, Set<Class<?>> visitedClasses) {
if (visitedClasses.contains(clazz)) {
return;
}
visitedClasses.add(clazz);
List<Annotation> partialResult = new ArrayList<Annotation>(); // collect only the annotation on this class
List<Annotation> annos = classes.get(clazz);
if (annos != null) {
result.addAll(annos);
return;
}
// collect local annotations
for (Annotation anno : clazz.getAnnotations()) {
partialResult.add(anno);
}
// first scan interfaces
for (Class<?> itf : clazz.getInterfaces()) {
collectAnnotations(itf, partialResult, visitedClasses);
}
// collect annotations from super classes
Class<?> superClass = clazz.getSuperclass();
if (superClass != null) {
collectAnnotations(superClass, partialResult, visitedClasses);
}
if (!partialResult.isEmpty()) {
result.addAll(partialResult);
}
classes.put(clazz, partialResult);
}
}