package japicmp.model;
import com.google.common.base.Optional;
import japicmp.cmp.JarArchiveComparator;
import japicmp.util.MethodDescriptorParser;
import javassist.CtMethod;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlTransient;
public class JApiMethod extends JApiBehavior {
private final Optional<CtMethod> oldMethod;
private final Optional<CtMethod> newMethod;
private final JApiReturnType returnType;
public JApiMethod(JApiClass jApiClass, String name, JApiChangeStatus changeStatus, Optional<CtMethod> oldMethod, Optional<CtMethod> newMethod, JarArchiveComparator jarArchiveComparator) {
super(jApiClass, name, oldMethod, newMethod, changeStatus, jarArchiveComparator);
this.oldMethod = oldMethod;
this.newMethod = newMethod;
this.returnType = computeReturnTypeChanges(oldMethod, newMethod);
this.changeStatus = evaluateChangeStatus(this.changeStatus);
}
private JApiChangeStatus evaluateChangeStatus(JApiChangeStatus changeStatus) {
if (changeStatus == JApiChangeStatus.UNCHANGED) {
if (this.returnType.getChangeStatus() != JApiChangeStatus.UNCHANGED) {
changeStatus = JApiChangeStatus.MODIFIED;
}
}
return changeStatus;
}
private JApiReturnType computeReturnTypeChanges(Optional<CtMethod> oldMethodOptional, Optional<CtMethod> newMethodOptional) {
JApiReturnType jApiReturnType = new JApiReturnType(JApiChangeStatus.UNCHANGED, Optional.<String>absent(), Optional.<String>absent());
if (oldMethodOptional.isPresent() && newMethodOptional.isPresent()) {
String oldReturnType = computeReturnType(oldMethodOptional.get());
String newReturnType = computeReturnType(newMethodOptional.get());
JApiChangeStatus changeStatusReturnType = JApiChangeStatus.UNCHANGED;
if (!oldReturnType.equals(newReturnType)) {
changeStatusReturnType = JApiChangeStatus.MODIFIED;
}
jApiReturnType = new JApiReturnType(changeStatusReturnType, Optional.of(oldReturnType), Optional.of(newReturnType));
} else {
if (oldMethodOptional.isPresent()) {
String oldReturnType = computeReturnType(oldMethodOptional.get());
jApiReturnType = new JApiReturnType(JApiChangeStatus.REMOVED, Optional.of(oldReturnType), Optional.<String>absent());
}
if (newMethodOptional.isPresent()) {
String newReturnType = computeReturnType(newMethodOptional.get());
jApiReturnType = new JApiReturnType(JApiChangeStatus.NEW, Optional.<String>absent(), Optional.of(newReturnType));
}
}
return jApiReturnType;
}
private String computeReturnType(CtMethod oldMethod) {
MethodDescriptorParser parser = new MethodDescriptorParser();
parser.parse(oldMethod.getSignature());
return parser.getReturnType();
}
public boolean hasSameReturnType(JApiMethod otherMethod) {
boolean haveSameReturnType = false;
JApiReturnType otherReturnType = otherMethod.getReturnType();
if (otherReturnType.getChangeStatus() == JApiChangeStatus.UNCHANGED || otherReturnType.getChangeStatus() == JApiChangeStatus.MODIFIED) {
if (this.returnType.getChangeStatus() == JApiChangeStatus.UNCHANGED || this.returnType.getChangeStatus() == JApiChangeStatus.MODIFIED) {
if (otherReturnType.getOldReturnType().equals(this.returnType.getOldReturnType()) && otherReturnType.getNewReturnType().equals(this.returnType.getNewReturnType())) {
haveSameReturnType = true;
}
} else if (this.returnType.getChangeStatus() == JApiChangeStatus.NEW) {
if (otherReturnType.getNewReturnType().equals(this.returnType.getNewReturnType())) {
haveSameReturnType = true;
}
} else if (this.returnType.getChangeStatus() == JApiChangeStatus.REMOVED) {
if (otherReturnType.getOldReturnType().equals(this.returnType.getOldReturnType())) {
haveSameReturnType = true;
}
}
} else if (otherReturnType.getChangeStatus() == JApiChangeStatus.NEW) {
if (this.returnType.getChangeStatus() == JApiChangeStatus.UNCHANGED || this.returnType.getChangeStatus() == JApiChangeStatus.MODIFIED) {
if (otherReturnType.getNewReturnType().equals(this.returnType.getNewReturnType())) {
haveSameReturnType = true;
}
} else if (this.returnType.getChangeStatus() == JApiChangeStatus.NEW) {
if (otherReturnType.getNewReturnType().equals(this.returnType.getNewReturnType())) {
haveSameReturnType = true;
}
} else if (this.returnType.getChangeStatus() == JApiChangeStatus.REMOVED) {
if (otherReturnType.getNewReturnType().equals(this.returnType.getOldReturnType())) {
haveSameReturnType = true;
}
}
} else {
if (this.returnType.getChangeStatus() == JApiChangeStatus.UNCHANGED || this.returnType.getChangeStatus() == JApiChangeStatus.MODIFIED) {
if (otherReturnType.getOldReturnType().equals(this.returnType.getNewReturnType())) {
haveSameReturnType = true;
}
} else if (this.returnType.getChangeStatus() == JApiChangeStatus.NEW) {
if (otherReturnType.getOldReturnType().equals(this.returnType.getNewReturnType())) {
haveSameReturnType = true;
}
} else if (this.returnType.getChangeStatus() == JApiChangeStatus.REMOVED) {
if (otherReturnType.getOldReturnType().equals(this.returnType.getOldReturnType())) {
haveSameReturnType = true;
}
}
}
return haveSameReturnType;
}
public boolean hasSameSignature(JApiMethod jApiMethod) {
return hasSameReturnType(jApiMethod) && hasSameParameter(jApiMethod);
}
@XmlTransient
public Optional<CtMethod> getNewMethod() {
return newMethod;
}
@XmlTransient
public Optional<CtMethod> getOldMethod() {
return oldMethod;
}
@XmlElement(name = "returnType")
public JApiReturnType getReturnType() {
return returnType;
}
}