Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Storage components #55

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 3 additions & 33 deletions src/main/java/seedu/address/MainApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,9 @@
import seedu.address.commons.util.StringUtil;
import seedu.address.logic.Logic;
import seedu.address.logic.LogicManager;
import seedu.address.model.AddressBook;
import seedu.address.model.Model;
import seedu.address.model.ModelManager;
import seedu.address.model.ReadOnlyAddressBook;
import seedu.address.model.ReadOnlyUserPrefs;
import seedu.address.model.UserPrefs;
import seedu.address.model.util.SampleDataUtil;
import seedu.address.storage.AddressBookStorage;
import seedu.address.storage.JsonAddressBookStorage;
import seedu.address.storage.JsonUserPrefsStorage;
Expand Down Expand Up @@ -60,39 +56,13 @@
AddressBookStorage addressBookStorage = new JsonAddressBookStorage(userPrefs.getAddressBookFilePath());
storage = new StorageManager(addressBookStorage, userPrefsStorage);

model = initModelManager(storage, userPrefs);
model = new ModelManager(storage.readInitialAddressBook(), userPrefs);

Check warning on line 59 in src/main/java/seedu/address/MainApp.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/seedu/address/MainApp.java#L59

Added line #L59 was not covered by tests

logic = new LogicManager(model, storage);

ui = new UiManager(logic);
}

/**
* Returns a {@code ModelManager} with the data from {@code storage}'s address book and {@code userPrefs}. <br>
* The data from the sample address book will be used instead if {@code storage}'s address book is not found,
* or an empty address book will be used instead if errors occur when reading {@code storage}'s address book.
*/
private Model initModelManager(Storage storage, ReadOnlyUserPrefs userPrefs) {
logger.info("Using data file : " + storage.getAddressBookFilePath());

Optional<ReadOnlyAddressBook> addressBookOptional;
ReadOnlyAddressBook initialData;
try {
addressBookOptional = storage.readAddressBook();
if (!addressBookOptional.isPresent()) {
logger.info("Creating a new data file " + storage.getAddressBookFilePath()
+ " populated with a sample AddressBook.");
}
initialData = addressBookOptional.orElseGet(SampleDataUtil::getSampleAddressBook);
} catch (DataLoadingException e) {
logger.warning("Data file at " + storage.getAddressBookFilePath() + " could not be loaded."
+ " Will be starting with an empty AddressBook.");
initialData = new AddressBook();
}

return new ModelManager(initialData, userPrefs);
}

private void initLogging(Config config) {
LogsCenter.init(config);
}
Expand All @@ -117,7 +87,7 @@

try {
Optional<Config> configOptional = ConfigUtil.readConfig(configFilePathUsed);
if (!configOptional.isPresent()) {
if (configOptional.isEmpty()) {
logger.info("Creating new config file " + configFilePathUsed);
}
initializedConfig = configOptional.orElse(new Config());
Expand Down Expand Up @@ -148,7 +118,7 @@
UserPrefs initializedPrefs;
try {
Optional<UserPrefs> prefsOptional = storage.readUserPrefs();
if (!prefsOptional.isPresent()) {
if (prefsOptional.isEmpty()) {
logger.info("Creating new preference file " + prefsFilePath);
}
initializedPrefs = prefsOptional.orElse(new UserPrefs());
Expand Down
10 changes: 2 additions & 8 deletions src/main/java/seedu/address/logic/Logic.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
import seedu.address.commons.core.GuiSettings;
import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.logic.parser.exceptions.ParseException;
import seedu.address.model.ReadOnlyAddressBook;
import seedu.address.model.person.Person;
import seedu.address.storage.exceptions.StorageException;

/**
* API of the Logic component
Expand All @@ -20,14 +20,8 @@ public interface Logic {
* @throws CommandException If an error occurs during command execution.
* @throws ParseException If an error occurs during parsing.
*/
String execute(String commandText) throws CommandException, ParseException;

/**
* Returns the AddressBook.
*
* @see seedu.address.model.Model#getAddressBook()
*/
ReadOnlyAddressBook getAddressBook();
String execute(String commandText) throws CommandException, ParseException, StorageException;

/** Returns an unmodifiable view of the filtered list of persons */
ObservableList<Person> getFilteredPersonList();
Expand Down
25 changes: 3 additions & 22 deletions src/main/java/seedu/address/logic/LogicManager.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package seedu.address.logic;

import java.io.IOException;
import java.nio.file.AccessDeniedException;
import java.nio.file.Path;
import java.util.logging.Logger;

Expand All @@ -13,19 +11,14 @@
import seedu.address.logic.parser.AddressBookParser;
import seedu.address.logic.parser.exceptions.ParseException;
import seedu.address.model.Model;
import seedu.address.model.ReadOnlyAddressBook;
import seedu.address.model.person.Person;
import seedu.address.storage.Storage;
import seedu.address.storage.exceptions.StorageException;

/**
* The main LogicManager of the app.
*/
public class LogicManager implements Logic {
public static final String FILE_OPS_ERROR_FORMAT = "Could not save data due to the following error: %s";

public static final String FILE_OPS_PERMISSION_ERROR_FORMAT =
"Could not save data to file %s due to insufficient permissions to write to the file or the folder.";

private final Logger logger = LogsCenter.getLogger(LogicManager.class);

private final Model model;
Expand All @@ -40,28 +33,16 @@ public LogicManager(Model model, Storage storage) {
}

@Override
public String execute(String commandText) throws CommandException, ParseException {
public String execute(String commandText) throws CommandException, ParseException, StorageException {
logger.info("----------------[USER COMMAND][" + commandText + "]");

Command command = AddressBookParser.parseCommand(commandText);
String 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);
}
storage.saveAddressBook(model.getAddressBook());

return commandResult;
}

@Override
public ReadOnlyAddressBook getAddressBook() {
return model.getAddressBook();
}

@Override
public ObservableList<Person> getFilteredPersonList() {
return model.getFilteredPersonList();
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/seedu/address/storage/AddressBookStorage.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package seedu.address.storage;

import java.io.IOException;
import java.nio.file.Path;
import java.util.Optional;

import seedu.address.commons.exceptions.DataLoadingException;
import seedu.address.model.ReadOnlyAddressBook;
import seedu.address.storage.exceptions.StorageException;

/**
* Represents a storage for {@link seedu.address.model.AddressBook}.
Expand Down Expand Up @@ -33,13 +33,13 @@ public interface AddressBookStorage {
/**
* Saves the given {@link ReadOnlyAddressBook} to the storage.
* @param addressBook cannot be null.
* @throws IOException if there was any problem writing to the file.
* @throws StorageException if there was any problem writing to the file.
*/
void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException;
void saveAddressBook(ReadOnlyAddressBook addressBook) throws StorageException;

/**
* @see #saveAddressBook(ReadOnlyAddressBook)
*/
void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) throws IOException;
void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) throws StorageException;

}
27 changes: 19 additions & 8 deletions src/main/java/seedu/address/storage/JsonAddressBookStorage.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static java.util.Objects.requireNonNull;

import java.io.IOException;
import java.nio.file.AccessDeniedException;
import java.nio.file.Path;
import java.util.Optional;
import java.util.logging.Logger;
Expand All @@ -13,11 +14,17 @@
import seedu.address.commons.util.JsonUtil;
import seedu.address.model.AddressBook;
import seedu.address.model.ReadOnlyAddressBook;
import seedu.address.storage.exceptions.StorageException;

/**
* A class to access AddressBook data stored as a json file on the hard disk.
*/
public class JsonAddressBookStorage implements AddressBookStorage {
public static final String FILE_OPS_ERROR_FORMAT = "Could not save data due to the following error: %s";

public static final String FILE_OPS_PERMISSION_ERROR_FORMAT =
"Could not save data to file %s due to insufficient permissions to write to the file or the folder.";


private static final Logger logger = LogsCenter.getLogger(JsonAddressBookStorage.class);

Expand Down Expand Up @@ -46,14 +53,11 @@
requireNonNull(filePath);

Optional<AddressBook> addressBook = JsonUtil.readJsonFile(filePath, AddressBook.class);
if (!addressBook.isPresent()) {
return Optional.empty();
}
return Optional.of(addressBook.get());
return addressBook.map(value -> value);
}

@Override
public void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException {
public void saveAddressBook(ReadOnlyAddressBook addressBook) throws StorageException {
saveAddressBook(addressBook, filePath);
}

Expand All @@ -62,12 +66,19 @@
*
* @param filePath location of the data. Cannot be null.
*/
public void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) throws IOException {
public void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) throws StorageException {
requireNonNull(addressBook);
requireNonNull(filePath);

FileUtil.createIfMissing(filePath);
JsonUtil.saveJsonFile(addressBook, filePath);
try {
FileUtil.createIfMissing(filePath);
JsonUtil.saveJsonFile(addressBook, filePath);
} catch (AccessDeniedException e) {
throw new StorageException(String.format(FILE_OPS_PERMISSION_ERROR_FORMAT, e.getMessage()), e);
} catch (IOException ioe) {
throw new StorageException(String.format(FILE_OPS_ERROR_FORMAT, ioe.getMessage()), ioe);

Check warning on line 79 in src/main/java/seedu/address/storage/JsonAddressBookStorage.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/seedu/address/storage/JsonAddressBookStorage.java#L76-L79

Added lines #L76 - L79 were not covered by tests
}

}

}
4 changes: 3 additions & 1 deletion src/main/java/seedu/address/storage/Storage.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import seedu.address.model.ReadOnlyAddressBook;
import seedu.address.model.ReadOnlyUserPrefs;
import seedu.address.model.UserPrefs;
import seedu.address.storage.exceptions.StorageException;

/**
* API of the Storage component
Expand All @@ -27,6 +28,7 @@ public interface Storage extends AddressBookStorage, UserPrefsStorage {
Optional<ReadOnlyAddressBook> readAddressBook() throws DataLoadingException;

@Override
void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException;
void saveAddressBook(ReadOnlyAddressBook addressBook) throws StorageException;

ReadOnlyAddressBook readInitialAddressBook();
}
36 changes: 33 additions & 3 deletions src/main/java/seedu/address/storage/StorageManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,17 @@

import seedu.address.commons.core.LogsCenter;
import seedu.address.commons.exceptions.DataLoadingException;
import seedu.address.model.AddressBook;
import seedu.address.model.ReadOnlyAddressBook;
import seedu.address.model.ReadOnlyUserPrefs;
import seedu.address.model.UserPrefs;
import seedu.address.model.util.SampleDataUtil;
import seedu.address.storage.exceptions.StorageException;

/**
* Manages storage of AddressBook data in local storage.
*/
public class StorageManager implements Storage {

private static final Logger logger = LogsCenter.getLogger(StorageManager.class);
private AddressBookStorage addressBookStorage;
private UserPrefsStorage userPrefsStorage;
Expand Down Expand Up @@ -65,14 +67,42 @@
}

@Override
public void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException {
public void saveAddressBook(ReadOnlyAddressBook addressBook) throws StorageException {
saveAddressBook(addressBook, addressBookStorage.getAddressBookFilePath());
}

@Override
public void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) throws IOException {
public void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) throws StorageException {
logger.fine("Attempting to write to data file: " + filePath);
addressBookStorage.saveAddressBook(addressBook, filePath);
}

/**
* Returns a {@code ReadOnlyAddressBook} with the initial data from {@code addressBookStorage}. <br>
* The data from the sample address book will be used instead if {@code addressBookStorage}'s address book is not
* found, or an empty address book will be used instead if errors occur when reading {@code addressBookStorage}'s
* address book.
*/
@Override
public ReadOnlyAddressBook readInitialAddressBook() {
logger.info("Using data file : " + getAddressBookFilePath());

Optional<ReadOnlyAddressBook> addressBookOptional;
ReadOnlyAddressBook initialAddressBook;
try {
addressBookOptional = readAddressBook();
if (addressBookOptional.isEmpty()) {
logger.info("Creating a new data file " + getAddressBookFilePath()
+ " populated with a sample AddressBook.");
}
initialAddressBook = addressBookOptional.orElseGet(SampleDataUtil::getSampleAddressBook);
} catch (DataLoadingException e) {
logger.warning("Data file at " + getAddressBookFilePath() + " could not be loaded."

Check warning on line 100 in src/main/java/seedu/address/storage/StorageManager.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/seedu/address/storage/StorageManager.java#L99-L100

Added lines #L99 - L100 were not covered by tests
+ " Will be starting with an empty AddressBook.");
initialAddressBook = new AddressBook();

Check warning on line 102 in src/main/java/seedu/address/storage/StorageManager.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/seedu/address/storage/StorageManager.java#L102

Added line #L102 was not covered by tests
}

return initialAddressBook;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package seedu.address.storage.exceptions;

/**
* Represents a storage error encountered by Storage.
*/
public class StorageException extends Exception {
public StorageException(String message) {
super(message);
}

Check warning on line 9 in src/main/java/seedu/address/storage/exceptions/StorageException.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/seedu/address/storage/exceptions/StorageException.java#L8-L9

Added lines #L8 - L9 were not covered by tests

public StorageException(String message, Throwable cause) {
super(message, cause);
}

Check warning on line 13 in src/main/java/seedu/address/storage/exceptions/StorageException.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/seedu/address/storage/exceptions/StorageException.java#L12-L13

Added lines #L12 - L13 were not covered by tests
}
5 changes: 3 additions & 2 deletions src/main/java/seedu/address/ui/CommandBox.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import javafx.scene.layout.Region;
import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.logic.parser.exceptions.ParseException;
import seedu.address.storage.exceptions.StorageException;

/**
* The UI component that is responsible for receiving user command inputs.
Expand Down Expand Up @@ -43,7 +44,7 @@
try {
commandExecutor.execute(commandText);
commandTextField.setText("");
} catch (CommandException | ParseException e) {
} catch (CommandException | ParseException | StorageException e) {

Check warning on line 47 in src/main/java/seedu/address/ui/CommandBox.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/seedu/address/ui/CommandBox.java#L47

Added line #L47 was not covered by tests
setStyleToIndicateCommandFailure();
}
}
Expand Down Expand Up @@ -78,7 +79,7 @@
*
* @see seedu.address.logic.Logic#execute(String)
*/
String execute(String commandText) throws CommandException, ParseException;
String execute(String commandText) throws CommandException, ParseException, StorageException;
}

}
Loading