Skip to content

Commit

Permalink
Merge pull request #55 from bryanyee33/6-refactor-storage
Browse files Browse the repository at this point in the history
Refactor Storage components
  • Loading branch information
aureliony authored Mar 8, 2024
2 parents 31ebb75 + 5b9a802 commit fb03371
Show file tree
Hide file tree
Showing 13 changed files with 126 additions and 147 deletions.
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 @@ public void init() throws Exception {
AddressBookStorage addressBookStorage = new JsonAddressBookStorage(userPrefs.getAddressBookFilePath());
storage = new StorageManager(addressBookStorage, userPrefsStorage);

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

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 @@ protected Config initConfig(Path configFilePath) {

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 @@ protected UserPrefs initPrefs(UserPrefsStorage storage) {
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 @@ public Optional<ReadOnlyAddressBook> readAddressBook(Path filePath) throws DataL
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 @@ public void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException
*
* @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);
}

}

}
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 @@ public Optional<ReadOnlyAddressBook> readAddressBook(Path filePath) throws DataL
}

@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."
+ " Will be starting with an empty AddressBook.");
initialAddressBook = new AddressBook();
}

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);
}

public StorageException(String message, Throwable cause) {
super(message, cause);
}
}
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 @@ private void handleCommandEntered() {
try {
commandExecutor.execute(commandText);
commandTextField.setText("");
} catch (CommandException | ParseException e) {
} catch (CommandException | ParseException | StorageException e) {
setStyleToIndicateCommandFailure();
}
}
Expand Down Expand Up @@ -78,7 +79,7 @@ public interface CommandExecutor {
*
* @see seedu.address.logic.Logic#execute(String)
*/
String execute(String commandText) throws CommandException, ParseException;
String execute(String commandText) throws CommandException, ParseException, StorageException;
}

}
Loading

0 comments on commit fb03371

Please sign in to comment.