diff --git a/src/main/java/seedu/address/storage/AddressBookStorage.java b/src/main/java/seedu/address/storage/AddressBookStorage.java index 4599182b3f92..c19f6acd7e9b 100644 --- a/src/main/java/seedu/address/storage/AddressBookStorage.java +++ b/src/main/java/seedu/address/storage/AddressBookStorage.java @@ -17,6 +17,11 @@ public interface AddressBookStorage { */ Path getAddressBookFilePath(); + /** + * Returns the file path of the backup data file. + */ + Path getAddressBookBackupFilePath(); + /** * Returns AddressBook data as a {@link ReadOnlyAddressBook}. * Returns {@code Optional.empty()} if storage file is not found. @@ -42,4 +47,10 @@ public interface AddressBookStorage { */ void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) throws IOException; + /** + * Backup the given {@link ReadOnlyAddressBook} to the storage. + * @param addressBook + * @throws IOException + */ + void backupAddressBook(ReadOnlyAddressBook addressBook) throws IOException; } diff --git a/src/main/java/seedu/address/storage/JsonAddressBookStorage.java b/src/main/java/seedu/address/storage/JsonAddressBookStorage.java index dfab9daaa0d3..864ce6f74c32 100644 --- a/src/main/java/seedu/address/storage/JsonAddressBookStorage.java +++ b/src/main/java/seedu/address/storage/JsonAddressBookStorage.java @@ -1,9 +1,11 @@ package seedu.address.storage; +import static java.util.Objects.isNull; import static java.util.Objects.requireNonNull; import java.io.IOException; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Optional; import java.util.logging.Logger; @@ -22,15 +24,25 @@ public class JsonAddressBookStorage implements AddressBookStorage { private static final Logger logger = LogsCenter.getLogger(JsonAddressBookStorage.class); private Path filePath; + private Path backupFilePath; public JsonAddressBookStorage(Path filePath) { this.filePath = filePath; + if (isNull(filePath.getParent())) { + this.backupFilePath = Paths.get("backup.json"); + } else { + this.backupFilePath = filePath.getParent().resolve("backup.json"); + } } public Path getAddressBookFilePath() { return filePath; } + public Path getAddressBookBackupFilePath() { + return backupFilePath; + } + @Override public Optional readAddressBook() throws DataConversionException { return readAddressBook(filePath); @@ -77,4 +89,8 @@ public void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) thro JsonUtil.saveJsonFile(new JsonSerializableAddressBook(addressBook), filePath); } + @Override + public void backupAddressBook(ReadOnlyAddressBook addressBook) throws IOException { + saveAddressBook(addressBook, backupFilePath); + } } diff --git a/src/main/java/seedu/address/storage/Storage.java b/src/main/java/seedu/address/storage/Storage.java index beda8bd9f11b..757324ac45b3 100644 --- a/src/main/java/seedu/address/storage/Storage.java +++ b/src/main/java/seedu/address/storage/Storage.java @@ -23,10 +23,16 @@ public interface Storage extends AddressBookStorage, UserPrefsStorage { @Override Path getAddressBookFilePath(); + @Override + Path getAddressBookBackupFilePath(); + @Override Optional readAddressBook() throws DataConversionException, IOException; @Override void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException; + @Override + void backupAddressBook(ReadOnlyAddressBook addressBook) throws IOException; + } diff --git a/src/main/java/seedu/address/storage/StorageManager.java b/src/main/java/seedu/address/storage/StorageManager.java index e4f452b6cbf4..4cd5e765820a 100644 --- a/src/main/java/seedu/address/storage/StorageManager.java +++ b/src/main/java/seedu/address/storage/StorageManager.java @@ -52,6 +52,11 @@ public Path getAddressBookFilePath() { return addressBookStorage.getAddressBookFilePath(); } + @Override + public Path getAddressBookBackupFilePath() { + return addressBookStorage.getAddressBookBackupFilePath(); + } + @Override public Optional readAddressBook() throws DataConversionException, IOException { return readAddressBook(addressBookStorage.getAddressBookFilePath()); @@ -74,4 +79,10 @@ public void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) thro addressBookStorage.saveAddressBook(addressBook, filePath); } + @Override + public void backupAddressBook(ReadOnlyAddressBook addressBook) throws IOException { + logger.fine("Attempting to write to backup data file: " + addressBookStorage.getAddressBookBackupFilePath()); + addressBookStorage.backupAddressBook(addressBook); + } + } diff --git a/src/test/java/seedu/address/storage/JsonAddressBookStorageTest.java b/src/test/java/seedu/address/storage/JsonAddressBookStorageTest.java index 6c18ecd0edd9..72e3815dcc91 100644 --- a/src/test/java/seedu/address/storage/JsonAddressBookStorageTest.java +++ b/src/test/java/seedu/address/storage/JsonAddressBookStorageTest.java @@ -98,6 +98,27 @@ public void readAndSaveAddressBook_allInOrder_success() throws Exception { } + @Test + public void readAndBackupAddressBook_allInOrder_success() throws Exception { + Path filePath = testFolder.getRoot().toPath().resolve("TempAddressBook.json"); + AddressBook original = getTypicalAddressBook(); + JsonAddressBookStorage jsonAddressBookStorage = new JsonAddressBookStorage(filePath); + + // Backup in new file and read back + jsonAddressBookStorage.backupAddressBook(original); + ReadOnlyAddressBook readBack = jsonAddressBookStorage.readAddressBook( + jsonAddressBookStorage.getAddressBookBackupFilePath()).get(); + assertEquals(original, new AddressBook(readBack)); + + // Modify data, overwrite backup file, and read back + original.addPerson(HOON); + original.removePerson(ALICE); + jsonAddressBookStorage.backupAddressBook(original); + readBack = jsonAddressBookStorage.readAddressBook( + jsonAddressBookStorage.getAddressBookBackupFilePath()).get(); + assertEquals(original, new AddressBook(readBack)); + } + @Test public void saveAddressBook_nullAddressBook_throwsNullPointerException() { thrown.expect(NullPointerException.class); diff --git a/src/test/java/seedu/address/storage/StorageManagerTest.java b/src/test/java/seedu/address/storage/StorageManagerTest.java index b56a68ded0b3..83beb795637d 100644 --- a/src/test/java/seedu/address/storage/StorageManagerTest.java +++ b/src/test/java/seedu/address/storage/StorageManagerTest.java @@ -62,9 +62,28 @@ public void addressBookReadSave() throws Exception { assertEquals(original, new AddressBook(retrieved)); } + @Test + public void addressBookReadBackup() throws Exception { + /* + * Note: This is an integration test that verifies the StorageManager is properly wired to the + * {@link JsonAddressBookStorage} class. + * More extensive testing of UserPref saving/reading is done in {@link JsonAddressBookStorageTest} class. + */ + AddressBook original = getTypicalAddressBook(); + storageManager.backupAddressBook(original); + ReadOnlyAddressBook retrieved = storageManager.readAddressBook( + storageManager.getAddressBookBackupFilePath()).get(); + assertEquals(original, new AddressBook(retrieved)); + } + @Test public void getAddressBookFilePath() { assertNotNull(storageManager.getAddressBookFilePath()); } + @Test + public void getAddressBookBackupFilePath() { + assertNotNull(storageManager.getAddressBookBackupFilePath()); + } + }