package husacct.analyse.domain.famix;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.TreeMap;
import java.util.TreeSet;
import husacct.analyse.domain.IModelQueryService;
import husacct.common.dto.AnalysisStatisticsDTO;
import husacct.common.dto.DependencyDTO;
import husacct.common.dto.SoftwareUnitDTO;
import husacct.common.dto.UmlLinkDTO;
import husacct.common.enums.DependencyTypes;
import husacct.common.enums.UmlLinkTypes;
public class FamixQueryServiceImpl implements IModelQueryService {
private FamixModel theModel;
private FamixModuleFinder moduleFinder;
private FamixDependencyFinder dependencyFinder;
public FamixQueryServiceImpl() {
this.theModel = FamixModel.getInstance();
clearModel();
this.moduleFinder = new FamixModuleFinder(theModel);
this.dependencyFinder = new FamixDependencyFinder(theModel);
}
@Override
public void clearModel() {
theModel.clear();
this.dependencyFinder = new FamixDependencyFinder(theModel);
}
@Override
public void buildCache(){
dependencyFinder.buildCache();
}
@Override
public void importDependencies(List<DependencyDTO> dependencies){
dependencyFinder.importDependencies(dependencies);
}
@Override
public SoftwareUnitDTO getSoftwareUnitByUniqueName(String uniqueName) {
return moduleFinder.getModuleForUniqueName(uniqueName);
}
@Override
public String getSourceFilePathOfClass(String uniqueName) {
String returnValue = "";
if (theModel.classes.containsKey(uniqueName)) {
returnValue = theModel.classes.get(uniqueName).sourceFilePath;
}
return returnValue;
}
@Override
public SoftwareUnitDTO[] getSoftwareUnitsInRoot() {
List<SoftwareUnitDTO> rootModules = moduleFinder.getRootModules();
return rootModules.toArray(new SoftwareUnitDTO[rootModules.size()]);
}
@Override
public SoftwareUnitDTO[] getChildUnitsOfSoftwareUnit(String uniqueName) {
SoftwareUnitDTO[] children;
List<SoftwareUnitDTO> childModules = moduleFinder.getChildModulesInModule(uniqueName);
int numberOfChildren = childModules.size();
if ((childModules != null) && numberOfChildren > 0) {
children = childModules.toArray(new SoftwareUnitDTO[childModules.size()]);
} else {
children = new SoftwareUnitDTO[0];
}
return children;
}
@Override
public SoftwareUnitDTO getParentUnitOfSoftwareUnit(String uniqueName) {
return moduleFinder.getParentModuleForModule(uniqueName);
}
@Override
public DependencyDTO[] getAllDependencies() {
List<DependencyDTO> result = dependencyFinder.getAllDependencies();
DependencyDTO[] allDependencies = result.toArray(new DependencyDTO[result.size()]);
return allDependencies;
}
// Query dependencies of all types
@Override
public DependencyDTO[] getDependenciesFromSoftwareUnitToSoftwareUnit(String pathFrom, String pathTo) {
List<DependencyDTO> foundDependenciesReturnList = new ArrayList<DependencyDTO>();
TreeMap<String, DependencyDTO> foundDependenciesTreeMap = new TreeMap<String, DependencyDTO>();
TreeSet<String> allFromTypeNames = getPhysicalClassPathsOfSoftwareUnit(pathFrom);
TreeSet<String> allToTypeNames = getPhysicalClassPathsOfSoftwareUnit(pathTo);
for (String fromTypeName : allFromTypeNames) {
for (String toTypeName : allToTypeNames) {
for (DependencyDTO dependency : dependencyFinder.getDependenciesFromTo(fromTypeName, toTypeName)) {
// Filter-out duplicate dependencies
String uniqueName = (dependency.from + dependency.to + dependency.lineNumber + dependency.type + dependency.subType + Boolean.toString(dependency.isIndirect));
foundDependenciesTreeMap.put(uniqueName, dependency);
}
}
}
foundDependenciesReturnList.addAll(foundDependenciesTreeMap.values());
return foundDependenciesReturnList.toArray(new DependencyDTO[foundDependenciesReturnList.size()]);
}
@Override
public DependencyDTO[] getDependenciesFromClassToClass(String classPathFrom, String classPathTo){
ArrayList<DependencyDTO> result = dependencyFinder.getDependenciesFromTo(classPathFrom, classPathTo);
DependencyDTO[] allDependencies = result.toArray(new DependencyDTO[result.size()]);
return allDependencies;
}
// Query only dependencies of the types Access, Call, and Reference (representing "Executing" activities).
@Override
public DependencyDTO[] getDependencies_OnlyAccessCallAndReferences_FromSoftwareUnitToSoftwareUnit(String pathFrom, String pathTo) {
List<DependencyDTO> foundDependenciesReturnList = new ArrayList<DependencyDTO>();
TreeMap<String, DependencyDTO> foundDependenciesTreeMap = new TreeMap<String, DependencyDTO>();
TreeSet<String> allFromTypeNames = getPhysicalClassPathsOfSoftwareUnit(pathFrom);
TreeSet<String> allToTypeNames = getPhysicalClassPathsOfSoftwareUnit(pathTo);
for (String fromTypeName : allFromTypeNames) {
for (String toTypeName : allToTypeNames) {
for (DependencyDTO dependency : dependencyFinder.getDependenciesFromTo(fromTypeName, toTypeName)) {
if (dependency.type.equals(DependencyTypes.ACCESS.toString()) || dependency.type.equals(DependencyTypes.CALL.toString())|| dependency.type.equals(DependencyTypes.REFERENCE.toString())) {
// Filter-out duplicate dependencies
String uniqueName = (dependency.from + dependency.to + dependency.lineNumber + dependency.type + dependency.subType + Boolean.toString(dependency.isIndirect));
foundDependenciesTreeMap.put(uniqueName, dependency);
}
}
}
}
foundDependenciesReturnList.addAll(foundDependenciesTreeMap.values());
return foundDependenciesReturnList.toArray(new DependencyDTO[foundDependenciesReturnList.size()]);
}
@Override
public DependencyDTO[] getDependencies_OnlyAccessCallAndReferences_FromClassToClass(String classPathFrom, String classPathTo){
ArrayList<DependencyDTO> DependencyDTOs = dependencyFinder.getDependenciesFromTo(classPathFrom, classPathTo);
ArrayList<DependencyDTO> result = new ArrayList<DependencyDTO>();
for (DependencyDTO dependency : DependencyDTOs) {
if (dependency.type.equals(DependencyTypes.ACCESS.toString()) || dependency.type.equals(DependencyTypes.CALL.toString())|| dependency.type.equals(DependencyTypes.REFERENCE.toString())) {
result.add(dependency);
}
}
DependencyDTO[] dependenciesOfSelectedTypes = result.toArray(new DependencyDTO[result.size()]);
return dependenciesOfSelectedTypes;
}
// Returns List with unique names of all types (classes, interfaces, inner classes) within the SoftwareUnit with uniqueName
@Override
public List<String> getAllPhysicalClassPathsOfSoftwareUnit(String uniqueName){
List<String> returnValue = new ArrayList<String>(getPhysicalClassPathsOfSoftwareUnit(uniqueName));
return returnValue;
}
// Returns TreeSet with unique names of all types (classes, interfaces, inner classes) within the SoftwareUnit with uniqueName
private TreeSet<String> getPhysicalClassPathsOfSoftwareUnit(String uniqueName){
TreeSet<String> uniqueNamesAllFoundTypes = new TreeSet<String>();
if (!theModel.packages.containsKey(uniqueName)) { // Add only classes and libraries
uniqueNamesAllFoundTypes.add(uniqueName);
}
TreeSet<String> children = (moduleFinder.getChildModulesNamesInModule(uniqueName));
if ((children != null) && (children.size() > 0)){
for (String child : children){
TreeSet<String> validChildName = getPhysicalClassPathsOfSoftwareUnit(child);
uniqueNamesAllFoundTypes.addAll(validChildName);
}
}
return uniqueNamesAllFoundTypes;
}
// Returns List with unique names of all packages within this SoftwareUnit
@Override
public List<String> getAllPhysicalPackagePathsOfSoftwareUnit(String uniqueName){
List<String> returnValue = new ArrayList<String>(getPhysicalPackagePathsOfSoftwareUnit(uniqueName));
return returnValue;
}
// Returns TreeSet with unique names of all packages within this SoftwareUnit
private TreeSet<String> getPhysicalPackagePathsOfSoftwareUnit(String uniqueName){
TreeSet<String> uniqueNamesAllFoundPackages = new TreeSet<String>();
if (theModel.packages.containsKey(uniqueName)) { // Add only packages
//uniqueNamesAllFoundPackages.add(uniqueName);
}
TreeSet<String> children = (moduleFinder.getChildModulesNamesInModule(uniqueName));
if ((children != null) && (children.size() > 0)){
for (String child : children){
if (theModel.packages.containsKey(child)) { // Add only packages
uniqueNamesAllFoundPackages.add(child);
}
TreeSet<String> validChildName = getPhysicalPackagePathsOfSoftwareUnit(child);
uniqueNamesAllFoundPackages.addAll(validChildName);
}
}
return uniqueNamesAllFoundPackages;
}
@Override
public List<String> getRootPackagesWithClass(String module) {
return moduleFinder.getRootPackagesWithClass(module);
}
@Override
// If selectedModule == null, statistics of the whole application are returned; otherwise statistics of the selectedModule only are returned.
public AnalysisStatisticsDTO getAnalysisStatistics(SoftwareUnitDTO selectedModule) {
AnalysisStatisticsDTO returnValue;
// Determine totalNrOfPackages, minus 1 for package xLibraries, since that one is created within the analysis process.
int totalNrOfPackages = 0;
totalNrOfPackages = theModel.packages.size();
if (theModel.packages.containsKey("xLibraries")) {
totalNrOfPackages --;
}
if (selectedModule == null) {
returnValue = new AnalysisStatisticsDTO(totalNrOfPackages, theModel.classes.size(), theModel.getTotalNumberOfLinesOfCode(), getAllDependencies().length, theModel.getTotalNumberOfUmlLinks(), 0, 0, 0);
} else {
int packages = 0;
int classes = 0;
int linesOfCode = 0;
if (selectedModule.type.equals("package")) {
if (theModel.packages.containsKey(selectedModule.uniqueName)) {
packages = getPhysicalPackagePathsOfSoftwareUnit(selectedModule.uniqueName).size();
TreeSet<String> classesSet = getPhysicalClassPathsOfSoftwareUnit(selectedModule.uniqueName);
classes = classesSet.size();
for (String typeName : classesSet) {
if (theModel.classes.containsKey(typeName)) {
FamixClass selected = theModel.classes.get(typeName);
linesOfCode = linesOfCode + selected.linesOfCode;
}
}
}
} else if (selectedModule.type.equals("class") || selectedModule.type.equals("interface")) {
if (theModel.classes.containsKey(selectedModule.uniqueName)) {
FamixClass selected = theModel.classes.get(selectedModule.uniqueName);
linesOfCode = selected.linesOfCode;
if (selected.hasInnerClasses) {
TreeSet<String> classesSet = getPhysicalClassPathsOfSoftwareUnit(selectedModule.uniqueName);
classes = classesSet.size();
} else {
classes = 1;
}
}
packages = 0;
} else {
// A library is selected, so return default 0-values.
}
returnValue = new AnalysisStatisticsDTO(totalNrOfPackages, theModel.classes.size(), theModel.getTotalNumberOfLinesOfCode(), getAllDependencies().length, theModel.getTotalNumberOfUmlLinks(), packages, classes, linesOfCode);
}
return returnValue;
}
@Override
public HashSet<UmlLinkDTO> getUmlLinksFromClassToOtherClasses(String fromClass) {
HashSet<UmlLinkDTO> returnValue = new HashSet<UmlLinkDTO>();
HashSet<FamixUmlLink> setOfFamixUmlLinks = theModel.getUmlLinksFromClassToOtherClasses(fromClass);
for (FamixUmlLink umlLink : setOfFamixUmlLinks) {
UmlLinkDTO umlLinkDTO = new UmlLinkDTO(umlLink.from, umlLink.to, umlLink.attributeFrom, umlLink.isComposite, umlLink.type.toString());
returnValue.add(umlLinkDTO);
}
return returnValue;
}
@Override
public UmlLinkDTO[] getUmlLinksFromClassToToClass(String fromClass, String toClass) {
ArrayList<UmlLinkDTO> returnValue = new ArrayList<UmlLinkDTO>();
HashSet<FamixUmlLink> setOfFamixUmlLinks = theModel.getUmlLinksFromClassToToClass(fromClass, toClass);
for (FamixUmlLink umlLink : setOfFamixUmlLinks) {
UmlLinkDTO umlLinkDTO = new UmlLinkDTO(umlLink.from, umlLink.to, umlLink.attributeFrom, umlLink.isComposite, umlLink.type.toString());
returnValue.add(umlLinkDTO);
}
return returnValue.toArray(new UmlLinkDTO[returnValue.size()]);
}
@Override
public UmlLinkDTO[] getUmlLinksFromSoftwareUnitToSoftwareUnit(String pathFrom, String pathTo) {
List<UmlLinkDTO> foundUmlLinksReturnList = new ArrayList<UmlLinkDTO>();
TreeMap<String, UmlLinkDTO> foundUmlLinksTreeMap = new TreeMap<String, UmlLinkDTO>();
TreeSet<String> allFromTypeNames = getPhysicalClassPathsOfSoftwareUnit(pathFrom);
TreeSet<String> allToTypeNames = getPhysicalClassPathsOfSoftwareUnit(pathTo);
for (String fromTypeName : allFromTypeNames) {
for (String toTypeName : allToTypeNames) {
for (FamixUmlLink umlLink : theModel.getUmlLinksFromClassToToClass(fromTypeName, toTypeName)) {
// Filter-out duplicate umlLinks
String uniqueName = (umlLink.from + umlLink.to + umlLink.type + umlLink.attributeFrom);
UmlLinkDTO umlLinkDTO = new UmlLinkDTO(umlLink.from, umlLink.to, umlLink.attributeFrom, umlLink.isComposite, umlLink.type.toString());
foundUmlLinksTreeMap.put(uniqueName, umlLinkDTO);
}
}
}
foundUmlLinksReturnList.addAll(foundUmlLinksTreeMap.values());
return foundUmlLinksReturnList.toArray(new UmlLinkDTO[foundUmlLinksReturnList.size()]);
}
@Override
public DependencyDTO[] getUmlLinksAsDependencyDtosFromSoftwareUnitToSoftwareUnit(String pathFrom, String pathTo) {
List<DependencyDTO> foundDependenciesReturnList = new ArrayList<DependencyDTO>();
TreeMap<String, DependencyDTO> foundDependenciesTreeMap = new TreeMap<String, DependencyDTO>();
TreeSet<String> allFromTypeNames = getPhysicalClassPathsOfSoftwareUnit(pathFrom);
TreeSet<String> allToTypeNames = getPhysicalClassPathsOfSoftwareUnit(pathTo);
for (String fromTypeName : allFromTypeNames) {
for (String toTypeName : allToTypeNames) {
for (FamixUmlLink umlLink : theModel.getUmlLinksFromClassToToClass(fromTypeName, toTypeName)) {
// Filter-out duplicate umlLinks
String uniqueName = (umlLink.from + umlLink.to + umlLink.type + umlLink.attributeFrom);
DependencyDTO umlLinkDepDTO = new DependencyDTO(umlLink.from, umlLink.to, umlLink.type, umlLink.attributeFrom, umlLink.lineNumber, umlLink.isComposite, false);
if (umlLink.type.equals(UmlLinkTypes.ATTRIBUTELINK.toString())){
String typeConcat = "Attr: " + umlLink.attributeFrom;
umlLinkDepDTO.type = typeConcat;
}
foundDependenciesTreeMap.put(uniqueName, umlLinkDepDTO);
}
}
}
foundDependenciesReturnList.addAll(foundDependenciesTreeMap.values());
return foundDependenciesReturnList.toArray(new DependencyDTO[foundDependenciesReturnList.size()]);
}
@Override
public List<SoftwareUnitDTO> getAllClasses() {
return moduleFinder.findAllClasses();
}
}