package br.uff.ic.gems.peixeespadacliente.tool; import br.uff.ic.gems.peixeespadacliente.exception.RefactoringException; import br.uff.ic.gems.peixeespadacliente.model.ProjectVCS; import br.uff.ic.gems.peixeespadacliente.symptom.PullPushMethodSymptom; import br.uff.ic.gems.peixeespadacliente.symptom.Symptom; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import net.sf.refactorit.classmodel.BinCIType; import net.sf.refactorit.classmodel.BinCITypeRef; import net.sf.refactorit.classmodel.BinMember; import net.sf.refactorit.classmodel.BinMethod; import net.sf.refactorit.classmodel.BinSourceTypeRef; /** * * @author Heliomar, João Felipe */ public class PushDownMethods extends PullPushMethodRefactoringTool { public PushDownMethods(ProjectVCS projectVCS) { super(projectVCS); } private boolean hasMemberInHierarchy(BinCITypeRef superClass, BinCITypeRef subClass, BinMember member) { if (subClass.getBinCIType().hasMemberWithSignature(member) != null) { return true; } Set middleClasses = subClass.getAllSupertypes(); //Encontra todos superiores da classe destino Set subClasses = new HashSet(superClass.getAllSubclasses()); //Encontra todos os inferiores entre o destino e a classe que possui o membro middleClasses.retainAll(subClasses); //Interseção = Todos entre a classe que possui e o destino return hasMemberInHierarchySet(middleClasses, member) || hasMemberInHierarchySet(superClass.getAllSupertypes(), member); } private boolean hasMemberInHierarchySet(Set classes, BinMember member) { for (Object sClass : classes) { if (sClass instanceof BinCITypeRef) { if (((BinCITypeRef) sClass).getBinCIType().hasMemberWithSignature(member) != null) { return true; } } else if (sClass instanceof BinSourceTypeRef) { if (((BinSourceTypeRef) sClass).getBinCIType().hasMemberWithSignature(member) != null) { return true; } } } return false; } private boolean isInterfaceOrAbstract(BinCITypeRef subClass) { return (subClass.getBinType().isAbstract() || subClass.getBinType().isAbstract()); } @Override public List<Symptom> findAllSymptoms() throws RefactoringException { if (!loadEnvironment()) { return null; } List<Symptom> result = new ArrayList<Symptom>(); for (Object object : getProject().getDefinedTypes()) { BinCITypeRef superClassCandidate = (BinCITypeRef) object; BinCIType bcit = superClassCandidate.getBinCIType(); if (!classShouldBeVerified(superClassCandidate)) { continue; } if (!bcit.isInterface()) { List<BinCITypeRef> listaSubClasses = superClassCandidate.getAllSubclasses(); for (BinMethod binMethod : superClassCandidate.getBinCIType().getDeclaredMethods()) { for (BinCITypeRef subClass : listaSubClasses) { if (!classShouldBeVerified(subClass)) { continue; } if ((binMethod.isAbstract() && isInterfaceOrAbstract(subClass)) || //Move metodo abstrato para classe abstrata ou interface ((!binMethod.isAbstract()) && (!isInterfaceOrAbstract(subClass))) || //Move metodo não abstrato para classe não abstrata nem interface ((!binMethod.isAbstract()) && (bcit.isAbstract()) && (subClass.getBinCIType().isAbstract())) || //Move metodo não abstrato de classe abstrata para classe abstrata (false) // ((!binMethod.isOverriddenOrOverrides())) ) { if (!hasMemberInHierarchy(superClassCandidate, subClass, binMethod)) { Symptom symptom = new PullPushMethodSymptom(binMethod, subClass.getBinCIType(), this); result.add(symptom); } } } } } } return result; } }