Skip to content

Commit

Permalink
Merge pull request AY2425S1-CS2103T-T12-4#121 from JJtan2002/save-and…
Browse files Browse the repository at this point in the history
…-load

Implement save and load commands
  • Loading branch information
flyingsalsa authored Oct 18, 2024
2 parents 38da93a + c9fb3ad commit 89dbe99
Show file tree
Hide file tree
Showing 24 changed files with 224 additions and 44 deletions.
3 changes: 2 additions & 1 deletion src/main/java/seedu/address/MainApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ public void init() throws Exception {

UserPrefsStorage userPrefsStorage = new JsonUserPrefsStorage(config.getUserPrefsFilePath());
UserPrefs userPrefs = initPrefs(userPrefsStorage);
AddressBookStorage addressBookStorage = new JsonAddressBookStorage(userPrefs.getAddressBookFilePath());
AddressBookStorage addressBookStorage =
new JsonAddressBookStorage(userPrefs.getAddressBookFilePath(), userPrefs.getManualSaveFilePath());
storage = new StorageManager(addressBookStorage, userPrefsStorage);

model = initModelManager(storage, userPrefs);
Expand Down
29 changes: 22 additions & 7 deletions src/main/java/seedu/address/logic/LogicManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,28 @@ public CommandResult execute(String commandText) throws CommandException, ParseE
CommandResult commandResult;
Command command = addressBookParser.parseCommand(commandText);
commandResult = command.execute(model);

try {
storage.saveAddressBook(model.getAddressBook());
} catch (AccessDeniedException e) {
throw new CommandException(String.format(FILE_OPS_PERMISSION_ERROR_FORMAT, e.getMessage()), e);
} catch (IOException ioe) {
throw new CommandException(String.format(FILE_OPS_ERROR_FORMAT, ioe.getMessage()), ioe);
if (commandResult.isLoad()) {
try {
ReadOnlyAddressBook loadedAddressBook = storage.loadAddressBookManually().get();
model.setAddressBook(loadedAddressBook);
storage.saveAddressBook(loadedAddressBook);
} catch (Exception e) {
throw new CommandException(String.format(FILE_OPS_ERROR_FORMAT, e.getMessage()), e);
}
} else if (commandResult.isSave()) {
try {
storage.saveAddressBookManually(model.getAddressBook());
} catch (IOException ioe) {
throw new CommandException(String.format(FILE_OPS_ERROR_FORMAT, ioe.getMessage()), ioe);
}
} else {
try {
storage.saveAddressBook(model.getAddressBook());
} catch (AccessDeniedException e) {
throw new CommandException(String.format(FILE_OPS_PERMISSION_ERROR_FORMAT, e.getMessage()), e);
} catch (IOException ioe) {
throw new CommandException(String.format(FILE_OPS_ERROR_FORMAT, ioe.getMessage()), ioe);
}
}

return commandResult;
Expand Down
25 changes: 21 additions & 4 deletions src/main/java/seedu/address/logic/commands/CommandResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,28 @@ public class CommandResult {
/** The application should exit. */
private final boolean exit;

/** Manually save the current address book state */
private final boolean save;

private final boolean load;

/**
* Constructs a {@code CommandResult} with the specified fields.
*/
public CommandResult(String feedbackToUser, boolean showHelp, boolean exit) {
public CommandResult(String feedbackToUser, boolean showHelp, boolean exit, boolean save, boolean load) {
this.feedbackToUser = requireNonNull(feedbackToUser);
this.showHelp = showHelp;
this.exit = exit;
this.save = save;
this.load = load;
}

/**
* Constructs a {@code CommandResult} with the specified {@code feedbackToUser},
* and other fields set to their default value.
*/
public CommandResult(String feedbackToUser) {
this(feedbackToUser, false, false);
this(feedbackToUser, false, false, false, false);
}

public String getFeedbackToUser() {
Expand All @@ -47,6 +54,13 @@ public boolean isShowHelp() {
public boolean isExit() {
return exit;
}
public boolean isSave() {
return save;
}
public boolean isLoad() {
return load;
}


@Override
public boolean equals(Object other) {
Expand All @@ -62,12 +76,13 @@ public boolean equals(Object other) {
CommandResult otherCommandResult = (CommandResult) other;
return feedbackToUser.equals(otherCommandResult.feedbackToUser)
&& showHelp == otherCommandResult.showHelp
&& exit == otherCommandResult.exit;
&& exit == otherCommandResult.exit
&& save == otherCommandResult.save;
}

@Override
public int hashCode() {
return Objects.hash(feedbackToUser, showHelp, exit);
return Objects.hash(feedbackToUser, showHelp, exit, save);
}

@Override
Expand All @@ -76,6 +91,8 @@ public String toString() {
.add("feedbackToUser", feedbackToUser)
.add("showHelp", showHelp)
.add("exit", exit)
.add("save", save)
.add("load", load)
.toString();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class ExitCommand extends Command {

@Override
public CommandResult execute(Model model) {
return new CommandResult(MESSAGE_EXIT_ACKNOWLEDGEMENT, false, true);
return new CommandResult(MESSAGE_EXIT_ACKNOWLEDGEMENT, false, true, false, false);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ public class HelpCommand extends Command {

@Override
public CommandResult execute(Model model) {
return new CommandResult(SHOWING_HELP_MESSAGE, true, false);
return new CommandResult(SHOWING_HELP_MESSAGE, true, false, false, false);
}
}
14 changes: 14 additions & 0 deletions src/main/java/seedu/address/logic/commands/LoadCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package seedu.address.logic.commands;

import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.Model;
/**
* Load command that will set address book to the saved file.
*/
public class LoadCommand extends Command {
public static final String COMMAND_WORD = "load";
public static final String MESSAGE_SUCCESS = "The saved address book has been loaded!";
public CommandResult execute(Model model) throws CommandException {
return new CommandResult(MESSAGE_SUCCESS, false, false, false, true);
}
}
15 changes: 15 additions & 0 deletions src/main/java/seedu/address/logic/commands/SaveCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package seedu.address.logic.commands;

import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.Model;

/**
* Save command that saves the address book state to a save file.
*/
public class SaveCommand extends Command {
public static final String COMMAND_WORD = "save";
public static final String MESSAGE_SUCCESS = "Address book has been saved!";
public CommandResult execute(Model model) throws CommandException {
return new CommandResult(MESSAGE_SUCCESS, false, false, true, false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import seedu.address.logic.commands.FindCommand;
import seedu.address.logic.commands.HelpCommand;
import seedu.address.logic.commands.ListCommand;
import seedu.address.logic.commands.LoadCommand;
import seedu.address.logic.commands.SaveCommand;
import seedu.address.logic.parser.exceptions.ParseException;

/**
Expand Down Expand Up @@ -81,6 +83,11 @@ public Command parseCommand(String userInput) throws ParseException {
case EditGameCommand.COMMAND_WORD:
return new EditGameCommandParser().parse(arguments);

case SaveCommand.COMMAND_WORD:
return new SaveCommand();

case LoadCommand.COMMAND_WORD:
return new LoadCommand();
default:
logger.finer("This user input caused a ParseException: " + userInput);
throw new ParseException(MESSAGE_UNKNOWN_COMMAND);
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/seedu/address/model/UserPrefs.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public class UserPrefs implements ReadOnlyUserPrefs {

private GuiSettings guiSettings = new GuiSettings();
private Path addressBookFilePath = Paths.get("data" , "addressbook.json");
private Path manualSaveFilePath = Paths.get("data", "save.json");

/**
* Creates a {@code UserPrefs} with default values.
Expand Down Expand Up @@ -56,6 +57,15 @@ public void setAddressBookFilePath(Path addressBookFilePath) {
this.addressBookFilePath = addressBookFilePath;
}

public Path getManualSaveFilePath() {
return manualSaveFilePath;
}

public void setManualSaveFilePath(Path manualSaveFilePath) {
requireNonNull(manualSaveFilePath);
this.manualSaveFilePath = manualSaveFilePath;
}

@Override
public boolean equals(Object other) {
if (other == this) {
Expand Down
29 changes: 29 additions & 0 deletions src/main/java/seedu/address/model/VersionedAddressBook.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package seedu.address.model;

import java.util.ArrayList;
import java.util.List;

/**
* {@code AddressBook} that tracks its state across command executions
*/
public class VersionedAddressBook extends AddressBook {
private final List<ReadOnlyAddressBook> addressBookStates;
private int currentStatePointer;

/**
* Constructs a {@code VersionedAddressBook} with the initial state of the address book.
* The address book will start with the specified initial state and the current state pointer
* will be set to the initial state.
*
* @param initialState The initial state of the address book to be used as the starting point.
* Cannot be null.
*/
public VersionedAddressBook(ReadOnlyAddressBook initialState) {
super(initialState);

addressBookStates = new ArrayList<>();
addressBookStates.add(new AddressBook(initialState));
currentStatePointer = 0;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,5 @@ public interface AddressBookStorage {
*/
void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) throws IOException;

Path getManualSaveFilePath();
}
14 changes: 13 additions & 1 deletion src/main/java/seedu/address/storage/JsonAddressBookStorage.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,27 @@ public class JsonAddressBookStorage implements AddressBookStorage {
private static final Logger logger = LogsCenter.getLogger(JsonAddressBookStorage.class);

private Path filePath;
private Path manualSaveFilePath;

public JsonAddressBookStorage(Path filePath) {
/**
* Creates a new JsonAddressBookStorage object.
*
* @param filePath The path to the JSON file where the address book data will be stored.
* @param manualSaveFilePath The path to the JSON file where the address book data will be manually saved.
*/
public JsonAddressBookStorage(Path filePath, Path manualSaveFilePath) {
this.filePath = filePath;
this.manualSaveFilePath = manualSaveFilePath;
}

public Path getAddressBookFilePath() {
return filePath;
}

public Path getManualSaveFilePath() {
return manualSaveFilePath;
}

@Override
public Optional<ReadOnlyAddressBook> readAddressBook() throws DataLoadingException {
return readAddressBook(filePath);
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/seedu/address/storage/Storage.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,7 @@ public interface Storage extends AddressBookStorage, UserPrefsStorage {
@Override
void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException;

void saveAddressBookManually(ReadOnlyAddressBook addressBook) throws IOException;

Optional<ReadOnlyAddressBook> loadAddressBookManually() throws Exception;
}
38 changes: 38 additions & 0 deletions src/main/java/seedu/address/storage/StorageManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,16 @@ public class StorageManager implements Storage {
private AddressBookStorage addressBookStorage;
private UserPrefsStorage userPrefsStorage;

// Path for the manual save/load file
private Path manualSaveFilePath;

/**
* Creates a {@code StorageManager} with the given {@code AddressBookStorage} and {@code UserPrefStorage}.
*/
public StorageManager(AddressBookStorage addressBookStorage, UserPrefsStorage userPrefsStorage) {
this.addressBookStorage = addressBookStorage;
this.userPrefsStorage = userPrefsStorage;
manualSaveFilePath = addressBookStorage.getManualSaveFilePath();
}

// ================ UserPrefs methods ==============================
Expand Down Expand Up @@ -75,4 +79,38 @@ public void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) thro
addressBookStorage.saveAddressBook(addressBook, filePath);
}

// ================ Manual Save/Load Methods ==============================

public Path getManualSaveFilePath() {
return addressBookStorage.getManualSaveFilePath();
}

/**
* Manually saves the address book to the specified file path.
*
* @param addressBook The address book data to save.
* @throws IOException If there is an error saving the file.
*/
@Override
public void saveAddressBookManually(ReadOnlyAddressBook addressBook) throws IOException {
if (manualSaveFilePath == null) {
throw new IOException("Manual save file path is not set.");
}
logger.fine("Attempting to manually write to file: " + manualSaveFilePath);
addressBookStorage.saveAddressBook(addressBook, manualSaveFilePath);
}

/**
* Manually loads the address book from the specified file path.
*
* @return An optional containing the address book if successfully loaded, otherwise an empty optional.
* @throws DataLoadingException If there is an error loading the file.
*/
@Override
public Optional<ReadOnlyAddressBook> loadAddressBookManually() throws DataLoadingException {

logger.fine("Attempting to manually read from file: " + manualSaveFilePath);
return addressBookStorage.readAddressBook(manualSaveFilePath);
}

}
14 changes: 13 additions & 1 deletion src/main/java/seedu/address/ui/MainWindow.java
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,9 @@ private CommandResult executeCommand(String commandText) throws CommandException
if (commandResult.isShowHelp()) {
handleHelp();
}

if (commandResult.isLoad()) {
refreshPersonListPanel();
}
if (commandResult.isExit()) {
handleExit();
}
Expand All @@ -193,4 +195,14 @@ private CommandResult executeCommand(String commandText) throws CommandException
throw e;
}
}
private void refreshPersonListPanel() {
// Clear existing components from the placeholder
personListPanelPlaceholder.getChildren().clear();

// Recreate the PersonListPanel with the updated list
personListPanel = new PersonListPanel(logic.getFilteredPersonList());

// Add the new PersonListPanel to the placeholder
personListPanelPlaceholder.getChildren().add(personListPanel.getRoot());
}
}
6 changes: 4 additions & 2 deletions src/test/java/seedu/address/logic/LogicManagerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ public class LogicManagerTest {
@BeforeEach
public void setUp() {
JsonAddressBookStorage addressBookStorage =
new JsonAddressBookStorage(temporaryFolder.resolve("addressBook.json"));
new JsonAddressBookStorage(temporaryFolder.resolve("addressBook.json"),
temporaryFolder.resolve("save.json"));
JsonUserPrefsStorage userPrefsStorage = new JsonUserPrefsStorage(temporaryFolder.resolve("userPrefs.json"));
StorageManager storage = new StorageManager(addressBookStorage, userPrefsStorage);
logic = new LogicManager(model, storage);
Expand Down Expand Up @@ -150,7 +151,8 @@ private void assertCommandFailureForExceptionFromStorage(IOException e, String e
Path prefPath = temporaryFolder.resolve("ExceptionUserPrefs.json");

// Inject LogicManager with an AddressBookStorage that throws the IOException e when saving
JsonAddressBookStorage addressBookStorage = new JsonAddressBookStorage(prefPath) {
JsonAddressBookStorage addressBookStorage = new JsonAddressBookStorage(prefPath,
temporaryFolder.resolve("save.json")) {
@Override
public void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath)
throws IOException {
Expand Down
Loading

0 comments on commit 89dbe99

Please sign in to comment.