All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gr.uom.java.xmi.decomposition.AbstractCall Maven / Gradle / Ivy

Go to download

RefactoringMiner is a library/API written in Java that can detect refactorings applied in the history of a Java project.

There is a newer version: 3.0.9
Show newest version
package gr.uom.java.xmi.decomposition;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import gr.uom.java.xmi.LocationInfo;
import gr.uom.java.xmi.LocationInfoProvider;
import gr.uom.java.xmi.decomposition.replacement.MergeVariableReplacement;
import gr.uom.java.xmi.decomposition.replacement.Replacement;
import gr.uom.java.xmi.decomposition.replacement.Replacement.ReplacementType;
import gr.uom.java.xmi.diff.CodeRange;
import static gr.uom.java.xmi.diff.UMLClassBaseDiff.allMappingsAreExactMatches;

public abstract class AbstractCall implements LocationInfoProvider {
	protected int typeArguments;
	protected String expression;
	protected List arguments;
	protected LocationInfo locationInfo;
	protected StatementCoverageType coverage = StatementCoverageType.NONE;

	public String getExpression() {
		return expression;
	}

	public List getArguments() {
		return arguments;
	}

	public LocationInfo getLocationInfo() {
		return locationInfo;
	}

	public StatementCoverageType getCoverage() {
		return coverage;
	}

	public abstract boolean identicalName(AbstractCall call);
	public abstract String getName();
	public abstract double normalizedNameDistance(AbstractCall call);
	public abstract AbstractCall update(String oldExpression, String newExpression);

	public String actualString() {
		StringBuilder sb = new StringBuilder();
		if(expression != null) {
			sb.append(expression).append(".");
		}
		sb.append(getName());
		sb.append("(");
		int size = arguments.size();
		if(size > 0) {
			for(int i=0; i replacements) {
		return identicalExpression(call) ||
		identicalExpressionAfterTypeReplacements(call, replacements);
	}

	public boolean identicalExpression(AbstractCall call) {
		return (getExpression() != null && call.getExpression() != null &&
				getExpression().equals(call.getExpression())) ||
				(getExpression() == null && call.getExpression() == null);
	}

	private boolean identicalExpressionAfterTypeReplacements(AbstractCall call, Set replacements) {
		if(getExpression() != null && call.getExpression() != null) {
			String expression1 = getExpression();
			String expression2 = call.getExpression();
			String expression1AfterReplacements = new String(expression1);
			for(Replacement replacement : replacements) {
				if(replacement.getType().equals(ReplacementType.TYPE)) {
					expression1AfterReplacements = ReplacementUtil.performReplacement(expression1AfterReplacements, expression2, replacement.getBefore(), replacement.getAfter());
				}
			}
			if(expression1AfterReplacements.equals(expression2)) {
				return true;
			}
		}
		return false;
	}

	public boolean equalArguments(AbstractCall call) {
		return getArguments().equals(call.getArguments());
	}

	public boolean identicalOrReplacedArguments(AbstractCall call, Set replacements) {
		List arguments1 = getArguments();
		List arguments2 = call.getArguments();
		if(arguments1.size() != arguments2.size())
			return false;
		for(int i=0; i arguments1 = getArguments();
		List arguments2 = call.getArguments();
		if(arguments1.size() != arguments2.size())
			return false;
		for(int i=0; i tokens1 = new LinkedHashSet(Arrays.asList(argument1.split(UMLOperationBodyMapper.SPLIT_CONCAT_STRING_PATTERN)));
				Set tokens2 = new LinkedHashSet(Arrays.asList(argument2.split(UMLOperationBodyMapper.SPLIT_CONCAT_STRING_PATTERN)));
				Set intersection = new LinkedHashSet(tokens1);
				intersection.retainAll(tokens2);
				int size = intersection.size();
				int threshold = Math.max(tokens1.size(), tokens2.size()) - size;
				if(size > 0 && size >= threshold) {
					argumentConcatenated = true;
				}
			}
			if(!argument1.equals(argument2) && !argumentConcatenated)
				return false;
		}
		return true;
	}

	public boolean identicalOrWrappedArguments(AbstractCall call) {
		List arguments1 = getArguments();
		List arguments2 = call.getArguments();
		if(arguments1.size() != arguments2.size())
			return false;
		for(int i=0; i replacements) {
		int replacedArguments = 0;
		List arguments1 = getArguments();
		List arguments2 = call.getArguments();
		if(arguments1.size() == arguments2.size()) {
			for(int i=0; i 0 && replacedArguments == arguments1.size();
	}

	public boolean allArgumentsReplaced(AbstractCall call, Set replacements, Map parameterToArgumentMap) {
		int replacedArguments = 0;
		List arguments1 = getArguments();
		List arguments2 = call.getArguments();
		if(arguments1.size() == arguments2.size()) {
			for(int i=0; i 0 && replacedArguments == arguments1.size();
	}

	public boolean renamedWithIdenticalExpressionAndArguments(AbstractCall call, Set replacements, double distance) {
		boolean identicalOrReplacedArguments = identicalOrReplacedArguments(call, replacements);
		boolean allArgumentsReplaced = allArgumentsReplaced(call, replacements);
		return getExpression() != null && call.getExpression() != null &&
				identicalExpression(call, replacements) &&
				!identicalName(call) &&
				(equalArguments(call) || (allArgumentsReplaced && normalizedNameDistance(call) <= distance) || (identicalOrReplacedArguments && !allArgumentsReplaced));
	}

	public boolean renamedWithDifferentExpressionAndIdenticalArguments(AbstractCall call) {
		return (this.getName().contains(call.getName()) || call.getName().contains(this.getName())) &&
				equalArguments(call) && this.arguments.size() > 0 &&
				((this.getExpression() == null && call.getExpression() != null) || (call.getExpression() == null && this.getExpression() != null));
	}

	public boolean renamedWithIdenticalArgumentsAndNoExpression(AbstractCall call, double distance, List lambdaMappers) {
		boolean allExactLambdaMappers = lambdaMappers.size() > 0;
		for(UMLOperationBodyMapper lambdaMapper : lambdaMappers) {
			if(!allMappingsAreExactMatches(lambdaMapper)) {
				allExactLambdaMappers = false;
				break;
			}
		}
		return getExpression() == null && call.getExpression() == null &&
				!identicalName(call) &&
				(normalizedNameDistance(call) <= distance || allExactLambdaMappers) &&
				equalArguments(call);
	}

	public boolean renamedWithIdenticalExpressionAndDifferentNumberOfArguments(AbstractCall call, Set replacements, double distance, List lambdaMappers) {
		boolean allExactLambdaMappers = lambdaMappers.size() > 0;
		for(UMLOperationBodyMapper lambdaMapper : lambdaMappers) {
			if(!allMappingsAreExactMatches(lambdaMapper)) {
				allExactLambdaMappers = false;
				break;
			}
		}
		return getExpression() != null && call.getExpression() != null &&
				identicalExpression(call, replacements) &&
				(normalizedNameDistance(call) <= distance || allExactLambdaMappers) &&
				!equalArguments(call) &&
				getArguments().size() != call.getArguments().size();
	}

	private boolean onlyArgumentsChanged(AbstractCall call, Set replacements) {
		return identicalExpression(call, replacements) &&
				identicalName(call) &&
				!equalArguments(call) &&
				getArguments().size() != call.getArguments().size();
	}

	public boolean identicalWithMergedArguments(AbstractCall call, Set replacements) {
		if(onlyArgumentsChanged(call, replacements)) {
			List updatedArguments1 = new ArrayList(this.arguments);
			Map> commonVariableReplacementMap = new LinkedHashMap>();
			for(Replacement replacement : replacements) {
				if(replacement.getType().equals(ReplacementType.VARIABLE_NAME)) {
					String key = replacement.getAfter();
					if(commonVariableReplacementMap.containsKey(key)) {
						commonVariableReplacementMap.get(key).add(replacement);
						int index = updatedArguments1.indexOf(replacement.getBefore());
						if(index != -1) {
							updatedArguments1.remove(index);
						}
					}
					else {
						Set r = new LinkedHashSet();
						r.add(replacement);
						commonVariableReplacementMap.put(key, r);
						int index = updatedArguments1.indexOf(replacement.getBefore());
						if(index != -1) {
							updatedArguments1.remove(index);
							updatedArguments1.add(index, key);
						}
					}
				}
			}
			if(updatedArguments1.equals(call.arguments)) {
				for(String key : commonVariableReplacementMap.keySet()) {
					Set r = commonVariableReplacementMap.get(key);
					if(r.size() > 1) {
						replacements.removeAll(r);
						Set mergedVariables = new LinkedHashSet();
						for(Replacement replacement : r) {
							mergedVariables.add(replacement.getBefore());
						}
						MergeVariableReplacement merge = new MergeVariableReplacement(mergedVariables, key);
						replacements.add(merge);
					}
				}
				return true;
			}
		}
		return false;
	}

	public boolean identicalWithDifferentNumberOfArguments(AbstractCall call, Set replacements, Map parameterToArgumentMap) {
		if(onlyArgumentsChanged(call, replacements)) {
			int argumentIntersectionSize = argumentIntersectionSize(call, parameterToArgumentMap);
			if(argumentIntersectionSize > 0 || getArguments().size() == 0 || call.getArguments().size() == 0) {
				return true;
			}
		}
		return false;
	}

	public boolean identical(AbstractCall call, Set replacements) {
		return identicalExpression(call, replacements) &&
				identicalName(call) &&
				equalArguments(call);
	}

	public Set argumentIntersection(AbstractCall call) {
		List args1 = preprocessArguments(getArguments());
		List args2 = preprocessArguments(call.getArguments());
		Set argumentIntersection = new LinkedHashSet(args1);
		argumentIntersection.retainAll(args2);
		return argumentIntersection;
	}

	private List preprocessArguments(List arguments) {
		List args = new ArrayList();
		for(String arg : arguments) {
			if(arg.contains("\n")) {
				args.add(arg.substring(0, arg.indexOf("\n")));
			}
			else {
				args.add(arg);
			}
		}
		return args;
	}

	private int argumentIntersectionSize(AbstractCall call, Map parameterToArgumentMap) {
		Set argumentIntersection = argumentIntersection(call);
		int argumentIntersectionSize = argumentIntersection.size();
		for(String parameter : parameterToArgumentMap.keySet()) {
			String argument = parameterToArgumentMap.get(parameter);
			if(getArguments().contains(argument) &&
					call.getArguments().contains(parameter)) {
				argumentIntersectionSize++;
			}
		}
		return argumentIntersectionSize;
	}

	private boolean argumentIsEqual(String statement) {
		return statement.endsWith(";\n") && getArguments().size() == 1 &&
				//length()-2 to remove ";\n" from the end of the statement
				equalsIgnoringExtraParenthesis(getArguments().get(0), statement.substring(0, statement.length()-2));
	}

	private boolean argumentIsReturned(String statement) {
		return statement.startsWith("return ") && getArguments().size() == 1 &&
				//length()-2 to remove ";\n" from the end of the return statement, 7 to remove the prefix "return "
				equalsIgnoringExtraParenthesis(getArguments().get(0), statement.substring(7, statement.length()-2));
	}

	public Replacement makeReplacementForReturnedArgument(String statement) {
		if(argumentIsReturned(statement)) {
			return new Replacement(getArguments().get(0), statement.substring(7, statement.length()-2),
					ReplacementType.ARGUMENT_REPLACED_WITH_RETURN_EXPRESSION);
		}
		else if(argumentIsEqual(statement)) {
			return new Replacement(getArguments().get(0), statement.substring(0, statement.length()-2),
					ReplacementType.ARGUMENT_REPLACED_WITH_STATEMENT);
		}
		return null;
	}

	public Replacement makeReplacementForWrappedCall(String statement) {
		if(argumentIsReturned(statement)) {
			return new Replacement(statement.substring(7, statement.length()-2), getArguments().get(0),
					ReplacementType.ARGUMENT_REPLACED_WITH_RETURN_EXPRESSION);
		}
		else if(argumentIsEqual(statement)) {
			return new Replacement(statement.substring(0, statement.length()-2), getArguments().get(0),
					ReplacementType.ARGUMENT_REPLACED_WITH_STATEMENT);
		}
		return null;
	}

	private boolean argumentIsAssigned(String statement) {
		return getArguments().size() == 1 && statement.contains("=") && statement.endsWith(";\n") &&
				//length()-2 to remove ";\n" from the end of the assignment statement, indexOf("=")+1 to remove the left hand side of the assignment
				equalsIgnoringExtraParenthesis(getArguments().get(0), statement.substring(statement.indexOf("=")+1, statement.length()-2));
	}

	public Replacement makeReplacementForAssignedArgument(String statement) {
		if(argumentIsAssigned(statement)) {
			return new Replacement(statement.substring(statement.indexOf("=")+1, statement.length()-2),
					getArguments().get(0), ReplacementType.ARGUMENT_REPLACED_WITH_RIGHT_HAND_SIDE_OF_ASSIGNMENT_EXPRESSION);
		}
		return null;
	}

	private static boolean equalsIgnoringExtraParenthesis(String s1, String s2) {
		if(s1.equals(s2))
			return true;
		String parenthesizedS1 = "("+s1+")";
		if(parenthesizedS1.equals(s2))
			return true;
		String parenthesizedS2 = "("+s2+")";
		if(parenthesizedS2.equals(s1))
			return true;
		return false;
	}

	protected void update(AbstractCall newCall, String oldExpression, String newExpression) {
		newCall.typeArguments = this.typeArguments;
		if(this.expression != null && this.expression.equals(oldExpression)) {
			newCall.expression = newExpression;
		}
		else {
			newCall.expression = this.expression;
		}
		newCall.arguments = new ArrayList();
		for(String argument : this.arguments) {
			newCall.arguments.add(
				ReplacementUtil.performReplacement(argument, oldExpression, newExpression));
		}
	}

	public CodeRange codeRange() {
		LocationInfo info = getLocationInfo();
		return info.codeRange();
	}

	public enum StatementCoverageType {
		NONE, ONLY_CALL, RETURN_CALL, THROW_CALL, CAST_CALL, VARIABLE_DECLARATION_INITIALIZER_CALL;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy