package japicmp.util;
import com.google.common.base.Optional;
import japicmp.cmp.JarArchiveComparatorOptions;
import japicmp.model.JApiAnnotation;
import japicmp.model.JApiChangeStatus;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.ClassFile;
import javassist.bytecode.annotation.Annotation;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class AnnotationHelper {
public interface AnnotationsAttributeCallback<T> {
AnnotationsAttribute getAnnotationsAttribute(T t);
}
public static <T> void computeAnnotationChanges(List<JApiAnnotation> annotations, Optional<T> oldClassOptional, Optional<T> newClassOptional,
JarArchiveComparatorOptions options, AnnotationsAttributeCallback<T> annotationsAttributeCallback) {
if (!options.isNoAnnotations()) {
if (oldClassOptional.isPresent() && newClassOptional.isPresent()) {
T oldClass = oldClassOptional.get();
T newClass = newClassOptional.get();
AnnotationsAttribute oldAnnotationsAttribute = annotationsAttributeCallback.getAnnotationsAttribute(oldClass);
AnnotationsAttribute newAnnotationsAttribute = annotationsAttributeCallback.getAnnotationsAttribute(newClass);
Map<String, Annotation> oldAnnotationMap;
Map<String, Annotation> newAnnotationMap;
if (oldAnnotationsAttribute != null) {
oldAnnotationMap = buildAnnotationMap(oldAnnotationsAttribute.getAnnotations());
} else {
oldAnnotationMap = new HashMap<>();
}
if (newAnnotationsAttribute != null) {
newAnnotationMap = buildAnnotationMap(newAnnotationsAttribute.getAnnotations());
} else {
newAnnotationMap = new HashMap<>();
}
for (Annotation annotation : oldAnnotationMap.values()) {
Annotation foundAnnotation = newAnnotationMap.get(annotation.getTypeName());
if (foundAnnotation != null) {
JApiAnnotation jApiAnnotation = new JApiAnnotation(annotation.getTypeName(), Optional.of(annotation), Optional.of(foundAnnotation), JApiChangeStatus.UNCHANGED);
annotations.add(jApiAnnotation);
} else {
JApiAnnotation jApiAnnotation = new JApiAnnotation(annotation.getTypeName(), Optional.of(annotation), Optional.<Annotation>absent(), JApiChangeStatus.REMOVED);
annotations.add(jApiAnnotation);
}
}
for (Annotation annotation : newAnnotationMap.values()) {
Annotation foundAnnotation = oldAnnotationMap.get(annotation.getTypeName());
if (foundAnnotation == null) {
JApiAnnotation jApiAnnotation = new JApiAnnotation(annotation.getTypeName(), Optional.<Annotation>absent(), Optional.of(annotation), JApiChangeStatus.NEW);
annotations.add(jApiAnnotation);
}
}
} else {
if (oldClassOptional.isPresent()) {
T oldClass = oldClassOptional.get();
AnnotationsAttribute oldAnnotationsAttribute = annotationsAttributeCallback.getAnnotationsAttribute(oldClass);
if (oldAnnotationsAttribute != null) {
Map<String, Annotation> oldAnnotationMap = buildAnnotationMap(oldAnnotationsAttribute.getAnnotations());
for (Annotation annotation : oldAnnotationMap.values()) {
JApiAnnotation jApiAnnotation = new JApiAnnotation(annotation.getTypeName(), Optional.of(annotation), Optional.<Annotation>absent(),
JApiChangeStatus.REMOVED);
annotations.add(jApiAnnotation);
}
}
}
if (newClassOptional.isPresent()) {
T newClass = newClassOptional.get();
AnnotationsAttribute newAnnotationsAttribute = annotationsAttributeCallback.getAnnotationsAttribute(newClass);
if (newAnnotationsAttribute != null) {
Map<String, Annotation> newAnnotationMap = buildAnnotationMap(newAnnotationsAttribute.getAnnotations());
for (Annotation annotation : newAnnotationMap.values()) {
JApiAnnotation jApiAnnotation = new JApiAnnotation(annotation.getTypeName(), Optional.<Annotation>absent(), Optional.of(annotation), JApiChangeStatus.NEW);
annotations.add(jApiAnnotation);
}
}
}
}
}
}
private static Map<String, Annotation> buildAnnotationMap(Annotation[] annotations) {
Map<String, Annotation> map = new HashMap<>();
for (Annotation annotation : annotations) {
map.put(annotation.getTypeName(), annotation);
}
return map;
}
public static boolean hasAnnotation(ClassFile classFile, String annotationClassName) {
List attributes = classFile.getAttributes();
if (hasAnnotation(attributes, annotationClassName)) {
return true;
}
return false;
}
public static boolean hasAnnotation(List attributes, String annotationClassName) {
for (Object obj : attributes) {
if (obj instanceof AnnotationsAttribute) {
AnnotationsAttribute annotationsAttribute = (AnnotationsAttribute) obj;
Annotation[] annotations = annotationsAttribute.getAnnotations();
for (Annotation annotation : annotations) {
if (annotation.getTypeName().equals(annotationClassName)) {
return true;
}
}
}
}
return false;
}
}