Commit 32f3082d authored by Joachim Müssig's avatar Joachim Müssig
Browse files

merge with herdaDev

parents b7331c3c 4553cad4
......@@ -72,6 +72,7 @@ Respective authors are listed in the following section.
This software was mainly designed and implemented by the following students:
* Joachim Müssig
* Holger Klein
* Marko Kleine Büning
* [Simon Bischof](https://pp.ipd.kit.edu/person.php?id=148)
......
......@@ -7,6 +7,7 @@ package gui;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.paint.Color;
/**
*
......@@ -23,14 +24,75 @@ public class CurrentActionLogger {
endProgress();
}
/**
* start progress indicator and show the given string as current action on the GUI
* @param msg the message you want to show on the GUI as current action
*/
public void startProgress(String msg) {
progressIndicator.setVisible(true);
labelCurrentAction.setText(msg);
labelCurrentAction.setTextFill(Color.BLACK);
}
/**
* start progress indicator and show the given string as current action on the GUI in a specific color
* @param msg the message you want to show on the GUI as current action
* @param c the color for the message
*/
public void startProgress(String msg, Color c) {
progressIndicator.setVisible(true);
labelCurrentAction.setTextFill(c);
labelCurrentAction.setText(msg);
}
/**
* stop progress indicator and clear the current action text on the gui.
*/
public void endProgress() {
labelCurrentAction.setText("");
progressIndicator.setVisible(false);
labelCurrentAction.setTextFill(Color.BLACK);
}
/**
* stop progress indicator and show the given string as current action on the GUI
* @param msg the message you want to show on the GUI as current action
*/
public void endProgressWithMessage(String msg) {
labelCurrentAction.setText(msg);
progressIndicator.setVisible(false);
labelCurrentAction.setTextFill(Color.BLACK);
}
/**
* stop progress indicator and show the given string as current action on the GUI
* @param msg the message you want to show on the GUI as current action
* @param c the color for the message
*/
public void endProgressWithMessage(String msg, Color c) {
labelCurrentAction.setText(msg);
labelCurrentAction.setTextFill(c);
progressIndicator.setVisible(false);
}
/**
* show the given string as current action on the GUI
* @param msg the message you want to show on the GUI as current action
*/
public void showMessage(String msg) {
labelCurrentAction.setText(msg);
labelCurrentAction.setTextFill(Color.BLACK);
}
/**
* show the given string as current action on the GUI
* @param msg the message you want to show on the GUI as current action
* @param c the color for the message
*/
public void showMessage(String msg, Color c) {
labelCurrentAction.setText(msg);
labelCurrentAction.setTextFill(c);
}
}
This diff is collapsed.
......@@ -29,6 +29,7 @@ public class DisproveViaKeYAndJoanaGUI extends Application {
controller.setMainStage(stage);
Scene scene = new Scene(root);
stage.setTitle("Combined Approach KeYJoana");
stage.setScene(scene);
stage.show();
......
......@@ -5,6 +5,10 @@
*/
package gui;
import java.io.IOException;
import java.util.ArrayList;
import edu.kit.joana.ifc.sdg.graph.SDG;
import edu.kit.joana.ifc.sdg.graph.SDGEdge;
import edu.kit.joana.ifc.sdg.graph.SDGNodeTuple;
import joanakey.AutomationHelper;
......@@ -12,28 +16,30 @@ import joanakey.customlistener.SummaryEdgeAndMethodToCorresData;
import joanakey.javaforkeycreator.JavaForKeYCreator;
import joanakey.persistence.DisprovingProject;
import joanakey.staticCG.javamodel.StaticCGJavaMethod;
import joanakey.violations.ViolationChop;
import joanakey.violations.ViolationsDisproverSemantic;
import joanakey.violations.ViolationsWrapper;
import joanakey.violations.ViolationsDisproverSemantic.PO_TYPE;
import java.io.IOException;
import joanakey.violations.ViolationsWrapper;
/**
*
* @author holger
* this class can be used to start the disproving process with KeY (also with command line mode)
* @author holger, joachim
*/
public class JoanaKeYInterfacer {
private ViolationsWrapper violationsWrapper;
private JavaForKeYCreator javaForKeyCreator;
private SummaryEdgeAndMethodToCorresData summaryEdgeToCorresData;
private boolean useSlicedFiles = true;
private boolean useMethodInlining = false;
private boolean useLoopUnwinding = false;
public JoanaKeYInterfacer(
DisprovingProject disprovingProject) throws IOException {
this.violationsWrapper = disprovingProject.getViolationsWrapper();
this.javaForKeyCreator
= new JavaForKeYCreator(
disprovingProject.getPathToJava(),
disprovingProject.getPathToJava(),
disprovingProject.getCallGraph(),
disprovingProject.getSdg(),
disprovingProject.getStateSaver());
......@@ -62,34 +68,47 @@ public class JoanaKeYInterfacer {
public void openInKeY(SDGEdge e,
SDGNodeTuple tuple,
StaticCGJavaMethod corresMethod) throws IOException {
//String pathToTestJava =
javaForKeyCreator.generateJavaForFormalTupleCalledFromGui(
summaryEdgeToCorresData.getContractFor(tuple),
corresMethod,
summaryEdgeToCorresData.getEdgeToLoopInvariantTemplate().get(e),
summaryEdgeToCorresData.getEdgeToLoopInvariant().get(e),
summaryEdgeToCorresData.getMethodToMostGeneralContract()
);
AutomationHelper.openKeY(ViolationsDisproverSemantic.PO_PATH);
if(corresMethod == null) {
throw new IllegalArgumentException("No method selected");
}
ArrayList<ViolationChop> chops = violationsWrapper.getSummaryEdgesAndContainingChops().get(e);
if (chops != null && !chops.isEmpty()) {
javaForKeyCreator.setMethodInlining(this.useMethodInlining);
javaForKeyCreator.setUseLoopUnwinding(this.useLoopUnwinding);
javaForKeyCreator.generateJavaForFormalTupleCalledFromGui(summaryEdgeToCorresData.getContractFor(tuple),
corresMethod, summaryEdgeToCorresData.getEdgeToLoopInvariantTemplate().get(e),
summaryEdgeToCorresData.getEdgeToLoopInvariant().get(e),
summaryEdgeToCorresData.getMethodToMostGeneralContract(), chops.get(0), useSlicedFiles); //all chops same slice ?
AutomationHelper.openKeY(ViolationsDisproverSemantic.PO_PATH);
}
}
/**
* try to disprove the given summary Edge with KeY in command line mode.
* @param e {@link SDGEdge} you want to disprove
* @param tuple
* @param corresMethod
* @return true if successfully disproven. Otherwise return False.
* @throws IOException
*/
public boolean tryDisproveEdge(
SDGEdge e,
SDGNodeTuple tuple,
StaticCGJavaMethod corresMethod) throws IOException {
StaticCGJavaMethod corresMethod) throws IOException{
if (corresMethod == null) {
throw new IOException("No method selected!");
throw new IllegalArgumentException("No method selected!");
}
//String pathToTestJava =
javaForKeyCreator.generateJavaForFormalTupleCalledFromGui(
summaryEdgeToCorresData.getContractFor(tuple),
corresMethod,
summaryEdgeToCorresData.getEdgeToLoopInvariantTemplate().get(e),
summaryEdgeToCorresData.getEdgeToLoopInvariant().get(e),
summaryEdgeToCorresData.getMethodToMostGeneralContract()
);
boolean worked = AutomationHelper.runKeY(ViolationsDisproverSemantic.PO_PATH,
PO_TYPE.INFORMATION_FLOW);
boolean worked = false;
ArrayList<ViolationChop> chops = violationsWrapper.getSummaryEdgesAndContainingChops().get(e);
if (chops != null && !chops.isEmpty()) {
ViolationChop chop = chops.get(0); //all chop same slice ?
// String pathToTestJava =
javaForKeyCreator.generateJavaForFormalTupleCalledFromGui(summaryEdgeToCorresData.getContractFor(tuple),
corresMethod, summaryEdgeToCorresData.getEdgeToLoopInvariantTemplate().get(e),
summaryEdgeToCorresData.getEdgeToLoopInvariant().get(e),
summaryEdgeToCorresData.getMethodToMostGeneralContract(), chop, useSlicedFiles);
worked = AutomationHelper.runKeY(ViolationsDisproverSemantic.PO_PATH, PO_TYPE.INFORMATION_FLOW);
}
if (worked) {
worked = AutomationHelper.runKeY(ViolationsDisproverSemantic.PO_PATH,
PO_TYPE.FUNCTIONAL);
......@@ -100,9 +119,19 @@ public class JoanaKeYInterfacer {
return worked;
}
public void markAsDisproved(SDGEdge currentSelectedEdge) {
/**
* mark the given {@link SDGEdge} as disproven and remove it from the {@link SDG} in {@link ViolationsWrapper}.
* @param currentSelectedEdge the {@link SDGEdge} you want to mark as disproven.
* @throws IllegalArgumentException
*/
public void markAsDisproved(SDGEdge currentSelectedEdge) throws IllegalArgumentException{
if(currentSelectedEdge == null) {
throw new IllegalArgumentException("No method selected!");
}
violationsWrapper.removeEdge(currentSelectedEdge);
}
public JavaForKeYCreator getJavaForKeyCreator() {
return javaForKeyCreator;
......@@ -111,8 +140,28 @@ public class JoanaKeYInterfacer {
public SummaryEdgeAndMethodToCorresData getSummaryEdgeToCorresData() {
return summaryEdgeToCorresData;
}
public void setUseSclicedFiles(boolean selected) {
this.useSlicedFiles = selected;
}
/**
* set method inlining option for the disproving process
* @param selected true, if you want to use method inlining
*/
public void setUseMethodInlining(boolean selected) {
this.useMethodInlining = selected;
javaForKeyCreator.setMethodInlining(selected);
}
/**
* set loop unwinding option for the disproving process
* @param selected true, if you want to use loop unwinding
*/
public void setUseLoopUnwinding(boolean selected) {
this.useLoopUnwinding = selected;
javaForKeyCreator.setUseLoopUnwinding(selected);
}
}
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Accordion?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ButtonBar?>
<?import javafx.scene.control.CheckMenuItem?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.control.Menu?>
......@@ -9,16 +11,18 @@
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.control.ProgressIndicator?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.control.TitledPane?>
<?import javafx.scene.input.KeyCodeCombination?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<AnchorPane id="AnchorPane" fx:id="anchorPaneMain" prefHeight="625.0" prefWidth="801.0" xmlns:fx="http://javafx.com/fxml/1" fx:controller="gui.MainWindowController">
<AnchorPane id="AnchorPane" fx:id="anchorPaneMain" prefHeight="625.0" prefWidth="801.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="gui.MainWindowController">
<children>
<SplitPane dividerPositions="0.13377926421404682" layoutX="475.0" layoutY="120.0" orientation="VERTICAL" prefHeight="200.0" prefWidth="160.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="25.0">
<items>
<AnchorPane fx:id="anchorPaneBasicInfo" minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="160.0">
<AnchorPane fx:id="anchorPaneBasicInfo" minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="160.0" SplitPane.resizableWithParent="false">
<children>
<GridPane layoutX="140.0" layoutY="42.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints>
......@@ -81,62 +85,67 @@
<children>
<SplitPane dividerPositions="0.4085106382978723" layoutX="320.0" layoutY="113.0" orientation="VERTICAL" prefHeight="200.0" prefWidth="160.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="160.0">
<AnchorPane minHeight="0.0" minWidth="0.0">
<children>
<SplitPane dividerPositions="0.7773584905660378" layoutX="340.0" layoutY="36.0" prefHeight="160.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<SplitPane dividerPositions="0.5952080706179067, 0.5" prefHeight="160.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="229.0" prefWidth="628.0">
<AnchorPane prefHeight="203.0" prefWidth="383.0">
<children>
<SplitPane dividerPositions="0.39299610894941633" prefHeight="160.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="30.0">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<SplitPane dividerPositions="0.29797979797979796" prefHeight="160.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<ListView fx:id="listViewUncheckedChops" layoutX="-51.0" layoutY="32.0" minWidth="-Infinity" prefHeight="173.0" prefWidth="328.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="30.0" />
<Label text="Violation to check" />
</children>
</AnchorPane>
<AnchorPane minHeight="0.0" minWidth="265.0" prefHeight="203.0" prefWidth="265.0">
<children>
<ListView fx:id="listViewUncheckedEdges" layoutY="30.0" prefHeight="173.0" prefWidth="249.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="30.0" />
<Label text="Summary Edges" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane minWidth="-Infinity" prefHeight="203.0" prefWidth="82.0">
<children>
<Accordion prefHeight="203.0" prefWidth="259.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<panes>
<TitledPane animated="false" text="Loops in Method">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<AnchorPane layoutX="0.40000000000000036" layoutY="-4.6" minHeight="0.0" minWidth="0.0" prefHeight="133.0" prefWidth="260.0" AnchorPane.bottomAnchor="-14.0" AnchorPane.leftAnchor="-10.0" AnchorPane.rightAnchor="-10.0" AnchorPane.topAnchor="-13.0">
<children>
<ListView fx:id="listViewUncheckedEdges" prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="30.0" />
<Label text="Summary Edges" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="0.0" />
<ListView fx:id="listViewLoopsOfSE" layoutX="-2.0" layoutY="-4.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="-3.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="169.0" prefWidth="132.0">
</children>
</AnchorPane>
</content>
</TitledPane>
<TitledPane animated="false" text="Called Methods in Current Method">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<AnchorPane layoutX="10.4" layoutY="9.4" minHeight="0.0" minWidth="0.0" prefHeight="129.0" prefWidth="260.0" AnchorPane.bottomAnchor="-3.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="-1.0">
<children>
<Label text="Formal In/Out Pairs" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="0.0" />
<ListView fx:id="listViewFormalInoutPairs" layoutX="-28.0" layoutY="-24.0" prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="30.0" />
<ListView fx:id="listViewCalledMethodsOfSE" layoutX="-12.0" layoutY="-8.0" AnchorPane.bottomAnchor="-10.0" AnchorPane.leftAnchor="-12.0" AnchorPane.rightAnchor="-11.0" AnchorPane.topAnchor="-8.0" />
</children>
</AnchorPane>
</items>
</SplitPane>
</children>
</AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<SplitPane dividerPositions="0.5013698630136987" layoutX="54.0" prefHeight="160.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="115.0">
</children>
</AnchorPane>
</content>
</TitledPane>
<TitledPane animated="false" text="Formal In/Out Pairs">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="124.0" prefWidth="176.0">
<children>
<AnchorPane layoutX="8.4" layoutY="9.4" prefHeight="137.0" prefWidth="189.0" AnchorPane.bottomAnchor="-12.0" AnchorPane.leftAnchor="-2.0" AnchorPane.rightAnchor="-11.0" AnchorPane.topAnchor="-1.0">
<children>
<ListView fx:id="listViewLoopsOfSE" layoutX="-56.0" layoutY="14.0" prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="30.0" />
<Label layoutX="7.0" layoutY="6.0" text="Loops in Method" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="0.0" />
<ListView fx:id="listViewFormalInoutPairs" layoutX="-10.0" layoutY="-9.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="-10.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="-9.0" />
</children>
</AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<ListView fx:id="listViewCalledMethodsOfSE" layoutX="14.0" layoutY="-34.0" prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="30.0" />
<Label layoutX="28.0" layoutY="6.0" text="Called Methods in Current Method" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children></AnchorPane>
</items>
</SplitPane>
</children>
</AnchorPane>
</items>
</SplitPane>
<Label text="Currently Not Disproved Summary Edges" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<Label layoutX="24.0" layoutY="22.0" text="Unchecked Violation Chops" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="0.0" />
<ListView fx:id="listViewUncheckedChops" layoutX="27.0" layoutY="15.0" prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="30.0" />
</children>
</AnchorPane>
</content>
</TitledPane>
</panes>
</Accordion>
</children>
</AnchorPane>
</items>
......@@ -189,11 +198,34 @@
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem fx:id="menuItemOpenJoak" mnemonicParsing="false" text="Load *.joak" />
<MenuItem fx:id="menuItemOpenDispro" mnemonicParsing="false" text="Load *.dispro" />
<MenuItem fx:id="menuItemSaveProgress" mnemonicParsing="false" text="Save Progress" />
<MenuItem fx:id="menuItemOpenJoak" mnemonicParsing="false" text="Load *.joak">
<accelerator>
<KeyCodeCombination alt="UP" code="L" control="DOWN" meta="UP" shift="UP" shortcut="UP" />
</accelerator></MenuItem>
<MenuItem fx:id="menuItemOpenDispro" mnemonicParsing="false" text="Load *.dispro">
<accelerator>
<KeyCodeCombination alt="UP" code="L" control="DOWN" meta="UP" shift="DOWN" shortcut="UP" />
</accelerator></MenuItem>
<MenuItem fx:id="menuItemReloadFile" disable="false" mnemonicParsing="false" text="Reload File">
<accelerator>
<KeyCodeCombination alt="UP" code="R" control="DOWN" meta="UP" shift="UP" shortcut="UP" />
</accelerator></MenuItem>
<Menu fx:id="menuOpenRecent" mnemonicParsing="false" text="Open Recent">
</Menu>
<MenuItem fx:id="menuItemSaveProgress" disable="true" mnemonicParsing="false" text="Save Progress">
<accelerator>
<KeyCodeCombination alt="UP" code="S" control="DOWN" meta="UP" shift="UP" shortcut="UP" />
</accelerator></MenuItem>
<MenuItem fx:id="menuItemExit" mnemonicParsing="false" text="Exit" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Options">
<items>
<CheckMenuItem fx:id="checkMenuItemUseSlicedFiles" disable="true" mnemonicParsing="false" selected="true" text="Use Sliced Files" />
<CheckMenuItem fx:id="checkMenuItemUseMethodInlining" disable="true" mnemonicParsing="false" text="Use Method Inlining" />
<CheckMenuItem fx:id="checkMenuItemUseLoopUnwinding" disable="true" mnemonicParsing="false" text="Use Loop Unwinding" />
</items>
</Menu>
</menus>
</MenuBar>
</children>
......
package gui;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
/**
* this class manages the recently loaded files
* @author joachim
*
*/
public class RecentlyUsedFilesManager {
private String recentlyUsedFilesPath;
private String mostRecentlyUsedFile;
private ArrayList<String> recentlyUsedFiles;
private int maxNumberOfSavedRecentlyLoadedFiles;
public RecentlyUsedFilesManager(String path) {
// recentlyUsedFilesPath = SettingsPaths.getRecentLoadedFilesPath();
recentlyUsedFilesPath = path;
this.maxNumberOfSavedRecentlyLoadedFiles = 5;
File f = new File(recentlyUsedFilesPath);
if (!f.exists()) {
try {
f.createNewFile();
} catch (IOException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
}
loadRecentlyUsedFilesPaths(recentlyUsedFilesPath);
}
/**
* get the most recently loaded file
* @return the most recently loaded file otherwise null
*/
public File getMostRecentlyUsedFile() {
if (mostRecentlyUsedFile != null) {
return new File(mostRecentlyUsedFile);
} else {
loadRecentlyUsedFilesPaths(recentlyUsedFilesPath);
boolean updated = updateMostRecentlyLoadedFilePath();
if (!updated) {
return null;
}
if (mostRecentlyUsedFile != null) {
File f = new File(mostRecentlyUsedFile);
if (f.exists()) {
return f;
}
}
return null;
}
}
public String[] getAllRecentlyUsedFilePaths() {
String[] names = new String[this.recentlyUsedFiles.size()];
for (int i = 0; i < names.length; i++) {
names[i] = recentlyUsedFiles.get(i);
}
return names;
}
/**
* Get the path of the most recently loaded file
* @return path of the most recently loaded file as path String
*/
public String getMostRecentlyUsedFilePath() {
if (mostRecentlyUsedFile == null) {
loadRecentlyUsedFilesPaths(recentlyUsedFilesPath);
return mostRecentlyUsedFile;
}
return mostRecentlyUsedFile;
}
/**
* stores the given file to the recently loaded files and update the most recently loaded file to it
* @param file you want to store and update to the most recently loaded file
*/
public void storeFileToRecentlyUsedFiles(File file) {
if(recentlyUsedFiles.contains(file.getAbsolutePath())) {
int index = recentlyUsedFiles.indexOf(file.getAbsolutePath());
recentlyUsedFiles.remove(index);
}
recentlyUsedFiles.add(0, file.getAbsolutePath());
updateMostRecentlyLoadedFilePath();
if (recentlyUsedFiles.size() > maxNumberOfSavedRecentlyLoadedFiles) {
recentlyUsedFiles.remove(recentlyUsedFiles.size()-1);
}
//Update mostRecentlyUsedFile
//store new content in the File for recently loaded files
try {
StringBuilder created = new StringBuilder();
FileWriter writer = new FileWriter(recentlyUsedFilesPath);
// PrintWriter out = new PrintWriter(writer);
for (int i = 0; i < recentlyUsedFiles.size(); i++) {
created.append(recentlyUsedFiles.get(i));
if (i != recentlyUsedFiles.size()-1) {
created.append("\n");
}
}
writer.write("");
// File recentlyUsedFiles = new File(recentlyUsedFilesPath);
// recentlyUsedFiles.delete();
// recentlyUsedFiles.createNewFile();
writer.write(created.toString());
writer.close();
// out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* set the maximum number of recently loaded files saved
* @param maxNumber
*/
public void setMaxNumberOfSavedFiles(int maxNumber) {
this.maxNumberOfSavedRecentlyLoadedFiles = maxNumber;
}