package husacct.analyse.domain.famix;
import husacct.common.dto.SoftwareUnitDTO;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.TreeSet;
import java.util.Map.Entry;
import org.apache.log4j.Logger;
class FamixModuleFinder extends FamixFinder {
private static enum FinderArguments {
ROOT, CHILDS, PARENT, FETCH
};
private String currentArgument;
private FinderArguments currentFunction = FinderArguments.ROOT;
private List<SoftwareUnitDTO> currentResult;
private final Logger logger = Logger.getLogger(FamixModuleFinder.class);
public FamixModuleFinder(FamixModel model) {
super(model);
this.currentResult = new ArrayList<SoftwareUnitDTO>();
this.currentArgument = "";
}
public SoftwareUnitDTO getModuleForUniqueName(String uniquename) {
if (theModel.packages.containsKey(uniquename)) {
return createAnalysedModuleDTO(theModel.packages.get(uniquename));
} else if (theModel.classes.containsKey(uniquename)){
return createAnalysedModuleDTO(theModel.classes.get(uniquename));
} else if (theModel.libraries.containsKey(uniquename)){
return createAnalysedModuleDTO(theModel.libraries.get(uniquename));
}
else {
return new SoftwareUnitDTO("", "", "", "");
}
}
public List<SoftwareUnitDTO> getRootModules() {
this.performQuery(FinderArguments.ROOT);
return this.currentResult;
}
public TreeSet<String> getChildModulesNamesInModule(String module) {
TreeSet<String> children = null;
// New finder function, based on FamixDecompositionEntity
if (theModel.packages.containsKey(module)){
children = theModel.packages.get(module).children;
} else if (theModel.classes.containsKey(module)){
children = theModel.classes.get(module).children;
} else if (theModel.libraries.containsKey(module)){
children = theModel.libraries.get(module).children;
}
return children;
}
// Get a list of rootPackagesWithClass: the first packages (starting from the root) that contain one or more classes.
// These rootPackagesWithClasses identify the paths to the systems internal classes.
public List<String> getRootPackagesWithClass(String module) {
List<String> rootPackagesWithClassList = new ArrayList<String>();
List<SoftwareUnitDTO> children = getChildModulesInModule(module);
boolean isRootPackageWithClass = false;
for (SoftwareUnitDTO child : children) {
if (!child.type.equals("package")) {
isRootPackageWithClass = true;
break;
}
}
if (isRootPackageWithClass) {
rootPackagesWithClassList.add(module);
} else {
for (SoftwareUnitDTO child : children) {
rootPackagesWithClassList.addAll(getRootPackagesWithClass(child.uniqueName));
}
}
return rootPackagesWithClassList;
}
public List<SoftwareUnitDTO> getChildModulesInModule(String module) {
List<SoftwareUnitDTO> result = new ArrayList<SoftwareUnitDTO>();
TreeSet<String> children = getChildModulesNamesInModule(module);
SoftwareUnitDTO current;
if ((children != null) && (children.size() > 0)){
for (String child : children){
if (theModel.packages.containsKey(child)){
current = createAnalysedModuleDTO(theModel.packages.get(child));
result.add(current);
}
if (theModel.classes.containsKey(child)){
current = createAnalysedModuleDTO(theModel.classes.get(child));
result.add(current);
} else if (theModel.libraries.containsKey(child)){
current = createAnalysedModuleDTO(theModel.libraries.get(child));
result.add(current);
}
}
}
return result;
}
// Deprecated
public List<SoftwareUnitDTO> getChildModulesInModule(String module, int depth) {
this.performQuery(FinderArguments.CHILDS, module, depth);
return this.currentResult;
}
public SoftwareUnitDTO getParentModuleForModule(String module) {
this.performQuery(FinderArguments.PARENT, module);
if (this.currentResult.isEmpty()) {
return new SoftwareUnitDTO("", "", "", "");
} else {
return currentResult.get(0);
}
}
private void performQuery(FinderArguments function) {
performQuery(function, "", 0);
}
private void performQuery(FinderArguments function, String argument) {
performQuery(function, argument, 0);
}
private void performQuery(FinderArguments function, String argument, int depth) {
this.prepare(function, argument);
List<SoftwareUnitDTO> result = new ArrayList<SoftwareUnitDTO>();
result.addAll(this.findPackages());
result.addAll(this.findClasses());
result.addAll(this.findLibraries());
if (depth > 0) {
for (SoftwareUnitDTO moduleDTO : result) {
moduleDTO.subModules.addAll(getChildModulesInModule(moduleDTO.uniqueName, depth - 1));
}
}
this.currentResult = result;
}
private void prepare(FinderArguments function, String argument) {
this.currentResult.clear();
this.currentFunction = function;
this.currentArgument = argument;
}
private List<SoftwareUnitDTO> findPackages() {
List<SoftwareUnitDTO> result = new ArrayList<SoftwareUnitDTO>();
Iterator<Entry<String, FamixPackage>> iterator = theModel.packages.entrySet().iterator();
SoftwareUnitDTO current;
while (iterator.hasNext()) {
Entry<String, FamixPackage> currentEntry = iterator.next();
FamixPackage fPackage = currentEntry.getValue();
boolean correctResult = this.compliesWithArguments(fPackage.uniqueName);
if (correctResult) {
current = createAnalysedModuleDTO(fPackage);
result.add(current);
}
}
return result;
}
private List<SoftwareUnitDTO> findClasses() {
List<SoftwareUnitDTO> result = new ArrayList<SoftwareUnitDTO>();
Iterator<Entry<String, FamixClass>> iterator = theModel.classes.entrySet().iterator();
SoftwareUnitDTO current;
while (iterator.hasNext()) {
Entry<String, FamixClass> currentEntry = iterator.next();
FamixClass fClass = currentEntry.getValue();
boolean correctResult = this.compliesWithArguments(fClass.uniqueName);
if (correctResult) {
current = createAnalysedModuleDTO(fClass);
result.add(current);
}
}
return result;
}
public List<SoftwareUnitDTO> findAllClasses() {
List<SoftwareUnitDTO> result = new ArrayList<SoftwareUnitDTO>();
Iterator<Entry<String, FamixClass>> iterator = theModel.classes.entrySet().iterator();
SoftwareUnitDTO current;
while (iterator.hasNext()) {
Entry<String, FamixClass> currentEntry = iterator.next();
FamixClass fClass = currentEntry.getValue();
current = createAnalysedModuleDTO(fClass);
result.add(current);
}
return result;
}
private List<SoftwareUnitDTO> findLibraries() {
List<SoftwareUnitDTO> result = new ArrayList<SoftwareUnitDTO>();
Iterator<Entry<String, FamixLibrary>> iterator = theModel.libraries.entrySet().iterator();
SoftwareUnitDTO current;
while (iterator.hasNext()) {
Entry<String, FamixLibrary> currentEntry = iterator.next();
FamixLibrary fLibrary = currentEntry.getValue();
boolean correctResult = this.compliesWithArguments(fLibrary.uniqueName);
if (correctResult) {
current = createAnalysedModuleDTO(fLibrary);
result.add(current);
}
}
return result;
}
private boolean compliesWithArguments(String uniqueName) {
switch (this.currentFunction) {
case ROOT:
return isRootModule(uniqueName);
case CHILDS:
return isChild(uniqueName, this.currentArgument);
case PARENT:
return isParent(uniqueName, this.currentArgument);
case FETCH:
return uniqueName.equals(this.currentArgument);
}
return false;
}
private boolean isRootModule(String uniqueName) {
int seperatorCount = uniqueName.split("\\.").length;
return seperatorCount <= 1;
}
private boolean isChild(String child, String parent) {
if (isRootModule(child)) {
return false;
}
String currentParent = child.substring(0, child.lastIndexOf("."));
return parent.equals(currentParent);
}
private boolean isParent(String parent, String child) {
if (!moduleExists(child)) {
return false;
}
String name = child.substring(child.lastIndexOf(".") + 1, child.length());
String currentChild = parent + "." + name;
return currentChild.equals(child);
}
private SoftwareUnitDTO createAnalysedModuleDTO(FamixEntity theEntity) {
List<SoftwareUnitDTO> emptyList = new ArrayList<SoftwareUnitDTO>();
return createAnalysedModuleDTO(theEntity, emptyList);
}
private SoftwareUnitDTO createAnalysedModuleDTO(FamixEntity theEntity, List<SoftwareUnitDTO> childs) {
String type;
String name = theEntity.name;
String uniqueName = theEntity.uniqueName;
String visibility = theEntity.visibility;
if (theEntity instanceof FamixPackage){
type = "package";
} else if (theEntity instanceof FamixClass){
if (((FamixClass) theEntity).isInterface)
type = "interface";
else
type = "class";
} else if (theEntity instanceof FamixLibrary){
// To the uniqueName of a FamixLibrary the prefix "xLibrary." is added.
// uniqueName = ((FamixLibrary) theEntity).physicalPath;
type = "library";
} else {
type = "class";
this.logger.error(new Date().toString() + " Unknown type of enity: " + uniqueName);
}
return new SoftwareUnitDTO(uniqueName, name, type, visibility);
}
private boolean moduleExists(String uniqueName) {
if (theModel.classes.get(uniqueName) != null) {
return true;
}
if (theModel.packages.get(uniqueName) != null) {
return true;
}
if (theModel.libraries.get(uniqueName) != null) {
return true;
}
return false;
}
}