diff --git a/build.gradle b/build.gradle index 93029ef8262..e72606ed10a 100644 --- a/build.gradle +++ b/build.gradle @@ -67,7 +67,7 @@ dependencies { } shadowJar { - archiveName = 'addressbook.jar' + archiveName = 'MYMorise.jar' destinationDir = file("${buildDir}/jar/") } diff --git a/docs/DeveloperGuide.adoc b/docs/DeveloperGuide.adoc index 7178240fdd7..f50e4571681 100644 --- a/docs/DeveloperGuide.adoc +++ b/docs/DeveloperGuide.adoc @@ -57,7 +57,7 @@ Each of the four components * Defines its _API_ in an `interface` with the same name as the Component. * Exposes its functionality using a `{Component Name}Manager` class. -For example, the `Logic` component (see the class diagram given below) defines it's API in the `Logic.java` interface and exposes its functionality using the `LogicManager.java` class. +For example, the `Logic` component (see the class diagram given below) defines its API in the `Logic.java` interface and exposes its functionality using the `LogicManager.java` class. .Class Diagram of the Logic Component image::LogicClassDiagram.png[] diff --git a/docs/diagrams/ArchitectureSequenceDiagram.puml b/docs/diagrams/ArchitectureSequenceDiagram.puml index d1e2ae93675..00a78b7584e 100644 --- a/docs/diagrams/ArchitectureSequenceDiagram.puml +++ b/docs/diagrams/ArchitectureSequenceDiagram.puml @@ -19,7 +19,7 @@ activate model MODEL_COLOR model -[MODEL_COLOR]-> logic deactivate model -logic -[LOGIC_COLOR]> storage : saveAddressBook(addressBook) +logic -[LOGIC_COLOR]> storage : saveExpenseList(expenseList) activate storage STORAGE_COLOR storage -[STORAGE_COLOR]> storage : Save to file diff --git a/docs/diagrams/BetterModelClassDiagram.puml b/docs/diagrams/BetterModelClassDiagram.puml index 7790472da52..daabe53296c 100644 --- a/docs/diagrams/BetterModelClassDiagram.puml +++ b/docs/diagrams/BetterModelClassDiagram.puml @@ -4,18 +4,17 @@ skinparam arrowThickness 1.1 skinparam arrowColor MODEL_COLOR skinparam classBackgroundColor MODEL_COLOR -AddressBook *-right-> "1" UniquePersonList -AddressBook *-right-> "1" UniqueTagList -UniqueTagList -[hidden]down- UniquePersonList -UniqueTagList -[hidden]down- UniquePersonList +ExpenseList *-right-> "1" UniqueExpenseList +ExpenseList *-right-> "1" UniqueTagList +UniqueTagList -[hidden]down- UniqueExpenseList +UniqueTagList -[hidden]down- UniqueExpenseList UniqueTagList *-right-> "*" Tag -UniquePersonList o-right-> Person +UniqueExpenseList o-right-> Expense -Person o-up-> "*" Tag +Expense o-up-> "*" Tag -Person *--> Name -Person *--> Phone -Person *--> Email -Person *--> Address +Expense *--> Name +Expense *--> Amount +Expense *--> Date @enduml diff --git a/docs/diagrams/DeleteSequenceDiagram.puml b/docs/diagrams/DeleteSequenceDiagram.puml index 1dc2311b245..51b806aee88 100644 --- a/docs/diagrams/DeleteSequenceDiagram.puml +++ b/docs/diagrams/DeleteSequenceDiagram.puml @@ -48,7 +48,7 @@ deactivate AddressBookParser LogicManager -> DeleteCommand : execute() activate DeleteCommand -DeleteCommand -> Model : deletePerson(1) +DeleteCommand -> Model : deleteExpense(1) activate Model Model --> DeleteCommand diff --git a/docs/diagrams/LogicClassDiagram.puml b/docs/diagrams/LogicClassDiagram.puml index 016ef33e2e2..93fbbf12f5a 100644 --- a/docs/diagrams/LogicClassDiagram.puml +++ b/docs/diagrams/LogicClassDiagram.puml @@ -8,7 +8,7 @@ package Logic { package Parser { Interface Parser <> -Class AddressBookParser +Class MymParser Class XYZCommandParser Class CliSyntax Class ParserUtil @@ -35,8 +35,8 @@ Class HiddenOutside #FFFFFF HiddenOutside ..> Logic LogicManager .up.|> Logic -LogicManager -->"1" AddressBookParser -AddressBookParser .left.> XYZCommandParser: creates > +LogicManager -->"1" MymParser +MymParser .left.> XYZCommandParser: creates > XYZCommandParser ..> XYZCommand : creates > XYZCommandParser ..|> Parser diff --git a/docs/diagrams/ModelClassDiagram.puml b/docs/diagrams/ModelClassDiagram.puml index e85a00d4107..2e2cbcac2c5 100644 --- a/docs/diagrams/ModelClassDiagram.puml +++ b/docs/diagrams/ModelClassDiagram.puml @@ -5,23 +5,22 @@ skinparam arrowColor MODEL_COLOR skinparam classBackgroundColor MODEL_COLOR Package Model <>{ -Interface ReadOnlyAddressBook <> +Interface ReadOnlyExpenseList <> Interface Model <> Interface ObservableList <> -Class AddressBook -Class ReadOnlyAddressBook +Class ExpenseList +Class ReadOnlyExpenseList Class Model Class ModelManager Class UserPrefs Class ReadOnlyUserPrefs -Package Person { -Class Person -Class Address -Class Email +Package Expense { +Class Expense +Class Amount +Class Date Class Name -Class Phone -Class UniquePersonList +Class UniqueExpenseList } Package Tag { @@ -32,25 +31,23 @@ Class Tag Class HiddenOutside #FFFFFF HiddenOutside ..> Model -AddressBook .up.|> ReadOnlyAddressBook +ExpenseList .up.|> ReadOnlyExpenseList ModelManager .up.|> Model Model .right.> ObservableList -ModelManager o--> "1" AddressBook +ModelManager o--> "1" ExpenseList ModelManager o-left-> "1" UserPrefs UserPrefs .up.|> ReadOnlyUserPrefs -AddressBook *--> "1" UniquePersonList -UniquePersonList o--> "*" Person -Person *--> Name -Person *--> Phone -Person *--> Email -Person *--> Address -Person *--> "*" Tag +ExpenseList *--> "1" UniqueExpenseList +UniqueExpenseList o--> "*" Expense +Expense *--> Name +Expense *--> Amount +Expense *--> Date +Expense *--> "*" Tag -Name -[hidden]right-> Phone -Phone -[hidden]right-> Address -Address -[hidden]right-> Email +Name -[hidden]right-> Amount +Amount -[hidden]right-> Date -ModelManager -->"1" Person : filtered list +ModelManager -->"1" Expense : filtered list @enduml diff --git a/docs/diagrams/StorageClassDiagram.puml b/docs/diagrams/StorageClassDiagram.puml index 6adb2e156bf..88c0f92c696 100644 --- a/docs/diagrams/StorageClassDiagram.puml +++ b/docs/diagrams/StorageClassDiagram.puml @@ -6,19 +6,19 @@ skinparam classBackgroundColor STORAGE_COLOR Interface Storage <> Interface UserPrefsStorage <> -Interface AddressBookStorage <> +Interface ExpenseListStorage <> Class StorageManager Class JsonUserPrefsStorage -Class JsonAddressBookStorage +Class JsonExpenseListStorage StorageManager .left.|> Storage StorageManager o-right-> UserPrefsStorage -StorageManager o--> AddressBookStorage +StorageManager o--> ExpenseListStorage JsonUserPrefsStorage .left.|> UserPrefsStorage -JsonAddressBookStorage .left.|> AddressBookStorage -JsonAddressBookStorage .down.> JsonSerializableAddressBookStorage -JsonSerializableAddressBookStorage .right.> JsonSerializablePerson -JsonSerializablePerson .right.> JsonAdaptedTag +JsonExpenseListStorage .left.|> ExpenseListStorage +JsonExpenseListStorage .down.> JsonSerializableExpenseList +JsonSerializableExpenseList .right.> JsonAdaptedExpense +JsonAdaptedExpense .right.> JsonAdaptedTag @enduml diff --git a/docs/diagrams/UiClassDiagram.puml b/docs/diagrams/UiClassDiagram.puml index 92746f9fcf7..d0f3870dda6 100644 --- a/docs/diagrams/UiClassDiagram.puml +++ b/docs/diagrams/UiClassDiagram.puml @@ -11,8 +11,8 @@ Class UiManager Class MainWindow Class HelpWindow Class ResultDisplay -Class PersonListPanel -Class PersonCard +Class ExpenseListPanel +Class ExpenseCard Class StatusBarFooter Class CommandBox } @@ -33,25 +33,25 @@ UiManager -down-> MainWindow MainWindow --> HelpWindow MainWindow *-down-> CommandBox MainWindow *-down-> ResultDisplay -MainWindow *-down-> PersonListPanel +MainWindow *-down-> ExpenseListPanel MainWindow *-down-> StatusBarFooter -PersonListPanel -down-> PersonCard +ExpenseListPanel -down-> ExpenseCard MainWindow -left-|> UiPart ResultDisplay --|> UiPart CommandBox --|> UiPart -PersonListPanel --|> UiPart -PersonCard --|> UiPart +ExpenseListPanel --|> UiPart +ExpenseCard --|> UiPart StatusBarFooter --|> UiPart HelpWindow -down-|> UiPart -PersonCard ..> Model +ExpenseCard ..> Model UiManager -right-> Logic MainWindow -left-> Logic -PersonListPanel -[hidden]left- HelpWindow +ExpenseListPanel -[hidden]left- HelpWindow HelpWindow -[hidden]left- CommandBox CommandBox -[hidden]left- ResultDisplay ResultDisplay -[hidden]left- StatusBarFooter diff --git a/docs/diagrams/UndoRedoState0.puml b/docs/diagrams/UndoRedoState0.puml index 96e30744d24..8db94b45342 100644 --- a/docs/diagrams/UndoRedoState0.puml +++ b/docs/diagrams/UndoRedoState0.puml @@ -6,9 +6,9 @@ skinparam ClassBorderColor #000000 title Initial state package States { - class State1 as "__ab0:AddressBook__" - class State2 as "__ab1:AddressBook__" - class State3 as "__ab2:AddressBook__" + class State1 as "__mym1:ExpenseList__" + class State2 as "__mym2:ExpenseList__" + class State3 as "__mym3:ExpenseList__" } State1 -[hidden]right-> State2 State2 -[hidden]right-> State3 diff --git a/docs/diagrams/UndoRedoState1.puml b/docs/diagrams/UndoRedoState1.puml index 01fcb9b2b96..0db473e1937 100644 --- a/docs/diagrams/UndoRedoState1.puml +++ b/docs/diagrams/UndoRedoState1.puml @@ -6,9 +6,9 @@ skinparam ClassBorderColor #000000 title After command "delete 5" package States <> { - class State1 as "__ab0:AddressBook__" - class State2 as "__ab1:AddressBook__" - class State3 as "__ab2:AddressBook__" + class State1 as "__mym1:ExpenseList__" + class State2 as "__mym2:ExpenseList__" + class State3 as "__mym3:ExpenseList__" } State1 -[hidden]right-> State2 diff --git a/docs/diagrams/UndoRedoState2.puml b/docs/diagrams/UndoRedoState2.puml index bccc230a5d1..320868064e1 100644 --- a/docs/diagrams/UndoRedoState2.puml +++ b/docs/diagrams/UndoRedoState2.puml @@ -3,12 +3,12 @@ skinparam ClassFontColor #000000 skinparam ClassBorderColor #000000 -title After command "add n/David" +title After command "add /n Coffee" package States <> { - class State1 as "__ab0:AddressBook__" - class State2 as "__ab1:AddressBook__" - class State3 as "__ab2:AddressBook__" + class State1 as "__mym1:ExpenseList__" + class State2 as "__mym2:ExpenseList__" + class State3 as "__mym3:ExpenseList__" } State1 -[hidden]right-> State2 diff --git a/docs/diagrams/UndoRedoState3.puml b/docs/diagrams/UndoRedoState3.puml index ea29c9483e4..6f736109420 100644 --- a/docs/diagrams/UndoRedoState3.puml +++ b/docs/diagrams/UndoRedoState3.puml @@ -6,9 +6,9 @@ skinparam ClassBorderColor #000000 title After command "undo" package States <> { - class State1 as "__ab0:AddressBook__" - class State2 as "__ab1:AddressBook__" - class State3 as "__ab2:AddressBook__" + class State1 as "__mym1:ExpenseList__" + class State2 as "__mym2:ExpenseList__" + class State3 as "__mym3:ExpenseList__" } State1 -[hidden]right-> State2 diff --git a/docs/diagrams/UndoRedoState4.puml b/docs/diagrams/UndoRedoState4.puml index 1b784cece80..2b455d3dcc0 100644 --- a/docs/diagrams/UndoRedoState4.puml +++ b/docs/diagrams/UndoRedoState4.puml @@ -6,9 +6,9 @@ skinparam ClassBorderColor #000000 title After command "list" package States <> { - class State1 as "__ab0:AddressBook__" - class State2 as "__ab1:AddressBook__" - class State3 as "__ab2:AddressBook__" + class State1 as "__mym1:ExpenseList__" + class State2 as "__mym2:ExpenseList__" + class State3 as "__mym3:ExpenseList__" } State1 -[hidden]right-> State2 diff --git a/docs/diagrams/UndoRedoState5.puml b/docs/diagrams/UndoRedoState5.puml index 88927be32bc..e33960b814e 100644 --- a/docs/diagrams/UndoRedoState5.puml +++ b/docs/diagrams/UndoRedoState5.puml @@ -6,9 +6,9 @@ skinparam ClassBorderColor #000000 title After command "clear" package States <> { - class State1 as "__ab0:AddressBook__" - class State2 as "__ab1:AddressBook__" - class State3 as "__ab3:AddressBook__" + class State1 as "__mym1:ExpenseList__" + class State2 as "__mym2:ExpenseList__" + class State3 as "__mym3:ExpenseList__" } State1 -[hidden]right-> State2 @@ -17,5 +17,5 @@ State2 -[hidden]right-> State3 class Pointer as "Current State" #FFFFF Pointer -up-> State3 -note right on link: State ab2 deleted. +note right on link: State mym2 deleted. @end diff --git a/docs/diagrams/UndoSequenceDiagram.puml b/docs/diagrams/UndoSequenceDiagram.puml index 410aab4e412..4a545041896 100644 --- a/docs/diagrams/UndoSequenceDiagram.puml +++ b/docs/diagrams/UndoSequenceDiagram.puml @@ -9,7 +9,7 @@ end box box Model MODEL_COLOR_T1 participant ":Model" as Model MODEL_COLOR -participant ":VersionedAddressBook" as VersionedAddressBook MODEL_COLOR +participant ":VersionedExpenseList" as VersionedExpenseList MODEL_COLOR end box [-> LogicManager : execute(undo) activate LogicManager @@ -30,15 +30,15 @@ deactivate AddressBookParser LogicManager -> UndoCommand : execute() activate UndoCommand -UndoCommand -> Model : undoAddressBook() +UndoCommand -> Model : undoExpenseList() activate Model -Model -> VersionedAddressBook : undo() -activate VersionedAddressBook +Model -> VersionedExpenseList : undo() +activate VersionedExpenseList -VersionedAddressBook -> VersionedAddressBook :resetData(ReadOnlyAddressBook) -VersionedAddressBook --> Model : -deactivate VersionedAddressBook +VersionedExpenseList -> VersionedExpenseList :resetData(ReadOnlyExpenseList) +VersionedExpenseList --> Model : +deactivate VersionedExpenseList Model --> UndoCommand deactivate Model diff --git a/src/main/java/seedu/address/MainApp.java b/src/main/java/seedu/address/MainApp.java index e5cfb161b73..15973fd90ad 100644 --- a/src/main/java/seedu/address/MainApp.java +++ b/src/main/java/seedu/address/MainApp.java @@ -15,15 +15,15 @@ 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.ExpenseList; import seedu.address.model.Model; import seedu.address.model.ModelManager; -import seedu.address.model.ReadOnlyAddressBook; +import seedu.address.model.ReadOnlyExpenseList; 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.ExpenseListStorage; +import seedu.address.storage.JsonExpenseListStorage; import seedu.address.storage.JsonUserPrefsStorage; import seedu.address.storage.Storage; import seedu.address.storage.StorageManager; @@ -48,7 +48,7 @@ public class MainApp extends Application { @Override public void init() throws Exception { - logger.info("=============================[ Initializing AddressBook ]==========================="); + logger.info("=============================[ Initializing MYMorise ]==========================="); super.init(); AppParameters appParameters = AppParameters.parse(getParameters()); @@ -56,8 +56,8 @@ public void init() throws Exception { UserPrefsStorage userPrefsStorage = new JsonUserPrefsStorage(config.getUserPrefsFilePath()); UserPrefs userPrefs = initPrefs(userPrefsStorage); - AddressBookStorage addressBookStorage = new JsonAddressBookStorage(userPrefs.getAddressBookFilePath()); - storage = new StorageManager(addressBookStorage, userPrefsStorage); + ExpenseListStorage expenseListStorage = new JsonExpenseListStorage(userPrefs.getExpenseListFilePath()); + storage = new StorageManager(expenseListStorage, userPrefsStorage); initLogging(config); @@ -69,25 +69,25 @@ public void init() throws Exception { } /** - * Returns a {@code ModelManager} with the data from {@code storage}'s address book and {@code userPrefs}.
- * 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. + * Returns a {@code ModelManager} with the data from {@code storage}'s expense list and {@code userPrefs}.
+ * The data from the sample expense list will be used instead if {@code storage}'s expense list is not found, + * or an empty expense list will be used instead if errors occur when reading {@code storage}'s expense list. */ private Model initModelManager(Storage storage, ReadOnlyUserPrefs userPrefs) { - Optional addressBookOptional; - ReadOnlyAddressBook initialData; + Optional expenseListOptional; + ReadOnlyExpenseList initialData; try { - addressBookOptional = storage.readAddressBook(); - if (!addressBookOptional.isPresent()) { - logger.info("Data file not found. Will be starting with a sample AddressBook"); + expenseListOptional = storage.readExpenseList(); + if (!expenseListOptional.isPresent()) { + logger.info("Data file not found. Will be starting with a sample ExpenseList"); } - initialData = addressBookOptional.orElseGet(SampleDataUtil::getSampleAddressBook); + initialData = expenseListOptional.orElseGet(SampleDataUtil::getSampleExpenseList); } catch (DataConversionException e) { - logger.warning("Data file not in the correct format. Will be starting with an empty AddressBook"); - initialData = new AddressBook(); + logger.warning("Data file not in the correct format. Will be starting with an empty ExpenseList"); + initialData = new ExpenseList(); } catch (IOException e) { - logger.warning("Problem while reading from the file. Will be starting with an empty AddressBook"); - initialData = new AddressBook(); + logger.warning("Problem while reading from the file. Will be starting with an empty ExpenseList"); + initialData = new ExpenseList(); } return new ModelManager(initialData, userPrefs); @@ -151,7 +151,7 @@ protected UserPrefs initPrefs(UserPrefsStorage storage) { + "Using default user prefs"); initializedPrefs = new UserPrefs(); } catch (IOException e) { - logger.warning("Problem while reading from the file. Will be starting with an empty AddressBook"); + logger.warning("Problem while reading from the file. Will be starting with an empty ExpenseList"); initializedPrefs = new UserPrefs(); } @@ -167,13 +167,13 @@ protected UserPrefs initPrefs(UserPrefsStorage storage) { @Override public void start(Stage primaryStage) { - logger.info("Starting AddressBook " + MainApp.VERSION); + logger.info("Starting ExpenseList " + MainApp.VERSION); ui.start(primaryStage); } @Override public void stop() { - logger.info("============================ [ Stopping Address Book ] ============================="); + logger.info("============================ [ Stopping MYMorise ] ============================="); try { storage.saveUserPrefs(model.getUserPrefs()); } catch (IOException e) { diff --git a/src/main/java/seedu/address/commons/core/Config.java b/src/main/java/seedu/address/commons/core/Config.java index 91145745521..a5de8bd65a1 100644 --- a/src/main/java/seedu/address/commons/core/Config.java +++ b/src/main/java/seedu/address/commons/core/Config.java @@ -44,7 +44,7 @@ public boolean equals(Object other) { Config o = (Config) other; return Objects.equals(logLevel, o.logLevel) - && Objects.equals(userPrefsFilePath, o.userPrefsFilePath); + && Objects.equals(userPrefsFilePath, o.userPrefsFilePath); } @Override @@ -59,5 +59,4 @@ public String toString() { sb.append("\nPreference file Location : " + userPrefsFilePath); return sb.toString(); } - } diff --git a/src/main/java/seedu/address/commons/core/GuiSettings.java b/src/main/java/seedu/address/commons/core/GuiSettings.java index 5ace559ad15..dc4b73ae0ac 100644 --- a/src/main/java/seedu/address/commons/core/GuiSettings.java +++ b/src/main/java/seedu/address/commons/core/GuiSettings.java @@ -53,8 +53,8 @@ public boolean equals(Object other) { GuiSettings o = (GuiSettings) other; return windowWidth == o.windowWidth - && windowHeight == o.windowHeight - && Objects.equals(windowCoordinates, o.windowCoordinates); + && windowHeight == o.windowHeight + && Objects.equals(windowCoordinates, o.windowCoordinates); } @Override diff --git a/src/main/java/seedu/address/commons/core/LogsCenter.java b/src/main/java/seedu/address/commons/core/LogsCenter.java index 431e7185e76..104feb603b5 100644 --- a/src/main/java/seedu/address/commons/core/LogsCenter.java +++ b/src/main/java/seedu/address/commons/core/LogsCenter.java @@ -12,10 +12,11 @@ * Configures and manages loggers and handlers, including their logging level * Named {@link Logger}s can be obtained from this class
* These loggers have been configured to output messages to the console and a {@code .log} file by default, - * at the {@code INFO} level. A new {@code .log} file with a new numbering will be created after the log - * file reaches 5MB big, up to a maximum of 5 files.
+ * at the {@code INFO} level. A new {@code .log} file with a new numbering will be created after the log + * file reaches 5MB big, up to a maximum of 5 files.
*/ public class LogsCenter { + private static final int MAX_FILE_COUNT = 5; private static final int MAX_FILE_SIZE_IN_BYTES = (int) (Math.pow(2, 20) * 5); // 5MB private static final String LOG_FILE = "addressbook.log"; @@ -75,7 +76,7 @@ private static void addConsoleHandler(Logger logger) { */ private static void removeHandlers(Logger logger) { Arrays.stream(logger.getHandlers()) - .forEach(logger::removeHandler); + .forEach(logger::removeHandler); } /** @@ -95,6 +96,7 @@ private static void addFileHandler(Logger logger) { /** * Creates a {@code FileHandler} for the log file. + * * @throws IOException if there are problems opening the file. */ private static FileHandler createFileHandler() throws IOException { diff --git a/src/main/java/seedu/address/commons/core/Messages.java b/src/main/java/seedu/address/commons/core/Messages.java index 1deb3a1e469..10df391f77c 100644 --- a/src/main/java/seedu/address/commons/core/Messages.java +++ b/src/main/java/seedu/address/commons/core/Messages.java @@ -7,7 +7,7 @@ public class Messages { public static final String MESSAGE_UNKNOWN_COMMAND = "Unknown command"; public static final String MESSAGE_INVALID_COMMAND_FORMAT = "Invalid command format! \n%1$s"; - public static final String MESSAGE_INVALID_PERSON_DISPLAYED_INDEX = "The person index provided is invalid"; - public static final String MESSAGE_PERSONS_LISTED_OVERVIEW = "%1$d persons listed!"; + public static final String MESSAGE_INVALID_EXPENSE_DISPLAYED_INDEX = "The expense index provided is invalid"; + public static final String MESSAGE_EXPENSES_LISTED_OVERVIEW = "%1$d expenses listed!"; } diff --git a/src/main/java/seedu/address/commons/core/Version.java b/src/main/java/seedu/address/commons/core/Version.java index e117f91b3b2..f5573d1b7a0 100644 --- a/src/main/java/seedu/address/commons/core/Version.java +++ b/src/main/java/seedu/address/commons/core/Version.java @@ -47,6 +47,7 @@ public boolean isEarlyAccess() { /** * Parses a version number string in the format V1.2.3. + * * @param versionString version number string * @return a Version object */ @@ -59,9 +60,9 @@ public static Version fromString(String versionString) throws IllegalArgumentExc } return new Version(Integer.parseInt(versionMatcher.group(1)), - Integer.parseInt(versionMatcher.group(2)), - Integer.parseInt(versionMatcher.group(3)), - versionMatcher.group(4) == null ? false : true); + Integer.parseInt(versionMatcher.group(2)), + Integer.parseInt(versionMatcher.group(3)), + versionMatcher.group(4) == null ? false : true); } @JsonValue diff --git a/src/main/java/seedu/address/commons/exceptions/DataConversionException.java b/src/main/java/seedu/address/commons/exceptions/DataConversionException.java index 1f689bd8e3f..eba57b3b4d4 100644 --- a/src/main/java/seedu/address/commons/exceptions/DataConversionException.java +++ b/src/main/java/seedu/address/commons/exceptions/DataConversionException.java @@ -4,8 +4,8 @@ * Represents an error during conversion of data from one format to another */ public class DataConversionException extends Exception { + public DataConversionException(Exception cause) { super(cause); } - } diff --git a/src/main/java/seedu/address/commons/exceptions/IllegalValueException.java b/src/main/java/seedu/address/commons/exceptions/IllegalValueException.java index 19124db485c..55d1fa4b8f5 100644 --- a/src/main/java/seedu/address/commons/exceptions/IllegalValueException.java +++ b/src/main/java/seedu/address/commons/exceptions/IllegalValueException.java @@ -4,6 +4,7 @@ * Signals that some given data does not fulfill some constraints. */ public class IllegalValueException extends Exception { + /** * @param message should contain relevant information on the failed constraint(s) */ @@ -13,7 +14,7 @@ public IllegalValueException(String message) { /** * @param message should contain relevant information on the failed constraint(s) - * @param cause of the main exception + * @param cause of the main exception */ public IllegalValueException(String message, Throwable cause) { super(message, cause); diff --git a/src/main/java/seedu/address/commons/util/CollectionUtil.java b/src/main/java/seedu/address/commons/util/CollectionUtil.java index eafe4dfd681..942edda97d7 100644 --- a/src/main/java/seedu/address/commons/util/CollectionUtil.java +++ b/src/main/java/seedu/address/commons/util/CollectionUtil.java @@ -12,7 +12,9 @@ */ public class CollectionUtil { - /** @see #requireAllNonNull(Collection) */ + /** + * @see #requireAllNonNull(Collection) + */ public static void requireAllNonNull(Object... items) { requireNonNull(items); Stream.of(items).forEach(Objects::requireNonNull); diff --git a/src/main/java/seedu/address/commons/util/ConfigUtil.java b/src/main/java/seedu/address/commons/util/ConfigUtil.java index f7f8a2bd44c..d6f31acab79 100644 --- a/src/main/java/seedu/address/commons/util/ConfigUtil.java +++ b/src/main/java/seedu/address/commons/util/ConfigUtil.java @@ -19,5 +19,4 @@ public static Optional readConfig(Path configFilePath) throws DataConver public static void saveConfig(Config config, Path configFilePath) throws IOException { JsonUtil.saveJsonFile(config, configFilePath); } - } diff --git a/src/main/java/seedu/address/commons/util/FileUtil.java b/src/main/java/seedu/address/commons/util/FileUtil.java index b1e2767cdd9..2278d859f39 100644 --- a/src/main/java/seedu/address/commons/util/FileUtil.java +++ b/src/main/java/seedu/address/commons/util/FileUtil.java @@ -20,6 +20,7 @@ public static boolean isFileExists(Path file) { /** * Returns true if {@code path} can be converted into a {@code Path} via {@link Paths#get(String)}, * otherwise returns false. + * * @param path A string representing the file path. Cannot be null. */ public static boolean isValidPath(String path) { @@ -33,6 +34,7 @@ public static boolean isValidPath(String path) { /** * Creates a file if it does not exist along with its missing parent directories. + * * @throws IOException if the file or directory cannot be created. */ public static void createIfMissing(Path file) throws IOException { @@ -79,5 +81,4 @@ public static String readFromFile(Path file) throws IOException { public static void writeToFile(Path file, String content) throws IOException { Files.write(file, content.getBytes(CHARSET)); } - } diff --git a/src/main/java/seedu/address/commons/util/JsonUtil.java b/src/main/java/seedu/address/commons/util/JsonUtil.java index 8ef609f055d..d3e9b7f15e9 100644 --- a/src/main/java/seedu/address/commons/util/JsonUtil.java +++ b/src/main/java/seedu/address/commons/util/JsonUtil.java @@ -31,32 +31,33 @@ public class JsonUtil { private static final Logger logger = LogsCenter.getLogger(JsonUtil.class); private static ObjectMapper objectMapper = new ObjectMapper().findAndRegisterModules() - .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false) - .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) - .setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE) - .setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY) - .registerModule(new SimpleModule("SimpleModule") - .addSerializer(Level.class, new ToStringSerializer()) - .addDeserializer(Level.class, new LevelDeserializer(Level.class))); + .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false) + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE) + .setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY) + .registerModule(new SimpleModule("SimpleModule") + .addSerializer(Level.class, new ToStringSerializer()) + .addDeserializer(Level.class, new LevelDeserializer(Level.class))); static void serializeObjectToJsonFile(Path jsonFile, T objectToSerialize) throws IOException { FileUtil.writeToFile(jsonFile, toJsonString(objectToSerialize)); } static T deserializeObjectFromJsonFile(Path jsonFile, Class classOfObjectToDeserialize) - throws IOException { + throws IOException { return fromJsonString(FileUtil.readFromFile(jsonFile), classOfObjectToDeserialize); } /** * Returns the Json object from the given file or {@code Optional.empty()} object if the file is not found. * If any values are missing from the file, default values will be used, as long as the file is a valid json file. - * @param filePath cannot be null. + * + * @param filePath cannot be null. * @param classOfObjectToDeserialize Json file has to correspond to the structure in the class given here. * @throws DataConversionException if the file format is not as expected. */ public static Optional readJsonFile( - Path filePath, Class classOfObjectToDeserialize) throws DataConversionException { + Path filePath, Class classOfObjectToDeserialize) throws DataConversionException { requireNonNull(filePath); if (!Files.exists(filePath)) { @@ -79,6 +80,7 @@ public static Optional readJsonFile( /** * Saves the Json object to the specified file. * Overwrites existing file if it exists, creates a new file if it doesn't. + * * @param jsonFile cannot be null * @param filePath cannot be null * @throws IOException if there was an error during writing to the file @@ -90,9 +92,9 @@ public static void saveJsonFile(T jsonFile, Path filePath) throws IOExceptio serializeObjectToJsonFile(filePath, jsonFile); } - /** * Converts a given string representation of a JSON data to instance of a class + * * @param The generic type to create an instance of * @return The instance of T with the specified values in the JSON string */ @@ -102,8 +104,9 @@ public static T fromJsonString(String json, Class instanceClass) throws I /** * Converts a given instance of a class into its JSON data string representation + * * @param instance The T object to be converted into the JSON string - * @param The generic type to create an instance of + * @param The generic type to create an instance of * @return JSON data representation of the given class instance, in string */ public static String toJsonString(T instance) throws JsonProcessingException { @@ -128,7 +131,6 @@ protected Level _deserialize(String value, DeserializationContext ctxt) { * Gets the logging level that matches loggingLevelString *

* Returns null if there are no matches - * */ private Level getLoggingLevel(String loggingLevelString) { return Level.parse(loggingLevelString); @@ -139,5 +141,4 @@ public Class handledType() { return Level.class; } } - } diff --git a/src/main/java/seedu/address/commons/util/StringUtil.java b/src/main/java/seedu/address/commons/util/StringUtil.java index 61cc8c9a1cb..df320512db1 100644 --- a/src/main/java/seedu/address/commons/util/StringUtil.java +++ b/src/main/java/seedu/address/commons/util/StringUtil.java @@ -14,14 +14,15 @@ public class StringUtil { /** * Returns true if the {@code sentence} contains the {@code word}. - * Ignores case, but a full word match is required. - *
examples:

+     * Ignores case, but a full word match is required.
+     * 
examples:
      *       containsWordIgnoreCase("ABc def", "abc") == true
      *       containsWordIgnoreCase("ABc def", "DEF") == true
      *       containsWordIgnoreCase("ABc def", "AB") == false //not a full word match
      *       
+ * * @param sentence cannot be null - * @param word cannot be null, cannot be empty, must be a single word + * @param word cannot be null, cannot be empty, must be a single word */ public static boolean containsWordIgnoreCase(String sentence, String word) { requireNonNull(sentence); @@ -35,7 +36,7 @@ public static boolean containsWordIgnoreCase(String sentence, String word) { String[] wordsInPreppedSentence = preppedSentence.split("\\s+"); return Arrays.stream(wordsInPreppedSentence) - .anyMatch(preppedWord::equalsIgnoreCase); + .anyMatch(preppedWord::equalsIgnoreCase); } /** @@ -53,6 +54,7 @@ public static String getDetails(Throwable t) { * e.g. 1, 2, 3, ..., {@code Integer.MAX_VALUE}
* Will return false for any other non-null string input * e.g. empty string, "-1", "0", "+1", and " 2 " (untrimmed), "3 0" (contains whitespace), "1 a" (contains letters) + * * @throws NullPointerException if {@code s} is null. */ public static boolean isNonZeroUnsignedInteger(String s) { diff --git a/src/main/java/seedu/address/logic/Logic.java b/src/main/java/seedu/address/logic/Logic.java index 92cd8fa605a..12a9dbae271 100644 --- a/src/main/java/seedu/address/logic/Logic.java +++ b/src/main/java/seedu/address/logic/Logic.java @@ -7,36 +7,41 @@ import seedu.address.logic.commands.CommandResult; 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.model.Model; +import seedu.address.model.ReadOnlyExpenseList; +import seedu.address.model.expense.Expense; /** * API of the Logic component */ public interface Logic { + /** * Executes the command and returns the result. + * * @param commandText The command as entered by the user. * @return the result of the command execution. * @throws CommandException If an error occurs during command execution. - * @throws ParseException If an error occurs during parsing. + * @throws ParseException If an error occurs during parsing. */ CommandResult execute(String commandText) throws CommandException, ParseException; /** - * Returns the AddressBook. + * Returns the ExpenseList. * - * @see seedu.address.model.Model#getAddressBook() + * @see Model#getExpenseList() */ - ReadOnlyAddressBook getAddressBook(); + ReadOnlyExpenseList getExpenseList(); - /** Returns an unmodifiable view of the filtered list of persons */ - ObservableList getFilteredPersonList(); + /** + * Returns an unmodifiable view of the filtered list of expenses + */ + ObservableList getFilteredExpenseList(); /** - * Returns the user prefs' address book file path. + * Returns the user prefs' expense list file path. */ - Path getAddressBookFilePath(); + Path getExpenseListFilePath(); /** * Returns the user prefs' GUI settings. diff --git a/src/main/java/seedu/address/logic/LogicManager.java b/src/main/java/seedu/address/logic/LogicManager.java index d47ce874b1a..23a371b477b 100644 --- a/src/main/java/seedu/address/logic/LogicManager.java +++ b/src/main/java/seedu/address/logic/LogicManager.java @@ -10,28 +10,29 @@ import seedu.address.logic.commands.Command; import seedu.address.logic.commands.CommandResult; import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.logic.parser.AddressBookParser; +import seedu.address.logic.parser.MymParser; 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.model.ReadOnlyExpenseList; +import seedu.address.model.expense.Expense; import seedu.address.storage.Storage; /** * The main LogicManager of the app. */ public class LogicManager implements Logic { + public static final String FILE_OPS_ERROR_MESSAGE = "Could not save data to file: "; private final Logger logger = LogsCenter.getLogger(LogicManager.class); private final Model model; private final Storage storage; - private final AddressBookParser addressBookParser; + private final MymParser mymParser; public LogicManager(Model model, Storage storage) { this.model = model; this.storage = storage; - addressBookParser = new AddressBookParser(); + mymParser = new MymParser(); } @Override @@ -39,11 +40,11 @@ public CommandResult execute(String commandText) throws CommandException, ParseE logger.info("----------------[USER COMMAND][" + commandText + "]"); CommandResult commandResult; - Command command = addressBookParser.parseCommand(commandText); + Command command = mymParser.parseCommand(commandText); commandResult = command.execute(model); try { - storage.saveAddressBook(model.getAddressBook()); + storage.saveExpenseList(model.getExpenseList()); } catch (IOException ioe) { throw new CommandException(FILE_OPS_ERROR_MESSAGE + ioe, ioe); } @@ -52,18 +53,18 @@ public CommandResult execute(String commandText) throws CommandException, ParseE } @Override - public ReadOnlyAddressBook getAddressBook() { - return model.getAddressBook(); + public ReadOnlyExpenseList getExpenseList() { + return model.getExpenseList(); } @Override - public ObservableList getFilteredPersonList() { - return model.getFilteredPersonList(); + public ObservableList getFilteredExpenseList() { + return model.getFilteredExpenseList(); } @Override - public Path getAddressBookFilePath() { - return model.getAddressBookFilePath(); + public Path getExpenseListFilePath() { + return model.getExpenseListFilePath(); } @Override diff --git a/src/main/java/seedu/address/logic/commands/AddCommand.java b/src/main/java/seedu/address/logic/commands/AddCommand.java index 71656d7c5c8..6cbf811f524 100644 --- a/src/main/java/seedu/address/logic/commands/AddCommand.java +++ b/src/main/java/seedu/address/logic/commands/AddCommand.java @@ -1,60 +1,57 @@ package seedu.address.logic.commands; import static java.util.Objects.requireNonNull; -import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS; -import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL; +import static seedu.address.logic.parser.CliSyntax.PREFIX_AMOUNT; +import static seedu.address.logic.parser.CliSyntax.PREFIX_DATE; import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; -import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.model.Model; -import seedu.address.model.person.Person; +import seedu.address.model.expense.Expense; /** - * Adds a person to the address book. + * Adds an expense to the expense list. */ public class AddCommand extends Command { public static final String COMMAND_WORD = "add"; - public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a person to the address book. " + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds an expense to the expense list. " + "Parameters: " + PREFIX_NAME + "NAME " - + PREFIX_PHONE + "PHONE " - + PREFIX_EMAIL + "EMAIL " - + PREFIX_ADDRESS + "ADDRESS " + + PREFIX_AMOUNT + "AMOUNT " + + PREFIX_DATE + "DATE " + "[" + PREFIX_TAG + "TAG]...\n" + "Example: " + COMMAND_WORD + " " - + PREFIX_NAME + "John Doe " - + PREFIX_PHONE + "98765432 " - + PREFIX_EMAIL + "johnd@example.com " - + PREFIX_ADDRESS + "311, Clementi Ave 2, #02-25 " - + PREFIX_TAG + "friends " - + PREFIX_TAG + "owesMoney"; + + PREFIX_NAME + "Textbook " + + PREFIX_AMOUNT + "$23.50 " + + PREFIX_DATE + "1245 " + + PREFIX_TAG + "education " + + PREFIX_TAG + "school"; - public static final String MESSAGE_SUCCESS = "New person added: %1$s"; - public static final String MESSAGE_DUPLICATE_PERSON = "This person already exists in the address book"; + public static final String MESSAGE_SUCCESS = "New expense added: %1$s"; + public static final String MESSAGE_DUPLICATE_EXPENSE = "This expense already exists in the expense list"; - private final Person toAdd; + private final Expense toAdd; /** - * Creates an AddCommand to add the specified {@code Person} + * Creates an AddCommand to add the specified {@code Expense} */ - public AddCommand(Person person) { - requireNonNull(person); - toAdd = person; + public AddCommand(Expense expense) { + requireNonNull(expense); + toAdd = expense; } @Override public CommandResult execute(Model model) throws CommandException { requireNonNull(model); - if (model.hasPerson(toAdd)) { - throw new CommandException(MESSAGE_DUPLICATE_PERSON); + if (model.hasExpense(toAdd)) { + throw new CommandException(MESSAGE_DUPLICATE_EXPENSE); } - model.addPerson(toAdd); + model.addExpense(toAdd); return new CommandResult(String.format(MESSAGE_SUCCESS, toAdd)); } diff --git a/src/main/java/seedu/address/logic/commands/ClearCommand.java b/src/main/java/seedu/address/logic/commands/ClearCommand.java index 9c86b1fa6e4..d1b09b84b6e 100644 --- a/src/main/java/seedu/address/logic/commands/ClearCommand.java +++ b/src/main/java/seedu/address/logic/commands/ClearCommand.java @@ -2,7 +2,7 @@ import static java.util.Objects.requireNonNull; -import seedu.address.model.AddressBook; +import seedu.address.model.ExpenseList; import seedu.address.model.Model; /** @@ -11,13 +11,13 @@ public class ClearCommand extends Command { public static final String COMMAND_WORD = "clear"; - public static final String MESSAGE_SUCCESS = "Address book has been cleared!"; + public static final String MESSAGE_SUCCESS = "Expense list has been cleared!"; @Override public CommandResult execute(Model model) { requireNonNull(model); - model.setAddressBook(new AddressBook()); + model.setExpenseList(new ExpenseList()); return new CommandResult(MESSAGE_SUCCESS); } } diff --git a/src/main/java/seedu/address/logic/commands/Command.java b/src/main/java/seedu/address/logic/commands/Command.java index 64f18992160..4fbfb0a6458 100644 --- a/src/main/java/seedu/address/logic/commands/Command.java +++ b/src/main/java/seedu/address/logic/commands/Command.java @@ -16,5 +16,4 @@ public abstract class Command { * @throws CommandException If an error occurs during command execution. */ public abstract CommandResult execute(Model model) throws CommandException; - } diff --git a/src/main/java/seedu/address/logic/commands/CommandResult.java b/src/main/java/seedu/address/logic/commands/CommandResult.java index 92f900b7916..14eeea2245f 100644 --- a/src/main/java/seedu/address/logic/commands/CommandResult.java +++ b/src/main/java/seedu/address/logic/commands/CommandResult.java @@ -11,10 +11,14 @@ public class CommandResult { private final String feedbackToUser; - /** Help information should be shown to the user. */ + /** + * Help information should be shown to the user. + */ private final boolean showHelp; - /** The application should exit. */ + /** + * The application should exit. + */ private final boolean exit; /** @@ -59,13 +63,12 @@ public boolean equals(Object other) { CommandResult otherCommandResult = (CommandResult) other; return feedbackToUser.equals(otherCommandResult.feedbackToUser) - && showHelp == otherCommandResult.showHelp - && exit == otherCommandResult.exit; + && showHelp == otherCommandResult.showHelp + && exit == otherCommandResult.exit; } @Override public int hashCode() { return Objects.hash(feedbackToUser, showHelp, exit); } - } diff --git a/src/main/java/seedu/address/logic/commands/DeleteCommand.java b/src/main/java/seedu/address/logic/commands/DeleteCommand.java index 02fd256acba..4782f4143c8 100644 --- a/src/main/java/seedu/address/logic/commands/DeleteCommand.java +++ b/src/main/java/seedu/address/logic/commands/DeleteCommand.java @@ -8,21 +8,21 @@ import seedu.address.commons.core.index.Index; import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.model.Model; -import seedu.address.model.person.Person; +import seedu.address.model.expense.Expense; /** - * Deletes a person identified using it's displayed index from the address book. + * Deletes an expense identified using it's displayed index from the expense list. */ public class DeleteCommand extends Command { public static final String COMMAND_WORD = "delete"; public static final String MESSAGE_USAGE = COMMAND_WORD - + ": Deletes the person identified by the index number used in the displayed person list.\n" - + "Parameters: INDEX (must be a positive integer)\n" - + "Example: " + COMMAND_WORD + " 1"; + + ": Deletes the expense identified by the index number used in the displayed expense list.\n" + + "Parameters: INDEX (must be a positive integer)\n" + + "Example: " + COMMAND_WORD + " 1"; - public static final String MESSAGE_DELETE_PERSON_SUCCESS = "Deleted Person: %1$s"; + public static final String MESSAGE_DELETE_EXPENSE_SUCCESS = "Deleted Expense: %1$s"; private final Index targetIndex; @@ -33,21 +33,21 @@ public DeleteCommand(Index targetIndex) { @Override public CommandResult execute(Model model) throws CommandException { requireNonNull(model); - List lastShownList = model.getFilteredPersonList(); + List lastShownList = model.getFilteredExpenseList(); if (targetIndex.getZeroBased() >= lastShownList.size()) { - throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); + throw new CommandException(Messages.MESSAGE_INVALID_EXPENSE_DISPLAYED_INDEX); } - Person personToDelete = lastShownList.get(targetIndex.getZeroBased()); - model.deletePerson(personToDelete); - return new CommandResult(String.format(MESSAGE_DELETE_PERSON_SUCCESS, personToDelete)); + Expense expenseToDelete = lastShownList.get(targetIndex.getZeroBased()); + model.deleteExpense(expenseToDelete); + return new CommandResult(String.format(MESSAGE_DELETE_EXPENSE_SUCCESS, expenseToDelete)); } @Override public boolean equals(Object other) { return other == this // short circuit if same object - || (other instanceof DeleteCommand // instanceof handles nulls - && targetIndex.equals(((DeleteCommand) other).targetIndex)); // state check + || (other instanceof DeleteCommand // instanceof handles nulls + && targetIndex.equals(((DeleteCommand) other).targetIndex)); // state check } } diff --git a/src/main/java/seedu/address/logic/commands/EditCommand.java b/src/main/java/seedu/address/logic/commands/EditCommand.java index 7e36114902f..7cabfed025a 100644 --- a/src/main/java/seedu/address/logic/commands/EditCommand.java +++ b/src/main/java/seedu/address/logic/commands/EditCommand.java @@ -1,12 +1,11 @@ package seedu.address.logic.commands; import static java.util.Objects.requireNonNull; -import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS; -import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL; +import static seedu.address.logic.parser.CliSyntax.PREFIX_AMOUNT; +import static seedu.address.logic.parser.CliSyntax.PREFIX_DATE; import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; -import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; -import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS; +import static seedu.address.model.Model.PREDICATE_SHOW_ALL_EXPENSES; import java.util.Collections; import java.util.HashSet; @@ -19,87 +18,84 @@ import seedu.address.commons.util.CollectionUtil; import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.model.Model; -import seedu.address.model.person.Address; -import seedu.address.model.person.Email; -import seedu.address.model.person.Name; -import seedu.address.model.person.Person; -import seedu.address.model.person.Phone; +import seedu.address.model.expense.Amount; +import seedu.address.model.expense.Date; +import seedu.address.model.expense.Expense; +import seedu.address.model.expense.Name; import seedu.address.model.tag.Tag; /** - * Edits the details of an existing person in the address book. + * Edits the details of an existing expense in the expense list. */ public class EditCommand extends Command { public static final String COMMAND_WORD = "edit"; - public static final String MESSAGE_USAGE = COMMAND_WORD + ": Edits the details of the person identified " - + "by the index number used in the displayed person list. " - + "Existing values will be overwritten by the input values.\n" - + "Parameters: INDEX (must be a positive integer) " - + "[" + PREFIX_NAME + "NAME] " - + "[" + PREFIX_PHONE + "PHONE] " - + "[" + PREFIX_EMAIL + "EMAIL] " - + "[" + PREFIX_ADDRESS + "ADDRESS] " - + "[" + PREFIX_TAG + "TAG]...\n" - + "Example: " + COMMAND_WORD + " 1 " - + PREFIX_PHONE + "91234567 " - + PREFIX_EMAIL + "johndoe@example.com"; - - public static final String MESSAGE_EDIT_PERSON_SUCCESS = "Edited Person: %1$s"; + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Edits the details of the expense identified " + + "by the index number used in the displayed expense list. " + + "Existing values will be overwritten by the input values.\n" + + "Parameters: INDEX (must be a positive integer) " + + "[" + PREFIX_NAME + "NAME] " + + "[" + PREFIX_AMOUNT + "AMOUNT] " + + "[" + PREFIX_DATE + "DATE] " + + "[" + PREFIX_TAG + "TAG]...\n" + + "Example: " + COMMAND_WORD + " 1 " + + PREFIX_AMOUNT + "$23.50 " + + PREFIX_DATE + "1245"; + + public static final String MESSAGE_EDIT_EXPENSE_SUCCESS = "Edited Expense: %1$s"; public static final String MESSAGE_NOT_EDITED = "At least one field to edit must be provided."; - public static final String MESSAGE_DUPLICATE_PERSON = "This person already exists in the address book."; + public static final String MESSAGE_DUPLICATE_EXPENSE = "This expense already exists in the expense list."; private final Index index; - private final EditPersonDescriptor editPersonDescriptor; + private final EditExpenseDescriptor editExpenseDescriptor; /** - * @param index of the person in the filtered person list to edit - * @param editPersonDescriptor details to edit the person with + * @param index of the expense in the filtered expense list to edit + * @param editExpenseDescriptor details to edit the expense with */ - public EditCommand(Index index, EditPersonDescriptor editPersonDescriptor) { + public EditCommand(Index index, EditExpenseDescriptor editExpenseDescriptor) { requireNonNull(index); - requireNonNull(editPersonDescriptor); + requireNonNull(editExpenseDescriptor); this.index = index; - this.editPersonDescriptor = new EditPersonDescriptor(editPersonDescriptor); + this.editExpenseDescriptor = new EditExpenseDescriptor(editExpenseDescriptor); } @Override public CommandResult execute(Model model) throws CommandException { requireNonNull(model); - List lastShownList = model.getFilteredPersonList(); + List lastShownList = model.getFilteredExpenseList(); if (index.getZeroBased() >= lastShownList.size()) { - throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); + throw new CommandException(Messages.MESSAGE_INVALID_EXPENSE_DISPLAYED_INDEX); } - Person personToEdit = lastShownList.get(index.getZeroBased()); - Person editedPerson = createEditedPerson(personToEdit, editPersonDescriptor); + Expense expenseToEdit = lastShownList.get(index.getZeroBased()); + Expense editedExpense = createEditedExpense(expenseToEdit, editExpenseDescriptor); - if (!personToEdit.isSamePerson(editedPerson) && model.hasPerson(editedPerson)) { - throw new CommandException(MESSAGE_DUPLICATE_PERSON); + if (!expenseToEdit.isSameExpense(editedExpense) && model.hasExpense(editedExpense)) { + throw new CommandException(MESSAGE_DUPLICATE_EXPENSE); } - model.setPerson(personToEdit, editedPerson); - model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); - return new CommandResult(String.format(MESSAGE_EDIT_PERSON_SUCCESS, editedPerson)); + model.setExpense(expenseToEdit, editedExpense); + model.updateFilteredExpenseList(PREDICATE_SHOW_ALL_EXPENSES); + return new CommandResult(String.format(MESSAGE_EDIT_EXPENSE_SUCCESS, editedExpense)); } /** - * Creates and returns a {@code Person} with the details of {@code personToEdit} - * edited with {@code editPersonDescriptor}. + * Creates and returns a {@code Expense} with the details of {@code expenseToEdit} + * edited with {@code editExpenseDescriptor}. */ - private static Person createEditedPerson(Person personToEdit, EditPersonDescriptor editPersonDescriptor) { - assert personToEdit != null; + private static Expense createEditedExpense(Expense expenseToEdit, EditExpenseDescriptor editExpenseDescriptor) { + assert expenseToEdit != null; - Name updatedName = editPersonDescriptor.getName().orElse(personToEdit.getName()); - Phone updatedPhone = editPersonDescriptor.getPhone().orElse(personToEdit.getPhone()); - Email updatedEmail = editPersonDescriptor.getEmail().orElse(personToEdit.getEmail()); - Address updatedAddress = editPersonDescriptor.getAddress().orElse(personToEdit.getAddress()); - Set updatedTags = editPersonDescriptor.getTags().orElse(personToEdit.getTags()); + Name updatedName = editExpenseDescriptor.getName().orElse(expenseToEdit.getName()); + Amount updatedAmount = editExpenseDescriptor.getAmount().orElse(expenseToEdit.getAmount()); + Date updatedDate = editExpenseDescriptor.getDate().orElse(expenseToEdit.getDate()); + Set updatedTags = editExpenseDescriptor.getTags().orElse(expenseToEdit.getTags()); - return new Person(updatedName, updatedPhone, updatedEmail, updatedAddress, updatedTags); + return new Expense(updatedName, updatedAmount, updatedDate, updatedTags); } @Override @@ -117,31 +113,31 @@ public boolean equals(Object other) { // state check EditCommand e = (EditCommand) other; return index.equals(e.index) - && editPersonDescriptor.equals(e.editPersonDescriptor); + && editExpenseDescriptor.equals(e.editExpenseDescriptor); } /** - * Stores the details to edit the person with. Each non-empty field value will replace the - * corresponding field value of the person. + * Stores the details to edit the expense with. Each non-empty field value will replace the + * corresponding field value of the expense. */ - public static class EditPersonDescriptor { + public static class EditExpenseDescriptor { + private Name name; - private Phone phone; - private Email email; - private Address address; + private Amount amount; + private Date date; private Set tags; - public EditPersonDescriptor() {} + public EditExpenseDescriptor() { + } /** * Copy constructor. * A defensive copy of {@code tags} is used internally. */ - public EditPersonDescriptor(EditPersonDescriptor toCopy) { + public EditExpenseDescriptor(EditExpenseDescriptor toCopy) { setName(toCopy.name); - setPhone(toCopy.phone); - setEmail(toCopy.email); - setAddress(toCopy.address); + setAmount(toCopy.amount); + setDate(toCopy.date); setTags(toCopy.tags); } @@ -149,7 +145,7 @@ public EditPersonDescriptor(EditPersonDescriptor toCopy) { * Returns true if at least one field is edited. */ public boolean isAnyFieldEdited() { - return CollectionUtil.isAnyNonNull(name, phone, email, address, tags); + return CollectionUtil.isAnyNonNull(name, amount, date, tags); } public void setName(Name name) { @@ -160,28 +156,20 @@ public Optional getName() { return Optional.ofNullable(name); } - public void setPhone(Phone phone) { - this.phone = phone; - } - - public Optional getPhone() { - return Optional.ofNullable(phone); - } - - public void setEmail(Email email) { - this.email = email; + public void setAmount(Amount amount) { + this.amount = amount; } - public Optional getEmail() { - return Optional.ofNullable(email); + public Optional getAmount() { + return Optional.ofNullable(amount); } - public void setAddress(Address address) { - this.address = address; + public void setDate(Date date) { + this.date = date; } - public Optional
getAddress() { - return Optional.ofNullable(address); + public Optional getDate() { + return Optional.ofNullable(date); } /** @@ -209,18 +197,17 @@ public boolean equals(Object other) { } // instanceof handles nulls - if (!(other instanceof EditPersonDescriptor)) { + if (!(other instanceof EditExpenseDescriptor)) { return false; } // state check - EditPersonDescriptor e = (EditPersonDescriptor) other; + EditExpenseDescriptor e = (EditExpenseDescriptor) other; return getName().equals(e.getName()) - && getPhone().equals(e.getPhone()) - && getEmail().equals(e.getEmail()) - && getAddress().equals(e.getAddress()) - && getTags().equals(e.getTags()); + && getAmount().equals(e.getAmount()) + && getDate().equals(e.getDate()) + && getTags().equals(e.getTags()); } } } diff --git a/src/main/java/seedu/address/logic/commands/ExitCommand.java b/src/main/java/seedu/address/logic/commands/ExitCommand.java index 3dd85a8ba90..a02e887fd04 100644 --- a/src/main/java/seedu/address/logic/commands/ExitCommand.java +++ b/src/main/java/seedu/address/logic/commands/ExitCommand.java @@ -9,7 +9,7 @@ public class ExitCommand extends Command { public static final String COMMAND_WORD = "exit"; - public static final String MESSAGE_EXIT_ACKNOWLEDGEMENT = "Exiting Address Book as requested ..."; + public static final String MESSAGE_EXIT_ACKNOWLEDGEMENT = "Exiting MYMorise as requested ..."; @Override public CommandResult execute(Model model) { diff --git a/src/main/java/seedu/address/logic/commands/FindCommand.java b/src/main/java/seedu/address/logic/commands/FindCommand.java index d6b19b0a0de..7905b90f049 100644 --- a/src/main/java/seedu/address/logic/commands/FindCommand.java +++ b/src/main/java/seedu/address/logic/commands/FindCommand.java @@ -4,20 +4,20 @@ import seedu.address.commons.core.Messages; import seedu.address.model.Model; -import seedu.address.model.person.NameContainsKeywordsPredicate; +import seedu.address.model.expense.NameContainsKeywordsPredicate; /** - * Finds and lists all persons in address book whose name contains any of the argument keywords. + * Finds and lists all expenses in expense list whose name contains any of the argument keywords. * Keyword matching is case insensitive. */ public class FindCommand extends Command { public static final String COMMAND_WORD = "find"; - public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all persons whose names contain any of " + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all expenses whose names contain any of " + "the specified keywords (case-insensitive) and displays them as a list with index numbers.\n" + "Parameters: KEYWORD [MORE_KEYWORDS]...\n" - + "Example: " + COMMAND_WORD + " alice bob charlie"; + + "Example: " + COMMAND_WORD + " coffee"; private final NameContainsKeywordsPredicate predicate; @@ -28,9 +28,9 @@ public FindCommand(NameContainsKeywordsPredicate predicate) { @Override public CommandResult execute(Model model) { requireNonNull(model); - model.updateFilteredPersonList(predicate); + model.updateFilteredExpenseList(predicate); return new CommandResult( - String.format(Messages.MESSAGE_PERSONS_LISTED_OVERVIEW, model.getFilteredPersonList().size())); + String.format(Messages.MESSAGE_EXPENSES_LISTED_OVERVIEW, model.getFilteredExpenseList().size())); } @Override diff --git a/src/main/java/seedu/address/logic/commands/HelpCommand.java b/src/main/java/seedu/address/logic/commands/HelpCommand.java index bf824f91bd0..6120757b0c7 100644 --- a/src/main/java/seedu/address/logic/commands/HelpCommand.java +++ b/src/main/java/seedu/address/logic/commands/HelpCommand.java @@ -10,7 +10,7 @@ public class HelpCommand extends Command { public static final String COMMAND_WORD = "help"; public static final String MESSAGE_USAGE = COMMAND_WORD + ": Shows program usage instructions.\n" - + "Example: " + COMMAND_WORD; + + "Example: " + COMMAND_WORD; public static final String SHOWING_HELP_MESSAGE = "Opened help window."; diff --git a/src/main/java/seedu/address/logic/commands/ListCommand.java b/src/main/java/seedu/address/logic/commands/ListCommand.java index 84be6ad2596..ce08b42c2d0 100644 --- a/src/main/java/seedu/address/logic/commands/ListCommand.java +++ b/src/main/java/seedu/address/logic/commands/ListCommand.java @@ -1,24 +1,23 @@ package seedu.address.logic.commands; import static java.util.Objects.requireNonNull; -import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS; +import static seedu.address.model.Model.PREDICATE_SHOW_ALL_EXPENSES; import seedu.address.model.Model; /** - * Lists all persons in the address book to the user. + * Lists all expenses in the address book to the user. */ public class ListCommand extends Command { public static final String COMMAND_WORD = "list"; - public static final String MESSAGE_SUCCESS = "Listed all persons"; - + public static final String MESSAGE_SUCCESS = "Listed all expenses"; @Override public CommandResult execute(Model model) { requireNonNull(model); - model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); + model.updateFilteredExpenseList(PREDICATE_SHOW_ALL_EXPENSES); return new CommandResult(MESSAGE_SUCCESS); } } diff --git a/src/main/java/seedu/address/logic/commands/exceptions/CommandException.java b/src/main/java/seedu/address/logic/commands/exceptions/CommandException.java index a16bd14f2cd..f44c0c19186 100644 --- a/src/main/java/seedu/address/logic/commands/exceptions/CommandException.java +++ b/src/main/java/seedu/address/logic/commands/exceptions/CommandException.java @@ -1,5 +1,7 @@ package seedu.address.logic.commands.exceptions; +import seedu.address.logic.commands.Command; + /** * Represents an error which occurs during execution of a {@link Command}. */ diff --git a/src/main/java/seedu/address/logic/parser/AddCommandParser.java b/src/main/java/seedu/address/logic/parser/AddCommandParser.java index 3b8bfa035e8..a0a5107d019 100644 --- a/src/main/java/seedu/address/logic/parser/AddCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/AddCommandParser.java @@ -1,10 +1,9 @@ package seedu.address.logic.parser; import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; -import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS; -import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL; +import static seedu.address.logic.parser.CliSyntax.PREFIX_AMOUNT; +import static seedu.address.logic.parser.CliSyntax.PREFIX_DATE; import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; -import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; import java.util.Set; @@ -12,11 +11,10 @@ import seedu.address.logic.commands.AddCommand; import seedu.address.logic.parser.exceptions.ParseException; -import seedu.address.model.person.Address; -import seedu.address.model.person.Email; -import seedu.address.model.person.Name; -import seedu.address.model.person.Person; -import seedu.address.model.person.Phone; +import seedu.address.model.expense.Amount; +import seedu.address.model.expense.Date; +import seedu.address.model.expense.Expense; +import seedu.address.model.expense.Name; import seedu.address.model.tag.Tag; /** @@ -27,26 +25,26 @@ public class AddCommandParser implements Parser { /** * Parses the given {@code String} of arguments in the context of the AddCommand * and returns an AddCommand object for execution. + * * @throws ParseException if the user input does not conform the expected format */ public AddCommand parse(String args) throws ParseException { ArgumentMultimap argMultimap = - ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TAG); + ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_AMOUNT, PREFIX_DATE, PREFIX_TAG); - if (!arePrefixesPresent(argMultimap, PREFIX_NAME, PREFIX_ADDRESS, PREFIX_PHONE, PREFIX_EMAIL) - || !argMultimap.getPreamble().isEmpty()) { + if (!arePrefixesPresent(argMultimap, PREFIX_NAME, PREFIX_AMOUNT, PREFIX_DATE) + || !argMultimap.getPreamble().isEmpty()) { throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE)); } Name name = ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get()); - Phone phone = ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE).get()); - Email email = ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL).get()); - Address address = ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS).get()); + Amount amount = ParserUtil.parseAmount(argMultimap.getValue(PREFIX_AMOUNT).get()); + Date date = ParserUtil.parseDate(argMultimap.getValue(PREFIX_DATE).get()); Set tagList = ParserUtil.parseTags(argMultimap.getAllValues(PREFIX_TAG)); - Person person = new Person(name, phone, email, address, tagList); + Expense expense = new Expense(name, amount, date, tagList); - return new AddCommand(person); + return new AddCommand(expense); } /** @@ -56,5 +54,4 @@ public AddCommand parse(String args) throws ParseException { private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) { return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent()); } - } diff --git a/src/main/java/seedu/address/logic/parser/CliSyntax.java b/src/main/java/seedu/address/logic/parser/CliSyntax.java index 75b1a9bf119..a482b3533ef 100644 --- a/src/main/java/seedu/address/logic/parser/CliSyntax.java +++ b/src/main/java/seedu/address/logic/parser/CliSyntax.java @@ -7,9 +7,8 @@ public class CliSyntax { /* Prefix definitions */ public static final Prefix PREFIX_NAME = new Prefix("n/"); - public static final Prefix PREFIX_PHONE = new Prefix("p/"); - public static final Prefix PREFIX_EMAIL = new Prefix("e/"); - public static final Prefix PREFIX_ADDRESS = new Prefix("a/"); + public static final Prefix PREFIX_AMOUNT = new Prefix("a/"); + public static final Prefix PREFIX_DATE = new Prefix("d/"); public static final Prefix PREFIX_TAG = new Prefix("t/"); } diff --git a/src/main/java/seedu/address/logic/parser/EditCommandParser.java b/src/main/java/seedu/address/logic/parser/EditCommandParser.java index 845644b7dea..4e0f703f616 100644 --- a/src/main/java/seedu/address/logic/parser/EditCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/EditCommandParser.java @@ -2,10 +2,9 @@ import static java.util.Objects.requireNonNull; import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; -import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS; -import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL; +import static seedu.address.logic.parser.CliSyntax.PREFIX_AMOUNT; +import static seedu.address.logic.parser.CliSyntax.PREFIX_DATE; import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; -import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; import java.util.Collection; @@ -15,7 +14,7 @@ import seedu.address.commons.core.index.Index; import seedu.address.logic.commands.EditCommand; -import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; +import seedu.address.logic.commands.EditCommand.EditExpenseDescriptor; import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.tag.Tag; @@ -27,12 +26,13 @@ public class EditCommandParser implements Parser { /** * Parses the given {@code String} of arguments in the context of the EditCommand * and returns an EditCommand object for execution. + * * @throws ParseException if the user input does not conform the expected format */ public EditCommand parse(String args) throws ParseException { requireNonNull(args); ArgumentMultimap argMultimap = - ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TAG); + ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_AMOUNT, PREFIX_DATE, PREFIX_TAG); Index index; @@ -42,26 +42,24 @@ public EditCommand parse(String args) throws ParseException { throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE), pe); } - EditPersonDescriptor editPersonDescriptor = new EditPersonDescriptor(); + EditExpenseDescriptor editExpenseDescriptor = new EditExpenseDescriptor(); if (argMultimap.getValue(PREFIX_NAME).isPresent()) { - editPersonDescriptor.setName(ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get())); + editExpenseDescriptor.setName(ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get())); } - if (argMultimap.getValue(PREFIX_PHONE).isPresent()) { - editPersonDescriptor.setPhone(ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE).get())); + if (argMultimap.getValue(PREFIX_AMOUNT).isPresent()) { + editExpenseDescriptor.setAmount(ParserUtil.parseAmount(argMultimap.getValue(PREFIX_AMOUNT).get())); } - if (argMultimap.getValue(PREFIX_EMAIL).isPresent()) { - editPersonDescriptor.setEmail(ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL).get())); + if (argMultimap.getValue(PREFIX_DATE).isPresent()) { + editExpenseDescriptor.setDate(ParserUtil.parseDate(argMultimap.getValue(PREFIX_DATE).get())); } - if (argMultimap.getValue(PREFIX_ADDRESS).isPresent()) { - editPersonDescriptor.setAddress(ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS).get())); - } - parseTagsForEdit(argMultimap.getAllValues(PREFIX_TAG)).ifPresent(editPersonDescriptor::setTags); - if (!editPersonDescriptor.isAnyFieldEdited()) { + parseTagsForEdit(argMultimap.getAllValues(PREFIX_TAG)).ifPresent(editExpenseDescriptor::setTags); + + if (!editExpenseDescriptor.isAnyFieldEdited()) { throw new ParseException(EditCommand.MESSAGE_NOT_EDITED); } - return new EditCommand(index, editPersonDescriptor); + return new EditCommand(index, editExpenseDescriptor); } /** @@ -78,5 +76,4 @@ private Optional> parseTagsForEdit(Collection tags) throws Pars Collection tagSet = tags.size() == 1 && tags.contains("") ? Collections.emptySet() : tags; return Optional.of(ParserUtil.parseTags(tagSet)); } - } diff --git a/src/main/java/seedu/address/logic/parser/FindCommandParser.java b/src/main/java/seedu/address/logic/parser/FindCommandParser.java index 4fb71f23103..06befff9d69 100644 --- a/src/main/java/seedu/address/logic/parser/FindCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/FindCommandParser.java @@ -6,7 +6,7 @@ import seedu.address.logic.commands.FindCommand; import seedu.address.logic.parser.exceptions.ParseException; -import seedu.address.model.person.NameContainsKeywordsPredicate; +import seedu.address.model.expense.NameContainsKeywordsPredicate; /** * Parses input arguments and creates a new FindCommand object diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/MymParser.java similarity index 98% rename from src/main/java/seedu/address/logic/parser/AddressBookParser.java rename to src/main/java/seedu/address/logic/parser/MymParser.java index 1e466792b46..5d2a74d9051 100644 --- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java +++ b/src/main/java/seedu/address/logic/parser/MymParser.java @@ -20,7 +20,7 @@ /** * Parses user input. */ -public class AddressBookParser { +public class MymParser { /** * Used for initial separation of command word and args. @@ -72,5 +72,4 @@ public Command parseCommand(String userInput) throws ParseException { throw new ParseException(MESSAGE_UNKNOWN_COMMAND); } } - } diff --git a/src/main/java/seedu/address/logic/parser/ParserUtil.java b/src/main/java/seedu/address/logic/parser/ParserUtil.java index b117acb9c55..7481cc552ff 100644 --- a/src/main/java/seedu/address/logic/parser/ParserUtil.java +++ b/src/main/java/seedu/address/logic/parser/ParserUtil.java @@ -9,10 +9,9 @@ import seedu.address.commons.core.index.Index; import seedu.address.commons.util.StringUtil; import seedu.address.logic.parser.exceptions.ParseException; -import seedu.address.model.person.Address; -import seedu.address.model.person.Email; -import seedu.address.model.person.Name; -import seedu.address.model.person.Phone; +import seedu.address.model.expense.Amount; +import seedu.address.model.expense.Date; +import seedu.address.model.expense.Name; import seedu.address.model.tag.Tag; /** @@ -51,48 +50,33 @@ public static Name parseName(String name) throws ParseException { } /** - * Parses a {@code String phone} into a {@code Phone}. + * Parses a {@code String amount} into a {@code Amount}. * Leading and trailing whitespaces will be trimmed. * - * @throws ParseException if the given {@code phone} is invalid. + * @throws ParseException if the given {@code amount} is invalid. */ - public static Phone parsePhone(String phone) throws ParseException { - requireNonNull(phone); - String trimmedPhone = phone.trim(); - if (!Phone.isValidPhone(trimmedPhone)) { - throw new ParseException(Phone.MESSAGE_CONSTRAINTS); + public static Amount parseAmount(String amount) throws ParseException { + requireNonNull(amount); + String trimmedAmount = amount.trim(); + if (!Amount.isValidAmount(trimmedAmount)) { + throw new ParseException(Amount.MESSAGE_CONSTRAINTS); } - return new Phone(trimmedPhone); + return new Amount(trimmedAmount); } /** - * Parses a {@code String address} into an {@code Address}. + * Parses a {@code String date} into an {@code Date}. * Leading and trailing whitespaces will be trimmed. * - * @throws ParseException if the given {@code address} is invalid. + * @throws ParseException if the given {@code date} is invalid. */ - public static Address parseAddress(String address) throws ParseException { - requireNonNull(address); - String trimmedAddress = address.trim(); - if (!Address.isValidAddress(trimmedAddress)) { - throw new ParseException(Address.MESSAGE_CONSTRAINTS); + public static Date parseDate(String date) throws ParseException { + requireNonNull(date); + String trimmedDate = date.trim(); + if (!Date.isValidDate(trimmedDate)) { + throw new ParseException(Date.MESSAGE_CONSTRAINTS); } - return new Address(trimmedAddress); - } - - /** - * Parses a {@code String email} into an {@code Email}. - * Leading and trailing whitespaces will be trimmed. - * - * @throws ParseException if the given {@code email} is invalid. - */ - public static Email parseEmail(String email) throws ParseException { - requireNonNull(email); - String trimmedEmail = email.trim(); - if (!Email.isValidEmail(trimmedEmail)) { - throw new ParseException(Email.MESSAGE_CONSTRAINTS); - } - return new Email(trimmedEmail); + return new Date(trimmedDate, true); } /** diff --git a/src/main/java/seedu/address/model/AddressBook.java b/src/main/java/seedu/address/model/AddressBook.java deleted file mode 100644 index 1a943a0781a..00000000000 --- a/src/main/java/seedu/address/model/AddressBook.java +++ /dev/null @@ -1,120 +0,0 @@ -package seedu.address.model; - -import static java.util.Objects.requireNonNull; - -import java.util.List; - -import javafx.collections.ObservableList; -import seedu.address.model.person.Person; -import seedu.address.model.person.UniquePersonList; - -/** - * Wraps all data at the address-book level - * Duplicates are not allowed (by .isSamePerson comparison) - */ -public class AddressBook implements ReadOnlyAddressBook { - - private final UniquePersonList persons; - - /* - * The 'unusual' code block below is a non-static initialization block, sometimes used to avoid duplication - * between constructors. See https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html - * - * Note that non-static init blocks are not recommended to use. There are other ways to avoid duplication - * among constructors. - */ - { - persons = new UniquePersonList(); - } - - public AddressBook() {} - - /** - * Creates an AddressBook using the Persons in the {@code toBeCopied} - */ - public AddressBook(ReadOnlyAddressBook toBeCopied) { - this(); - resetData(toBeCopied); - } - - //// list overwrite operations - - /** - * Replaces the contents of the person list with {@code persons}. - * {@code persons} must not contain duplicate persons. - */ - public void setPersons(List persons) { - this.persons.setPersons(persons); - } - - /** - * Resets the existing data of this {@code AddressBook} with {@code newData}. - */ - public void resetData(ReadOnlyAddressBook newData) { - requireNonNull(newData); - - setPersons(newData.getPersonList()); - } - - //// person-level operations - - /** - * Returns true if a person with the same identity as {@code person} exists in the address book. - */ - public boolean hasPerson(Person person) { - requireNonNull(person); - return persons.contains(person); - } - - /** - * Adds a person to the address book. - * The person must not already exist in the address book. - */ - public void addPerson(Person p) { - persons.add(p); - } - - /** - * Replaces the given person {@code target} in the list with {@code editedPerson}. - * {@code target} must exist in the address book. - * The person identity of {@code editedPerson} must not be the same as another existing person in the address book. - */ - public void setPerson(Person target, Person editedPerson) { - requireNonNull(editedPerson); - - persons.setPerson(target, editedPerson); - } - - /** - * Removes {@code key} from this {@code AddressBook}. - * {@code key} must exist in the address book. - */ - public void removePerson(Person key) { - persons.remove(key); - } - - //// util methods - - @Override - public String toString() { - return persons.asUnmodifiableObservableList().size() + " persons"; - // TODO: refine later - } - - @Override - public ObservableList getPersonList() { - return persons.asUnmodifiableObservableList(); - } - - @Override - public boolean equals(Object other) { - return other == this // short circuit if same object - || (other instanceof AddressBook // instanceof handles nulls - && persons.equals(((AddressBook) other).persons)); - } - - @Override - public int hashCode() { - return persons.hashCode(); - } -} diff --git a/src/main/java/seedu/address/model/ExpenseList.java b/src/main/java/seedu/address/model/ExpenseList.java new file mode 100644 index 00000000000..7233028974e --- /dev/null +++ b/src/main/java/seedu/address/model/ExpenseList.java @@ -0,0 +1,121 @@ +package seedu.address.model; + +import static java.util.Objects.requireNonNull; + +import java.util.List; + +import javafx.collections.ObservableList; +import seedu.address.model.expense.Expense; +import seedu.address.model.expense.UniqueExpenseList; + +/** + * Wraps all data at the expenseList level + * Duplicates are not allowed (by .isSameExpense comparison) + */ +public class ExpenseList implements ReadOnlyExpenseList { + + private final UniqueExpenseList expenses; + + /* + * The 'unusual' code block below is a non-static initialization block, sometimes used to avoid duplication + * between constructors. See https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html + * + * Note that non-static init blocks are not recommended to use. There are other ways to avoid duplication + * among constructors. + */ { + expenses = new UniqueExpenseList(); + } + + public ExpenseList() { + } + + /** + * Creates an ExpenseList using the Expenses in the {@code toBeCopied} + */ + public ExpenseList(ReadOnlyExpenseList toBeCopied) { + this(); + resetData(toBeCopied); + } + + //// list overwrite operations + + /** + * Replaces the contents of the expense list with {@code expenses}. + * {@code expenses} must not contain duplicate expenses. + */ + public void setExpenses(List expenses) { + this.expenses.setExpenses(expenses); + } + + /** + * Resets the existing data of this {@code ExpenseList} with {@code newData}. + */ + public void resetData(ReadOnlyExpenseList newData) { + requireNonNull(newData); + + setExpenses(newData.getExpenseList()); + } + + //// expense-level operations + + /** + * Returns true if a expense with the same identity as {@code expense} exists in the expense list. + */ + public boolean hasExpense(Expense expense) { + requireNonNull(expense); + return expenses.contains(expense); + } + + /** + * Adds a expense to the expense list. + * The expense must not already exist in the expense list. + */ + public void addExpense(Expense p) { + expenses.add(p); + } + + /** + * Replaces the given expense {@code target} in the list with {@code editedExpense}. + * {@code target} must exist in the expense list. + * The expense identity of {@code editedExpense} must not be the same as another existing expense in the expense + * list. + */ + public void setExpense(Expense target, Expense editedExpense) { + requireNonNull(editedExpense); + + expenses.setExpense(target, editedExpense); + } + + /** + * Removes {@code key} from this {@code ExpenseList}. + * {@code key} must exist in the expense list. + */ + public void removeExpense(Expense key) { + expenses.remove(key); + } + + //// util methods + + @Override + public String toString() { + return expenses.asUnmodifiableObservableList().size() + " expenses"; + // TODO: refine later + } + + @Override + public ObservableList getExpenseList() { + return expenses.asUnmodifiableObservableList(); + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof ExpenseList // instanceof handles nulls + && expenses.equals(((ExpenseList) other).expenses)); + } + + @Override + public int hashCode() { + return expenses.hashCode(); + } +} diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java index d54df471c1f..474a0a5c54f 100644 --- a/src/main/java/seedu/address/model/Model.java +++ b/src/main/java/seedu/address/model/Model.java @@ -5,14 +5,14 @@ import javafx.collections.ObservableList; import seedu.address.commons.core.GuiSettings; -import seedu.address.model.person.Person; +import seedu.address.model.expense.Expense; /** * The API of the Model component. */ public interface Model { /** {@code Predicate} that always evaluate to true */ - Predicate PREDICATE_SHOW_ALL_PERSONS = unused -> true; + Predicate PREDICATE_SHOW_ALL_EXPENSES = unused -> true; /** * Replaces user prefs data with the data in {@code userPrefs}. @@ -35,53 +35,54 @@ public interface Model { void setGuiSettings(GuiSettings guiSettings); /** - * Returns the user prefs' address book file path. + * Returns the user prefs' expense list file path. */ - Path getAddressBookFilePath(); + Path getExpenseListFilePath(); /** - * Sets the user prefs' address book file path. + * Sets the user prefs' expense list file path. */ - void setAddressBookFilePath(Path addressBookFilePath); + void setExpenseListFilePath(Path expenseListFilePath); /** - * Replaces address book data with the data in {@code addressBook}. + * Replaces expense list data with the data in {@code expenseList}. */ - void setAddressBook(ReadOnlyAddressBook addressBook); + void setExpenseList(ReadOnlyExpenseList expenseList); - /** Returns the AddressBook */ - ReadOnlyAddressBook getAddressBook(); + /** Returns the ExpenseList */ + ReadOnlyExpenseList getExpenseList(); /** - * Returns true if a person with the same identity as {@code person} exists in the address book. + * Returns true if an expense with the same identity as {@code expense} exists in the expense list. */ - boolean hasPerson(Person person); + boolean hasExpense(Expense expense); /** - * Deletes the given person. - * The person must exist in the address book. + * Deletes the given expense. + * The expense must exist in the expense list. */ - void deletePerson(Person target); + void deleteExpense(Expense target); /** - * Adds the given person. - * {@code person} must not already exist in the address book. + * Adds the given expense. + * {@code expense} must not already exist in the expense list. */ - void addPerson(Person person); + void addExpense(Expense expense); /** - * Replaces the given person {@code target} with {@code editedPerson}. - * {@code target} must exist in the address book. - * The person identity of {@code editedPerson} must not be the same as another existing person in the address book. + * Replaces the given expense {@code target} with {@code editedExpense}. + * {@code target} must exist in the expense list. + * The expense identity of {@code editedExpense} must not be the same as + * another existing expense in the expense list. */ - void setPerson(Person target, Person editedPerson); + void setExpense(Expense target, Expense editedExpense); - /** Returns an unmodifiable view of the filtered person list */ - ObservableList getFilteredPersonList(); + /** Returns an unmodifiable view of the filtered expense list */ + ObservableList getFilteredExpenseList(); /** - * Updates the filter of the filtered person list to filter by the given {@code predicate}. + * Updates the filter of the filtered expense list to filter by the given {@code predicate}. * @throws NullPointerException if {@code predicate} is null. */ - void updateFilteredPersonList(Predicate predicate); + void updateFilteredExpenseList(Predicate predicate); } diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index 0650c954f5c..074ba67b0a3 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -11,34 +11,34 @@ import javafx.collections.transformation.FilteredList; import seedu.address.commons.core.GuiSettings; import seedu.address.commons.core.LogsCenter; -import seedu.address.model.person.Person; +import seedu.address.model.expense.Expense; /** - * Represents the in-memory model of the address book data. + * Represents the in-memory model of the expense list data. */ public class ModelManager implements Model { private static final Logger logger = LogsCenter.getLogger(ModelManager.class); - private final AddressBook addressBook; + private final ExpenseList expenseList; private final UserPrefs userPrefs; - private final FilteredList filteredPersons; + private final FilteredList filteredExpenses; /** - * Initializes a ModelManager with the given addressBook and userPrefs. + * Initializes a ModelManager with the given expenseList and userPrefs. */ - public ModelManager(ReadOnlyAddressBook addressBook, ReadOnlyUserPrefs userPrefs) { + public ModelManager(ReadOnlyExpenseList expenseList, ReadOnlyUserPrefs userPrefs) { super(); - requireAllNonNull(addressBook, userPrefs); + requireAllNonNull(expenseList, userPrefs); - logger.fine("Initializing with address book: " + addressBook + " and user prefs " + userPrefs); + logger.fine("Initializing with expense list: " + expenseList + " and user prefs " + userPrefs); - this.addressBook = new AddressBook(addressBook); + this.expenseList = new ExpenseList(expenseList); this.userPrefs = new UserPrefs(userPrefs); - filteredPersons = new FilteredList<>(this.addressBook.getPersonList()); + filteredExpenses = new FilteredList<>(this.expenseList.getExpenseList()); } public ModelManager() { - this(new AddressBook(), new UserPrefs()); + this(new ExpenseList(), new UserPrefs()); } //=========== UserPrefs ================================================================================== @@ -66,67 +66,67 @@ public void setGuiSettings(GuiSettings guiSettings) { } @Override - public Path getAddressBookFilePath() { - return userPrefs.getAddressBookFilePath(); + public Path getExpenseListFilePath() { + return userPrefs.getExpenseListFilePath(); } @Override - public void setAddressBookFilePath(Path addressBookFilePath) { - requireNonNull(addressBookFilePath); - userPrefs.setAddressBookFilePath(addressBookFilePath); + public void setExpenseListFilePath(Path expenseListFilePath) { + requireNonNull(expenseListFilePath); + userPrefs.setExpenseListFilePath(expenseListFilePath); } - //=========== AddressBook ================================================================================ + //=========== ExpenseList ================================================================================ @Override - public void setAddressBook(ReadOnlyAddressBook addressBook) { - this.addressBook.resetData(addressBook); + public void setExpenseList(ReadOnlyExpenseList expenseList) { + this.expenseList.resetData(expenseList); } @Override - public ReadOnlyAddressBook getAddressBook() { - return addressBook; + public ReadOnlyExpenseList getExpenseList() { + return expenseList; } @Override - public boolean hasPerson(Person person) { - requireNonNull(person); - return addressBook.hasPerson(person); + public boolean hasExpense(Expense expense) { + requireNonNull(expense); + return expenseList.hasExpense(expense); } @Override - public void deletePerson(Person target) { - addressBook.removePerson(target); + public void deleteExpense(Expense target) { + expenseList.removeExpense(target); } @Override - public void addPerson(Person person) { - addressBook.addPerson(person); - updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); + public void addExpense(Expense expense) { + expenseList.addExpense(expense); + updateFilteredExpenseList(PREDICATE_SHOW_ALL_EXPENSES); } @Override - public void setPerson(Person target, Person editedPerson) { - requireAllNonNull(target, editedPerson); + public void setExpense(Expense target, Expense editedExpense) { + requireAllNonNull(target, editedExpense); - addressBook.setPerson(target, editedPerson); + expenseList.setExpense(target, editedExpense); } - //=========== Filtered Person List Accessors ============================================================= + //=========== Filtered Expense List Accessors ============================================================= /** - * Returns an unmodifiable view of the list of {@code Person} backed by the internal list of + * Returns an unmodifiable view of the list of {@code Expense} backed by the internal list of * {@code versionedAddressBook} */ @Override - public ObservableList getFilteredPersonList() { - return filteredPersons; + public ObservableList getFilteredExpenseList() { + return filteredExpenses; } @Override - public void updateFilteredPersonList(Predicate predicate) { + public void updateFilteredExpenseList(Predicate predicate) { requireNonNull(predicate); - filteredPersons.setPredicate(predicate); + filteredExpenses.setPredicate(predicate); } @Override @@ -143,9 +143,9 @@ public boolean equals(Object obj) { // state check ModelManager other = (ModelManager) obj; - return addressBook.equals(other.addressBook) + return expenseList.equals(other.expenseList) && userPrefs.equals(other.userPrefs) - && filteredPersons.equals(other.filteredPersons); + && filteredExpenses.equals(other.filteredExpenses); } } diff --git a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java b/src/main/java/seedu/address/model/ReadOnlyAddressBook.java deleted file mode 100644 index 6ddc2cd9a29..00000000000 --- a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java +++ /dev/null @@ -1,17 +0,0 @@ -package seedu.address.model; - -import javafx.collections.ObservableList; -import seedu.address.model.person.Person; - -/** - * Unmodifiable view of an address book - */ -public interface ReadOnlyAddressBook { - - /** - * Returns an unmodifiable view of the persons list. - * This list will not contain any duplicate persons. - */ - ObservableList getPersonList(); - -} diff --git a/src/main/java/seedu/address/model/ReadOnlyExpenseList.java b/src/main/java/seedu/address/model/ReadOnlyExpenseList.java new file mode 100644 index 00000000000..9cc081b36d4 --- /dev/null +++ b/src/main/java/seedu/address/model/ReadOnlyExpenseList.java @@ -0,0 +1,16 @@ +package seedu.address.model; + +import javafx.collections.ObservableList; +import seedu.address.model.expense.Expense; + +/** + * Unmodifiable view of an expense list + */ +public interface ReadOnlyExpenseList { + + /** + * Returns an unmodifiable view of the expenses list. + * This list will not contain any duplicate expenses. + */ + ObservableList getExpenseList(); +} diff --git a/src/main/java/seedu/address/model/ReadOnlyUserPrefs.java b/src/main/java/seedu/address/model/ReadOnlyUserPrefs.java index befd58a4c73..b42441018e0 100644 --- a/src/main/java/seedu/address/model/ReadOnlyUserPrefs.java +++ b/src/main/java/seedu/address/model/ReadOnlyUserPrefs.java @@ -11,6 +11,6 @@ public interface ReadOnlyUserPrefs { GuiSettings getGuiSettings(); - Path getAddressBookFilePath(); + Path getExpenseListFilePath(); } diff --git a/src/main/java/seedu/address/model/UserPrefs.java b/src/main/java/seedu/address/model/UserPrefs.java index 25a5fd6eab9..0826d1221fd 100644 --- a/src/main/java/seedu/address/model/UserPrefs.java +++ b/src/main/java/seedu/address/model/UserPrefs.java @@ -14,12 +14,13 @@ public class UserPrefs implements ReadOnlyUserPrefs { private GuiSettings guiSettings = new GuiSettings(); - private Path addressBookFilePath = Paths.get("data" , "addressbook.json"); + private Path expenseListFilePath = Paths.get("data", "expenselist.json"); /** * Creates a {@code UserPrefs} with default values. */ - public UserPrefs() {} + public UserPrefs() { + } /** * Creates a {@code UserPrefs} with the prefs in {@code userPrefs}. @@ -35,7 +36,7 @@ public UserPrefs(ReadOnlyUserPrefs userPrefs) { public void resetData(ReadOnlyUserPrefs newUserPrefs) { requireNonNull(newUserPrefs); setGuiSettings(newUserPrefs.getGuiSettings()); - setAddressBookFilePath(newUserPrefs.getAddressBookFilePath()); + setExpenseListFilePath(newUserPrefs.getExpenseListFilePath()); } public GuiSettings getGuiSettings() { @@ -47,13 +48,13 @@ public void setGuiSettings(GuiSettings guiSettings) { this.guiSettings = guiSettings; } - public Path getAddressBookFilePath() { - return addressBookFilePath; + public Path getExpenseListFilePath() { + return expenseListFilePath; } - public void setAddressBookFilePath(Path addressBookFilePath) { - requireNonNull(addressBookFilePath); - this.addressBookFilePath = addressBookFilePath; + public void setExpenseListFilePath(Path expenseListFilePath) { + requireNonNull(expenseListFilePath); + this.expenseListFilePath = expenseListFilePath; } @Override @@ -68,20 +69,19 @@ public boolean equals(Object other) { UserPrefs o = (UserPrefs) other; return guiSettings.equals(o.guiSettings) - && addressBookFilePath.equals(o.addressBookFilePath); + && expenseListFilePath.equals(o.expenseListFilePath); } @Override public int hashCode() { - return Objects.hash(guiSettings, addressBookFilePath); + return Objects.hash(guiSettings, expenseListFilePath); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("Gui Settings : " + guiSettings); - sb.append("\nLocal data file location : " + addressBookFilePath); + sb.append("\nLocal data file location : " + expenseListFilePath); return sb.toString(); } - } diff --git a/src/main/java/seedu/address/model/expense/Amount.java b/src/main/java/seedu/address/model/expense/Amount.java new file mode 100644 index 00000000000..ea7e47f3e88 --- /dev/null +++ b/src/main/java/seedu/address/model/expense/Amount.java @@ -0,0 +1,52 @@ +package seedu.address.model.expense; + +import static java.util.Objects.requireNonNull; +import static seedu.address.commons.util.AppUtil.checkArgument; + +/** + * Represents the amount of an expense in the MYMorise. + * Guarantees: immutable; is valid as declared in {@link #isValidAmount(String)} + */ +public class Amount { + + public static final String MESSAGE_CONSTRAINTS = "Amount should contain numbers, 1-12 digits and it may have a " + + "prefix of currency sign" + "and it should not be blank"; + public static final String VALIDATION_REGEX = "[\\p{Sc}]?[\\d]{1,12}[.]??[\\d]{0,2}"; + + public final String value; + + /** + * Constructs an {@code Amount}. + * + * @param amount A valid amount. + */ + public Amount(String amount) { + requireNonNull(amount); + checkArgument(isValidAmount(amount), MESSAGE_CONSTRAINTS); + value = amount; + } + + /** + * Returns if a given string is a valid amount. + */ + public static boolean isValidAmount(String test) { + return test.matches(VALIDATION_REGEX); + } + + @Override + public String toString() { + return value; + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof Amount // instanceof handles nulls + && value.equals(((Amount) other).value)); // state check + } + + @Override + public int hashCode() { + return value.hashCode(); + } +} diff --git a/src/main/java/seedu/address/model/expense/Date.java b/src/main/java/seedu/address/model/expense/Date.java new file mode 100644 index 00000000000..b612366fac0 --- /dev/null +++ b/src/main/java/seedu/address/model/expense/Date.java @@ -0,0 +1,149 @@ +package seedu.address.model.expense; + +import static java.util.Objects.requireNonNull; +import static seedu.address.commons.util.AppUtil.checkArgument; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; + +/** + * Represents the date of an expense in the MYMorise. + * Guarantees: immutable; is valid as declared in {@link #isValidDate(String)} + */ +public class Date { + + public static final String MESSAGE_CONSTRAINTS = "Date should be of the format Hmm or HHmm or dd/MM/yyyy Hmm or " + + "d/MM/yyyy Hmm or dd/MM/yyyy or d/MM/yyyy"; + public static final String HMM_REGEX = "\\d{3}"; + public static final String HHMM_REGEX = "\\d{4}"; + public static final String DMYYYY_REGEX = "[\\d]{1}[/][\\d]{1}[/][\\d]{4}"; + public static final String DMMYYYY_REGEX = "[\\d]{1}[/][\\d]{2}[/][\\d]{4}"; + public static final String DDMYYYY_REGEX = "[\\d]{2}[/][\\d]{1}[/][\\d]{4}"; + public static final String DDMMYYYY_REGEX = "[\\d]{2}[/][\\d]{2}[/][\\d]{4}"; + public static final String DMYYYYHMM_REGEX = "[\\d]{1}[/][\\d]{1}[/][\\d]{4}\\s[\\d]{3}"; + public static final String DMMYYYYHMM_REGEX = "[\\d]{1}[/][\\d]{2}[/][\\d]{4}\\s[\\d]{3}"; + public static final String DDMYYYYHMM_REGEX = "[\\d]{2}[/][\\d]{1}[/][\\d]{4}\\s[\\d]{3}"; + public static final String DDMMYYYYHMM_REGEX = "[\\d]{2}[/][\\d]{2}[/][\\d]{4}\\s[\\d]{3}"; + public static final String DMYYYYHHMM_REGEX = "[\\d]{1}[/][\\d]{1}[/][\\d]{4}\\s[\\d]{4}"; + public static final String DMMYYYYHHMM_REGEX = "[\\d]{1}[/][\\d]{2}[/][\\d]{4}\\s[\\d]{4}"; + public static final String DDMYYYYHHMM_REGEX = "[\\d]{2}[/][\\d]{1}[/][\\d]{4}\\s[\\d]{4}"; + public static final String DDMMYYYYHHMM_REGEX = "[\\d]{2}[/][\\d]{2}[/][\\d]{4}\\s[\\d]{4}"; + + public final String value; + public final String rawValue; + + /** + * Constructs an {@code Date}. + * @param date A valid date. + * @param ifConverted + * + */ + public Date(String date, boolean ifConverted) { + requireNonNull(date); + checkArgument(isValidDate(date), MESSAGE_CONSTRAINTS); + rawValue = date; + value = ifConverted ? convertDate(date) : date; + } + + /** + * Returns if a given string is a valid date. + */ + public static boolean isValidDate(String test) { + return !test.equals(convertDate(test)); + } + + /** + * Transform a given string to a date + * Supported format: Hmm, HHmm, d/M/yyyy, d/MM/yyyy, dd/M/yyyy, dd/MM/yyyy, + * d/M/yyyy Hmm, d/MM/yyyy Hmm, dd/M/yyyy Hmm, dd/MM/yyyy Hmm, + * d/M/yyyy HHmm, d/MM/yyyy HHmm, dd/M/yyyy HHmm, dd/MM/yyyy HHmm, + * e.g. 1/12/2019, 1/12/2019 1845, 10/12/2019, 10/12/2019 1845, 1245 + * + * @param date given string + * @return converted date + */ + private static String convertDate(String date) { + DateTimeFormatter formatter; + LocalTime newTime; + LocalDate newDate; + LocalDateTime newDateTime; + if (date.matches(HMM_REGEX)) { + formatter = DateTimeFormatter.ofPattern("Hmm"); + newTime = LocalTime.parse(date, formatter); + return newTime.format(DateTimeFormatter.ofPattern("H:mma")); + } else if (date.matches(HHMM_REGEX)) { + formatter = DateTimeFormatter.ofPattern("HHmm"); + newTime = LocalTime.parse(date, formatter); + return newTime.format(DateTimeFormatter.ofPattern("HH:mma")); + } else if (date.matches(DMYYYY_REGEX)) { + formatter = DateTimeFormatter.ofPattern("d/M/yyyy"); + newDate = LocalDate.parse(date, formatter); + return newDate.format(DateTimeFormatter.ofPattern("MMM dd, yyyy")); + } else if (date.matches(DMMYYYY_REGEX)) { + formatter = DateTimeFormatter.ofPattern("d/MM/yyyy"); + newDate = LocalDate.parse(date, formatter); + return newDate.format(DateTimeFormatter.ofPattern("MMM dd, yyyy")); + } else if (date.matches(DDMYYYY_REGEX)) { + formatter = DateTimeFormatter.ofPattern("dd/M/yyyy"); + newDate = LocalDate.parse(date, formatter); + return newDate.format(DateTimeFormatter.ofPattern("MMM dd, yyyy")); + } else if (date.matches(DDMMYYYY_REGEX)) { + formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy"); + newDate = LocalDate.parse(date, formatter); + return newDate.format(DateTimeFormatter.ofPattern("MMM dd, yyyy")); + } else if (date.matches(DMYYYYHMM_REGEX)) { + formatter = DateTimeFormatter.ofPattern("d/M/yyyy Hmm"); + newDateTime = LocalDateTime.parse(date, formatter); + return newDateTime.format(DateTimeFormatter.ofPattern("MMM dd H:mma, yyyy")); + } else if (date.matches(DMMYYYYHMM_REGEX)) { + formatter = DateTimeFormatter.ofPattern("d/MM/yyyy Hmm"); + newDateTime = LocalDateTime.parse(date, formatter); + return newDateTime.format(DateTimeFormatter.ofPattern("MMM dd H:mma, yyyy")); + } else if (date.matches(DDMYYYYHMM_REGEX)) { + formatter = DateTimeFormatter.ofPattern("dd/M/yyyy Hmm"); + newDateTime = LocalDateTime.parse(date, formatter); + return newDateTime.format(DateTimeFormatter.ofPattern("MMM dd H:mma, yyyy")); + } else if (date.matches(DDMMYYYYHMM_REGEX)) { + formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy Hmm"); + newDateTime = LocalDateTime.parse(date, formatter); + return newDateTime.format(DateTimeFormatter.ofPattern("MMM dd H:mma, yyyy")); + } else if (date.matches(DMYYYYHHMM_REGEX)) { + formatter = DateTimeFormatter.ofPattern("d/M/yyyy HHmm"); + newDateTime = LocalDateTime.parse(date, formatter); + return newDateTime.format(DateTimeFormatter.ofPattern("MMM dd H:mma, yyyy")); + } else if (date.matches(DMMYYYYHHMM_REGEX)) { + formatter = DateTimeFormatter.ofPattern("d/MM/yyyy HHmm"); + newDateTime = LocalDateTime.parse(date, formatter); + return newDateTime.format(DateTimeFormatter.ofPattern("MMM dd H:mma, yyyy")); + } else if (date.matches(DDMYYYYHHMM_REGEX)) { + formatter = DateTimeFormatter.ofPattern("dd/M/yyyy HHmm"); + newDateTime = LocalDateTime.parse(date, formatter); + return newDateTime.format(DateTimeFormatter.ofPattern("MMM dd H:mma, yyyy")); + } else if (date.matches(DDMMYYYYHHMM_REGEX)) { + formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HHmm"); + newDateTime = LocalDateTime.parse(date, formatter); + return newDateTime.format(DateTimeFormatter.ofPattern("MMM dd H:mma, yyyy")); + } else { + return date; + } + } + + @Override + public String toString() { + return value; + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof Date // instanceof handles nulls + && value.equals(((Date) other).value)); // state check + } + + @Override + public int hashCode() { + return value.hashCode(); + } +} diff --git a/src/main/java/seedu/address/model/expense/Expense.java b/src/main/java/seedu/address/model/expense/Expense.java new file mode 100644 index 00000000000..5d29b95bc1b --- /dev/null +++ b/src/main/java/seedu/address/model/expense/Expense.java @@ -0,0 +1,110 @@ +package seedu.address.model.expense; + +import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +import seedu.address.model.tag.Tag; + +/** + * Represents an expense in the expense list. + * Guarantees: details are present and not null, field values are validated, immutable. + */ +public class Expense { + + // Identity fields + private final Name name; + private final Amount amount; + + // Data Fields + private final Date date; + private final Set tags = new HashSet<>(); + + /** + * Every field must be present and not null. + */ + public Expense(Name name, Amount amount, Date date, Set tags) { + requireAllNonNull(name, amount, date, tags); + this.name = name; + this.amount = amount; + this.date = date; + this.tags.addAll(tags); + } + + public Name getName() { + return name; + } + + public Amount getAmount() { + return amount; + } + + public Date getDate() { + return date; + } + + /** + * Returns an immutable tag set, which throws {@code UnsupportedOperationException} + * if modification is attempted. + */ + public Set getTags() { + return Collections.unmodifiableSet(tags); + } + + /** + * Returns true if both expenses of the same name have at least one other identity field that is the same. + * This defines a weaker notion of equality between two expenses. + */ + public boolean isSameExpense(Expense otherExpense) { + if (otherExpense == this) { + return true; + } + + return otherExpense != null + && otherExpense.getName().equals(getName()) + && (otherExpense.getAmount().equals(getAmount()) || otherExpense.getDate().equals(getDate())); + } + + /** + * Returns true if both expenses have the same identity and data fields. + * This defines a stronger notion of equality between two expenses. + */ + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + if (!(other instanceof Expense)) { + return false; + } + + Expense otherExpense = (Expense) other; + return otherExpense.getName().equals(getName()) + && otherExpense.getAmount().equals(getAmount()) + && otherExpense.getDate().equals(getDate()) + && otherExpense.getTags().equals(getTags()); + } + + @Override + public int hashCode() { + // use this method for custom fields hashing instead of implementing your own + return Objects.hash(name, amount, date, tags); + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append(getName()) + .append(" Amount: ") + .append(getAmount()) + .append(" Date: ") + .append(getDate()) + .append(" Tags: "); + getTags().forEach(builder::append); + return builder.toString(); + } +} diff --git a/src/main/java/seedu/address/model/person/Name.java b/src/main/java/seedu/address/model/expense/Name.java similarity index 69% rename from src/main/java/seedu/address/model/person/Name.java rename to src/main/java/seedu/address/model/expense/Name.java index 79244d71cf7..e2a768d1801 100644 --- a/src/main/java/seedu/address/model/person/Name.java +++ b/src/main/java/seedu/address/model/expense/Name.java @@ -1,22 +1,22 @@ -package seedu.address.model.person; +package seedu.address.model.expense; import static java.util.Objects.requireNonNull; import static seedu.address.commons.util.AppUtil.checkArgument; /** - * Represents a Person's name in the address book. + * Represents the description of an expense in the MYMorise. * Guarantees: immutable; is valid as declared in {@link #isValidName(String)} */ public class Name { public static final String MESSAGE_CONSTRAINTS = - "Names should only contain alphanumeric characters and spaces, and it should not be blank"; + "Names should only contain alphanumeric characters and spaces, and it should not be blank"; /* - * The first character of the address must not be a whitespace, + * The first character of the expense must not be a whitespace, * otherwise " " (a blank string) becomes a valid input. */ - public static final String VALIDATION_REGEX = "[\\p{Alnum}][\\p{Alnum} ]*"; + public static final String VALIDATION_REGEX = "[^\\s].*"; public final String fullName; @@ -38,7 +38,6 @@ public static boolean isValidName(String test) { return test.matches(VALIDATION_REGEX); } - @Override public String toString() { return fullName; @@ -47,13 +46,12 @@ public String toString() { @Override public boolean equals(Object other) { return other == this // short circuit if same object - || (other instanceof Name // instanceof handles nulls - && fullName.equals(((Name) other).fullName)); // state check + || (other instanceof Name // instanceof handles nulls + && fullName.equals(((Name) other).fullName)); // state check } @Override public int hashCode() { return fullName.hashCode(); } - } diff --git a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/expense/NameContainsKeywordsPredicate.java similarity index 77% rename from src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java rename to src/main/java/seedu/address/model/expense/NameContainsKeywordsPredicate.java index c9b5868427c..2963805d417 100644 --- a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java +++ b/src/main/java/seedu/address/model/expense/NameContainsKeywordsPredicate.java @@ -1,4 +1,4 @@ -package seedu.address.model.person; +package seedu.address.model.expense; import java.util.List; import java.util.function.Predicate; @@ -6,9 +6,9 @@ import seedu.address.commons.util.StringUtil; /** - * Tests that a {@code Person}'s {@code Name} matches any of the keywords given. + * Tests that a {@code Expense}'s {@code Name} matches any of the keywords given. */ -public class NameContainsKeywordsPredicate implements Predicate { +public class NameContainsKeywordsPredicate implements Predicate { private final List keywords; public NameContainsKeywordsPredicate(List keywords) { @@ -16,9 +16,9 @@ public NameContainsKeywordsPredicate(List keywords) { } @Override - public boolean test(Person person) { + public boolean test(Expense expense) { return keywords.stream() - .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(person.getName().fullName, keyword)); + .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(expense.getName().fullName, keyword)); } @Override diff --git a/src/main/java/seedu/address/model/expense/UniqueExpenseList.java b/src/main/java/seedu/address/model/expense/UniqueExpenseList.java new file mode 100644 index 00000000000..a9d5651c1cb --- /dev/null +++ b/src/main/java/seedu/address/model/expense/UniqueExpenseList.java @@ -0,0 +1,139 @@ +package seedu.address.model.expense; + +import static java.util.Objects.requireNonNull; +import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; + +import java.util.Iterator; +import java.util.List; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import seedu.address.model.expense.exceptions.DuplicateExpenseException; +import seedu.address.model.expense.exceptions.ExpenseNotFoundException; + +/** + * A list of expenses that enforces uniqueness between its elements and does not allow nulls. + * A expense is considered unique by comparing using {@code Expense#isSameExpense(Expense)}. As such, adding and + * updating of + * expenses uses Expense#isSameExpense(Expense) for equality so as to ensure that the expense being added or updated is + * unique in terms of identity in the UniqueExpenseList. However, the removal of a expense uses Expense#equals + * (Object) so + * as to ensure that the expense with exactly the same fields will be removed. + *

+ * Supports a minimal set of list operations. + * + * @see Expense#isSameExpense(Expense) + */ +public class UniqueExpenseList implements Iterable { + + private final ObservableList internalList = FXCollections.observableArrayList(); + private final ObservableList internalUnmodifiableList = + FXCollections.unmodifiableObservableList(internalList); + + /** + * Returns true if the list contains an equivalent expense as the given argument. + */ + public boolean contains(Expense toCheck) { + requireNonNull(toCheck); + return internalList.stream().anyMatch(toCheck::isSameExpense); + } + + /** + * Adds a expense to the list. + * The expense must not already exist in the list. + */ + public void add(Expense toAdd) { + requireNonNull(toAdd); + if (contains(toAdd)) { + throw new DuplicateExpenseException(); + } + internalList.add(toAdd); + } + + /** + * Replaces the expense {@code target} in the list with {@code editedExpense}. + * {@code target} must exist in the list. + * The expense identity of {@code editedExpense} must not be the same as another existing expense in the list. + */ + public void setExpense(Expense target, Expense editedExpense) { + requireAllNonNull(target, editedExpense); + + int index = internalList.indexOf(target); + if (index == -1) { + throw new ExpenseNotFoundException(); + } + + if (!target.isSameExpense(editedExpense) && contains(editedExpense)) { + throw new DuplicateExpenseException(); + } + + internalList.set(index, editedExpense); + } + + /** + * Removes the equivalent expense from the list. + * The expense must exist in the list. + */ + public void remove(Expense toRemove) { + requireNonNull(toRemove); + if (!internalList.remove(toRemove)) { + throw new ExpenseNotFoundException(); + } + } + + public void setExpenses(UniqueExpenseList replacement) { + requireNonNull(replacement); + internalList.setAll(replacement.internalList); + } + + /** + * Replaces the contents of this list with {@code expenses}. + * {@code expenses} must not contain duplicate expenses. + */ + public void setExpenses(List expenses) { + requireAllNonNull(expenses); + if (!expensesAreUnique(expenses)) { + throw new DuplicateExpenseException(); + } + + internalList.setAll(expenses); + } + + /** + * Returns the backing list as an unmodifiable {@code ObservableList}. + */ + public ObservableList asUnmodifiableObservableList() { + return internalUnmodifiableList; + } + + @Override + public Iterator iterator() { + return internalList.iterator(); + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof UniqueExpenseList // instanceof handles nulls + && internalList.equals(((UniqueExpenseList) other).internalList)); + } + + @Override + public int hashCode() { + return internalList.hashCode(); + } + + /** + * Returns true if {@code expenses} contains only unique expenses. + */ + private boolean expensesAreUnique(List expenses) { + for (int i = 0; i < expenses.size() - 1; i++) { + for (int j = i + 1; j < expenses.size(); j++) { + if (expenses.get(i).isSameExpense(expenses.get(j))) { + return false; + } + } + } + return true; + } +} diff --git a/src/main/java/seedu/address/model/expense/exceptions/DuplicateExpenseException.java b/src/main/java/seedu/address/model/expense/exceptions/DuplicateExpenseException.java new file mode 100644 index 00000000000..3992d73c90d --- /dev/null +++ b/src/main/java/seedu/address/model/expense/exceptions/DuplicateExpenseException.java @@ -0,0 +1,11 @@ +package seedu.address.model.expense.exceptions; + +/** + * Signals that the operation will result in duplicate Expenses + * (Expenses are considered duplicates if they have the same identity). + */ +public class DuplicateExpenseException extends RuntimeException { + public DuplicateExpenseException() { + super("Operation would result in duplicate expenses"); + } +} diff --git a/src/main/java/seedu/address/model/expense/exceptions/ExpenseNotFoundException.java b/src/main/java/seedu/address/model/expense/exceptions/ExpenseNotFoundException.java new file mode 100644 index 00000000000..26ed63f7762 --- /dev/null +++ b/src/main/java/seedu/address/model/expense/exceptions/ExpenseNotFoundException.java @@ -0,0 +1,6 @@ +package seedu.address.model.expense.exceptions; + +/** + * Signals that the operation is unable to find the specified expense. + */ +public class ExpenseNotFoundException extends RuntimeException {} diff --git a/src/main/java/seedu/address/model/person/Address.java b/src/main/java/seedu/address/model/person/Address.java deleted file mode 100644 index 60472ca22a0..00000000000 --- a/src/main/java/seedu/address/model/person/Address.java +++ /dev/null @@ -1,57 +0,0 @@ -package seedu.address.model.person; - -import static java.util.Objects.requireNonNull; -import static seedu.address.commons.util.AppUtil.checkArgument; - -/** - * Represents a Person's address in the address book. - * Guarantees: immutable; is valid as declared in {@link #isValidAddress(String)} - */ -public class Address { - - public static final String MESSAGE_CONSTRAINTS = "Addresses can take any values, and it should not be blank"; - - /* - * The first character of the address must not be a whitespace, - * otherwise " " (a blank string) becomes a valid input. - */ - public static final String VALIDATION_REGEX = "[^\\s].*"; - - public final String value; - - /** - * Constructs an {@code Address}. - * - * @param address A valid address. - */ - public Address(String address) { - requireNonNull(address); - checkArgument(isValidAddress(address), MESSAGE_CONSTRAINTS); - value = address; - } - - /** - * Returns true if a given string is a valid email. - */ - public static boolean isValidAddress(String test) { - return test.matches(VALIDATION_REGEX); - } - - @Override - public String toString() { - return value; - } - - @Override - public boolean equals(Object other) { - return other == this // short circuit if same object - || (other instanceof Address // instanceof handles nulls - && value.equals(((Address) other).value)); // state check - } - - @Override - public int hashCode() { - return value.hashCode(); - } - -} diff --git a/src/main/java/seedu/address/model/person/Email.java b/src/main/java/seedu/address/model/person/Email.java deleted file mode 100644 index a5bbe0b6a5f..00000000000 --- a/src/main/java/seedu/address/model/person/Email.java +++ /dev/null @@ -1,67 +0,0 @@ -package seedu.address.model.person; - -import static java.util.Objects.requireNonNull; -import static seedu.address.commons.util.AppUtil.checkArgument; - -/** - * Represents a Person's email in the address book. - * Guarantees: immutable; is valid as declared in {@link #isValidEmail(String)} - */ -public class Email { - - private static final String SPECIAL_CHARACTERS = "!#$%&'*+/=?`{|}~^.-"; - public static final String MESSAGE_CONSTRAINTS = "Emails should be of the format local-part@domain " - + "and adhere to the following constraints:\n" - + "1. The local-part should only contain alphanumeric characters and these special characters, excluding " - + "the parentheses, (" + SPECIAL_CHARACTERS + ") .\n" - + "2. This is followed by a '@' and then a domain name. " - + "The domain name must:\n" - + " - be at least 2 characters long\n" - + " - start and end with alphanumeric characters\n" - + " - consist of alphanumeric characters, a period or a hyphen for the characters in between, if any."; - // alphanumeric and special characters - private static final String LOCAL_PART_REGEX = "^[\\w" + SPECIAL_CHARACTERS + "]+"; - private static final String DOMAIN_FIRST_CHARACTER_REGEX = "[^\\W_]"; // alphanumeric characters except underscore - private static final String DOMAIN_MIDDLE_REGEX = "[a-zA-Z0-9.-]*"; // alphanumeric, period and hyphen - private static final String DOMAIN_LAST_CHARACTER_REGEX = "[^\\W_]$"; - public static final String VALIDATION_REGEX = LOCAL_PART_REGEX + "@" - + DOMAIN_FIRST_CHARACTER_REGEX + DOMAIN_MIDDLE_REGEX + DOMAIN_LAST_CHARACTER_REGEX; - - public final String value; - - /** - * Constructs an {@code Email}. - * - * @param email A valid email address. - */ - public Email(String email) { - requireNonNull(email); - checkArgument(isValidEmail(email), MESSAGE_CONSTRAINTS); - value = email; - } - - /** - * Returns if a given string is a valid email. - */ - public static boolean isValidEmail(String test) { - return test.matches(VALIDATION_REGEX); - } - - @Override - public String toString() { - return value; - } - - @Override - public boolean equals(Object other) { - return other == this // short circuit if same object - || (other instanceof Email // instanceof handles nulls - && value.equals(((Email) other).value)); // state check - } - - @Override - public int hashCode() { - return value.hashCode(); - } - -} diff --git a/src/main/java/seedu/address/model/person/Person.java b/src/main/java/seedu/address/model/person/Person.java deleted file mode 100644 index 557a7a60cd5..00000000000 --- a/src/main/java/seedu/address/model/person/Person.java +++ /dev/null @@ -1,120 +0,0 @@ -package seedu.address.model.person; - -import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; - -import seedu.address.model.tag.Tag; - -/** - * Represents a Person in the address book. - * Guarantees: details are present and not null, field values are validated, immutable. - */ -public class Person { - - // Identity fields - private final Name name; - private final Phone phone; - private final Email email; - - // Data fields - private final Address address; - private final Set tags = new HashSet<>(); - - /** - * Every field must be present and not null. - */ - public Person(Name name, Phone phone, Email email, Address address, Set tags) { - requireAllNonNull(name, phone, email, address, tags); - this.name = name; - this.phone = phone; - this.email = email; - this.address = address; - this.tags.addAll(tags); - } - - public Name getName() { - return name; - } - - public Phone getPhone() { - return phone; - } - - public Email getEmail() { - return email; - } - - public Address getAddress() { - return address; - } - - /** - * Returns an immutable tag set, which throws {@code UnsupportedOperationException} - * if modification is attempted. - */ - public Set getTags() { - return Collections.unmodifiableSet(tags); - } - - /** - * Returns true if both persons of the same name have at least one other identity field that is the same. - * This defines a weaker notion of equality between two persons. - */ - public boolean isSamePerson(Person otherPerson) { - if (otherPerson == this) { - return true; - } - - return otherPerson != null - && otherPerson.getName().equals(getName()) - && (otherPerson.getPhone().equals(getPhone()) || otherPerson.getEmail().equals(getEmail())); - } - - /** - * Returns true if both persons have the same identity and data fields. - * This defines a stronger notion of equality between two persons. - */ - @Override - public boolean equals(Object other) { - if (other == this) { - return true; - } - - if (!(other instanceof Person)) { - return false; - } - - Person otherPerson = (Person) other; - return otherPerson.getName().equals(getName()) - && otherPerson.getPhone().equals(getPhone()) - && otherPerson.getEmail().equals(getEmail()) - && otherPerson.getAddress().equals(getAddress()) - && otherPerson.getTags().equals(getTags()); - } - - @Override - public int hashCode() { - // use this method for custom fields hashing instead of implementing your own - return Objects.hash(name, phone, email, address, tags); - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append(getName()) - .append(" Phone: ") - .append(getPhone()) - .append(" Email: ") - .append(getEmail()) - .append(" Address: ") - .append(getAddress()) - .append(" Tags: "); - getTags().forEach(builder::append); - return builder.toString(); - } - -} diff --git a/src/main/java/seedu/address/model/person/Phone.java b/src/main/java/seedu/address/model/person/Phone.java deleted file mode 100644 index 872c76b382f..00000000000 --- a/src/main/java/seedu/address/model/person/Phone.java +++ /dev/null @@ -1,53 +0,0 @@ -package seedu.address.model.person; - -import static java.util.Objects.requireNonNull; -import static seedu.address.commons.util.AppUtil.checkArgument; - -/** - * Represents a Person's phone number in the address book. - * Guarantees: immutable; is valid as declared in {@link #isValidPhone(String)} - */ -public class Phone { - - - public static final String MESSAGE_CONSTRAINTS = - "Phone numbers should only contain numbers, and it should be at least 3 digits long"; - public static final String VALIDATION_REGEX = "\\d{3,}"; - public final String value; - - /** - * Constructs a {@code Phone}. - * - * @param phone A valid phone number. - */ - public Phone(String phone) { - requireNonNull(phone); - checkArgument(isValidPhone(phone), MESSAGE_CONSTRAINTS); - value = phone; - } - - /** - * Returns true if a given string is a valid phone number. - */ - public static boolean isValidPhone(String test) { - return test.matches(VALIDATION_REGEX); - } - - @Override - public String toString() { - return value; - } - - @Override - public boolean equals(Object other) { - return other == this // short circuit if same object - || (other instanceof Phone // instanceof handles nulls - && value.equals(((Phone) other).value)); // state check - } - - @Override - public int hashCode() { - return value.hashCode(); - } - -} diff --git a/src/main/java/seedu/address/model/person/UniquePersonList.java b/src/main/java/seedu/address/model/person/UniquePersonList.java deleted file mode 100644 index 0fee4fe57e6..00000000000 --- a/src/main/java/seedu/address/model/person/UniquePersonList.java +++ /dev/null @@ -1,137 +0,0 @@ -package seedu.address.model.person; - -import static java.util.Objects.requireNonNull; -import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; - -import java.util.Iterator; -import java.util.List; - -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import seedu.address.model.person.exceptions.DuplicatePersonException; -import seedu.address.model.person.exceptions.PersonNotFoundException; - -/** - * A list of persons that enforces uniqueness between its elements and does not allow nulls. - * A person is considered unique by comparing using {@code Person#isSamePerson(Person)}. As such, adding and updating of - * persons uses Person#isSamePerson(Person) for equality so as to ensure that the person being added or updated is - * unique in terms of identity in the UniquePersonList. However, the removal of a person uses Person#equals(Object) so - * as to ensure that the person with exactly the same fields will be removed. - * - * Supports a minimal set of list operations. - * - * @see Person#isSamePerson(Person) - */ -public class UniquePersonList implements Iterable { - - private final ObservableList internalList = FXCollections.observableArrayList(); - private final ObservableList internalUnmodifiableList = - FXCollections.unmodifiableObservableList(internalList); - - /** - * Returns true if the list contains an equivalent person as the given argument. - */ - public boolean contains(Person toCheck) { - requireNonNull(toCheck); - return internalList.stream().anyMatch(toCheck::isSamePerson); - } - - /** - * Adds a person to the list. - * The person must not already exist in the list. - */ - public void add(Person toAdd) { - requireNonNull(toAdd); - if (contains(toAdd)) { - throw new DuplicatePersonException(); - } - internalList.add(toAdd); - } - - /** - * Replaces the person {@code target} in the list with {@code editedPerson}. - * {@code target} must exist in the list. - * The person identity of {@code editedPerson} must not be the same as another existing person in the list. - */ - public void setPerson(Person target, Person editedPerson) { - requireAllNonNull(target, editedPerson); - - int index = internalList.indexOf(target); - if (index == -1) { - throw new PersonNotFoundException(); - } - - if (!target.isSamePerson(editedPerson) && contains(editedPerson)) { - throw new DuplicatePersonException(); - } - - internalList.set(index, editedPerson); - } - - /** - * Removes the equivalent person from the list. - * The person must exist in the list. - */ - public void remove(Person toRemove) { - requireNonNull(toRemove); - if (!internalList.remove(toRemove)) { - throw new PersonNotFoundException(); - } - } - - public void setPersons(UniquePersonList replacement) { - requireNonNull(replacement); - internalList.setAll(replacement.internalList); - } - - /** - * Replaces the contents of this list with {@code persons}. - * {@code persons} must not contain duplicate persons. - */ - public void setPersons(List persons) { - requireAllNonNull(persons); - if (!personsAreUnique(persons)) { - throw new DuplicatePersonException(); - } - - internalList.setAll(persons); - } - - /** - * Returns the backing list as an unmodifiable {@code ObservableList}. - */ - public ObservableList asUnmodifiableObservableList() { - return internalUnmodifiableList; - } - - @Override - public Iterator iterator() { - return internalList.iterator(); - } - - @Override - public boolean equals(Object other) { - return other == this // short circuit if same object - || (other instanceof UniquePersonList // instanceof handles nulls - && internalList.equals(((UniquePersonList) other).internalList)); - } - - @Override - public int hashCode() { - return internalList.hashCode(); - } - - /** - * Returns true if {@code persons} contains only unique persons. - */ - private boolean personsAreUnique(List persons) { - for (int i = 0; i < persons.size() - 1; i++) { - for (int j = i + 1; j < persons.size(); j++) { - if (persons.get(i).isSamePerson(persons.get(j))) { - return false; - } - } - } - return true; - } -} diff --git a/src/main/java/seedu/address/model/person/exceptions/DuplicatePersonException.java b/src/main/java/seedu/address/model/person/exceptions/DuplicatePersonException.java deleted file mode 100644 index d7290f59442..00000000000 --- a/src/main/java/seedu/address/model/person/exceptions/DuplicatePersonException.java +++ /dev/null @@ -1,11 +0,0 @@ -package seedu.address.model.person.exceptions; - -/** - * Signals that the operation will result in duplicate Persons (Persons are considered duplicates if they have the same - * identity). - */ -public class DuplicatePersonException extends RuntimeException { - public DuplicatePersonException() { - super("Operation would result in duplicate persons"); - } -} diff --git a/src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java b/src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java deleted file mode 100644 index fa764426ca7..00000000000 --- a/src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java +++ /dev/null @@ -1,6 +0,0 @@ -package seedu.address.model.person.exceptions; - -/** - * Signals that the operation is unable to find the specified person. - */ -public class PersonNotFoundException extends RuntimeException {} diff --git a/src/main/java/seedu/address/model/util/SampleDataUtil.java b/src/main/java/seedu/address/model/util/SampleDataUtil.java index 1806da4facf..d1802ae22f2 100644 --- a/src/main/java/seedu/address/model/util/SampleDataUtil.java +++ b/src/main/java/seedu/address/model/util/SampleDataUtil.java @@ -4,48 +4,42 @@ import java.util.Set; import java.util.stream.Collectors; -import seedu.address.model.AddressBook; -import seedu.address.model.ReadOnlyAddressBook; -import seedu.address.model.person.Address; -import seedu.address.model.person.Email; -import seedu.address.model.person.Name; -import seedu.address.model.person.Person; -import seedu.address.model.person.Phone; +import seedu.address.model.ExpenseList; +import seedu.address.model.ReadOnlyExpenseList; +import seedu.address.model.expense.Amount; +import seedu.address.model.expense.Date; +import seedu.address.model.expense.Expense; +import seedu.address.model.expense.Name; import seedu.address.model.tag.Tag; /** - * Contains utility methods for populating {@code AddressBook} with sample data. + * Contains utility methods for populating {@code ExpenseList} with sample data. */ public class SampleDataUtil { - public static Person[] getSamplePersons() { - return new Person[] { - new Person(new Name("Alex Yeoh"), new Phone("87438807"), new Email("alexyeoh@example.com"), - new Address("Blk 30 Geylang Street 29, #06-40"), - getTagSet("friends")), - new Person(new Name("Bernice Yu"), new Phone("99272758"), new Email("berniceyu@example.com"), - new Address("Blk 30 Lorong 3 Serangoon Gardens, #07-18"), - getTagSet("colleagues", "friends")), - new Person(new Name("Charlotte Oliveiro"), new Phone("93210283"), new Email("charlotte@example.com"), - new Address("Blk 11 Ang Mo Kio Street 74, #11-04"), - getTagSet("neighbours")), - new Person(new Name("David Li"), new Phone("91031282"), new Email("lidavid@example.com"), - new Address("Blk 436 Serangoon Gardens Street 26, #16-43"), - getTagSet("family")), - new Person(new Name("Irfan Ibrahim"), new Phone("92492021"), new Email("irfan@example.com"), - new Address("Blk 47 Tampines Street 20, #17-35"), - getTagSet("classmates")), - new Person(new Name("Roy Balakrishnan"), new Phone("92624417"), new Email("royb@example.com"), - new Address("Blk 45 Aljunied Street 85, #11-31"), - getTagSet("colleagues")) + + public static Expense[] getSampleExpenses() { + return new Expense[] { + new Expense(new Name("Coffee"), new Amount("$1.8"), new Date("1245", false), + getTagSet("food")), + new Expense(new Name("Textbook"), new Amount("$23.50"), new Date("930", false), + getTagSet("education", "school")), + new Expense(new Name("Earphone"), new Amount("$45"), new Date("10/12/2019 1800", false), + getTagSet("utility")), + new Expense(new Name("Hang out"), new Amount("$50"), new Date("15/12/2019 2100", false), + getTagSet("entertainment")), + new Expense(new Name("Travel to Paris"), new Amount("€850"), new Date("25/12/2019 800", false), + getTagSet("travel")), + new Expense(new Name("Gift for duke"), new Amount("$30"), new Date("1/11/2019", false), + getTagSet("relationship")) }; } - public static ReadOnlyAddressBook getSampleAddressBook() { - AddressBook sampleAb = new AddressBook(); - for (Person samplePerson : getSamplePersons()) { - sampleAb.addPerson(samplePerson); + public static ReadOnlyExpenseList getSampleExpenseList() { + ExpenseList sampleEl = new ExpenseList(); + for (Expense sampleExpense : getSampleExpenses()) { + sampleEl.addExpense(sampleExpense); } - return sampleAb; + return sampleEl; } /** @@ -53,8 +47,7 @@ public static ReadOnlyAddressBook getSampleAddressBook() { */ public static Set getTagSet(String... strings) { return Arrays.stream(strings) - .map(Tag::new) - .collect(Collectors.toSet()); + .map(Tag::new) + .collect(Collectors.toSet()); } - } diff --git a/src/main/java/seedu/address/storage/AddressBookStorage.java b/src/main/java/seedu/address/storage/AddressBookStorage.java deleted file mode 100644 index 4599182b3f9..00000000000 --- a/src/main/java/seedu/address/storage/AddressBookStorage.java +++ /dev/null @@ -1,45 +0,0 @@ -package seedu.address.storage; - -import java.io.IOException; -import java.nio.file.Path; -import java.util.Optional; - -import seedu.address.commons.exceptions.DataConversionException; -import seedu.address.model.ReadOnlyAddressBook; - -/** - * Represents a storage for {@link seedu.address.model.AddressBook}. - */ -public interface AddressBookStorage { - - /** - * Returns the file path of the data file. - */ - Path getAddressBookFilePath(); - - /** - * Returns AddressBook data as a {@link ReadOnlyAddressBook}. - * Returns {@code Optional.empty()} if storage file is not found. - * @throws DataConversionException if the data in storage is not in the expected format. - * @throws IOException if there was any problem when reading from the storage. - */ - Optional readAddressBook() throws DataConversionException, IOException; - - /** - * @see #getAddressBookFilePath() - */ - Optional readAddressBook(Path filePath) throws DataConversionException, IOException; - - /** - * Saves the given {@link ReadOnlyAddressBook} to the storage. - * @param addressBook cannot be null. - * @throws IOException if there was any problem writing to the file. - */ - void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException; - - /** - * @see #saveAddressBook(ReadOnlyAddressBook) - */ - void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) throws IOException; - -} diff --git a/src/main/java/seedu/address/storage/ExpenseListStorage.java b/src/main/java/seedu/address/storage/ExpenseListStorage.java new file mode 100644 index 00000000000..0a3fffd4513 --- /dev/null +++ b/src/main/java/seedu/address/storage/ExpenseListStorage.java @@ -0,0 +1,47 @@ +package seedu.address.storage; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.Optional; + +import seedu.address.commons.exceptions.DataConversionException; +import seedu.address.model.ExpenseList; +import seedu.address.model.ReadOnlyExpenseList; + +/** + * Represents a storage for {@link ExpenseList}. + */ +public interface ExpenseListStorage { + + /** + * Returns the file path of the data file. + */ + Path getExpenseListFilePath(); + + /** + * Returns ExpenseList data as a {@link ReadOnlyExpenseList}. + * Returns {@code Optional.empty()} if storage file is not found. + * + * @throws DataConversionException if the data in storage is not in the expected format. + * @throws IOException if there was any problem when reading from the storage. + */ + Optional readExpenseList() throws DataConversionException, IOException; + + /** + * @see #getExpenseListFilePath() + */ + Optional readExpenseList(Path filePath) throws DataConversionException, IOException; + + /** + * Saves the given {@link ReadOnlyExpenseList} to the storage. + * + * @param expenseList cannot be null. + * @throws IOException if there was any problem writing to the file. + */ + void saveExpenseList(ReadOnlyExpenseList expenseList) throws IOException; + + /** + * @see #saveExpenseList(ReadOnlyExpenseList) + */ + void saveExpenseList(ReadOnlyExpenseList expenseList, Path filePath) throws IOException; +} diff --git a/src/main/java/seedu/address/storage/JsonAdaptedExpense.java b/src/main/java/seedu/address/storage/JsonAdaptedExpense.java new file mode 100644 index 00000000000..8c8d796ca37 --- /dev/null +++ b/src/main/java/seedu/address/storage/JsonAdaptedExpense.java @@ -0,0 +1,96 @@ +package seedu.address.storage; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +import seedu.address.commons.exceptions.IllegalValueException; +import seedu.address.model.expense.Amount; +import seedu.address.model.expense.Date; +import seedu.address.model.expense.Expense; +import seedu.address.model.expense.Name; +import seedu.address.model.tag.Tag; + +/** + * Jackson-friendly version of {@link Expense}. + */ +class JsonAdaptedExpense { + + public static final String MISSING_FIELD_MESSAGE_FORMAT = "%s field of an expense is missing!"; + + private final String name; + private final String amount; + private final String date; + private final List tagged = new ArrayList<>(); + + /** + * Constructs a {@code JsonAdaptedExpense} with the given expense details. + */ + @JsonCreator + public JsonAdaptedExpense(@JsonProperty("name") String name, @JsonProperty("amount") String amount, + @JsonProperty("date") String date, + @JsonProperty("tagged") List tagged) { + this.name = name; + this.amount = amount; + this.date = date; + if (tagged != null) { + this.tagged.addAll(tagged); + } + } + + /** + * Converts a given {@code Expense} into this class for Jackson use. + */ + public JsonAdaptedExpense(Expense source) { + name = source.getName().fullName; + amount = source.getAmount().value; + date = source.getDate().rawValue; + tagged.addAll(source.getTags().stream() + .map(JsonAdaptedTag::new) + .collect(Collectors.toList())); + } + + /** + * Converts this Jackson-friendly adapted expense object into the model's {@code Expense} object. + * + * @throws IllegalValueException if there were any data constraints violated in the adapted expense. + */ + public Expense toModelType() throws IllegalValueException { + final List expenseTags = new ArrayList<>(); + for (JsonAdaptedTag tag : tagged) { + expenseTags.add(tag.toModelType()); + } + + if (name == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Name.class.getSimpleName())); + } + if (!Name.isValidName(name)) { + throw new IllegalValueException(Name.MESSAGE_CONSTRAINTS); + } + final Name modelName = new Name(name); + + if (amount == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Amount.class.getSimpleName())); + } + if (!Amount.isValidAmount(amount)) { + throw new IllegalValueException(Amount.MESSAGE_CONSTRAINTS); + } + final Amount modelAmount = new Amount(amount); + + if (date == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Date.class.getSimpleName())); + } + if (!Date.isValidDate(date)) { + throw new IllegalValueException(Date.MESSAGE_CONSTRAINTS); + } + final Date modelDate = new Date(date, true); + + final Set modelTags = new HashSet<>(expenseTags); + return new Expense(modelName, modelAmount, modelDate, modelTags); + } +} diff --git a/src/main/java/seedu/address/storage/JsonAdaptedPerson.java b/src/main/java/seedu/address/storage/JsonAdaptedPerson.java deleted file mode 100644 index a6321cec2ea..00000000000 --- a/src/main/java/seedu/address/storage/JsonAdaptedPerson.java +++ /dev/null @@ -1,109 +0,0 @@ -package seedu.address.storage; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; - -import seedu.address.commons.exceptions.IllegalValueException; -import seedu.address.model.person.Address; -import seedu.address.model.person.Email; -import seedu.address.model.person.Name; -import seedu.address.model.person.Person; -import seedu.address.model.person.Phone; -import seedu.address.model.tag.Tag; - -/** - * Jackson-friendly version of {@link Person}. - */ -class JsonAdaptedPerson { - - public static final String MISSING_FIELD_MESSAGE_FORMAT = "Person's %s field is missing!"; - - private final String name; - private final String phone; - private final String email; - private final String address; - private final List tagged = new ArrayList<>(); - - /** - * Constructs a {@code JsonAdaptedPerson} with the given person details. - */ - @JsonCreator - public JsonAdaptedPerson(@JsonProperty("name") String name, @JsonProperty("phone") String phone, - @JsonProperty("email") String email, @JsonProperty("address") String address, - @JsonProperty("tagged") List tagged) { - this.name = name; - this.phone = phone; - this.email = email; - this.address = address; - if (tagged != null) { - this.tagged.addAll(tagged); - } - } - - /** - * Converts a given {@code Person} into this class for Jackson use. - */ - public JsonAdaptedPerson(Person source) { - name = source.getName().fullName; - phone = source.getPhone().value; - email = source.getEmail().value; - address = source.getAddress().value; - tagged.addAll(source.getTags().stream() - .map(JsonAdaptedTag::new) - .collect(Collectors.toList())); - } - - /** - * Converts this Jackson-friendly adapted person object into the model's {@code Person} object. - * - * @throws IllegalValueException if there were any data constraints violated in the adapted person. - */ - public Person toModelType() throws IllegalValueException { - final List personTags = new ArrayList<>(); - for (JsonAdaptedTag tag : tagged) { - personTags.add(tag.toModelType()); - } - - if (name == null) { - throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Name.class.getSimpleName())); - } - if (!Name.isValidName(name)) { - throw new IllegalValueException(Name.MESSAGE_CONSTRAINTS); - } - final Name modelName = new Name(name); - - if (phone == null) { - throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Phone.class.getSimpleName())); - } - if (!Phone.isValidPhone(phone)) { - throw new IllegalValueException(Phone.MESSAGE_CONSTRAINTS); - } - final Phone modelPhone = new Phone(phone); - - if (email == null) { - throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Email.class.getSimpleName())); - } - if (!Email.isValidEmail(email)) { - throw new IllegalValueException(Email.MESSAGE_CONSTRAINTS); - } - final Email modelEmail = new Email(email); - - if (address == null) { - throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Address.class.getSimpleName())); - } - if (!Address.isValidAddress(address)) { - throw new IllegalValueException(Address.MESSAGE_CONSTRAINTS); - } - final Address modelAddress = new Address(address); - - final Set modelTags = new HashSet<>(personTags); - return new Person(modelName, modelPhone, modelEmail, modelAddress, modelTags); - } - -} diff --git a/src/main/java/seedu/address/storage/JsonAddressBookStorage.java b/src/main/java/seedu/address/storage/JsonExpenseListStorage.java similarity index 57% rename from src/main/java/seedu/address/storage/JsonAddressBookStorage.java rename to src/main/java/seedu/address/storage/JsonExpenseListStorage.java index dfab9daaa0d..6ee04add01a 100644 --- a/src/main/java/seedu/address/storage/JsonAddressBookStorage.java +++ b/src/main/java/seedu/address/storage/JsonExpenseListStorage.java @@ -12,47 +12,47 @@ import seedu.address.commons.exceptions.IllegalValueException; import seedu.address.commons.util.FileUtil; import seedu.address.commons.util.JsonUtil; -import seedu.address.model.ReadOnlyAddressBook; +import seedu.address.model.ReadOnlyExpenseList; /** - * A class to access AddressBook data stored as a json file on the hard disk. + * A class to access ExpenseList data stored as a json file on the hard disk. */ -public class JsonAddressBookStorage implements AddressBookStorage { +public class JsonExpenseListStorage implements ExpenseListStorage { - private static final Logger logger = LogsCenter.getLogger(JsonAddressBookStorage.class); + private static final Logger logger = LogsCenter.getLogger(JsonExpenseListStorage.class); private Path filePath; - public JsonAddressBookStorage(Path filePath) { + public JsonExpenseListStorage(Path filePath) { this.filePath = filePath; } - public Path getAddressBookFilePath() { + public Path getExpenseListFilePath() { return filePath; } @Override - public Optional readAddressBook() throws DataConversionException { - return readAddressBook(filePath); + public Optional readExpenseList() throws DataConversionException { + return readExpenseList(filePath); } /** - * Similar to {@link #readAddressBook()}. + * Similar to {@link #readExpenseList()}. * * @param filePath location of the data. Cannot be null. * @throws DataConversionException if the file is not in the correct format. */ - public Optional readAddressBook(Path filePath) throws DataConversionException { + public Optional readExpenseList(Path filePath) throws DataConversionException { requireNonNull(filePath); - Optional jsonAddressBook = JsonUtil.readJsonFile( - filePath, JsonSerializableAddressBook.class); - if (!jsonAddressBook.isPresent()) { + Optional jsonExpenseList = JsonUtil.readJsonFile( + filePath, JsonSerializableExpenseList.class); + if (!jsonExpenseList.isPresent()) { return Optional.empty(); } try { - return Optional.of(jsonAddressBook.get().toModelType()); + return Optional.of(jsonExpenseList.get().toModelType()); } catch (IllegalValueException ive) { logger.info("Illegal values found in " + filePath + ": " + ive.getMessage()); throw new DataConversionException(ive); @@ -60,21 +60,21 @@ public Optional readAddressBook(Path filePath) throws DataC } @Override - public void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException { - saveAddressBook(addressBook, filePath); + public void saveExpenseList(ReadOnlyExpenseList addressBook) throws IOException { + saveExpenseList(addressBook, filePath); } /** - * Similar to {@link #saveAddressBook(ReadOnlyAddressBook)}. + * Similar to {@link #saveExpenseList(ReadOnlyExpenseList)}. * * @param filePath location of the data. Cannot be null. */ - public void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) throws IOException { - requireNonNull(addressBook); + public void saveExpenseList(ReadOnlyExpenseList expenseList, Path filePath) throws IOException { + requireNonNull(expenseList); requireNonNull(filePath); FileUtil.createIfMissing(filePath); - JsonUtil.saveJsonFile(new JsonSerializableAddressBook(addressBook), filePath); + JsonUtil.saveJsonFile(new JsonSerializableExpenseList(expenseList), filePath); } } diff --git a/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java b/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java deleted file mode 100644 index 5efd834091d..00000000000 --- a/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java +++ /dev/null @@ -1,60 +0,0 @@ -package seedu.address.storage; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonRootName; - -import seedu.address.commons.exceptions.IllegalValueException; -import seedu.address.model.AddressBook; -import seedu.address.model.ReadOnlyAddressBook; -import seedu.address.model.person.Person; - -/** - * An Immutable AddressBook that is serializable to JSON format. - */ -@JsonRootName(value = "addressbook") -class JsonSerializableAddressBook { - - public static final String MESSAGE_DUPLICATE_PERSON = "Persons list contains duplicate person(s)."; - - private final List persons = new ArrayList<>(); - - /** - * Constructs a {@code JsonSerializableAddressBook} with the given persons. - */ - @JsonCreator - public JsonSerializableAddressBook(@JsonProperty("persons") List persons) { - this.persons.addAll(persons); - } - - /** - * Converts a given {@code ReadOnlyAddressBook} into this class for Jackson use. - * - * @param source future changes to this will not affect the created {@code JsonSerializableAddressBook}. - */ - public JsonSerializableAddressBook(ReadOnlyAddressBook source) { - persons.addAll(source.getPersonList().stream().map(JsonAdaptedPerson::new).collect(Collectors.toList())); - } - - /** - * Converts this address book into the model's {@code AddressBook} object. - * - * @throws IllegalValueException if there were any data constraints violated. - */ - public AddressBook toModelType() throws IllegalValueException { - AddressBook addressBook = new AddressBook(); - for (JsonAdaptedPerson jsonAdaptedPerson : persons) { - Person person = jsonAdaptedPerson.toModelType(); - if (addressBook.hasPerson(person)) { - throw new IllegalValueException(MESSAGE_DUPLICATE_PERSON); - } - addressBook.addPerson(person); - } - return addressBook; - } - -} diff --git a/src/main/java/seedu/address/storage/JsonSerializableExpenseList.java b/src/main/java/seedu/address/storage/JsonSerializableExpenseList.java new file mode 100644 index 00000000000..bc9034f4e5c --- /dev/null +++ b/src/main/java/seedu/address/storage/JsonSerializableExpenseList.java @@ -0,0 +1,59 @@ +package seedu.address.storage; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonRootName; + +import seedu.address.commons.exceptions.IllegalValueException; +import seedu.address.model.ExpenseList; +import seedu.address.model.ReadOnlyExpenseList; +import seedu.address.model.expense.Expense; + +/** + * An Immutable ExpenseList that is serializable to JSON format. + */ +@JsonRootName(value = "expenselist") +class JsonSerializableExpenseList { + + public static final String MESSAGE_DUPLICATE_EXPENSE = "Expenses list contains duplicate expense(s)."; + + private final List expenses = new ArrayList<>(); + + /** + * Constructs a {@code JsonSerializableExpenseList} with the given expenses. + */ + @JsonCreator + public JsonSerializableExpenseList(@JsonProperty("expenses") List expenses) { + this.expenses.addAll(expenses); + } + + /** + * Converts a given {@code ReadOnlyExpenseList} into this class for Jackson use. + * + * @param source future changes to this will not affect the created {@code JsonSerializableExpenseList}. + */ + public JsonSerializableExpenseList(ReadOnlyExpenseList source) { + expenses.addAll(source.getExpenseList().stream().map(JsonAdaptedExpense::new).collect(Collectors.toList())); + } + + /** + * Converts this address book into the model's {@code ExpenseList} object. + * + * @throws IllegalValueException if there were any data constraints violated. + */ + public ExpenseList toModelType() throws IllegalValueException { + ExpenseList expenseList = new ExpenseList(); + for (JsonAdaptedExpense jsonAdaptedExpense : expenses) { + Expense expense = jsonAdaptedExpense.toModelType(); + if (expenseList.hasExpense(expense)) { + throw new IllegalValueException(MESSAGE_DUPLICATE_EXPENSE); + } + expenseList.addExpense(expense); + } + return expenseList; + } +} diff --git a/src/main/java/seedu/address/storage/Storage.java b/src/main/java/seedu/address/storage/Storage.java index beda8bd9f11..810a4445012 100644 --- a/src/main/java/seedu/address/storage/Storage.java +++ b/src/main/java/seedu/address/storage/Storage.java @@ -5,14 +5,14 @@ import java.util.Optional; import seedu.address.commons.exceptions.DataConversionException; -import seedu.address.model.ReadOnlyAddressBook; +import seedu.address.model.ReadOnlyExpenseList; import seedu.address.model.ReadOnlyUserPrefs; import seedu.address.model.UserPrefs; /** * API of the Storage component */ -public interface Storage extends AddressBookStorage, UserPrefsStorage { +public interface Storage extends ExpenseListStorage, UserPrefsStorage { @Override Optional readUserPrefs() throws DataConversionException, IOException; @@ -21,12 +21,12 @@ public interface Storage extends AddressBookStorage, UserPrefsStorage { void saveUserPrefs(ReadOnlyUserPrefs userPrefs) throws IOException; @Override - Path getAddressBookFilePath(); + Path getExpenseListFilePath(); @Override - Optional readAddressBook() throws DataConversionException, IOException; + Optional readExpenseList() throws DataConversionException, IOException; @Override - void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException; + void saveExpenseList(ReadOnlyExpenseList addressBook) throws IOException; } diff --git a/src/main/java/seedu/address/storage/StorageManager.java b/src/main/java/seedu/address/storage/StorageManager.java index e4f452b6cbf..72ea17c6048 100644 --- a/src/main/java/seedu/address/storage/StorageManager.java +++ b/src/main/java/seedu/address/storage/StorageManager.java @@ -7,23 +7,23 @@ import seedu.address.commons.core.LogsCenter; import seedu.address.commons.exceptions.DataConversionException; -import seedu.address.model.ReadOnlyAddressBook; +import seedu.address.model.ReadOnlyExpenseList; import seedu.address.model.ReadOnlyUserPrefs; import seedu.address.model.UserPrefs; /** - * Manages storage of AddressBook data in local storage. + * Manages storage of ExpenseList data in local storage. */ public class StorageManager implements Storage { private static final Logger logger = LogsCenter.getLogger(StorageManager.class); - private AddressBookStorage addressBookStorage; + private ExpenseListStorage expenseListStorage; private UserPrefsStorage userPrefsStorage; - public StorageManager(AddressBookStorage addressBookStorage, UserPrefsStorage userPrefsStorage) { + public StorageManager(ExpenseListStorage expenseListStorage, UserPrefsStorage userPrefsStorage) { super(); - this.addressBookStorage = addressBookStorage; + this.expenseListStorage = expenseListStorage; this.userPrefsStorage = userPrefsStorage; } @@ -45,33 +45,33 @@ public void saveUserPrefs(ReadOnlyUserPrefs userPrefs) throws IOException { } - // ================ AddressBook methods ============================== + // ================ ExpenseList methods ============================== @Override - public Path getAddressBookFilePath() { - return addressBookStorage.getAddressBookFilePath(); + public Path getExpenseListFilePath() { + return expenseListStorage.getExpenseListFilePath(); } @Override - public Optional readAddressBook() throws DataConversionException, IOException { - return readAddressBook(addressBookStorage.getAddressBookFilePath()); + public Optional readExpenseList() throws DataConversionException, IOException { + return readExpenseList(expenseListStorage.getExpenseListFilePath()); } @Override - public Optional readAddressBook(Path filePath) throws DataConversionException, IOException { + public Optional readExpenseList(Path filePath) throws DataConversionException, IOException { logger.fine("Attempting to read data from file: " + filePath); - return addressBookStorage.readAddressBook(filePath); + return expenseListStorage.readExpenseList(filePath); } @Override - public void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException { - saveAddressBook(addressBook, addressBookStorage.getAddressBookFilePath()); + public void saveExpenseList(ReadOnlyExpenseList expenseList) throws IOException { + saveExpenseList(expenseList, expenseListStorage.getExpenseListFilePath()); } @Override - public void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) throws IOException { + public void saveExpenseList(ReadOnlyExpenseList expenseList, Path filePath) throws IOException { logger.fine("Attempting to write to data file: " + filePath); - addressBookStorage.saveAddressBook(addressBook, filePath); + expenseListStorage.saveExpenseList(expenseList, filePath); } } diff --git a/src/main/java/seedu/address/ui/PersonCard.java b/src/main/java/seedu/address/ui/ExpenseCard.java similarity index 52% rename from src/main/java/seedu/address/ui/PersonCard.java rename to src/main/java/seedu/address/ui/ExpenseCard.java index 0684b088868..bb5607feb08 100644 --- a/src/main/java/seedu/address/ui/PersonCard.java +++ b/src/main/java/seedu/address/ui/ExpenseCard.java @@ -7,24 +7,24 @@ import javafx.scene.layout.FlowPane; import javafx.scene.layout.HBox; import javafx.scene.layout.Region; -import seedu.address.model.person.Person; +import seedu.address.model.expense.Expense; /** - * An UI component that displays information of a {@code Person}. + * An UI component that displays information of a {@code Expense}. */ -public class PersonCard extends UiPart { +public class ExpenseCard extends UiPart { - private static final String FXML = "PersonListCard.fxml"; + private static final String FXML = "ExpenseListCard.fxml"; /** * Note: Certain keywords such as "location" and "resources" are reserved keywords in JavaFX. * As a consequence, UI elements' variable names cannot be set to such keywords * or an exception will be thrown by JavaFX during runtime. * - * @see The issue on AddressBook level 4 + * @see The issue on ExpenseList level 4 */ - public final Person person; + public final Expense expense; @FXML private HBox cardPane; @@ -33,25 +33,22 @@ public class PersonCard extends UiPart { @FXML private Label id; @FXML - private Label phone; + private Label amount; @FXML - private Label address; - @FXML - private Label email; + private Label date; @FXML private FlowPane tags; - public PersonCard(Person person, int displayedIndex) { + public ExpenseCard(Expense expense, int displayedIndex) { super(FXML); - this.person = person; + this.expense = expense; id.setText(displayedIndex + ". "); - name.setText(person.getName().fullName); - phone.setText(person.getPhone().value); - address.setText(person.getAddress().value); - email.setText(person.getEmail().value); - person.getTags().stream() - .sorted(Comparator.comparing(tag -> tag.tagName)) - .forEach(tag -> tags.getChildren().add(new Label(tag.tagName))); + name.setText(expense.getName().fullName); + amount.setText(expense.getAmount().value); + date.setText(expense.getDate().value); + expense.getTags().stream() + .sorted(Comparator.comparing(tag -> tag.tagName)) + .forEach(tag -> tags.getChildren().add(new Label(tag.tagName))); } @Override @@ -62,13 +59,13 @@ public boolean equals(Object other) { } // instanceof handles nulls - if (!(other instanceof PersonCard)) { + if (!(other instanceof ExpenseCard)) { return false; } // state check - PersonCard card = (PersonCard) other; + ExpenseCard card = (ExpenseCard) other; return id.getText().equals(card.id.getText()) - && person.equals(card.person); + && expense.equals(card.expense); } } diff --git a/src/main/java/seedu/address/ui/ExpenseListPanel.java b/src/main/java/seedu/address/ui/ExpenseListPanel.java new file mode 100644 index 00000000000..5e2c5425c53 --- /dev/null +++ b/src/main/java/seedu/address/ui/ExpenseListPanel.java @@ -0,0 +1,47 @@ +package seedu.address.ui; + +import java.util.logging.Logger; + +import javafx.collections.ObservableList; +import javafx.fxml.FXML; +import javafx.scene.control.ListCell; +import javafx.scene.control.ListView; +import javafx.scene.layout.Region; +import seedu.address.commons.core.LogsCenter; +import seedu.address.model.expense.Expense; + +/** + * Panel containing the list of expenses. + */ +public class ExpenseListPanel extends UiPart { + + private static final String FXML = "ExpenseListPanel.fxml"; + private final Logger logger = LogsCenter.getLogger(ExpenseListPanel.class); + + @FXML + private ListView expenseListView; + + public ExpenseListPanel(ObservableList expenseList) { + super(FXML); + expenseListView.setItems(expenseList); + expenseListView.setCellFactory(listView -> new ExpenseListViewCell()); + } + + /** + * Custom {@code ListCell} that displays the graphics of a {@code Expense} using a {@code ExpenseCard}. + */ + class ExpenseListViewCell extends ListCell { + + @Override + protected void updateItem(Expense expense, boolean empty) { + super.updateItem(expense, empty); + + if (empty || expense == null) { + setGraphic(null); + setText(null); + } else { + setGraphic(new ExpenseCard(expense, getIndex() + 1).getRoot()); + } + } + } +} diff --git a/src/main/java/seedu/address/ui/MainWindow.java b/src/main/java/seedu/address/ui/MainWindow.java index 90bbf11de97..14945223f9f 100644 --- a/src/main/java/seedu/address/ui/MainWindow.java +++ b/src/main/java/seedu/address/ui/MainWindow.java @@ -31,7 +31,7 @@ public class MainWindow extends UiPart { private Logic logic; // Independent Ui parts residing in this Ui container - private PersonListPanel personListPanel; + private ExpenseListPanel expenseListPanel; private ResultDisplay resultDisplay; private HelpWindow helpWindow; @@ -42,7 +42,7 @@ public class MainWindow extends UiPart { private MenuItem helpMenuItem; @FXML - private StackPane personListPanelPlaceholder; + private StackPane expenseListPanelPlaceholder; @FXML private StackPane resultDisplayPlaceholder; @@ -107,13 +107,13 @@ private void setAccelerator(MenuItem menuItem, KeyCombination keyCombination) { * Fills up all the placeholders of this window. */ void fillInnerParts() { - personListPanel = new PersonListPanel(logic.getFilteredPersonList()); - personListPanelPlaceholder.getChildren().add(personListPanel.getRoot()); + expenseListPanel = new ExpenseListPanel(logic.getFilteredExpenseList()); + expenseListPanelPlaceholder.getChildren().add(expenseListPanel.getRoot()); resultDisplay = new ResultDisplay(); resultDisplayPlaceholder.getChildren().add(resultDisplay.getRoot()); - StatusBarFooter statusBarFooter = new StatusBarFooter(logic.getAddressBookFilePath()); + StatusBarFooter statusBarFooter = new StatusBarFooter(logic.getExpenseListFilePath()); statusbarPlaceholder.getChildren().add(statusBarFooter.getRoot()); CommandBox commandBox = new CommandBox(this::executeCommand); @@ -160,8 +160,8 @@ private void handleExit() { primaryStage.hide(); } - public PersonListPanel getPersonListPanel() { - return personListPanel; + public ExpenseListPanel getExpenseListPanel() { + return expenseListPanel; } /** diff --git a/src/main/java/seedu/address/ui/PersonListPanel.java b/src/main/java/seedu/address/ui/PersonListPanel.java deleted file mode 100644 index 1328917096e..00000000000 --- a/src/main/java/seedu/address/ui/PersonListPanel.java +++ /dev/null @@ -1,46 +0,0 @@ -package seedu.address.ui; - -import java.util.logging.Logger; - -import javafx.collections.ObservableList; -import javafx.fxml.FXML; -import javafx.scene.control.ListCell; -import javafx.scene.control.ListView; -import javafx.scene.layout.Region; -import seedu.address.commons.core.LogsCenter; -import seedu.address.model.person.Person; - -/** - * Panel containing the list of persons. - */ -public class PersonListPanel extends UiPart { - private static final String FXML = "PersonListPanel.fxml"; - private final Logger logger = LogsCenter.getLogger(PersonListPanel.class); - - @FXML - private ListView personListView; - - public PersonListPanel(ObservableList personList) { - super(FXML); - personListView.setItems(personList); - personListView.setCellFactory(listView -> new PersonListViewCell()); - } - - /** - * Custom {@code ListCell} that displays the graphics of a {@code Person} using a {@code PersonCard}. - */ - class PersonListViewCell extends ListCell { - @Override - protected void updateItem(Person person, boolean empty) { - super.updateItem(person, empty); - - if (empty || person == null) { - setGraphic(null); - setText(null); - } else { - setGraphic(new PersonCard(person, getIndex() + 1).getRoot()); - } - } - } - -} diff --git a/src/main/java/seedu/address/ui/UiManager.java b/src/main/java/seedu/address/ui/UiManager.java index 876621d79b9..ece4873e7c6 100644 --- a/src/main/java/seedu/address/ui/UiManager.java +++ b/src/main/java/seedu/address/ui/UiManager.java @@ -20,7 +20,7 @@ public class UiManager implements Ui { public static final String ALERT_DIALOG_PANE_FIELD_ID = "alertDialogPane"; private static final Logger logger = LogsCenter.getLogger(UiManager.class); - private static final String ICON_APPLICATION = "/images/address_book_32.png"; + private static final String ICON_APPLICATION = "/images/expense_list_32.png"; private Logic logic; private MainWindow mainWindow; diff --git a/src/main/resources/images/address_book_32.png b/src/main/resources/images/expense_list_32.png similarity index 100% rename from src/main/resources/images/address_book_32.png rename to src/main/resources/images/expense_list_32.png diff --git a/src/main/resources/view/PersonListCard.fxml b/src/main/resources/view/ExpenseListCard.fxml similarity index 84% rename from src/main/resources/view/PersonListCard.fxml rename to src/main/resources/view/ExpenseListCard.fxml index f08ea32ad55..3fe94bbd9e7 100644 --- a/src/main/resources/view/PersonListCard.fxml +++ b/src/main/resources/view/ExpenseListCard.fxml @@ -28,9 +28,8 @@