code: package gr.uom.java.jdeodorant.refactoring.manipulators;
  
  import gr.uom.java.ast.inheritance.InheritanceTree;
  
  import java.util.ArrayList;
  import java.util.Collections;
  import java.util.LinkedHashSet;
  import java.util.List;
  import java.util.Set;
  
  import org.eclipse.jdt.core.dom.SimpleName;
  
  public class TypeCheckEliminationGroup implements Comparable<TypeCheckEliminationGroup> {
  	private List<TypeCheckElimination> candidates;
  	private int groupSizeAtSystemLevel;
  	private double averageGroupSizeAtClassLevel;
  	private double averageNumberOfStatementsInGroup;
  	
  	public TypeCheckEliminationGroup() {
  		this.candidates = new ArrayList<TypeCheckElimination>();
  	}
  
  	public void addCandidate(TypeCheckElimination elimination) {
  		this.candidates.add(elimination);
  	}
  
  	public List<TypeCheckElimination> getCandidates() {
  		Collections.sort(candidates);
  		return candidates;
  	}
  
  	public int getGroupSizeAtSystemLevel() {
  		return groupSizeAtSystemLevel;
  	}
  
  	public void setGroupSizeAtSystemLevel(int groupSizeAtSystemLevel) {
  		this.groupSizeAtSystemLevel = groupSizeAtSystemLevel;
  	}
  
  	public double getAverageGroupSizeAtClassLevel() {
  		return averageGroupSizeAtClassLevel;
  	}
  
  	public void setAverageGroupSizeAtClassLevel(double averageGroupSizeAtClassLevel) {
  		this.averageGroupSizeAtClassLevel = averageGroupSizeAtClassLevel;
  	}
  
  	public double getAverageNumberOfStatementsInGroup() {
  		return averageNumberOfStatementsInGroup;
  	}
  
  	public void setAverageNumberOfStatementsInGroup(double averageNumberOfStatementsInGroup) {
  		this.averageNumberOfStatementsInGroup = averageNumberOfStatementsInGroup;
  	}
  
  	public Set<String> getConstantVariables() {
  		TypeCheckElimination elimination = (TypeCheckElimination)candidates.toArray()[0];
  		if(elimination.getExistingInheritanceTree() == null && elimination.getInheritanceTreeMatchingWithStaticTypes() == null) {
  			Set<String> constantVariables = new LinkedHashSet<String>();
  			for(SimpleName simpleName : elimination.getStaticFields())
  				constantVariables.add(simpleName.getIdentifier());
  			for(SimpleName simpleName : elimination.getAdditionalStaticFields())
  				constantVariables.add(simpleName.getIdentifier());
  			return constantVariables;
  		}
  		return null;
  	}
  
  	public InheritanceTree getInheritanceTree() {
  		TypeCheckElimination elimination = (TypeCheckElimination)candidates.toArray()[0];
  		InheritanceTree tree = null;
  		if(elimination.getExistingInheritanceTree() != null)
  			tree = elimination.getExistingInheritanceTree();
  		else if(elimination.getInheritanceTreeMatchingWithStaticTypes() != null) {
  			tree = elimination.getInheritanceTreeMatchingWithStaticTypes();
  		}
  		return tree;
  	}
  
  	public int compareTo(TypeCheckEliminationGroup other) {
  		int groupSizeAtSystemLevel1 = this.getGroupSizeAtSystemLevel();
  		int groupSizeAtSystemLevel2 = other.getGroupSizeAtSystemLevel();
  		double averageNumberOfStatementsInGroup1 = this.getAverageNumberOfStatementsInGroup();
  		double averageNumberOfStatementsInGroup2 = other.getAverageNumberOfStatementsInGroup();
  		
  		if(groupSizeAtSystemLevel1 > groupSizeAtSystemLevel2)
  			return -1;
  		if(groupSizeAtSystemLevel1 < groupSizeAtSystemLevel2)
  			return 1;
  		
  		if(averageNumberOfStatementsInGroup1 > averageNumberOfStatementsInGroup2)
  			return -1;
  		if(averageNumberOfStatementsInGroup1 < averageNumberOfStatementsInGroup2)
  			return 1;
  		
  		Set<String> constantVariables1 = this.getConstantVariables();
  		Set<String> constantVariables2 = other.getConstantVariables();
  		if(constantVariables1 != null && constantVariables2 != null) {
  			if(!constantVariables1.equals(constantVariables2)) {
  				StringBuilder sb1 = new StringBuilder();
  				for(String s : constantVariables1)
  					sb1.append(s);
  				StringBuilder sb2 = new StringBuilder();
  				for(String s : constantVariables2)
  					sb2.append(s);
  				return sb1.toString().compareTo(sb2.toString());
  			}
  		}
  		InheritanceTree tree1 = this.getInheritanceTree();
  		InheritanceTree tree2 = other.getInheritanceTree();
  		if(tree1 != null && tree2 != null) {
  			String root1 = (String)tree1.getRootNode().getUserObject();
  			String root2 = (String)tree2.getRootNode().getUserObject();
  			if(!root1.equals(root2)) {
  				return root1.compareTo(root2);
  			}
  		}
  		return 0;
  	}
  
  	public String toString() {
  		Set<String> constantVariables = this.getConstantVariables();
  		if(constantVariables != null)
  			return "constant variables: " + constantVariables;
  		InheritanceTree tree = this.getInheritanceTree();
  		if(tree != null)
  			return "inheritance hierarchy: " + "[" + tree.getRootNode().getUserObject().toString() + "]";
  		return "";
  	}
  }
  