private void checkForExtractedOperations() { List<UMLOperation> operationsToBeRemoved = new ArrayList<UMLOperation>(); for(Iterator<UMLOperation> addedOperationIterator = addedOperations.iterator(); addedOperationIterator.hasNext();) { UMLOperation addedOperation = addedOperationIterator.next(); for(UMLOperationBodyMapper mapper : getOperationBodyMapperList()) { ExtractOperationDetection detection = new ExtractOperationDetection(addedOperations, modelDiff); ExtractOperationRefactoring refactoring = detection.check(mapper, addedOperation); if(refactoring != null) { refactorings.add(refactoring); UMLOperationBodyMapper operationBodyMapper = refactoring.getBodyMapper(); refactorings.addAll(operationBodyMapper.getRefactorings()); mapper.addAdditionalMapper(operationBodyMapper); operationsToBeRemoved.add(addedOperation); } } } addedOperations.removeAll(operationsToBeRemoved); }
private UMLOperationBodyMapper createMapperForExtractedMethod(UMLOperationBodyMapper mapper, UMLOperation originalOperation, UMLOperation addedOperation, OperationInvocation addedOperationInvocation) { List<UMLParameter> originalMethodParameters = originalOperation.getParametersWithoutReturnType(); Map<UMLParameter, UMLParameter> originalMethodParametersPassedAsArgumentsMappedToCalledMethodParameters = new LinkedHashMap<UMLParameter, UMLParameter>(); List<String> arguments = addedOperationInvocation.getArguments(); List<UMLParameter> parameters = addedOperation.getParametersWithoutReturnType(); Map<String, String> parameterToArgumentMap = new LinkedHashMap<String, String>(); //special handling for methods with varargs parameter for which no argument is passed in the matching invocation int size = Math.min(arguments.size(), parameters.size()); for(int i=0; i<size; i++) { String argumentName = arguments.get(i); String parameterName = parameters.get(i).getName(); parameterToArgumentMap.put(parameterName, argumentName); for(UMLParameter originalMethodParameter : originalMethodParameters) { if(originalMethodParameter.getName().equals(argumentName)) { originalMethodParametersPassedAsArgumentsMappedToCalledMethodParameters.put(originalMethodParameter, parameters.get(i)); } } } if(parameterTypesMatch(originalMethodParametersPassedAsArgumentsMappedToCalledMethodParameters)) { UMLOperation delegateMethod = findDelegateMethod(originalOperation, addedOperation, addedOperationInvocation); return new UMLOperationBodyMapper(mapper, delegateMethod != null ? delegateMethod : addedOperation, new LinkedHashMap<String, String>(), parameterToArgumentMap); } return null; }
!mapper.getReplacementsInvolvingMethodInvocation().isEmpty()) { Set<OperationInvocation> operationInvocations = mapper.getOperation2().getAllOperationInvocations(); OperationInvocation addedOperationInvocation = matchingInvocation(addedOperation, operationInvocations, mapper.getOperation2().variableTypeMap()); if(addedOperationInvocation != null) { CallTreeNode root = new CallTreeNode(mapper.getOperation1(), addedOperation, addedOperationInvocation); CallTree callTree = new CallTree(root); generateCallTree(addedOperation, root, callTree); UMLOperationBodyMapper operationBodyMapper = createMapperForExtractedMethod(mapper, mapper.getOperation1(), addedOperation, addedOperationInvocation); if(operationBodyMapper != null) { List<AbstractCodeMapping> additionalExactMatches = new ArrayList<AbstractCodeMapping>(); for(int i=1; i<nodesInBreadthFirstOrder.size(); i++) { CallTreeNode node = nodesInBreadthFirstOrder.get(i); if(matchingInvocation(node.getInvokedOperation(), operationInvocations, mapper.getOperation2().variableTypeMap()) == null) { UMLOperationBodyMapper nestedMapper = createMapperForExtractedMethod(mapper, node.getOriginalOperation(), node.getInvokedOperation(), node.getInvocation()); if(nestedMapper != null) { additionalExactMatches.addAll(nestedMapper.getExactMatches()); UMLOperation delegateMethod = findDelegateMethod(mapper.getOperation1(), addedOperation, addedOperationInvocation); if(extractMatchCondition(operationBodyMapper, additionalExactMatches)) { if(delegateMethod == null) { return new ExtractOperationRefactoring(operationBodyMapper, mapper.getOperation2(), addedOperationInvocation);
private void generateCallTree(UMLOperation operation, CallTreeNode parent, CallTree callTree) { Set<OperationInvocation> invocations = operation.getAllOperationInvocations(); for(UMLOperation addedOperation : addedOperations) { for(OperationInvocation invocation : invocations) { if(invocation.matchesOperation(addedOperation, operation.variableTypeMap(), modelDiff)) { if(!callTree.contains(addedOperation)) { CallTreeNode node = new CallTreeNode(operation, addedOperation, invocation); parent.addChild(node); generateCallTree(addedOperation, node, callTree); } } } } }
private boolean extractMatchCondition(UMLOperationBodyMapper operationBodyMapper, List<AbstractCodeMapping> additionalExactMatches) { int mappings = operationBodyMapper.mappingsWithoutBlocks(); int nonMappedElementsT1 = operationBodyMapper.nonMappedElementsT1(); int nonMappedElementsT2 = operationBodyMapper.nonMappedElementsT2(); List<AbstractCodeMapping> exactMatchList = new ArrayList<AbstractCodeMapping>(operationBodyMapper.getExactMatches()); boolean exceptionHandlingExactMatch = false; boolean throwsNewExceptionExactMatch = false; if(exactMatchList.size() == 1) { AbstractCodeMapping mapping = exactMatchList.get(0); if(mapping.getFragment1() instanceof StatementObject && mapping.getFragment2() instanceof StatementObject) { StatementObject statement1 = (StatementObject)mapping.getFragment1(); StatementObject statement2 = (StatementObject)mapping.getFragment2(); if(statement1.getParent().getString().startsWith("catch(") && statement2.getParent().getString().startsWith("catch(")) { exceptionHandlingExactMatch = true; } } if(mapping.getFragment1().throwsNewException() && mapping.getFragment2().throwsNewException()) { throwsNewExceptionExactMatch = true; } } exactMatchList.addAll(additionalExactMatches); int exactMatches = exactMatchList.size(); return mappings > 0 && (mappings > nonMappedElementsT2 || (exactMatches >= mappings && nonMappedElementsT1 == 0) || (exactMatches == 1 && !throwsNewExceptionExactMatch && nonMappedElementsT2-exactMatches < 10) || (!exceptionHandlingExactMatch && exactMatches > 1 && additionalExactMatches.size() < exactMatches && nonMappedElementsT2-exactMatches < 20) || (mappings == 1 && mappings > operationBodyMapper.nonMappedLeafElementsT2())) || argumentExtractedWithDefaultReturnAdded(operationBodyMapper); }
private void checkForExtractedOperationsWithinMovedMethod(UMLOperationBodyMapper movedMethodMapper, UMLClass addedClass) { UMLOperation removedOperation = movedMethodMapper.getOperation1(); UMLOperation addedOperation = movedMethodMapper.getOperation2(); Set<OperationInvocation> removedInvocations = removedOperation.getAllOperationInvocations(); Set<OperationInvocation> addedInvocations = addedOperation.getAllOperationInvocations(); Set<OperationInvocation> intersection = new LinkedHashSet<OperationInvocation>(removedInvocations); intersection.retainAll(addedInvocations); Set<OperationInvocation> newInvocations = new LinkedHashSet<OperationInvocation>(addedInvocations); newInvocations.removeAll(intersection); for(OperationInvocation newInvocation : newInvocations) { for(UMLOperation operation : addedClass.getOperations()) { if(!operation.isAbstract() && !operation.hasEmptyBody() && newInvocation.matchesOperation(operation, addedOperation.variableTypeMap(), this)) { ExtractOperationDetection detection = new ExtractOperationDetection(addedClass.getOperations(), this); ExtractOperationRefactoring refactoring = detection.check(movedMethodMapper, operation); if(refactoring != null) { this.refactorings.add(refactoring); } } } } }