/**
* Copyright 2013
*
* HAN University of Applied Sciences
* Maik Diepenbroek
* Wouter Konecny
* Sjoerd van den Top
* Teun van Vegchel
* Niek Versteege
*
* See the file MIT-license.txt for copying permission.
*/
package nl.han.ica.app.controllers;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.input.DragEvent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.VBox;
import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser;
import nl.han.ica.core.Job;
import nl.han.ica.core.SourceFile;
import nl.han.ica.core.issue.IssueDetectionService;
import nl.han.ica.core.issue.IssueDetector;
import nl.han.ica.core.issue.IssueSolvingService;
import nl.han.ica.core.issue.detector.EncapsulateFieldDetector;
import nl.han.ica.core.issue.detector.HideMethodDetector;
import nl.han.ica.core.issue.detector.MagicNumberDetector;
import nl.han.ica.core.issue.solver.EncapsulateFieldSolver;
import nl.han.ica.core.issue.solver.HideMethodSolver;
import nl.han.ica.core.issue.solver.MagicNumberSolver;
import nl.han.ica.core.util.FileUtil;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.List;
import java.util.ResourceBundle;
import java.util.Set;
/**
* Handles all interaction on the source and strategy selection screen.
*/
public class IssueDetectorIndexController extends BaseController {
private final static String FILES_SELECTION_TITLE = "Select source files";
private Job job;
private Scene scene;
@FXML
protected VBox strategyOptions;
@FXML
protected Label selectedFile;
@FXML
protected Label selectedFilePath;
@FXML
protected Button analyzeButton;
/**
* Initialize a new IssueDetectorIndexController.
*
* @param scene The scene in which the controller's view is located.
* @param job The job to select source files and strategies for.
*/
public IssueDetectorIndexController(Scene scene, Job job) {
this.scene = scene;
this.job = job;
initializeIssueDetectors();
}
private void initializeIssueDetectors() {
IssueDetectionService detectionService = job.getIssueDetectionService();
detectionService.addDetector(new MagicNumberDetector());
detectionService.addDetector(new HideMethodDetector());
detectionService.addDetector(new EncapsulateFieldDetector());
IssueSolvingService solvingService = job.getIssueSolvingService();
solvingService.addSolver(new MagicNumberSolver());
solvingService.addSolver(new HideMethodSolver());
solvingService.addSolver(new EncapsulateFieldSolver());
}
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
super.initialize(url, resourceBundle);
initializeStrategyCheckboxList();
}
@Override
public Parent getView() {
try {
return buildView("/views/strategy_selection.fxml");
} catch (IOException e) {
logger.fatal("Could not build the view from the FXML document.", e);
return null;
}
}
/**
* Opens a file browser where (multiple) files could be selected.
*
* @param event The event that is passed by the view.
*/
@FXML
private void selectSourceFiles(ActionEvent event) {
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle(FILES_SELECTION_TITLE);
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("Java Files", "*.java"));
List<File> files = fileChooser.showOpenMultipleDialog(null);
if (null != files) {
for (File file : files) {
job.getSourceFiles().add(new SourceFile(file));
}
} else {
job.getSourceFiles().clear();
}
onSourceFilesSelected();
}
/**
* Opens a file browser where (multiple) folders could be selected.
*
* @param event The event that is passed by the view.
*/
@FXML
private void selectSourceDirectory(ActionEvent event) {
DirectoryChooser directoryChooser = new DirectoryChooser();
directoryChooser.setTitle(FILES_SELECTION_TITLE);
File directory = directoryChooser.showDialog(null);
if (null != directory) {
List<File> files = FileUtil.listFilesRecursively(directory, ".java");
for (File file : files) {
job.getSourceFiles().add(new SourceFile(file));
}
} else {
job.getSourceFiles().clear();
}
onSourceFilesSelected();
}
/**
* This event gets executed when files or folders are hovered on the application.
*
* @param event The event that is passed by the view.
*/
@FXML
public void handleFilesDragOver(DragEvent event) {
Dragboard db = event.getDragboard();
if (db.hasFiles()) {
event.acceptTransferModes(TransferMode.COPY);
} else {
event.consume();
}
}
/**
* This event gets executed when files or folders are dropped on the application.
*
* @param event The event that is passed by the view.
*/
@FXML
public void handleFilesDragDropped(DragEvent event) {
Dragboard db = event.getDragboard();
boolean success = false;
if (db.hasFiles()) {
success = true;
job.getSourceFiles().clear();
for (File file : db.getFiles()) {
if (file.isDirectory()) {
for (File directoryFile : FileUtil.listFilesRecursively(file, ".java")) {
job.getSourceFiles().add(new SourceFile(directoryFile));
}
} else if (file.getName().endsWith(".java")) {
job.getSourceFiles().add(new SourceFile(file));
}
}
onSourceFilesSelected();
}
event.setDropCompleted(success);
event.consume();
}
/**
* This action is executed when the Analyze button is clicked.
*
* @param event The event that is passed by the view.
*/
@FXML
public void analyze(ActionEvent event) {
IssueIndexController issueIndexController = new IssueIndexController(job);
scene.setRoot(issueIndexController.getView());
}
private void onSourceFilesSelected() {
if (job.getSourceFiles().size() > 0) {
selectedFilePath.setText(formatFileSet(job.getSourceFiles()));
selectedFilePath.setVisible(true);
selectedFile.setVisible(true);
} else {
selectedFilePath.setVisible(false);
selectedFile.setVisible(false);
}
updateCanAnalyze();
}
private void updateCanAnalyze() {
analyzeButton.setDisable(!job.canProcess());
}
private String formatFileSet(Set<SourceFile> sourceFiles) {
StringBuilder fileList = new StringBuilder();
for (SourceFile sourceFile : sourceFiles) {
fileList.append(sourceFile.getFile().getName()).append("\n");
}
return fileList.toString();
}
private void initializeStrategyCheckboxList() {
for (final IssueDetector issueDetector : job.getIssueDetectionService().getDetectors()) {
final CheckBox checkBox = new CheckBox();
checkBox.setText(issueDetector.getTitle());
checkBox.selectedProperty().addListener(new ChangeListener<Boolean>() {
@Override
public void changed(ObservableValue<? extends Boolean> observableValue, Boolean oldSelected, Boolean newSelected) {
if (newSelected) {
job.getIssueDetectionService().addDetector(issueDetector);
} else {
job.getIssueDetectionService().removeDetector(issueDetector);
}
updateCanAnalyze();
}
});
checkBox.setSelected(true);
strategyOptions.getChildren().add(checkBox);
}
}
}