package japicmp.model;
import com.google.common.base.Optional;
import javassist.bytecode.annotation.*;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlTransient;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class JApiAnnotationElement implements JApiHasChangeStatus, JApiCompatibility {
private final String name;
private final Optional<MemberValue> oldValue;
private final Optional<MemberValue> newValue;
private final JApiChangeStatus changeStatus;
public JApiAnnotationElement(String name, Optional<MemberValue> oldValue, Optional<MemberValue> newValue, JApiChangeStatus changeStatus) {
this.name = name;
this.oldValue = oldValue;
this.newValue = newValue;
this.changeStatus = evaluateChangeStatus(changeStatus);
}
private JApiChangeStatus evaluateChangeStatus(JApiChangeStatus changeStatus) {
if (changeStatus == JApiChangeStatus.UNCHANGED) {
if (oldValue.isPresent() && newValue.isPresent()) {
MemberValue memberValueOld = oldValue.get();
MemberValue memberValueNew = newValue.get();
if (!getMemberValue(memberValueOld).equals(getMemberValue(memberValueNew))) {
changeStatus = JApiChangeStatus.MODIFIED;
}
} else if (!oldValue.isPresent() && newValue.isPresent()) {
changeStatus = JApiChangeStatus.NEW;
} else if (oldValue.isPresent() && !newValue.isPresent()) {
changeStatus = JApiChangeStatus.REMOVED;
}
}
return changeStatus;
}
static JApiAnnotationElementValue getMemberValue(MemberValue memberValue) {
if (memberValue instanceof DoubleMemberValue) {
DoubleMemberValue value = (DoubleMemberValue) memberValue;
return new JApiAnnotationElementValue(JApiAnnotationElementValue.Type.Double, value.getValue(), Double.class.getName());
} else if (memberValue instanceof CharMemberValue) {
CharMemberValue value = (CharMemberValue) memberValue;
return new JApiAnnotationElementValue(JApiAnnotationElementValue.Type.Char, value.getValue(), Character.class.getName());
} else if (memberValue instanceof LongMemberValue) {
LongMemberValue value = (LongMemberValue) memberValue;
return new JApiAnnotationElementValue(JApiAnnotationElementValue.Type.Long, value.getValue(), Long.class.getName());
} else if (memberValue instanceof IntegerMemberValue) {
IntegerMemberValue value = (IntegerMemberValue) memberValue;
return new JApiAnnotationElementValue(JApiAnnotationElementValue.Type.Integer, value.getValue(), Integer.class.getName());
} else if (memberValue instanceof FloatMemberValue) {
FloatMemberValue value = (FloatMemberValue) memberValue;
return new JApiAnnotationElementValue(JApiAnnotationElementValue.Type.Float, value.getValue(), Float.class.getName());
} else if (memberValue instanceof AnnotationMemberValue) {
AnnotationMemberValue value = (AnnotationMemberValue) memberValue;
Annotation annotation = value.getValue();
return new JApiAnnotationElementValue(JApiAnnotationElementValue.Type.Annotation, annotation, annotation.getTypeName());
} else if (memberValue instanceof ClassMemberValue) {
ClassMemberValue value = (ClassMemberValue) memberValue;
return new JApiAnnotationElementValue(JApiAnnotationElementValue.Type.Class, value.getValue(), value.getValue());
} else if (memberValue instanceof ByteMemberValue) {
ByteMemberValue value = (ByteMemberValue) memberValue;
return new JApiAnnotationElementValue(JApiAnnotationElementValue.Type.Byte, value.getValue(), Byte.class.getName());
} else if (memberValue instanceof EnumMemberValue) {
EnumMemberValue value = (EnumMemberValue) memberValue;
String type = value.getType();
return new JApiAnnotationElementValue(JApiAnnotationElementValue.Type.Enum, value.getValue(), type);
} else if (memberValue instanceof ArrayMemberValue) {
ArrayMemberValue value = (ArrayMemberValue) memberValue;
return new JApiAnnotationElementValue(JApiAnnotationElementValue.Type.Array, value.getValue(), "[]");
} else if (memberValue instanceof ShortMemberValue) {
ShortMemberValue value = (ShortMemberValue) memberValue;
return new JApiAnnotationElementValue(JApiAnnotationElementValue.Type.Short, value.getValue(), Short.class.getName());
} else if (memberValue instanceof BooleanMemberValue) {
BooleanMemberValue value = (BooleanMemberValue) memberValue;
return new JApiAnnotationElementValue(JApiAnnotationElementValue.Type.Boolean, value.getValue(), Boolean.class.getName());
} else if (memberValue instanceof StringMemberValue) {
StringMemberValue value = (StringMemberValue) memberValue;
return new JApiAnnotationElementValue(JApiAnnotationElementValue.Type.String, value.getValue(), String.class.getName());
} else {
return new JApiAnnotationElementValue(JApiAnnotationElementValue.Type.UnsupportedType, "n.a.", "n.a.");
}
}
@XmlAttribute(name = "name")
public String getName() {
return name;
}
@XmlTransient
public Optional<MemberValue> getOldValue() {
return oldValue;
}
@XmlTransient
public Optional<MemberValue> getNewValue() {
return newValue;
}
@Override
@XmlAttribute(name = "changeStatus")
public JApiChangeStatus getChangeStatus() {
return this.changeStatus;
}
@XmlElementWrapper(name = "oldElementValues")
@XmlElement(name = "oldElementValue")
public List<JApiAnnotationElementValue> getOldElementValues() {
List<JApiAnnotationElementValue> values = new ArrayList<>();
if (this.oldValue.isPresent()) {
JApiAnnotationElementValue memberValue = getMemberValue(this.oldValue.get());
if (memberValue.getType() == JApiAnnotationElementValue.Type.Array) {
List<JApiAnnotationElementValue> multiValues = memberValue.getValues();
for (JApiAnnotationElementValue multiValue : multiValues) {
values.add(multiValue);
}
} else {
values.add(memberValue);
}
}
return values;
}
@XmlElementWrapper(name = "newElementValues")
@XmlElement(name = "newElementValue")
public List<JApiAnnotationElementValue> getNewElementValues() {
List<JApiAnnotationElementValue> values = new ArrayList<>();
if (this.newValue.isPresent()) {
JApiAnnotationElementValue memberValue = getMemberValue(this.newValue.get());
if (memberValue.getType() == JApiAnnotationElementValue.Type.Array) {
List<JApiAnnotationElementValue> multiValues = memberValue.getValues();
for (JApiAnnotationElementValue multiValue : multiValues) {
values.add(multiValue);
}
} else {
values.add(memberValue);
}
}
return values;
}
@XmlAttribute
public boolean isBinaryCompatible() {
return true;
}
@XmlAttribute
public boolean isSourceCompatible() {
return true;
}
@XmlElementWrapper(name = "compatibilityChanges")
@XmlElement(name = "compatibilityChange")
public List getCompatibilityChanges() {
return Collections.EMPTY_LIST;
}
}