/* JayFX - A Fact Extractor Plug-in for Eclipse
* Copyright (C) 2006 McGill University (http://www.cs.mcgill.ca/~swevo/jayfx)
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* $Revision: 1.7 $
*/
package de.ovgu.cide.mining.database;
import java.util.ArrayList;
import java.util.EventObject;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Observable;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.swt.widgets.Display;
import cide.gast.ASTNode;
import de.ovgu.cide.features.FeatureModelManager;
import de.ovgu.cide.features.FeatureModelNotFoundException;
import de.ovgu.cide.features.IFeature;
import de.ovgu.cide.features.IFeatureModel;
import de.ovgu.cide.features.source.ColoredSourceFile;
import de.ovgu.cide.mining.database.model.AElement;
import de.ovgu.cide.mining.database.model.AFlyweightElementFactory;
import de.ovgu.cide.mining.database.model.ARelationKind;
import de.ovgu.cide.mining.database.recommendationengine.AElementColorManager;
import de.ovgu.cide.mining.database.recommendationengine.AElementRecommendationManager;
import de.ovgu.cide.mining.database.recommendationengine.AElementViewCountManager;
import de.ovgu.cide.mining.database.recommendationengine.ARecommendationContextCollection;
import de.ovgu.cide.mining.events.AGenerateRecommendationsEvent;
import de.ovgu.cide.mining.events.AInitEvent;
import de.ovgu.cide.mining.logging.EvalLogging;
/**
* Facade for the JavaDB component. This component takes in a Java projects and
* produces a database of the program relations between all the source element
* in the input project and dependent projects.
*/
public class ApplicationController extends Observable {
IProject initializedProject = null;
public static final boolean CHECK_COLOR_RELATIONS = true;
// The database object should be used for building the database
private AbstractProgramDatabase aDB;
private AElementColorManager elementColorManager;
private AElementViewCountManager viewCountManager;
// private TypeCheckManager typingManager;
private AElementRecommendationManager elementRecommendationManager;
// private IEvaluationStrategy evaluationStrategy;
private AFlyweightElementFactory elementFactory;
private Set<IFeature> projectFeatures;
private Map<Integer, ICompilationUnit> compUnitMap;
// The analyzer is a wrapper providing additional query functionalities
// to the database.
private AAnalyzer aAnalyzer;
private static ApplicationController AC = null;
private ApplicationController() {
AC = null;
initializedProject = null;
}
public int getViewCountForElement(AElement element) {
return viewCountManager.getViewCountForElement(element);
}
public Set<IFeature> getElementNonColors(AElement element) {
return elementColorManager.getElementNonColors(element);
}
public Set<IFeature> getElementColors(AElement element) {
return elementColorManager.getElementColors(element);
}
public Set<AElement> getElementsOfColor(IFeature color) {
return elementColorManager.getElementsOfColor(color);
}
public Set<AElement> getElementsOfNonColor(IFeature color) {
return elementColorManager.getElementsOfNonColor(color);
}
public Set<IFeature> getRelatedColors(IFeature color) {
return elementColorManager.getRelatedColors(color);
}
public Set<IFeature> getRelatedNonColors(IFeature color) {
return elementColorManager.getRelatedNonColors(color);
}
public Set<IFeature> getAvailableColors() {
return elementColorManager.getAvailableColors();
}
public Map<IFeature, ARecommendationContextCollection> getAllRecommendations(
AElement element) {
return elementRecommendationManager.getAllRecommendations(element);
}
public Map<AElement, ARecommendationContextCollection> getRecommendations(
IFeature color, AElement element) {
return elementRecommendationManager.getRecommendations(color, element);
}
public int getRecommendationsCount(IFeature color, AElement element) {
return elementRecommendationManager.getRecommendationsCount(color,
element);
}
public int getRecommendationsCount(IFeature color, int start, int end,
int cuhash) {
return elementRecommendationManager.getRecommendationsCount(color,
start, end, cuhash);
}
public Map<AElement, ARecommendationContextCollection> getRecommendations(
IFeature color, int start, int end, int cuhash) {
return elementRecommendationManager.getRecommendations(color, start,
end, cuhash);
}
public Map<AElement, ARecommendationContextCollection> getRecommendations(
IFeature color) {
return elementRecommendationManager.getRecommendations(color);
}
public void __script_updateRecommendations() {
elementRecommendationManager.__script_updateRecommendations();
}
public static ApplicationController getInstance() {
if (AC == null)
AC = new ApplicationController();
return AC;
}
/**
* Returns an IElement describing the argument Java element. Not designed to
* be able to find initializer blocks or arrays.
*
* @param pElement
* Never null.
* @return Never null
* @throws ConversionException
* if the element cannot be converted.
*/
public AElement convertToElement(ASTNode astNode)
throws ConversionException {
return aDB.getElement(astNode.getId());
}
public Set<AElement> getRange(AElement pElement, ARelationKind pRelation) {
return aAnalyzer.getRange(pElement, pRelation);
}
/**
* Returns all the elements in the database in their lighweight form.
*
* @return A Set of IElement objects representing all the elements in the
* program database.
*/
public Iterable<AElement> getAllElements() {
return aDB.getAllElements();
}
/**
* Returns whether pElements has any associated relations.
*
* @param pElement
* The element to check. Must not be null and exist in the
* database.
* @return True if pElement has any associated relations.
* @throws ElementNotFoundException
* If either pFrom or pTo is not indexed in the database.
*/
public boolean hasRelations(AElement pElement)
throws ElementNotFoundException {
return aDB.hasRelations(pElement);
}
public ICompilationUnit getICompilationUnit(int hash) {
return compUnitMap.get(hash);
}
// public AElementColorManager getElementColorManager() {
// return elementColorManager;
// }
/**
* Initializes the program database with information about relations between
* all the source elements in pProject and all of its dependent projects.
*
* @param pProject
* The project to analyze. Should never be null.
* @param pProgress
* A progress monitor. Can be null.
* @param pCHA
* Whether to calculate overriding relationships between methods
* and to use these in the calculation of CALLS and CALLS_BY
* relations.
* @throws ApplicationControllerException
* If the method cannot complete correctly
*/
public void initialize(IProject pProject, IProgressMonitor pProgress)
throws ApplicationControllerException {
assert (pProject != null);
assert (pProgress != null);
// The database object should be used for building the database
// aDB = BerkeleyProgramDatabase.getInstance();
aDB = new ProgramDatabase();
elementFactory = new AFlyweightElementFactory();
// The analyzer is a wrapper providing additional query functionalities
// to the database.
aAnalyzer = new AAnalyzer(aDB);
compUnitMap = new HashMap<Integer, ICompilationUnit>();
initializedProject = pProject;
// Collect all target classes
List<ICompilationUnit> lTargets = new ArrayList<ICompilationUnit>();
for (IJavaProject lNext : getJavaProjects(pProject)) {
lTargets.addAll(getCompilationUnits(lNext));
}
int units = lTargets.size();
pProgress.beginTask("Building program database", (int) (units * 3.1));
pProgress.subTask("Loading feature model...");
try {
if (pProgress.isCanceled())
return;
pProgress.subTask("Parsing features");
IFeatureModel model = FeatureModelManager.getInstance()
.getFeatureModel(initializedProject);
projectFeatures = model.getFeatures();
} catch (FeatureModelNotFoundException e) {
// TODO Auto-generated catch block
projectFeatures = new HashSet<IFeature>();
}
elementRecommendationManager = new AElementRecommendationManager(this,
elementColorManager);
elementColorManager = new AElementColorManager(this);
pProgress.worked(units / 10);
ADeclareRelationBuilder loader = new ADeclareRelationBuilder(aDB,
elementFactory);
int i = 0;
for (ICompilationUnit lCU : lTargets) {
if (pProgress.isCanceled())
return;
pProgress.subTask("Creating elements in " + lCU.getElementName()
+ " (" + (++i) + "/" + units + ")");
ColoredSourceFile coloredSourceFile = getColoredSourcefile(lCU);
int lCUHash = lCU.hashCode();
compUnitMap.put(lCUHash, lCU);
loader.createElementsAndDeclareRelations(lCU, lCUHash,
elementColorManager, coloredSourceFile.getColorManager());
pProgress.worked(1);
}
i = 0;
AAccessRelationBuilder relationBuilder = new AAccessRelationBuilder(
aDB, elementFactory);
for (ICompilationUnit lCU : lTargets) {
if (pProgress.isCanceled())
return;
pProgress.subTask("Creating relations in " + lCU.getElementName()
+ " (" + (++i) + "/" + units + ")");
ColoredSourceFile coloredSourceFile = getColoredSourcefile(lCU);
int lCUHash = lCU.hashCode();
relationBuilder.buildRelations(lCU, lCUHash, elementColorManager,
coloredSourceFile.getColorManager());
pProgress.worked(2);
}
// try {
// evaluationStrategy = EvaluationStrategyManager.getInstance()
// .getEvaluationStrategy(pProject);
//
//
//
// } catch (FeatureModelNotFoundException e1) {
// e1.printStackTrace();
// }
//
aDB.estimateFootprint();
EvalLogging.getInstance().init(pProject, aDB);
Display.getDefault().syncExec(new Runnable() {
public void run() {
viewCountManager = new AElementViewCountManager(
ApplicationController.this);
fireEvent(new AInitEvent(this, initializedProject));
fireEvent(new AGenerateRecommendationsEvent(this));
}
});
pProgress.done();
}
private ColoredSourceFile getColoredSourcefile(ICompilationUnit lCU) {
ColoredSourceFile coloredSourceFile = null;
try {
coloredSourceFile = ColoredSourceFile
.getColoredSourceFile((IFile) lCU.getResource());
} catch (FeatureModelNotFoundException e) {
e.printStackTrace();
}
return coloredSourceFile;
}
// public IEvaluationStrategy getEvaluationStrategy() {
// return evaluationStrategy;
// }
public IProject getInitializedProject() {
return initializedProject;
}
public Set<IFeature> getProjectFeatures() {
return projectFeatures;
}
public void fireEvent(EventObject event) {
setChanged();
notifyObservers(event);
}
/**
* Returns all projects to analyze in IJavaProject form, including the
* dependent projects.
*
* @param pProject
* The project to analyze (with its dependencies. Should not be
* null.
* @return A list of all the dependent projects (including pProject). Never
* null.
* @throws ApplicationControllerException
* If the method cannot complete correctly.
*/
private static List<IJavaProject> getJavaProjects(IProject pProject)
throws ApplicationControllerException {
assert (pProject != null);
List<IJavaProject> lReturn = new ArrayList<IJavaProject>();
try {
lReturn.add(JavaCore.create(pProject));
IProject[] lReferencedProjects = pProject.getReferencedProjects();
for (int i = 0; i < lReferencedProjects.length; i++) {
lReturn.add(JavaCore.create(lReferencedProjects[i]));
}
} catch (CoreException pException) {
throw new ApplicationControllerException(
"Could not extract project information", pException);
}
return lReturn;
}
/**
* Returns all the compilation units in this projects
*
* @param pProject
* The project to analyze. Should never be null.
* @return The compilation units to generate. Never null.
* @throws ApplicationControllerException
* If the method cannot complete correctly
*/
private static List<ICompilationUnit> getCompilationUnits(
IJavaProject pProject) throws ApplicationControllerException {
assert (pProject != null);
List<ICompilationUnit> lReturn = new ArrayList<ICompilationUnit>();
try {
IPackageFragment[] lFragments = pProject.getPackageFragments();
for (int i = 0; i < lFragments.length; i++) {
ICompilationUnit[] lCUs = lFragments[i].getCompilationUnits();
for (int j = 0; j < lCUs.length; j++) {
lReturn.add(lCUs[j]);
}
}
} catch (JavaModelException pException) {
throw new ApplicationControllerException(
"Could not extract compilation units from project",
pException);
}
return lReturn;
}
}