
com.ecfeed.core.operations.GenericRemoveNodesOperation Maven / Gradle / Ivy
/*******************************************************************************
*
* Copyright (c) 2016 ecFeed AS.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
*******************************************************************************/
package com.ecfeed.core.operations;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import com.ecfeed.core.model.AbstractNode;
import com.ecfeed.core.model.AbstractParameterNode;
import com.ecfeed.core.model.ChoiceNode;
import com.ecfeed.core.model.ClassNode;
import com.ecfeed.core.model.ConstraintNode;
import com.ecfeed.core.model.GlobalParameterNode;
import com.ecfeed.core.model.MethodNode;
import com.ecfeed.core.model.MethodParameterNode;
import com.ecfeed.core.model.TestCaseNode;
import com.ecfeed.core.type.adapter.ITypeAdapterProvider;
public class GenericRemoveNodesOperation extends BulkOperation {
private final Set fSelectedNodes;
private final Set fAffectedNodes = new HashSet<>();
private final Set fAffectedTestCases = new HashSet<>();
private final Set fAffectedConstraints = new HashSet<>();
public GenericRemoveNodesOperation(
Collection extends AbstractNode> nodes,
ITypeAdapterProvider adapterProvider,
boolean validate,
AbstractNode nodeToSelect,
AbstractNode nodeToSelectAfterReverseOperation) {
super(OperationNames.REMOVE_NODES,
false,
nodeToSelect,
nodeToSelectAfterReverseOperation);
fSelectedNodes = new HashSet<>(nodes);
Iterator iterator = fSelectedNodes.iterator();
while(iterator.hasNext()){
AbstractNode node = iterator.next();
for(AbstractNode ancestor : node.getAncestors()) {
if(fSelectedNodes.contains(ancestor)) {
iterator.remove();
break;
}
}
}
prepareOperations(adapterProvider, validate);
return;
}
public Set getAffectedConstraints() {
return fAffectedConstraints;
}
public Set getAffectedTestCases() {
return fAffectedTestCases;
}
private void prepareOperations(ITypeAdapterProvider adapterProvider, boolean validate){
HashMap>>> duplicatesMap = new HashMap<>();
HashMap> parameterMap = new HashMap<>();
ArrayList classes = new ArrayList<>();
ArrayList methods = new ArrayList<>();
ArrayList params = new ArrayList<>();
ArrayList globals = new ArrayList<>();
ArrayList choices = new ArrayList<>();
ArrayList others = new ArrayList<>();
HashSet constraints = new HashSet<>();
ArrayList testcases = new ArrayList<>();
for(AbstractNode node : fSelectedNodes) {
if(node instanceof ClassNode){
classes.add((ClassNode)node);
} else if(node instanceof MethodNode){
methods.add((MethodNode)node);
} else if(node instanceof MethodParameterNode){
params.add((MethodParameterNode)node);
} else if(node instanceof GlobalParameterNode){
globals.add((GlobalParameterNode)node);
} else if(node instanceof ConstraintNode){
constraints.add((ConstraintNode)node);
} else if(node instanceof TestCaseNode){
testcases.add((TestCaseNode)node);
} else if(node instanceof ChoiceNode){
choices.add((ChoiceNode)node);
} else{
others.add(node);
}
}
Set allConstraintNodes = getAllConstraintNodes();
Set allTestCaseNodes = getAllTestCaseNodes();
// removing classes, they are independent from anything
for (ClassNode clazz : classes) {
fAffectedNodes.add(clazz);
}
// removing choices and deleting connected constraints/test cases from their respective to-remove lists beforehand
for (ChoiceNode choice : choices) {
createAffectedConstraints(choice, allConstraintNodes);
createAffectedTestCases(choice, allTestCaseNodes);
fAffectedNodes.add(choice);
}
// removing test cases
for (TestCaseNode tcase : testcases) {
fAffectedNodes.add(tcase);
}
// leaving this in case of any further nodes being added
for (AbstractNode node : others) {
fAffectedNodes.add(node);
}
/*
* Iterate through global params. Do the same checks as for method
* parameters with every linker. If no linker is in potentially
* duplicate method - just proceed to remove global and all linkers and
* remove it from the lists.
*/
Iterator globalItr = globals.iterator();
while (globalItr.hasNext()) {
GlobalParameterNode global = globalItr.next();
List linkers = global.getLinkers();
boolean isDependent = false;
for (MethodParameterNode param : linkers) {
MethodNode method = param.getMethod();
if (addMethodToMap(method, duplicatesMap, methods)) {
duplicatesMap.get(method.getClassNode()).get(method.getFullName()).get(method).set(param.getMyIndex(), null);
isDependent = true;
if (!parameterMap.containsKey(method)) {
parameterMap.put(method, new ArrayList());
}
parameterMap.get(method).add(global);
}
}
if (!isDependent) {
//remove mentioning constraints from the list to avoid duplicates
createAffectedConstraints(global, allConstraintNodes);
fAffectedNodes.add(global);
globalItr.remove();
/*
* in case linkers contain parameters assigned to removal -
* remove them from list; Global param removal will handle them.
*/
for (MethodParameterNode param : linkers) {
params.remove(param);
}
}
}
/*
* Iterate through parameters. If parent method is potential duplicate -
* add it to map for further validation. Replace values of to-be-deleted
* param with NULL to remove them later without disturbing parameters
* order. If parameters method is not potential duplicate - simply
* forward it for removal and remove it from to-remove list.
*/
Iterator paramItr = params.iterator();
while (paramItr.hasNext()) {
MethodParameterNode param = paramItr.next();
MethodNode method = param.getMethod();
if (addMethodToMap(method, duplicatesMap, methods)) {
duplicatesMap.get(method.getClassNode()).get(method.getFullName()).get(method).set(param.getMyIndex(), null);
if (!parameterMap.containsKey(method)) {
parameterMap.put(method, new ArrayList());
}
parameterMap.get(method).add(param);
} else {
//remove mentioning constraints from the list to avoid duplicates
createAffectedConstraints(param, allConstraintNodes);
fAffectedNodes.add(param);
paramItr.remove();
}
}
//Removing methods - information for model map has been already taken
Iterator methodItr = methods.iterator();
while (methodItr.hasNext()) {
MethodNode method = methodItr.next();
fAffectedNodes.add(method);
methodItr.remove();
}
// Detect duplicates
Iterator classItr = duplicatesMap.keySet().iterator();
while (classItr.hasNext()) {
ClassNode classNext = classItr.next();
Iterator nameItr = duplicatesMap.get(classNext).keySet().iterator();
while (nameItr.hasNext()) {
// delete removed parameters marked with null (set?)
// remember that we are validating both param and method removal at once. Need to store params somewhere else.
HashSet> paramSet = new HashSet<>();
String strNext = nameItr.next();
methodItr = duplicatesMap.get(classNext).get(strNext).keySet().iterator();
while (methodItr.hasNext()) {
MethodNode methodNext = methodItr.next();
List paramList = duplicatesMap.get(classNext).get(strNext).get(methodNext);
Iterator parameterItr = paramList.iterator();
//removing parameters from model image
while (parameterItr.hasNext()) {
if (parameterItr.next() == null) {
parameterItr.remove();
}
}
paramSet.add(paramList);
}
// There is more methods than method signatures, ergo duplicates present. Proceeding to remove with duplicate check on.
Set methodSet = duplicatesMap.get(classNext).get(strNext).keySet();
if (paramSet.size() < methodSet.size()) {
for (MethodNode method : methodSet) {
if (parameterMap.containsKey(method)) {
for (AbstractParameterNode node : parameterMap.get(method)) {
//remove mentioning constraints from the list to avoid duplicates
createAffectedConstraints(node, allConstraintNodes);
fAffectedNodes.add(node);
}
}
}
}
// Else remove with duplicate check off;
else {
for (MethodNode method : methodSet) {
if (parameterMap.containsKey(method)) {
for (AbstractParameterNode node : parameterMap.get(method)) {
//remove mentioning constraints from the list to avoid duplicates
createAffectedConstraints(node, allConstraintNodes);
if (node instanceof MethodParameterNode) {
addOperation(new MethodOperationRemoveParameter(method, (MethodParameterNode)node, validate, true));
} else if (node instanceof GlobalParameterNode) {
addOperation(new GenericOperationRemoveGlobalParameter(((GlobalParameterNode)node).getParametersParent(), (GlobalParameterNode)node, true));
}
}
}
}
}
}
}
for (ConstraintNode constraint : constraints) {
fAffectedNodes.add(constraint);
}
fAffectedConstraints.stream().forEach(
e-> addOperation(FactoryRemoveOperation.getRemoveOperation(e, adapterProvider, validate)));
fAffectedTestCases.stream().forEach(
e-> addOperation(FactoryRemoveOperation.getRemoveOperation(e, adapterProvider, validate)));
fAffectedNodes.stream().forEach(
e-> addOperation(FactoryRemoveOperation.getRemoveOperation(e, adapterProvider, validate)));
}
private Set getAllConstraintNodes() {
return fSelectedNodes.iterator().next()
.getRoot()
.getChildren()
.stream()
.filter(e -> (e instanceof ClassNode))
.map(m -> m.getChildren()
.stream()
.filter(e -> (e instanceof MethodNode))
.collect(Collectors.toList()))
.flatMap(f -> f.stream())
.map(m -> m.getChildren()
.stream()
.filter(e -> (e instanceof ConstraintNode))
.collect(Collectors.toList()))
.flatMap(f -> f.stream())
.map(e -> (ConstraintNode) e)
.collect(Collectors.toSet());
}
private Set getAllTestCaseNodes() {
return fSelectedNodes.iterator().next()
.getRoot()
.getChildren()
.stream()
.filter(e -> (e instanceof ClassNode))
.map(m -> m.getChildren()
.stream()
.filter(e -> (e instanceof MethodNode))
.collect(Collectors.toList()))
.flatMap(f -> f.stream())
.map(m -> m.getChildren()
.stream()
.filter(e -> (e instanceof TestCaseNode))
.collect(Collectors.toList()))
.flatMap(f -> f.stream())
.map(e -> (TestCaseNode) e)
.collect(Collectors.toSet());
}
private boolean addMethodToMap(MethodNode method, HashMap>>> duplicatesMap, List removedMethods){
ClassNode clazz = method.getClassNode();
boolean hasDuplicate = false;
for(MethodNode classMethod : clazz.getMethods()){
if(classMethod != method && classMethod.getFullName().equals(method.getFullName()) && !removedMethods.contains(classMethod)){
if(duplicatesMap.get(clazz) == null){
duplicatesMap.put(clazz, new HashMap>>());
}
if(!(duplicatesMap.get(clazz).containsKey(classMethod.getFullName()))){
duplicatesMap.get(clazz).put(classMethod.getFullName(), new HashMap>());
}
if(!duplicatesMap.get(clazz).get(classMethod.getFullName()).containsKey(classMethod)){
duplicatesMap.get(clazz).get(classMethod.getFullName())
.put(classMethod, new ArrayList(classMethod.getParameterTypes()));
}
if(!duplicatesMap.get(clazz).get(classMethod.getFullName()).containsKey(method)){
duplicatesMap.get(clazz).get(classMethod.getFullName()).put(method, new ArrayList(method.getParameterTypes()));
}
hasDuplicate = true;
}
}
return hasDuplicate;
}
private void createAffectedConstraints(AbstractNode node, Set allConstraintNodes) {
if (node instanceof ChoiceNode) {
Iterator itr = allConstraintNodes.iterator();
while (itr.hasNext()) {
ConstraintNode constraint = itr.next();
if (constraint.mentions((ChoiceNode)node)) {
fAffectedConstraints.add(constraint);
}
}
} else if (node instanceof AbstractParameterNode) {
Iterator itr = allConstraintNodes.iterator();
while (itr.hasNext()) {
ConstraintNode constraint = itr.next();
if (constraint.mentions((AbstractParameterNode)node)) {
fAffectedConstraints.add(constraint);
}
}
}
}
private void createAffectedTestCases(AbstractNode node, Set allTestCaseNodes) {
Iterator itr = allTestCaseNodes.iterator();
while (itr.hasNext()) {
TestCaseNode testCase = itr.next();
if (testCase.mentions((ChoiceNode)node)) {
fAffectedTestCases.add(testCase);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy