/*******************************************************************************
* Copyright (c) 2012 itemis AG (http://www.itemis.eu) 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
*******************************************************************************/
package org.xpect.util;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;
import com.google.common.collect.Lists;
/**
* @author Moritz Eysholdt - Initial contribution and API
*/
public class AnnotationUtil {
@SuppressWarnings("unchecked")
public static <T> T newInstance(Class<T> type, Class<?> declarator, Annotation annotation) throws IllegalAccessException {
if (declarator != null)
try {
Constructor<?> c = type.getDeclaredConstructor(declarator.getClass(), annotation.annotationType());
c.setAccessible(true);
if (c != null)
return (T) c.newInstance(declarator, annotation);
} catch (SecurityException e) {
} catch (NoSuchMethodException e) {
} catch (InstantiationException e) {
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
try {
Constructor<?> c = type.getConstructor(annotation.annotationType());
if (c != null)
return (T) c.newInstance(annotation);
} catch (SecurityException e) {
} catch (NoSuchMethodException e) {
} catch (InstantiationException e) {
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
try {
Constructor<?> c = type.getConstructor();
if (c != null)
return (T) c.newInstance();
} catch (SecurityException e) {
} catch (NoSuchMethodException e) {
} catch (InstantiationException e) {
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
return null;
}
public static <T> List<T> newInstancesViaMetaAnnotation(Class<?> declarator, Class<? extends Annotation> metaAnnotationClass, Class<T> expected) {
List<T> result = Lists.newArrayList();
for (Annotation annotation : declarator.getAnnotations()) {
Annotation metaAnnotation = annotation.annotationType().getAnnotation(metaAnnotationClass);
T r = newInstanceViaAnnotation(declarator, metaAnnotation, expected, annotation);
if (r != null)
result.add(r);
}
return result;
}
public static <T> List<T> newInstancesViaMetaAnnotation(Method declarator, Class<? extends Annotation> metaAnnotationClass, Class<T> expected) {
List<T> result = Lists.newArrayList();
for (Annotation annotation : declarator.getAnnotations()) {
Annotation metaAnnotation = annotation.annotationType().getAnnotation(metaAnnotationClass);
T r = newInstanceViaAnnotation(null, metaAnnotation, expected, annotation);
if (r != null)
result.add(r);
}
return result;
}
public static <T> List<T> newInstancesViaMetaAnnotation(Method declarator, int paramIndex, Class<? extends Annotation> metaAnnotationClass, Class<T> expected) {
List<T> result = Lists.newArrayList();
Annotation[][] annotations = declarator.getParameterAnnotations();
if (paramIndex >= 0 && paramIndex < annotations.length)
for (Annotation annotation : annotations[paramIndex]) {
Annotation metaAnnotation = annotation.annotationType().getAnnotation(metaAnnotationClass);
T r = newInstanceViaAnnotation(null, metaAnnotation, expected, annotation);
if (r != null)
result.add(r);
}
return result;
}
@SuppressWarnings("unchecked")
public static <T> T newInstanceViaAnnotation(Class<?> declarator, Annotation annotation, Class<T> expected, Annotation parameter) {
if (annotation != null)
for (Method f : annotation.annotationType().getDeclaredMethods())
if (f.getReturnType() == Class.class) {
try {
Object objtype = f.invoke(annotation);
if (objtype instanceof Class<?> && expected.isAssignableFrom((Class<?>) objtype)) {
T result = newInstance((Class<T>) objtype, declarator, parameter);
if (result != null)
return result;
}
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
return null;
}
public static <T> T newInstanceViaAnnotation(Class<?> declarator, Class<? extends Annotation> AnnotationClass, Class<T> expected) {
Annotation annotation = declarator.getAnnotation(AnnotationClass);
return newInstanceViaAnnotation(declarator, annotation, expected, annotation);
}
public static <T> T newInstanceViaMetaAnnotation(Class<?> declarator, Class<? extends Annotation> metaAnnotationClass, Class<T> expected) {
for (Annotation annotation : declarator.getAnnotations()) {
Annotation metaAnnotation = annotation.annotationType().getAnnotation(metaAnnotationClass);
T r = newInstanceViaAnnotation(declarator, metaAnnotation, expected, annotation);
if (r != null)
return r;
}
return null;
}
public static <T extends Annotation> T newInstanceWithDefaults(Class<T> annotationType) {
Object proxy = Proxy.newProxyInstance(annotationType.getClassLoader(), new Class<?>[] { annotationType }, new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.getDefaultValue();
}
});
return annotationType.cast(proxy);
}
}