gr.uom.java.xmi.diff.UMLOperationDiff Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of refactoring-miner Show documentation
Show all versions of refactoring-miner Show documentation
RefactoringMiner is a library/API written in Java that can detect refactorings applied in the history of a Java project.
package gr.uom.java.xmi.diff;
import gr.uom.java.xmi.UMLAnnotation;
import gr.uom.java.xmi.UMLOperation;
import gr.uom.java.xmi.UMLParameter;
import gr.uom.java.xmi.decomposition.AbstractCodeMapping;
import gr.uom.java.xmi.decomposition.VariableReferenceExtractor;
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.refactoringminer.api.Refactoring;
public class UMLOperationDiff {
private UMLOperation removedOperation;
private UMLOperation addedOperation;
private List addedParameters;
private List removedParameters;
private List parameterDiffList;
private boolean visibilityChanged;
private boolean abstractionChanged;
private boolean returnTypeChanged;
private boolean qualifiedReturnTypeChanged;
private boolean operationRenamed;
private boolean parametersReordered;
private Set mappings = new LinkedHashSet();
private UMLAnnotationListDiff annotationListDiff;
public UMLOperationDiff(UMLOperation removedOperation, UMLOperation addedOperation) {
this.removedOperation = removedOperation;
this.addedOperation = addedOperation;
this.addedParameters = new ArrayList();
this.removedParameters = new ArrayList();
this.parameterDiffList = new ArrayList();
this.visibilityChanged = false;
this.abstractionChanged = false;
this.returnTypeChanged = false;
this.operationRenamed = false;
if(!removedOperation.getName().equals(addedOperation.getName()))
operationRenamed = true;
if(!removedOperation.getVisibility().equals(addedOperation.getVisibility()))
visibilityChanged = true;
if(removedOperation.isAbstract() != addedOperation.isAbstract())
abstractionChanged = true;
if(!removedOperation.equalReturnParameter(addedOperation))
returnTypeChanged = true;
else if(!removedOperation.equalQualifiedReturnParameter(addedOperation))
qualifiedReturnTypeChanged = true;
this.annotationListDiff = new UMLAnnotationListDiff(removedOperation.getAnnotations(), addedOperation.getAnnotations());
List> matchedParameters = updateAddedRemovedParameters(removedOperation, addedOperation);
for(SimpleEntry matchedParameter : matchedParameters) {
UMLParameter parameter1 = matchedParameter.getKey();
UMLParameter parameter2 = matchedParameter.getValue();
UMLParameterDiff parameterDiff = new UMLParameterDiff(parameter1, parameter2, removedOperation, addedOperation, mappings);
parameterDiffList.add(parameterDiff);
}
int matchedParameterCount = matchedParameters.size()/2;
List parameterNames1 = removedOperation.getParameterNameList();
List parameterNames2 = addedOperation.getParameterNameList();
if(removedParameters.isEmpty() && addedParameters.isEmpty() &&
matchedParameterCount == parameterNames1.size() && matchedParameterCount == parameterNames2.size() &&
parameterNames1.size() == parameterNames2.size() && parameterNames1.size() > 1 && !parameterNames1.equals(parameterNames2)) {
parametersReordered = true;
}
//first round match parameters with the same name
for(Iterator removedParameterIterator = removedParameters.iterator(); removedParameterIterator.hasNext();) {
UMLParameter removedParameter = removedParameterIterator.next();
for(Iterator addedParameterIterator = addedParameters.iterator(); addedParameterIterator.hasNext();) {
UMLParameter addedParameter = addedParameterIterator.next();
if(removedParameter.getName().equals(addedParameter.getName())) {
UMLParameterDiff parameterDiff = new UMLParameterDiff(removedParameter, addedParameter, removedOperation, addedOperation, mappings);
parameterDiffList.add(parameterDiff);
addedParameterIterator.remove();
removedParameterIterator.remove();
break;
}
}
}
//second round match parameters with the same type
for(Iterator removedParameterIterator = removedParameters.iterator(); removedParameterIterator.hasNext();) {
UMLParameter removedParameter = removedParameterIterator.next();
for(Iterator addedParameterIterator = addedParameters.iterator(); addedParameterIterator.hasNext();) {
UMLParameter addedParameter = addedParameterIterator.next();
if(removedParameter.getType().equalsQualified(addedParameter.getType()) &&
!existsAnotherAddedParameterWithTheSameType(addedParameter)) {
UMLParameterDiff parameterDiff = new UMLParameterDiff(removedParameter, addedParameter, removedOperation, addedOperation, mappings);
parameterDiffList.add(parameterDiff);
addedParameterIterator.remove();
removedParameterIterator.remove();
break;
}
}
}
//third round match parameters with different type and name
List removedParametersWithoutReturnType = removedOperation.getParametersWithoutReturnType();
List addedParametersWithoutReturnType = addedOperation.getParametersWithoutReturnType();
if(matchedParameterCount == removedParametersWithoutReturnType.size()-1 && matchedParameterCount == addedParametersWithoutReturnType.size()-1) {
for(Iterator removedParameterIterator = removedParameters.iterator(); removedParameterIterator.hasNext();) {
UMLParameter removedParameter = removedParameterIterator.next();
int indexOfRemovedParameter = removedParametersWithoutReturnType.indexOf(removedParameter);
for(Iterator addedParameterIterator = addedParameters.iterator(); addedParameterIterator.hasNext();) {
UMLParameter addedParameter = addedParameterIterator.next();
int indexOfAddedParameter = addedParametersWithoutReturnType.indexOf(addedParameter);
if(indexOfRemovedParameter == indexOfAddedParameter) {
UMLParameterDiff parameterDiff = new UMLParameterDiff(removedParameter, addedParameter, removedOperation, addedOperation, mappings);
parameterDiffList.add(parameterDiff);
addedParameterIterator.remove();
removedParameterIterator.remove();
break;
}
}
}
}
}
public UMLOperationDiff(UMLOperation removedOperation, UMLOperation addedOperation, Set mappings) {
this(removedOperation, addedOperation);
this.mappings = mappings;
}
private boolean existsAnotherAddedParameterWithTheSameType(UMLParameter parameter) {
if(removedOperation.hasTwoParametersWithTheSameType() && addedOperation.hasTwoParametersWithTheSameType()) {
return false;
}
for(UMLParameter addedParameter : addedParameters) {
if(!addedParameter.getName().equals(parameter.getName()) &&
addedParameter.getType().equalsQualified(parameter.getType())) {
return true;
}
}
return false;
}
private List> updateAddedRemovedParameters(UMLOperation removedOperation, UMLOperation addedOperation) {
List> matchedParameters = new ArrayList>();
for(UMLParameter parameter1 : removedOperation.getParameters()) {
if(!parameter1.getKind().equals("return")) {
boolean found = false;
for(UMLParameter parameter2 : addedOperation.getParameters()) {
if(parameter1.equalsIncludingName(parameter2)) {
matchedParameters.add(new SimpleEntry(parameter1, parameter2));
found = true;
break;
}
}
if(!found) {
this.removedParameters.add(parameter1);
}
}
}
for(UMLParameter parameter1 : addedOperation.getParameters()) {
if(!parameter1.getKind().equals("return")) {
boolean found = false;
for(UMLParameter parameter2 : removedOperation.getParameters()) {
if(parameter1.equalsIncludingName(parameter2)) {
matchedParameters.add(new SimpleEntry(parameter2, parameter1));
found = true;
break;
}
}
if(!found) {
this.addedParameters.add(parameter1);
}
}
}
return matchedParameters;
}
public List getParameterDiffList() {
return parameterDiffList;
}
public UMLOperation getRemovedOperation() {
return removedOperation;
}
public UMLOperation getAddedOperation() {
return addedOperation;
}
public List getAddedParameters() {
return addedParameters;
}
public List getRemovedParameters() {
return removedParameters;
}
public boolean isOperationRenamed() {
return operationRenamed;
}
public boolean isEmpty() {
return addedParameters.isEmpty() && removedParameters.isEmpty() && parameterDiffList.isEmpty() &&
!visibilityChanged && !abstractionChanged && !returnTypeChanged && !operationRenamed && annotationListDiff.isEmpty();
}
public String toString() {
StringBuilder sb = new StringBuilder();
if(!isEmpty())
sb.append("\t").append(removedOperation).append("\n");
if(operationRenamed)
sb.append("\t").append("renamed from " + removedOperation.getName() + " to " + addedOperation.getName()).append("\n");
if(visibilityChanged)
sb.append("\t").append("visibility changed from " + removedOperation.getVisibility() + " to " + addedOperation.getVisibility()).append("\n");
if(abstractionChanged)
sb.append("\t").append("abstraction changed from " + (removedOperation.isAbstract() ? "abstract" : "concrete") + " to " +
(addedOperation.isAbstract() ? "abstract" : "concrete")).append("\n");
if(returnTypeChanged || qualifiedReturnTypeChanged)
sb.append("\t").append("return type changed from " + removedOperation.getReturnParameter() + " to " + addedOperation.getReturnParameter()).append("\n");
for(UMLParameter umlParameter : removedParameters) {
sb.append("\t").append("parameter " + umlParameter + " removed").append("\n");
}
for(UMLParameter umlParameter : addedParameters) {
sb.append("\t").append("parameter " + umlParameter + " added").append("\n");
}
for(UMLParameterDiff parameterDiff : parameterDiffList) {
sb.append(parameterDiff);
}
for(UMLAnnotation annotation : annotationListDiff.getRemovedAnnotations()) {
sb.append("\t").append("annotation " + annotation + " removed").append("\n");
}
for(UMLAnnotation annotation : annotationListDiff.getAddedAnnotations()) {
sb.append("\t").append("annotation " + annotation + " added").append("\n");
}
for(UMLAnnotationDiff annotationDiff : annotationListDiff.getAnnotationDiffList()) {
sb.append("\t").append("annotation " + annotationDiff.getRemovedAnnotation() + " modified to " + annotationDiff.getAddedAnnotation()).append("\n");
}
return sb.toString();
}
public Set getRefactorings() {
Set refactorings = new LinkedHashSet();
if(returnTypeChanged || qualifiedReturnTypeChanged) {
UMLParameter removedOperationReturnParameter = removedOperation.getReturnParameter();
UMLParameter addedOperationReturnParameter = addedOperation.getReturnParameter();
if(removedOperationReturnParameter != null && addedOperationReturnParameter != null) {
Set references = VariableReferenceExtractor.findReturnReferences(mappings);
ChangeReturnTypeRefactoring refactoring = new ChangeReturnTypeRefactoring(removedOperationReturnParameter.getType(), addedOperationReturnParameter.getType(),
removedOperation, addedOperation, references);
refactorings.add(refactoring);
}
}
for(UMLParameterDiff parameterDiff : getParameterDiffList()) {
refactorings.addAll(parameterDiff.getRefactorings());
}
if(removedParameters.isEmpty()) {
for(UMLParameter umlParameter : addedParameters) {
AddParameterRefactoring refactoring = new AddParameterRefactoring(umlParameter, removedOperation, addedOperation);
refactorings.add(refactoring);
}
}
if(addedParameters.isEmpty()) {
for(UMLParameter umlParameter : removedParameters) {
RemoveParameterRefactoring refactoring = new RemoveParameterRefactoring(umlParameter, removedOperation, addedOperation);
refactorings.add(refactoring);
}
}
if(parametersReordered) {
ReorderParameterRefactoring refactoring = new ReorderParameterRefactoring(removedOperation, addedOperation);
refactorings.add(refactoring);
}
for(UMLAnnotation annotation : annotationListDiff.getAddedAnnotations()) {
AddMethodAnnotationRefactoring refactoring = new AddMethodAnnotationRefactoring(annotation, removedOperation, addedOperation);
refactorings.add(refactoring);
}
for(UMLAnnotation annotation : annotationListDiff.getRemovedAnnotations()) {
RemoveMethodAnnotationRefactoring refactoring = new RemoveMethodAnnotationRefactoring(annotation, removedOperation, addedOperation);
refactorings.add(refactoring);
}
for(UMLAnnotationDiff annotationDiff : annotationListDiff.getAnnotationDiffList()) {
ModifyMethodAnnotationRefactoring refactoring = new ModifyMethodAnnotationRefactoring(annotationDiff.getRemovedAnnotation(), annotationDiff.getAddedAnnotation(), removedOperation, addedOperation);
refactorings.add(refactoring);
}
return refactorings;
}
}