package japicmp.model;
import com.google.common.base.Optional;
import com.google.common.xml.XmlEscapers;
import japicmp.util.OptionalHelper;
import javassist.bytecode.annotation.Annotation;
import javassist.bytecode.annotation.MemberValue;
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.List;
import java.util.Set;
public class JApiAnnotationElementValue {
private final String fullyQualifiedName;
private final Type type;
private final Object value;
private Optional<String> name = Optional.<String>absent();
public enum Type {
Double, Char, Long, Integer, Float, Byte, Enum, Annotation, Class, Short, Boolean, UnsupportedType, Array, String
}
public JApiAnnotationElementValue(Type type, Object value, String fullyQualifiedName) {
this.type = type;
this.value = value;
this.fullyQualifiedName = fullyQualifiedName;
}
@XmlTransient
public Type getType() {
return type;
}
@XmlAttribute(name = "type")
public String getTypeString() {
return type.name();
}
@XmlTransient
public Object getValue() {
return value;
}
@XmlAttribute(name = "value")
public String getValueString() {
if (type != Type.Array && type != Type.Annotation) {
return XmlEscapers.xmlAttributeEscaper().escape(value.toString());
}
return "n.a.";
}
@XmlElementWrapper(name = "values")
@XmlElement(name = "value")
public List<JApiAnnotationElementValue> getValues() {
List<JApiAnnotationElementValue> values = new ArrayList<>();
if (type == Type.Array) {
if (value instanceof MemberValue[]) {
MemberValue[] memberValues = (MemberValue[]) value;
for (MemberValue memberValue : memberValues) {
JApiAnnotationElementValue elementValue = JApiAnnotationElement.getMemberValue(memberValue);
values.add(elementValue);
}
}
} else if (type == Type.Annotation) {
if (value instanceof Annotation) {
Annotation annotation = (Annotation) value;
@SuppressWarnings("unchecked")
Set<String> memberNames = annotation.getMemberNames();
if (memberNames != null) {
for (String memberName : memberNames) {
MemberValue memberValue = annotation.getMemberValue(memberName);
JApiAnnotationElementValue elementValue = JApiAnnotationElement.getMemberValue(memberValue);
elementValue.setName(Optional.of(memberName));
values.add(elementValue);
}
}
}
}
return values;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
JApiAnnotationElementValue that = (JApiAnnotationElementValue) o;
if (type != that.type) {
return false;
}
if (type == Type.Array || type == Type.Annotation) {
List<JApiAnnotationElementValue> values = getValues();
List<JApiAnnotationElementValue> thatValues = that.getValues();
if (values.size() != thatValues.size()) {
return false;
}
for (int i = 0; i < values.size(); i++) {
if (!values.get(i).equals(thatValues.get(i))) {
return false;
}
}
} else {
if (value != null ? !value.equals(that.value) : that.value != null)
return false;
}
return true;
}
@Override
public int hashCode() {
int result = fullyQualifiedName != null ? fullyQualifiedName.hashCode() : 0;
result = 31 * result + (type != null ? type.hashCode() : 0);
result = 31 * result + (value != null ? value.hashCode() : 0);
result = 31 * result + (name != null ? name.hashCode() : 0);
return result;
}
@XmlAttribute(name = "fullyQualifiedName")
public String getFullyQualifiedName() {
return fullyQualifiedName;
}
@XmlTransient
public Optional<String> getName() {
return this.name;
}
@XmlAttribute(name = "name")
public String getNameString() {
return OptionalHelper.optionalToString(this.name);
}
public void setName(Optional<String> name) {
this.name = name;
}
}