package compareAlgorithm;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.codec.EncoderException;
import org.apache.commons.codec.language.RefinedSoundex;
import org.apache.commons.codec.language.Soundex;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EOperation;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import controller.diagramparser.ClassDiagramParser;
import controller.diagramparser.DiagramParser;
import domain.CD_Attribute;
import domain.CD_Class;
import domain.CD_Operation;
import domain.CD_Reference;
/**
* Algorithm class that compares all the features of a class diagram.
*
* @author Gautam Ch
*
*
*/
public class UnifiedAlgorithm {
private DiagramParser diagParser1;
private DiagramParser diagParser2;
private EList<EObject> firstModel; // ECore objects
private EList<EObject> secondModel;
private ECorePackage ePackage1; // Packages
private ECorePackage ePackage2;
private ArrayList<String> matchedClasses; // Records matched classes
private ArrayList<String> comparedClasses; // Records compared classes
private ArrayList<String> partialMatchedClasses; //Record Partially matched classes
private String reportText;
private int noOfComparison;
//private ArrayList<String> similarClasses;
//private ArrayList<String> aloneClasses;
Report report; // for writing report to the pdf file
/**
* Constructor to initialize necessary class members.
*
* @param firstDiagram
* first diagram to compare
* @param secondParser
* second diagram to compare
* @param reportFile
* path to store report
*/
public UnifiedAlgorithm(DiagramParser firstDiagram, DiagramParser secondParser,
String reportFile) {
this.diagParser1 = firstDiagram;
this.diagParser2 = secondParser;
report = new Report(reportFile);
matchedClasses = new ArrayList<String>();
comparedClasses = new ArrayList<String>();
partialMatchedClasses = new ArrayList<String>();
noOfComparison = 0;
}
public void testClasses() {
List<CD_Class> classList = ((ClassDiagramParser) diagParser1).getClasses();
for(CD_Class cdClass : classList) {
System.out.println("Class Name: " + cdClass.getClassName());
}
}
/**
* Main dispatch function for comparing the features of a class.
*/
public String compare() {
// report.addToReport("Comparison Report\n");
reportText = "\nReport \n\n";
report.addToReport("\nChecking individual classes due to absence of packages:");
reportText += "Checking individual classes due to absence of packages:\n\n";
List<CD_Class> classList1 = ((ClassDiagramParser) diagParser1).getClasses();
List<CD_Class> classList2 = ((ClassDiagramParser) diagParser2).getClasses();
for(CD_Class cdClass1 : classList1) {
for(CD_Class cdClass2 : classList2) {
compareUnPackedClasses(cdClass1, cdClass2);
}
}
// Reporting unmatch classes
reportUnmatchedClasses();
reportPartialMatchedClasses();
//********************************For testing matchedClasses, plz keep
reportMatchedClasses();
// Close the report
report.finalize();
// if (comparePackage()) {
// eClass1 = new ECoreClass(ePackage1);
// eClass2 = new ECoreClass(ePackage2);
//
// // Comparing classes entirely including the details
// compareClasses(eClass1, eClass2);
//
// // Reporting unmatch classes
// reportUnmatchedClasses();
//
// } else {
// report.addToReport("Checking individual classes due to absence of packages");
// for (int i = 0; i < firstModel.size(); i++) {
// EClass firstClass = (EClass) firstModel.get(i);
// for (int j = 0; j < secondModel.size(); j++) {
// EClass secondClass = (EClass) secondModel.get(j);
// compareUnPackedClasses(firstClass, secondClass);
// }
// }
//
// // Reporting unmatch classes
// reportUnmatchedClasses();
// }
//
// //********************************For testing matchedClasses, plz keep, Dong Guo
// for(int i = 0; i < matchedClasses.size(); i++){
// report.addToReport(i + ": " + matchedClasses.get(i));
// }
// //**********************************************************
//
// // Close the report
// report.finalize();
return reportText;
}
/**
* Checks packages and returns if the packages are similar or not.
*
* @return true if similar else false
*/
private boolean comparePackage() {
// report.startRoutine("packages");
try {
if (checkPackages()) {
ePackage1 = new ECorePackage(firstModel);
ePackage2 = new ECorePackage(secondModel);
if (packageNameSimilar(ePackage1.getName(), ePackage2.getName()) > 0) {
report.addToReport("Packages match : "
+ ePackage1.getName() + " and "
+ ePackage2.getName());
reportText += "Packages match : "
+ ePackage1.getName() + " and "
+ ePackage2.getName() + "\n\n";
return true;
} else {
report.addToReport("Packages don't match\n"
+ "\nName of first Package : "
+ ePackage1.getName()
+ "\n Name of second Package : "
+ ePackage1.getName());
reportText += "Packages don't match\n\n"
+ "\nName of first Package : "
+ ePackage1.getName()
+ "\n Name of second Package : "
+ ePackage1.getName() + "\n\n";
return false;
}
} else {
return false;
}
} catch (Exception ex) {
// ex.printStackTrace();
} finally {
// report.terminateRoutine("Packages");
}
return false;
}
/**
* Checking if files are in proper format
*
* @return true if files are valid, false otherwise
*/
private boolean checkPackages() {
if (firstModel.get(0) instanceof EPackage) {
if (secondModel.get(0) instanceof EPackage) {
} else {
report.addToReport("Could not find packages in second model");
reportText += "Could not find packages in second model\n\n";
return false;
}
} else {
report.addToReport("Could not find packages in first model");
reportText += "Could not find packages in first model\n\n";
return false;
}
return true;
}
/**
* Compares package names.
*
* @param firstName
* first name to compare
* @param secondName
* second name to compare
* @return true if names match else false
*/
private int packageNameSimilar(String firstName, String secondName) {
return this.compareNames(firstName, secondName);
}
/**
* General method for comparing any pair of names.
*
* @param name1
* - first name to compare
* @param name2
* - second name to compare
* @return PERFECT_MATCH if same names
* @return PARTIAL_MATCH if names are similar based on soundex comparison
* @return NOT_MATCH if names not matched at all
*/
private int compareNames(String name1, String name2) {
try {
// boolean firstStringLonger = name1.length() > name2.length();
// int maxCount = 0;
// if(firstStringLonger)
// maxCount = name2.length();
// else
//
Soundex soundex = new Soundex();
// new RefinedSoundex().difference(name1, name2) ==
if (soundex.difference(name1.toString(), name2.toString()) == 4) {
if(name1.equalsIgnoreCase(name2)) {
return Constants.PERFECT_MATCH;
}
}
if (soundex.difference(name1.toString(), name2.toString()) > 2) {
if(name1.toLowerCase().contains(name2.toLowerCase()) || name2.toLowerCase().contains(name1.toLowerCase())) {
return Constants.PARTIAL_MATCH;
}
}
// if (new Soundex().difference(name1.toString(), name2.toString()) == 4) {
// return Constants.PERFECT_MATCH;
// }
// if (new Soundex().difference(name1, name2) > 2) {
// return Constants.PARTIAL_MATCH;
// }
} catch (EncoderException e) {
return Constants.NOT_MATCH;
}
return Constants.NOT_MATCH;
}
/**
* Compare package information. If package are the same, compare class
* details. If package are not the same, compare structure details. Adds
* comments to report.
*
* @param cdClass1
* first class to compare
* @param cdClass2
* second class to compare
*/
private void compareUnPackedClasses(CD_Class cdClass1, CD_Class cdClass2) {
// report.startRoutine("classes");
try {
report.addToReport("\n" + ++noOfComparison + ". Comparing classes: " + cdClass1.getClassName()
+ " : " + cdClass2.getClassName());
reportText += noOfComparison + ". Comparing classes: \t" + cdClass1.getClassName()
+ " : " + cdClass2.getClassName() + "\n\n";
// compare class names by soundex
int comparedValue = compareNames(cdClass1.getClassName(), cdClass2.getClassName());
if (comparedValue == Constants.PERFECT_MATCH) {
// add classes to the list of matched classes
matchedClasses.add(cdClass1.getClassName());
//matchedClasses.add(cdClass2.getClassName());
// add to the report
report.addToReport(" Class Name Match: Perfect");
reportText += "\tPerfect Name Match: \t" + cdClass1.getClassName()
+ " : " + cdClass2.getClassName() + "\n\n";
// send the classes for comparing details
compareClassDetails(cdClass1, cdClass2);
} else {
if(comparedValue == Constants.PARTIAL_MATCH)
{
partialMatchedClasses.add(cdClass1.getClassName());
partialMatchedClasses.add(cdClass2.getClassName());
report.addToReport(" Class Name Match: Partial");
// Pass the two classes for structural class comparison
this.structuralComparison(cdClass1, cdClass2);
}
else {
report.addToReport(" Class Name Match : No Match");
}
}
listComparedClasses(cdClass1, cdClass2);
} catch (Exception ex) {
ex.printStackTrace();
} finally {
// report.terminateRoutine("Unpacked Classes");
}
}
/**
* Compares Classes. Finds perfect and partial match. Adds comments to
* report object.
*
* @param firstEClass
* first class to compare
* @param secondEClass
* second class to compare
*/
/*private void compareClasses(ECoreClass firstEClass, ECoreClass secondEClass) {
// report.startRoutine("classes");
try {
for (int x = 0; x < firstEClass.size(); x++) {
// flag for determining whether a class is found
boolean classFound = false;
EClass class1 = firstEClass.getEClass(x);
for (int y = 0; y < secondEClass.size(); y++) {
EClass class2 = secondEClass.getEClass(y);
// compare class names by soundex
int comparedValue = compareNames(class1.getName(),
class2.getName());
if (comparedValue == Constants.PERFECT_MATCH) {
// add classes to the list of matched classes
matchedClasses.add(class1.getName());
matchedClasses.add(class2.getName());
// add to the report
report.addToReport("Perfect Match : "
+ class1.getName() + " : " + class2.getName());
// send the classes for comparing details
compareClassDetails(class1, class2);
// set the flag
classFound = true;
} else {
// Pass the two classes for structural class comparison
this.structuralComparison(class1, class2);
// set the flag
classFound = true;
}
}
}
} catch (Exception ex) {
ex.printStackTrace();
} finally {
// report.terminateRoutine("Classes");
}
}*/
/**
* Compare classes details after classes match.
*
* @param cdClass1
* first class to compare
* @param cdClass2
* second class to compare
*/
private void compareClassDetails(CD_Class cdClass1, CD_Class cdClass2) {
compareSuperClass(cdClass1, cdClass2);
compareAttributes(cdClass1, cdClass2);
compareMethods(cdClass1, cdClass2);
compareReferences(cdClass1, cdClass2);
/*
* If the classes match each other,
* they will be added into matchedClasses in compareClasses()
* These two lines are duplicated.
*
* Dong Guo 02/17/2013
*/
//matchedClasses.add(cls1.getName());
//matchedClasses.add(cls2.getName());
}
/**
* Compares super classes of designated classes and adds comments to report
* object.
*
* @param cdClass1
* first class to compare super class
* @param cdClass2
* second class to compare super class
*/
private void compareSuperClass(CD_Class cdClass1, CD_Class cdClass2) {
// report.startRoutine("super classes");
try {
// Get super class list from classes
List<CD_Class> superClassList1 = cdClass1.getSuperClasses();
List<CD_Class> superClassList2 = cdClass2.getSuperClasses();
// Select classes one by one and compare
for (CD_Class superClass1 : superClassList1) {
for (CD_Class superClass2 : superClassList2) {
if (compareNames(superClass1.getClassName(),
superClass2.getClassName()) > 0) {
report.addToReport(" Super Classes matched: "
+ "First: " + superClass1.getClassName()
+ " with " + "Second: "
+ superClass2.getClassName());
reportText += "\tSuper Classes matched: " + "First Diagram Super Class: " + superClass1.getClassName()
+ " with " + "Second Diagram Super Class: " + superClass2.getClassName() + "\n\n";
}
}
}
} catch (Exception ex) {
ex.printStackTrace();
} finally {
// report.terminateRoutine("Super classes");
}
}
/**
* Compare class attributes and adds comments to report object.
*
* @param cdClass1
* first class containing attribute to compare
* @param cdClass2
* second class containing attributes to compare
*/
private void compareAttributes(CD_Class cdClass1, CD_Class cdClass2) {
// report.startRoutine("attributes");
try {
List<CD_Attribute> attrList1 = cdClass1.getAttributes();
List<CD_Attribute> attrList2 = cdClass2.getAttributes();
for (int i = 0; i < attrList1.size(); i++) {
// flag set if attribute found
boolean attrFound = false;
for (int j = 0; j < attrList2.size(); j++) {
if (compareNames(attrList1.get(i).getAttrName(),
attrList2.get(j).getAttrName()) > 1) {
// set the flag
attrFound = true;
report.addToReport(" Attributes name matches: "
+ "first " + attrList1.get(i).getAttrName()
+ " with " + "second "
+ attrList2.get(i).getAttrName());
reportText += "\tAttributes name matches: " + "first: " + attrList1.get(i).getAttrName()
+ " with " + "second: " + attrList2.get(i).getAttrName() + "\n\n";
// compare attribute type
if (compareETypes(attrList1.get(i).getAttrType(),
attrList2.get(j).getAttrType())) {
report.addToReport(" Attributes type matches: "
+ "first "
+ attrList1.get(j).getAttrType()
+ " with " + "second "
+ attrList2.get(j).getAttrType());
reportText += "\tAttributes type matches : " + "first: " + attrList1.get(j).getAttrType()
+ " with " + "second: " + attrList2.get(j).getAttrType() + "\n\n";
}
}
}
// add to report the unmatched attribute
if (!attrFound) {
report.addToReport(" Attributes from first that don't match : "
+ attrList1.get(i).getAttrName());
reportText += "Attributes from first that don't match : "
+ attrList1.get(i).getAttrName() + "\n\n";
}
}
} catch (Exception ex) {
ex.printStackTrace();
} finally {
// report.terminateRoutine("Attributes");
}
}
/**
* Compare methods by method name and type and adds comments to report
* object.
*
* @param cdClass1
* first class containing operations to compare
* @param cdClass2
* second class containing operations to compare
*/
private void compareMethods(CD_Class cdClass1, CD_Class cdClass2) {
// report.startRoutine("methods");
try {
// EList<EOperation> methodList1 = cdClass1.getEAllOperations();
// EList<EOperation> methodList2 = cdClass2.getEAllOperations();
List<CD_Operation> methodList1 = cdClass1.getOperations();
List<CD_Operation> methodList2 = cdClass2.getOperations();
for(CD_Operation operation1 : methodList1) {
for (CD_Operation operation2 : methodList2) {
if (compareNames(operation1.getOperationName(), operation2.getOperationName()) > 0) {
report.addToReport(" Methods name matches : " + "first "
+ operation1.getOperationName() + " with "
+ "second " +operation2.getOperationName());
reportText += "Methods name matches : " + "first " + operation1.getOperationName() + " with "
+ "second " +operation2.getOperationName() + "\n\n";
if (this.compareETypes(operation1.getReturnType(),
operation2.getReturnType())) {
report.addToReport(" Methods return type matches : "
+ "first "
+ operation1.getReturnType()
+ " with " + "second "
+ operation2.getReturnType());
reportText += "Methods return type matches : " + "first " + operation1.getReturnType()
+ " with " + "second " + operation2.getReturnType() + "\n\n";
}
}
}
}
} catch (Exception ex) {
ex.printStackTrace();
} finally {
// report.terminateRoutine("Methods");
}
}
/**
* Compare references of a class. Adds comments to report object if
* references match or not.
*
* @param cdClass1
* first class containing references to compare
* @param cdClass2
* second class containing references to compare
*/
private void compareReferences(CD_Class cdClass1, CD_Class cdClass2) {
// report.addToReport("references");
try {
List<CD_Reference> refList1 = cdClass1.getReferences();
List<CD_Reference> refList2 = cdClass2.getReferences();
for (CD_Reference reference1 : refList1) {
// flag set if references match
boolean refFound = false;
for (CD_Reference reference2 : refList2) {
if (this.compareNames(reference1.getReferenceTypeName(),
reference2.getReferenceTypeName()) > 0) {
// add to report
report.addToReport(" Reference Name match : "
+ reference1.getReferenceName());
reportText += "Reference Name match : " + reference1.getReferenceName() + "\n\n";
String refName1 = reference1.getReferenceTypeName().toString();
String refName2 = reference2.getReferenceTypeName().toString();
// compare opposite reference
if (compareNames(refName1, refName2) == 2) {
report.addToReport(" Opposite Reference match : "
+ refName1);
reportText += "Opposite Reference match : " + refName1 + "\n\n";
refFound = true;
}
}
}
if (!refFound) {
report.addToReport(" Reference from first diagram "
+ reference1.getReferenceName() + " -->"
+ reference1.getReferenceTypeName()
+ " not found in second diagram");
reportText += "Reference from first diagram "
+ reference1.getReferenceName() + " -->"
+ reference1.getReferenceTypeName()
+ " not found in second diagram\n\n";
}
}
} catch (Exception ex) {
ex.printStackTrace();
} finally {
// report.terminateRoutine("References");
}
}
/**
* Compare ETypes
*
* @param etype1
* first classifier to compare
* @param etype2
* second classifier to compare
* @return true if equals else false
*/
private boolean compareETypes(String etype1, String etype2) {
return etype1.equals(etype2);
}
/**
* Structurally compare the two classes ie reference attribute n methods
*
* @param cdClass1
* first class to compare
* @param cdClass2
* second class to compare
*/
private void structuralComparison(CD_Class cdClass1, CD_Class cdClass2) {
// report.startRoutine("structural class");
try {
// check if any of the class already in list of matched classes
if (!(this.matchedClasses.contains(cdClass1.getClassName()) || this.matchedClasses
.contains(cdClass2.getClassName()))) {
// Check if structurally the similarity is greater than 50 %
if (this.structAttrCompare(cdClass1, cdClass2) >= 0.5
&& structMethodCompare(cdClass1, cdClass2) >= 0.5
&& structRefCompare(cdClass1, cdClass2) >= 0.5) {
report.addToReport(" Structural Match: Yes");
reportText += "\tStructural Match: \tYes\n\n";
/*
* set list of classes with different names but might be same
* Dong Guo
*
* similarClasses.add(cls1.getName());
* similarClasses.add(cls2.getName());
*/
this.compareClassDetails(cdClass1, cdClass2);
} else {
// Add the unmatched classes to the list of classes compared
listComparedClasses(cdClass1, cdClass2);
}
}
} catch (Exception ex) {
ex.printStackTrace();
} finally {
// report.terminateRoutine("Structural class");
}
}
/**
* Compare attributes based on name.
*
* @param cls1
* first class containing attributes to compare
* @param cls2
* second class containing attributes to compare
* @return float between 0 and 1. Percentage of attributes matching.
*/
private float structAttrCompare(CD_Class cls1, CD_Class cls2) {
// report.startRoutine("structural attributes");
try {
List<CD_Attribute> attrList1 = cls1.getAttributes();
List<CD_Attribute> attrList2 = cls2.getAttributes();
// If attribute list of both classes is empty then return 1
// This allows comparison based on method and reference similarities
if (attrList1.size() == 0 && attrList2.size() == 0)
return 1;
float attrScore = 0;
for (CD_Attribute attribute1 : attrList1) {
for (CD_Attribute attribute2 : attrList2) {
if (compareNames(attribute1.getAttrName(),
attribute2.getAttrName()) == 2) {
// debug code
report.addToReport("Attribute match "
+ attribute1.getAttrName());
reportText += "Attribute match "
+ attribute1.getAttrName() + "\n\n";
attrScore += 1;
}
}
}
// If attribute list is not empty then return, percentage of the
// matched attribute
// In this case a value between 0 and 1
if (attrList1.size() != 0)
return attrScore / attrList1.size();
// Return 0 if attribute list of class 1 is empty and other is not
return attrScore;
} catch (Exception ex) {
ex.printStackTrace();
} finally {
// report.terminateRoutine("Structural attributes");
}
return 0;
}
/**
* Compare methods structurally based on name and return type
*
* @param cls1
* first class containing operations to compare
* @param cls2
* second class containing operations to compare
* @return float between 0 to 1. Percentage of operations matching.
*/
private float structMethodCompare(CD_Class cls1, CD_Class cls2) {
// report.startRoutine("structural methods");
try {
List<CD_Operation> methodList1 = cls1.getOperations();
List<CD_Operation> methodList2 = cls2.getOperations();
if (methodList1.size() == 0 && methodList2.size() == 0)
return 1;
float methodScore = 0;
for (CD_Operation operation1 : methodList1) {
for (CD_Operation operation2 : methodList2) {
// Compare method name
if (this.compareNames(operation1.getOperationName(),
operation2.getOperationName()) > 0) {
// Compare method return type
if (this.compareETypes(operation1.getReturnType(),
operation2.getReturnType())) {
// method params not compared
report.addToReport("Method match "
+ operation1.getOperationName());
reportText += "Method match " + operation1.getOperationName() + "\n\n";
methodScore += 1;
}
}
}
}
// Return a percentage of the matched methods
// In this case a decimal value between 0 & 1
if (methodList1.size() != 0)
return methodScore / methodList1.size();
// Return 0 if the method list of class1 is empty and other class is
// not
return methodScore;
} catch (Exception ex) {
ex.printStackTrace();
} finally {
// report.terminateRoutine("Structural methods");
}
return 0;
}
/**
* Compare two classes structure
*
* @param cls1
* first class containing references to compare
* @param cls2
* second class containing references to compare
* @return a float value between 1 and 0. 1 is perfect match and 0
* completely different
*
*/
private float structRefCompare(CD_Class cls1, CD_Class cls2) {
// report.startRoutine("structural references");
try {
List<CD_Reference> refList1 = cls1.getReferences();
List<CD_Reference> refList2 = cls2.getReferences();
// If both classes do not hav any references return 1
// This allows comparison to be continued on the basis of matched
// attributes and methods
if (refList1.size() == 0 && refList2.size() == 0)
return 1;
float refScore = 0;
for (CD_Reference reference1 : refList1) {
for (CD_Reference reference2 : refList2) {
// Compare if the referenced class is same
if (this.compareNames(reference1.getReferenceTypeName(),
reference2.getReferenceTypeName()) > 0) {
String refName1 = reference1.getReferenceTypeName().toString();
String refName2 = reference1.getReferenceTypeName().toString();
// Check if the relationship name is same
if (this.compareNames(refName1, refName2) == 2) {
report.addToReport("Reference match "
+ reference1.getReferenceName());
reportText += "Reference match "
+ reference1.getReferenceName() + "\n\n";
refScore += 1;
}
}
}
}
// Return a percentage of the matched references
if (refList1.size() != 0)
return refScore / refList1.size();
return refScore;
} catch (Exception ex) {
ex.printStackTrace();
} finally {
// report.terminateRoutine("Structural references");
}
return 0;
}
/**
* Add classes to the list of compared classes
*
* @param cls1
* first class that was compared
* @param cls2
* second class that was compared
*/
private void listComparedClasses(CD_Class cls1, CD_Class cls2) {
if (!comparedClasses.contains(cls1.getClassName()))
comparedClasses.add(cls1.getClassName());
if (!comparedClasses.contains(cls2.getClassName()))
comparedClasses.add(cls2.getClassName());
}
/**
* Add to report the list of unmatched classes by seperating the classes
* already present in matched classes
*/
private void reportUnmatchedClasses() {
report.addToReport("\nUnmatched Classes: ");
reportText += "Unmatched Classes: \n\n";
for (int i = 0; i < comparedClasses.size(); i++) {
if (!matchedClasses.contains(comparedClasses.get(i)) &&
!partialMatchedClasses.contains(comparedClasses.get(i))) {
report.addToReport(" " + (i+1) + ". " + comparedClasses.get(i));
reportText += " \t" + (i+1) + ". " +comparedClasses.get(i) + "\n\n";
}
}
}
private void reportPartialMatchedClasses() {
report.addToReport("\nPartial Matched Classes: ");
reportText += "Partial Matched Classes: \n\n";
for(int i = 0; i < partialMatchedClasses.size(); i=i+2){
report.addToReport(" " + (i+1) + ". " + partialMatchedClasses.get(i)
+ " and " + partialMatchedClasses.get(i+1)) ;
reportText += "\t" + (i+1) + ". " + partialMatchedClasses.get(i)
+ " and " + partialMatchedClasses.get(i+1) + "\n\n";
}
}
private void reportMatchedClasses() {
report.addToReport("\nMatched Classes: ");
reportText += "Matched Classes: \n\n";
for(int i = 0; i < matchedClasses.size(); i++){
report.addToReport(" " + (i+1) + ". " + matchedClasses.get(i));
reportText += "\t" + (i+1) + ". " + matchedClasses.get(i) + "\n\n";
}
}
/*
* The aloneClasses list that might be useful
*
* private void setAloneClasses(){
* for(int i = 0; i < comparedClasses.size(); i++) {
* if(!matchedClasses.contains(comparedClasses.get(i))
* && !similarClasses.contains(comparedClasses.get(i))){
* aloneClasses.add(comparedClasses.get(i));
* }
* }
* }
*/
}