blob: 5f1fdd5e0f4baa1de05eade1760dbdc3fe9a9f9f [file] [log] [blame]
package org.eclipse.emf.refactor.smells.uml24;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.refactor.smells.interfaces.IModelSmellFinder;
import org.eclipse.uml2.uml.Class;
import org.eclipse.uml2.uml.Model;
import org.eclipse.uml2.uml.Property;
public final class EqualAttributesinSiblingClasses implements IModelSmellFinder {
@Override
public LinkedList<LinkedList<EObject>> findSmell(EObject root) {
LinkedList<LinkedList<EObject>> results = new LinkedList<LinkedList<EObject>>();
List<Property> attributes = getAllClassAttributes(root);
for (Property attribute : attributes) {
Class owningClass = attribute.getClass_();
List<Class> superClasses = owningClass.getSuperClasses();
for (Class superClass : superClasses) {
if (eachSubClassContainsAttribute(superClass, attribute)) {
LinkedList<EObject> result = new LinkedList<EObject>();
result.add(attribute.getClass_());
result.add(attribute);
results.add(result);
}
}
}
return results;
}
private boolean eachSubClassContainsAttribute(Class superClass, Property attribute) {
List<Class> subClasses = new ArrayList<Class>();
List<Class> allClasses = getAllClasses(superClass.getModel());
for (Class modelClass : allClasses) {
if (modelClass != attribute.getClass_() && modelClass.getSuperClasses().contains(superClass)) {
subClasses.add(modelClass);
}
}
if (subClasses.isEmpty()) return false;
for (Class subClass : subClasses) {
if (! classContainsEqualAttribute(subClass, attribute)) {
return false;
}
}
return true;
}
private boolean classContainsEqualAttribute(Class cls, Property attribute) {
if (attribute.getClass_().equals(cls)) return true;
boolean classHasEqualAttribute = false;
for (Property attr : cls.getOwnedAttributes()) {
if (! haveSameNames(attr, attribute)) continue;
if (! haveSameType(attr, attribute)) continue;
if (! haveSameVisibilities(attr, attribute)) continue;
if (! haveSameMultiplicities(attr, attribute)) continue;
if (! haveSameAggregations(attr, attribute)) continue;
if (! haveSameDefaultValues(attr, attribute)) continue;
if (! haveSameDerivedProperties(attr, attribute)) continue;
if (! haveSameLeafProperties(attr, attribute)) continue;
if (! haveSameReadOnlyProperties(attr, attribute)) continue;
if (! haveSameUniqueProperties(attr, attribute)) continue;
if (! haveSameOrderedProperties(attr, attribute)) continue;
if (! haveSameStaticProperties(attr, attribute)) continue;
if (! haveSameDerivedUnionProperties(attr, attribute)) continue;
if ((attr.getAssociation() != null) && (attribute.getAssociation() != null)) {
if (getOtherSideUpper(attr) != getOtherSideUpper(attribute)) continue;
}
classHasEqualAttribute = true;
break;
}
return classHasEqualAttribute;
}
private int getOtherSideUpper(Property attribute) {
int upper = 0;
for (Property ae : attribute.getAssociation().getMemberEnds()) {
if (! ae.equals(attribute)) upper = ae.getUpper();
}
return upper;
}
private boolean haveSameDerivedUnionProperties(Property att1, Property att2) {
return (att1.isDerivedUnion() == att2.isDerivedUnion());
}
private boolean haveSameStaticProperties(Property att1, Property att2) {
return (att1.isStatic() == att2.isStatic());
}
private boolean haveSameOrderedProperties(Property att1, Property att2) {
return (att1.isOrdered() == att2.isOrdered());
}
private boolean haveSameUniqueProperties(Property att1, Property att2) {
return (att1.isUnique() == att2.isUnique());
}
private boolean haveSameReadOnlyProperties(Property att1, Property att2) {
return (att1.isReadOnly() == att2.isReadOnly());
}
private boolean haveSameLeafProperties(Property att1, Property att2) {
return (att1.isLeaf() == att2.isLeaf());
}
private boolean haveSameDerivedProperties(Property att1, Property att2) {
return (att1.isDerived() == att2.isDerived());
}
private boolean haveSameDefaultValues(Property att1, Property att2) {
if ((att1.getDefault() == null) && (att2.getDefault() == null)) return true;
if ((att1.getDefault() != null)
&& (att2.getDefault() != null)
&& (att1.getDefault().equals(att2.getDefault()))) return true;
return false;
}
private boolean haveSameAggregations(Property att1, Property att2) {
return att1.getAggregation().equals(att2.getAggregation());
}
private boolean haveSameMultiplicities(Property att1, Property att2) {
return ((att1.getLower() == att2.getLower())
&& (att1.getUpper() == att2.getUpper()));
}
private boolean haveSameVisibilities(Property att1, Property att2) {
return att1.getVisibility().equals(att2.getVisibility());
}
private boolean haveSameNames(Property att1, Property att2) {
return att1.getName().equals(att2.getName());
}
private boolean haveSameType(Property att1, Property att2) {
if ((att1.getType() == null) && (att2.getType() == null)) return true;
if ((att1.getType() != null)
&& (att2.getType() != null)
&& (att1.getType().equals(att2.getType()))) return true;
return false;
}
private ArrayList<Class> getAllClasses(Model model) {
ArrayList<Class> classes = new ArrayList<Class>();
// TreeIterator<EObject> iter = model.eResource().getAllContents();
TreeIterator<EObject> iter = getRoot(model).eAllContents();
while (iter.hasNext()) {
EObject eObject = iter.next();
if (eObject instanceof Class) {
classes.add((Class) eObject);
}
}
return classes;
}
private EObject getRoot(EObject eObject) {
if (eObject.eContainer() == null) return eObject;
else return getRoot(eObject.eContainer());
}
private List<Property> getAllClassAttributes(EObject root) {
List<Property> attributes = new ArrayList<Property>();
TreeIterator<EObject> iter = root.eAllContents();
while (iter.hasNext()) {
EObject eObject = iter.next();
if (eObject instanceof Property) {
Property prop = (Property) eObject;
if (prop.getClass_() != null) {
attributes.add(prop);
}
}
}
return attributes;
}
}