/*
* Copyright 2016, Stuart Douglas, and individual contributors as indicated
* by the @authors tag.
*
* Licensed 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 org.fakereplace.reflection;
import java.lang.annotation.Annotation;
import java.lang.annotation.Inherited;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import org.fakereplace.data.AnnotationDataStore;
import org.fakereplace.data.ModifiedMethod;
public class AnnotationReflection {
private static boolean heiracheyChanged(Class<?> clazz) {
Class<?> c = clazz;
while (c != Object.class && c != null) {
if (AnnotationDataStore.isClassDataRecorded(c)) {
return true;
}
c = c.getSuperclass();
}
return false;
}
public static boolean isAnnotationPresent(Class<?> clazz, Class anType) {
if (anType.isAnnotationPresent(Inherited.class) && heiracheyChanged(clazz)) {
Class<?> c = clazz;
while (c != null && c != Object.class) {
if (AnnotationDataStore.isClassDataRecorded(c)) {
if (AnnotationDataStore.isClassAnnotationPresent(c, anType)) {
return true;
}
} else {
// can't just use getAnnotation, as an inherited annotation
// may have been removed from a parent class
Annotation[] declared = c.getDeclaredAnnotations();
for (Annotation a : declared) {
if (a.annotationType() == anType) {
return true;
}
}
}
c = c.getSuperclass();
}
return false;
} else if (AnnotationDataStore.isClassDataRecorded(clazz)) {
return AnnotationDataStore.isClassAnnotationPresent(clazz, anType);
}
return clazz.isAnnotationPresent(anType);
}
public static Annotation getAnnotation(Class<?> clazz, Class anType) {
if (anType.isAnnotationPresent(Inherited.class) && heiracheyChanged(clazz)) {
Annotation result = null;
Class<?> c = clazz;
while (result == null && c != null && c != Object.class) {
if (AnnotationDataStore.isClassDataRecorded(c)) {
result = AnnotationDataStore.getClassAnnotation(c, anType);
} else {
// can't just use getAnnotation, as an inherited annotation
// may have been removed from a parent class
Annotation[] declared = c.getDeclaredAnnotations();
for (Annotation a : declared) {
if (a.annotationType() == anType) {
result = a;
break;
}
}
}
c = c.getSuperclass();
}
return result;
} else if (AnnotationDataStore.isClassDataRecorded(clazz)) {
return AnnotationDataStore.getClassAnnotation(clazz, anType);
}
return clazz.getAnnotation(anType);
}
public static Annotation[] getAnnotations(Class<?> clazz) {
if (heiracheyChanged(clazz)) {
Annotation[] pres;
if (AnnotationDataStore.isClassDataRecorded(clazz)) {
pres = AnnotationDataStore.getClassAnnotations(clazz);
} else {
pres = clazz.getDeclaredAnnotations();
}
List<Annotation> result = new ArrayList<Annotation>();
for (Annotation a : pres) {
result.add(a);
}
Class<?> c = clazz.getSuperclass();
while (c != Object.class && c != null) {
if (AnnotationDataStore.isClassDataRecorded(c)) {
pres = AnnotationDataStore.getClassAnnotations(c);
} else {
pres = c.getDeclaredAnnotations();
}
for (Annotation a : pres) {
if (a.annotationType().isAnnotationPresent(Inherited.class)) {
result.add(a);
}
}
c = c.getSuperclass();
}
Annotation[] ret = new Annotation[result.size()];
int count = 0;
for (Annotation a : result) {
ret[count++] = a;
}
return ret;
}
return clazz.getAnnotations();
}
public static Annotation[] getDeclaredAnnotations(Class<?> clazz) {
if (AnnotationDataStore.isClassDataRecorded(clazz)) {
Annotation[] result = AnnotationDataStore.getClassAnnotations(clazz);
return result;
}
return clazz.getDeclaredAnnotations();
}
public static boolean isAnnotationPresent(Field clazz, Class anType) {
if (AnnotationDataStore.isFieldDataRecorded(clazz)) {
boolean result = AnnotationDataStore.isFieldAnnotationPresent(clazz, anType);
return result;
}
return clazz.isAnnotationPresent(anType);
}
public static Annotation getAnnotation(Field clazz, Class anType) {
if (AnnotationDataStore.isFieldDataRecorded(clazz)) {
Annotation result = AnnotationDataStore.getFieldAnnotation(clazz, anType);
return result;
}
return clazz.getAnnotation(anType);
}
public static Annotation[] getAnnotations(Field clazz) {
if (AnnotationDataStore.isFieldDataRecorded(clazz)) {
Annotation[] result = AnnotationDataStore.getFieldAnnotations(clazz);
return result;
}
return clazz.getAnnotations();
}
public static Annotation[] getDeclaredAnnotations(Field clazz) {
if (AnnotationDataStore.isFieldDataRecorded(clazz)) {
Annotation[] result = AnnotationDataStore.getFieldAnnotations(clazz);
return result;
}
return clazz.getDeclaredAnnotations();
}
public static boolean isAnnotationPresent(Method clazz, Class anType) {
if (AnnotationDataStore.isMethodDataRecorded(clazz)) {
boolean result = AnnotationDataStore.isMethodAnnotationPresent(clazz, anType);
return result;
}
return clazz.isAnnotationPresent(anType);
}
public static Annotation getAnnotation(Method clazz, Class anType) {
if (AnnotationDataStore.isMethodDataRecorded(clazz)) {
Annotation result = AnnotationDataStore.getMethodAnnotation(clazz, anType);
return result;
}
return clazz.getAnnotation(anType);
}
public static Annotation[] getAnnotations(Method clazz) {
if (AnnotationDataStore.isMethodDataRecorded(clazz)) {
Annotation[] result = AnnotationDataStore.getMethodAnnotations(clazz);
int rc = 0;
boolean found = false;
for (Annotation a : result) {
if (a instanceof ModifiedMethod) {
found = true;
break;
}
}
if (!found) {
return result;
}
Annotation[] ret = new Annotation[result.length - 1];
for (Annotation a : result) {
if (!(a instanceof ModifiedMethod)) {
ret[rc] = a;
rc++;
}
}
return ret;
}
if (clazz.isAnnotationPresent(ModifiedMethod.class)) {
Annotation[] d = clazz.getAnnotations();
Annotation[] ret = new Annotation[d.length - 1];
int rc = 0;
for (Annotation a : d) {
if (!(a instanceof ModifiedMethod)) {
ret[rc] = a;
rc++;
}
}
return ret;
}
return clazz.getAnnotations();
}
public static Annotation[] getDeclaredAnnotations(Method clazz) {
if (AnnotationDataStore.isMethodDataRecorded(clazz)) {
Annotation[] result = AnnotationDataStore.getMethodAnnotations(clazz);
int rc = 0;
boolean found = false;
for (Annotation a : result) {
if (a instanceof ModifiedMethod) {
found = true;
break;
}
}
if (!found) {
return result;
}
Annotation[] ret = new Annotation[result.length - 1];
for (Annotation a : result) {
if (!(a instanceof ModifiedMethod)) {
ret[rc] = a;
rc++;
}
}
return ret;
}
if (clazz.isAnnotationPresent(ModifiedMethod.class)) {
Annotation[] d = clazz.getDeclaredAnnotations();
Annotation[] ret = new Annotation[d.length - 1];
int rc = 0;
for (Annotation a : d) {
if (!(a instanceof ModifiedMethod)) {
ret[rc] = a;
rc++;
}
}
return ret;
}
return clazz.getDeclaredAnnotations();
}
public static Annotation[][] getParameterAnnotations(Method clazz) {
if (AnnotationDataStore.isMethodDataRecorded(clazz)) {
Annotation[][] result = AnnotationDataStore.getMethodParameterAnnotations(clazz);
return result;
}
return clazz.getParameterAnnotations();
}
// constructors
public static boolean isAnnotationPresent(Constructor<?> clazz, Class anType) {
if (AnnotationDataStore.isConstructorDataRecorded(clazz)) {
boolean result = AnnotationDataStore.isConstructorAnnotationPresent(clazz, anType);
return result;
}
return clazz.isAnnotationPresent(anType);
}
public static Annotation getAnnotation(Constructor<?> clazz, Class anType) {
if (AnnotationDataStore.isConstructorDataRecorded(clazz)) {
Annotation result = AnnotationDataStore.getConstructorAnnotation(clazz, anType);
return result;
}
return clazz.getAnnotation(anType);
}
public static Annotation[] getAnnotations(Constructor<?> clazz) {
if (AnnotationDataStore.isConstructorDataRecorded(clazz)) {
Annotation[] result = AnnotationDataStore.getConstructorAnnotations(clazz);
return result;
}
return clazz.getAnnotations();
}
public static Annotation[] getDeclaredAnnotations(Constructor<?> clazz) {
if (AnnotationDataStore.isConstructorDataRecorded(clazz)) {
Annotation[] result = AnnotationDataStore.getConstructorAnnotations(clazz);
return result;
}
return clazz.getDeclaredAnnotations();
}
public static Annotation[][] getParameterAnnotations(Constructor<?> clazz) {
if (AnnotationDataStore.isConstructorDataRecorded(clazz)) {
Annotation[][] result = AnnotationDataStore.getMethodParameterAnnotations(clazz);
return result;
}
return clazz.getParameterAnnotations();
}
// AnnotatedElement
public static boolean isAnnotationPresent(AnnotatedElement clazz, Class anType) {
if (clazz instanceof Class<?>) {
return isAnnotationPresent((Class) clazz, anType);
} else if (clazz instanceof Field) {
return isAnnotationPresent((Field) clazz, anType);
} else if (clazz instanceof Method) {
return isAnnotationPresent((Method) clazz, anType);
} else if (clazz instanceof Constructor<?>) {
return isAnnotationPresent((Constructor<?>) clazz, anType);
}
return clazz.isAnnotationPresent(anType);
}
public static Annotation getAnnotation(AnnotatedElement clazz, Class anType) {
if (clazz instanceof Class<?>) {
return getAnnotation((Class) clazz, anType);
} else if (clazz instanceof Field) {
return getAnnotation((Field) clazz, anType);
} else if (clazz instanceof Method) {
return getAnnotation((Method) clazz, anType);
} else if (clazz instanceof Constructor<?>) {
return getAnnotation((Constructor<?>) clazz, anType);
}
return clazz.getAnnotation(anType);
}
public static Annotation[] getAnnotations(AnnotatedElement clazz) {
if (clazz instanceof Class<?>) {
return getAnnotations((Class) clazz);
} else if (clazz instanceof Field) {
return getAnnotations((Field) clazz);
} else if (clazz instanceof Method) {
return getAnnotations((Method) clazz);
} else if (clazz instanceof Constructor<?>) {
return getAnnotations((Constructor<?>) clazz);
}
return clazz.getAnnotations();
}
public static Annotation[] getDeclaredAnnotations(AnnotatedElement clazz) {
if (clazz instanceof Class<?>) {
return getDeclaredAnnotations((Class) clazz);
} else if (clazz instanceof Field) {
return getDeclaredAnnotations((Field) clazz);
} else if (clazz instanceof Method) {
return getDeclaredAnnotations((Method) clazz);
} else if (clazz instanceof Constructor<?>) {
return getDeclaredAnnotations((Constructor<?>) clazz);
}
return clazz.getDeclaredAnnotations();
}
}