From 208a6e0a1bb243caaee3d442c5a49bdd74a89530 Mon Sep 17 00:00:00 2001 From: khiayi <33336624+khiayi@users.noreply.github.com> Date: Thu, 8 Mar 2018 00:39:37 +0800 Subject: [PATCH 01/98] Updated UserGuide and DeveloperGuide --- docs/DeveloperGuide.adoc | 2 +- docs/UserGuide.adoc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/DeveloperGuide.adoc b/docs/DeveloperGuide.adoc index 1733af113b29..ad8eeea7873d 100644 --- a/docs/DeveloperGuide.adoc +++ b/docs/DeveloperGuide.adoc @@ -10,7 +10,7 @@ ifdef::env-github[] :tip-caption: :bulb: :note-caption: :information_source: endif::[] -:repoURL: https://github.com/se-edu/addressbook-level4/tree/master +:repoURL: https://github.com/khiayi/addressbook-level4 By: `Team SE-EDU`      Since: `Jun 2016`      Licence: `MIT` diff --git a/docs/UserGuide.adoc b/docs/UserGuide.adoc index 74248917e438..27029c202b5b 100644 --- a/docs/UserGuide.adoc +++ b/docs/UserGuide.adoc @@ -11,7 +11,7 @@ ifdef::env-github[] :tip-caption: :bulb: :note-caption: :information_source: endif::[] -:repoURL: https://github.com/se-edu/addressbook-level4 +:repoURL: https://github.com/khiayi/addressbook-level4 By: `Team SE-EDU` Since: `Jun 2016` Licence: `MIT` From 9af1675365b8c5030904fcc02cb96901e1bc3e29 Mon Sep 17 00:00:00 2001 From: khiayi <33336624+khiayi@users.noreply.github.com> Date: Thu, 8 Mar 2018 00:56:11 +0800 Subject: [PATCH 02/98] Updated CI link in README.adoc --- README.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.adoc b/README.adoc index 03eff3a4d191..3d387f7a8fb7 100644 --- a/README.adoc +++ b/README.adoc @@ -1,7 +1,7 @@ = Address Book (Level 4) ifdef::env-github,env-browser[:relfileprefix: docs/] -https://travis-ci.org/se-edu/addressbook-level4[image:https://travis-ci.org/se-edu/addressbook-level4.svg?branch=master[Build Status]] +https://travis-ci.org/khiayi/addressbook-level4[image:https://travis-ci.org/khiayi/addressbook-level4.svg?branch=master[Build Status]] https://ci.appveyor.com/project/damithc/addressbook-level4[image:https://ci.appveyor.com/api/projects/status/3boko2x2vr5cc3w2?svg=true[Build status]] https://coveralls.io/github/se-edu/addressbook-level4?branch=master[image:https://coveralls.io/repos/github/se-edu/addressbook-level4/badge.svg?branch=master[Coverage Status]] https://www.codacy.com/app/damith/addressbook-level4?utm_source=github.com&utm_medium=referral&utm_content=se-edu/addressbook-level4&utm_campaign=Badge_Grade[image:https://api.codacy.com/project/badge/Grade/fc0b7775cf7f4fdeaf08776f3d8e364a[Codacy Badge]] From e6038103355e1bed3363c4a7c2c44b4b068937e9 Mon Sep 17 00:00:00 2001 From: khiayi <33336624+khiayi@users.noreply.github.com> Date: Thu, 8 Mar 2018 01:01:40 +0800 Subject: [PATCH 03/98] Updated coveralls link in README.adoc --- README.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.adoc b/README.adoc index 3d387f7a8fb7..93bf2ac0cdf8 100644 --- a/README.adoc +++ b/README.adoc @@ -3,7 +3,7 @@ ifdef::env-github,env-browser[:relfileprefix: docs/] https://travis-ci.org/khiayi/addressbook-level4[image:https://travis-ci.org/khiayi/addressbook-level4.svg?branch=master[Build Status]] https://ci.appveyor.com/project/damithc/addressbook-level4[image:https://ci.appveyor.com/api/projects/status/3boko2x2vr5cc3w2?svg=true[Build status]] -https://coveralls.io/github/se-edu/addressbook-level4?branch=master[image:https://coveralls.io/repos/github/se-edu/addressbook-level4/badge.svg?branch=master[Coverage Status]] +https://coveralls.io/github/khiayi/addressbook-level4?branch=master[image:https://coveralls.io/repos/github/khiayi/addressbook-level4/badge.svg?branch=master[Coverage Status]] https://www.codacy.com/app/damith/addressbook-level4?utm_source=github.com&utm_medium=referral&utm_content=se-edu/addressbook-level4&utm_campaign=Badge_Grade[image:https://api.codacy.com/project/badge/Grade/fc0b7775cf7f4fdeaf08776f3d8e364a[Codacy Badge]] https://gitter.im/se-edu/Lobby[image:https://badges.gitter.im/se-edu/Lobby.svg[Gitter chat]] From e363f3b25916b20ecddab17e2acdb5d9eec708d6 Mon Sep 17 00:00:00 2001 From: khiayi <33336624+khiayi@users.noreply.github.com> Date: Thu, 8 Mar 2018 01:07:08 +0800 Subject: [PATCH 04/98] Remove Codacy Badge from README.adoc --- README.adoc | 1 - 1 file changed, 1 deletion(-) diff --git a/README.adoc b/README.adoc index 93bf2ac0cdf8..a04a58a8487a 100644 --- a/README.adoc +++ b/README.adoc @@ -4,7 +4,6 @@ ifdef::env-github,env-browser[:relfileprefix: docs/] https://travis-ci.org/khiayi/addressbook-level4[image:https://travis-ci.org/khiayi/addressbook-level4.svg?branch=master[Build Status]] https://ci.appveyor.com/project/damithc/addressbook-level4[image:https://ci.appveyor.com/api/projects/status/3boko2x2vr5cc3w2?svg=true[Build status]] https://coveralls.io/github/khiayi/addressbook-level4?branch=master[image:https://coveralls.io/repos/github/khiayi/addressbook-level4/badge.svg?branch=master[Coverage Status]] -https://www.codacy.com/app/damith/addressbook-level4?utm_source=github.com&utm_medium=referral&utm_content=se-edu/addressbook-level4&utm_campaign=Badge_Grade[image:https://api.codacy.com/project/badge/Grade/fc0b7775cf7f4fdeaf08776f3d8e364a[Codacy Badge]] https://gitter.im/se-edu/Lobby[image:https://badges.gitter.im/se-edu/Lobby.svg[Gitter chat]] ifdef::env-github[] From 54394e68123534da5b2928f22fe6132879d7ca59 Mon Sep 17 00:00:00 2001 From: khiayi <33336624+khiayi@users.noreply.github.com> Date: Thu, 8 Mar 2018 01:26:29 +0800 Subject: [PATCH 05/98] UserGuide.adoc: Updated repo URL --- docs/UserGuide.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UserGuide.adoc b/docs/UserGuide.adoc index 27029c202b5b..ee27161b4b9e 100644 --- a/docs/UserGuide.adoc +++ b/docs/UserGuide.adoc @@ -11,7 +11,7 @@ ifdef::env-github[] :tip-caption: :bulb: :note-caption: :information_source: endif::[] -:repoURL: https://github.com/khiayi/addressbook-level4 +:repoURL: https://github.com/khiayi/addressbook-level4/tree/master By: `Team SE-EDU` Since: `Jun 2016` Licence: `MIT` From 6c027f5239b9c9b9c8e9ad6d3adc1a2ce8c3a1fb Mon Sep 17 00:00:00 2001 From: Khia Yi <33336624+khiayi@users.noreply.github.com> Date: Thu, 8 Mar 2018 16:18:10 +0800 Subject: [PATCH 06/98] DeveloperGuide.adoc and UserGuide.adoc: Updated Organisation URL --- docs/DeveloperGuide.adoc | 2 +- docs/UserGuide.adoc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/DeveloperGuide.adoc b/docs/DeveloperGuide.adoc index ad8eeea7873d..facfda8daa75 100644 --- a/docs/DeveloperGuide.adoc +++ b/docs/DeveloperGuide.adoc @@ -10,7 +10,7 @@ ifdef::env-github[] :tip-caption: :bulb: :note-caption: :information_source: endif::[] -:repoURL: https://github.com/khiayi/addressbook-level4 +:repoURL: https://github.com/CS2103JAN2018-T16-B1/addressbook-level4 By: `Team SE-EDU`      Since: `Jun 2016`      Licence: `MIT` diff --git a/docs/UserGuide.adoc b/docs/UserGuide.adoc index ee27161b4b9e..0baecddca50c 100644 --- a/docs/UserGuide.adoc +++ b/docs/UserGuide.adoc @@ -11,7 +11,7 @@ ifdef::env-github[] :tip-caption: :bulb: :note-caption: :information_source: endif::[] -:repoURL: https://github.com/khiayi/addressbook-level4/tree/master +:repoURL: https://github.com/CS2103JAN2018-T16-B1/addressbook-level4 By: `Team SE-EDU` Since: `Jun 2016` Licence: `MIT` From b11613a9e71c4fe2285a0aa8d317de005de0970b Mon Sep 17 00:00:00 2001 From: Qiu Haohao Date: Thu, 15 Mar 2018 13:10:08 +0800 Subject: [PATCH 07/98] Define interface for authentication --- src/main/java/seedu/address/model/Model.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java index 4a6079ce0199..1c897af2ebec 100644 --- a/src/main/java/seedu/address/model/Model.java +++ b/src/main/java/seedu/address/model/Model.java @@ -14,6 +14,10 @@ public interface Model { /** {@code Predicate} that always evaluate to true */ Predicate PREDICATE_SHOW_ALL_PERSONS = unused -> true; + int PRIVILEGE_LEVEL_GUEST = 0; + int PRIVILEGE_LEVEL_STUDENT = 1; + int PRIVILEGE_LEVEL_LIBRARIAN = 2; + /** Clears existing backing model and replaces with the provided new data. */ void resetData(ReadOnlyAddressBook newData); @@ -45,4 +49,10 @@ void updatePerson(Person target, Person editedPerson) */ void updateFilteredPersonList(Predicate predicate); + int authenticate(String username, String password); + + void logout(); + + int getPrivilegeLevel(); + } From c1509e57cd5e7b4767c1a1337d0a833921e6df31 Mon Sep 17 00:00:00 2001 From: Qiu Haohao Date: Thu, 15 Mar 2018 13:10:30 +0800 Subject: [PATCH 08/98] Implemented authentication --- .../seedu/address/model/ModelManager.java | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index 22a7d0eb3f4d..b084c573f81d 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -23,8 +23,11 @@ public class ModelManager extends ComponentManager implements Model { private static final Logger logger = LogsCenter.getLogger(ModelManager.class); + private final AddressBook addressBook; private final FilteredList filteredPersons; + private int privilegeLevel; + /** * Initializes a ModelManager with the given addressBook and userPrefs. @@ -37,6 +40,7 @@ public ModelManager(ReadOnlyAddressBook addressBook, UserPrefs userPrefs) { this.addressBook = new AddressBook(addressBook); filteredPersons = new FilteredList<>(this.addressBook.getPersonList()); + this.privilegeLevel = PRIVILEGE_LEVEL_GUEST; } public ModelManager() { @@ -98,6 +102,55 @@ public void updateFilteredPersonList(Predicate predicate) { filteredPersons.setPredicate(predicate); } + @Override + public int authenticate(String username, String password) { + if (isStudent(username,password)){ + setPrivilegeLevel(PRIVILEGE_LEVEL_STUDENT); + return PRIVILEGE_LEVEL_STUDENT; + } + if (isLibrarian(username,password)){ + setPrivilegeLevel(PRIVILEGE_LEVEL_LIBRARIAN); + return PRIVILEGE_LEVEL_LIBRARIAN; + } + //if not found + return PRIVILEGE_LEVEL_GUEST; + } + + @Override + public void logout() { + setPrivilegeLevel(PRIVILEGE_LEVEL_GUEST); + } + + @Override + public int getPrivilegeLevel() { + return this.privilegeLevel; + } + + + private boolean isStudent(String username, String password) { + //This is temporary before we add in account database + if (username == "student" && password == "student"){ + return true; + } + else{ + return false; + } + } + + private boolean isLibrarian(String username, String password) { + //This is temporary before we add in account database + if (username == "admin" && password == "admin"){ + return true; + } + else{ + return false; + } + } + + private void setPrivilegeLevel(int level) { + this.privilegeLevel = level; + } + @Override public boolean equals(Object obj) { // short circuit if same object From 164cdc37b417ca53184339913ce7d12d1f16df5d Mon Sep 17 00:00:00 2001 From: Qiu Haohao Date: Thu, 15 Mar 2018 13:19:21 +0800 Subject: [PATCH 09/98] Add privilege levels to commands --- src/main/java/seedu/address/logic/commands/AddCommand.java | 3 +++ src/main/java/seedu/address/logic/commands/ClearCommand.java | 3 ++- src/main/java/seedu/address/logic/commands/DeleteCommand.java | 3 +++ src/main/java/seedu/address/logic/commands/EditCommand.java | 3 +++ src/main/java/seedu/address/logic/commands/ExitCommand.java | 3 +++ src/main/java/seedu/address/logic/commands/FindCommand.java | 3 +++ src/main/java/seedu/address/logic/commands/HelpCommand.java | 3 +++ src/main/java/seedu/address/logic/commands/HistoryCommand.java | 1 + src/main/java/seedu/address/logic/commands/ListCommand.java | 3 +++ src/main/java/seedu/address/logic/commands/RedoCommand.java | 2 ++ src/main/java/seedu/address/logic/commands/SelectCommand.java | 3 +++ src/main/java/seedu/address/logic/commands/UndoCommand.java | 2 ++ .../java/seedu/address/logic/commands/UndoableCommand.java | 3 +++ 13 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/address/logic/commands/AddCommand.java b/src/main/java/seedu/address/logic/commands/AddCommand.java index c334710c0ea3..4edf1865b57b 100644 --- a/src/main/java/seedu/address/logic/commands/AddCommand.java +++ b/src/main/java/seedu/address/logic/commands/AddCommand.java @@ -8,6 +8,7 @@ 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.person.exceptions.DuplicatePersonException; @@ -36,6 +37,8 @@ public class AddCommand extends UndoableCommand { 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 int PRIVILEGE_LEVEL = Model.PRIVILEGE_LEVEL_LIBRARIAN; + private final Person toAdd; /** diff --git a/src/main/java/seedu/address/logic/commands/ClearCommand.java b/src/main/java/seedu/address/logic/commands/ClearCommand.java index ceeb7ba913c6..a55f04e89717 100644 --- a/src/main/java/seedu/address/logic/commands/ClearCommand.java +++ b/src/main/java/seedu/address/logic/commands/ClearCommand.java @@ -3,6 +3,7 @@ import static java.util.Objects.requireNonNull; import seedu.address.model.AddressBook; +import seedu.address.model.Model; /** * Clears the address book. @@ -11,7 +12,7 @@ public class ClearCommand extends UndoableCommand { public static final String COMMAND_WORD = "clear"; public static final String MESSAGE_SUCCESS = "Address book has been cleared!"; - + public static final int PRIVILEGE_LEVEL = Model.PRIVILEGE_LEVEL_LIBRARIAN; @Override public CommandResult executeUndoableCommand() { diff --git a/src/main/java/seedu/address/logic/commands/DeleteCommand.java b/src/main/java/seedu/address/logic/commands/DeleteCommand.java index b539d240001a..b35a9efc2f0b 100644 --- a/src/main/java/seedu/address/logic/commands/DeleteCommand.java +++ b/src/main/java/seedu/address/logic/commands/DeleteCommand.java @@ -8,6 +8,7 @@ import seedu.address.commons.core.Messages; 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.person.exceptions.PersonNotFoundException; @@ -25,6 +26,8 @@ public class DeleteCommand extends UndoableCommand { public static final String MESSAGE_DELETE_PERSON_SUCCESS = "Deleted Person: %1$s"; + public static final int PRIVILEGE_LEVEL = Model.PRIVILEGE_LEVEL_LIBRARIAN; + private final Index targetIndex; private Person personToDelete; diff --git a/src/main/java/seedu/address/logic/commands/EditCommand.java b/src/main/java/seedu/address/logic/commands/EditCommand.java index e6c3a3e034bc..70de744aa505 100644 --- a/src/main/java/seedu/address/logic/commands/EditCommand.java +++ b/src/main/java/seedu/address/logic/commands/EditCommand.java @@ -19,6 +19,7 @@ import seedu.address.commons.core.index.Index; 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; @@ -52,6 +53,8 @@ public class EditCommand extends UndoableCommand { 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 int PRIVILEGE_LEVEL = Model.PRIVILEGE_LEVEL_LIBRARIAN; + private final Index index; private final EditPersonDescriptor editPersonDescriptor; diff --git a/src/main/java/seedu/address/logic/commands/ExitCommand.java b/src/main/java/seedu/address/logic/commands/ExitCommand.java index fbd1beb2966e..a5b699d35033 100644 --- a/src/main/java/seedu/address/logic/commands/ExitCommand.java +++ b/src/main/java/seedu/address/logic/commands/ExitCommand.java @@ -2,6 +2,7 @@ import seedu.address.commons.core.EventsCenter; import seedu.address.commons.events.ui.ExitAppRequestEvent; +import seedu.address.model.Model; /** * Terminates the program. @@ -12,6 +13,8 @@ public class ExitCommand extends Command { public static final String MESSAGE_EXIT_ACKNOWLEDGEMENT = "Exiting Address Book as requested ..."; + public static final int PRIVILEGE_LEVEL = Model.PRIVILEGE_LEVEL_LIBRARIAN; + @Override public CommandResult execute() { EventsCenter.getInstance().post(new ExitAppRequestEvent()); diff --git a/src/main/java/seedu/address/logic/commands/FindCommand.java b/src/main/java/seedu/address/logic/commands/FindCommand.java index b1e671f633d2..65f70da1fe71 100644 --- a/src/main/java/seedu/address/logic/commands/FindCommand.java +++ b/src/main/java/seedu/address/logic/commands/FindCommand.java @@ -1,5 +1,6 @@ package seedu.address.logic.commands; +import seedu.address.model.Model; import seedu.address.model.person.NameContainsKeywordsPredicate; /** @@ -15,6 +16,8 @@ public class FindCommand extends Command { + "Parameters: KEYWORD [MORE_KEYWORDS]...\n" + "Example: " + COMMAND_WORD + " alice bob charlie"; + public static final int PRIVILEGE_LEVEL = Model.PRIVILEGE_LEVEL_GUEST; + private final NameContainsKeywordsPredicate predicate; public FindCommand(NameContainsKeywordsPredicate predicate) { diff --git a/src/main/java/seedu/address/logic/commands/HelpCommand.java b/src/main/java/seedu/address/logic/commands/HelpCommand.java index 10febf6d9136..88a0a95241f1 100644 --- a/src/main/java/seedu/address/logic/commands/HelpCommand.java +++ b/src/main/java/seedu/address/logic/commands/HelpCommand.java @@ -2,6 +2,7 @@ import seedu.address.commons.core.EventsCenter; import seedu.address.commons.events.ui.ShowHelpRequestEvent; +import seedu.address.model.Model; /** * Format full help instructions for every command for display. @@ -15,6 +16,8 @@ public class HelpCommand extends Command { public static final String SHOWING_HELP_MESSAGE = "Opened help window."; + public static final int PRIVILEGE_LEVEL = Model.PRIVILEGE_LEVEL_GUEST; + @Override public CommandResult execute() { EventsCenter.getInstance().post(new ShowHelpRequestEvent()); diff --git a/src/main/java/seedu/address/logic/commands/HistoryCommand.java b/src/main/java/seedu/address/logic/commands/HistoryCommand.java index f87abee5511d..55fcf480d763 100644 --- a/src/main/java/seedu/address/logic/commands/HistoryCommand.java +++ b/src/main/java/seedu/address/logic/commands/HistoryCommand.java @@ -17,6 +17,7 @@ public class HistoryCommand extends Command { public static final String COMMAND_WORD = "history"; public static final String MESSAGE_SUCCESS = "Entered commands (from most recent to earliest):\n%1$s"; public static final String MESSAGE_NO_HISTORY = "You have not yet entered any commands."; + public static final int PRIVILEGE_LEVEL = Model.PRIVILEGE_LEVEL_GUEST; @Override public CommandResult execute() { diff --git a/src/main/java/seedu/address/logic/commands/ListCommand.java b/src/main/java/seedu/address/logic/commands/ListCommand.java index 7b6463780824..af727b4e0b17 100644 --- a/src/main/java/seedu/address/logic/commands/ListCommand.java +++ b/src/main/java/seedu/address/logic/commands/ListCommand.java @@ -1,6 +1,7 @@ package seedu.address.logic.commands; import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS; +import seedu.address.model.Model; /** * Lists all persons in the address book to the user. @@ -11,6 +12,8 @@ public class ListCommand extends Command { public static final String MESSAGE_SUCCESS = "Listed all persons"; + public static final int PRIVILEGE_LEVEL = Model.PRIVILEGE_LEVEL_GUEST; + @Override public CommandResult execute() { diff --git a/src/main/java/seedu/address/logic/commands/RedoCommand.java b/src/main/java/seedu/address/logic/commands/RedoCommand.java index 7b99d0f372fc..848b6256e179 100644 --- a/src/main/java/seedu/address/logic/commands/RedoCommand.java +++ b/src/main/java/seedu/address/logic/commands/RedoCommand.java @@ -16,6 +16,8 @@ public class RedoCommand extends Command { public static final String MESSAGE_SUCCESS = "Redo success!"; public static final String MESSAGE_FAILURE = "No more commands to redo!"; + public static final int PRIVILEGE_LEVEL = Model.PRIVILEGE_LEVEL_LIBRARIAN; + @Override public CommandResult execute() throws CommandException { requireAllNonNull(model, undoRedoStack); diff --git a/src/main/java/seedu/address/logic/commands/SelectCommand.java b/src/main/java/seedu/address/logic/commands/SelectCommand.java index 9e3840a9dde6..4e31332b3a06 100644 --- a/src/main/java/seedu/address/logic/commands/SelectCommand.java +++ b/src/main/java/seedu/address/logic/commands/SelectCommand.java @@ -7,6 +7,7 @@ import seedu.address.commons.core.index.Index; import seedu.address.commons.events.ui.JumpToListRequestEvent; import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.Model; import seedu.address.model.person.Person; /** @@ -23,6 +24,8 @@ public class SelectCommand extends Command { public static final String MESSAGE_SELECT_PERSON_SUCCESS = "Selected Person: %1$s"; + public static final int PRIVILEGE_LEVEL = Model.PRIVILEGE_LEVEL_GUEST; + private final Index targetIndex; public SelectCommand(Index targetIndex) { diff --git a/src/main/java/seedu/address/logic/commands/UndoCommand.java b/src/main/java/seedu/address/logic/commands/UndoCommand.java index 1f3dcea8bbaa..1388c658765a 100644 --- a/src/main/java/seedu/address/logic/commands/UndoCommand.java +++ b/src/main/java/seedu/address/logic/commands/UndoCommand.java @@ -16,6 +16,8 @@ public class UndoCommand extends Command { public static final String MESSAGE_SUCCESS = "Undo success!"; public static final String MESSAGE_FAILURE = "No more commands to undo!"; + public static final int PRIVILEGE_LEVEL = Model.PRIVILEGE_LEVEL_LIBRARIAN; + @Override public CommandResult execute() throws CommandException { requireAllNonNull(model, undoRedoStack); diff --git a/src/main/java/seedu/address/logic/commands/UndoableCommand.java b/src/main/java/seedu/address/logic/commands/UndoableCommand.java index c107ffcd9cb3..ac4576c3d04d 100644 --- a/src/main/java/seedu/address/logic/commands/UndoableCommand.java +++ b/src/main/java/seedu/address/logic/commands/UndoableCommand.java @@ -6,6 +6,7 @@ import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.model.AddressBook; +import seedu.address.model.Model; import seedu.address.model.ReadOnlyAddressBook; /** @@ -14,6 +15,8 @@ public abstract class UndoableCommand extends Command { private ReadOnlyAddressBook previousAddressBook; + public static final int PRIVILEGE_LEVEL = Model.PRIVILEGE_LEVEL_GUEST; + protected abstract CommandResult executeUndoableCommand() throws CommandException; /** From a3bb9b550d2ada4c26983464c28aeda9d03d15be Mon Sep 17 00:00:00 2001 From: Qiu Haohao Date: Thu, 15 Mar 2018 14:51:03 +0800 Subject: [PATCH 10/98] Fixed isStudent and isLibrarian --- src/main/java/seedu/address/logic/commands/LoginCommand.java | 4 ++++ .../java/seedu/address/logic/parser/LoginCommandParser.java | 4 ++++ src/main/java/seedu/address/model/ModelManager.java | 4 ++-- 3 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 src/main/java/seedu/address/logic/commands/LoginCommand.java create mode 100644 src/main/java/seedu/address/logic/parser/LoginCommandParser.java diff --git a/src/main/java/seedu/address/logic/commands/LoginCommand.java b/src/main/java/seedu/address/logic/commands/LoginCommand.java new file mode 100644 index 000000000000..0baf40903eba --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/LoginCommand.java @@ -0,0 +1,4 @@ +package seedu.address.logic.commands; + +public class LoginCommand { +} diff --git a/src/main/java/seedu/address/logic/parser/LoginCommandParser.java b/src/main/java/seedu/address/logic/parser/LoginCommandParser.java new file mode 100644 index 000000000000..9abbbdc7953a --- /dev/null +++ b/src/main/java/seedu/address/logic/parser/LoginCommandParser.java @@ -0,0 +1,4 @@ +package seedu.address.logic.parser; + +public class LoginCommandParser { +} diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index b084c573f81d..93c5ee91e121 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -129,7 +129,7 @@ public int getPrivilegeLevel() { private boolean isStudent(String username, String password) { //This is temporary before we add in account database - if (username == "student" && password == "student"){ + if (username.equals("student") && password.equals("student")){ return true; } else{ @@ -139,7 +139,7 @@ private boolean isStudent(String username, String password) { private boolean isLibrarian(String username, String password) { //This is temporary before we add in account database - if (username == "admin" && password == "admin"){ + if (username.equals("admin") && password.equals("admin")){ return true; } else{ From 28536206d97ce40c5b9a222cd14fa3048aa7a27f Mon Sep 17 00:00:00 2001 From: Qiu Haohao Date: Thu, 15 Mar 2018 14:51:21 +0800 Subject: [PATCH 11/98] Added Login Command --- .../address/logic/commands/LoginCommand.java | 41 ++++++++++++++++++- .../logic/parser/AddressBookParser.java | 4 ++ .../logic/parser/LoginCommandParser.java | 21 +++++++++- 3 files changed, 64 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/address/logic/commands/LoginCommand.java b/src/main/java/seedu/address/logic/commands/LoginCommand.java index 0baf40903eba..614e38fa284d 100644 --- a/src/main/java/seedu/address/logic/commands/LoginCommand.java +++ b/src/main/java/seedu/address/logic/commands/LoginCommand.java @@ -1,4 +1,43 @@ package seedu.address.logic.commands; -public class LoginCommand { +import seedu.address.model.Model; +import seedu.address.model.person.NameContainsKeywordsPredicate; + +public class LoginCommand extends Command{ + public static final String COMMAND_WORD = "login"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Login as student or librarian.\n" + + "Parameters: USERNAME PASSWORD\n" + + "Example: " + COMMAND_WORD + " MyUsername MyPassword"; + + public static final String MESSAGE_LOGGED_IN_AS_STUTENT = "You are logged in as student"; + public static final String MESSAGE_LOGGED_IN_AS_LIBRARIAN = "You are logged in as librarian"; + public static final String MESSAGE_NOT_LOGGED_IN = "Wrong username/password, try again"; + + public static final int PRIVILEGE_LEVEL = Model.PRIVILEGE_LEVEL_GUEST; + + private final String username; + private final String password; + + + public LoginCommand(String username, String password) { + this.username = username; + this.password = password; + } + + @Override + public CommandResult execute() { + int newPrivilegeLevel = model.authenticate(username,password); + switch (newPrivilegeLevel){ + case Model.PRIVILEGE_LEVEL_GUEST: + return new CommandResult(MESSAGE_NOT_LOGGED_IN); + case Model.PRIVILEGE_LEVEL_STUDENT: + return new CommandResult(MESSAGE_LOGGED_IN_AS_STUTENT); + case Model.PRIVILEGE_LEVEL_LIBRARIAN: + return new CommandResult(MESSAGE_LOGGED_IN_AS_LIBRARIAN); + default: + return new CommandResult(MESSAGE_NOT_LOGGED_IN); + } + + } } diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java index b7d57f5db86a..38c909fc102f 100644 --- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java +++ b/src/main/java/seedu/address/logic/parser/AddressBookParser.java @@ -16,6 +16,7 @@ import seedu.address.logic.commands.HelpCommand; import seedu.address.logic.commands.HistoryCommand; import seedu.address.logic.commands.ListCommand; +import seedu.address.logic.commands.LoginCommand; import seedu.address.logic.commands.RedoCommand; import seedu.address.logic.commands.SelectCommand; import seedu.address.logic.commands.UndoCommand; @@ -84,6 +85,9 @@ public Command parseCommand(String userInput) throws ParseException { case RedoCommand.COMMAND_WORD: return new RedoCommand(); + case LoginCommand.COMMAND_WORD: + return new LoginCommandParser().parse(arguments); + default: throw new ParseException(MESSAGE_UNKNOWN_COMMAND); } diff --git a/src/main/java/seedu/address/logic/parser/LoginCommandParser.java b/src/main/java/seedu/address/logic/parser/LoginCommandParser.java index 9abbbdc7953a..e96c00cced33 100644 --- a/src/main/java/seedu/address/logic/parser/LoginCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/LoginCommandParser.java @@ -1,4 +1,23 @@ package seedu.address.logic.parser; -public class LoginCommandParser { +import seedu.address.logic.commands.LoginCommand; +import seedu.address.logic.parser.exceptions.ParseException; +import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; + + +public class LoginCommandParser implements Parser{ + + public LoginCommand parse(String args) throws ParseException { + String trimmedArgs = args.trim(); + String[] nameKeywords = trimmedArgs.split("\\s+"); + if (nameKeywords.length != 2) { + throw new ParseException( + String.format(MESSAGE_INVALID_COMMAND_FORMAT, LoginCommand.MESSAGE_USAGE)); + } + + String username = nameKeywords[0]; + String password = nameKeywords[1]; + + return new LoginCommand(username, password); + } } From 80dacbf77d0d1281304cbc9a541d21ee1b7a2e21 Mon Sep 17 00:00:00 2001 From: Qiu Haohao Date: Thu, 15 Mar 2018 14:57:01 +0800 Subject: [PATCH 12/98] Add logout command --- .../address/logic/commands/LoginCommand.java | 1 - .../address/logic/commands/LogoutCommand.java | 22 +++++++++++++++++++ .../logic/parser/AddressBookParser.java | 4 ++++ 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 src/main/java/seedu/address/logic/commands/LogoutCommand.java diff --git a/src/main/java/seedu/address/logic/commands/LoginCommand.java b/src/main/java/seedu/address/logic/commands/LoginCommand.java index 614e38fa284d..6cc4959fd58d 100644 --- a/src/main/java/seedu/address/logic/commands/LoginCommand.java +++ b/src/main/java/seedu/address/logic/commands/LoginCommand.java @@ -38,6 +38,5 @@ public CommandResult execute() { default: return new CommandResult(MESSAGE_NOT_LOGGED_IN); } - } } diff --git a/src/main/java/seedu/address/logic/commands/LogoutCommand.java b/src/main/java/seedu/address/logic/commands/LogoutCommand.java new file mode 100644 index 000000000000..f8325187ad6e --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/LogoutCommand.java @@ -0,0 +1,22 @@ +package seedu.address.logic.commands; + +import seedu.address.logic.commands.Command; +import seedu.address.logic.commands.CommandResult; +import seedu.address.model.Model; + +public class LogoutCommand extends Command{ + public static final String COMMAND_WORD = "logout"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Logout as student or librarian.\n" + + "Example: " + COMMAND_WORD; + + public static final String MESSAGE_LOGGED_OUT = "You are logged out."; + + public static final int PRIVILEGE_LEVEL = Model.PRIVILEGE_LEVEL_STUDENT; + + @Override + public CommandResult execute() { + model.logout(); + return new CommandResult(MESSAGE_LOGGED_OUT); + } +} diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java index 38c909fc102f..329fefec874f 100644 --- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java +++ b/src/main/java/seedu/address/logic/parser/AddressBookParser.java @@ -17,6 +17,7 @@ import seedu.address.logic.commands.HistoryCommand; import seedu.address.logic.commands.ListCommand; import seedu.address.logic.commands.LoginCommand; +import seedu.address.logic.commands.LogoutCommand; import seedu.address.logic.commands.RedoCommand; import seedu.address.logic.commands.SelectCommand; import seedu.address.logic.commands.UndoCommand; @@ -88,6 +89,9 @@ public Command parseCommand(String userInput) throws ParseException { case LoginCommand.COMMAND_WORD: return new LoginCommandParser().parse(arguments); + case LogoutCommand.COMMAND_WORD: + return new LogoutCommand(); + default: throw new ParseException(MESSAGE_UNKNOWN_COMMAND); } From b5b3bf9dd0010c59b04d74853d826c193d1b1f37 Mon Sep 17 00:00:00 2001 From: Qiu Haohao Date: Thu, 15 Mar 2018 15:47:10 +0800 Subject: [PATCH 13/98] Implement privilege --- src/main/java/seedu/address/logic/LogicManager.java | 7 +++++++ src/main/java/seedu/address/logic/commands/AddCommand.java | 5 +++++ .../java/seedu/address/logic/commands/ClearCommand.java | 5 +++++ src/main/java/seedu/address/logic/commands/Command.java | 4 ++++ .../java/seedu/address/logic/commands/DeleteCommand.java | 5 +++++ .../java/seedu/address/logic/commands/EditCommand.java | 7 +++++++ .../java/seedu/address/logic/commands/ExitCommand.java | 5 +++++ .../java/seedu/address/logic/commands/FindCommand.java | 5 +++++ .../java/seedu/address/logic/commands/HelpCommand.java | 5 +++++ .../java/seedu/address/logic/commands/HistoryCommand.java | 5 +++++ .../java/seedu/address/logic/commands/ListCommand.java | 5 +++++ .../java/seedu/address/logic/commands/LoginCommand.java | 5 +++++ .../java/seedu/address/logic/commands/LogoutCommand.java | 5 +++++ .../java/seedu/address/logic/commands/RedoCommand.java | 5 +++++ .../java/seedu/address/logic/commands/SelectCommand.java | 5 +++++ .../java/seedu/address/logic/commands/UndoCommand.java | 5 +++++ .../java/seedu/address/logic/commands/UndoableCommand.java | 2 -- 17 files changed, 83 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/address/logic/LogicManager.java b/src/main/java/seedu/address/logic/LogicManager.java index 9f6846bdfc74..5eea5a04107c 100644 --- a/src/main/java/seedu/address/logic/LogicManager.java +++ b/src/main/java/seedu/address/logic/LogicManager.java @@ -36,6 +36,9 @@ public CommandResult execute(String commandText) throws CommandException, ParseE logger.info("----------------[USER COMMAND][" + commandText + "]"); try { Command command = addressBookParser.parseCommand(commandText); + if (!isPrivileged(command)){ + return new CommandResult(Command.MESSAGE_UNPRIVILEGED); + } command.setData(model, history, undoRedoStack); CommandResult result = command.execute(); undoRedoStack.push(command); @@ -54,4 +57,8 @@ public ObservableList getFilteredPersonList() { public ListElementPointer getHistorySnapshot() { return new ListElementPointer(history.getHistory()); } + + protected boolean isPrivileged(Command command){ + return command.getPrivilegeLevel() <= model.getPrivilegeLevel(); + } } diff --git a/src/main/java/seedu/address/logic/commands/AddCommand.java b/src/main/java/seedu/address/logic/commands/AddCommand.java index 4edf1865b57b..d142f7bb496a 100644 --- a/src/main/java/seedu/address/logic/commands/AddCommand.java +++ b/src/main/java/seedu/address/logic/commands/AddCommand.java @@ -67,4 +67,9 @@ public boolean equals(Object other) { || (other instanceof AddCommand // instanceof handles nulls && toAdd.equals(((AddCommand) other).toAdd)); } + + @Override + public int getPrivilegeLevel(){ + return PRIVILEGE_LEVEL; + } } diff --git a/src/main/java/seedu/address/logic/commands/ClearCommand.java b/src/main/java/seedu/address/logic/commands/ClearCommand.java index a55f04e89717..98a671a80b23 100644 --- a/src/main/java/seedu/address/logic/commands/ClearCommand.java +++ b/src/main/java/seedu/address/logic/commands/ClearCommand.java @@ -20,4 +20,9 @@ public CommandResult executeUndoableCommand() { model.resetData(new AddressBook()); return new CommandResult(MESSAGE_SUCCESS); } + + @Override + public int getPrivilegeLevel(){ + return PRIVILEGE_LEVEL; + } } diff --git a/src/main/java/seedu/address/logic/commands/Command.java b/src/main/java/seedu/address/logic/commands/Command.java index 6580e0b51c90..8c0c4fefb152 100644 --- a/src/main/java/seedu/address/logic/commands/Command.java +++ b/src/main/java/seedu/address/logic/commands/Command.java @@ -14,6 +14,8 @@ public abstract class Command { protected CommandHistory history; protected UndoRedoStack undoRedoStack; + public static final String MESSAGE_UNPRIVILEGED = "You are not allowed to execute this command, login and try again"; + /** * Constructs a feedback message to summarise an operation that displayed a listing of persons. * @@ -40,4 +42,6 @@ public static String getMessageForPersonListShownSummary(int displaySize) { public void setData(Model model, CommandHistory history, UndoRedoStack undoRedoStack) { this.model = model; } + + public abstract int getPrivilegeLevel(); } diff --git a/src/main/java/seedu/address/logic/commands/DeleteCommand.java b/src/main/java/seedu/address/logic/commands/DeleteCommand.java index b35a9efc2f0b..98c3db094bea 100644 --- a/src/main/java/seedu/address/logic/commands/DeleteCommand.java +++ b/src/main/java/seedu/address/logic/commands/DeleteCommand.java @@ -67,4 +67,9 @@ public boolean equals(Object other) { && this.targetIndex.equals(((DeleteCommand) other).targetIndex) // state check && Objects.equals(this.personToDelete, ((DeleteCommand) other).personToDelete)); } + + @Override + public int getPrivilegeLevel(){ + return PRIVILEGE_LEVEL; + } } diff --git a/src/main/java/seedu/address/logic/commands/EditCommand.java b/src/main/java/seedu/address/logic/commands/EditCommand.java index 70de744aa505..55d4764abcbc 100644 --- a/src/main/java/seedu/address/logic/commands/EditCommand.java +++ b/src/main/java/seedu/address/logic/commands/EditCommand.java @@ -133,6 +133,11 @@ public boolean equals(Object other) { && Objects.equals(personToEdit, e.personToEdit); } + @Override + public int getPrivilegeLevel(){ + return PRIVILEGE_LEVEL; + } + /** * Stores the details to edit the person with. Each non-empty field value will replace the * corresponding field value of the person. @@ -235,5 +240,7 @@ && getEmail().equals(e.getEmail()) && getAddress().equals(e.getAddress()) && 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 a5b699d35033..4fc67bcf9364 100644 --- a/src/main/java/seedu/address/logic/commands/ExitCommand.java +++ b/src/main/java/seedu/address/logic/commands/ExitCommand.java @@ -21,4 +21,9 @@ public CommandResult execute() { return new CommandResult(MESSAGE_EXIT_ACKNOWLEDGEMENT); } + @Override + public int getPrivilegeLevel(){ + return PRIVILEGE_LEVEL; + } + } diff --git a/src/main/java/seedu/address/logic/commands/FindCommand.java b/src/main/java/seedu/address/logic/commands/FindCommand.java index 65f70da1fe71..587a0933c466 100644 --- a/src/main/java/seedu/address/logic/commands/FindCommand.java +++ b/src/main/java/seedu/address/logic/commands/FindCommand.java @@ -36,4 +36,9 @@ public boolean equals(Object other) { || (other instanceof FindCommand // instanceof handles nulls && this.predicate.equals(((FindCommand) other).predicate)); // state check } + + @Override + public int getPrivilegeLevel(){ + return PRIVILEGE_LEVEL; + } } diff --git a/src/main/java/seedu/address/logic/commands/HelpCommand.java b/src/main/java/seedu/address/logic/commands/HelpCommand.java index 88a0a95241f1..d2ce3c4e6056 100644 --- a/src/main/java/seedu/address/logic/commands/HelpCommand.java +++ b/src/main/java/seedu/address/logic/commands/HelpCommand.java @@ -23,4 +23,9 @@ public CommandResult execute() { EventsCenter.getInstance().post(new ShowHelpRequestEvent()); return new CommandResult(SHOWING_HELP_MESSAGE); } + + @Override + public int getPrivilegeLevel(){ + return PRIVILEGE_LEVEL; + } } diff --git a/src/main/java/seedu/address/logic/commands/HistoryCommand.java b/src/main/java/seedu/address/logic/commands/HistoryCommand.java index 55fcf480d763..d910e343a0be 100644 --- a/src/main/java/seedu/address/logic/commands/HistoryCommand.java +++ b/src/main/java/seedu/address/logic/commands/HistoryCommand.java @@ -36,4 +36,9 @@ public void setData(Model model, CommandHistory history, UndoRedoStack undoRedoS requireNonNull(history); this.history = history; } + + @Override + public int getPrivilegeLevel(){ + return PRIVILEGE_LEVEL; + } } diff --git a/src/main/java/seedu/address/logic/commands/ListCommand.java b/src/main/java/seedu/address/logic/commands/ListCommand.java index af727b4e0b17..5b597512682d 100644 --- a/src/main/java/seedu/address/logic/commands/ListCommand.java +++ b/src/main/java/seedu/address/logic/commands/ListCommand.java @@ -20,4 +20,9 @@ public CommandResult execute() { model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); return new CommandResult(MESSAGE_SUCCESS); } + + @Override + public int getPrivilegeLevel(){ + return PRIVILEGE_LEVEL; + } } diff --git a/src/main/java/seedu/address/logic/commands/LoginCommand.java b/src/main/java/seedu/address/logic/commands/LoginCommand.java index 6cc4959fd58d..e7bda6443eb4 100644 --- a/src/main/java/seedu/address/logic/commands/LoginCommand.java +++ b/src/main/java/seedu/address/logic/commands/LoginCommand.java @@ -39,4 +39,9 @@ public CommandResult execute() { return new CommandResult(MESSAGE_NOT_LOGGED_IN); } } + + @Override + public int getPrivilegeLevel(){ + return PRIVILEGE_LEVEL; + } } diff --git a/src/main/java/seedu/address/logic/commands/LogoutCommand.java b/src/main/java/seedu/address/logic/commands/LogoutCommand.java index f8325187ad6e..baf7652b2f04 100644 --- a/src/main/java/seedu/address/logic/commands/LogoutCommand.java +++ b/src/main/java/seedu/address/logic/commands/LogoutCommand.java @@ -19,4 +19,9 @@ public CommandResult execute() { model.logout(); return new CommandResult(MESSAGE_LOGGED_OUT); } + + @Override + public int getPrivilegeLevel(){ + return PRIVILEGE_LEVEL; + } } diff --git a/src/main/java/seedu/address/logic/commands/RedoCommand.java b/src/main/java/seedu/address/logic/commands/RedoCommand.java index 848b6256e179..19e4c16c4f8e 100644 --- a/src/main/java/seedu/address/logic/commands/RedoCommand.java +++ b/src/main/java/seedu/address/logic/commands/RedoCommand.java @@ -35,4 +35,9 @@ public void setData(Model model, CommandHistory commandHistory, UndoRedoStack un this.model = model; this.undoRedoStack = undoRedoStack; } + + @Override + public int getPrivilegeLevel(){ + return PRIVILEGE_LEVEL; + } } diff --git a/src/main/java/seedu/address/logic/commands/SelectCommand.java b/src/main/java/seedu/address/logic/commands/SelectCommand.java index 4e31332b3a06..f622892c27b1 100644 --- a/src/main/java/seedu/address/logic/commands/SelectCommand.java +++ b/src/main/java/seedu/address/logic/commands/SelectCommand.java @@ -52,4 +52,9 @@ public boolean equals(Object other) { || (other instanceof SelectCommand // instanceof handles nulls && this.targetIndex.equals(((SelectCommand) other).targetIndex)); // state check } + + @Override + public int getPrivilegeLevel(){ + return PRIVILEGE_LEVEL; + } } diff --git a/src/main/java/seedu/address/logic/commands/UndoCommand.java b/src/main/java/seedu/address/logic/commands/UndoCommand.java index 1388c658765a..6338864ba109 100644 --- a/src/main/java/seedu/address/logic/commands/UndoCommand.java +++ b/src/main/java/seedu/address/logic/commands/UndoCommand.java @@ -35,4 +35,9 @@ public void setData(Model model, CommandHistory commandHistory, UndoRedoStack un this.model = model; this.undoRedoStack = undoRedoStack; } + + @Override + public int getPrivilegeLevel(){ + return PRIVILEGE_LEVEL; + } } diff --git a/src/main/java/seedu/address/logic/commands/UndoableCommand.java b/src/main/java/seedu/address/logic/commands/UndoableCommand.java index ac4576c3d04d..31622771625c 100644 --- a/src/main/java/seedu/address/logic/commands/UndoableCommand.java +++ b/src/main/java/seedu/address/logic/commands/UndoableCommand.java @@ -15,8 +15,6 @@ public abstract class UndoableCommand extends Command { private ReadOnlyAddressBook previousAddressBook; - public static final int PRIVILEGE_LEVEL = Model.PRIVILEGE_LEVEL_GUEST; - protected abstract CommandResult executeUndoableCommand() throws CommandException; /** From aebb2378b3b8c671f39e5a6823488e6040bb3ad6 Mon Sep 17 00:00:00 2001 From: "LAPTOP-VHS80CCS\\lucas" Date: Thu, 15 Mar 2018 16:26:17 +0800 Subject: [PATCH 14/98] Update User Stories --- docs/DeveloperGuide.adoc | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/docs/DeveloperGuide.adoc b/docs/DeveloperGuide.adoc index facfda8daa75..89a089236a7f 100644 --- a/docs/DeveloperGuide.adoc +++ b/docs/DeveloperGuide.adoc @@ -792,23 +792,40 @@ See this https://github.com/se-edu/addressbook-level4/pull/599[PR] for the step- [appendix] == User Stories +As a librarian, I can add new book titles into the database +As a librarian, I can delete book titles in the database +As a librarian, I want confirmation in notification before deleting a book +As a librarian, I can find a book title using the database +As a librarian, I can view the history of borrowed books from each borrower +As a student, I can find a book title in the database by it's name +As a student, I can find a book in the database by it's tag +As a student, I can check for the availability of the book +As a student, I can loan an available book +As a student, I can renew existing loaned book +As a student, I can reserve a book that is on on loan by someone else and not available in the library currently +As a student, I will receive notification when my current book loan duration is coming to an end +As a guest, I can find a book title in the database +As a guest, I can check for the availability of the book Priorities: High (must have) - `* * \*`, Medium (nice to have) - `* \*`, Low (unlikely to have) - `*` [width="59%",cols="22%,<23%,<25%,<30%",options="header",] |======================================================================= |Priority |As a ... |I want to ... |So that I can... -|`* * *` |new user |see usage instructions |refer to instructions when I forget how to use the App - -|`* * *` |user |add a new person | - -|`* * *` |user |delete a person |remove entries that I no longer need - -|`* * *` |user |find a person by name |locate details of persons without having to go through the entire list - -|`* *` |user |hide <> by default |minimize chance of someone else seeing them by accident - -|`*` |user with many persons in the address book |sort persons by name |locate a person easily +|`* * *` |As a librarian |I want to add a new book title into the database |So that I can constantly update the database for borrowers +|`* * *` |As a librarian |I want to delete a book title from the database |So that I can constantly update the database for borrowers +|`* * *` |As a librarian |I want to confirmation in notification before deleting a book |So that I will not accidentally delete the wrong book title +|`* * *` |As a librarian |I want to find a book title in the database |So that I can see the status of the book +|`* * ` |As a librarian |I want to view the history of borrowed books from each borrower |So that I can keep track of books availability +|`* * *` |As a student |I want to find a book title in the database by it's name |So I can facilitate my search process +|`* * *` |As a student |I want to find a book title in the database by it's tag |So that I can facilitate my search process +|`* * *` |As a student |I want to check for the availability of the book |So that I can know it' loan status +|`* * *` |As a student |I want to loan a book |So that I can use the book for higher learning +|`* *` |As a student |I want to renew existing loaned book |So that I have more time to finish the book +|`* *` |As a student |I want to reserve a book currently being loaned |So that I will be able to loan the book as soon as it is available +|`* * *` |As a student |I want to receive notification when my current book is due soon |So that I will not miss the due date +|`* * *` |As a guest |I want to find a book title in the database |So that I can see the status of the book +|`* * *` |As a guest |I want to check for the availability of the book |So that I can see it's loan status |======================================================================= _{More to be added}_ From b0e3a5082e32a3fa62551d6670ceb8625522b590 Mon Sep 17 00:00:00 2001 From: Qiu Haohao Date: Thu, 15 Mar 2018 18:30:17 +0800 Subject: [PATCH 15/98] Fixed getPrivilegeLevel --- .../seedu/address/logic/commands/Command.java | 2 +- .../address/logic/commands/AddCommandTest.java | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/address/logic/commands/Command.java b/src/main/java/seedu/address/logic/commands/Command.java index 8c0c4fefb152..85cdf0678a04 100644 --- a/src/main/java/seedu/address/logic/commands/Command.java +++ b/src/main/java/seedu/address/logic/commands/Command.java @@ -43,5 +43,5 @@ public void setData(Model model, CommandHistory history, UndoRedoStack undoRedoS this.model = model; } - public abstract int getPrivilegeLevel(); + public int getPrivilegeLevel(){ return Model.PRIVILEGE_LEVEL_GUEST; }; } diff --git a/src/test/java/seedu/address/logic/commands/AddCommandTest.java b/src/test/java/seedu/address/logic/commands/AddCommandTest.java index 461cf09d1217..3f896c33adc6 100644 --- a/src/test/java/seedu/address/logic/commands/AddCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddCommandTest.java @@ -133,6 +133,21 @@ public ObservableList getFilteredPersonList() { public void updateFilteredPersonList(Predicate predicate) { fail("This method should not be called."); } + + @Override + public int authenticate(String username, String password) { + return 0; + } + + @Override + public void logout() { + + } + + @Override + public int getPrivilegeLevel() { + return 0; + } } /** From 1a9e8e0e68b4c0e7b6bcd12dfe545ec9e36507f5 Mon Sep 17 00:00:00 2001 From: Khia Yi <33336624+khiayi@users.noreply.github.com> Date: Fri, 16 Mar 2018 23:50:56 +0800 Subject: [PATCH 16/98] README,AboutUs,ContactUs,DeveloperGuide,UserGuide:Updated links --- README.adoc | 4 ++-- docs/AboutUs.adoc | 2 +- docs/ContactUs.adoc | 2 +- docs/DeveloperGuide.adoc | 2 +- docs/UserGuide.adoc | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.adoc b/README.adoc index a04a58a8487a..37cb41707062 100644 --- a/README.adoc +++ b/README.adoc @@ -1,9 +1,9 @@ = Address Book (Level 4) ifdef::env-github,env-browser[:relfileprefix: docs/] -https://travis-ci.org/khiayi/addressbook-level4[image:https://travis-ci.org/khiayi/addressbook-level4.svg?branch=master[Build Status]] +https://travis-ci.org/CS2103JAN2018-T16-B1/main[image:https://travis-ci.org/CS2103JAN2018-T16-B1/main.svg?branch=master[Build Status]] https://ci.appveyor.com/project/damithc/addressbook-level4[image:https://ci.appveyor.com/api/projects/status/3boko2x2vr5cc3w2?svg=true[Build status]] -https://coveralls.io/github/khiayi/addressbook-level4?branch=master[image:https://coveralls.io/repos/github/khiayi/addressbook-level4/badge.svg?branch=master[Coverage Status]] +https://coveralls.io/github/CS2103JAN2018-T16-B1/main?branch=master[image:https://coveralls.io/repos/github/CS2103JAN2018-T16-B1/main/badge.svg?branch=master[Coverage Status]] https://gitter.im/se-edu/Lobby[image:https://badges.gitter.im/se-edu/Lobby.svg[Gitter chat]] ifdef::env-github[] diff --git a/docs/AboutUs.adoc b/docs/AboutUs.adoc index 0f0a8e7ab51e..7742e0aff8f7 100644 --- a/docs/AboutUs.adoc +++ b/docs/AboutUs.adoc @@ -3,7 +3,7 @@ :imagesDir: images :stylesDir: stylesheets -AddressBook - Level 4 was developed by the https://se-edu.github.io/docs/Team.html[se-edu] team. + +AddressBook - Level 4 was developed by the https://CS2103JAN2018-T16-B1.github.io/docs/Team.html[CS2103JAN2018-T16-B1] team. + _{The dummy content given below serves as a placeholder to be used by future forks of the project.}_ + {empty} + We are a team based in the http://www.comp.nus.edu.sg[School of Computing, National University of Singapore]. diff --git a/docs/ContactUs.adoc b/docs/ContactUs.adoc index eafdc9574a50..6da7df4a9f91 100644 --- a/docs/ContactUs.adoc +++ b/docs/ContactUs.adoc @@ -1,6 +1,6 @@ = Contact Us :stylesDir: stylesheets -* *Bug reports, Suggestions* : Post in our https://github.com/se-edu/addressbook-level4/issues[issue tracker] if you noticed bugs or have suggestions on how to improve. +* *Bug reports, Suggestions* : Post in our https://github.com/CS2103JAN2018-T16-B1/main/issues[issue tracker] if you noticed bugs or have suggestions on how to improve. * *Contributing* : We welcome pull requests. Follow the process described https://github.com/oss-generic/process[here] * *Email us* : You can also reach us at `damith [at] comp.nus.edu.sg` diff --git a/docs/DeveloperGuide.adoc b/docs/DeveloperGuide.adoc index 89a089236a7f..192125fa8202 100644 --- a/docs/DeveloperGuide.adoc +++ b/docs/DeveloperGuide.adoc @@ -10,7 +10,7 @@ ifdef::env-github[] :tip-caption: :bulb: :note-caption: :information_source: endif::[] -:repoURL: https://github.com/CS2103JAN2018-T16-B1/addressbook-level4 +:repoURL: https://github.com/CS2103JAN2018-T16-B1/main By: `Team SE-EDU`      Since: `Jun 2016`      Licence: `MIT` diff --git a/docs/UserGuide.adoc b/docs/UserGuide.adoc index 0baecddca50c..c1f93acde393 100644 --- a/docs/UserGuide.adoc +++ b/docs/UserGuide.adoc @@ -11,7 +11,7 @@ ifdef::env-github[] :tip-caption: :bulb: :note-caption: :information_source: endif::[] -:repoURL: https://github.com/CS2103JAN2018-T16-B1/addressbook-level4 +:repoURL: https://github.com/CS2103JAN2018-T16-B1/main By: `Team SE-EDU` Since: `Jun 2016` Licence: `MIT` From aa2546da0c8a1a1d48e0654e075d9ee14ebdfd2f Mon Sep 17 00:00:00 2001 From: Khia Yi <33336624+khiayi@users.noreply.github.com> Date: Sat, 17 Mar 2018 00:03:59 +0800 Subject: [PATCH 17/98] README.adoc:Deleted unused links --- README.adoc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.adoc b/README.adoc index 37cb41707062..dd8928ac464b 100644 --- a/README.adoc +++ b/README.adoc @@ -2,9 +2,8 @@ ifdef::env-github,env-browser[:relfileprefix: docs/] https://travis-ci.org/CS2103JAN2018-T16-B1/main[image:https://travis-ci.org/CS2103JAN2018-T16-B1/main.svg?branch=master[Build Status]] -https://ci.appveyor.com/project/damithc/addressbook-level4[image:https://ci.appveyor.com/api/projects/status/3boko2x2vr5cc3w2?svg=true[Build status]] https://coveralls.io/github/CS2103JAN2018-T16-B1/main?branch=master[image:https://coveralls.io/repos/github/CS2103JAN2018-T16-B1/main/badge.svg?branch=master[Coverage Status]] -https://gitter.im/se-edu/Lobby[image:https://badges.gitter.im/se-edu/Lobby.svg[Gitter chat]] + ifdef::env-github[] image::docs/images/Ui.png[width="600"] From 7597ec5098f9bfd2aac43a5f0774966c09682fb0 Mon Sep 17 00:00:00 2001 From: Khia Yi <33336624+khiayi@users.noreply.github.com> Date: Sat, 17 Mar 2018 00:04:17 +0800 Subject: [PATCH 18/98] AboutUs.adoc:Updated team profile --- docs/AboutUs.adoc | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/AboutUs.adoc b/docs/AboutUs.adoc index 7742e0aff8f7..99e17758b823 100644 --- a/docs/AboutUs.adoc +++ b/docs/AboutUs.adoc @@ -10,44 +10,44 @@ We are a team based in the http://www.comp.nus.edu.sg[School of Computing, Natio == Project Team -=== John Doe -image::damithc.jpg[width="150", align="left"] -{empty}[http://www.comp.nus.edu.sg/~damithch[homepage]] [https://github.com/damithc[github]] [<>] +=== Chan Tiong Ley +image::chantiongley.jpg[width="150", align="left"] +{empty} [https://github.com/chantiongley[github]] [<>] Role: Project Advisor ''' -=== John Roe -image::lejolly.jpg[width="150", align="left"] -{empty}[http://github.com/lejolly[github]] [<>] +=== Le Khang Tai +image::LeKhangTai.jpg[width="150", align="left"] +{empty}[https://github.com/LeKhangTai[github]] [<>] Role: Team Lead + Responsibilities: UI ''' -=== Johnny Doe -image::yijinl.jpg[width="150", align="left"] -{empty}[http://github.com/yijinl[github]] [<>] +=== Qiu Hao Ze +image::QiuHaohao.jpg[width="150", align="left"] +{empty}[https://github.com/QiuHaohao[github]] [<>] Role: Developer + Responsibilities: Data ''' -=== Johnny Roe -image::m133225.jpg[width="150", align="left"] -{empty}[http://github.com/m133225[github]] [<>] +=== Victor Tardieu +image::victortardieu.jpg[width="150", align="left"] +{empty}[https://github.com/victortardieu[github]] [<>] Role: Developer + Responsibilities: Dev Ops + Threading ''' -=== Benson Meier -image::yl_coder.jpg[width="150", align="left"] -{empty}[http://github.com/yl-coder[github]] [<>] +=== Wong Khia Yi +image::khiayi.jpg[width="150", align="left"] +{empty}[https://github.com/khiayi[github]] [<>] Role: Developer + Responsibilities: UI From c30e5aa0698baec3ea2dd1dc871e2eca294d52db Mon Sep 17 00:00:00 2001 From: Khia Yi <33336624+khiayi@users.noreply.github.com> Date: Sat, 17 Mar 2018 00:41:32 +0800 Subject: [PATCH 19/98] Added photo for khiayi --- docs/images/khiayi.png | Bin 0 -> 21578 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/images/khiayi.png diff --git a/docs/images/khiayi.png b/docs/images/khiayi.png new file mode 100644 index 0000000000000000000000000000000000000000..aaef9dac713bd2ceabb07375c292a28507732bf9 GIT binary patch literal 21578 zcmX6^1zc0#`yQivBV-^5jF2HBqf4pL-5nBw0-`k1J-U&UuF)+ZAl)U>N=SEi{rCO- z&pzAz+`H}GbI&>N^S;fx7{a@^*yw!*3povC0N@KN0N@t{0NkJt`E3CJE?fY>ju`+ToB{w)eadK77e#-8 z|4B~Y2>>AJ`tOa==TK~kK8RzkD2o6*{`bmmElL0YG?nBL5?b!_d#(C0mNPD#-$Pn2 zsm+IlY&Z1GtHUXzi7)D34z$(mwGq#f`nX{d^WHolec(4az5(~Ye0YBYIeva>{QY<5 zh2cpOhyD{6#=%@cq?CFOyN-^I3OvKuivajP>(}9EV(04TnC}G5hl2#e`|O; zUyM4M`20wEgBK9v_kgz*6aD`izlW_W^qybat59TqA|Ts-VSTJ(_vAEDW1#^q13C%dQR@1AAHY57Nf2^Q?GTMS~t4lO%bADHK>iRumYdLP7F`=uBo zdeWa4^Jaecyt!hxxq?G+(`cc=O8?s(Nqf!i{kR`%Zo;m>stQ8C+vg~dUi9v$OYCMM zMn_lo@!;^`qlLxlh`!PK@ zv3Iqve2ycg=cA&c#=H-lbSsQXQ0R6CPTh)vUlZPaK-@}U3Y+e0lxdxBZP^HCzPbG4 z^s4RZpKjYp(y_Z;xi|WKjI%=zvx=0R4JO&HSt)Vv(EBfPtqkJ zAwdt+@rZ-Z>E2xJ?d@&q+tfKvQ*BDAT-p6>x@PF;v7KyCCSb8}=l(*Yls$1!EyRh`IquYKHNPoBd zt3Xk=(u6YZ{{G&iQXo}nuqH#LNL$8kh+q@3`G^u*;XsU|cpWWPinFgiG__QXy#Tzit!3JCP zCTeL%&vY79MNQCa}^kN<>CFeH6}Yv`>#$Vdb&-<23fVZy4P}^z!2Bjg-k_ z89crI!J!BZhrd%%g#CTNa{VHH3sO55fdW|&F#>+p+s^o0bCysp;Y6?cCBpqA`W^oBh{yGCq{zy4pRFi+%Ku zSA8=T#-67m0$IKf*Z++g`fhP?aZw70Il2Cm+lv0SuWN0jPZTd-Jq}0T+VOuL^*A*3 z+^+{oPVy!UtR45!`(CYtM!|a_-~sj)X9r5fPEfA14Gn zXv+WvI7O${j+sXeOoS!aKHd-5Q-62gB+g!CGNhVw9o-5AU7*|LrJJkkqWfx;>@$zG zn1`*HXI@7gE1&v@Q)LdyN8FbDKN_N8XMdqF%ll%^`kTkb^=8)C6T@W0CN0=%s-1b# ztsuGuPn{9UvpKopB8AACU@J&0cL$`5ysK=x*|FsQJo@?^J=|}u*QTeF>z{xR|94hS z#mx*)v}O4|oMtUGyX-D6GX%v_Hal@f=q1dtt^zUUwQ6GBaG2X5t zC?sc>mM$0DPX=G0r_Ow%x#DZ%#j~2wrpF&(G`Ln6x47QlxEy-3cG#`Fb7N9;Q>W-n zDaihtb8`sXQo5Y0AL!#|8yuEax3m{ZRZ1&-zi{z%=?Vw>=3>?YZD7chxz&8wi38r& zwb!>EMnz?kD(}md$FpIcF|SRLr2!LD{^jI}O|LmrT8Yp?)$`Uqk>cgG*ZtpC29{6c z6FyP{N1hukzO)d`5^5>bH*2XVMeU?oe-m=r7`{H;q<3HT=Qx*EU$gprlDtIcwxpO{ zD@S8dqrcPYi=M&%nR~%klP@d5RA^&V1yV?kH_{(gUM43m$s0;)^IUV-Ctb!LuMaHk zG9fJ8+%D-KR_OnO=QY)bwGLc*EWf{h|DKjw$KSJ%uHk6| za2TBP>#2P9lBtObs_%}u_U;!z41bp{;+}aLa7f}zlAfRFb5Wb+y>DxZ9;2AYs~CEp ztCeB2)e3KX!^oVw7Hk8zon{_-p?`3@>HDym$lIGzDJnM5J1u|RECpD4KHqq^WOa71 zX5a57%ro$-z6Epl(tI|TO+!J*HbKZzkT$w+b!uwL3$=H+ruu`Bq{&(wZ4!Nyu}Fk;&WI3zCJnuvl1L0WNPIS{_$;ILSVq+ zZ4F0yp~v<5*Z=G>;l+0TzgEJQhi^h+ttMlTKqT5J{kO!WNMCEs)FTBq2WvQn9JiA) zyWOs%e2-^4Pnc7;c)(V8HPn|XmWOgGZM$(AHPZ%YFJr%unVI?3)JJIdXg%{*`tISD z#JO$5E>@W}0gWnMU0n_KXpouYZHq9Tx#oOVyG;@%j;+P;^NzXwRK@B$#U{%jtN_9+ zJ%xogY=cM4{&Gy*4-mjUl!dzbNIKHsb&)ezbGG=nj4O8aA6_psI;gTHn2P>%T=E}v z>>ftLio?T(!#B@^rU6SRP>vP<3L+gh2XVzCQiw$OQ5yjzlo`N$aCQ_350y>e&mGUm z-(4J=s{oW-wM(Th-cyPSll;n1f|y_%rHJjWDIu_h@L?y(F%)Nu6L{TauLt%IZ`v0= z%-Km|1@j10nBGn|w$(cu&NsB~(&jaVif=Ce9334!I5_ZnGiI75mwW~|%!;CN!XM}Kgy+ZCv|;n+2Zd+%ixaQ`i2NAD zn}e=irb!M?-y6EF*u80QZT#Bmf9y^KQ2gX{bkmg+JvcHf zGLdI!;owheUW`Ta6_K)t1drqb!Jpv6F|&rJ~{h>H<1o}C5=@&J=*Oyx89h3Ct$v*9o1;8M}noM~bB z^+Q&-0I0zt) zmk3%($wT7BfsT)kj?j@Z+TG?&6fYfG6Z=vL`FrBmUHS-TKBJ?1IeDHIgj_P%&M(6P zNU}i*kf^?@cY#!3jPszvK~@GN85b}I2rPwg7j*ohe(|SN5kU|yj-M9G{6Q;%h&i{o zI9mZZ7tSm#j==!LU=f-QSL`%tPP@+Ju^!EM<9%~?eToK%q3m5_T4&Opri$G|pUeLo zKl-4M-@q^`Oq@7}ky&j#h#`{3+wjS>K92IV+Dh45ZlWh0Tr@JQT-hn2wj3!pqjDmq z^yj^;0UCbe#@Dl5yDtIrR_6ulx7~4EGO8GIqtfXI^rDhr) zUQo--*kh(nfHMVP50Uq(O16j$`7W>rE=Hd1kby%BU}{5et;`Lzr{>DfO)!L)#C$)z z7~YWhwQ(_Tw>V02F>#b#=TgZ|EENuAAb1is_vKJpf)5`k4#WnK3GxRW*#{-R+POL3 z{m(D?qC@}xQVzGwxn^r|L)+R-Z|=SKnM@#Hz8xfR%~!s26^vAEO|z ziPsphuyWFB?ZR&SFFSsHV`^|5izvF)x4!u#`YeY2jqgqNCaZ(V0&O&FUdO{qN9xqn zM^I(^g@H{W%SyI$Qaz0q&tWr!VyX(NyrX@|&lGcNWE8(6!)e$?9Gg{jpFK9#ZV2NjCHSY5f;=)KrTQ<#6LWbY?OOm&Zf z5Pw-%Ff6@)7SUI~GC!ZqJ1Wd0TFZx0n5_KL`i;`mP_Vwuaes40pl`K#30G3KuC=+Q zwfaq}5{LX)EHy=e#4om-%;4_iKuLu}dqIHN&qRwkyjbzYZ{x5b?%wY$Eh3pJPRP|R z)lp8&wI*6dKmp^Ma)gl7y<)D0WNawm#^SEhUE#imC^)^38tg?l zNV3A0QXOgz477yMy|t=x*3#oNZmQ?jqq`7~$5DkR_ZRRP+OBqF8_<*Lgx*7d0T+Y0 zy5Ex~7=qtfiTa?Ei_FgjFEo(a?c7__Go)WyO(H)#*?SAWPP1wL^aY*7o6zZ%5yx7Y zv(jD7A;=N7;(%ZvW3{?@I6gR?lVdgbdn5;RExB^#)Axpke%s_@;emPHCsM3SoMNNH0>*cPeYR&2-Mz_86}r&S2Oj()#W zhlKtk%9W@vq9NuQJYTrA4NN*;wAs8^smmmt<_BDF3VamQ4Pu6xz2tdCMuEo#A##+z zTU=cHl|ASpbP3*ytof0iRa-_hh~W=mLdJ6I@h1~>C9O!T$RxdZnWJGprx5^Qz>(!G zR^YU8;WD6}u9eATw63apQef7Au(a#cOw;Ul6BK2UpM9EEFEqFW0aWOCKx}B6*I{i zCaXuU{`^t1Vz-%Or9NX-iBcd$m2hUfO@#3Fbf!&B^jGVfJ|+F)?T7doGRqxNi?D+z zT1UZ=w32e{;RINbS`-y1b|Cyo*k^T&$g1XMcIX>Ln4i-}K}*f)T7Kv7T+w0_NZNu~ z<-R$55=O|JSRm4dXI(11iB5UZj7&0YzGXc0QjdD$Y^!CuQcxyK)w};l0S0WpErW77!&EhgpMrZI%sAm|~YZ3w@sN zMwCJN+? z!|gxeZ~z0cpKXqRk_hWf+27wUcfV8T4+-afQS<( z^J93Iio^s@DRJdr9^kVum*Xr z&}6A4PN7bW0p5m!$|JCF2>?|RfxSXscTdIf0V!qh#E361Y`+%7eP>I=2uou=ss4n& zX2%g`j>XJuCHbb}KwL*#%TR_%EIUX$ z{VM*|O6XaPbpFgPqxnJu7ENoVqM>dupG*S4TszTD0g*Yj*<{c&-w6`oj3r`d$z}M5 z1w|neCro9qQuW2Z?&}y&Le)8OWx$jYtWrdlQh30D??BC+W*rTvMfzMmie2JE%TFws z4lv2?hxwbDs)khvmRcAjF18=?ET->2l8RgIn$eKXBWe9z`fxcyOArd`+M7LEsF}AU zREeDxtRW$OkrtE!;Pr>`O-2(v3_dm z2#L4q<{?VMK~QzIAPAp?5;Oq1#q#_^N0K&PW;b){!vu&$#xW$5aj08fO9CK`fse7> z8BB;aLfci+_B7sz*_)f2U%re`4F-^{(tG8LNg^_8ncVz;d2Cl$i9zM?-YTmh>Gwnl z@SkPf3YJ5^3`7D`3(*1Ywk7x(5M*e9KZmD=EIID*q?i1VH=4#76dMo&&t)SgVGqr< z>8L@7N5z+0Y#P1Iv~tkrdn<{}Aij5ggQi&rWX{^d!XJ&WtE;Qy`OXpN#O_*Eb3i4w|4Pr$*-RA*f<0l}2Yybn>2=1n7gT4$XMr<|^_@RAi zEKhQg{idn3ZQZkkNK?VXQA$Q=rkFC&L|e}~l2K9%p`;#2iedSrnH4dCGePr#eMU>W z{?|olS6e`dE%z|=R}d(Hs}>+1J&p++tTB;~YhGIzJ)|3Py}WQZq#xZ-{s^&ONCss% zje^kVux&^39Tc3%+*^z{ZSdT@oUa!WE|DaTO%eO0brB7)C)QSrdT*||y7JL9(rA-t z*o)1&8*O9C0yvJiqqG{D3muuNCWVEu$FrWlaVI@(uuYrWZ*BeCvEnXDOB~u-!!=y| zt8#}Tu(um41Oj02XO<)5>z?jw&CAPNz-{rwJ?)hZuHhihh7F?Faa_h|WVC?zZRhr@ z-V6#z{T?zdVTp#7G zAY5jg8LU zt(=5`Yb8@Dj-fC07=Aj_)+<4qN?YvTK{cjW3}q1&b-gJQW?Xxh)Qs}uDL-CC1Mbe` zSh#r@@tEa*+Tl~jVc?6)OG~JIw*O5}>`7xGIr6Ne8|$FWsm^(%u8dt9+Y)0dZIsNw zR-F7PZ?(tO-NlGNMOw|tfNpY1eqFZ=en(XV+0TE2y~PLTX%$gGX>EgqTiIMzw(Omm z-RjfY?X`>g?9*$TS$ZNIoiDu*MP>##lq^hAgN?5J;bsgwOg*!pKFJ^U!nI+y8M2C| z;~3?M{#KcevEtL!S}-5)@!-{n%Tvzd^{VogUIymk|Ic3FHVMT zYp*TmDUwPvoNz$eT3CRvSsDvvh4&WrtpZz^YE-})n9+LKU+>jqXGWSvVOo&n*8K8F z)#6zjHrz%JJC3}XGA>rMF0CLEx!X(vedB!kv8}#-s=@xPKJhvMCV;P34+}PAQbsFJ zKx;uH4`w64U<8uKvB@a}qULF1vV8uL5y+D?O2{T`5-l1=E&L4u~?eTzES< zTGVEXYE~^q)1!G4;@axLY}5!cfIKXiLQ{X5ag?PyAJ}~_VT#1<%BklMc6WBpW(?@Q zc4mc2YZuzZw3lz&s3YSKUwXXiaImk)5^6m+ZGUhX=c>CX$hy0#*R6PS*5CIK`nWB2 zsUt%;64Y+<`LFRB(E#O?c>(C)(CG1)^Z_@O&V-A+6@w^Z)|F};0D zSJIs#vh)&4Hn+SUWh?O1x13{V<&zB(ug>&qJ)Lu73u3%<7sW2F8SO`w^VTw9bx0gB zchA_x_D}Nz>GR6Ai<{EQw&v!xC&HCvV|Mo6=Ks*d$Vk79DJ0jj61T*$K;#2t_`={t zR4IP=T2@ZpE-r$z2geTwqd(F^2Ea0c-(616vs#@W;v&>8RLx)X=}n4IuOB#uq=rJo zg;kR`LvL#X{}LM7(#|iJzfcCuLSinTiv$mh5^(vywd4wZt4#)`ke;|-z?Dtdooq-K z_`71+;Oj1!sgm{G%gSwY1D$Qfh<$F-{fdW=L}K|9!@<;wbBow<;(m70;$(@f+%AmQ z*9RRPjcw;IrDw%NzkA!xa2@`g_bzdNZ^cDR61vHm!ABIGC;_1Ic%_|(NFJb;BEZ3y z)9G6Uu9$7UOQCz)IWhq-ZuLFga1!&mxLbdoT%!3JgJiMmg9f%u+V@WhX-!$G9|Biv z1phP%iOtSb@BxbW1sL&}qHr+#ddZ$LvvLiG%*9$YczWWZOSxX>Q@RdDo_V_G^qzaa zdT*x7Gw-b*7D#>15~v*hcuf|itUAqY)=kqWj>cLzhGZ}fMHCW4Q7HE3ZZ(s<&tfbR z3%5bX6SDNJUe}K3^%ay`C5wxDy3KJDtBbj6_?jMFk0Y`%59myJTPbHOQW1{JFJLRx z)meUF8*wriG1lb_WXPtEbrRc}xFMk!pXW-K40l=a;xVTFy_@&2eO}LFm`?glBqm;C zlN#1ysN{zvvI$F_tJzL-)g$Gf5zvt-Mf<0(^etys1&T$g4vqG=vlgV@D-pi#+rL=E z&lVRt&%d5;KfOCXPl+M_24D{|(^uU1J(AgZaYNJNT-8Y4T)0%aa9x*5m&wI* zkZvtVd*LWuM@QtS<>Os&KyoSP{DrqfxruvgM%$%IOqP;W4knns`#u+5$Z0Is+}5_} z`Yg(LwUfcvcQq=0-}my?^v_&-eRH#;v-8=$gKrD_)n3WVB#0z~wG>gjVdZZd1;!u< z6R_%K>h;zqVHzS*l9-2;!*>0PoyW7RhuG9|INO)=ovB)DRR;%q#L_u#l2yIZ&=xv3OHl5lj zR8dY=Q5HF9(o<|KQpI+U;+F$UXo$;y%Jp@v{xSa~Zh$g+q)Ip8ts^>l%9}vqK?Fla z1)M4+36kGixDdni5uI4Mzp$rLPWfRh76YKVwl0e1>xpy+qtX`r%9(WM&uzZW4}UO4 zWKU}v1y_;uT*1R@IuVH0R_AdOg`D@Uq!~LI9Qfa!t}Vj@vs!VmwcB z705fCxdnR5%851_Ni_Q4z5QFt-{cTo_=%e?G=g%}I|}>H$;?{97Df8xECJx@uKl;(h4Ei>J;) z#!|*N7)xDig$T^(>f&I=k|=q2a>G2krbf!MmfTN&W5(Pq9{Q>qsNS1TT-_2L^%?_5 za1z+afncpxCn_=5jh@ZQ_B$_a;*zogA%i8ozw>B`hHa&;2tX}AKmLh6+d!DF%xVTK zJU*30yX+D`PiCSNIk* zU1~IKP*5scUV|VyDwY+X@FiCnFLLF#^W5{Dsr8K;gLYjBT#1gU*1+owPt3aYo)@Z5 zo<1#6_RBvs;0i@^`rV+Oltf4zprGCR!b11W!-?W6R7`J@G~H~IkMRY;OsQgSnKK@B ztUQ=97-W2q`!zco%aWMFjzWk%7LEsu*NS(~3YbY`2>X|-D8e!VlLWtn5Ch54*_FQ4 zBn!Sg*_JtT$;zOx*0C{_6owwi|U0SOscn~_^+Cygg7Pr@_+SK0V?`DBsrL#N_> z?w1{&tfrIWB0!kuLH+gbQEcJEO2fVLxsKYEoQi$P;5bNzl_JE#F3savFrP!Z zU0^|CKt4oDj!`B{g9vs5kur#u1xp#xa1t8oN*hxKR|hrSkYzeCIxl+COUaQ*YaXm= zo#bF^%fJX*xM^mrD1{F#Xrgp|FK+5{XGFXoI=Aiu{p^N(DDJbzz16~4hob!nYKtdf zI~w?Yf9J1p=^uw3j9OhhedjY?d%C(hizr{(f};AhL>6ibSsk-O2J{VaSa_4m6#a~e zB;r9RiK*YCg>Y6($8&-J_{W-c+Ojg$w2OkTz86;(R5N{n&7ab^ zU(4YQxWR&$fdsMf-Oi$NGKiS;`;1yYhmjTn7{9TI?S>sOwajRkEOu;$KM{=Ie&#y6 zFZe2cf#7siFe+Vx01Zsi04xbGAVE#^;iZMro>xa*ebX~xF`B4nzITJZo)>+MXnD+N zhS=pYliKfWKclt&^@Zih+tq+}UH`L<>(i|JKbtrA{x0jbm8QGIvN1+p&T$T8>S3_p zA3yQo!EEsLFm6YBrzCkZyZ$1^q#0`(gKV~E z{M=33>~J-4>GinVLjeK6`$oX$^d#x|kcqdqbzkz7nV`vU%8jtsa>cpwT1P>g!kk@Q zJ$08>R)$0+_J&K?05+q6VZ1sl8o!j6z+lkEsYl43abMA9WH@eW=;hC z$=zJVZpi9{*|@-T!@ifBubY$SZjLOy=iNZj;J&6G*6>eecJV`T3M&lWLGQS&b!-=V zLV#M5s?Q1eB&+Dr5mRBY8!1T&wM%sYF}c4SUWc1;h&!WK06U&|_V0!_Ol&}7s(_f` z2KL>WvhvTv(^Y(S_^AVehHC_|i5lP5oBt54u9+qFq?AIW@L=)^WL<_jeU9$Siya;7 z&nwHy%1v4xdUtN-d#5-4+%DZ^j(zjlQWwXR2T;dKh9COZv<;1yn-XlfiKM?IL}ElP zh(7)-c%hrdAW@V$y0@0zTFJl07xMU&r{r>f;n^TB24sE`FM z7{2g_ZOmv*-ND7!(6;sRx~^$`nZ)b#cS9l>#>S2vSllw#$OtEXw!trqR zIdC#C@=}1kSD;xn|709V7TC>(7XeF2B^a#PLw6+!1<6~Jedtm;7)|o9O`?@G`lJ$h zE%Oda!f08hsenp}|3dE_DUVGd4QD=w+uLP+@K*b|uUWKVPp&R@8~jRK9g|ubvlpfY zuE|FI@!7aFmm|z5aW9kn)!3&KJWuqT`+l1F#{?*@~+|i z==N1Co5y&c{`}M=CXVw3HacVhkL6;am!$e}2~Yp^ zMw&i8hTFt=LDaiY%*5mV=DhfFn$}c5+(*7)9?2Y#fd^s< zizh(JO%5lwxQe3HTC2zIP8Ob4R@iZ9hk=$rtgQIEpsQ2~n*wM}-dZFD6fG!Z@#JXX z(o|5Ml$N(N!VHce$rK#F)ph3Z z*~c8?c@56{MP8Rr_Jrj#yN4N>`_i+0frPGcmB-8WtBB6I*-=TJB_q=bh)yWxP%mA~ zo*~K6vx^t+n7JDrmfFw}ve)$5$4#_!Nl;Yu&)nQ=VPVN-w5Vo(Uvu?%D{5D_)nTDQ zy1Tx#94#C+|)OgB_6jk5sxz_ zw@0i0G@iS(n2f{z{SX^K8gC*+E4gCHbZ_rnRJuw`Bph997jiqG1#ae#SaQRAEy)Wj zc566Jufna~Kg7e6`Ljv~M{l!Bwhdk(3z6*F4rlFmm5+wLKO|e zJQMkIbpRIr;(PJkZ7Scgh8h+QG-HS%0PK^+n>=(s&+tUq$)6mTyGq?T8ml7J+?ONr7Fy9{i0Ok zv8Edu;)oJ*a)-%E@!*nYIjBA0q}#)t_HWsCi(}fSN5#+I)9N!ykX5ejE;0Z)Zr(|lU2Qexc|)G%wK}C+kgggNO+u(?sDi?`&@#8smQzEV zdTC((Y)eRt=c5!EDuWdmfjv8G$N<~tIM8D~JHDc5sy4p1B$UDT8IydTf<02Pd$cfoGkvK_8{7h;){>Bj%?AfjVu6E%>Eq;y8DiPw(G*xi zJx0*nli>QjT*Q(qBeU%X3nCui4jn#^G;;2AScjOAC!!dE9}g6^4QD&KB3DfgJRV4N zHQ}t&I< z?FBzXPPozKaxc_47rZ3TecO&hnBkk>1tSxUM zSXyo@L+8=#YD`Q+L$@dUpj&s)+6=x;7wdaV)_j5#PT#wM$K52V(0leUVLv>45F-Yc z^~^sT?$ohO*@V1nuV>ysfQBSMhdqNScT4l*j@usA^7MlWRm-#+9LKyE*J_ftHE+?~ z#R}Xu%qF{UE+-!-Cx^<-B$XDrIxF&Jde!1K+SzT&6gCPspf9Llwces{zv~uwSbDT} zdo(lp3S`Gp0a0W4ofKNeN1~m?_nF-S2Dpq;HmYqGLQHu)aa0N-uVrCWsC&N z&wWH-zu}1+ zT8|n%Txp739W*Y0hy!xjHvbt~fV4Uw&|M-LWisz@cnul2+N}MVpleP9tl(ENaw{RL zph-p=%AX>VfW_QvLmYuZ%E)&VafZn>qUyoz0MUsPJ zyQdRZlZwQyx2b$iUKuYS3952|m{3*(wjU=BW*ToW$m=Pu{QIHKCKF$@ekQ4u7X#DK z)_avSy^FIhmbrU0A|AUTpIyF(A>czIh10!kBou{Io{5ruF&?x(Y5nZ>tVkjr#h~v! zMq||Ud_L}RZ|q^uN6|UH8yU2yS)h-cQKa8N1a|LmSK#qg3r=;aqwXU+h=UfZM(vXI^^9DzCt7{eXKX$Y4k}* zDkWb@xLhKITZHOYyvB(R8*S5IxKVwKI(<_m_foO|9k?54RU z$M+wf@j}V;+}EI}Y$$s;e$s44(-EL}7KOvS%YiZAIl#SB8HM0EHRpB$u>zRY0QjfZ zv{+FtBnjP(z4qTSI1>_7sSlcUsk=rgrB{ePFS@5m62UmV#aQ`!0dXjm&DunLLairL zs&bZtoteT;4e28hD>l@6(R~SwSNWu$R7=(#Fui{eDn`adVdEgdh-Q90+j5pjvvR&P zUKS`GBUh)nt$`c?4WGYRVlhkt!2srm{>!`UD8iDLJcx#mayjWGZeOh`kSWV2u;=KL zbT>|K)Fl=J$QYL#Xb(E{R^85ZC@tY?jH*rKY=h)doEgVC(ptYEcYoqo^4AVxi}};;2+-kM895>uKdN^areB*JbTSCE~<%p z{`l%(A#JZY`n2u9#P-nX=`hhdKrDk@iH&?@eh|xiK{zFBQ2Mh*l4BEl+=~IJLDd1x zXD6{@v5&D@&k{tLOZpq0?FD_-HXo>QdCnG>%ZAMV83Fhwj5)k-bYWF~AbPgwNfMGx zCgdnsEJ-{%EF{>XdT8Q(eRJDQO~p4Op#;Q*gSlBPfQqE2d^{GhJTp%*J_y+s+F^w_ z{2}M5b^a6B8X)D0JHwyK{xpS+E2Ed00N335A1!x8AIJ6G(ksJzZ0ahx;^H^-*{Tz~3NdND#;s_VxTcWCQT7+=$dntVi24F&(i;JOe`xSU+ zi`lg26Gwbj?lbK#X_YFw1RD*7eH?h-s!v|AeYv~ab-4KEW^w3|cUGK4++`35lqBkL zY>I^AG)N+b;#0#x7+UAQ@L$)UtR0Qn|JB&GX8cKG|KutnydBo{bEo;4-b#q}p-De? z)n{C%w>WaC`$}9!?Y*R|F%1&C#}i|ZttLmsuQquc1UK{Y^4R?2%*{A+VV{|U*CCAk zRhIMM-yL{*TBST6_8+tbiSP%F@Bbz(7TLTm=orr?Qn7U~3X%EdQudDF z!Oy&|^^y4e4Sic&$JQCOki^1jASNTzlsIh!cLDRTeti^Ne`ng0Hu-Yv;SvN2L8{N3 zJ2p9!i+r2FDCQJ<{i)bx^&62!05{gWKa-8%qQ`gcNmIMm51VNL?U!X&)TgeyST0c# zSU4QkA13eC5WnT3@Zm^@?)o(J(_GUH_6qjDM9nT|<`z>^YZKm#e`x!ZLzm?l{3-m5 zA_tT*C!d9(wk%!`UFSRu@)uzUzYroPwi?1Usv2jyc#WO->phNSjC*Ud4WpsibF*Q6 zrw=+q_%MzHMkJdxtGc8RtlS^>PtH2dPYie$p)n|A?_g*0cpM{kem&L@`usD0LOijNemKQb`+iXV)}1`%Fny%# zQ;;kZCK*Rp&AVW@69AS^B;iHarYtQ4#4E)n_?Ec@fTuN=mkMTP8~k|4(@o_L)bCGy zD>8DZ#2A$Au{^OE{RBr^-QDOSWueJc$KLzx1w}{q{Y>*o&|`q##l_*Hf*}TSlV3ct z?71wOTsvgf`o1;I_IKPr)YqGVMbKJ2j;L1&1L&6xG|r%X!kl+ZK{lbKr^B|k^?XL4 zQGoKKmHx-cPCdPHkwwnkbd2fCl)TvQb#+|$Pvyj!_srf=r87cTWSwtuM)xvm!`ZXK zzXllDXGl`ubNCMgv)2b=$Il&1H?;^X&iS5)Do+oMJy5RwXl;sWNCIgus2t35Y!2fP zKsD|piSAD^CW!U)&EpvbTbMH$WzV!PP%@D=zv?URw@-bK)^BeGF6kEyf6EUZ+u5ED zJkQFAjz|c-Y$#mk4f&kSMj-|JOtg_0MeVY)6aDdh#pXfM!%+F&keKvQN-Xa8;h#E( zZA*tprcI+plmSP&(bUTx_v^t>-_5N1)2N8AAX&EX12z1UE$STwMOA51?%mMmVEp0nifGc_gt^nP$CXO2vsZKn zhxZY_*Od)#Zs3+bDNsTzoJ=WBS^AHX8ZlX(g0`77L>eEu)o|Vd1FQ4^asrF@H;2C0 z?Y`TJ4(&HgBB{F{+Kl#0n@+lU=x?_!rd^F+evPm|6KD|GLTD^kAW|w;%`ecJ<9C=~ zJgGsDz9g4}5;;bZnAJP;9qq}M%8qdp6j4iE^gou#5vNVy@wy__lGlDz&%_^%hyH@+ ztD~GL;2`Pv!YA{wtRvXCH;;!CSg~YSfeTKDc-#M`>leP)gSUqe#aXy33(4@eMIs%TRT|r7!8roN)0O&LK($iLbeLB2!zyIpZ zy}+B$0X*1SUVcsRvYBA3fi0uQ_G_X6#%`%~?gF+NXKjXNBrEl9}jb#!L7 zfF+W`e{1|}u&Qd+-?cJ9n&)t1dDHbR3Cuz`H)SVl&N!$Fiw*S%dt13kF|!rbf~iN6#BxTscxCxB(7 z5W&$^&HsC8*Sm#rVfUG881Z{$H@2XkQ2qMT+KL{O<#14L4L=XNTS?~48uIcS+<&UfV!-J(JI{aXBgPEz5 z6{*P)N9XsRp7nz2n{KS{wKYFV!`TPJ6U4b|UnwVWMKB0T!AlZu&jp|ISm>%4lmc)K zNqg#i57n(^VFEn9xumu=4oC5aBw&|021cy-_}|P}xrt6PgJ40AD=yZTu)$+)2ycDm z<6NV|kBfwX!^e(F?+2%>hdt}+mWXvAij5$w$Jq#?=ly>H1{3-0wnqRV1Ee}4k06Sk zWxLBd7|7P9x?$7NXaofl7qP(J0~{XTee`}F7kx;*_fn6O%6JaSBME1tXs1B4k!Yb(V% zEYec0mmCBjm?CE^7K?Xp-@keDYyabqj_=$%ynWYJs|j&Xt>%l>(b4(Y#>m?UmII4Z zh%1zt8_lcKC=-Yq%i9+&UisuliVs~_1+;B@vY1y@)wv{h%B_)wL1rdi0frDlbOF+# zbL58hHj_sNH@f3MG<6gP074PFMiSu+=ehM;S(R#(Fv+CH^ZCtti#zwrWwRm0l*@Km zg%Hc}biS(Y9Ug|V+`fG22)PNOOc<4$mo7c?sb_!nbD!P(%b!FP2t!zjGbDo)EYPxx z+1!nkdP4`UD_{fz9zMMH_S@H9e)*+ue(Q}NyfP-1stHX!QbUL_$b?z8HmPmJ_ag~m zR0axdUC-;q=H@1`35X0L!bUn@Jbd@gQ&)Cl6o^C#$u)6>y%ohG#G+=%mel#^vq%_J z8;4k|s-67a8f%@I2{CuX0|ent+YgreYH$eC{lHU#rb#FQY`&=L#gdW|k)_;Pm6~>O zG7l&7+4kl~u3SD|uJ&%+m|WPd+P2oDB8$EIci(yIm8&nFzjFDDzw=KgySun}f!UZT z5?XD&r?r;Z@vwswKoPfYU%UF^H@@~K*RQ?S9G?`xHc@F>L>cjzQ=+y-QyDRckW(ll z1#VJX*9#-%5N2`KYUUt9EI`2_=d7z{zW0!uERnN93<0D}Mg%h!aUN(>&Dmhexr@{= ztoM=qdsm$Ij_B~9s{=8SG5gZKr}k$=Z->bQ8leTGiRV7`>woKSe(c$2d1nVf zVh~7xIa+}L_8{(`xBTM|efatR^k1I;((m27{?<6zIBTftF|G{nqB3i8~g@q!ITm}Yqh@9WU87nIq)C|i=eN_>$WM%QdruyHPtf20M@EK$7RvjV(-EJ&0F=+ ze8N(&jfAi`$zIE-z?>GBJ?&Ap=b|`N+{?@9lSD)1EKO2|%l*H1!w=IYrCCj4eZz0Agc7LWYns zvOtNzOn%J{!ysmmxOkqL0*B3Nc5dU`xea7(HHR2ENYX4Jcp}C`rb-4kG|(k@>+Dm5 zeNVHxPS+5Ot|dakER6oNG$1vtnTrnR;S%;I1V z=FG@M2`&^21_}911{bpn#sSnWmpdD?^V8|Uox3l6^E*HI&Uf0|_s4C!v9nt@O&|%e zj3N4+6qw{Q*(9|y<|3=DDyr)V(KHm+Hla%dKp2)`S&Ez#uZm@KsSbJYGOz zDr#Ccx>}{>s#M*Gk?QKFuf6{DKl$2AKe`r}uUx!D%&2P$Q9xR^@=t#0%1DITHm_Eq z?KFf@2++h?#Vt%^q~xMIA*f|z0*Q<81PVfdL1YLZw!YlAY)~WPvN%4OTgp2-JG0Gm zRb5wYJDE)2&`$?lfLwvaTv?jC@@^QE3~~99R)d#jeTB{lL?YsjT+^(VQZ^R|b2WA{gM!Tpp#TbI1)&rv zL86v(dT?;?!nePD?fWl{bADobn+(XxMU*d$N@yn2C^U-2xG0cwy;=rgA}}+&C&@x0 zEaKp70t7510YQ{VEqcw=x2hDbjA^5CTrI1nu7gN98kOTwD541&lLU!_q1AehG^QT- z;vd66ZgR%QiHM1XSX^q8*qXgp@=Ta>5RlM*B*s|xVN%TN!CH>XJ*^N%peItyxR1d z%#4X<vFi9kdz^iX5U(!TwzVn$@Tm*z z(H?3kYfd6mmIc&^nMsJ)M=DIrK$IZnZ-oovU_xq^HE=(zCn%dSl#K|~qL8StRb8*z z#t2l#Fe*Y>NC@J8y6$p6P#1P>Qm;Nv14VD&)0Q4Hqf-QOB(?+nnRz-I7a^1qSy7!V z?%%n4|JI%A;nA!`*^#Lc5tw|u!``eCCCU(mm_!6&N(3+y3w5D{nLtcgQz&CGDzc@M z)pFUaVp;5LZ8rM{J7qa$&WjUj+mZ18?RUTN)vw6k-`=QKRZ2Q4Mw96@i1>!PNObLO zpP#_H5THWD)JTaHu9t>vrpnSgG{eYTSeqeZ88vkSrgBu)RlWb7(xt@`X9L;b$N*sauXA?0TdZUKp>a;B~Tz5Nt_hLW-;M5-F@rkJ3oHC zJ)B>hY{aUuHfhd5B#IC$aEwKXtPC+T(r%4cn29+Fh|OVo43Ae`@Xo4jY7H7fEMibI zt(x8GMp`cGswyOoqNJwMrj2Iw?|%71UZeRG0R7APlFhm+4GuM&{%pLCW$_VP2!Vr` z<+^Qho5+FWfm_qYGK#>{5l=>c^>2TEy0e9GF;8_(CZl4N+vCF%TeW0djz_cEEXG*5 zE-z7xQQOqEZCf`vXP5~{#V{*ZsmewyNOh`L%Yx(Pc)T;&yfB$9_l|ya^~F2aZu!V zx9^k^F6{1ZY;1U7$(qYp3bCoBHmQ5DhzIMYX+RWMVu*#uZon8-Zp+DNYxCSF6uGIj zZqF6v`RT?6$Nd|(uD|@lJ3o0F$BVJa1U%u0oChltk)Jr8!@6b7J&t^v%g8#>PU@Te zHYm%uiO@~e%!s<@kpGSWWX1+I3)JTdo%FM(q#~Ae=voVUrV+na`>1JVL!xn7y$z5e zA`Zb_gFsGOoXy%grIZd251pv-$&Y+^dg1)2oGo*+Y7-{YD%3gWax^N&r4ib;t(uyI z25<8@5D~ND$?fxPs+SLs>-kd5o*Zq=;%L;;?KiI9dGnq7H*OWJP0Dd-HPw~Nnhh;^ z?Qh1;#9sZMo_>SZcK`15=4@>_XRVS7eILdLRsG(bha!YC<-jmb_J-Hl5xC`b0=+X& zTyGqADX@WHmQ}L?K9wL+gX;Oo#=)KYuN)ja*xP^l6VGg2+#MBx7$?1_!0V8HFc|6Pab0!c4CIKVs)TpW3qno#0J3gLnp1b(eliN>S-rU(pflR5@ zwq7ndkiUPR;5+zl6KEHo>>)y$|{mnb~ zE`I#!a%o?TzLB+uMr7 zZ*ihP=4+JR-eWT(%a%1rFqm2H(+u@z4#C)~Q(BABOpbLkC&DI}v1Kz6i7{AK*PA9a z5EU_|oZC8y(1b#UHTy?54-Vh{={uWG>^yP#sohJv+vj(uTQdnoa@uqSQ8LSQ-8Rel za=x;vx%S$d^Zkd*gX5r>#WKK}#j;+kwx%1V3b2$#j8O?yQ>UEA%w&ch>M?ltX*R`= zG_XiJ?05FVPL*Nml$G5{b;@t-p01=_=cYrmlMFGMh@{{0FjJ^eAR?nKfm2@rB7&;E zAI5TMO8Dz^f0Gv=!Nii8nyM))M8tcfDP;>>gkWrxUN5+^+5qqfw29pYb zND0~0>9N&UHLOd+pd<=b6Gb#Cz>zo@Ii|^lK$OX(OXH*`;RayVXloVz@m`YqDa8&}q|mq$Q$M#R~} zhtMBNNs|~N zgbXkvg6OHgNG|~-o>UpJK|yTDYcoP4WS>fM2lyo>CNfx0r$W4zpRRkf=e6tJo!@hf zJX}Lxvag$aI7Q9Cu7A|qK17ymP74ZxI%b}!YdVuEJsNr0@IEv+`q+meN%jNSI>OrZ zmO2BT1$1IgN|{;Fbp%Yh%$+=*bskOJXFCj)tVEhUG7^$?yeh^-q`toi7+cq@CK}e< ze3!#|Y$AE);O6dgWa}5VKv04jGBNq2^O3MKBxBu5on`7iRHtwWek1f*y1ShYQYO|r z=@6&hFJup&#QG!RqhKR5Wa57QWR83B8EcoT_z4WO24nLMW|x5bxun_yHc5L=WaD6F z1~y96{omOP1V>(*SyE*HYOIF$tp5z5_RN~(;M!-djts;U*ds%~`A28ZDnI%2T9p{c zUqxuG%7BPi%H32BVDh`Kzt;E3H`b#^*LDF}%3aDqq#&O*IeZHMIY6#U(Mg$-L7mjm z0Y-zN{r)%0hGCkomPa7=6yJ~t+P7KOOk-x?Y@Tn>+RpE~Grl*O>Xtnp-4yOXYs~QE z^}UZQqP06cjqR@|sc!2Y;5Hn}^oZsFP4CH5f^!gSQfi$b3YX?ftGi)#ka;n%k z+%zmIoI7|q9NgtLV35Ha;c5yq6N9LVgia`fI+PuCM|#%>QZwn~mHzzO#zV#X*e1_o ze|bFz1Mt5AIK<`#7&A;=0000bbVXQnWMOn=I%9HWVRU5xGB7bXEif}JF*Z~&H##yh zIx#gXFflqXFfNdrPXGV_C3HntbYx+4WjbwdWNBu305UK!I4v+UEipD!F*iCgGCDCe ZD=;xSFfd=uBl7?N002ovPDHLkV1giXlv4lz literal 0 HcmV?d00001 From ac4334f45b33d8a5f7acf2fc7fae7c75e669dbec Mon Sep 17 00:00:00 2001 From: Khia Yi <33336624+khiayi@users.noreply.github.com> Date: Sat, 17 Mar 2018 00:42:28 +0800 Subject: [PATCH 20/98] Created Portfolio files for team --- docs/team/LeKhangTai.adoc | 66 ++++++++++++++++++++++++++++++++++++ docs/team/QiuHaohao.adoc | 66 ++++++++++++++++++++++++++++++++++++ docs/team/chantiongley.adoc | 66 ++++++++++++++++++++++++++++++++++++ docs/team/khiayi.adoc | 66 ++++++++++++++++++++++++++++++++++++ docs/team/victortardieu.adoc | 66 ++++++++++++++++++++++++++++++++++++ 5 files changed, 330 insertions(+) create mode 100644 docs/team/LeKhangTai.adoc create mode 100644 docs/team/QiuHaohao.adoc create mode 100644 docs/team/chantiongley.adoc create mode 100644 docs/team/khiayi.adoc create mode 100644 docs/team/victortardieu.adoc diff --git a/docs/team/LeKhangTai.adoc b/docs/team/LeKhangTai.adoc new file mode 100644 index 000000000000..ec192bb61ed3 --- /dev/null +++ b/docs/team/LeKhangTai.adoc @@ -0,0 +1,66 @@ += Le Khang Tai - Project Portfolio +:imagesDir: ../images +:stylesDir: ../stylesheets + +== PROJECT: Catalogue + +--- + +== Overview + +* This is a desktop Catalogue application. It has a GUI but most of the user interactions happen using a CLI (Command Line Interface). +* It is a Java application intended for librarians, students and guests using the library. + +== Summary of contributions + +* *Major enhancement*: +** What it does: +** Justification: +** Highlights: +** Credits: + +* *Minor enhancement*: + +* *Code contributed*: + +* *Other contributions*: + +** Project management: + +** Enhancements to existing features: + +** Documentation: + +** Community: + +** Tools: + +_{you can add/remove categories in the list above}_ + +== Contributions to the User Guide + + +|=== +|_Given below are sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users._ +|=== + +include::../UserGuide.adoc[tag=undoredo] + +include::../UserGuide.adoc[tag=dataencryption] + +== Contributions to the Developer Guide + +|=== +|_Given below are sections I contributed to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project._ +|=== + +include::../DeveloperGuide.adoc[tag=undoredo] + +include::../DeveloperGuide.adoc[tag=dataencryption] + + +== PROJECT: PowerPointLabs + +--- + +_{Optionally, you may include other projects in your portfolio.}_ diff --git a/docs/team/QiuHaohao.adoc b/docs/team/QiuHaohao.adoc new file mode 100644 index 000000000000..41e38f9bf5d6 --- /dev/null +++ b/docs/team/QiuHaohao.adoc @@ -0,0 +1,66 @@ += Qiu Hao Ze - Project Portfolio +:imagesDir: ../images +:stylesDir: ../stylesheets + +== PROJECT: Catalogue + +--- + +== Overview + +* This is a desktop Catalogue application. It has a GUI but most of the user interactions happen using a CLI (Command Line Interface). +* It is a Java application intended for librarians, students and guests using the library. + +== Summary of contributions + +* *Major enhancement*: +** What it does: +** Justification: +** Highlights: +** Credits: + +* *Minor enhancement*: + +* *Code contributed*: + +* *Other contributions*: + +** Project management: + +** Enhancements to existing features: + +** Documentation: + +** Community: + +** Tools: + +_{you can add/remove categories in the list above}_ + +== Contributions to the User Guide + + +|=== +|_Given below are sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users._ +|=== + +include::../UserGuide.adoc[tag=undoredo] + +include::../UserGuide.adoc[tag=dataencryption] + +== Contributions to the Developer Guide + +|=== +|_Given below are sections I contributed to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project._ +|=== + +include::../DeveloperGuide.adoc[tag=undoredo] + +include::../DeveloperGuide.adoc[tag=dataencryption] + + +== PROJECT: PowerPointLabs + +--- + +_{Optionally, you may include other projects in your portfolio.}_ diff --git a/docs/team/chantiongley.adoc b/docs/team/chantiongley.adoc new file mode 100644 index 000000000000..775129e9f871 --- /dev/null +++ b/docs/team/chantiongley.adoc @@ -0,0 +1,66 @@ += Chan Tiong Ley - Project Portfolio +:imagesDir: ../images +:stylesDir: ../stylesheets + +== PROJECT: Catalogue + +--- + +== Overview + +* This is a desktop Catalogue application. It has a GUI but most of the user interactions happen using a CLI (Command Line Interface). +* It is a Java application intended for librarians, students and guests using the library. + +== Summary of contributions + +* *Major enhancement*: +** What it does: +** Justification: +** Highlights: +** Credits: + +* *Minor enhancement*: + +* *Code contributed*: + +* *Other contributions*: + +** Project management: + +** Enhancements to existing features: + +** Documentation: + +** Community: + +** Tools: + +_{you can add/remove categories in the list above}_ + +== Contributions to the User Guide + + +|=== +|_Given below are sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users._ +|=== + +include::../UserGuide.adoc[tag=undoredo] + +include::../UserGuide.adoc[tag=dataencryption] + +== Contributions to the Developer Guide + +|=== +|_Given below are sections I contributed to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project._ +|=== + +include::../DeveloperGuide.adoc[tag=undoredo] + +include::../DeveloperGuide.adoc[tag=dataencryption] + + +== PROJECT: PowerPointLabs + +--- + +_{Optionally, you may include other projects in your portfolio.}_ diff --git a/docs/team/khiayi.adoc b/docs/team/khiayi.adoc new file mode 100644 index 000000000000..127b929dce13 --- /dev/null +++ b/docs/team/khiayi.adoc @@ -0,0 +1,66 @@ += Wong Khia Yi - Project Portfolio +:imagesDir: ../images +:stylesDir: ../stylesheets + +== PROJECT: Catalogue + +--- + +== Overview + +* This is a desktop Catalogue application. It has a GUI but most of the user interactions happen using a CLI (Command Line Interface). +* It is a Java application intended for librarians, students and guests using the library. + +== Summary of contributions + +* *Major enhancement*: +** What it does: +** Justification: +** Highlights: +** Credits: + +* *Minor enhancement*: + +* *Code contributed*: + +* *Other contributions*: + +** Project management: + +** Enhancements to existing features: + +** Documentation: + +** Community: + +** Tools: + +_{you can add/remove categories in the list above}_ + +== Contributions to the User Guide + + +|=== +|_Given below are sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users._ +|=== + +include::../UserGuide.adoc[tag=undoredo] + +include::../UserGuide.adoc[tag=dataencryption] + +== Contributions to the Developer Guide + +|=== +|_Given below are sections I contributed to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project._ +|=== + +include::../DeveloperGuide.adoc[tag=undoredo] + +include::../DeveloperGuide.adoc[tag=dataencryption] + + +== PROJECT: PowerPointLabs + +--- + +_{Optionally, you may include other projects in your portfolio.}_ diff --git a/docs/team/victortardieu.adoc b/docs/team/victortardieu.adoc new file mode 100644 index 000000000000..a38d92d2928b --- /dev/null +++ b/docs/team/victortardieu.adoc @@ -0,0 +1,66 @@ += Victor Tardieu - Project Portfolio +:imagesDir: ../images +:stylesDir: ../stylesheets + +== PROJECT: Catalogue + +--- + +== Overview + +* This is a desktop Catalogue application. It has a GUI but most of the user interactions happen using a CLI (Command Line Interface). +* It is a Java application intended for librarians, students and guests using the library. + +== Summary of contributions + +* *Major enhancement*: +** What it does: +** Justification: +** Highlights: +** Credits: + +* *Minor enhancement*: + +* *Code contributed*: + +* *Other contributions*: + +** Project management: + +** Enhancements to existing features: + +** Documentation: + +** Community: + +** Tools: + +_{you can add/remove categories in the list above}_ + +== Contributions to the User Guide + + +|=== +|_Given below are sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users._ +|=== + +include::../UserGuide.adoc[tag=undoredo] + +include::../UserGuide.adoc[tag=dataencryption] + +== Contributions to the Developer Guide + +|=== +|_Given below are sections I contributed to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project._ +|=== + +include::../DeveloperGuide.adoc[tag=undoredo] + +include::../DeveloperGuide.adoc[tag=dataencryption] + + +== PROJECT: PowerPointLabs + +--- + +_{Optionally, you may include other projects in your portfolio.}_ From d5b134cc17a9136e24882cefeb0ca44963494cec Mon Sep 17 00:00:00 2001 From: Khia Yi <33336624+khiayi@users.noreply.github.com> Date: Sat, 17 Mar 2018 00:42:44 +0800 Subject: [PATCH 21/98] Updated README --- README.adoc | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/README.adoc b/README.adoc index dd8928ac464b..03aedd2db9e3 100644 --- a/README.adoc +++ b/README.adoc @@ -1,4 +1,4 @@ -= Address Book (Level 4) += Catalogue ifdef::env-github,env-browser[:relfileprefix: docs/] https://travis-ci.org/CS2103JAN2018-T16-B1/main[image:https://travis-ci.org/CS2103JAN2018-T16-B1/main.svg?branch=master[Build Status]] @@ -13,24 +13,18 @@ ifndef::env-github[] image::images/Ui.png[width="600"] endif::[] -* This is a desktop Address Book application. It has a GUI but most of the user interactions happen using a CLI (Command Line Interface). -* It is a Java sample application intended for students learning Software Engineering while using Java as the main programming language. -* It is *written in OOP fashion*. It provides a *reasonably well-written* code example that is *significantly bigger* (around 6 KLoC)than what students usually write in beginner-level SE modules. -* What's different from https://github.com/se-edu/addressbook-level3[level 3]: -** A more sophisticated GUI that includes a list panel and an in-built Browser. -** More test cases, including automated GUI testing. -** Support for _Build Automation_ using Gradle and for _Continuous Integration_ using Travis CI. +* This is a desktop Catalogue application. It has a GUI but most of the user interactions happen using a CLI (Command Line Interface). +* It is a Java application intended for librarians, students and guests using the library. == Site Map * <> * <> -* <> * <> * <> == Acknowledgements - +* This sample application is adapted from https://github.com/se-edu/[se-edu]. * Some parts of this sample application were inspired by the excellent http://code.makery.ch/library/javafx-8-tutorial/[Java FX tutorial] by _Marco Jakob_. * Libraries used: https://github.com/TomasMikula/EasyBind[EasyBind], https://github.com/TestFX/TestFX[TextFX], https://bitbucket.org/controlsfx/controlsfx/[ControlsFX], https://github.com/FasterXML/jackson[Jackson], https://github.com/google/guava[Guava], https://github.com/junit-team/junit4[JUnit4] From 51b1e003703063f4344e77991f3c38865a419783 Mon Sep 17 00:00:00 2001 From: Khia Yi <33336624+khiayi@users.noreply.github.com> Date: Sat, 17 Mar 2018 00:45:03 +0800 Subject: [PATCH 22/98] AboutUs:changed link for photo of khiayi --- docs/AboutUs.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.adoc b/docs/AboutUs.adoc index 99e17758b823..4e82b57187aa 100644 --- a/docs/AboutUs.adoc +++ b/docs/AboutUs.adoc @@ -46,7 +46,7 @@ Responsibilities: Dev Ops + Threading ''' === Wong Khia Yi -image::khiayi.jpg[width="150", align="left"] +image::khiayi.png[width="150", align="left"] {empty}[https://github.com/khiayi[github]] [<>] Role: Developer + From 887a6850d128a5464910dc62abd30c93611a0e77 Mon Sep 17 00:00:00 2001 From: Khia Yi <33336624+khiayi@users.noreply.github.com> Date: Sat, 17 Mar 2018 00:49:00 +0800 Subject: [PATCH 23/98] Updated AboutUs and ContactUs --- docs/AboutUs.adoc | 2 +- docs/ContactUs.adoc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/AboutUs.adoc b/docs/AboutUs.adoc index 4e82b57187aa..02fff88da07b 100644 --- a/docs/AboutUs.adoc +++ b/docs/AboutUs.adoc @@ -3,7 +3,7 @@ :imagesDir: images :stylesDir: stylesheets -AddressBook - Level 4 was developed by the https://CS2103JAN2018-T16-B1.github.io/docs/Team.html[CS2103JAN2018-T16-B1] team. + +Catalogue was developed by the https://CS2103JAN2018-T16-B1.github.io/docs/Team.html[CS2103JAN2018-T16-B1] team. + _{The dummy content given below serves as a placeholder to be used by future forks of the project.}_ + {empty} + We are a team based in the http://www.comp.nus.edu.sg[School of Computing, National University of Singapore]. diff --git a/docs/ContactUs.adoc b/docs/ContactUs.adoc index 6da7df4a9f91..9f9410c14eae 100644 --- a/docs/ContactUs.adoc +++ b/docs/ContactUs.adoc @@ -3,4 +3,4 @@ * *Bug reports, Suggestions* : Post in our https://github.com/CS2103JAN2018-T16-B1/main/issues[issue tracker] if you noticed bugs or have suggestions on how to improve. * *Contributing* : We welcome pull requests. Follow the process described https://github.com/oss-generic/process[here] -* *Email us* : You can also reach us at `damith [at] comp.nus.edu.sg` +* *Email us* : You can also reach us at `e0031399 [at] u.nus.edu` From c1892891982d7117adaea79c17b7660ae4e836af Mon Sep 17 00:00:00 2001 From: "LAPTOP-VHS80CCS\\lucas" Date: Sat, 17 Mar 2018 09:19:47 +0800 Subject: [PATCH 24/98] Update Photo --- docs/images/LeKhangTai | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/images/LeKhangTai diff --git a/docs/images/LeKhangTai b/docs/images/LeKhangTai new file mode 100644 index 000000000000..e69de29bb2d1 From b5ddc2aa627b19fb4639eada91d9f330497dbcc7 Mon Sep 17 00:00:00 2001 From: "LAPTOP-VHS80CCS\\lucas" Date: Sat, 17 Mar 2018 09:41:35 +0800 Subject: [PATCH 25/98] Re: Update Photo of Le Khang Tai --- docs/images/LeKhangTai | 0 docs/images/LeKhangTai.jpg | Bin 0 -> 66818 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 docs/images/LeKhangTai create mode 100644 docs/images/LeKhangTai.jpg diff --git a/docs/images/LeKhangTai b/docs/images/LeKhangTai deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/docs/images/LeKhangTai.jpg b/docs/images/LeKhangTai.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f89da349a81351591ec598218f0d2369de9a614a GIT binary patch literal 66818 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 literal 0 HcmV?d00001 From 342bbf2d79b20f9cf4d66a1ca2d4d2c4aa656e53 Mon Sep 17 00:00:00 2001 From: Qiu Haohao Date: Sun, 18 Mar 2018 15:23:18 +0800 Subject: [PATCH 26/98] Add Haoze's photo --- docs/images/Haoze.jpg | Bin 0 -> 224702 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/images/Haoze.jpg diff --git a/docs/images/Haoze.jpg b/docs/images/Haoze.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0fef1d3937855a56e8a3a5f5a9334dada7f9ae59 GIT binary patch literal 224702 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�G2xluq?VBki1 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
4th street
- - - + + + Hans Muster 948asdf2424 hans@example.com
4th street
-
- + + diff --git a/src/test/data/XmlAddressBookStorageTest/invalidPersonAddressBook.xml b/src/test/data/XmlAddressBookStorageTest/invalidPersonAddressBook.xml index cfa128e72828..936d32b8c7d2 100644 --- a/src/test/data/XmlAddressBookStorageTest/invalidPersonAddressBook.xml +++ b/src/test/data/XmlAddressBookStorageTest/invalidPersonAddressBook.xml @@ -1,10 +1,10 @@ - - - + + + Ha!ns Mu@ster 9482424 hans@example.com
4th street
-
-
+ + diff --git a/src/test/data/XmlSerializableAddressBookTest/invalidPersonAddressBook.xml b/src/test/data/XmlSerializableAddressBookTest/invalidPersonAddressBook.xml index 13d5b1cb1c8a..0c06d8c81358 100644 --- a/src/test/data/XmlSerializableAddressBookTest/invalidPersonAddressBook.xml +++ b/src/test/data/XmlSerializableAddressBookTest/invalidPersonAddressBook.xml @@ -1,10 +1,10 @@ - - - + + + Hans Muster 9482424 hans@exam!32ple
4th street
-
-
+ + diff --git a/src/test/data/XmlSerializableAddressBookTest/invalidTagAddressBook.xml b/src/test/data/XmlSerializableAddressBookTest/invalidTagAddressBook.xml index 5fa697c22c4c..a75e25b9c0dc 100644 --- a/src/test/data/XmlSerializableAddressBookTest/invalidTagAddressBook.xml +++ b/src/test/data/XmlSerializableAddressBookTest/invalidTagAddressBook.xml @@ -1,5 +1,5 @@ - + frie!nds - + diff --git a/src/test/data/XmlSerializableAddressBookTest/typicalPersonsAddressBook.xml b/src/test/data/XmlSerializableAddressBookTest/typicalPersonsAddressBook.xml index f647a77a8c39..eaa9c0db738d 100644 --- a/src/test/data/XmlSerializableAddressBookTest/typicalPersonsAddressBook.xml +++ b/src/test/data/XmlSerializableAddressBookTest/typicalPersonsAddressBook.xml @@ -1,52 +1,52 @@ - - - + + + Alice Pauline 85355255 alice@example.com
123, Jurong West Ave 6, #08-111
friends -
- + + Benson Meier 98765432 johnd@example.com
311, Clementi Ave 2, #02-25
owesMoney friends -
- + + Carl Kurz 95352563 heinz@example.com
wall street
-
- + + Daniel Meier 87652533 cornelia@example.com
10th street
-
- + + Elle Meyer 9482224 werner@example.com
michegan ave
-
- + + Fiona Kunz 9482427 lydia@example.com
little tokyo
-
- + + George Best 9482442 anna@example.com
4th street
-
+ friends owesMoney -
+ diff --git a/src/test/data/XmlUtilTest/invalidPersonField.xml b/src/test/data/XmlUtilTest/invalidPersonField.xml index ba49c971e884..723141fa8da7 100644 --- a/src/test/data/XmlUtilTest/invalidPersonField.xml +++ b/src/test/data/XmlUtilTest/invalidPersonField.xml @@ -1,9 +1,9 @@ - - + + Hans Muster 9482asf424 hans@example
4th street
friends -
+ diff --git a/src/test/data/XmlUtilTest/missingPersonField.xml b/src/test/data/XmlUtilTest/missingPersonField.xml index c0da5c86d080..8e9b9ea719e1 100644 --- a/src/test/data/XmlUtilTest/missingPersonField.xml +++ b/src/test/data/XmlUtilTest/missingPersonField.xml @@ -1,8 +1,8 @@ - - + + 9482424 hans@example
4th street
friends -
+ diff --git a/src/test/data/XmlUtilTest/tempAddressBook.xml b/src/test/data/XmlUtilTest/tempAddressBook.xml index 41eeb8eb391a..8657ddd207c3 100644 --- a/src/test/data/XmlUtilTest/tempAddressBook.xml +++ b/src/test/data/XmlUtilTest/tempAddressBook.xml @@ -1,6 +1,6 @@ - - + + 1 John Doe @@ -8,8 +8,8 @@ - + Friends - + diff --git a/src/test/data/XmlUtilTest/validAddressBook.xml b/src/test/data/XmlUtilTest/validAddressBook.xml index 6265778674d3..5ac4a9bd0af6 100644 --- a/src/test/data/XmlUtilTest/validAddressBook.xml +++ b/src/test/data/XmlUtilTest/validAddressBook.xml @@ -1,57 +1,57 @@ - - + + Hans Muster 9482424 hans@example.com
4th street
-
- + + Ruth Mueller 87249245 ruth@example.com
81th street
-
- + + Heinz Kurz 95352563 heinz@example.com
wall street
-
- + + Cornelia Meier 87652533 cornelia@example.com
10th street
-
- + + Werner Meyer 9482224 werner@example.com
michegan ave
-
- + + Lydia Kunz 9482427 lydia@example.com
little tokyo
-
- + + Anna Best 9482442 anna@example.com
4th street
-
- + + Stefan Meier 8482424 stefan@example.com
little india
-
- + + Martin Mueller 8482131 hans@example.com
chicago ave
-
-
+ + diff --git a/src/test/data/XmlUtilTest/validPerson.xml b/src/test/data/XmlUtilTest/validPerson.xml index c029008d54f4..d55d3e91811d 100644 --- a/src/test/data/XmlUtilTest/validPerson.xml +++ b/src/test/data/XmlUtilTest/validPerson.xml @@ -1,8 +1,8 @@ - + Hans Muster 9482424 hans@example
4th street
friends -
+ diff --git a/src/test/java/guitests/guihandles/PersonCardHandle.java b/src/test/java/guitests/guihandles/PersonCardHandle.java index d337d3a4cee9..c438cf0c3b09 100644 --- a/src/test/java/guitests/guihandles/PersonCardHandle.java +++ b/src/test/java/guitests/guihandles/PersonCardHandle.java @@ -8,7 +8,7 @@ import javafx.scene.layout.Region; /** - * Provides a handle to a person card in the person list panel. + * Provides a handle to a book card in the book list panel. */ public class PersonCardHandle extends NodeHandle { private static final String ID_FIELD_ID = "#id"; diff --git a/src/test/java/guitests/guihandles/PersonListPanelHandle.java b/src/test/java/guitests/guihandles/PersonListPanelHandle.java index 40564bb2d960..f1641f6966bf 100644 --- a/src/test/java/guitests/guihandles/PersonListPanelHandle.java +++ b/src/test/java/guitests/guihandles/PersonListPanelHandle.java @@ -4,7 +4,7 @@ import java.util.Optional; import javafx.scene.control.ListView; -import seedu.address.model.person.Person; +import seedu.address.model.book.Book; import seedu.address.ui.PersonCard; /** @@ -28,7 +28,7 @@ public PersonCardHandle getHandleToSelectedCard() { List personList = getRootNode().getSelectionModel().getSelectedItems(); if (personList.size() != 1) { - throw new AssertionError("Person list size expected 1."); + throw new AssertionError("Book list size expected 1."); } return new PersonCardHandle(personList.get(0).getRoot()); @@ -55,14 +55,14 @@ public boolean isAnyCardSelected() { } /** - * Navigates the listview to display and select the person. + * Navigates the listview to display and select the book. */ - public void navigateToCard(Person person) { + public void navigateToCard(Book book) { List cards = getRootNode().getItems(); - Optional matchingCard = cards.stream().filter(card -> card.person.equals(person)).findFirst(); + Optional matchingCard = cards.stream().filter(card -> card.book.equals(book)).findFirst(); if (!matchingCard.isPresent()) { - throw new IllegalArgumentException("Person does not exist."); + throw new IllegalArgumentException("Book does not exist."); } guiRobot.interact(() -> { @@ -73,21 +73,21 @@ public void navigateToCard(Person person) { } /** - * Returns the person card handle of a person associated with the {@code index} in the list. + * Returns the book card handle of a book associated with the {@code index} in the list. */ public PersonCardHandle getPersonCardHandle(int index) { - return getPersonCardHandle(getRootNode().getItems().get(index).person); + return getPersonCardHandle(getRootNode().getItems().get(index).book); } /** - * Returns the {@code PersonCardHandle} of the specified {@code person} in the list. + * Returns the {@code PersonCardHandle} of the specified {@code book} in the list. */ - public PersonCardHandle getPersonCardHandle(Person person) { + public PersonCardHandle getPersonCardHandle(Book book) { Optional handle = getRootNode().getItems().stream() - .filter(card -> card.person.equals(person)) + .filter(card -> card.book.equals(book)) .map(card -> new PersonCardHandle(card.getRoot())) .findFirst(); - return handle.orElseThrow(() -> new IllegalArgumentException("Person does not exist.")); + return handle.orElseThrow(() -> new IllegalArgumentException("Book does not exist.")); } /** diff --git a/src/test/java/seedu/address/TestApp.java b/src/test/java/seedu/address/TestApp.java index 2ff4bb77b030..faaefe6950ae 100644 --- a/src/test/java/seedu/address/TestApp.java +++ b/src/test/java/seedu/address/TestApp.java @@ -71,7 +71,7 @@ protected UserPrefs initPrefs(UserPrefsStorage storage) { } /** - * Returns a defensive copy of the address book data stored inside the storage file. + * Returns a defensive copy of the catalogue data stored inside the storage file. */ public Catalogue readStorageCatalogue() { try { diff --git a/src/test/java/seedu/address/commons/util/XmlUtilTest.java b/src/test/java/seedu/address/commons/util/XmlUtilTest.java index 6d0eb1d59615..97e22db2f6b9 100644 --- a/src/test/java/seedu/address/commons/util/XmlUtilTest.java +++ b/src/test/java/seedu/address/commons/util/XmlUtilTest.java @@ -27,11 +27,11 @@ public class XmlUtilTest { private static final String TEST_DATA_FOLDER = FileUtil.getPath("src/test/data/XmlUtilTest/"); private static final File EMPTY_FILE = new File(TEST_DATA_FOLDER + "empty.xml"); private static final File MISSING_FILE = new File(TEST_DATA_FOLDER + "missing.xml"); - private static final File VALID_FILE = new File(TEST_DATA_FOLDER + "validAddressBook.xml"); + private static final File VALID_FILE = new File(TEST_DATA_FOLDER + "validCatalogue.xml"); private static final File MISSING_PERSON_FIELD_FILE = new File(TEST_DATA_FOLDER + "missingPersonField.xml"); private static final File INVALID_PERSON_FIELD_FILE = new File(TEST_DATA_FOLDER + "invalidPersonField.xml"); private static final File VALID_PERSON_FILE = new File(TEST_DATA_FOLDER + "validPerson.xml"); - private static final File TEMP_FILE = new File(TestUtil.getFilePathInSandboxFolder("tempAddressBook.xml")); + private static final File TEMP_FILE = new File(TestUtil.getFilePathInSandboxFolder("tempCatalogue.xml")); private static final String INVALID_PHONE = "9482asf424"; @@ -141,6 +141,6 @@ public void saveDataToFile_validFile_dataSaved() throws Exception { * Test class annotated with {@code XmlRootElement} to allow unmarshalling of .xml data to {@code XmlAdaptedPerson} * objects. */ - @XmlRootElement(name = "person") + @XmlRootElement(name = "book") private static class XmlAdaptedPersonWithRootElement extends XmlAdaptedPerson {} } diff --git a/src/test/java/seedu/address/logic/LogicManagerTest.java b/src/test/java/seedu/address/logic/LogicManagerTest.java index dab45263a7bd..ab9913b74db4 100644 --- a/src/test/java/seedu/address/logic/LogicManagerTest.java +++ b/src/test/java/seedu/address/logic/LogicManagerTest.java @@ -90,7 +90,7 @@ private void assertCommandFailure(String inputCommand, Class expectedExceptio * Executes the command, confirms that the result message is correct and that the expected exception is thrown, * and also confirms that the following two parts of the LogicManager object's state are as expected:
* - the internal model manager data are same as those in the {@code expectedModel}
- * - {@code expectedModel}'s address book was saved to the storage file. + * - {@code expectedModel}'s catalogue was saved to the storage file. */ private void assertCommandBehavior(Class expectedException, String inputCommand, String expectedMessage, Model expectedModel) { diff --git a/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java b/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java index 9ca132de4a93..8d5ead283bcd 100644 --- a/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java +++ b/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java @@ -12,7 +12,7 @@ import seedu.address.model.Model; import seedu.address.model.ModelManager; import seedu.address.model.UserPrefs; -import seedu.address.model.person.Person; +import seedu.address.model.book.Book; import seedu.address.testutil.PersonBuilder; /** @@ -29,26 +29,26 @@ public void setUp() { @Test public void execute_newPerson_success() throws Exception { - Person validPerson = new PersonBuilder().build(); + Book validBook = new PersonBuilder().build(); Model expectedModel = new ModelManager(model.getCatalogue(), new UserPrefs()); - expectedModel.addPerson(validPerson); + expectedModel.addPerson(validBook); - assertCommandSuccess(prepareCommand(validPerson, model), model, - String.format(AddCommand.MESSAGE_SUCCESS, validPerson), expectedModel); + assertCommandSuccess(prepareCommand(validBook, model), model, + String.format(AddCommand.MESSAGE_SUCCESS, validBook), expectedModel); } @Test public void execute_duplicatePerson_throwsCommandException() { - Person personInList = model.getCatalogue().getPersonList().get(0); - assertCommandFailure(prepareCommand(personInList, model), model, AddCommand.MESSAGE_DUPLICATE_PERSON); + Book bookInList = model.getCatalogue().getPersonList().get(0); + assertCommandFailure(prepareCommand(bookInList, model), model, AddCommand.MESSAGE_DUPLICATE_PERSON); } /** - * Generates a new {@code AddCommand} which upon execution, adds {@code person} into the {@code model}. + * Generates a new {@code AddCommand} which upon execution, adds {@code book} into the {@code model}. */ - private AddCommand prepareCommand(Person person, Model model) { - AddCommand command = new AddCommand(person); + private AddCommand prepareCommand(Book book, Model model) { + AddCommand command = new AddCommand(book); command.setData(model, new CommandHistory(), new UndoRedoStack()); return command; } diff --git a/src/test/java/seedu/address/logic/commands/AddCommandTest.java b/src/test/java/seedu/address/logic/commands/AddCommandTest.java index f8678b5ff808..d6758008220f 100644 --- a/src/test/java/seedu/address/logic/commands/AddCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddCommandTest.java @@ -21,9 +21,9 @@ import seedu.address.model.Catalogue; import seedu.address.model.Model; import seedu.address.model.ReadOnlyCatalogue; -import seedu.address.model.person.Person; -import seedu.address.model.person.exceptions.DuplicatePersonException; -import seedu.address.model.person.exceptions.PersonNotFoundException; +import seedu.address.model.book.Book; +import seedu.address.model.book.exceptions.DuplicatePersonException; +import seedu.address.model.book.exceptions.PersonNotFoundException; import seedu.address.testutil.PersonBuilder; public class AddCommandTest { @@ -40,29 +40,29 @@ public void constructor_nullPerson_throwsNullPointerException() { @Test public void execute_personAcceptedByModel_addSuccessful() throws Exception { ModelStubAcceptingPersonAdded modelStub = new ModelStubAcceptingPersonAdded(); - Person validPerson = new PersonBuilder().build(); + Book validBook = new PersonBuilder().build(); - CommandResult commandResult = getAddCommandForPerson(validPerson, modelStub).execute(); + CommandResult commandResult = getAddCommandForPerson(validBook, modelStub).execute(); - assertEquals(String.format(AddCommand.MESSAGE_SUCCESS, validPerson), commandResult.feedbackToUser); - assertEquals(Arrays.asList(validPerson), modelStub.personsAdded); + assertEquals(String.format(AddCommand.MESSAGE_SUCCESS, validBook), commandResult.feedbackToUser); + assertEquals(Arrays.asList(validBook), modelStub.personsAdded); } @Test public void execute_duplicatePerson_throwsCommandException() throws Exception { ModelStub modelStub = new ModelStubThrowingDuplicatePersonException(); - Person validPerson = new PersonBuilder().build(); + Book validBook = new PersonBuilder().build(); thrown.expect(CommandException.class); thrown.expectMessage(AddCommand.MESSAGE_DUPLICATE_PERSON); - getAddCommandForPerson(validPerson, modelStub).execute(); + getAddCommandForPerson(validBook, modelStub).execute(); } @Test public void equals() { - Person alice = new PersonBuilder().withName("Alice").build(); - Person bob = new PersonBuilder().withName("Bob").build(); + Book alice = new PersonBuilder().withName("Alice").build(); + Book bob = new PersonBuilder().withName("Bob").build(); AddCommand addAliceCommand = new AddCommand(alice); AddCommand addBobCommand = new AddCommand(bob); @@ -79,15 +79,15 @@ public void equals() { // null -> returns false assertFalse(addAliceCommand.equals(null)); - // different person -> returns false + // different book -> returns false assertFalse(addAliceCommand.equals(addBobCommand)); } /** - * Generates a new AddCommand with the details of the given person. + * Generates a new AddCommand with the details of the given book. */ - private AddCommand getAddCommandForPerson(Person person, Model model) { - AddCommand command = new AddCommand(person); + private AddCommand getAddCommandForPerson(Book book, Model model) { + AddCommand command = new AddCommand(book); command.setData(model, new CommandHistory(), new UndoRedoStack()); return command; } @@ -97,7 +97,7 @@ private AddCommand getAddCommandForPerson(Person person, Model model) { */ private class ModelStub implements Model { @Override - public void addPerson(Person person) throws DuplicatePersonException { + public void addPerson(Book book) throws DuplicatePersonException { fail("This method should not be called."); } @@ -113,34 +113,34 @@ public ReadOnlyCatalogue getCatalogue() { } @Override - public void deletePerson(Person target) throws PersonNotFoundException { + public void deletePerson(Book target) throws PersonNotFoundException { fail("This method should not be called."); } @Override - public void updatePerson(Person target, Person editedPerson) + public void updatePerson(Book target, Book editedBook) throws DuplicatePersonException { fail("This method should not be called."); } @Override - public ObservableList getFilteredPersonList() { + public ObservableList getFilteredPersonList() { fail("This method should not be called."); return null; } @Override - public void updateFilteredPersonList(Predicate predicate) { + public void updateFilteredPersonList(Predicate predicate) { fail("This method should not be called."); } } /** - * A Model stub that always throw a DuplicatePersonException when trying to add a person. + * A Model stub that always throw a DuplicatePersonException when trying to add a book. */ private class ModelStubThrowingDuplicatePersonException extends ModelStub { @Override - public void addPerson(Person person) throws DuplicatePersonException { + public void addPerson(Book book) throws DuplicatePersonException { throw new DuplicatePersonException(); } @@ -151,15 +151,15 @@ public ReadOnlyCatalogue getCatalogue() { } /** - * A Model stub that always accept the person being added. + * A Model stub that always accept the book being added. */ private class ModelStubAcceptingPersonAdded extends ModelStub { - final ArrayList personsAdded = new ArrayList<>(); + final ArrayList personsAdded = new ArrayList<>(); @Override - public void addPerson(Person person) throws DuplicatePersonException { - requireNonNull(person); - personsAdded.add(person); + public void addPerson(Book book) throws DuplicatePersonException { + requireNonNull(book); + personsAdded.add(book); } @Override diff --git a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java index 862fbd10eb94..35ec74d0e948 100644 --- a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java +++ b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java @@ -19,9 +19,9 @@ import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.model.Catalogue; import seedu.address.model.Model; -import seedu.address.model.person.NameContainsKeywordsPredicate; -import seedu.address.model.person.Person; -import seedu.address.model.person.exceptions.PersonNotFoundException; +import seedu.address.model.book.Book; +import seedu.address.model.book.NameContainsKeywordsPredicate; +import seedu.address.model.book.exceptions.PersonNotFoundException; import seedu.address.testutil.EditPersonDescriptorBuilder; /** @@ -92,13 +92,13 @@ public static void assertCommandSuccess(Command command, Model actualModel, Stri * Executes the given {@code command}, confirms that
* - a {@code CommandException} is thrown
* - the CommandException message matches {@code expectedMessage}
- * - the address book and the filtered person list in the {@code actualModel} remain unchanged + * - the catalogue and the filtered book list in the {@code actualModel} remain unchanged */ public static void assertCommandFailure(Command command, Model actualModel, String expectedMessage) { // we are unable to defensively copy the model for comparison later, so we can // only do so by copying its components. Catalogue expectedCatalogue = new Catalogue(actualModel.getCatalogue()); - List expectedFilteredList = new ArrayList<>(actualModel.getFilteredPersonList()); + List expectedFilteredList = new ArrayList<>(actualModel.getFilteredPersonList()); try { command.execute(); @@ -111,28 +111,28 @@ public static void assertCommandFailure(Command command, Model actualModel, Stri } /** - * Updates {@code model}'s filtered list to show only the person at the given {@code targetIndex} in the - * {@code model}'s address book. + * Updates {@code model}'s filtered list to show only the book at the given {@code targetIndex} in the + * {@code model}'s catalogue. */ public static void showPersonAtIndex(Model model, Index targetIndex) { assertTrue(targetIndex.getZeroBased() < model.getFilteredPersonList().size()); - Person person = model.getFilteredPersonList().get(targetIndex.getZeroBased()); - final String[] splitName = person.getName().fullName.split("\\s+"); + Book book = model.getFilteredPersonList().get(targetIndex.getZeroBased()); + final String[] splitName = book.getName().fullName.split("\\s+"); model.updateFilteredPersonList(new NameContainsKeywordsPredicate(Arrays.asList(splitName[0]))); assertEquals(1, model.getFilteredPersonList().size()); } /** - * Deletes the first person in {@code model}'s filtered list from {@code model}'s address book. + * Deletes the first book in {@code model}'s filtered list from {@code model}'s catalogue. */ public static void deleteFirstPerson(Model model) { - Person firstPerson = model.getFilteredPersonList().get(0); + Book firstBook = model.getFilteredPersonList().get(0); try { - model.deletePerson(firstPerson); + model.deletePerson(firstBook); } catch (PersonNotFoundException pnfe) { - throw new AssertionError("Person in filtered list must exist in model.", pnfe); + throw new AssertionError("Book in filtered list must exist in model.", pnfe); } } diff --git a/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java index ac98e886befc..8bf2c05979a1 100644 --- a/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java @@ -21,7 +21,7 @@ import seedu.address.model.Model; import seedu.address.model.ModelManager; import seedu.address.model.UserPrefs; -import seedu.address.model.person.Person; +import seedu.address.model.book.Book; /** * Contains integration tests (interaction with the Model, UndoCommand and RedoCommand) and unit tests for @@ -33,13 +33,13 @@ public class DeleteCommandTest { @Test public void execute_validIndexUnfilteredList_success() throws Exception { - Person personToDelete = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); + Book bookToDelete = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); DeleteCommand deleteCommand = prepareCommand(INDEX_FIRST_PERSON); - String expectedMessage = String.format(DeleteCommand.MESSAGE_DELETE_PERSON_SUCCESS, personToDelete); + String expectedMessage = String.format(DeleteCommand.MESSAGE_DELETE_PERSON_SUCCESS, bookToDelete); ModelManager expectedModel = new ModelManager(model.getCatalogue(), new UserPrefs()); - expectedModel.deletePerson(personToDelete); + expectedModel.deletePerson(bookToDelete); assertCommandSuccess(deleteCommand, model, expectedMessage, expectedModel); } @@ -56,13 +56,13 @@ public void execute_invalidIndexUnfilteredList_throwsCommandException() throws E public void execute_validIndexFilteredList_success() throws Exception { showPersonAtIndex(model, INDEX_FIRST_PERSON); - Person personToDelete = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); + Book bookToDelete = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); DeleteCommand deleteCommand = prepareCommand(INDEX_FIRST_PERSON); - String expectedMessage = String.format(DeleteCommand.MESSAGE_DELETE_PERSON_SUCCESS, personToDelete); + String expectedMessage = String.format(DeleteCommand.MESSAGE_DELETE_PERSON_SUCCESS, bookToDelete); Model expectedModel = new ModelManager(model.getCatalogue(), new UserPrefs()); - expectedModel.deletePerson(personToDelete); + expectedModel.deletePerson(bookToDelete); showNoPerson(expectedModel); assertCommandSuccess(deleteCommand, model, expectedMessage, expectedModel); @@ -73,7 +73,7 @@ public void execute_invalidIndexFilteredList_throwsCommandException() { showPersonAtIndex(model, INDEX_FIRST_PERSON); Index outOfBoundIndex = INDEX_SECOND_PERSON; - // ensures that outOfBoundIndex is still in bounds of address book list + // ensures that outOfBoundIndex is still in bounds of catalogue list assertTrue(outOfBoundIndex.getZeroBased() < model.getCatalogue().getPersonList().size()); DeleteCommand deleteCommand = prepareCommand(outOfBoundIndex); @@ -86,19 +86,19 @@ public void executeUndoRedo_validIndexUnfilteredList_success() throws Exception UndoRedoStack undoRedoStack = new UndoRedoStack(); UndoCommand undoCommand = prepareUndoCommand(model, undoRedoStack); RedoCommand redoCommand = prepareRedoCommand(model, undoRedoStack); - Person personToDelete = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); + Book bookToDelete = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); DeleteCommand deleteCommand = prepareCommand(INDEX_FIRST_PERSON); Model expectedModel = new ModelManager(model.getCatalogue(), new UserPrefs()); - // delete -> first person deleted + // delete -> first book deleted deleteCommand.execute(); undoRedoStack.push(deleteCommand); - // undo -> reverts addressbook back to previous state and filtered person list to show all persons + // undo -> reverts catalogue back to previous state and filtered book list to show all persons assertCommandSuccess(undoCommand, model, UndoCommand.MESSAGE_SUCCESS, expectedModel); - // redo -> same first person deleted again - expectedModel.deletePerson(personToDelete); + // redo -> same first book deleted again + expectedModel.deletePerson(bookToDelete); assertCommandSuccess(redoCommand, model, RedoCommand.MESSAGE_SUCCESS, expectedModel); } @@ -119,11 +119,11 @@ public void executeUndoRedo_invalidIndexUnfilteredList_failure() { } /** - * 1. Deletes a {@code Person} from a filtered list. + * 1. Deletes a {@code Book} from a filtered list. * 2. Undo the deletion. - * 3. The unfiltered list should be shown now. Verify that the index of the previously deleted person in the + * 3. The unfiltered list should be shown now. Verify that the index of the previously deleted book in the * unfiltered list is different from the index at the filtered list. - * 4. Redo the deletion. This ensures {@code RedoCommand} deletes the person object regardless of indexing. + * 4. Redo the deletion. This ensures {@code RedoCommand} deletes the book object regardless of indexing. */ @Test public void executeUndoRedo_validIndexFilteredList_samePersonDeleted() throws Exception { @@ -134,17 +134,17 @@ public void executeUndoRedo_validIndexFilteredList_samePersonDeleted() throws Ex Model expectedModel = new ModelManager(model.getCatalogue(), new UserPrefs()); showPersonAtIndex(model, INDEX_SECOND_PERSON); - Person personToDelete = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); - // delete -> deletes second person in unfiltered person list / first person in filtered person list + Book bookToDelete = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); + // delete -> deletes second book in unfiltered book list / first book in filtered book list deleteCommand.execute(); undoRedoStack.push(deleteCommand); - // undo -> reverts addressbook back to previous state and filtered person list to show all persons + // undo -> reverts catalogue back to previous state and filtered book list to show all persons assertCommandSuccess(undoCommand, model, UndoCommand.MESSAGE_SUCCESS, expectedModel); - expectedModel.deletePerson(personToDelete); - assertNotEquals(personToDelete, model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased())); - // redo -> deletes same second person in unfiltered person list + expectedModel.deletePerson(bookToDelete); + assertNotEquals(bookToDelete, model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased())); + // redo -> deletes same second book in unfiltered book list assertCommandSuccess(redoCommand, model, RedoCommand.MESSAGE_SUCCESS, expectedModel); } @@ -170,7 +170,7 @@ public void equals() throws Exception { // null -> returns false assertFalse(deleteFirstCommand.equals(null)); - // different person -> returns false + // different book -> returns false assertFalse(deleteFirstCommand.equals(deleteSecondCommand)); } diff --git a/src/test/java/seedu/address/logic/commands/EditPersonDescriptorTest.java b/src/test/java/seedu/address/logic/commands/EditBookDescriptorTest.java similarity index 98% rename from src/test/java/seedu/address/logic/commands/EditPersonDescriptorTest.java rename to src/test/java/seedu/address/logic/commands/EditBookDescriptorTest.java index bfa7549c690f..46ac252ea7fa 100644 --- a/src/test/java/seedu/address/logic/commands/EditPersonDescriptorTest.java +++ b/src/test/java/seedu/address/logic/commands/EditBookDescriptorTest.java @@ -15,7 +15,7 @@ import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; import seedu.address.testutil.EditPersonDescriptorBuilder; -public class EditPersonDescriptorTest { +public class EditBookDescriptorTest { @Test public void equals() { diff --git a/src/test/java/seedu/address/logic/commands/EditCommandTest.java b/src/test/java/seedu/address/logic/commands/EditCommandTest.java index 84022cbf900c..4954980f3033 100644 --- a/src/test/java/seedu/address/logic/commands/EditCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/EditCommandTest.java @@ -28,7 +28,7 @@ import seedu.address.model.Model; import seedu.address.model.ModelManager; import seedu.address.model.UserPrefs; -import seedu.address.model.person.Person; +import seedu.address.model.book.Book; import seedu.address.testutil.EditPersonDescriptorBuilder; import seedu.address.testutil.PersonBuilder; @@ -41,14 +41,14 @@ public class EditCommandTest { @Test public void execute_allFieldsSpecifiedUnfilteredList_success() throws Exception { - Person editedPerson = new PersonBuilder().build(); - EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(editedPerson).build(); + Book editedBook = new PersonBuilder().build(); + EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(editedBook).build(); EditCommand editCommand = prepareCommand(INDEX_FIRST_PERSON, descriptor); - String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson); + String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedBook); Model expectedModel = new ModelManager(new Catalogue(model.getCatalogue()), new UserPrefs()); - expectedModel.updatePerson(model.getFilteredPersonList().get(0), editedPerson); + expectedModel.updatePerson(model.getFilteredPersonList().get(0), editedBook); assertCommandSuccess(editCommand, model, expectedMessage, expectedModel); } @@ -56,20 +56,20 @@ public void execute_allFieldsSpecifiedUnfilteredList_success() throws Exception @Test public void execute_someFieldsSpecifiedUnfilteredList_success() throws Exception { Index indexLastPerson = Index.fromOneBased(model.getFilteredPersonList().size()); - Person lastPerson = model.getFilteredPersonList().get(indexLastPerson.getZeroBased()); + Book lastBook = model.getFilteredPersonList().get(indexLastPerson.getZeroBased()); - PersonBuilder personInList = new PersonBuilder(lastPerson); - Person editedPerson = personInList.withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB) + PersonBuilder personInList = new PersonBuilder(lastBook); + Book editedBook = personInList.withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB) .withTags(VALID_TAG_HUSBAND).build(); EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB) .withPhone(VALID_PHONE_BOB).withTags(VALID_TAG_HUSBAND).build(); EditCommand editCommand = prepareCommand(indexLastPerson, descriptor); - String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson); + String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedBook); Model expectedModel = new ModelManager(new Catalogue(model.getCatalogue()), new UserPrefs()); - expectedModel.updatePerson(lastPerson, editedPerson); + expectedModel.updatePerson(lastBook, editedBook); assertCommandSuccess(editCommand, model, expectedMessage, expectedModel); } @@ -77,9 +77,9 @@ public void execute_someFieldsSpecifiedUnfilteredList_success() throws Exception @Test public void execute_noFieldSpecifiedUnfilteredList_success() { EditCommand editCommand = prepareCommand(INDEX_FIRST_PERSON, new EditPersonDescriptor()); - Person editedPerson = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); + Book editedBook = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); - String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson); + String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedBook); Model expectedModel = new ModelManager(new Catalogue(model.getCatalogue()), new UserPrefs()); @@ -90,23 +90,23 @@ public void execute_noFieldSpecifiedUnfilteredList_success() { public void execute_filteredList_success() throws Exception { showPersonAtIndex(model, INDEX_FIRST_PERSON); - Person personInFilteredList = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); - Person editedPerson = new PersonBuilder(personInFilteredList).withName(VALID_NAME_BOB).build(); + Book bookInFilteredList = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); + Book editedBook = new PersonBuilder(bookInFilteredList).withName(VALID_NAME_BOB).build(); EditCommand editCommand = prepareCommand(INDEX_FIRST_PERSON, new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB).build()); - String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson); + String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedBook); Model expectedModel = new ModelManager(new Catalogue(model.getCatalogue()), new UserPrefs()); - expectedModel.updatePerson(model.getFilteredPersonList().get(0), editedPerson); + expectedModel.updatePerson(model.getFilteredPersonList().get(0), editedBook); assertCommandSuccess(editCommand, model, expectedMessage, expectedModel); } @Test public void execute_duplicatePersonUnfilteredList_failure() { - Person firstPerson = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); - EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(firstPerson).build(); + Book firstBook = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); + EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(firstBook).build(); EditCommand editCommand = prepareCommand(INDEX_SECOND_PERSON, descriptor); assertCommandFailure(editCommand, model, EditCommand.MESSAGE_DUPLICATE_PERSON); @@ -116,10 +116,10 @@ public void execute_duplicatePersonUnfilteredList_failure() { public void execute_duplicatePersonFilteredList_failure() { showPersonAtIndex(model, INDEX_FIRST_PERSON); - // edit person in filtered list into a duplicate in address book - Person personInList = model.getCatalogue().getPersonList().get(INDEX_SECOND_PERSON.getZeroBased()); + // edit book in filtered list into a duplicate in catalogue + Book bookInList = model.getCatalogue().getPersonList().get(INDEX_SECOND_PERSON.getZeroBased()); EditCommand editCommand = prepareCommand(INDEX_FIRST_PERSON, - new EditPersonDescriptorBuilder(personInList).build()); + new EditPersonDescriptorBuilder(bookInList).build()); assertCommandFailure(editCommand, model, EditCommand.MESSAGE_DUPLICATE_PERSON); } @@ -135,13 +135,13 @@ public void execute_invalidPersonIndexUnfilteredList_failure() { /** * Edit filtered list where index is larger than size of filtered list, - * but smaller than size of address book + * but smaller than size of catalogue */ @Test public void execute_invalidPersonIndexFilteredList_failure() { showPersonAtIndex(model, INDEX_FIRST_PERSON); Index outOfBoundIndex = INDEX_SECOND_PERSON; - // ensures that outOfBoundIndex is still in bounds of address book list + // ensures that outOfBoundIndex is still in bounds of catalogue list assertTrue(outOfBoundIndex.getZeroBased() < model.getCatalogue().getPersonList().size()); EditCommand editCommand = prepareCommand(outOfBoundIndex, @@ -155,21 +155,21 @@ public void executeUndoRedo_validIndexUnfilteredList_success() throws Exception UndoRedoStack undoRedoStack = new UndoRedoStack(); UndoCommand undoCommand = prepareUndoCommand(model, undoRedoStack); RedoCommand redoCommand = prepareRedoCommand(model, undoRedoStack); - Person editedPerson = new PersonBuilder().build(); - Person personToEdit = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); - EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(editedPerson).build(); + Book editedBook = new PersonBuilder().build(); + Book bookToEdit = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); + EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(editedBook).build(); EditCommand editCommand = prepareCommand(INDEX_FIRST_PERSON, descriptor); Model expectedModel = new ModelManager(new Catalogue(model.getCatalogue()), new UserPrefs()); - // edit -> first person edited + // edit -> first book edited editCommand.execute(); undoRedoStack.push(editCommand); - // undo -> reverts addressbook back to previous state and filtered person list to show all persons + // undo -> reverts catalogue back to previous state and filtered book list to show all persons assertCommandSuccess(undoCommand, model, UndoCommand.MESSAGE_SUCCESS, expectedModel); - // redo -> same first person edited again - expectedModel.updatePerson(personToEdit, editedPerson); + // redo -> same first book edited again + expectedModel.updatePerson(bookToEdit, editedBook); assertCommandSuccess(redoCommand, model, RedoCommand.MESSAGE_SUCCESS, expectedModel); } @@ -191,34 +191,34 @@ public void executeUndoRedo_invalidIndexUnfilteredList_failure() { } /** - * 1. Edits a {@code Person} from a filtered list. + * 1. Edits a {@code Book} from a filtered list. * 2. Undo the edit. - * 3. The unfiltered list should be shown now. Verify that the index of the previously edited person in the + * 3. The unfiltered list should be shown now. Verify that the index of the previously edited book in the * unfiltered list is different from the index at the filtered list. - * 4. Redo the edit. This ensures {@code RedoCommand} edits the person object regardless of indexing. + * 4. Redo the edit. This ensures {@code RedoCommand} edits the book object regardless of indexing. */ @Test public void executeUndoRedo_validIndexFilteredList_samePersonEdited() throws Exception { UndoRedoStack undoRedoStack = new UndoRedoStack(); UndoCommand undoCommand = prepareUndoCommand(model, undoRedoStack); RedoCommand redoCommand = prepareRedoCommand(model, undoRedoStack); - Person editedPerson = new PersonBuilder().build(); - EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(editedPerson).build(); + Book editedBook = new PersonBuilder().build(); + EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(editedBook).build(); EditCommand editCommand = prepareCommand(INDEX_FIRST_PERSON, descriptor); Model expectedModel = new ModelManager(new Catalogue(model.getCatalogue()), new UserPrefs()); showPersonAtIndex(model, INDEX_SECOND_PERSON); - Person personToEdit = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); - // edit -> edits second person in unfiltered person list / first person in filtered person list + Book bookToEdit = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); + // edit -> edits second book in unfiltered book list / first book in filtered book list editCommand.execute(); undoRedoStack.push(editCommand); - // undo -> reverts addressbook back to previous state and filtered person list to show all persons + // undo -> reverts catalogue back to previous state and filtered book list to show all persons assertCommandSuccess(undoCommand, model, UndoCommand.MESSAGE_SUCCESS, expectedModel); - expectedModel.updatePerson(personToEdit, editedPerson); - assertNotEquals(model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()), personToEdit); - // redo -> edits same second person in unfiltered person list + expectedModel.updatePerson(bookToEdit, editedBook); + assertNotEquals(model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()), bookToEdit); + // redo -> edits same second book in unfiltered book list assertCommandSuccess(redoCommand, model, RedoCommand.MESSAGE_SUCCESS, expectedModel); } diff --git a/src/test/java/seedu/address/logic/commands/FindCommandTest.java b/src/test/java/seedu/address/logic/commands/FindCommandTest.java index 19ab56514735..08d9c3dbb68c 100644 --- a/src/test/java/seedu/address/logic/commands/FindCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/FindCommandTest.java @@ -21,8 +21,8 @@ import seedu.address.model.Model; import seedu.address.model.ModelManager; import seedu.address.model.UserPrefs; -import seedu.address.model.person.NameContainsKeywordsPredicate; -import seedu.address.model.person.Person; +import seedu.address.model.book.NameContainsKeywordsPredicate; +import seedu.address.model.book.Book; /** * Contains integration tests (interaction with the Model) for {@code FindCommand}. @@ -53,7 +53,7 @@ public void equals() { // null -> returns false assertFalse(findFirstCommand.equals(null)); - // different person -> returns false + // different book -> returns false assertFalse(findFirstCommand.equals(findSecondCommand)); } @@ -84,10 +84,10 @@ private FindCommand prepareCommand(String userInput) { /** * Asserts that {@code command} is successfully executed, and
* - the command feedback is equal to {@code expectedMessage}
- * - the {@code FilteredList} is equal to {@code expectedList}
+ * - the {@code FilteredList} is equal to {@code expectedList}
* - the {@code Catalogue} in model remains the same after executing the {@code command} */ - private void assertCommandSuccess(FindCommand command, String expectedMessage, List expectedList) { + private void assertCommandSuccess(FindCommand command, String expectedMessage, List expectedList) { Catalogue expectedCatalogue = new Catalogue(model.getCatalogue()); CommandResult commandResult = command.execute(); diff --git a/src/test/java/seedu/address/logic/commands/SelectCommandTest.java b/src/test/java/seedu/address/logic/commands/SelectCommandTest.java index 206992089755..40e75529fa1b 100644 --- a/src/test/java/seedu/address/logic/commands/SelectCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/SelectCommandTest.java @@ -67,7 +67,7 @@ public void execute_invalidIndexFilteredList_failure() { showPersonAtIndex(model, INDEX_FIRST_PERSON); Index outOfBoundsIndex = INDEX_SECOND_PERSON; - // ensures that outOfBoundIndex is still in bounds of address book list + // ensures that outOfBoundIndex is still in bounds of catalogue list assertTrue(outOfBoundsIndex.getZeroBased() < model.getCatalogue().getPersonList().size()); assertExecutionFailure(outOfBoundsIndex, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); @@ -91,7 +91,7 @@ public void equals() { // null -> returns false assertFalse(selectFirstCommand.equals(null)); - // different person -> returns false + // different book -> returns false assertFalse(selectFirstCommand.equals(selectSecondCommand)); } diff --git a/src/test/java/seedu/address/logic/commands/UndoableCommandTest.java b/src/test/java/seedu/address/logic/commands/UndoableCommandTest.java index 18bb7b1cf455..1c81b8b37b6f 100644 --- a/src/test/java/seedu/address/logic/commands/UndoableCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/UndoableCommandTest.java @@ -13,8 +13,8 @@ import seedu.address.model.Model; import seedu.address.model.ModelManager; import seedu.address.model.UserPrefs; -import seedu.address.model.person.Person; -import seedu.address.model.person.exceptions.PersonNotFoundException; +import seedu.address.model.book.Book; +import seedu.address.model.book.exceptions.PersonNotFoundException; public class UndoableCommandTest { private final Model model = new ModelManager(getTypicalCatalogue(), new UserPrefs()); @@ -47,7 +47,7 @@ public void redo() { } /** - * Deletes the first person in the model's filtered list. + * Deletes the first book in the model's filtered list. */ class DummyCommand extends UndoableCommand { DummyCommand(Model model) { @@ -56,11 +56,11 @@ class DummyCommand extends UndoableCommand { @Override public CommandResult executeUndoableCommand() throws CommandException { - Person personToDelete = model.getFilteredPersonList().get(0); + Book bookToDelete = model.getFilteredPersonList().get(0); try { - model.deletePerson(personToDelete); + model.deletePerson(bookToDelete); } catch (PersonNotFoundException pnfe) { - fail("Impossible: personToDelete was retrieved from model."); + fail("Impossible: bookToDelete was retrieved from model."); } return new CommandResult(""); } diff --git a/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java b/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java index c9a350c09657..ec0dcaf36432 100644 --- a/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java @@ -34,11 +34,11 @@ import org.junit.Test; import seedu.address.logic.commands.AddCommand; -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.book.Address; +import seedu.address.model.book.Book; +import seedu.address.model.book.Email; +import seedu.address.model.book.Name; +import seedu.address.model.book.Phone; import seedu.address.model.tag.Tag; import seedu.address.testutil.PersonBuilder; @@ -47,44 +47,44 @@ public class AddCommandParserTest { @Test public void parse_allFieldsPresent_success() { - Person expectedPerson = new PersonBuilder().withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB) + Book expectedBook = new PersonBuilder().withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB) .withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_FRIEND).build(); // whitespace only preamble assertParseSuccess(parser, PREAMBLE_WHITESPACE + NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB - + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedPerson)); + + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedBook)); // multiple names - last name accepted assertParseSuccess(parser, NAME_DESC_AMY + NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB - + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedPerson)); + + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedBook)); // multiple phones - last phone accepted assertParseSuccess(parser, NAME_DESC_BOB + PHONE_DESC_AMY + PHONE_DESC_BOB + EMAIL_DESC_BOB - + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedPerson)); + + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedBook)); // multiple emails - last email accepted assertParseSuccess(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_AMY + EMAIL_DESC_BOB - + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedPerson)); + + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedBook)); // multiple addresses - last address accepted assertParseSuccess(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_AMY - + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedPerson)); + + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedBook)); // multiple tags - all accepted - Person expectedPersonMultipleTags = new PersonBuilder().withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB) + Book expectedBookMultipleTags = new PersonBuilder().withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB) .withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB) .withTags(VALID_TAG_FRIEND, VALID_TAG_HUSBAND).build(); assertParseSuccess(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB - + TAG_DESC_HUSBAND + TAG_DESC_FRIEND, new AddCommand(expectedPersonMultipleTags)); + + TAG_DESC_HUSBAND + TAG_DESC_FRIEND, new AddCommand(expectedBookMultipleTags)); } @Test public void parse_optionalFieldsMissing_success() { // zero tags - Person expectedPerson = new PersonBuilder().withName(VALID_NAME_AMY).withPhone(VALID_PHONE_AMY) + Book expectedBook = new PersonBuilder().withName(VALID_NAME_AMY).withPhone(VALID_PHONE_AMY) .withEmail(VALID_EMAIL_AMY).withAddress(VALID_ADDRESS_AMY).withTags().build(); assertParseSuccess(parser, NAME_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY + ADDRESS_DESC_AMY, - new AddCommand(expectedPerson)); + new AddCommand(expectedBook)); } @Test diff --git a/src/test/java/seedu/address/logic/parser/CatalogueParserTest.java b/src/test/java/seedu/address/logic/parser/CatalogueParserTest.java index 94299ac6446e..3f738d9b3ffb 100644 --- a/src/test/java/seedu/address/logic/parser/CatalogueParserTest.java +++ b/src/test/java/seedu/address/logic/parser/CatalogueParserTest.java @@ -29,8 +29,8 @@ import seedu.address.logic.commands.SelectCommand; import seedu.address.logic.commands.UndoCommand; import seedu.address.logic.parser.exceptions.ParseException; -import seedu.address.model.person.NameContainsKeywordsPredicate; -import seedu.address.model.person.Person; +import seedu.address.model.book.Book; +import seedu.address.model.book.NameContainsKeywordsPredicate; import seedu.address.testutil.EditPersonDescriptorBuilder; import seedu.address.testutil.PersonBuilder; import seedu.address.testutil.PersonUtil; @@ -43,9 +43,9 @@ public class CatalogueParserTest { @Test public void parseCommand_add() throws Exception { - Person person = new PersonBuilder().build(); - AddCommand command = (AddCommand) parser.parseCommand(PersonUtil.getAddCommand(person)); - assertEquals(new AddCommand(person), command); + Book book = new PersonBuilder().build(); + AddCommand command = (AddCommand) parser.parseCommand(PersonUtil.getAddCommand(book)); + assertEquals(new AddCommand(book), command); } @Test @@ -63,10 +63,10 @@ public void parseCommand_delete() throws Exception { @Test public void parseCommand_edit() throws Exception { - Person person = new PersonBuilder().build(); - EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(person).build(); + Book book = new PersonBuilder().build(); + EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(book).build(); EditCommand command = (EditCommand) parser.parseCommand(EditCommand.COMMAND_WORD + " " - + INDEX_FIRST_PERSON.getOneBased() + " " + PersonUtil.getPersonDetails(person)); + + INDEX_FIRST_PERSON.getOneBased() + " " + PersonUtil.getPersonDetails(book)); assertEquals(new EditCommand(INDEX_FIRST_PERSON, descriptor), command); } diff --git a/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java b/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java index 24c138b41a7f..f27cda0878ba 100644 --- a/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java @@ -36,10 +36,10 @@ import seedu.address.commons.core.index.Index; import seedu.address.logic.commands.EditCommand; import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; -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.book.Address; +import seedu.address.model.book.Email; +import seedu.address.model.book.Name; +import seedu.address.model.book.Phone; import seedu.address.model.tag.Tag; import seedu.address.testutil.EditPersonDescriptorBuilder; @@ -94,7 +94,7 @@ public void parse_invalidValue_failure() { // is tested at {@code parse_invalidValueFollowedByValidValue_success()} assertParseFailure(parser, "1" + PHONE_DESC_BOB + INVALID_PHONE_DESC, Phone.MESSAGE_PHONE_CONSTRAINTS); - // while parsing {@code PREFIX_TAG} alone will reset the tags of the {@code Person} being edited, + // while parsing {@code PREFIX_TAG} alone will reset the tags of the {@code Book} being edited, // parsing it together with a valid tag results in error assertParseFailure(parser, "1" + TAG_DESC_FRIEND + TAG_DESC_HUSBAND + TAG_EMPTY, Tag.MESSAGE_TAG_CONSTRAINTS); assertParseFailure(parser, "1" + TAG_DESC_FRIEND + TAG_EMPTY + TAG_DESC_HUSBAND, Tag.MESSAGE_TAG_CONSTRAINTS); diff --git a/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java b/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java index e65143d3b7b0..db52a7b1136e 100644 --- a/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java @@ -9,7 +9,7 @@ import org.junit.Test; import seedu.address.logic.commands.FindCommand; -import seedu.address.model.person.NameContainsKeywordsPredicate; +import seedu.address.model.book.NameContainsKeywordsPredicate; public class FindCommandParserTest { diff --git a/src/test/java/seedu/address/logic/parser/ParserUtilTest.java b/src/test/java/seedu/address/logic/parser/ParserUtilTest.java index 54516c1c5e95..f65a19ccd0e1 100644 --- a/src/test/java/seedu/address/logic/parser/ParserUtilTest.java +++ b/src/test/java/seedu/address/logic/parser/ParserUtilTest.java @@ -18,10 +18,10 @@ import org.junit.rules.ExpectedException; 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.Phone; +import seedu.address.model.book.Address; +import seedu.address.model.book.Email; +import seedu.address.model.book.Name; +import seedu.address.model.book.Phone; import seedu.address.model.tag.Tag; import seedu.address.testutil.Assert; diff --git a/src/test/java/seedu/address/model/CatalogueTest.java b/src/test/java/seedu/address/model/CatalogueTest.java index b56c21e0af88..1e4eba238567 100644 --- a/src/test/java/seedu/address/model/CatalogueTest.java +++ b/src/test/java/seedu/address/model/CatalogueTest.java @@ -16,7 +16,7 @@ import javafx.collections.FXCollections; import javafx.collections.ObservableList; -import seedu.address.model.person.Person; +import seedu.address.model.book.Book; import seedu.address.model.tag.Tag; public class CatalogueTest { @@ -48,9 +48,9 @@ public void resetData_withValidReadOnlyCatalogue_replacesData() { @Test public void resetData_withDuplicatePersons_throwsAssertionError() { // Repeat ALICE twice - List newPersons = Arrays.asList(ALICE, ALICE); + List newBooks = Arrays.asList(ALICE, ALICE); List newTags = new ArrayList<>(ALICE.getTags()); - CatalogueStub newData = new CatalogueStub(newPersons, newTags); + CatalogueStub newData = new CatalogueStub(newBooks, newTags); thrown.expect(AssertionError.class); catalogue.resetData(newData); @@ -69,20 +69,20 @@ public void getTagList_modifyList_throwsUnsupportedOperationException() { } /** - * A stub ReadOnlyCatalogue whose persons and tags lists can violate interface constraints. + * A stub ReadOnlyCatalogue whose books and tags lists can violate interface constraints. */ private static class CatalogueStub implements ReadOnlyCatalogue { - private final ObservableList persons = FXCollections.observableArrayList(); + private final ObservableList books = FXCollections.observableArrayList(); private final ObservableList tags = FXCollections.observableArrayList(); - CatalogueStub(Collection persons, Collection tags) { - this.persons.setAll(persons); + CatalogueStub(Collection books, Collection tags) { + this.books.setAll(books); this.tags.setAll(tags); } @Override - public ObservableList getPersonList() { - return persons; + public ObservableList getPersonList() { + return books; } @Override diff --git a/src/test/java/seedu/address/model/ModelManagerTest.java b/src/test/java/seedu/address/model/ModelManagerTest.java index 9ff92bf21455..609ce6c6900d 100644 --- a/src/test/java/seedu/address/model/ModelManagerTest.java +++ b/src/test/java/seedu/address/model/ModelManagerTest.java @@ -12,7 +12,7 @@ import org.junit.Test; import org.junit.rules.ExpectedException; -import seedu.address.model.person.NameContainsKeywordsPredicate; +import seedu.address.model.book.NameContainsKeywordsPredicate; import seedu.address.testutil.CatalogueBuilder; public class ModelManagerTest { diff --git a/src/test/java/seedu/address/model/UniquePersonListTest.java b/src/test/java/seedu/address/model/UniqueBookListTest.java similarity index 84% rename from src/test/java/seedu/address/model/UniquePersonListTest.java rename to src/test/java/seedu/address/model/UniqueBookListTest.java index ae39646daab2..785b28649bb3 100644 --- a/src/test/java/seedu/address/model/UniquePersonListTest.java +++ b/src/test/java/seedu/address/model/UniqueBookListTest.java @@ -4,9 +4,9 @@ import org.junit.Test; import org.junit.rules.ExpectedException; -import seedu.address.model.person.UniquePersonList; +import seedu.address.model.book.UniquePersonList; -public class UniquePersonListTest { +public class UniqueBookListTest { @Rule public ExpectedException thrown = ExpectedException.none(); diff --git a/src/test/java/seedu/address/model/person/AddressTest.java b/src/test/java/seedu/address/model/book/AddressTest.java similarity index 97% rename from src/test/java/seedu/address/model/person/AddressTest.java rename to src/test/java/seedu/address/model/book/AddressTest.java index 11974544d81d..5c983a912891 100644 --- a/src/test/java/seedu/address/model/person/AddressTest.java +++ b/src/test/java/seedu/address/model/book/AddressTest.java @@ -1,4 +1,4 @@ -package seedu.address.model.person; +package seedu.address.model.book; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; diff --git a/src/test/java/seedu/address/model/person/EmailTest.java b/src/test/java/seedu/address/model/book/EmailTest.java similarity index 98% rename from src/test/java/seedu/address/model/person/EmailTest.java rename to src/test/java/seedu/address/model/book/EmailTest.java index 10187e8eb884..a2fca7cfd5be 100644 --- a/src/test/java/seedu/address/model/person/EmailTest.java +++ b/src/test/java/seedu/address/model/book/EmailTest.java @@ -1,4 +1,4 @@ -package seedu.address.model.person; +package seedu.address.model.book; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; diff --git a/src/test/java/seedu/address/model/person/NameContainsKeywordsPredicateTest.java b/src/test/java/seedu/address/model/book/NameContainsKeywordsPredicateTest.java similarity index 97% rename from src/test/java/seedu/address/model/person/NameContainsKeywordsPredicateTest.java rename to src/test/java/seedu/address/model/book/NameContainsKeywordsPredicateTest.java index 76841215e3a0..dd2e6cf1e399 100644 --- a/src/test/java/seedu/address/model/person/NameContainsKeywordsPredicateTest.java +++ b/src/test/java/seedu/address/model/book/NameContainsKeywordsPredicateTest.java @@ -1,4 +1,4 @@ -package seedu.address.model.person; +package seedu.address.model.book; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -34,7 +34,7 @@ public void equals() { // null -> returns false assertFalse(firstPredicate.equals(null)); - // different person -> returns false + // different book -> returns false assertFalse(firstPredicate.equals(secondPredicate)); } diff --git a/src/test/java/seedu/address/model/person/NameTest.java b/src/test/java/seedu/address/model/book/NameTest.java similarity index 97% rename from src/test/java/seedu/address/model/person/NameTest.java rename to src/test/java/seedu/address/model/book/NameTest.java index b4a356b6f011..e85a303106b5 100644 --- a/src/test/java/seedu/address/model/person/NameTest.java +++ b/src/test/java/seedu/address/model/book/NameTest.java @@ -1,4 +1,4 @@ -package seedu.address.model.person; +package seedu.address.model.book; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; diff --git a/src/test/java/seedu/address/model/person/PhoneTest.java b/src/test/java/seedu/address/model/book/PhoneTest.java similarity index 97% rename from src/test/java/seedu/address/model/person/PhoneTest.java rename to src/test/java/seedu/address/model/book/PhoneTest.java index c721cbbfc048..0cdf546026d7 100644 --- a/src/test/java/seedu/address/model/person/PhoneTest.java +++ b/src/test/java/seedu/address/model/book/PhoneTest.java @@ -1,4 +1,4 @@ -package seedu.address.model.person; +package seedu.address.model.book; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; diff --git a/src/test/java/seedu/address/storage/JsonUserPrefsStorageTest.java b/src/test/java/seedu/address/storage/JsonUserPrefsStorageTest.java index 8129422eb845..68a6483e2dbd 100644 --- a/src/test/java/seedu/address/storage/JsonUserPrefsStorageTest.java +++ b/src/test/java/seedu/address/storage/JsonUserPrefsStorageTest.java @@ -82,8 +82,8 @@ public void readUserPrefs_extraValuesInFile_extraValuesIgnored() throws DataConv private UserPrefs getTypicalUserPrefs() { UserPrefs userPrefs = new UserPrefs(); userPrefs.setGuiSettings(1000, 500, 300, 100); - userPrefs.setCatalogueFilePath("addressbook.xml"); - userPrefs.setCatalogueBookName("TypicalAddressBookName"); + userPrefs.setCatalogueFilePath("catalogue.xml"); + userPrefs.setCatalogueBookName("TypicalCatalogueName"); return userPrefs; } diff --git a/src/test/java/seedu/address/storage/XmlAdaptedPersonTest.java b/src/test/java/seedu/address/storage/XmlAdaptedBookTest.java similarity index 96% rename from src/test/java/seedu/address/storage/XmlAdaptedPersonTest.java rename to src/test/java/seedu/address/storage/XmlAdaptedBookTest.java index c3c91a5c27a7..dcafcb242409 100644 --- a/src/test/java/seedu/address/storage/XmlAdaptedPersonTest.java +++ b/src/test/java/seedu/address/storage/XmlAdaptedBookTest.java @@ -11,13 +11,13 @@ import org.junit.Test; 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.Phone; +import seedu.address.model.book.Address; +import seedu.address.model.book.Email; +import seedu.address.model.book.Name; +import seedu.address.model.book.Phone; import seedu.address.testutil.Assert; -public class XmlAdaptedPersonTest { +public class XmlAdaptedBookTest { private static final String INVALID_NAME = "R@chel"; private static final String INVALID_PHONE = "+651234"; private static final String INVALID_ADDRESS = " "; diff --git a/src/test/java/seedu/address/storage/XmlCatalogueStorageTest.java b/src/test/java/seedu/address/storage/XmlCatalogueStorageTest.java index 7165e2aa4fee..38d88bb8e31d 100644 --- a/src/test/java/seedu/address/storage/XmlCatalogueStorageTest.java +++ b/src/test/java/seedu/address/storage/XmlCatalogueStorageTest.java @@ -53,7 +53,7 @@ public void read_missingFile_emptyResult() throws Exception { public void read_notXmlFormat_exceptionThrown() throws Exception { thrown.expect(DataConversionException.class); - readCatalogue("NotXmlFormatAddressBook.xml"); + readCatalogue("NotXmlFormatCatalogue.xml"); /* IMPORTANT: Any code below an exception-throwing line (like the one above) will be ignored. * That means you should not have more than one exception test in one method @@ -63,18 +63,18 @@ public void read_notXmlFormat_exceptionThrown() throws Exception { @Test public void readCatalogue_invalidPersonCatalogue_throwDataConversionException() throws Exception { thrown.expect(DataConversionException.class); - readCatalogue("invalidPersonAddressBook.xml"); + readCatalogue("invalidPersonCatalogue.xml"); } @Test public void readCatalogue_invalidAndValidPersonCatalogue_throwDataConversionException() throws Exception { thrown.expect(DataConversionException.class); - readCatalogue("invalidAndValidPersonAddressBook.xml"); + readCatalogue("invalidAndValidPersonCatalogue.xml"); } @Test public void readAndSaveCatalogue_allInOrder_success() throws Exception { - String filePath = testFolder.getRoot().getPath() + "TempAddressBook.xml"; + String filePath = testFolder.getRoot().getPath() + "TempCatalogue.xml"; Catalogue original = getTypicalCatalogue(); XmlCatalogueStorage xmlCatalogueStorage = new XmlCatalogueStorage(filePath); diff --git a/src/test/java/seedu/address/storage/XmlSerializableCatalogueTest.java b/src/test/java/seedu/address/storage/XmlSerializableCatalogueTest.java index f5099d8cbe1e..83696d213c63 100644 --- a/src/test/java/seedu/address/storage/XmlSerializableCatalogueTest.java +++ b/src/test/java/seedu/address/storage/XmlSerializableCatalogueTest.java @@ -17,9 +17,9 @@ public class XmlSerializableCatalogueTest { private static final String TEST_DATA_FOLDER = FileUtil.getPath("src/test/data/XmlSerializableCatalogueTest/"); - private static final File TYPICAL_PERSONS_FILE = new File(TEST_DATA_FOLDER + "typicalPersonsAddressBook.xml"); - private static final File INVALID_PERSON_FILE = new File(TEST_DATA_FOLDER + "invalidPersonAddressBook.xml"); - private static final File INVALID_TAG_FILE = new File(TEST_DATA_FOLDER + "invalidTagAddressBook.xml"); + private static final File TYPICAL_PERSONS_FILE = new File(TEST_DATA_FOLDER + "typicalPersonsCatalogue.xml"); + private static final File INVALID_PERSON_FILE = new File(TEST_DATA_FOLDER + "invalidPersonCatalogue.xml"); + private static final File INVALID_TAG_FILE = new File(TEST_DATA_FOLDER + "invalidTagCatalogue.xml"); @Rule public ExpectedException thrown = ExpectedException.none(); diff --git a/src/test/java/seedu/address/testutil/CatalogueBuilder.java b/src/test/java/seedu/address/testutil/CatalogueBuilder.java index 5cee787d0122..5c05adf5a500 100644 --- a/src/test/java/seedu/address/testutil/CatalogueBuilder.java +++ b/src/test/java/seedu/address/testutil/CatalogueBuilder.java @@ -2,8 +2,8 @@ import seedu.address.commons.exceptions.IllegalValueException; import seedu.address.model.Catalogue; -import seedu.address.model.person.Person; -import seedu.address.model.person.exceptions.DuplicatePersonException; +import seedu.address.model.book.Book; +import seedu.address.model.book.exceptions.DuplicatePersonException; import seedu.address.model.tag.Tag; /** @@ -24,13 +24,13 @@ public CatalogueBuilder(Catalogue catalogue) { } /** - * Adds a new {@code Person} to the {@code Catalogue} that we are building. + * Adds a new {@code Book} to the {@code Catalogue} that we are building. */ - public CatalogueBuilder withPerson(Person person) { + public CatalogueBuilder withPerson(Book book) { try { - catalogue.addPerson(person); + catalogue.addPerson(book); } catch (DuplicatePersonException dpe) { - throw new IllegalArgumentException("person is expected to be unique."); + throw new IllegalArgumentException("book is expected to be unique."); } return this; } diff --git a/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java b/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java index 4584bd5044e1..f3d3bb1c400d 100644 --- a/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java +++ b/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java @@ -5,11 +5,11 @@ import java.util.stream.Stream; import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; -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.book.Address; +import seedu.address.model.book.Email; +import seedu.address.model.book.Name; +import seedu.address.model.book.Book; +import seedu.address.model.book.Phone; import seedu.address.model.tag.Tag; /** @@ -28,15 +28,15 @@ public EditPersonDescriptorBuilder(EditPersonDescriptor descriptor) { } /** - * Returns an {@code EditPersonDescriptor} with fields containing {@code person}'s details + * Returns an {@code EditPersonDescriptor} with fields containing {@code book}'s details */ - public EditPersonDescriptorBuilder(Person person) { + public EditPersonDescriptorBuilder(Book book) { descriptor = new EditPersonDescriptor(); - descriptor.setName(person.getName()); - descriptor.setPhone(person.getPhone()); - descriptor.setEmail(person.getEmail()); - descriptor.setAddress(person.getAddress()); - descriptor.setTags(person.getTags()); + descriptor.setName(book.getName()); + descriptor.setPhone(book.getPhone()); + descriptor.setEmail(book.getEmail()); + descriptor.setAddress(book.getAddress()); + descriptor.setTags(book.getTags()); } /** diff --git a/src/test/java/seedu/address/testutil/PersonBuilder.java b/src/test/java/seedu/address/testutil/PersonBuilder.java index b124fc1d73b1..90c9c3e152d7 100644 --- a/src/test/java/seedu/address/testutil/PersonBuilder.java +++ b/src/test/java/seedu/address/testutil/PersonBuilder.java @@ -3,16 +3,16 @@ import java.util.HashSet; import java.util.Set; -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.book.Address; +import seedu.address.model.book.Book; +import seedu.address.model.book.Email; +import seedu.address.model.book.Name; +import seedu.address.model.book.Phone; import seedu.address.model.tag.Tag; import seedu.address.model.util.SampleDataUtil; /** - * A utility class to help with building Person objects. + * A utility class to help with building Book objects. */ public class PersonBuilder { @@ -37,18 +37,18 @@ public PersonBuilder() { } /** - * Initializes the PersonBuilder with the data of {@code personToCopy}. + * Initializes the PersonBuilder with the data of {@code bookToCopy}. */ - public PersonBuilder(Person personToCopy) { - name = personToCopy.getName(); - phone = personToCopy.getPhone(); - email = personToCopy.getEmail(); - address = personToCopy.getAddress(); - tags = new HashSet<>(personToCopy.getTags()); + public PersonBuilder(Book bookToCopy) { + name = bookToCopy.getName(); + phone = bookToCopy.getPhone(); + email = bookToCopy.getEmail(); + address = bookToCopy.getAddress(); + tags = new HashSet<>(bookToCopy.getTags()); } /** - * Sets the {@code Name} of the {@code Person} that we are building. + * Sets the {@code Name} of the {@code Book} that we are building. */ public PersonBuilder withName(String name) { this.name = new Name(name); @@ -56,7 +56,7 @@ public PersonBuilder withName(String name) { } /** - * Parses the {@code tags} into a {@code Set} and set it to the {@code Person} that we are building. + * Parses the {@code tags} into a {@code Set} and set it to the {@code Book} that we are building. */ public PersonBuilder withTags(String ... tags) { this.tags = SampleDataUtil.getTagSet(tags); @@ -64,7 +64,7 @@ public PersonBuilder withTags(String ... tags) { } /** - * Sets the {@code Address} of the {@code Person} that we are building. + * Sets the {@code Address} of the {@code Book} that we are building. */ public PersonBuilder withAddress(String address) { this.address = new Address(address); @@ -72,7 +72,7 @@ public PersonBuilder withAddress(String address) { } /** - * Sets the {@code Phone} of the {@code Person} that we are building. + * Sets the {@code Phone} of the {@code Book} that we are building. */ public PersonBuilder withPhone(String phone) { this.phone = new Phone(phone); @@ -80,15 +80,15 @@ public PersonBuilder withPhone(String phone) { } /** - * Sets the {@code Email} of the {@code Person} that we are building. + * Sets the {@code Email} of the {@code Book} that we are building. */ public PersonBuilder withEmail(String email) { this.email = new Email(email); return this; } - public Person build() { - return new Person(name, phone, email, address, tags); + public Book build() { + return new Book(name, phone, email, address, tags); } } diff --git a/src/test/java/seedu/address/testutil/PersonUtil.java b/src/test/java/seedu/address/testutil/PersonUtil.java index 642d4f174514..21c2b78630b5 100644 --- a/src/test/java/seedu/address/testutil/PersonUtil.java +++ b/src/test/java/seedu/address/testutil/PersonUtil.java @@ -7,30 +7,30 @@ import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; import seedu.address.logic.commands.AddCommand; -import seedu.address.model.person.Person; +import seedu.address.model.book.Book; /** - * A utility class for Person. + * A utility class for Book. */ public class PersonUtil { /** - * Returns an add command string for adding the {@code person}. + * Returns an add command string for adding the {@code book}. */ - public static String getAddCommand(Person person) { - return AddCommand.COMMAND_WORD + " " + getPersonDetails(person); + public static String getAddCommand(Book book) { + return AddCommand.COMMAND_WORD + " " + getPersonDetails(book); } /** - * Returns the part of command string for the given {@code person}'s details. + * Returns the part of command string for the given {@code book}'s details. */ - public static String getPersonDetails(Person person) { + public static String getPersonDetails(Book book) { StringBuilder sb = new StringBuilder(); - sb.append(PREFIX_NAME + person.getName().fullName + " "); - sb.append(PREFIX_PHONE + person.getPhone().value + " "); - sb.append(PREFIX_EMAIL + person.getEmail().value + " "); - sb.append(PREFIX_ADDRESS + person.getAddress().value + " "); - person.getTags().stream().forEach( + sb.append(PREFIX_NAME + book.getName().fullName + " "); + sb.append(PREFIX_PHONE + book.getPhone().value + " "); + sb.append(PREFIX_EMAIL + book.getEmail().value + " "); + sb.append(PREFIX_ADDRESS + book.getAddress().value + " "); + book.getTags().stream().forEach( s -> sb.append(PREFIX_TAG + s.tagName + " ") ); return sb.toString(); diff --git a/src/test/java/seedu/address/testutil/TestUtil.java b/src/test/java/seedu/address/testutil/TestUtil.java index b66c57bc94a6..843a29acc23e 100644 --- a/src/test/java/seedu/address/testutil/TestUtil.java +++ b/src/test/java/seedu/address/testutil/TestUtil.java @@ -6,7 +6,7 @@ import seedu.address.commons.core.index.Index; import seedu.address.commons.util.FileUtil; import seedu.address.model.Model; -import seedu.address.model.person.Person; +import seedu.address.model.book.Book; /** * A utility class for test cases. @@ -32,23 +32,23 @@ public static String getFilePathInSandboxFolder(String fileName) { } /** - * Returns the middle index of the person in the {@code model}'s person list. + * Returns the middle index of the book in the {@code model}'s book list. */ public static Index getMidIndex(Model model) { return Index.fromOneBased(model.getCatalogue().getPersonList().size() / 2); } /** - * Returns the last index of the person in the {@code model}'s person list. + * Returns the last index of the book in the {@code model}'s book list. */ public static Index getLastIndex(Model model) { return Index.fromOneBased(model.getCatalogue().getPersonList().size()); } /** - * Returns the person in the {@code model}'s person list at {@code index}. + * Returns the book in the {@code model}'s book list at {@code index}. */ - public static Person getPerson(Model model, Index index) { + public static Book getPerson(Model model, Index index) { return model.getCatalogue().getPersonList().get(index.getZeroBased()); } } diff --git a/src/test/java/seedu/address/testutil/TypicalPersons.java b/src/test/java/seedu/address/testutil/TypicalPersons.java index 06a7770c5259..da91c35fff8e 100644 --- a/src/test/java/seedu/address/testutil/TypicalPersons.java +++ b/src/test/java/seedu/address/testutil/TypicalPersons.java @@ -16,43 +16,43 @@ import java.util.List; import seedu.address.model.Catalogue; -import seedu.address.model.person.Person; -import seedu.address.model.person.exceptions.DuplicatePersonException; +import seedu.address.model.book.Book; +import seedu.address.model.book.exceptions.DuplicatePersonException; /** - * A utility class containing a list of {@code Person} objects to be used in tests. + * A utility class containing a list of {@code Book} objects to be used in tests. */ public class TypicalPersons { - public static final Person ALICE = new PersonBuilder().withName("Alice Pauline") + public static final Book ALICE = new PersonBuilder().withName("Alice Pauline") .withAddress("123, Jurong West Ave 6, #08-111").withEmail("alice@example.com") .withPhone("85355255") .withTags("friends").build(); - public static final Person BENSON = new PersonBuilder().withName("Benson Meier") + public static final Book BENSON = new PersonBuilder().withName("Benson Meier") .withAddress("311, Clementi Ave 2, #02-25") .withEmail("johnd@example.com").withPhone("98765432") .withTags("owesMoney", "friends").build(); - public static final Person CARL = new PersonBuilder().withName("Carl Kurz").withPhone("95352563") + public static final Book CARL = new PersonBuilder().withName("Carl Kurz").withPhone("95352563") .withEmail("heinz@example.com").withAddress("wall street").build(); - public static final Person DANIEL = new PersonBuilder().withName("Daniel Meier").withPhone("87652533") + public static final Book DANIEL = new PersonBuilder().withName("Daniel Meier").withPhone("87652533") .withEmail("cornelia@example.com").withAddress("10th street").build(); - public static final Person ELLE = new PersonBuilder().withName("Elle Meyer").withPhone("9482224") + public static final Book ELLE = new PersonBuilder().withName("Elle Meyer").withPhone("9482224") .withEmail("werner@example.com").withAddress("michegan ave").build(); - public static final Person FIONA = new PersonBuilder().withName("Fiona Kunz").withPhone("9482427") + public static final Book FIONA = new PersonBuilder().withName("Fiona Kunz").withPhone("9482427") .withEmail("lydia@example.com").withAddress("little tokyo").build(); - public static final Person GEORGE = new PersonBuilder().withName("George Best").withPhone("9482442") + public static final Book GEORGE = new PersonBuilder().withName("George Best").withPhone("9482442") .withEmail("anna@example.com").withAddress("4th street").build(); // Manually added - public static final Person HOON = new PersonBuilder().withName("Hoon Meier").withPhone("8482424") + public static final Book HOON = new PersonBuilder().withName("Hoon Meier").withPhone("8482424") .withEmail("stefan@example.com").withAddress("little india").build(); - public static final Person IDA = new PersonBuilder().withName("Ida Mueller").withPhone("8482131") + public static final Book IDA = new PersonBuilder().withName("Ida Mueller").withPhone("8482131") .withEmail("hans@example.com").withAddress("chicago ave").build(); - // Manually added - Person's details found in {@code CommandTestUtil} - public static final Person AMY = new PersonBuilder().withName(VALID_NAME_AMY).withPhone(VALID_PHONE_AMY) + // Manually added - Book's details found in {@code CommandTestUtil} + public static final Book AMY = new PersonBuilder().withName(VALID_NAME_AMY).withPhone(VALID_PHONE_AMY) .withEmail(VALID_EMAIL_AMY).withAddress(VALID_ADDRESS_AMY).withTags(VALID_TAG_FRIEND).build(); - public static final Person BOB = new PersonBuilder().withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB) + public static final Book BOB = new PersonBuilder().withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB) .withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND, VALID_TAG_FRIEND) .build(); @@ -65,9 +65,9 @@ private TypicalPersons() {} // prevents instantiation */ public static Catalogue getTypicalCatalogue() { Catalogue ab = new Catalogue(); - for (Person person : getTypicalPersons()) { + for (Book book : getTypicalPersons()) { try { - ab.addPerson(person); + ab.addPerson(book); } catch (DuplicatePersonException e) { throw new AssertionError("not possible"); } @@ -75,7 +75,7 @@ public static Catalogue getTypicalCatalogue() { return ab; } - public static List getTypicalPersons() { + public static List getTypicalPersons() { return new ArrayList<>(Arrays.asList(ALICE, BENSON, CARL, DANIEL, ELLE, FIONA, GEORGE)); } } diff --git a/src/test/java/seedu/address/ui/BookCardTest.java b/src/test/java/seedu/address/ui/BookCardTest.java new file mode 100644 index 000000000000..ade3a0b54d0a --- /dev/null +++ b/src/test/java/seedu/address/ui/BookCardTest.java @@ -0,0 +1,72 @@ +package seedu.address.ui; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static seedu.address.ui.testutil.GuiTestAssert.assertCardDisplaysPerson; + +import org.junit.Test; + +import guitests.guihandles.PersonCardHandle; +import seedu.address.model.book.Book; +import seedu.address.testutil.PersonBuilder; + +public class BookCardTest extends GuiUnitTest { + + @Test + public void display() { + // no tags + Book bookWithNoTags = new PersonBuilder().withTags(new String[0]).build(); + PersonCard personCard = new PersonCard(bookWithNoTags, 1); + uiPartRule.setUiPart(personCard); + assertCardDisplay(personCard, bookWithNoTags, 1); + + // with tags + Book bookWithTags = new PersonBuilder().build(); + personCard = new PersonCard(bookWithTags, 2); + uiPartRule.setUiPart(personCard); + assertCardDisplay(personCard, bookWithTags, 2); + } + + @Test + public void equals() { + Book book = new PersonBuilder().build(); + PersonCard personCard = new PersonCard(book, 0); + + // same book, same index -> returns true + PersonCard copy = new PersonCard(book, 0); + assertTrue(personCard.equals(copy)); + + // same object -> returns true + assertTrue(personCard.equals(personCard)); + + // null -> returns false + assertFalse(personCard.equals(null)); + + // different types -> returns false + assertFalse(personCard.equals(0)); + + // different book, same index -> returns false + Book differentBook = new PersonBuilder().withName("differentName").build(); + assertFalse(personCard.equals(new PersonCard(differentBook, 0))); + + // same book, different index -> returns false + assertFalse(personCard.equals(new PersonCard(book, 1))); + } + + /** + * Asserts that {@code personCard} displays the details of {@code expectedBook} correctly and matches + * {@code expectedId}. + */ + private void assertCardDisplay(PersonCard personCard, Book expectedBook, int expectedId) { + guiRobot.pauseForHuman(); + + PersonCardHandle personCardHandle = new PersonCardHandle(personCard.getRoot()); + + // verify id is displayed correctly + assertEquals(Integer.toString(expectedId) + ". ", personCardHandle.getId()); + + // verify book details are displayed correctly + assertCardDisplaysPerson(expectedBook, personCardHandle); + } +} diff --git a/src/test/java/seedu/address/ui/PersonListPanelTest.java b/src/test/java/seedu/address/ui/BookListPanelTest.java similarity index 81% rename from src/test/java/seedu/address/ui/PersonListPanelTest.java rename to src/test/java/seedu/address/ui/BookListPanelTest.java index 906ec2bebc03..d9210ae3f0bd 100644 --- a/src/test/java/seedu/address/ui/PersonListPanelTest.java +++ b/src/test/java/seedu/address/ui/BookListPanelTest.java @@ -15,10 +15,10 @@ import javafx.collections.FXCollections; import javafx.collections.ObservableList; import seedu.address.commons.events.ui.JumpToListRequestEvent; -import seedu.address.model.person.Person; +import seedu.address.model.book.Book; -public class PersonListPanelTest extends GuiUnitTest { - private static final ObservableList TYPICAL_PERSONS = +public class BookListPanelTest extends GuiUnitTest { + private static final ObservableList TYPICAL_BOOKS = FXCollections.observableList(getTypicalPersons()); private static final JumpToListRequestEvent JUMP_TO_SECOND_EVENT = new JumpToListRequestEvent(INDEX_SECOND_PERSON); @@ -27,7 +27,7 @@ public class PersonListPanelTest extends GuiUnitTest { @Before public void setUp() { - PersonListPanel personListPanel = new PersonListPanel(TYPICAL_PERSONS); + PersonListPanel personListPanel = new PersonListPanel(TYPICAL_BOOKS); uiPartRule.setUiPart(personListPanel); personListPanelHandle = new PersonListPanelHandle(getChildNode(personListPanel.getRoot(), @@ -36,12 +36,12 @@ public void setUp() { @Test public void display() { - for (int i = 0; i < TYPICAL_PERSONS.size(); i++) { - personListPanelHandle.navigateToCard(TYPICAL_PERSONS.get(i)); - Person expectedPerson = TYPICAL_PERSONS.get(i); + for (int i = 0; i < TYPICAL_BOOKS.size(); i++) { + personListPanelHandle.navigateToCard(TYPICAL_BOOKS.get(i)); + Book expectedBook = TYPICAL_BOOKS.get(i); PersonCardHandle actualCard = personListPanelHandle.getPersonCardHandle(i); - assertCardDisplaysPerson(expectedPerson, actualCard); + assertCardDisplaysPerson(expectedBook, actualCard); assertEquals(Integer.toString(i + 1) + ". ", actualCard.getId()); } } diff --git a/src/test/java/seedu/address/ui/BrowserPanelTest.java b/src/test/java/seedu/address/ui/BrowserPanelTest.java index 48aab940f8a8..9455927c1494 100644 --- a/src/test/java/seedu/address/ui/BrowserPanelTest.java +++ b/src/test/java/seedu/address/ui/BrowserPanelTest.java @@ -38,7 +38,7 @@ public void display() throws Exception { URL expectedDefaultPageUrl = MainApp.class.getResource(FXML_FILE_FOLDER + DEFAULT_PAGE); assertEquals(expectedDefaultPageUrl, browserPanelHandle.getLoadedUrl()); - // associated web page of a person + // associated web page of a book postNow(selectionChangedEventStub); URL expectedPersonUrl = new URL(BrowserPanel.SEARCH_PAGE_URL + ALICE.getName().fullName.replaceAll(" ", "%20")); diff --git a/src/test/java/seedu/address/ui/PersonCardTest.java b/src/test/java/seedu/address/ui/PersonCardTest.java deleted file mode 100644 index 42f840faa3b4..000000000000 --- a/src/test/java/seedu/address/ui/PersonCardTest.java +++ /dev/null @@ -1,72 +0,0 @@ -package seedu.address.ui; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static seedu.address.ui.testutil.GuiTestAssert.assertCardDisplaysPerson; - -import org.junit.Test; - -import guitests.guihandles.PersonCardHandle; -import seedu.address.model.person.Person; -import seedu.address.testutil.PersonBuilder; - -public class PersonCardTest extends GuiUnitTest { - - @Test - public void display() { - // no tags - Person personWithNoTags = new PersonBuilder().withTags(new String[0]).build(); - PersonCard personCard = new PersonCard(personWithNoTags, 1); - uiPartRule.setUiPart(personCard); - assertCardDisplay(personCard, personWithNoTags, 1); - - // with tags - Person personWithTags = new PersonBuilder().build(); - personCard = new PersonCard(personWithTags, 2); - uiPartRule.setUiPart(personCard); - assertCardDisplay(personCard, personWithTags, 2); - } - - @Test - public void equals() { - Person person = new PersonBuilder().build(); - PersonCard personCard = new PersonCard(person, 0); - - // same person, same index -> returns true - PersonCard copy = new PersonCard(person, 0); - assertTrue(personCard.equals(copy)); - - // same object -> returns true - assertTrue(personCard.equals(personCard)); - - // null -> returns false - assertFalse(personCard.equals(null)); - - // different types -> returns false - assertFalse(personCard.equals(0)); - - // different person, same index -> returns false - Person differentPerson = new PersonBuilder().withName("differentName").build(); - assertFalse(personCard.equals(new PersonCard(differentPerson, 0))); - - // same person, different index -> returns false - assertFalse(personCard.equals(new PersonCard(person, 1))); - } - - /** - * Asserts that {@code personCard} displays the details of {@code expectedPerson} correctly and matches - * {@code expectedId}. - */ - private void assertCardDisplay(PersonCard personCard, Person expectedPerson, int expectedId) { - guiRobot.pauseForHuman(); - - PersonCardHandle personCardHandle = new PersonCardHandle(personCard.getRoot()); - - // verify id is displayed correctly - assertEquals(Integer.toString(expectedId) + ". ", personCardHandle.getId()); - - // verify person details are displayed correctly - assertCardDisplaysPerson(expectedPerson, personCardHandle); - } -} diff --git a/src/test/java/seedu/address/ui/StatusBarFooterTest.java b/src/test/java/seedu/address/ui/StatusBarFooterTest.java index 721aacb10f21..67e059395f69 100644 --- a/src/test/java/seedu/address/ui/StatusBarFooterTest.java +++ b/src/test/java/seedu/address/ui/StatusBarFooterTest.java @@ -56,7 +56,7 @@ public void display() { // initial state assertStatusBarContent(RELATIVE_PATH + STUB_SAVE_LOCATION, SYNC_STATUS_INITIAL); - // after address book is updated + // after catalogue is updated postNow(EVENT_STUB); assertStatusBarContent(RELATIVE_PATH + STUB_SAVE_LOCATION, String.format(SYNC_STATUS_UPDATED, new Date(injectedClock.millis()).toString())); diff --git a/src/test/java/seedu/address/ui/testutil/GuiTestAssert.java b/src/test/java/seedu/address/ui/testutil/GuiTestAssert.java index d21cc2fb3739..6a826cc75007 100644 --- a/src/test/java/seedu/address/ui/testutil/GuiTestAssert.java +++ b/src/test/java/seedu/address/ui/testutil/GuiTestAssert.java @@ -8,7 +8,7 @@ import guitests.guihandles.PersonCardHandle; import guitests.guihandles.PersonListPanelHandle; import guitests.guihandles.ResultDisplayHandle; -import seedu.address.model.person.Person; +import seedu.address.model.book.Book; /** * A set of assertion methods useful for writing GUI tests. @@ -27,33 +27,33 @@ public static void assertCardEquals(PersonCardHandle expectedCard, PersonCardHan } /** - * Asserts that {@code actualCard} displays the details of {@code expectedPerson}. + * Asserts that {@code actualCard} displays the details of {@code expectedBook}. */ - public static void assertCardDisplaysPerson(Person expectedPerson, PersonCardHandle actualCard) { - assertEquals(expectedPerson.getName().fullName, actualCard.getName()); - assertEquals(expectedPerson.getPhone().value, actualCard.getPhone()); - assertEquals(expectedPerson.getEmail().value, actualCard.getEmail()); - assertEquals(expectedPerson.getAddress().value, actualCard.getAddress()); - assertEquals(expectedPerson.getTags().stream().map(tag -> tag.tagName).collect(Collectors.toList()), + public static void assertCardDisplaysPerson(Book expectedBook, PersonCardHandle actualCard) { + assertEquals(expectedBook.getName().fullName, actualCard.getName()); + assertEquals(expectedBook.getPhone().value, actualCard.getPhone()); + assertEquals(expectedBook.getEmail().value, actualCard.getEmail()); + assertEquals(expectedBook.getAddress().value, actualCard.getAddress()); + assertEquals(expectedBook.getTags().stream().map(tag -> tag.tagName).collect(Collectors.toList()), actualCard.getTags()); } /** - * Asserts that the list in {@code personListPanelHandle} displays the details of {@code persons} correctly and + * Asserts that the list in {@code personListPanelHandle} displays the details of {@code books} correctly and * in the correct order. */ - public static void assertListMatching(PersonListPanelHandle personListPanelHandle, Person... persons) { - for (int i = 0; i < persons.length; i++) { - assertCardDisplaysPerson(persons[i], personListPanelHandle.getPersonCardHandle(i)); + public static void assertListMatching(PersonListPanelHandle personListPanelHandle, Book... books) { + for (int i = 0; i < books.length; i++) { + assertCardDisplaysPerson(books[i], personListPanelHandle.getPersonCardHandle(i)); } } /** - * Asserts that the list in {@code personListPanelHandle} displays the details of {@code persons} correctly and + * Asserts that the list in {@code personListPanelHandle} displays the details of {@code books} correctly and * in the correct order. */ - public static void assertListMatching(PersonListPanelHandle personListPanelHandle, List persons) { - assertListMatching(personListPanelHandle, persons.toArray(new Person[0])); + public static void assertListMatching(PersonListPanelHandle personListPanelHandle, List books) { + assertListMatching(personListPanelHandle, books.toArray(new Book[0])); } /** diff --git a/src/test/java/systemtests/AddCommandSystemTest.java b/src/test/java/systemtests/AddCommandSystemTest.java index e54d9a31f636..bb310f326a8f 100644 --- a/src/test/java/systemtests/AddCommandSystemTest.java +++ b/src/test/java/systemtests/AddCommandSystemTest.java @@ -42,12 +42,12 @@ import seedu.address.logic.commands.RedoCommand; import seedu.address.logic.commands.UndoCommand; 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.person.exceptions.DuplicatePersonException; +import seedu.address.model.book.Address; +import seedu.address.model.book.Book; +import seedu.address.model.book.Email; +import seedu.address.model.book.Name; +import seedu.address.model.book.Phone; +import seedu.address.model.book.exceptions.DuplicatePersonException; import seedu.address.model.tag.Tag; import seedu.address.testutil.PersonBuilder; import seedu.address.testutil.PersonUtil; @@ -60,10 +60,10 @@ public void add() throws Exception { /* ------------------------ Perform add operations on the shown unfiltered list ----------------------------- */ - /* Case: add a person without tags to a non-empty address book, command with leading spaces and trailing spaces + /* Case: add a book without tags to a non-empty catalogue, command with leading spaces and trailing spaces * -> added */ - Person toAdd = AMY; + Book toAdd = AMY; String command = " " + AddCommand.COMMAND_WORD + " " + NAME_DESC_AMY + " " + PHONE_DESC_AMY + " " + EMAIL_DESC_AMY + " " + ADDRESS_DESC_AMY + " " + TAG_DESC_FRIEND + " "; assertCommandSuccess(command, toAdd); @@ -79,69 +79,69 @@ public void add() throws Exception { expectedResultMessage = RedoCommand.MESSAGE_SUCCESS; assertCommandSuccess(command, model, expectedResultMessage); - /* Case: add a person with all fields same as another person in the address book except name -> added */ + /* Case: add a book with all fields same as another book in the catalogue except name -> added */ toAdd = new PersonBuilder().withName(VALID_NAME_BOB).withPhone(VALID_PHONE_AMY).withEmail(VALID_EMAIL_AMY) .withAddress(VALID_ADDRESS_AMY).withTags(VALID_TAG_FRIEND).build(); command = AddCommand.COMMAND_WORD + NAME_DESC_BOB + PHONE_DESC_AMY + EMAIL_DESC_AMY + ADDRESS_DESC_AMY + TAG_DESC_FRIEND; assertCommandSuccess(command, toAdd); - /* Case: add a person with all fields same as another person in the address book except phone -> added */ + /* Case: add a book with all fields same as another book in the catalogue except phone -> added */ toAdd = new PersonBuilder().withName(VALID_NAME_AMY).withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_AMY) .withAddress(VALID_ADDRESS_AMY).withTags(VALID_TAG_FRIEND).build(); command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + PHONE_DESC_BOB + EMAIL_DESC_AMY + ADDRESS_DESC_AMY + TAG_DESC_FRIEND; assertCommandSuccess(command, toAdd); - /* Case: add a person with all fields same as another person in the address book except email -> added */ + /* Case: add a book with all fields same as another book in the catalogue except email -> added */ toAdd = new PersonBuilder().withName(VALID_NAME_AMY).withPhone(VALID_PHONE_AMY).withEmail(VALID_EMAIL_BOB) .withAddress(VALID_ADDRESS_AMY).withTags(VALID_TAG_FRIEND).build(); command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_BOB + ADDRESS_DESC_AMY + TAG_DESC_FRIEND; assertCommandSuccess(command, toAdd); - /* Case: add a person with all fields same as another person in the address book except address -> added */ + /* Case: add a book with all fields same as another book in the catalogue except address -> added */ toAdd = new PersonBuilder().withName(VALID_NAME_AMY).withPhone(VALID_PHONE_AMY).withEmail(VALID_EMAIL_AMY) .withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_FRIEND).build(); command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY + ADDRESS_DESC_BOB + TAG_DESC_FRIEND; assertCommandSuccess(command, toAdd); - /* Case: add to empty address book -> added */ + /* Case: add to empty catalogue -> added */ deleteAllPersons(); assertCommandSuccess(ALICE); - /* Case: add a person with tags, command with parameters in random order -> added */ + /* Case: add a book with tags, command with parameters in random order -> added */ toAdd = BOB; command = AddCommand.COMMAND_WORD + TAG_DESC_FRIEND + PHONE_DESC_BOB + ADDRESS_DESC_BOB + NAME_DESC_BOB + TAG_DESC_HUSBAND + EMAIL_DESC_BOB; assertCommandSuccess(command, toAdd); - /* Case: add a person, missing tags -> added */ + /* Case: add a book, missing tags -> added */ assertCommandSuccess(HOON); /* -------------------------- Perform add operation on the shown filtered list ------------------------------ */ - /* Case: filters the person list before adding -> added */ + /* Case: filters the book list before adding -> added */ showPersonsWithName(KEYWORD_MATCHING_MEIER); assertCommandSuccess(IDA); - /* ------------------------ Perform add operation while a person card is selected --------------------------- */ + /* ------------------------ Perform add operation while a book card is selected --------------------------- */ - /* Case: selects first card in the person list, add a person -> added, card selection remains unchanged */ + /* Case: selects first card in the book list, add a book -> added, card selection remains unchanged */ selectPerson(Index.fromOneBased(1)); assertCommandSuccess(CARL); /* ----------------------------------- Perform invalid add operations --------------------------------------- */ - /* Case: add a duplicate person -> rejected */ + /* Case: add a duplicate book -> rejected */ command = PersonUtil.getAddCommand(HOON); assertCommandFailure(command, AddCommand.MESSAGE_DUPLICATE_PERSON); - /* Case: add a duplicate person except with different tags -> rejected */ + /* Case: add a duplicate book except with different tags -> rejected */ // "friends" is an existing tag used in the default model, see TypicalPersons#ALICE // This test will fail if a new tag that is not in the model is used, see the bug documented in - // Catalogue#addPerson(Person) + // Catalogue#addPerson(Book) command = PersonUtil.getAddCommand(HOON) + " " + PREFIX_TAG.getPrefix() + "friends"; assertCommandFailure(command, AddCommand.MESSAGE_DUPLICATE_PERSON); @@ -201,16 +201,16 @@ public void add() throws Exception { * {@code CatalogueSystemTest#assertApplicationDisplaysExpected(String, String, Model)}.
* @see CatalogueSystemTest#assertApplicationDisplaysExpected(String, String, Model) */ - private void assertCommandSuccess(Person toAdd) { + private void assertCommandSuccess(Book toAdd) { assertCommandSuccess(PersonUtil.getAddCommand(toAdd), toAdd); } /** - * Performs the same verification as {@code assertCommandSuccess(Person)}. Executes {@code command} + * Performs the same verification as {@code assertCommandSuccess(Book)}. Executes {@code command} * instead. - * @see AddCommandSystemTest#assertCommandSuccess(Person) + * @see AddCommandSystemTest#assertCommandSuccess(Book) */ - private void assertCommandSuccess(String command, Person toAdd) { + private void assertCommandSuccess(String command, Book toAdd) { Model expectedModel = getModel(); try { expectedModel.addPerson(toAdd); @@ -223,12 +223,12 @@ private void assertCommandSuccess(String command, Person toAdd) { } /** - * Performs the same verification as {@code assertCommandSuccess(String, Person)} except asserts that + * Performs the same verification as {@code assertCommandSuccess(String, Book)} except asserts that * the,
* 1. Result display box displays {@code expectedResultMessage}.
* 2. {@code Model}, {@code Storage} and {@code PersonListPanel} equal to the corresponding components in * {@code expectedModel}.
- * @see AddCommandSystemTest#assertCommandSuccess(String, Person) + * @see AddCommandSystemTest#assertCommandSuccess(String, Book) */ private void assertCommandSuccess(String command, Model expectedModel, String expectedResultMessage) { executeCommand(command); diff --git a/src/test/java/systemtests/CatalogueSystemTest.java b/src/test/java/systemtests/CatalogueSystemTest.java index 7cc24486f0a2..6f449abebb4b 100644 --- a/src/test/java/systemtests/CatalogueSystemTest.java +++ b/src/test/java/systemtests/CatalogueSystemTest.java @@ -137,7 +137,7 @@ protected void executeCommand(String command) { } /** - * Displays all persons in the address book. + * Displays all persons in the catalogue. */ protected void showAllPersons() { executeCommand(ListCommand.COMMAND_WORD); @@ -153,7 +153,7 @@ protected void showPersonsWithName(String keyword) { } /** - * Selects the person at {@code index} of the displayed list. + * Selects the book at {@code index} of the displayed list. */ protected void selectPerson(Index index) { executeCommand(SelectCommand.COMMAND_WORD + " " + index.getOneBased()); @@ -161,7 +161,7 @@ protected void selectPerson(Index index) { } /** - * Deletes all persons in the address book. + * Deletes all persons in the catalogue. */ protected void deleteAllPersons() { executeCommand(ClearCommand.COMMAND_WORD); @@ -170,8 +170,8 @@ protected void deleteAllPersons() { /** * Asserts that the {@code CommandBox} displays {@code expectedCommandInput}, the {@code ResultDisplay} displays - * {@code expectedResultMessage}, the model and storage contains the same person objects as {@code expectedModel} - * and the person list panel displays the persons in the model correctly. + * {@code expectedResultMessage}, the model and storage contains the same book objects as {@code expectedModel} + * and the book list panel displays the persons in the model correctly. */ protected void assertApplicationDisplaysExpected(String expectedCommandInput, String expectedResultMessage, Model expectedModel) { @@ -196,7 +196,7 @@ private void rememberStates() { /** * Asserts that the previously selected card is now deselected and the browser's url remains displaying the details - * of the previously selected person. + * of the previously selected book. * @see BrowserPanelHandle#isUrlChanged() */ protected void assertSelectedCardDeselected() { @@ -205,7 +205,7 @@ protected void assertSelectedCardDeselected() { } /** - * Asserts that the browser's url is changed to display the details of the person in the person list panel at + * Asserts that the browser's url is changed to display the details of the book in the book list panel at * {@code expectedSelectedCardIndex}, and only the card at {@code expectedSelectedCardIndex} is selected. * @see BrowserPanelHandle#isUrlChanged() * @see PersonListPanelHandle#isSelectedPersonCardChanged() @@ -224,7 +224,7 @@ protected void assertSelectedCardChanged(Index expectedSelectedCardIndex) { } /** - * Asserts that the browser's url and the selected card in the person list panel remain unchanged. + * Asserts that the browser's url and the selected card in the book list panel remain unchanged. * @see BrowserPanelHandle#isUrlChanged() * @see PersonListPanelHandle#isSelectedPersonCardChanged() */ diff --git a/src/test/java/systemtests/ClearCommandSystemTest.java b/src/test/java/systemtests/ClearCommandSystemTest.java index dcb06bd08123..2ae8754493fd 100644 --- a/src/test/java/systemtests/ClearCommandSystemTest.java +++ b/src/test/java/systemtests/ClearCommandSystemTest.java @@ -18,37 +18,37 @@ public class ClearCommandSystemTest extends CatalogueSystemTest { public void clear() { final Model defaultModel = getModel(); - /* Case: clear non-empty address book, command with leading spaces and trailing alphanumeric characters and + /* Case: clear non-empty catalogue, command with leading spaces and trailing alphanumeric characters and * spaces -> cleared */ assertCommandSuccess(" " + ClearCommand.COMMAND_WORD + " ab12 "); assertSelectedCardUnchanged(); - /* Case: undo clearing address book -> original address book restored */ + /* Case: undo clearing catalogue -> original catalogue restored */ String command = UndoCommand.COMMAND_WORD; String expectedResultMessage = UndoCommand.MESSAGE_SUCCESS; assertCommandSuccess(command, expectedResultMessage, defaultModel); assertSelectedCardUnchanged(); - /* Case: redo clearing address book -> cleared */ + /* Case: redo clearing catalogue -> cleared */ command = RedoCommand.COMMAND_WORD; expectedResultMessage = RedoCommand.MESSAGE_SUCCESS; assertCommandSuccess(command, expectedResultMessage, new ModelManager()); assertSelectedCardUnchanged(); - /* Case: selects first card in person list and clears address book -> cleared and no card selected */ - executeCommand(UndoCommand.COMMAND_WORD); // restores the original address book + /* Case: selects first card in book list and clears catalogue -> cleared and no card selected */ + executeCommand(UndoCommand.COMMAND_WORD); // restores the original catalogue selectPerson(Index.fromOneBased(1)); assertCommandSuccess(ClearCommand.COMMAND_WORD); assertSelectedCardDeselected(); - /* Case: filters the person list before clearing -> entire address book cleared */ - executeCommand(UndoCommand.COMMAND_WORD); // restores the original address book + /* Case: filters the book list before clearing -> entire catalogue cleared */ + executeCommand(UndoCommand.COMMAND_WORD); // restores the original catalogue showPersonsWithName(KEYWORD_MATCHING_MEIER); assertCommandSuccess(ClearCommand.COMMAND_WORD); assertSelectedCardUnchanged(); - /* Case: clear empty address book -> cleared */ + /* Case: clear empty catalogue -> cleared */ assertCommandSuccess(ClearCommand.COMMAND_WORD); assertSelectedCardUnchanged(); diff --git a/src/test/java/systemtests/DeleteCommandSystemTest.java b/src/test/java/systemtests/DeleteCommandSystemTest.java index 9d523baf122a..76b262b8729d 100644 --- a/src/test/java/systemtests/DeleteCommandSystemTest.java +++ b/src/test/java/systemtests/DeleteCommandSystemTest.java @@ -18,8 +18,8 @@ import seedu.address.logic.commands.RedoCommand; import seedu.address.logic.commands.UndoCommand; import seedu.address.model.Model; -import seedu.address.model.person.Person; -import seedu.address.model.person.exceptions.PersonNotFoundException; +import seedu.address.model.book.Book; +import seedu.address.model.book.exceptions.PersonNotFoundException; public class DeleteCommandSystemTest extends CatalogueSystemTest { @@ -30,42 +30,42 @@ public class DeleteCommandSystemTest extends CatalogueSystemTest { public void delete() { /* ----------------- Performing delete operation while an unfiltered list is being shown -------------------- */ - /* Case: delete the first person in the list, command with leading spaces and trailing spaces -> deleted */ + /* Case: delete the first book in the list, command with leading spaces and trailing spaces -> deleted */ Model expectedModel = getModel(); String command = " " + DeleteCommand.COMMAND_WORD + " " + INDEX_FIRST_PERSON.getOneBased() + " "; - Person deletedPerson = removePerson(expectedModel, INDEX_FIRST_PERSON); - String expectedResultMessage = String.format(MESSAGE_DELETE_PERSON_SUCCESS, deletedPerson); + Book deletedBook = removePerson(expectedModel, INDEX_FIRST_PERSON); + String expectedResultMessage = String.format(MESSAGE_DELETE_PERSON_SUCCESS, deletedBook); assertCommandSuccess(command, expectedModel, expectedResultMessage); - /* Case: delete the last person in the list -> deleted */ + /* Case: delete the last book in the list -> deleted */ Model modelBeforeDeletingLast = getModel(); Index lastPersonIndex = getLastIndex(modelBeforeDeletingLast); assertCommandSuccess(lastPersonIndex); - /* Case: undo deleting the last person in the list -> last person restored */ + /* Case: undo deleting the last book in the list -> last book restored */ command = UndoCommand.COMMAND_WORD; expectedResultMessage = UndoCommand.MESSAGE_SUCCESS; assertCommandSuccess(command, modelBeforeDeletingLast, expectedResultMessage); - /* Case: redo deleting the last person in the list -> last person deleted again */ + /* Case: redo deleting the last book in the list -> last book deleted again */ command = RedoCommand.COMMAND_WORD; removePerson(modelBeforeDeletingLast, lastPersonIndex); expectedResultMessage = RedoCommand.MESSAGE_SUCCESS; assertCommandSuccess(command, modelBeforeDeletingLast, expectedResultMessage); - /* Case: delete the middle person in the list -> deleted */ + /* Case: delete the middle book in the list -> deleted */ Index middlePersonIndex = getMidIndex(getModel()); assertCommandSuccess(middlePersonIndex); /* ------------------ Performing delete operation while a filtered list is being shown ---------------------- */ - /* Case: filtered person list, delete index within bounds of address book and person list -> deleted */ + /* Case: filtered book list, delete index within bounds of catalogue and book list -> deleted */ showPersonsWithName(KEYWORD_MATCHING_MEIER); Index index = INDEX_FIRST_PERSON; assertTrue(index.getZeroBased() < getModel().getFilteredPersonList().size()); assertCommandSuccess(index); - /* Case: filtered person list, delete index within bounds of address book but out of bounds of person list + /* Case: filtered book list, delete index within bounds of catalogue but out of bounds of book list * -> rejected */ showPersonsWithName(KEYWORD_MATCHING_MEIER); @@ -73,17 +73,17 @@ public void delete() { command = DeleteCommand.COMMAND_WORD + " " + invalidIndex; assertCommandFailure(command, MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); - /* --------------------- Performing delete operation while a person card is selected ------------------------ */ + /* --------------------- Performing delete operation while a book card is selected ------------------------ */ - /* Case: delete the selected person -> person list panel selects the person before the deleted person */ + /* Case: delete the selected book -> book list panel selects the book before the deleted book */ showAllPersons(); expectedModel = getModel(); Index selectedIndex = getLastIndex(expectedModel); Index expectedIndex = Index.fromZeroBased(selectedIndex.getZeroBased() - 1); selectPerson(selectedIndex); command = DeleteCommand.COMMAND_WORD + " " + selectedIndex.getOneBased(); - deletedPerson = removePerson(expectedModel, selectedIndex); - expectedResultMessage = String.format(MESSAGE_DELETE_PERSON_SUCCESS, deletedPerson); + deletedBook = removePerson(expectedModel, selectedIndex); + expectedResultMessage = String.format(MESSAGE_DELETE_PERSON_SUCCESS, deletedBook); assertCommandSuccess(command, expectedModel, expectedResultMessage, expectedIndex); /* --------------------------------- Performing invalid delete operation ------------------------------------ */ @@ -113,28 +113,28 @@ public void delete() { } /** - * Removes the {@code Person} at the specified {@code index} in {@code model}'s address book. - * @return the removed person + * Removes the {@code Book} at the specified {@code index} in {@code model}'s catalogue. + * @return the removed book */ - private Person removePerson(Model model, Index index) { - Person targetPerson = getPerson(model, index); + private Book removePerson(Model model, Index index) { + Book targetBook = getPerson(model, index); try { - model.deletePerson(targetPerson); + model.deletePerson(targetBook); } catch (PersonNotFoundException pnfe) { - throw new AssertionError("targetPerson is retrieved from model."); + throw new AssertionError("targetBook is retrieved from model."); } - return targetPerson; + return targetBook; } /** - * Deletes the person at {@code toDelete} by creating a default {@code DeleteCommand} using {@code toDelete} and + * Deletes the book at {@code toDelete} by creating a default {@code DeleteCommand} using {@code toDelete} and * performs the same verification as {@code assertCommandSuccess(String, Model, String)}. * @see DeleteCommandSystemTest#assertCommandSuccess(String, Model, String) */ private void assertCommandSuccess(Index toDelete) { Model expectedModel = getModel(); - Person deletedPerson = removePerson(expectedModel, toDelete); - String expectedResultMessage = String.format(MESSAGE_DELETE_PERSON_SUCCESS, deletedPerson); + Book deletedBook = removePerson(expectedModel, toDelete); + String expectedResultMessage = String.format(MESSAGE_DELETE_PERSON_SUCCESS, deletedBook); assertCommandSuccess( DeleteCommand.COMMAND_WORD + " " + toDelete.getOneBased(), expectedModel, expectedResultMessage); diff --git a/src/test/java/systemtests/EditCommandSystemTest.java b/src/test/java/systemtests/EditCommandSystemTest.java index c929e85a3db3..e2ba37ed1979 100644 --- a/src/test/java/systemtests/EditCommandSystemTest.java +++ b/src/test/java/systemtests/EditCommandSystemTest.java @@ -38,13 +38,13 @@ import seedu.address.logic.commands.RedoCommand; import seedu.address.logic.commands.UndoCommand; 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.person.exceptions.DuplicatePersonException; -import seedu.address.model.person.exceptions.PersonNotFoundException; +import seedu.address.model.book.Address; +import seedu.address.model.book.Book; +import seedu.address.model.book.Email; +import seedu.address.model.book.Name; +import seedu.address.model.book.Phone; +import seedu.address.model.book.exceptions.DuplicatePersonException; +import seedu.address.model.book.exceptions.PersonNotFoundException; import seedu.address.model.tag.Tag; import seedu.address.testutil.PersonBuilder; import seedu.address.testutil.PersonUtil; @@ -63,23 +63,23 @@ public void edit() throws Exception { Index index = INDEX_FIRST_PERSON; String command = " " + EditCommand.COMMAND_WORD + " " + index.getOneBased() + " " + NAME_DESC_BOB + " " + PHONE_DESC_BOB + " " + EMAIL_DESC_BOB + " " + ADDRESS_DESC_BOB + " " + TAG_DESC_HUSBAND + " "; - Person editedPerson = new PersonBuilder().withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB) + Book editedBook = new PersonBuilder().withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB) .withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND).build(); - assertCommandSuccess(command, index, editedPerson); + assertCommandSuccess(command, index, editedBook); - /* Case: undo editing the last person in the list -> last person restored */ + /* Case: undo editing the last book in the list -> last book restored */ command = UndoCommand.COMMAND_WORD; String expectedResultMessage = UndoCommand.MESSAGE_SUCCESS; assertCommandSuccess(command, model, expectedResultMessage); - /* Case: redo editing the last person in the list -> last person edited again */ + /* Case: redo editing the last book in the list -> last book edited again */ command = RedoCommand.COMMAND_WORD; expectedResultMessage = RedoCommand.MESSAGE_SUCCESS; model.updatePerson( - getModel().getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()), editedPerson); + getModel().getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()), editedBook); assertCommandSuccess(command, model, expectedResultMessage); - /* Case: edit a person with new values same as existing values -> edited */ + /* Case: edit a book with new values same as existing values -> edited */ command = EditCommand.COMMAND_WORD + " " + index.getOneBased() + NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB + TAG_DESC_FRIEND + TAG_DESC_HUSBAND; assertCommandSuccess(command, index, BOB); @@ -87,28 +87,28 @@ public void edit() throws Exception { /* Case: edit some fields -> edited */ index = INDEX_FIRST_PERSON; command = EditCommand.COMMAND_WORD + " " + index.getOneBased() + TAG_DESC_FRIEND; - Person personToEdit = getModel().getFilteredPersonList().get(index.getZeroBased()); - editedPerson = new PersonBuilder(personToEdit).withTags(VALID_TAG_FRIEND).build(); - assertCommandSuccess(command, index, editedPerson); + Book bookToEdit = getModel().getFilteredPersonList().get(index.getZeroBased()); + editedBook = new PersonBuilder(bookToEdit).withTags(VALID_TAG_FRIEND).build(); + assertCommandSuccess(command, index, editedBook); /* Case: clear tags -> cleared */ index = INDEX_FIRST_PERSON; command = EditCommand.COMMAND_WORD + " " + index.getOneBased() + " " + PREFIX_TAG.getPrefix(); - editedPerson = new PersonBuilder(personToEdit).withTags().build(); - assertCommandSuccess(command, index, editedPerson); + editedBook = new PersonBuilder(bookToEdit).withTags().build(); + assertCommandSuccess(command, index, editedBook); /* ------------------ Performing edit operation while a filtered list is being shown ------------------------ */ - /* Case: filtered person list, edit index within bounds of address book and person list -> edited */ + /* Case: filtered book list, edit index within bounds of catalogue and book list -> edited */ showPersonsWithName(KEYWORD_MATCHING_MEIER); index = INDEX_FIRST_PERSON; assertTrue(index.getZeroBased() < getModel().getFilteredPersonList().size()); command = EditCommand.COMMAND_WORD + " " + index.getOneBased() + " " + NAME_DESC_BOB; - personToEdit = getModel().getFilteredPersonList().get(index.getZeroBased()); - editedPerson = new PersonBuilder(personToEdit).withName(VALID_NAME_BOB).build(); - assertCommandSuccess(command, index, editedPerson); + bookToEdit = getModel().getFilteredPersonList().get(index.getZeroBased()); + editedBook = new PersonBuilder(bookToEdit).withName(VALID_NAME_BOB).build(); + assertCommandSuccess(command, index, editedBook); - /* Case: filtered person list, edit index within bounds of address book but out of bounds of person list + /* Case: filtered book list, edit index within bounds of catalogue but out of bounds of book list * -> rejected */ showPersonsWithName(KEYWORD_MATCHING_MEIER); @@ -116,9 +116,9 @@ public void edit() throws Exception { assertCommandFailure(EditCommand.COMMAND_WORD + " " + invalidIndex + NAME_DESC_BOB, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); - /* --------------------- Performing edit operation while a person card is selected -------------------------- */ + /* --------------------- Performing edit operation while a book card is selected -------------------------- */ - /* Case: selects first card in the person list, edit a person -> edited, card selection remains unchanged but + /* Case: selects first card in the book list, edit a book -> edited, card selection remains unchanged but * browser url changes */ showAllPersons(); @@ -127,7 +127,7 @@ public void edit() throws Exception { command = EditCommand.COMMAND_WORD + " " + index.getOneBased() + NAME_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY + ADDRESS_DESC_AMY + TAG_DESC_FRIEND; // this can be misleading: card selection actually remains unchanged but the - // browser's url is updated to reflect the new person's name + // browser's url is updated to reflect the new book's name assertCommandSuccess(command, index, AMY, index); /* --------------------------------- Performing invalid edit operation -------------------------------------- */ @@ -173,7 +173,7 @@ public void edit() throws Exception { assertCommandFailure(EditCommand.COMMAND_WORD + " " + INDEX_FIRST_PERSON.getOneBased() + INVALID_TAG_DESC, Tag.MESSAGE_TAG_CONSTRAINTS); - /* Case: edit a person with new values same as another person's values -> rejected */ + /* Case: edit a book with new values same as another book's values -> rejected */ executeCommand(PersonUtil.getAddCommand(BOB)); assertTrue(getModel().getCatalogue().getPersonList().contains(BOB)); index = INDEX_FIRST_PERSON; @@ -182,44 +182,44 @@ public void edit() throws Exception { + ADDRESS_DESC_BOB + TAG_DESC_FRIEND + TAG_DESC_HUSBAND; assertCommandFailure(command, EditCommand.MESSAGE_DUPLICATE_PERSON); - /* Case: edit a person with new values same as another person's values but with different tags -> rejected */ + /* Case: edit a book with new values same as another book's values but with different tags -> rejected */ command = EditCommand.COMMAND_WORD + " " + index.getOneBased() + NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB + TAG_DESC_HUSBAND; assertCommandFailure(command, EditCommand.MESSAGE_DUPLICATE_PERSON); } /** - * Performs the same verification as {@code assertCommandSuccess(String, Index, Person, Index)} except that + * Performs the same verification as {@code assertCommandSuccess(String, Index, Book, Index)} except that * the browser url and selected card remain unchanged. * @param toEdit the index of the current model's filtered list - * @see EditCommandSystemTest#assertCommandSuccess(String, Index, Person, Index) + * @see EditCommandSystemTest#assertCommandSuccess(String, Index, Book, Index) */ - private void assertCommandSuccess(String command, Index toEdit, Person editedPerson) { - assertCommandSuccess(command, toEdit, editedPerson, null); + private void assertCommandSuccess(String command, Index toEdit, Book editedBook) { + assertCommandSuccess(command, toEdit, editedBook, null); } /** * Performs the same verification as {@code assertCommandSuccess(String, Model, String, Index)} and in addition,
* 1. Asserts that result display box displays the success message of executing {@code EditCommand}.
- * 2. Asserts that the model related components are updated to reflect the person at index {@code toEdit} being - * updated to values specified {@code editedPerson}.
+ * 2. Asserts that the model related components are updated to reflect the book at index {@code toEdit} being + * updated to values specified {@code editedBook}.
* @param toEdit the index of the current model's filtered list. * @see EditCommandSystemTest#assertCommandSuccess(String, Model, String, Index) */ - private void assertCommandSuccess(String command, Index toEdit, Person editedPerson, + private void assertCommandSuccess(String command, Index toEdit, Book editedBook, Index expectedSelectedCardIndex) { Model expectedModel = getModel(); try { expectedModel.updatePerson( - expectedModel.getFilteredPersonList().get(toEdit.getZeroBased()), editedPerson); + expectedModel.getFilteredPersonList().get(toEdit.getZeroBased()), editedBook); expectedModel.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); } catch (DuplicatePersonException | PersonNotFoundException e) { throw new IllegalArgumentException( - "editedPerson is a duplicate in expectedModel, or it isn't found in the model."); + "editedBook is a duplicate in expectedModel, or it isn't found in the model."); } assertCommandSuccess(command, expectedModel, - String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson), expectedSelectedCardIndex); + String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedBook), expectedSelectedCardIndex); } /** diff --git a/src/test/java/systemtests/FindCommandSystemTest.java b/src/test/java/systemtests/FindCommandSystemTest.java index 0b640b90aacf..08afd8cd35cd 100644 --- a/src/test/java/systemtests/FindCommandSystemTest.java +++ b/src/test/java/systemtests/FindCommandSystemTest.java @@ -25,7 +25,7 @@ public class FindCommandSystemTest extends CatalogueSystemTest { @Test public void find() { - /* Case: find multiple persons in address book, command with leading spaces and trailing spaces + /* Case: find multiple persons in catalogue, command with leading spaces and trailing spaces * -> 2 persons found */ String command = " " + FindCommand.COMMAND_WORD + " " + KEYWORD_MATCHING_MEIER + " "; @@ -34,36 +34,36 @@ public void find() { assertCommandSuccess(command, expectedModel); assertSelectedCardUnchanged(); - /* Case: repeat previous find command where person list is displaying the persons we are finding + /* Case: repeat previous find command where book list is displaying the persons we are finding * -> 2 persons found */ command = FindCommand.COMMAND_WORD + " " + KEYWORD_MATCHING_MEIER; assertCommandSuccess(command, expectedModel); assertSelectedCardUnchanged(); - /* Case: find person where person list is not displaying the person we are finding -> 1 person found */ + /* Case: find book where book list is not displaying the book we are finding -> 1 book found */ command = FindCommand.COMMAND_WORD + " Carl"; ModelHelper.setFilteredList(expectedModel, CARL); assertCommandSuccess(command, expectedModel); assertSelectedCardUnchanged(); - /* Case: find multiple persons in address book, 2 keywords -> 2 persons found */ + /* Case: find multiple persons in catalogue, 2 keywords -> 2 persons found */ command = FindCommand.COMMAND_WORD + " Benson Daniel"; ModelHelper.setFilteredList(expectedModel, BENSON, DANIEL); assertCommandSuccess(command, expectedModel); assertSelectedCardUnchanged(); - /* Case: find multiple persons in address book, 2 keywords in reversed order -> 2 persons found */ + /* Case: find multiple persons in catalogue, 2 keywords in reversed order -> 2 persons found */ command = FindCommand.COMMAND_WORD + " Daniel Benson"; assertCommandSuccess(command, expectedModel); assertSelectedCardUnchanged(); - /* Case: find multiple persons in address book, 2 keywords with 1 repeat -> 2 persons found */ + /* Case: find multiple persons in catalogue, 2 keywords with 1 repeat -> 2 persons found */ command = FindCommand.COMMAND_WORD + " Daniel Benson Daniel"; assertCommandSuccess(command, expectedModel); assertSelectedCardUnchanged(); - /* Case: find multiple persons in address book, 2 matching keywords and 1 non-matching keyword + /* Case: find multiple persons in catalogue, 2 matching keywords and 1 non-matching keyword * -> 2 persons found */ command = FindCommand.COMMAND_WORD + " Daniel Benson NonMatchingKeyWord"; @@ -80,7 +80,7 @@ public void find() { expectedResultMessage = RedoCommand.MESSAGE_FAILURE; assertCommandFailure(command, expectedResultMessage); - /* Case: find same persons in address book after deleting 1 of them -> 1 person found */ + /* Case: find same persons in catalogue after deleting 1 of them -> 1 book found */ executeCommand(DeleteCommand.COMMAND_WORD + " 1"); assertFalse(getModel().getCatalogue().getPersonList().contains(BENSON)); command = FindCommand.COMMAND_WORD + " " + KEYWORD_MATCHING_MEIER; @@ -89,50 +89,50 @@ public void find() { assertCommandSuccess(command, expectedModel); assertSelectedCardUnchanged(); - /* Case: find person in address book, keyword is same as name but of different case -> 1 person found */ + /* Case: find book in catalogue, keyword is same as name but of different case -> 1 book found */ command = FindCommand.COMMAND_WORD + " MeIeR"; assertCommandSuccess(command, expectedModel); assertSelectedCardUnchanged(); - /* Case: find person in address book, keyword is substring of name -> 0 persons found */ + /* Case: find book in catalogue, keyword is substring of name -> 0 persons found */ command = FindCommand.COMMAND_WORD + " Mei"; ModelHelper.setFilteredList(expectedModel); assertCommandSuccess(command, expectedModel); assertSelectedCardUnchanged(); - /* Case: find person in address book, name is substring of keyword -> 0 persons found */ + /* Case: find book in catalogue, name is substring of keyword -> 0 persons found */ command = FindCommand.COMMAND_WORD + " Meiers"; ModelHelper.setFilteredList(expectedModel); assertCommandSuccess(command, expectedModel); assertSelectedCardUnchanged(); - /* Case: find person not in address book -> 0 persons found */ + /* Case: find book not in catalogue -> 0 persons found */ command = FindCommand.COMMAND_WORD + " Mark"; assertCommandSuccess(command, expectedModel); assertSelectedCardUnchanged(); - /* Case: find phone number of person in address book -> 0 persons found */ + /* Case: find phone number of book in catalogue -> 0 persons found */ command = FindCommand.COMMAND_WORD + " " + DANIEL.getPhone().value; assertCommandSuccess(command, expectedModel); assertSelectedCardUnchanged(); - /* Case: find address of person in address book -> 0 persons found */ + /* Case: find address of book in catalogue -> 0 persons found */ command = FindCommand.COMMAND_WORD + " " + DANIEL.getAddress().value; assertCommandSuccess(command, expectedModel); assertSelectedCardUnchanged(); - /* Case: find email of person in address book -> 0 persons found */ + /* Case: find email of book in catalogue -> 0 persons found */ command = FindCommand.COMMAND_WORD + " " + DANIEL.getEmail().value; assertCommandSuccess(command, expectedModel); assertSelectedCardUnchanged(); - /* Case: find tags of person in address book -> 0 persons found */ + /* Case: find tags of book in catalogue -> 0 persons found */ List tags = new ArrayList<>(DANIEL.getTags()); command = FindCommand.COMMAND_WORD + " " + tags.get(0).tagName; assertCommandSuccess(command, expectedModel); assertSelectedCardUnchanged(); - /* Case: find while a person is selected -> selected card deselected */ + /* Case: find while a book is selected -> selected card deselected */ showAllPersons(); selectPerson(Index.fromOneBased(1)); assertFalse(getPersonListPanel().getHandleToSelectedCard().getName().equals(DANIEL.getName().fullName)); @@ -141,7 +141,7 @@ public void find() { assertCommandSuccess(command, expectedModel); assertSelectedCardDeselected(); - /* Case: find person in empty address book -> 0 persons found */ + /* Case: find book in empty catalogue -> 0 persons found */ deleteAllPersons(); command = FindCommand.COMMAND_WORD + " " + KEYWORD_MATCHING_MEIER; expectedModel = getModel(); diff --git a/src/test/java/systemtests/ModelHelper.java b/src/test/java/systemtests/ModelHelper.java index b7950598d36b..7dfc214a1060 100644 --- a/src/test/java/systemtests/ModelHelper.java +++ b/src/test/java/systemtests/ModelHelper.java @@ -6,19 +6,19 @@ import java.util.function.Predicate; import seedu.address.model.Model; -import seedu.address.model.person.Person; +import seedu.address.model.book.Book; /** * Contains helper methods to set up {@code Model} for testing. */ public class ModelHelper { - private static final Predicate PREDICATE_MATCHING_NO_PERSONS = unused -> false; + private static final Predicate PREDICATE_MATCHING_NO_PERSONS = unused -> false; /** * Updates {@code model}'s filtered list to display only {@code toDisplay}. */ - public static void setFilteredList(Model model, List toDisplay) { - Optional> predicate = + public static void setFilteredList(Model model, List toDisplay) { + Optional> predicate = toDisplay.stream().map(ModelHelper::getPredicateMatching).reduce(Predicate::or); model.updateFilteredPersonList(predicate.orElse(PREDICATE_MATCHING_NO_PERSONS)); } @@ -26,14 +26,14 @@ public static void setFilteredList(Model model, List toDisplay) { /** * @see ModelHelper#setFilteredList(Model, List) */ - public static void setFilteredList(Model model, Person... toDisplay) { + public static void setFilteredList(Model model, Book... toDisplay) { setFilteredList(model, Arrays.asList(toDisplay)); } /** - * Returns a predicate that evaluates to true if this {@code Person} equals to {@code other}. + * Returns a predicate that evaluates to true if this {@code Book} equals to {@code other}. */ - private static Predicate getPredicateMatching(Person other) { + private static Predicate getPredicateMatching(Book other) { return person -> person.equals(other); } } diff --git a/src/test/java/systemtests/SampleDataTest.java b/src/test/java/systemtests/SampleDataTest.java index 6fb70330dc73..35ade569178f 100644 --- a/src/test/java/systemtests/SampleDataTest.java +++ b/src/test/java/systemtests/SampleDataTest.java @@ -9,7 +9,7 @@ import org.junit.Test; import seedu.address.model.Catalogue; -import seedu.address.model.person.Person; +import seedu.address.model.book.Book; import seedu.address.model.util.SampleDataUtil; import seedu.address.testutil.TestUtil; @@ -45,7 +45,7 @@ private void deleteFileIfExists(String filePath) { @Test public void catalogue_dataFileDoesNotExist_loadSampleData() { - Person[] expectedList = SampleDataUtil.getSamplePersons(); + Book[] expectedList = SampleDataUtil.getSamplePersons(); assertListMatching(getPersonListPanel(), expectedList); } } diff --git a/src/test/java/systemtests/SelectCommandSystemTest.java b/src/test/java/systemtests/SelectCommandSystemTest.java index 0ab7d1251b76..c2bfa3fca7f5 100644 --- a/src/test/java/systemtests/SelectCommandSystemTest.java +++ b/src/test/java/systemtests/SelectCommandSystemTest.java @@ -22,13 +22,13 @@ public class SelectCommandSystemTest extends CatalogueSystemTest { public void select() { /* ------------------------ Perform select operations on the shown unfiltered list -------------------------- */ - /* Case: select the first card in the person list, command with leading spaces and trailing spaces + /* Case: select the first card in the book list, command with leading spaces and trailing spaces * -> selected */ String command = " " + SelectCommand.COMMAND_WORD + " " + INDEX_FIRST_PERSON.getOneBased() + " "; assertCommandSuccess(command, INDEX_FIRST_PERSON); - /* Case: select the last card in the person list -> selected */ + /* Case: select the last card in the book list -> selected */ Index personCount = Index.fromOneBased(getTypicalPersons().size()); command = SelectCommand.COMMAND_WORD + " " + personCount.getOneBased(); assertCommandSuccess(command, personCount); @@ -43,7 +43,7 @@ public void select() { expectedResultMessage = RedoCommand.MESSAGE_FAILURE; assertCommandFailure(command, expectedResultMessage); - /* Case: select the middle card in the person list -> selected */ + /* Case: select the middle card in the book list -> selected */ Index middleIndex = Index.fromOneBased(personCount.getOneBased() / 2); command = SelectCommand.COMMAND_WORD + " " + middleIndex.getOneBased(); assertCommandSuccess(command, middleIndex); @@ -53,14 +53,14 @@ public void select() { /* ------------------------ Perform select operations on the shown filtered list ---------------------------- */ - /* Case: filtered person list, select index within bounds of address book but out of bounds of person list + /* Case: filtered book list, select index within bounds of catalogue but out of bounds of book list * -> rejected */ showPersonsWithName(KEYWORD_MATCHING_MEIER); int invalidIndex = getModel().getCatalogue().getPersonList().size(); assertCommandFailure(SelectCommand.COMMAND_WORD + " " + invalidIndex, MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); - /* Case: filtered person list, select index within bounds of address book and person list -> selected */ + /* Case: filtered book list, select index within bounds of catalogue and book list -> selected */ Index validIndex = Index.fromOneBased(1); assertTrue(validIndex.getZeroBased() < getModel().getFilteredPersonList().size()); command = SelectCommand.COMMAND_WORD + " " + validIndex.getOneBased(); @@ -91,7 +91,7 @@ public void select() { /* Case: mixed case command word -> rejected */ assertCommandFailure("SeLeCt 1", MESSAGE_UNKNOWN_COMMAND); - /* Case: select from empty address book -> rejected */ + /* Case: select from empty catalogue -> rejected */ deleteAllPersons(); assertCommandFailure(SelectCommand.COMMAND_WORD + " " + INDEX_FIRST_PERSON.getOneBased(), MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); @@ -102,7 +102,7 @@ public void select() { * 1. Command box displays an empty string.
* 2. Command box has the default style class.
* 3. Result display box displays the success message of executing select command with the - * {@code expectedSelectedCardIndex} of the selected person.
+ * {@code expectedSelectedCardIndex} of the selected book.
* 4. {@code Model}, {@code Storage} and {@code PersonListPanel} remain unchanged.
* 5. Selected card is at {@code expectedSelectedCardIndex} and the browser url is updated accordingly.
* 6. Status bar remains unchanged.
From 8507e0c3a711df8cd6e578d033b6bedc73afd968 Mon Sep 17 00:00:00 2001 From: Khia Yi <33336624+khiayi@users.noreply.github.com> Date: Thu, 22 Mar 2018 11:49:19 +0800 Subject: [PATCH 32/98] Refactor person to book and addressbook to catalogue --- docs/DeveloperGuide.adoc | 58 +++---- docs/LearningOutcomes.adoc | 2 +- docs/UserGuide.adoc | 2 +- docs/UsingTravis.adoc | 2 +- .../seedu/address/commons/core/Messages.java | 4 +- .../events/model/CatalogueChangedEvent.java | 2 +- ...va => BookPanelSelectionChangedEvent.java} | 10 +- .../events/ui/JumpToListRequestEvent.java | 2 +- src/main/java/seedu/address/logic/Logic.java | 4 +- .../seedu/address/logic/LogicManager.java | 4 +- .../address/logic/commands/AddCommand.java | 10 +- .../seedu/address/logic/commands/Command.java | 8 +- .../address/logic/commands/DeleteCommand.java | 14 +- .../address/logic/commands/EditCommand.java | 64 ++++---- .../address/logic/commands/FindCommand.java | 8 +- .../address/logic/commands/ListCommand.java | 8 +- .../address/logic/commands/SelectCommand.java | 8 +- .../logic/commands/UndoableCommand.java | 10 +- .../logic/parser/EditCommandParser.java | 18 +-- .../java/seedu/address/model/Catalogue.java | 68 ++++---- src/main/java/seedu/address/model/Model.java | 22 +-- .../seedu/address/model/ModelManager.java | 26 +-- .../address/model/ReadOnlyCatalogue.java | 6 +- ...quePersonList.java => UniqueBookList.java} | 50 +++--- ...eption.java => BookNotFoundException.java} | 2 +- ...ption.java => DuplicateBookException.java} | 6 +- .../address/model/util/SampleDataUtil.java | 12 +- ...AdaptedPerson.java => XmlAdaptedBook.java} | 34 ++-- .../storage/XmlSerializableCatalogue.java | 14 +- .../ui/{PersonCard.java => BookCard.java} | 10 +- ...ersonListPanel.java => BookListPanel.java} | 44 ++--- .../java/seedu/address/ui/BrowserPanel.java | 8 +- .../java/seedu/address/ui/MainWindow.java | 12 +- ...{PersonListCard.fxml => BookListCard.fxml} | 0 ...ersonListPanel.fxml => BookListPanel.fxml} | 2 +- src/main/resources/view/DarkTheme.css | 2 +- src/main/resources/view/MainWindow.fxml | 2 +- .../NotXmlFormatCatalogue.xml} | 0 .../invalidAndValidBookCatalogue.xml} | 0 .../invalidBookCatalogue.xml} | 0 .../invalidBookCatalogue.xml} | 0 .../invalidTagCatalogue.xml} | 0 .../typicalBooksCatalogue.xml} | 2 +- ...idPersonField.xml => invalidBookField.xml} | 0 ...ngPersonField.xml => missingBookField.xml} | 0 ...{tempAddressBook.xml => tempCatalogue.xml} | 0 .../{validPerson.xml => validBook.xml} | 0 ...alidAddressBook.xml => validCatalogue.xml} | 0 ...sonCardHandle.java => BookCardHandle.java} | 4 +- .../guihandles/BookListPanelHandle.java | 134 ++++++++++++++++ .../guitests/guihandles/MainWindowHandle.java | 8 +- .../guihandles/PersonListPanelHandle.java | 134 ---------------- src/test/java/seedu/address/TestApp.java | 6 +- .../address/commons/core/index/IndexTest.java | 14 +- .../address/commons/util/XmlUtilTest.java | 48 +++--- .../seedu/address/logic/LogicManagerTest.java | 8 +- .../commands/AddCommandIntegrationTest.java | 16 +- .../logic/commands/AddCommandTest.java | 62 ++++---- .../logic/commands/ClearCommandTest.java | 2 +- .../logic/commands/CommandTestUtil.java | 34 ++-- .../logic/commands/DeleteCommandTest.java | 78 ++++----- .../commands/EditBookDescriptorTest.java | 16 +- .../logic/commands/EditCommandTest.java | 150 +++++++++--------- .../logic/commands/FindCommandTest.java | 20 +-- .../logic/commands/ListCommandTest.java | 8 +- .../logic/commands/RedoCommandTest.java | 16 +- .../logic/commands/SelectCommandTest.java | 42 ++--- .../logic/commands/UndoCommandTest.java | 12 +- .../logic/commands/UndoableCommandTest.java | 28 ++-- .../logic/parser/AddCommandParserTest.java | 8 +- .../logic/parser/CatalogueParserTest.java | 30 ++-- .../logic/parser/DeleteCommandParserTest.java | 4 +- .../logic/parser/EditCommandParserTest.java | 44 ++--- .../address/logic/parser/ParserUtilTest.java | 6 +- .../logic/parser/SelectCommandParserTest.java | 4 +- .../seedu/address/model/CatalogueTest.java | 14 +- .../seedu/address/model/ModelManagerTest.java | 16 +- .../address/model/UniqueBookListTest.java | 8 +- .../NameContainsKeywordsPredicateTest.java | 16 +- .../address/storage/StorageManagerTest.java | 2 +- .../address/storage/XmlAdaptedBookTest.java | 56 +++---- .../storage/XmlCatalogueStorageTest.java | 22 +-- .../storage/XmlSerializableCatalogueTest.java | 18 +-- .../{PersonBuilder.java => BookBuilder.java} | 18 +-- .../{PersonUtil.java => BookUtil.java} | 6 +- .../address/testutil/CatalogueBuilder.java | 10 +- .../testutil/EditBookDescriptorBuilder.java | 87 ++++++++++ .../testutil/EditPersonDescriptorBuilder.java | 87 ---------- .../java/seedu/address/testutil/TestUtil.java | 8 +- ...{TypicalPersons.java => TypicalBooks.java} | 38 ++--- .../address/testutil/TypicalIndexes.java | 6 +- .../java/seedu/address/ui/BookCardTest.java | 52 +++--- .../seedu/address/ui/BookListPanelTest.java | 34 ++-- .../seedu/address/ui/BrowserPanelTest.java | 12 +- .../address/ui/testutil/GuiTestAssert.java | 26 +-- .../systemtests/AddCommandSystemTest.java | 62 ++++---- .../java/systemtests/CatalogueSystemTest.java | 54 +++---- .../systemtests/ClearCommandSystemTest.java | 6 +- .../systemtests/DeleteCommandSystemTest.java | 64 ++++---- .../systemtests/EditCommandSystemTest.java | 98 ++++++------ .../systemtests/FindCommandSystemTest.java | 60 +++---- .../systemtests/HelpCommandSystemTest.java | 10 +- src/test/java/systemtests/ModelHelper.java | 6 +- src/test/java/systemtests/SampleDataTest.java | 4 +- .../systemtests/SelectCommandSystemTest.java | 48 +++--- 105 files changed, 1222 insertions(+), 1222 deletions(-) rename src/main/java/seedu/address/commons/events/ui/{PersonPanelSelectionChangedEvent.java => BookPanelSelectionChangedEvent.java} (57%) rename src/main/java/seedu/address/model/book/{UniquePersonList.java => UniqueBookList.java} (56%) rename src/main/java/seedu/address/model/book/exceptions/{PersonNotFoundException.java => BookNotFoundException.java} (67%) rename src/main/java/seedu/address/model/book/exceptions/{DuplicatePersonException.java => DuplicateBookException.java} (53%) rename src/main/java/seedu/address/storage/{XmlAdaptedPerson.java => XmlAdaptedBook.java} (79%) rename src/main/java/seedu/address/ui/{PersonCard.java => BookCard.java} (86%) rename src/main/java/seedu/address/ui/{PersonListPanel.java => BookListPanel.java} (54%) rename src/main/resources/view/{PersonListCard.fxml => BookListCard.fxml} (100%) rename src/main/resources/view/{PersonListPanel.fxml => BookListPanel.fxml} (77%) rename src/test/data/{XmlAddressBookStorageTest/NotXmlFormatAddressBook.xml => XmlCatalogueStorageTest/NotXmlFormatCatalogue.xml} (100%) rename src/test/data/{XmlAddressBookStorageTest/invalidAndValidPersonAddressBook.xml => XmlCatalogueStorageTest/invalidAndValidBookCatalogue.xml} (100%) rename src/test/data/{XmlAddressBookStorageTest/invalidPersonAddressBook.xml => XmlCatalogueStorageTest/invalidBookCatalogue.xml} (100%) rename src/test/data/{XmlSerializableAddressBookTest/invalidPersonAddressBook.xml => XmlSerializableCatalogueTest/invalidBookCatalogue.xml} (100%) rename src/test/data/{XmlSerializableAddressBookTest/invalidTagAddressBook.xml => XmlSerializableCatalogueTest/invalidTagCatalogue.xml} (100%) rename src/test/data/{XmlSerializableAddressBookTest/typicalPersonsAddressBook.xml => XmlSerializableCatalogueTest/typicalBooksCatalogue.xml} (96%) rename src/test/data/XmlUtilTest/{invalidPersonField.xml => invalidBookField.xml} (100%) rename src/test/data/XmlUtilTest/{missingPersonField.xml => missingBookField.xml} (100%) rename src/test/data/XmlUtilTest/{tempAddressBook.xml => tempCatalogue.xml} (100%) rename src/test/data/XmlUtilTest/{validPerson.xml => validBook.xml} (100%) rename src/test/data/XmlUtilTest/{validAddressBook.xml => validCatalogue.xml} (100%) rename src/test/java/guitests/guihandles/{PersonCardHandle.java => BookCardHandle.java} (95%) create mode 100644 src/test/java/guitests/guihandles/BookListPanelHandle.java delete mode 100644 src/test/java/guitests/guihandles/PersonListPanelHandle.java rename src/test/java/seedu/address/testutil/{PersonBuilder.java => BookBuilder.java} (83%) rename src/test/java/seedu/address/testutil/{PersonUtil.java => BookUtil.java} (88%) create mode 100644 src/test/java/seedu/address/testutil/EditBookDescriptorBuilder.java delete mode 100644 src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java rename src/test/java/seedu/address/testutil/{TypicalPersons.java => TypicalBooks.java} (64%) diff --git a/docs/DeveloperGuide.adoc b/docs/DeveloperGuide.adoc index 68f1257e3c00..af2ee6ee2485 100644 --- a/docs/DeveloperGuide.adoc +++ b/docs/DeveloperGuide.adoc @@ -77,7 +77,7 @@ Set up Travis to perform Continuous Integration (CI) for your fork. See <>). [NOTE] -Coverage reporting could be useful for a team repository that hosts the final version but it is not that useful for your personal fork. +Coverage reporting could be useful for a team repository that hosts the final version but it is not that useful for your bookal fork. Optionally, you can set up AppVeyor as a second CI (see <>). @@ -137,7 +137,7 @@ image::LogicClassDiagram.png[width="800"] The _Sequence Diagram_ below shows how the components interact for the scenario where the user issues the command `delete 1`. .Component interactions for `delete 1` command (part 1) -image::SDforDeletePerson.png[width="800"] +image::SDforDeleteBook.png[width="800"] [NOTE] Note how the `Model` simply raises a `CatalogueChangedEvent` when the Catalogue data are changed, instead of asking the `Storage` to save the updates to the hard disk. @@ -145,7 +145,7 @@ Note how the `Model` simply raises a `CatalogueChangedEvent` when the Catalogue The diagram below shows how the `EventsCenter` reacts to that event, which eventually results in the updates being saved to the hard disk and the status bar of the UI being updated to reflect the 'Last Updated' time. .Component interactions for `delete 1` command (part 2) -image::SDforDeletePersonEventHandling.png[width="800"] +image::SDforDeleteBookEventHandling.png[width="800"] [NOTE] Note how the event is propagated through the `EventsCenter` to the `Storage` and `UI` without `Model` having to be coupled to either of them. This is an example of how this Event Driven approach helps us reduce direct coupling between components. @@ -160,7 +160,7 @@ image::UiClassDiagram.png[width="800"] *API* : link:{repoURL}/src/main/java/seedu/address/ui/Ui.java[`Ui.java`] -The UI consists of a `MainWindow` that is made up of parts e.g.`CommandBox`, `ResultDisplay`, `PersonListPanel`, `StatusBarFooter`, `BrowserPanel` etc. All these, including the `MainWindow`, inherit from the abstract `UiPart` class. +The UI consists of a `MainWindow` that is made up of parts e.g.`CommandBox`, `ResultDisplay`, `BookListPanel`, `StatusBarFooter`, `BrowserPanel` etc. All these, including the `MainWindow`, inherit from the abstract `UiPart` class. The `UI` component uses JavaFx UI framework. The layout of these UI parts are defined in matching `.fxml` files that are in the `src/main/resources/view` folder. For example, the layout of the link:{repoURL}/src/main/java/seedu/address/ui/MainWindow.java[`MainWindow`] is specified in link:{repoURL}/src/main/resources/view/MainWindow.fxml[`MainWindow.fxml`] @@ -191,7 +191,7 @@ link:{repoURL}/src/main/java/seedu/address/logic/Logic.java[`Logic.java`] Given below is the Sequence Diagram for interactions within the `Logic` component for the `execute("delete 1")` API call. .Interactions Inside the Logic Component for the `delete 1` Command -image::DeletePersonSdForLogic.png[width="800"] +image::DeleteBookSdForLogic.png[width="800"] [[Design-Model]] === Model component @@ -205,7 +205,7 @@ The `Model`, * stores a `UserPref` object that represents the user's preferences. * stores the Catalogue data. -* exposes an unmodifiable `ObservableList` that can be 'observed' e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change. +* exposes an unmodifiable `ObservableList` that can be 'observed' e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change. * does not depend on any of the other three components. [[Design-Storage]] @@ -580,7 +580,7 @@ Do take a look at <> before attempting to modify the `Model` compo * Hints ** The link:{repoURL}/src/main/java/seedu/address/model/Model.java[`Model`] and the link:{repoURL}/src/main/java/seedu/address/model/Catalogue.java[`Catalogue`] API need to be updated. ** Think about how you can use SLAP to design the method. Where should we place the main logic of deleting tags? -** Find out which of the existing API methods in link:{repoURL}/src/main/java/seedu/address/model/Catalogue.java[`Catalogue`] and link:{repoURL}/src/main/java/seedu/address/model/book/Person.java[`Person`] classes can be used to implement the tag removal logic. link:{repoURL}/src/main/java/seedu/address/model/Catalogue.java[`Catalogue`] allows you to update a book, and link:{repoURL}/src/main/java/seedu/address/model/book/Person.java[`Person`] allows you to update the tags. +** Find out which of the existing API methods in link:{repoURL}/src/main/java/seedu/address/model/Catalogue.java[`Catalogue`] and link:{repoURL}/src/main/java/seedu/address/model/book/Book.java[`Book`] classes can be used to implement the tag removal logic. link:{repoURL}/src/main/java/seedu/address/model/Catalogue.java[`Catalogue`] allows you to update a book, and link:{repoURL}/src/main/java/seedu/address/model/book/Book.java[`Book`] allows you to update the tags. * Solution ** Implement a `removeTag(Tag)` method in link:{repoURL}/src/main/java/seedu/address/model/Catalogue.java[`Catalogue`]. Loop through each book, and remove the `tag` from each book. ** Add a new API method `deleteTag(Tag)` in link:{repoURL}/src/main/java/seedu/address/model/ModelManager.java[`ModelManager`]. Your link:{repoURL}/src/main/java/seedu/address/model/ModelManager.java[`ModelManager`] should call `Catalogue#removeTag(Tag)`. @@ -610,11 +610,11 @@ image::getting-started-ui-tag-after.png[width="300"] + **** * Hints -** The tag labels are created inside link:{repoURL}/src/main/java/seedu/address/ui/PersonCard.java[the `PersonCard` constructor] (`new Label(tag.tagName)`). https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/Label.html[JavaFX's `Label` class] allows you to modify the style of each Label, such as changing its color. +** The tag labels are created inside link:{repoURL}/src/main/java/seedu/address/ui/BookCard.java[the `BookCard` constructor] (`new Label(tag.tagName)`). https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/Label.html[JavaFX's `Label` class] allows you to modify the style of each Label, such as changing its color. ** Use the .css attribute `-fx-background-color` to add a color. ** You may wish to modify link:{repoURL}/src/main/resources/view/DarkTheme.css[`DarkTheme.css`] to include some pre-defined colors using css, especially if you have experience with web-based css. * Solution -** You can modify the existing test methods for `PersonCard` 's to include testing the tag's color as well. +** You can modify the existing test methods for `BookCard` 's to include testing the tag's color as well. ** See this https://github.com/se-edu/addressbook-level4/pull/798[PR] for the full solution. *** The PR uses the hash code of the tag names to generate a color. This is deliberately designed to ensure consistent colors each time the application runs. You may wish to expand on this design to include additional features, such as allowing users to set their own tag colors, and directly saving the colors to storage, so that tags retain their colors even if the hash code algorithm changes. **** @@ -732,20 +732,20 @@ Let's teach the application to parse arguments that our `remark` command will ac for `RemarkCommandParser`. . Modify link:{repoURL}/src/test/java/seedu/address/logic/parser/CatalogueParserTest.java[`CatalogueParserTest`] to test that the correct command is generated according to the user input. -===== [Step 3] Ui: Add a placeholder for remark in `PersonCard` -Let's add a placeholder on all our link:{repoURL}/src/main/java/seedu/address/ui/PersonCard.java[`PersonCard`] s to display a remark for each book later. +===== [Step 3] Ui: Add a placeholder for remark in `BookCard` +Let's add a placeholder on all our link:{repoURL}/src/main/java/seedu/address/ui/BookCard.java[`BookCard`] s to display a remark for each book later. **Main:** -. Add a `Label` with any random text inside link:{repoURL}/src/main/resources/view/PersonListCard.fxml[`PersonListCard.fxml`]. -. Add FXML annotation in link:{repoURL}/src/main/java/seedu/address/ui/PersonCard.java[`PersonCard`] to tie the variable to the actual label. +. Add a `Label` with any random text inside link:{repoURL}/src/main/resources/view/BookListCard.fxml[`BookListCard.fxml`]. +. Add FXML annotation in link:{repoURL}/src/main/java/seedu/address/ui/BookCard.java[`BookCard`] to tie the variable to the actual label. **Tests:** -. Modify link:{repoURL}/src/test/java/guitests/guihandles/PersonCardHandle.java[`PersonCardHandle`] so that future tests can read the contents of the remark label. +. Modify link:{repoURL}/src/test/java/guitests/guihandles/BookCardHandle.java[`BookCardHandle`] so that future tests can read the contents of the remark label. ===== [Step 4] Model: Add `Remark` class -We have to properly encapsulate the remark in our link:{repoURL}/src/main/java/seedu/address/model/book/Person.java[`Person`] class. Instead of just using a `String`, let's follow the conventional class structure that the codebase already uses by adding a `Remark` class. +We have to properly encapsulate the remark in our link:{repoURL}/src/main/java/seedu/address/model/book/Book.java[`Book`] class. Instead of just using a `String`, let's follow the conventional class structure that the codebase already uses by adding a `Remark` class. **Main:** @@ -756,17 +756,17 @@ We have to properly encapsulate the remark in our link:{repoURL}/src/main/java/s . Add test for `Remark`, to test the `Remark#equals()` method. -===== [Step 5] Model: Modify `Person` to support a `Remark` field -Now we have the `Remark` class, we need to actually use it inside link:{repoURL}/src/main/java/seedu/address/model/book/Person.java[`Person`]. +===== [Step 5] Model: Modify `Book` to support a `Remark` field +Now we have the `Remark` class, we need to actually use it inside link:{repoURL}/src/main/java/seedu/address/model/book/Book.java[`Book`]. **Main:** -. Add `getRemark()` in link:{repoURL}/src/main/java/seedu/address/model/book/Person.java[`Person`]. +. Add `getRemark()` in link:{repoURL}/src/main/java/seedu/address/model/book/Book.java[`Book`]. . You may assume that the user will not be able to use the `add` and `edit` commands to modify the remarks field (i.e. the book will be created without a remark). . Modify link:{repoURL}/src/main/java/seedu/address/model/util/SampleDataUtil.java/[`SampleDataUtil`] to add remarks for the sample data (delete your `catalogue.xml` so that the application will load the sample data when you launch it.) -===== [Step 6] Storage: Add `Remark` field to `XmlAdaptedPerson` class -We now have `Remark` s for `Person` s, but they will be gone when we exit the application. Let's modify link:{repoURL}/src/main/java/seedu/address/storage/XmlAdaptedPerson.java[`XmlAdaptedPerson`] to include a `Remark` field so that it will be saved. +===== [Step 6] Storage: Add `Remark` field to `XmlAdaptedBook` class +We now have `Remark` s for `Book` s, but they will be gone when we exit the application. Let's modify link:{repoURL}/src/main/java/seedu/address/storage/XmlAdaptedBook.java[`XmlAdaptedBook`] to include a `Remark` field so that it will be saved. **Main:** @@ -774,26 +774,26 @@ We now have `Remark` s for `Person` s, but they will be gone when we exit the ap **Tests:** -. Fix `invalidAndValidPersonCatalogue.xml`, `typicalPersonsCatalogue.xml`, `validCatalogue.xml` etc., such that the XML tests will not fail due to a missing `` element. +. Fix `invalidAndValidBookCatalogue.xml`, `typicalBooksCatalogue.xml`, `validCatalogue.xml` etc., such that the XML tests will not fail due to a missing `` element. -===== [Step 6b] Test: Add withRemark() for `PersonBuilder` -Since `Person` can now have a `Remark`, we should add a helper method to link:{repoURL}/src/test/java/seedu/address/testutil/PersonBuilder.java[`PersonBuilder`], so that users are able to create remarks when building a link:{repoURL}/src/main/java/seedu/address/model/book/Person.java[`Person`]. +===== [Step 6b] Test: Add withRemark() for `BookBuilder` +Since `Book` can now have a `Remark`, we should add a helper method to link:{repoURL}/src/test/java/seedu/address/testutil/BookBuilder.java[`BookBuilder`], so that users are able to create remarks when building a link:{repoURL}/src/main/java/seedu/address/model/book/Book.java[`Book`]. **Tests:** -. Add a new method `withRemark()` for link:{repoURL}/src/test/java/seedu/address/testutil/PersonBuilder.java[`PersonBuilder`]. This method will create a new `Remark` for the book that it is currently building. -. Try and use the method on any sample `Person` in link:{repoURL}/src/test/java/seedu/address/testutil/TypicalPersons.java[`TypicalPersons`]. +. Add a new method `withRemark()` for link:{repoURL}/src/test/java/seedu/address/testutil/BookBuilder.java[`BookBuilder`]. This method will create a new `Remark` for the book that it is currently building. +. Try and use the method on any sample `Book` in link:{repoURL}/src/test/java/seedu/address/testutil/TypicalBooks.java[`TypicalBooks`]. -===== [Step 7] Ui: Connect `Remark` field to `PersonCard` -Our remark label in link:{repoURL}/src/main/java/seedu/address/ui/PersonCard.java[`PersonCard`] is still a placeholder. Let's bring it to life by binding it with the actual `remark` field. +===== [Step 7] Ui: Connect `Remark` field to `BookCard` +Our remark label in link:{repoURL}/src/main/java/seedu/address/ui/BookCard.java[`BookCard`] is still a placeholder. Let's bring it to life by binding it with the actual `remark` field. **Main:** -. Modify link:{repoURL}/src/main/java/seedu/address/ui/PersonCard.java[`PersonCard`]'s constructor to bind the `Remark` field to the `Person` 's remark. +. Modify link:{repoURL}/src/main/java/seedu/address/ui/BookCard.java[`BookCard`]'s constructor to bind the `Remark` field to the `Book` 's remark. **Tests:** -. Modify link:{repoURL}/src/test/java/seedu/address/ui/testutil/GuiTestAssert.java[`GuiTestAssert#assertCardDisplaysPerson(...)`] so that it will compare the now-functioning remark label. +. Modify link:{repoURL}/src/test/java/seedu/address/ui/testutil/GuiTestAssert.java[`GuiTestAssert#assertCardDisplaysBook(...)`] so that it will compare the now-functioning remark label. ===== [Step 8] Logic: Implement `RemarkCommand#execute()` logic We now have everything set up... but we still can't modify the remarks. Let's finish it up by adding in actual logic for our `remark` command. diff --git a/docs/LearningOutcomes.adoc b/docs/LearningOutcomes.adoc index b764735c5f35..8eb21c01d624 100644 --- a/docs/LearningOutcomes.adoc +++ b/docs/LearningOutcomes.adoc @@ -222,7 +222,7 @@ Here are some example design patterns used in the code base. * *MVC Pattern* : ** The 'View' part of the application is mostly in the `.fxml` files in the `src/main/resources/view` folder. ** `Model` component contains the 'Model'. However, note that it is possible to view the `Logic` as the model because it hides the `Model` behind it and the view has to go through the `Logic` to access the `Model`. -** Sub classes of link:{repoURL}/src/main/java/seedu/address/ui/UiPart.java[`UiPart`] (e.g. `PersonListPanel` ) act as 'Controllers', each controlling some part of the UI and communicating with the 'Model' (via the `Logic` component which sits between the 'Controller' and the 'Model'). +** Sub classes of link:{repoURL}/src/main/java/seedu/address/ui/UiPart.java[`UiPart`] (e.g. `BookListPanel` ) act as 'Controllers', each controlling some part of the UI and communicating with the 'Model' (via the `Logic` component which sits between the 'Controller' and the 'Model'). * *Abstraction Occurrence Pattern* : Not currently used in the app. *Resources* diff --git a/docs/UserGuide.adoc b/docs/UserGuide.adoc index 766cba9d0ccc..1a252721ca4b 100644 --- a/docs/UserGuide.adoc +++ b/docs/UserGuide.adoc @@ -108,7 +108,7 @@ Format: `find KEYWORD [MORE_KEYWORDS]` * The order of the keywords does not matter. e.g. `Hans Bo` will match `Bo Hans` * Only the name is searched. * Only full words will be matched e.g. `Han` will not match `Hans` -* Persons matching at least one keyword will be returned (i.e. `OR` search). e.g. `Hans Bo` will return `Hans Gruber`, `Bo Yang` +* Books matching at least one keyword will be returned (i.e. `OR` search). e.g. `Hans Bo` will return `Hans Gruber`, `Bo Yang` **** Examples: diff --git a/docs/UsingTravis.adoc b/docs/UsingTravis.adoc index 78109fb1436c..149e13561467 100644 --- a/docs/UsingTravis.adoc +++ b/docs/UsingTravis.adoc @@ -61,7 +61,7 @@ image:travis_build.png[Travis build] Using this account, generate a personal access token https://github.com/settings/tokens/new[here]. + [NOTE] -Personal access tokens are like passwords so make sure you keep them secret! If the personal access token is leaked, please delete it and generate a new one. +Bookal access tokens are like passwords so make sure you keep them secret! If the personal access token is leaked, please delete it and generate a new one. + [NOTE] We use a new user account to generate the token for team projects to prevent team members from gaining access to other team members' repos. + diff --git a/src/main/java/seedu/address/commons/core/Messages.java b/src/main/java/seedu/address/commons/core/Messages.java index d6cc63453fc5..87cc97753813 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 book index provided is invalid"; - public static final String MESSAGE_PERSONS_LISTED_OVERVIEW = "%1$d persons listed!"; + public static final String MESSAGE_INVALID_BOOK_DISPLAYED_INDEX = "The book index provided is invalid"; + public static final String MESSAGE_BOOKS_LISTED_OVERVIEW = "%1$d books listed!"; } diff --git a/src/main/java/seedu/address/commons/events/model/CatalogueChangedEvent.java b/src/main/java/seedu/address/commons/events/model/CatalogueChangedEvent.java index 0c192e007674..ea808338dc06 100644 --- a/src/main/java/seedu/address/commons/events/model/CatalogueChangedEvent.java +++ b/src/main/java/seedu/address/commons/events/model/CatalogueChangedEvent.java @@ -14,6 +14,6 @@ public CatalogueChangedEvent(ReadOnlyCatalogue data) { @Override public String toString() { - return "number of persons " + data.getPersonList().size() + ", number of tags " + data.getTagList().size(); + return "number of books " + data.getBookList().size() + ", number of tags " + data.getTagList().size(); } } diff --git a/src/main/java/seedu/address/commons/events/ui/PersonPanelSelectionChangedEvent.java b/src/main/java/seedu/address/commons/events/ui/BookPanelSelectionChangedEvent.java similarity index 57% rename from src/main/java/seedu/address/commons/events/ui/PersonPanelSelectionChangedEvent.java rename to src/main/java/seedu/address/commons/events/ui/BookPanelSelectionChangedEvent.java index 0c84129a51ca..e12a78cff46e 100644 --- a/src/main/java/seedu/address/commons/events/ui/PersonPanelSelectionChangedEvent.java +++ b/src/main/java/seedu/address/commons/events/ui/BookPanelSelectionChangedEvent.java @@ -1,17 +1,17 @@ package seedu.address.commons.events.ui; import seedu.address.commons.events.BaseEvent; -import seedu.address.ui.PersonCard; +import seedu.address.ui.BookCard; /** * Represents a selection change in the Book List Panel */ -public class PersonPanelSelectionChangedEvent extends BaseEvent { +public class BookPanelSelectionChangedEvent extends BaseEvent { - private final PersonCard newSelection; + private final BookCard newSelection; - public PersonPanelSelectionChangedEvent(PersonCard newSelection) { + public BookPanelSelectionChangedEvent(BookCard newSelection) { this.newSelection = newSelection; } @@ -20,7 +20,7 @@ public String toString() { return this.getClass().getSimpleName(); } - public PersonCard getNewSelection() { + public BookCard getNewSelection() { return newSelection; } } diff --git a/src/main/java/seedu/address/commons/events/ui/JumpToListRequestEvent.java b/src/main/java/seedu/address/commons/events/ui/JumpToListRequestEvent.java index 4fc32183f074..cf40af55ba67 100644 --- a/src/main/java/seedu/address/commons/events/ui/JumpToListRequestEvent.java +++ b/src/main/java/seedu/address/commons/events/ui/JumpToListRequestEvent.java @@ -4,7 +4,7 @@ import seedu.address.commons.events.BaseEvent; /** - * Indicates a request to jump to the list of persons + * Indicates a request to jump to the list of books */ public class JumpToListRequestEvent extends BaseEvent { diff --git a/src/main/java/seedu/address/logic/Logic.java b/src/main/java/seedu/address/logic/Logic.java index 678346ac1a73..280f366981f8 100644 --- a/src/main/java/seedu/address/logic/Logic.java +++ b/src/main/java/seedu/address/logic/Logic.java @@ -19,8 +19,8 @@ public interface Logic { */ CommandResult execute(String commandText) throws CommandException, ParseException; - /** Returns an unmodifiable view of the filtered list of persons */ - ObservableList getFilteredPersonList(); + /** Returns an unmodifiable view of the filtered list of books */ + ObservableList getFilteredBookList(); /** Returns the list of input entered by the user, encapsulated in a {@code ListElementPointer} object */ ListElementPointer getHistorySnapshot(); diff --git a/src/main/java/seedu/address/logic/LogicManager.java b/src/main/java/seedu/address/logic/LogicManager.java index 86b36fee91d9..fecd29a9f4fb 100644 --- a/src/main/java/seedu/address/logic/LogicManager.java +++ b/src/main/java/seedu/address/logic/LogicManager.java @@ -46,8 +46,8 @@ public CommandResult execute(String commandText) throws CommandException, ParseE } @Override - public ObservableList getFilteredPersonList() { - return model.getFilteredPersonList(); + public ObservableList getFilteredBookList() { + return model.getFilteredBookList(); } @Override diff --git a/src/main/java/seedu/address/logic/commands/AddCommand.java b/src/main/java/seedu/address/logic/commands/AddCommand.java index a4bf972da125..2f27ec140bb9 100644 --- a/src/main/java/seedu/address/logic/commands/AddCommand.java +++ b/src/main/java/seedu/address/logic/commands/AddCommand.java @@ -9,7 +9,7 @@ import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.model.book.Book; -import seedu.address.model.book.exceptions.DuplicatePersonException; +import seedu.address.model.book.exceptions.DuplicateBookException; /** * Adds a book to the catalogue. @@ -34,7 +34,7 @@ public class AddCommand extends UndoableCommand { + PREFIX_TAG + "owesMoney"; public static final String MESSAGE_SUCCESS = "New book added: %1$s"; - public static final String MESSAGE_DUPLICATE_PERSON = "This book already exists in the catalogue"; + public static final String MESSAGE_DUPLICATE_BOOK = "This book already exists in the catalogue"; private final Book toAdd; @@ -50,10 +50,10 @@ public AddCommand(Book book) { public CommandResult executeUndoableCommand() throws CommandException { requireNonNull(model); try { - model.addPerson(toAdd); + model.addBook(toAdd); return new CommandResult(String.format(MESSAGE_SUCCESS, toAdd)); - } catch (DuplicatePersonException e) { - throw new CommandException(MESSAGE_DUPLICATE_PERSON); + } catch (DuplicateBookException e) { + throw new CommandException(MESSAGE_DUPLICATE_BOOK); } } diff --git a/src/main/java/seedu/address/logic/commands/Command.java b/src/main/java/seedu/address/logic/commands/Command.java index 6580e0b51c90..fb6ca64d0fa7 100644 --- a/src/main/java/seedu/address/logic/commands/Command.java +++ b/src/main/java/seedu/address/logic/commands/Command.java @@ -15,13 +15,13 @@ public abstract class Command { protected UndoRedoStack undoRedoStack; /** - * Constructs a feedback message to summarise an operation that displayed a listing of persons. + * Constructs a feedback message to summarise an operation that displayed a listing of books. * * @param displaySize used to generate summary - * @return summary message for persons displayed + * @return summary message for books displayed */ - public static String getMessageForPersonListShownSummary(int displaySize) { - return String.format(Messages.MESSAGE_PERSONS_LISTED_OVERVIEW, displaySize); + public static String getMessageForBookListShownSummary(int displaySize) { + return String.format(Messages.MESSAGE_BOOKS_LISTED_OVERVIEW, displaySize); } /** diff --git a/src/main/java/seedu/address/logic/commands/DeleteCommand.java b/src/main/java/seedu/address/logic/commands/DeleteCommand.java index 2782a7764aab..e25ce4f99898 100644 --- a/src/main/java/seedu/address/logic/commands/DeleteCommand.java +++ b/src/main/java/seedu/address/logic/commands/DeleteCommand.java @@ -9,7 +9,7 @@ import seedu.address.commons.core.index.Index; import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.model.book.Book; -import seedu.address.model.book.exceptions.PersonNotFoundException; +import seedu.address.model.book.exceptions.BookNotFoundException; /** * Deletes a book identified using it's last displayed index from the catalogue. @@ -23,7 +23,7 @@ public class DeleteCommand extends UndoableCommand { + "Parameters: INDEX (must be a positive integer)\n" + "Example: " + COMMAND_WORD + " 1"; - public static final String MESSAGE_DELETE_PERSON_SUCCESS = "Deleted Book: %1$s"; + public static final String MESSAGE_DELETE_BOOK_SUCCESS = "Deleted Book: %1$s"; private final Index targetIndex; @@ -38,20 +38,20 @@ public DeleteCommand(Index targetIndex) { public CommandResult executeUndoableCommand() { requireNonNull(bookToDelete); try { - model.deletePerson(bookToDelete); - } catch (PersonNotFoundException pnfe) { + model.deleteBook(bookToDelete); + } catch (BookNotFoundException pnfe) { throw new AssertionError("The target book cannot be missing"); } - return new CommandResult(String.format(MESSAGE_DELETE_PERSON_SUCCESS, bookToDelete)); + return new CommandResult(String.format(MESSAGE_DELETE_BOOK_SUCCESS, bookToDelete)); } @Override protected void preprocessUndoableCommand() throws CommandException { - List lastShownList = model.getFilteredPersonList(); + List lastShownList = model.getFilteredBookList(); if (targetIndex.getZeroBased() >= lastShownList.size()) { - throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); + throw new CommandException(Messages.MESSAGE_INVALID_BOOK_DISPLAYED_INDEX); } bookToDelete = lastShownList.get(targetIndex.getZeroBased()); diff --git a/src/main/java/seedu/address/logic/commands/EditCommand.java b/src/main/java/seedu/address/logic/commands/EditCommand.java index 890b9df91647..8489b6799e4b 100644 --- a/src/main/java/seedu/address/logic/commands/EditCommand.java +++ b/src/main/java/seedu/address/logic/commands/EditCommand.java @@ -6,7 +6,7 @@ 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_BOOKS; import java.util.Collections; import java.util.HashSet; @@ -24,8 +24,8 @@ import seedu.address.model.book.Email; import seedu.address.model.book.Name; import seedu.address.model.book.Phone; -import seedu.address.model.book.exceptions.DuplicatePersonException; -import seedu.address.model.book.exceptions.PersonNotFoundException; +import seedu.address.model.book.exceptions.DuplicateBookException; +import seedu.address.model.book.exceptions.BookNotFoundException; import seedu.address.model.tag.Tag; /** @@ -48,65 +48,65 @@ public class EditCommand extends UndoableCommand { + PREFIX_PHONE + "91234567 " + PREFIX_EMAIL + "johndoe@example.com"; - public static final String MESSAGE_EDIT_PERSON_SUCCESS = "Edited Book: %1$s"; + public static final String MESSAGE_EDIT_BOOK_SUCCESS = "Edited Book: %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 book already exists in the catalogue."; + public static final String MESSAGE_DUPLICATE_BOOK = "This book already exists in the catalogue."; private final Index index; - private final EditPersonDescriptor editPersonDescriptor; + private final EditBookDescriptor editBookDescriptor; private Book bookToEdit; private Book editedBook; /** * @param index of the book in the filtered book list to edit - * @param editPersonDescriptor details to edit the book with + * @param editBookDescriptor details to edit the book with */ - public EditCommand(Index index, EditPersonDescriptor editPersonDescriptor) { + public EditCommand(Index index, EditBookDescriptor editBookDescriptor) { requireNonNull(index); - requireNonNull(editPersonDescriptor); + requireNonNull(editBookDescriptor); this.index = index; - this.editPersonDescriptor = new EditPersonDescriptor(editPersonDescriptor); + this.editBookDescriptor = new EditBookDescriptor(editBookDescriptor); } @Override public CommandResult executeUndoableCommand() throws CommandException { try { - model.updatePerson(bookToEdit, editedBook); - } catch (DuplicatePersonException dpe) { - throw new CommandException(MESSAGE_DUPLICATE_PERSON); - } catch (PersonNotFoundException pnfe) { + model.updateBook(bookToEdit, editedBook); + } catch (DuplicateBookException dpe) { + throw new CommandException(MESSAGE_DUPLICATE_BOOK); + } catch (BookNotFoundException pnfe) { throw new AssertionError("The target book cannot be missing"); } - model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); - return new CommandResult(String.format(MESSAGE_EDIT_PERSON_SUCCESS, editedBook)); + model.updateFilteredBookList(PREDICATE_SHOW_ALL_BOOKS); + return new CommandResult(String.format(MESSAGE_EDIT_BOOK_SUCCESS, editedBook)); } @Override protected void preprocessUndoableCommand() throws CommandException { - List lastShownList = model.getFilteredPersonList(); + List lastShownList = model.getFilteredBookList(); if (index.getZeroBased() >= lastShownList.size()) { - throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); + throw new CommandException(Messages.MESSAGE_INVALID_BOOK_DISPLAYED_INDEX); } bookToEdit = lastShownList.get(index.getZeroBased()); - editedBook = createEditedPerson(bookToEdit, editPersonDescriptor); + editedBook = createEditedBook(bookToEdit, editBookDescriptor); } /** * Creates and returns a {@code Book} with the details of {@code bookToEdit} - * edited with {@code editPersonDescriptor}. + * edited with {@code editBookDescriptor}. */ - private static Book createEditedPerson(Book bookToEdit, EditPersonDescriptor editPersonDescriptor) { + private static Book createEditedBook(Book bookToEdit, EditBookDescriptor editBookDescriptor) { assert bookToEdit != null; - Name updatedName = editPersonDescriptor.getName().orElse(bookToEdit.getName()); - Phone updatedPhone = editPersonDescriptor.getPhone().orElse(bookToEdit.getPhone()); - Email updatedEmail = editPersonDescriptor.getEmail().orElse(bookToEdit.getEmail()); - Address updatedAddress = editPersonDescriptor.getAddress().orElse(bookToEdit.getAddress()); - Set updatedTags = editPersonDescriptor.getTags().orElse(bookToEdit.getTags()); + Name updatedName = editBookDescriptor.getName().orElse(bookToEdit.getName()); + Phone updatedPhone = editBookDescriptor.getPhone().orElse(bookToEdit.getPhone()); + Email updatedEmail = editBookDescriptor.getEmail().orElse(bookToEdit.getEmail()); + Address updatedAddress = editBookDescriptor.getAddress().orElse(bookToEdit.getAddress()); + Set updatedTags = editBookDescriptor.getTags().orElse(bookToEdit.getTags()); return new Book(updatedName, updatedPhone, updatedEmail, updatedAddress, updatedTags); } @@ -126,7 +126,7 @@ public boolean equals(Object other) { // state check EditCommand e = (EditCommand) other; return index.equals(e.index) - && editPersonDescriptor.equals(e.editPersonDescriptor) + && editBookDescriptor.equals(e.editBookDescriptor) && Objects.equals(bookToEdit, e.bookToEdit); } @@ -134,20 +134,20 @@ public boolean equals(Object other) { * Stores the details to edit the book with. Each non-empty field value will replace the * corresponding field value of the book. */ - public static class EditPersonDescriptor { + public static class EditBookDescriptor { private Name name; private Phone phone; private Email email; private Address address; private Set tags; - public EditPersonDescriptor() {} + public EditBookDescriptor() {} /** * Copy constructor. * A defensive copy of {@code tags} is used internally. */ - public EditPersonDescriptor(EditPersonDescriptor toCopy) { + public EditBookDescriptor(EditBookDescriptor toCopy) { setName(toCopy.name); setPhone(toCopy.phone); setEmail(toCopy.email); @@ -219,12 +219,12 @@ public boolean equals(Object other) { } // instanceof handles nulls - if (!(other instanceof EditPersonDescriptor)) { + if (!(other instanceof EditBookDescriptor)) { return false; } // state check - EditPersonDescriptor e = (EditPersonDescriptor) other; + EditBookDescriptor e = (EditBookDescriptor) other; return getName().equals(e.getName()) && getPhone().equals(e.getPhone()) diff --git a/src/main/java/seedu/address/logic/commands/FindCommand.java b/src/main/java/seedu/address/logic/commands/FindCommand.java index 53add3fd6546..bf6fea6e1f2b 100644 --- a/src/main/java/seedu/address/logic/commands/FindCommand.java +++ b/src/main/java/seedu/address/logic/commands/FindCommand.java @@ -3,14 +3,14 @@ import seedu.address.model.book.NameContainsKeywordsPredicate; /** - * Finds and lists all persons in catalogue whose name contains any of the argument keywords. + * Finds and lists all books in catalogue whose name contains any of the argument keywords. * Keyword matching is case sensitive. */ 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 books whose names contain any of " + "the specified keywords (case-sensitive) and displays them as a list with index numbers.\n" + "Parameters: KEYWORD [MORE_KEYWORDS]...\n" + "Example: " + COMMAND_WORD + " alice bob charlie"; @@ -23,8 +23,8 @@ public FindCommand(NameContainsKeywordsPredicate predicate) { @Override public CommandResult execute() { - model.updateFilteredPersonList(predicate); - return new CommandResult(getMessageForPersonListShownSummary(model.getFilteredPersonList().size())); + model.updateFilteredBookList(predicate); + return new CommandResult(getMessageForBookListShownSummary(model.getFilteredBookList().size())); } @Override diff --git a/src/main/java/seedu/address/logic/commands/ListCommand.java b/src/main/java/seedu/address/logic/commands/ListCommand.java index 478b450d0525..cf25f6a42dbd 100644 --- a/src/main/java/seedu/address/logic/commands/ListCommand.java +++ b/src/main/java/seedu/address/logic/commands/ListCommand.java @@ -1,20 +1,20 @@ package seedu.address.logic.commands; -import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS; +import static seedu.address.model.Model.PREDICATE_SHOW_ALL_BOOKS; /** - * Lists all persons in the catalogue to the user. + * Lists all books in the catalogue 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 books"; @Override public CommandResult execute() { - model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); + model.updateFilteredBookList(PREDICATE_SHOW_ALL_BOOKS); return new CommandResult(MESSAGE_SUCCESS); } } diff --git a/src/main/java/seedu/address/logic/commands/SelectCommand.java b/src/main/java/seedu/address/logic/commands/SelectCommand.java index e222d9e18c4d..cdeaef9208c0 100644 --- a/src/main/java/seedu/address/logic/commands/SelectCommand.java +++ b/src/main/java/seedu/address/logic/commands/SelectCommand.java @@ -21,7 +21,7 @@ public class SelectCommand extends Command { + "Parameters: INDEX (must be a positive integer)\n" + "Example: " + COMMAND_WORD + " 1"; - public static final String MESSAGE_SELECT_PERSON_SUCCESS = "Selected Book: %1$s"; + public static final String MESSAGE_SELECT_BOOK_SUCCESS = "Selected Book: %1$s"; private final Index targetIndex; @@ -32,14 +32,14 @@ public SelectCommand(Index targetIndex) { @Override public CommandResult execute() throws CommandException { - List lastShownList = model.getFilteredPersonList(); + List lastShownList = model.getFilteredBookList(); if (targetIndex.getZeroBased() >= lastShownList.size()) { - throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); + throw new CommandException(Messages.MESSAGE_INVALID_BOOK_DISPLAYED_INDEX); } EventsCenter.getInstance().post(new JumpToListRequestEvent(targetIndex)); - return new CommandResult(String.format(MESSAGE_SELECT_PERSON_SUCCESS, targetIndex.getOneBased())); + return new CommandResult(String.format(MESSAGE_SELECT_BOOK_SUCCESS, targetIndex.getOneBased())); } diff --git a/src/main/java/seedu/address/logic/commands/UndoableCommand.java b/src/main/java/seedu/address/logic/commands/UndoableCommand.java index ffbe3f80a55b..e518e91dc944 100644 --- a/src/main/java/seedu/address/logic/commands/UndoableCommand.java +++ b/src/main/java/seedu/address/logic/commands/UndoableCommand.java @@ -2,7 +2,7 @@ import static java.util.Objects.requireNonNull; import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; -import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS; +import static seedu.address.model.Model.PREDICATE_SHOW_ALL_BOOKS; import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.model.Catalogue; @@ -33,17 +33,17 @@ protected void preprocessUndoableCommand() throws CommandException {} /** * Reverts the Catalogue to the state before this command * was executed and updates the filtered book list to - * show all persons. + * show all books. */ protected final void undo() { requireAllNonNull(model, previousCatalogue); model.resetData(previousCatalogue); - model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); + model.updateFilteredBookList(PREDICATE_SHOW_ALL_BOOKS); } /** * Executes the command and updates the filtered book - * list to show all persons. + * list to show all books. */ protected final void redo() { requireNonNull(model); @@ -53,7 +53,7 @@ protected final void redo() { throw new AssertionError("The command has been successfully executed previously; " + "it should not fail now"); } - model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); + model.updateFilteredBookList(PREDICATE_SHOW_ALL_BOOKS); } @Override diff --git a/src/main/java/seedu/address/logic/parser/EditCommandParser.java b/src/main/java/seedu/address/logic/parser/EditCommandParser.java index c9cdbed26cf1..108dc98a692f 100644 --- a/src/main/java/seedu/address/logic/parser/EditCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/EditCommandParser.java @@ -16,7 +16,7 @@ import seedu.address.commons.core.index.Index; import seedu.address.commons.exceptions.IllegalValueException; import seedu.address.logic.commands.EditCommand; -import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; +import seedu.address.logic.commands.EditCommand.EditBookDescriptor; import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.tag.Tag; @@ -43,22 +43,22 @@ public EditCommand parse(String args) throws ParseException { throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE)); } - EditPersonDescriptor editPersonDescriptor = new EditPersonDescriptor(); + EditBookDescriptor editBookDescriptor = new EditBookDescriptor(); try { - ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME)).ifPresent(editPersonDescriptor::setName); - ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE)).ifPresent(editPersonDescriptor::setPhone); - ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL)).ifPresent(editPersonDescriptor::setEmail); - ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS)).ifPresent(editPersonDescriptor::setAddress); - parseTagsForEdit(argMultimap.getAllValues(PREFIX_TAG)).ifPresent(editPersonDescriptor::setTags); + ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME)).ifPresent(editBookDescriptor::setName); + ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE)).ifPresent(editBookDescriptor::setPhone); + ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL)).ifPresent(editBookDescriptor::setEmail); + ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS)).ifPresent(editBookDescriptor::setAddress); + parseTagsForEdit(argMultimap.getAllValues(PREFIX_TAG)).ifPresent(editBookDescriptor::setTags); } catch (IllegalValueException ive) { throw new ParseException(ive.getMessage(), ive); } - if (!editPersonDescriptor.isAnyFieldEdited()) { + if (!editBookDescriptor.isAnyFieldEdited()) { throw new ParseException(EditCommand.MESSAGE_NOT_EDITED); } - return new EditCommand(index, editPersonDescriptor); + return new EditCommand(index, editBookDescriptor); } /** diff --git a/src/main/java/seedu/address/model/Catalogue.java b/src/main/java/seedu/address/model/Catalogue.java index 5bc4bb5e98fe..f6f1b9a66031 100644 --- a/src/main/java/seedu/address/model/Catalogue.java +++ b/src/main/java/seedu/address/model/Catalogue.java @@ -12,9 +12,9 @@ import javafx.collections.ObservableList; import seedu.address.model.book.Book; -import seedu.address.model.book.UniquePersonList; -import seedu.address.model.book.exceptions.DuplicatePersonException; -import seedu.address.model.book.exceptions.PersonNotFoundException; +import seedu.address.model.book.UniqueBookList; +import seedu.address.model.book.exceptions.DuplicateBookException; +import seedu.address.model.book.exceptions.BookNotFoundException; import seedu.address.model.tag.Tag; import seedu.address.model.tag.UniqueTagList; @@ -24,7 +24,7 @@ */ public class Catalogue implements ReadOnlyCatalogue { - private final UniquePersonList persons; + private final UniqueBookList books; private final UniqueTagList tags; /* @@ -35,14 +35,14 @@ public class Catalogue implements ReadOnlyCatalogue { * among constructors. */ { - persons = new UniquePersonList(); + books = new UniqueBookList(); tags = new UniqueTagList(); } public Catalogue() {} /** - * Creates an Catalogue using the Persons and Tags in the {@code toBeCopied} + * Creates an Catalogue using the Books and Tags in the {@code toBeCopied} */ public Catalogue(ReadOnlyCatalogue toBeCopied) { this(); @@ -51,8 +51,8 @@ public Catalogue(ReadOnlyCatalogue toBeCopied) { //// list overwrite operations - public void setPersons(List books) throws DuplicatePersonException { - this.persons.setPersons(books); + public void setBooks(List books) throws DuplicateBookException { + this.books.setBooks(books); } public void setTags(Set tags) { @@ -65,14 +65,14 @@ public void setTags(Set tags) { public void resetData(ReadOnlyCatalogue newData) { requireNonNull(newData); setTags(new HashSet<>(newData.getTagList())); - List syncedBookList = newData.getPersonList().stream() + List syncedBookList = newData.getBookList().stream() .map(this::syncWithMasterTagList) .collect(Collectors.toList()); try { - setPersons(syncedBookList); - } catch (DuplicatePersonException e) { - throw new AssertionError("Catalogue should not have duplicate persons"); + setBooks(syncedBookList); + } catch (DuplicateBookException e) { + throw new AssertionError("Catalogue should not have duplicate books"); } } @@ -83,35 +83,35 @@ public void resetData(ReadOnlyCatalogue newData) { * Also checks the new book's tags and updates {@link #tags} with any new tags found, * and updates the Tag objects in the book to point to those in {@link #tags}. * - * @throws DuplicatePersonException if an equivalent book already exists. + * @throws DuplicateBookException if an equivalent book already exists. */ - public void addPerson(Book p) throws DuplicatePersonException { + public void addBook(Book p) throws DuplicateBookException { Book book = syncWithMasterTagList(p); // TODO: the tags master list will be updated even though the below line fails. // This can cause the tags master list to have additional tags that are not tagged to any book // in the book list. - persons.add(book); + books.add(book); } /** - * Replaces the given book {@code target} in the list with {@code editedPerson}. - * {@code Catalogue}'s tag list will be updated with the tags of {@code editedPerson}. + * Replaces the given book {@code target} in the list with {@code editedBook}. + * {@code Catalogue}'s tag list will be updated with the tags of {@code editedBook}. * - * @throws DuplicatePersonException if updating the book's details causes the book to be equivalent to + * @throws DuplicateBookException if updating the book's details causes the book to be equivalent to * another existing book in the list. - * @throws PersonNotFoundException if {@code target} could not be found in the list. + * @throws BookNotFoundException if {@code target} could not be found in the list. * * @see #syncWithMasterTagList(Book) */ - public void updatePerson(Book target, Book editedBook) - throws DuplicatePersonException, PersonNotFoundException { + public void updateBook(Book target, Book editedBook) + throws DuplicateBookException, BookNotFoundException { requireNonNull(editedBook); Book syncedEditedBook = syncWithMasterTagList(editedBook); // TODO: the tags master list will be updated even though the below line fails. // This can cause the tags master list to have additional tags that are not tagged to any book // in the book list. - persons.setPerson(target, syncedEditedBook); + books.setBook(target, syncedEditedBook); } /** @@ -120,8 +120,8 @@ public void updatePerson(Book target, Book editedBook) * list. */ private Book syncWithMasterTagList(Book book) { - final UniqueTagList personTags = new UniqueTagList(book.getTags()); - tags.mergeFrom(personTags); + final UniqueTagList bookTags = new UniqueTagList(book.getTags()); + tags.mergeFrom(bookTags); // Create map with values = tag object references in the master list // used for checking book tag references @@ -130,20 +130,20 @@ private Book syncWithMasterTagList(Book book) { // Rebuild the list of book tags to point to the relevant tags in the master tag list. final Set correctTagReferences = new HashSet<>(); - personTags.forEach(tag -> correctTagReferences.add(masterTagObjects.get(tag))); + bookTags.forEach(tag -> correctTagReferences.add(masterTagObjects.get(tag))); return new Book( book.getName(), book.getPhone(), book.getEmail(), book.getAddress(), correctTagReferences); } /** * Removes {@code key} from this {@code Catalogue}. - * @throws PersonNotFoundException if the {@code key} is not in this {@code Catalogue}. + * @throws BookNotFoundException if the {@code key} is not in this {@code Catalogue}. */ - public boolean removePerson(Book key) throws PersonNotFoundException { - if (persons.remove(key)) { + public boolean removeBook(Book key) throws BookNotFoundException { + if (books.remove(key)) { return true; } else { - throw new PersonNotFoundException(); + throw new BookNotFoundException(); } } @@ -157,13 +157,13 @@ public void addTag(Tag t) throws UniqueTagList.DuplicateTagException { @Override public String toString() { - return persons.asObservableList().size() + " persons, " + tags.asObservableList().size() + " tags"; + return books.asObservableList().size() + " books, " + tags.asObservableList().size() + " tags"; // TODO: refine later } @Override - public ObservableList getPersonList() { - return persons.asObservableList(); + public ObservableList getBookList() { + return books.asObservableList(); } @Override @@ -175,13 +175,13 @@ public ObservableList getTagList() { public boolean equals(Object other) { return other == this // short circuit if same object || (other instanceof Catalogue // instanceof handles nulls - && this.persons.equals(((Catalogue) other).persons) + && this.books.equals(((Catalogue) other).books) && this.tags.equalsOrderInsensitive(((Catalogue) other).tags)); } @Override public int hashCode() { // use this method for custom fields hashing instead of implementing your own - return Objects.hash(persons, tags); + return Objects.hash(books, tags); } } diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java index 7540260c18cd..fd9d3b19637a 100644 --- a/src/main/java/seedu/address/model/Model.java +++ b/src/main/java/seedu/address/model/Model.java @@ -4,15 +4,15 @@ import javafx.collections.ObservableList; import seedu.address.model.book.Book; -import seedu.address.model.book.exceptions.DuplicatePersonException; -import seedu.address.model.book.exceptions.PersonNotFoundException; +import seedu.address.model.book.exceptions.DuplicateBookException; +import seedu.address.model.book.exceptions.BookNotFoundException; /** * 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_BOOKS = unused -> true; /** Clears existing backing model and replaces with the provided new data. */ void resetData(ReadOnlyCatalogue newData); @@ -21,28 +21,28 @@ public interface Model { ReadOnlyCatalogue getCatalogue(); /** Deletes the given book. */ - void deletePerson(Book target) throws PersonNotFoundException; + void deleteBook(Book target) throws BookNotFoundException; /** Adds the given book */ - void addPerson(Book book) throws DuplicatePersonException; + void addBook(Book book) throws DuplicateBookException; /** * Replaces the given book {@code target} with {@code editedBook}. * - * @throws DuplicatePersonException if updating the book's details causes the book to be equivalent to + * @throws DuplicateBookException if updating the book's details causes the book to be equivalent to * another existing book in the list. - * @throws PersonNotFoundException if {@code target} could not be found in the list. + * @throws BookNotFoundException if {@code target} could not be found in the list. */ - void updatePerson(Book target, Book editedBook) - throws DuplicatePersonException, PersonNotFoundException; + void updateBook(Book target, Book editedBook) + throws DuplicateBookException, BookNotFoundException; /** Returns an unmodifiable view of the filtered book list */ - ObservableList getFilteredPersonList(); + ObservableList getFilteredBookList(); /** * Updates the filter of the filtered book list to filter by the given {@code predicate}. * @throws NullPointerException if {@code predicate} is null. */ - void updateFilteredPersonList(Predicate predicate); + void updateFilteredBookList(Predicate predicate); } diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index e1db0de6b423..ab9df6d25124 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -13,8 +13,8 @@ import seedu.address.commons.core.LogsCenter; import seedu.address.commons.events.model.CatalogueChangedEvent; import seedu.address.model.book.Book; -import seedu.address.model.book.exceptions.DuplicatePersonException; -import seedu.address.model.book.exceptions.PersonNotFoundException; +import seedu.address.model.book.exceptions.DuplicateBookException; +import seedu.address.model.book.exceptions.BookNotFoundException; /** * Represents the in-memory model of the catalogue data. @@ -36,7 +36,7 @@ public ModelManager(ReadOnlyCatalogue catalogue, UserPrefs userPrefs) { logger.fine("Initializing with catalogue: " + catalogue + " and user prefs " + userPrefs); this.catalogue = new Catalogue(catalogue); - filteredBooks = new FilteredList<>(this.catalogue.getPersonList()); + filteredBooks = new FilteredList<>(this.catalogue.getBookList()); } public ModelManager() { @@ -60,24 +60,24 @@ private void indicateCatalogueChanged() { } @Override - public synchronized void deletePerson(Book target) throws PersonNotFoundException { - catalogue.removePerson(target); + public synchronized void deleteBook(Book target) throws BookNotFoundException { + catalogue.removeBook(target); indicateCatalogueChanged(); } @Override - public synchronized void addPerson(Book book) throws DuplicatePersonException { - catalogue.addPerson(book); - updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); + public synchronized void addBook(Book book) throws DuplicateBookException { + catalogue.addBook(book); + updateFilteredBookList(PREDICATE_SHOW_ALL_BOOKS); indicateCatalogueChanged(); } @Override - public void updatePerson(Book target, Book editedBook) - throws DuplicatePersonException, PersonNotFoundException { + public void updateBook(Book target, Book editedBook) + throws DuplicateBookException, BookNotFoundException { requireAllNonNull(target, editedBook); - catalogue.updatePerson(target, editedBook); + catalogue.updateBook(target, editedBook); indicateCatalogueChanged(); } @@ -88,12 +88,12 @@ public void updatePerson(Book target, Book editedBook) * {@code catalogue} */ @Override - public ObservableList getFilteredPersonList() { + public ObservableList getFilteredBookList() { return FXCollections.unmodifiableObservableList(filteredBooks); } @Override - public void updateFilteredPersonList(Predicate predicate) { + public void updateFilteredBookList(Predicate predicate) { requireNonNull(predicate); filteredBooks.setPredicate(predicate); } diff --git a/src/main/java/seedu/address/model/ReadOnlyCatalogue.java b/src/main/java/seedu/address/model/ReadOnlyCatalogue.java index 9f60168ebf24..34536d7263cd 100644 --- a/src/main/java/seedu/address/model/ReadOnlyCatalogue.java +++ b/src/main/java/seedu/address/model/ReadOnlyCatalogue.java @@ -10,10 +10,10 @@ public interface ReadOnlyCatalogue { /** - * Returns an unmodifiable view of the persons list. - * This list will not contain any duplicate persons. + * Returns an unmodifiable view of the books list. + * This list will not contain any duplicate books. */ - ObservableList getPersonList(); + ObservableList getBookList(); /** * Returns an unmodifiable view of the tags list. diff --git a/src/main/java/seedu/address/model/book/UniquePersonList.java b/src/main/java/seedu/address/model/book/UniqueBookList.java similarity index 56% rename from src/main/java/seedu/address/model/book/UniquePersonList.java rename to src/main/java/seedu/address/model/book/UniqueBookList.java index d50c34b43d75..064b4b5f73cf 100644 --- a/src/main/java/seedu/address/model/book/UniquePersonList.java +++ b/src/main/java/seedu/address/model/book/UniqueBookList.java @@ -9,18 +9,18 @@ import javafx.collections.FXCollections; import javafx.collections.ObservableList; import seedu.address.commons.util.CollectionUtil; -import seedu.address.model.book.exceptions.DuplicatePersonException; -import seedu.address.model.book.exceptions.PersonNotFoundException; +import seedu.address.model.book.exceptions.DuplicateBookException; +import seedu.address.model.book.exceptions.BookNotFoundException; /** - * A list of persons that enforces uniqueness between its elements and does not allow nulls. + * A list of books that enforces uniqueness between its elements and does not allow nulls. * * Supports a minimal set of list operations. * * @see Book#equals(Object) * @see CollectionUtil#elementsAreUnique(Collection) */ -public class UniquePersonList implements Iterable { +public class UniqueBookList implements Iterable { private final ObservableList internalList = FXCollections.observableArrayList(); @@ -35,12 +35,12 @@ public boolean contains(Book toCheck) { /** * Adds a book to the list. * - * @throws DuplicatePersonException if the book to add is a duplicate of an existing book in the list. + * @throws DuplicateBookException if the book to add is a duplicate of an existing book in the list. */ - public void add(Book toAdd) throws DuplicatePersonException { + public void add(Book toAdd) throws DuplicateBookException { requireNonNull(toAdd); if (contains(toAdd)) { - throw new DuplicatePersonException(); + throw new DuplicateBookException(); } internalList.add(toAdd); } @@ -48,20 +48,20 @@ public void add(Book toAdd) throws DuplicatePersonException { /** * Replaces the book {@code target} in the list with {@code editedBook}. * - * @throws DuplicatePersonException if the replacement is equivalent to another existing book in the list. - * @throws PersonNotFoundException if {@code target} could not be found in the list. + * @throws DuplicateBookException if the replacement is equivalent to another existing book in the list. + * @throws BookNotFoundException if {@code target} could not be found in the list. */ - public void setPerson(Book target, Book editedBook) - throws DuplicatePersonException, PersonNotFoundException { + public void setBook(Book target, Book editedBook) + throws DuplicateBookException, BookNotFoundException { requireNonNull(editedBook); int index = internalList.indexOf(target); if (index == -1) { - throw new PersonNotFoundException(); + throw new BookNotFoundException(); } if (!target.equals(editedBook) && internalList.contains(editedBook)) { - throw new DuplicatePersonException(); + throw new DuplicateBookException(); } internalList.set(index, editedBook); @@ -70,28 +70,28 @@ public void setPerson(Book target, Book editedBook) /** * Removes the equivalent book from the list. * - * @throws PersonNotFoundException if no such book could be found in the list. + * @throws BookNotFoundException if no such book could be found in the list. */ - public boolean remove(Book toRemove) throws PersonNotFoundException { + public boolean remove(Book toRemove) throws BookNotFoundException { requireNonNull(toRemove); - final boolean personFoundAndDeleted = internalList.remove(toRemove); - if (!personFoundAndDeleted) { - throw new PersonNotFoundException(); + final boolean bookFoundAndDeleted = internalList.remove(toRemove); + if (!bookFoundAndDeleted) { + throw new BookNotFoundException(); } - return personFoundAndDeleted; + return bookFoundAndDeleted; } - public void setPersons(UniquePersonList replacement) { + public void setBooks(UniqueBookList replacement) { this.internalList.setAll(replacement.internalList); } - public void setPersons(List books) throws DuplicatePersonException { + public void setBooks(List books) throws DuplicateBookException { requireAllNonNull(books); - final UniquePersonList replacement = new UniquePersonList(); + final UniqueBookList replacement = new UniqueBookList(); for (final Book book : books) { replacement.add(book); } - setPersons(replacement); + setBooks(replacement); } /** @@ -109,8 +109,8 @@ public Iterator iterator() { @Override public boolean equals(Object other) { return other == this // short circuit if same object - || (other instanceof UniquePersonList // instanceof handles nulls - && this.internalList.equals(((UniquePersonList) other).internalList)); + || (other instanceof UniqueBookList // instanceof handles nulls + && this.internalList.equals(((UniqueBookList) other).internalList)); } @Override diff --git a/src/main/java/seedu/address/model/book/exceptions/PersonNotFoundException.java b/src/main/java/seedu/address/model/book/exceptions/BookNotFoundException.java similarity index 67% rename from src/main/java/seedu/address/model/book/exceptions/PersonNotFoundException.java rename to src/main/java/seedu/address/model/book/exceptions/BookNotFoundException.java index ac0bd58e8780..0c534ea33ec8 100644 --- a/src/main/java/seedu/address/model/book/exceptions/PersonNotFoundException.java +++ b/src/main/java/seedu/address/model/book/exceptions/BookNotFoundException.java @@ -3,4 +3,4 @@ /** * Signals that the operation is unable to find the specified book. */ -public class PersonNotFoundException extends Exception {} +public class BookNotFoundException extends Exception {} diff --git a/src/main/java/seedu/address/model/book/exceptions/DuplicatePersonException.java b/src/main/java/seedu/address/model/book/exceptions/DuplicateBookException.java similarity index 53% rename from src/main/java/seedu/address/model/book/exceptions/DuplicatePersonException.java rename to src/main/java/seedu/address/model/book/exceptions/DuplicateBookException.java index 8584fcf2aa25..c926dff56092 100644 --- a/src/main/java/seedu/address/model/book/exceptions/DuplicatePersonException.java +++ b/src/main/java/seedu/address/model/book/exceptions/DuplicateBookException.java @@ -5,8 +5,8 @@ /** * Signals that the operation will result in duplicate Book objects. */ -public class DuplicatePersonException extends DuplicateDataException { - public DuplicatePersonException() { - super("Operation would result in duplicate persons"); +public class DuplicateBookException extends DuplicateDataException { + public DuplicateBookException() { + super("Operation would result in duplicate books"); } } diff --git a/src/main/java/seedu/address/model/util/SampleDataUtil.java b/src/main/java/seedu/address/model/util/SampleDataUtil.java index cb785d22a821..0fa43da5c234 100644 --- a/src/main/java/seedu/address/model/util/SampleDataUtil.java +++ b/src/main/java/seedu/address/model/util/SampleDataUtil.java @@ -10,14 +10,14 @@ import seedu.address.model.book.Email; import seedu.address.model.book.Name; import seedu.address.model.book.Phone; -import seedu.address.model.book.exceptions.DuplicatePersonException; +import seedu.address.model.book.exceptions.DuplicateBookException; import seedu.address.model.tag.Tag; /** * Contains utility methods for populating {@code Catalogue} with sample data. */ public class SampleDataUtil { - public static Book[] getSamplePersons() { + public static Book[] getSampleBooks() { return new Book[] { new Book(new Name("Alex Yeoh"), new Phone("87438807"), new Email("alexyeoh@example.com"), new Address("Blk 30 Geylang Street 29, #06-40"), @@ -43,12 +43,12 @@ public static Book[] getSamplePersons() { public static ReadOnlyCatalogue getSampleCatalogue() { try { Catalogue sampleAb = new Catalogue(); - for (Book sampleBook : getSamplePersons()) { - sampleAb.addPerson(sampleBook); + for (Book sampleBook : getSampleBooks()) { + sampleAb.addBook(sampleBook); } return sampleAb; - } catch (DuplicatePersonException e) { - throw new AssertionError("sample data cannot contain duplicate persons", e); + } catch (DuplicateBookException e) { + throw new AssertionError("sample data cannot contain duplicate books", e); } } diff --git a/src/main/java/seedu/address/storage/XmlAdaptedPerson.java b/src/main/java/seedu/address/storage/XmlAdaptedBook.java similarity index 79% rename from src/main/java/seedu/address/storage/XmlAdaptedPerson.java rename to src/main/java/seedu/address/storage/XmlAdaptedBook.java index 63b5537ad14f..97d0cf3e787e 100644 --- a/src/main/java/seedu/address/storage/XmlAdaptedPerson.java +++ b/src/main/java/seedu/address/storage/XmlAdaptedBook.java @@ -19,7 +19,7 @@ /** * JAXB-friendly version of the Book. */ -public class XmlAdaptedPerson { +public class XmlAdaptedBook { public static final String MISSING_FIELD_MESSAGE_FORMAT = "Book's %s field is missing!"; @@ -36,15 +36,15 @@ public class XmlAdaptedPerson { private List tagged = new ArrayList<>(); /** - * Constructs an XmlAdaptedPerson. + * Constructs an XmlAdaptedBook. * This is the no-arg constructor that is required by JAXB. */ - public XmlAdaptedPerson() {} + public XmlAdaptedBook() {} /** - * Constructs an {@code XmlAdaptedPerson} with the given book details. + * Constructs an {@code XmlAdaptedBook} with the given book details. */ - public XmlAdaptedPerson(String name, String phone, String email, String address, List tagged) { + public XmlAdaptedBook(String name, String phone, String email, String address, List tagged) { this.name = name; this.phone = phone; this.email = email; @@ -57,9 +57,9 @@ public XmlAdaptedPerson(String name, String phone, String email, String address, /** * Converts a given Book into this class for JAXB use. * - * @param source future changes to this will not affect the created XmlAdaptedPerson + * @param source future changes to this will not affect the created XmlAdaptedBook */ - public XmlAdaptedPerson(Book source) { + public XmlAdaptedBook(Book source) { name = source.getName().fullName; phone = source.getPhone().value; email = source.getEmail().value; @@ -76,9 +76,9 @@ public XmlAdaptedPerson(Book source) { * @throws IllegalValueException if there were any data constraints violated in the adapted book */ public Book toModelType() throws IllegalValueException { - final List personTags = new ArrayList<>(); + final List bookTags = new ArrayList<>(); for (XmlAdaptedTag tag : tagged) { - personTags.add(tag.toModelType()); + bookTags.add(tag.toModelType()); } if (this.name == null) { @@ -113,7 +113,7 @@ public Book toModelType() throws IllegalValueException { } final Address address = new Address(this.address); - final Set tags = new HashSet<>(personTags); + final Set tags = new HashSet<>(bookTags); return new Book(name, phone, email, address, tags); } @@ -123,15 +123,15 @@ public boolean equals(Object other) { return true; } - if (!(other instanceof XmlAdaptedPerson)) { + if (!(other instanceof XmlAdaptedBook)) { return false; } - XmlAdaptedPerson otherPerson = (XmlAdaptedPerson) other; - return Objects.equals(name, otherPerson.name) - && Objects.equals(phone, otherPerson.phone) - && Objects.equals(email, otherPerson.email) - && Objects.equals(address, otherPerson.address) - && tagged.equals(otherPerson.tagged); + XmlAdaptedBook otherBook = (XmlAdaptedBook) other; + return Objects.equals(name, otherBook.name) + && Objects.equals(phone, otherBook.phone) + && Objects.equals(email, otherBook.email) + && Objects.equals(address, otherBook.address) + && tagged.equals(otherBook.tagged); } } diff --git a/src/main/java/seedu/address/storage/XmlSerializableCatalogue.java b/src/main/java/seedu/address/storage/XmlSerializableCatalogue.java index 11b7c8c91b90..42782918a8eb 100644 --- a/src/main/java/seedu/address/storage/XmlSerializableCatalogue.java +++ b/src/main/java/seedu/address/storage/XmlSerializableCatalogue.java @@ -18,7 +18,7 @@ public class XmlSerializableCatalogue { @XmlElement - private List persons; + private List books; @XmlElement private List tags; @@ -27,7 +27,7 @@ public class XmlSerializableCatalogue { * This empty constructor is required for marshalling. */ public XmlSerializableCatalogue() { - persons = new ArrayList<>(); + books = new ArrayList<>(); tags = new ArrayList<>(); } @@ -36,7 +36,7 @@ public XmlSerializableCatalogue() { */ public XmlSerializableCatalogue(ReadOnlyCatalogue src) { this(); - persons.addAll(src.getPersonList().stream().map(XmlAdaptedPerson::new).collect(Collectors.toList())); + books.addAll(src.getBookList().stream().map(XmlAdaptedBook::new).collect(Collectors.toList())); tags.addAll(src.getTagList().stream().map(XmlAdaptedTag::new).collect(Collectors.toList())); } @@ -44,15 +44,15 @@ public XmlSerializableCatalogue(ReadOnlyCatalogue src) { * Converts this catalogue into the model's {@code Catalogue} object. * * @throws IllegalValueException if there were any data constraints violated or duplicates in the - * {@code XmlAdaptedPerson} or {@code XmlAdaptedTag}. + * {@code XmlAdaptedBook} or {@code XmlAdaptedTag}. */ public Catalogue toModelType() throws IllegalValueException { Catalogue catalogue = new Catalogue(); for (XmlAdaptedTag t : tags) { catalogue.addTag(t.toModelType()); } - for (XmlAdaptedPerson p : persons) { - catalogue.addPerson(p.toModelType()); + for (XmlAdaptedBook p : books) { + catalogue.addBook(p.toModelType()); } return catalogue; } @@ -68,6 +68,6 @@ public boolean equals(Object other) { } XmlSerializableCatalogue otherAb = (XmlSerializableCatalogue) other; - return persons.equals(otherAb.persons) && tags.equals(otherAb.tags); + return books.equals(otherAb.books) && tags.equals(otherAb.tags); } } diff --git a/src/main/java/seedu/address/ui/PersonCard.java b/src/main/java/seedu/address/ui/BookCard.java similarity index 86% rename from src/main/java/seedu/address/ui/PersonCard.java rename to src/main/java/seedu/address/ui/BookCard.java index 3f4d95baf570..366a2d5ec7b9 100644 --- a/src/main/java/seedu/address/ui/PersonCard.java +++ b/src/main/java/seedu/address/ui/BookCard.java @@ -10,9 +10,9 @@ /** * An UI component that displays information of a {@code Book}. */ -public class PersonCard extends UiPart { +public class BookCard extends UiPart { - private static final String FXML = "PersonListCard.fxml"; + private static final String FXML = "BookListCard.fxml"; /** * Note: Certain keywords such as "location" and "resources" are reserved keywords in JavaFX. @@ -39,7 +39,7 @@ public class PersonCard extends UiPart { @FXML private FlowPane tags; - public PersonCard(Book book, int displayedIndex) { + public BookCard(Book book, int displayedIndex) { super(FXML); this.book = book; id.setText(displayedIndex + ". "); @@ -58,12 +58,12 @@ public boolean equals(Object other) { } // instanceof handles nulls - if (!(other instanceof PersonCard)) { + if (!(other instanceof BookCard)) { return false; } // state check - PersonCard card = (PersonCard) other; + BookCard card = (BookCard) other; return id.getText().equals(card.id.getText()) && book.equals(card.book); } diff --git a/src/main/java/seedu/address/ui/PersonListPanel.java b/src/main/java/seedu/address/ui/BookListPanel.java similarity index 54% rename from src/main/java/seedu/address/ui/PersonListPanel.java rename to src/main/java/seedu/address/ui/BookListPanel.java index 7f5fc87c9401..a619f6ed8bd8 100644 --- a/src/main/java/seedu/address/ui/PersonListPanel.java +++ b/src/main/java/seedu/address/ui/BookListPanel.java @@ -14,50 +14,50 @@ import javafx.scene.layout.Region; import seedu.address.commons.core.LogsCenter; import seedu.address.commons.events.ui.JumpToListRequestEvent; -import seedu.address.commons.events.ui.PersonPanelSelectionChangedEvent; +import seedu.address.commons.events.ui.BookPanelSelectionChangedEvent; import seedu.address.model.book.Book; /** - * Panel containing the list of persons. + * Panel containing the list of books. */ -public class PersonListPanel extends UiPart { - private static final String FXML = "PersonListPanel.fxml"; - private final Logger logger = LogsCenter.getLogger(PersonListPanel.class); +public class BookListPanel extends UiPart { + private static final String FXML = "BookListPanel.fxml"; + private final Logger logger = LogsCenter.getLogger(BookListPanel.class); @FXML - private ListView personListView; + private ListView bookListView; - public PersonListPanel(ObservableList bookList) { + public BookListPanel(ObservableList bookList) { super(FXML); setConnections(bookList); registerAsAnEventHandler(this); } private void setConnections(ObservableList bookList) { - ObservableList mappedList = EasyBind.map( - bookList, (person) -> new PersonCard(person, bookList.indexOf(person) + 1)); - personListView.setItems(mappedList); - personListView.setCellFactory(listView -> new PersonListViewCell()); + ObservableList mappedList = EasyBind.map( + bookList, (book) -> new BookCard(book, bookList.indexOf(book) + 1)); + bookListView.setItems(mappedList); + bookListView.setCellFactory(listView -> new BookListViewCell()); setEventHandlerForSelectionChangeEvent(); } private void setEventHandlerForSelectionChangeEvent() { - personListView.getSelectionModel().selectedItemProperty() + bookListView.getSelectionModel().selectedItemProperty() .addListener((observable, oldValue, newValue) -> { if (newValue != null) { logger.fine("Selection in book list panel changed to : '" + newValue + "'"); - raise(new PersonPanelSelectionChangedEvent(newValue)); + raise(new BookPanelSelectionChangedEvent(newValue)); } }); } /** - * Scrolls to the {@code PersonCard} at the {@code index} and selects it. + * Scrolls to the {@code BookCard} at the {@code index} and selects it. */ private void scrollTo(int index) { Platform.runLater(() -> { - personListView.scrollTo(index); - personListView.getSelectionModel().clearAndSelect(index); + bookListView.scrollTo(index); + bookListView.getSelectionModel().clearAndSelect(index); }); } @@ -68,19 +68,19 @@ private void handleJumpToListRequestEvent(JumpToListRequestEvent event) { } /** - * Custom {@code ListCell} that displays the graphics of a {@code PersonCard}. + * Custom {@code ListCell} that displays the graphics of a {@code BookCard}. */ - class PersonListViewCell extends ListCell { + class BookListViewCell extends ListCell { @Override - protected void updateItem(PersonCard person, boolean empty) { - super.updateItem(person, empty); + protected void updateItem(BookCard book, boolean empty) { + super.updateItem(book, empty); - if (empty || person == null) { + if (empty || book == null) { setGraphic(null); setText(null); } else { - setGraphic(person.getRoot()); + setGraphic(book.getRoot()); } } } diff --git a/src/main/java/seedu/address/ui/BrowserPanel.java b/src/main/java/seedu/address/ui/BrowserPanel.java index cd6e7a351539..28a32df496dd 100644 --- a/src/main/java/seedu/address/ui/BrowserPanel.java +++ b/src/main/java/seedu/address/ui/BrowserPanel.java @@ -12,7 +12,7 @@ import javafx.scene.web.WebView; import seedu.address.MainApp; import seedu.address.commons.core.LogsCenter; -import seedu.address.commons.events.ui.PersonPanelSelectionChangedEvent; +import seedu.address.commons.events.ui.BookPanelSelectionChangedEvent; import seedu.address.model.book.Book; /** @@ -41,7 +41,7 @@ public BrowserPanel() { registerAsAnEventHandler(this); } - private void loadPersonPage(Book book) { + private void loadBookPage(Book book) { loadPage(SEARCH_PAGE_URL + book.getName().fullName); } @@ -65,8 +65,8 @@ public void freeResources() { } @Subscribe - private void handlePersonPanelSelectionChangedEvent(PersonPanelSelectionChangedEvent event) { + private void handleBookPanelSelectionChangedEvent(BookPanelSelectionChangedEvent event) { logger.info(LogsCenter.getEventHandlingLogMessage(event)); - loadPersonPage(event.getNewSelection().book); + loadBookPage(event.getNewSelection().book); } } diff --git a/src/main/java/seedu/address/ui/MainWindow.java b/src/main/java/seedu/address/ui/MainWindow.java index 213985f026a1..c14593788df3 100644 --- a/src/main/java/seedu/address/ui/MainWindow.java +++ b/src/main/java/seedu/address/ui/MainWindow.java @@ -35,7 +35,7 @@ public class MainWindow extends UiPart { // Independent Ui parts residing in this Ui container private BrowserPanel browserPanel; - private PersonListPanel personListPanel; + private BookListPanel bookListPanel; private Config config; private UserPrefs prefs; @@ -49,7 +49,7 @@ public class MainWindow extends UiPart { private MenuItem helpMenuItem; @FXML - private StackPane personListPanelPlaceholder; + private StackPane bookListPanelPlaceholder; @FXML private StackPane resultDisplayPlaceholder; @@ -119,8 +119,8 @@ void fillInnerParts() { browserPanel = new BrowserPanel(); browserPlaceholder.getChildren().add(browserPanel.getRoot()); - personListPanel = new PersonListPanel(logic.getFilteredPersonList()); - personListPanelPlaceholder.getChildren().add(personListPanel.getRoot()); + bookListPanel = new BookListPanel(logic.getFilteredBookList()); + bookListPanelPlaceholder.getChildren().add(bookListPanel.getRoot()); ResultDisplay resultDisplay = new ResultDisplay(); resultDisplayPlaceholder.getChildren().add(resultDisplay.getRoot()); @@ -181,8 +181,8 @@ private void handleExit() { raise(new ExitAppRequestEvent()); } - public PersonListPanel getPersonListPanel() { - return this.personListPanel; + public BookListPanel getBookListPanel() { + return this.bookListPanel; } void releaseResources() { diff --git a/src/main/resources/view/PersonListCard.fxml b/src/main/resources/view/BookListCard.fxml similarity index 100% rename from src/main/resources/view/PersonListCard.fxml rename to src/main/resources/view/BookListCard.fxml diff --git a/src/main/resources/view/PersonListPanel.fxml b/src/main/resources/view/BookListPanel.fxml similarity index 77% rename from src/main/resources/view/PersonListPanel.fxml rename to src/main/resources/view/BookListPanel.fxml index 8836d323cc5d..42531ffd928f 100644 --- a/src/main/resources/view/PersonListPanel.fxml +++ b/src/main/resources/view/BookListPanel.fxml @@ -4,5 +4,5 @@ - + diff --git a/src/main/resources/view/DarkTheme.css b/src/main/resources/view/DarkTheme.css index d06336391cca..ac6b73f742d4 100644 --- a/src/main/resources/view/DarkTheme.css +++ b/src/main/resources/view/DarkTheme.css @@ -327,7 +327,7 @@ -fx-text-fill: white; } -#filterField, #personListPanel, #personWebpage { +#filterField, #bookListPanel, #bookWebpage { -fx-effect: innershadow(gaussian, black, 10, 0, 0, 0); } diff --git a/src/main/resources/view/MainWindow.fxml b/src/main/resources/view/MainWindow.fxml index 35ac5f11784d..c726246c7ca9 100644 --- a/src/main/resources/view/MainWindow.fxml +++ b/src/main/resources/view/MainWindow.fxml @@ -51,7 +51,7 @@ - + diff --git a/src/test/data/XmlAddressBookStorageTest/NotXmlFormatAddressBook.xml b/src/test/data/XmlCatalogueStorageTest/NotXmlFormatCatalogue.xml similarity index 100% rename from src/test/data/XmlAddressBookStorageTest/NotXmlFormatAddressBook.xml rename to src/test/data/XmlCatalogueStorageTest/NotXmlFormatCatalogue.xml diff --git a/src/test/data/XmlAddressBookStorageTest/invalidAndValidPersonAddressBook.xml b/src/test/data/XmlCatalogueStorageTest/invalidAndValidBookCatalogue.xml similarity index 100% rename from src/test/data/XmlAddressBookStorageTest/invalidAndValidPersonAddressBook.xml rename to src/test/data/XmlCatalogueStorageTest/invalidAndValidBookCatalogue.xml diff --git a/src/test/data/XmlAddressBookStorageTest/invalidPersonAddressBook.xml b/src/test/data/XmlCatalogueStorageTest/invalidBookCatalogue.xml similarity index 100% rename from src/test/data/XmlAddressBookStorageTest/invalidPersonAddressBook.xml rename to src/test/data/XmlCatalogueStorageTest/invalidBookCatalogue.xml diff --git a/src/test/data/XmlSerializableAddressBookTest/invalidPersonAddressBook.xml b/src/test/data/XmlSerializableCatalogueTest/invalidBookCatalogue.xml similarity index 100% rename from src/test/data/XmlSerializableAddressBookTest/invalidPersonAddressBook.xml rename to src/test/data/XmlSerializableCatalogueTest/invalidBookCatalogue.xml diff --git a/src/test/data/XmlSerializableAddressBookTest/invalidTagAddressBook.xml b/src/test/data/XmlSerializableCatalogueTest/invalidTagCatalogue.xml similarity index 100% rename from src/test/data/XmlSerializableAddressBookTest/invalidTagAddressBook.xml rename to src/test/data/XmlSerializableCatalogueTest/invalidTagCatalogue.xml diff --git a/src/test/data/XmlSerializableAddressBookTest/typicalPersonsAddressBook.xml b/src/test/data/XmlSerializableCatalogueTest/typicalBooksCatalogue.xml similarity index 96% rename from src/test/data/XmlSerializableAddressBookTest/typicalPersonsAddressBook.xml rename to src/test/data/XmlSerializableCatalogueTest/typicalBooksCatalogue.xml index eaa9c0db738d..ca8f4641e8b6 100644 --- a/src/test/data/XmlSerializableAddressBookTest/typicalPersonsAddressBook.xml +++ b/src/test/data/XmlSerializableCatalogueTest/typicalBooksCatalogue.xml @@ -1,6 +1,6 @@ +{@code TypicalBooks#getTypicalCatalogue()}--> Alice Pauline diff --git a/src/test/data/XmlUtilTest/invalidPersonField.xml b/src/test/data/XmlUtilTest/invalidBookField.xml similarity index 100% rename from src/test/data/XmlUtilTest/invalidPersonField.xml rename to src/test/data/XmlUtilTest/invalidBookField.xml diff --git a/src/test/data/XmlUtilTest/missingPersonField.xml b/src/test/data/XmlUtilTest/missingBookField.xml similarity index 100% rename from src/test/data/XmlUtilTest/missingPersonField.xml rename to src/test/data/XmlUtilTest/missingBookField.xml diff --git a/src/test/data/XmlUtilTest/tempAddressBook.xml b/src/test/data/XmlUtilTest/tempCatalogue.xml similarity index 100% rename from src/test/data/XmlUtilTest/tempAddressBook.xml rename to src/test/data/XmlUtilTest/tempCatalogue.xml diff --git a/src/test/data/XmlUtilTest/validPerson.xml b/src/test/data/XmlUtilTest/validBook.xml similarity index 100% rename from src/test/data/XmlUtilTest/validPerson.xml rename to src/test/data/XmlUtilTest/validBook.xml diff --git a/src/test/data/XmlUtilTest/validAddressBook.xml b/src/test/data/XmlUtilTest/validCatalogue.xml similarity index 100% rename from src/test/data/XmlUtilTest/validAddressBook.xml rename to src/test/data/XmlUtilTest/validCatalogue.xml diff --git a/src/test/java/guitests/guihandles/PersonCardHandle.java b/src/test/java/guitests/guihandles/BookCardHandle.java similarity index 95% rename from src/test/java/guitests/guihandles/PersonCardHandle.java rename to src/test/java/guitests/guihandles/BookCardHandle.java index c438cf0c3b09..cef381307846 100644 --- a/src/test/java/guitests/guihandles/PersonCardHandle.java +++ b/src/test/java/guitests/guihandles/BookCardHandle.java @@ -10,7 +10,7 @@ /** * Provides a handle to a book card in the book list panel. */ -public class PersonCardHandle extends NodeHandle { +public class BookCardHandle extends NodeHandle { private static final String ID_FIELD_ID = "#id"; private static final String NAME_FIELD_ID = "#name"; private static final String ADDRESS_FIELD_ID = "#address"; @@ -25,7 +25,7 @@ public class PersonCardHandle extends NodeHandle { private final Label emailLabel; private final List - Hans Muster + Hans Muster 948asdf2424 hans@example.com
4th street
diff --git a/src/test/data/XmlCatalogueStorageTest/invalidBookCatalogue.xml b/src/test/data/XmlCatalogueStorageTest/invalidBookCatalogue.xml index 936d32b8c7d2..b4d0e8738adb 100644 --- a/src/test/data/XmlCatalogueStorageTest/invalidBookCatalogue.xml +++ b/src/test/data/XmlCatalogueStorageTest/invalidBookCatalogue.xml @@ -1,8 +1,8 @@ - + - Ha!ns Mu@ster + Ha!ns Mu@ster 9482424 hans@example.com
4th street
diff --git a/src/test/data/XmlSerializableCatalogueTest/invalidBookCatalogue.xml b/src/test/data/XmlSerializableCatalogueTest/invalidBookCatalogue.xml index 0c06d8c81358..1d18c8b63982 100644 --- a/src/test/data/XmlSerializableCatalogueTest/invalidBookCatalogue.xml +++ b/src/test/data/XmlSerializableCatalogueTest/invalidBookCatalogue.xml @@ -2,7 +2,7 @@ - Hans Muster + Hans Muster 9482424 hans@exam!32ple
4th street
diff --git a/src/test/data/XmlSerializableCatalogueTest/typicalBooksCatalogue.xml b/src/test/data/XmlSerializableCatalogueTest/typicalBooksCatalogue.xml index ca8f4641e8b6..84e134b4dd9d 100644 --- a/src/test/data/XmlSerializableCatalogueTest/typicalBooksCatalogue.xml +++ b/src/test/data/XmlSerializableCatalogueTest/typicalBooksCatalogue.xml @@ -3,14 +3,14 @@ {@code TypicalBooks#getTypicalCatalogue()}--> - Alice Pauline + Alice Pauline 85355255 alice@example.com
123, Jurong West Ave 6, #08-111
friends
- Benson Meier + Benson Meier 98765432 johnd@example.com
311, Clementi Ave 2, #02-25
@@ -18,31 +18,31 @@ friends
- Carl Kurz + Carl Kurz 95352563 heinz@example.com
wall street
- Daniel Meier + Daniel Meier 87652533 cornelia@example.com
10th street
- Elle Meyer + Elle Meyer 9482224 werner@example.com
michegan ave
- Fiona Kunz + Fiona Kunz 9482427 lydia@example.com
little tokyo
- George Best + George Best 9482442 anna@example.com
4th street
diff --git a/src/test/data/XmlUtilTest/invalidBookField.xml b/src/test/data/XmlUtilTest/invalidBookField.xml index 723141fa8da7..dbedf7587310 100644 --- a/src/test/data/XmlUtilTest/invalidBookField.xml +++ b/src/test/data/XmlUtilTest/invalidBookField.xml @@ -1,7 +1,7 @@ - Hans Muster + Hans Muster 9482asf424 hans@example
4th street
diff --git a/src/test/data/XmlUtilTest/missingBookField.xml b/src/test/data/XmlUtilTest/missingBookField.xml index 8e9b9ea719e1..df6120e75105 100644 --- a/src/test/data/XmlUtilTest/missingBookField.xml +++ b/src/test/data/XmlUtilTest/missingBookField.xml @@ -1,5 +1,5 @@ - + 9482424 hans@example diff --git a/src/test/data/XmlUtilTest/validBook.xml b/src/test/data/XmlUtilTest/validBook.xml index d55d3e91811d..1c279963cc0e 100644 --- a/src/test/data/XmlUtilTest/validBook.xml +++ b/src/test/data/XmlUtilTest/validBook.xml @@ -1,6 +1,6 @@ - Hans Muster + Hans Muster 9482424 hans@example
4th street
diff --git a/src/test/data/XmlUtilTest/validCatalogue.xml b/src/test/data/XmlUtilTest/validCatalogue.xml index 5ac4a9bd0af6..7a9e04d3198e 100644 --- a/src/test/data/XmlUtilTest/validCatalogue.xml +++ b/src/test/data/XmlUtilTest/validCatalogue.xml @@ -1,55 +1,55 @@ - Hans Muster + Hans Muster 9482424 hans@example.com
4th street
- Ruth Mueller + Ruth Mueller 87249245 ruth@example.com
81th street
- Heinz Kurz + Heinz Kurz 95352563 heinz@example.com
wall street
- Cornelia Meier + Cornelia Meier 87652533 cornelia@example.com
10th street
- Werner Meyer + Werner Meyer 9482224 werner@example.com
michegan ave
- Lydia Kunz + Lydia Kunz 9482427 lydia@example.com
little tokyo
- Anna Best + Anna Best 9482442 anna@example.com
4th street
- Stefan Meier + Stefan Meier 8482424 stefan@example.com
little india
- Martin Mueller + Martin Mueller 8482131 hans@example.com
chicago ave
diff --git a/src/test/java/guitests/guihandles/BookCardHandle.java b/src/test/java/guitests/guihandles/BookCardHandle.java index cef381307846..83e33932f10e 100644 --- a/src/test/java/guitests/guihandles/BookCardHandle.java +++ b/src/test/java/guitests/guihandles/BookCardHandle.java @@ -12,14 +12,14 @@ */ public class BookCardHandle extends NodeHandle { private static final String ID_FIELD_ID = "#id"; - private static final String NAME_FIELD_ID = "#name"; + private static final String TITLE_FIELD_ID = "#title"; private static final String ADDRESS_FIELD_ID = "#address"; private static final String PHONE_FIELD_ID = "#phone"; private static final String EMAIL_FIELD_ID = "#email"; private static final String TAGS_FIELD_ID = "#tags"; private final Label idLabel; - private final Label nameLabel; + private final Label titleLabel; private final Label addressLabel; private final Label phoneLabel; private final Label emailLabel; @@ -29,7 +29,7 @@ public BookCardHandle(Node cardNode) { super(cardNode); this.idLabel = getChildNode(ID_FIELD_ID); - this.nameLabel = getChildNode(NAME_FIELD_ID); + this.titleLabel = getChildNode(TITLE_FIELD_ID); this.addressLabel = getChildNode(ADDRESS_FIELD_ID); this.phoneLabel = getChildNode(PHONE_FIELD_ID); this.emailLabel = getChildNode(EMAIL_FIELD_ID); @@ -47,7 +47,7 @@ public String getId() { } public String getName() { - return nameLabel.getText(); + return titleLabel.getText(); } public String getAddress() { diff --git a/src/test/java/seedu/address/TestApp.java b/src/test/java/seedu/address/TestApp.java index 468d69940399..813d4d476e69 100644 --- a/src/test/java/seedu/address/TestApp.java +++ b/src/test/java/seedu/address/TestApp.java @@ -66,7 +66,7 @@ protected UserPrefs initPrefs(UserPrefsStorage storage) { double y = Screen.getPrimary().getVisualBounds().getMinY(); userPrefs.updateLastUsedGuiSetting(new GuiSettings(600.0, 600.0, (int) x, (int) y)); userPrefs.setCatalogueFilePath(saveFileLocation); - userPrefs.setCatalogueBookName(CATALOGUE_NAME); + userPrefs.setCatalogueBookTitle(CATALOGUE_NAME); return userPrefs; } diff --git a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java index cb68253cfa66..6b8b8a75da3b 100644 --- a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java +++ b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java @@ -5,7 +5,7 @@ import static org.junit.Assert.fail; 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_NAME; +import static seedu.address.logic.parser.CliSyntax.PREFIX_TITLE; import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; @@ -20,7 +20,7 @@ import seedu.address.model.Catalogue; import seedu.address.model.Model; import seedu.address.model.book.Book; -import seedu.address.model.book.NameContainsKeywordsPredicate; +import seedu.address.model.book.TitleContainsKeywordsPredicate; import seedu.address.model.book.exceptions.BookNotFoundException; import seedu.address.testutil.EditBookDescriptorBuilder; @@ -29,8 +29,8 @@ */ public class CommandTestUtil { - public static final String VALID_NAME_AMY = "Amy Bee"; - public static final String VALID_NAME_BOB = "Bob Choo"; + public static final String VALID_TITLE_AMY = "Amy Bee"; + public static final String VALID_TITLE_BOB = "Bob Choo"; public static final String VALID_PHONE_AMY = "11111111"; public static final String VALID_PHONE_BOB = "22222222"; public static final String VALID_EMAIL_AMY = "amy@example.com"; @@ -40,8 +40,8 @@ public class CommandTestUtil { public static final String VALID_TAG_HUSBAND = "husband"; public static final String VALID_TAG_FRIEND = "friend"; - public static final String NAME_DESC_AMY = " " + PREFIX_NAME + VALID_NAME_AMY; - public static final String NAME_DESC_BOB = " " + PREFIX_NAME + VALID_NAME_BOB; + public static final String TITLE_DESC_AMY = " " + PREFIX_TITLE + VALID_TITLE_AMY; + public static final String TITLE_DESC_BOB = " " + PREFIX_TITLE + VALID_TITLE_BOB; public static final String PHONE_DESC_AMY = " " + PREFIX_PHONE + VALID_PHONE_AMY; public static final String PHONE_DESC_BOB = " " + PREFIX_PHONE + VALID_PHONE_BOB; public static final String EMAIL_DESC_AMY = " " + PREFIX_EMAIL + VALID_EMAIL_AMY; @@ -51,7 +51,7 @@ public class CommandTestUtil { public static final String TAG_DESC_FRIEND = " " + PREFIX_TAG + VALID_TAG_FRIEND; public static final String TAG_DESC_HUSBAND = " " + PREFIX_TAG + VALID_TAG_HUSBAND; - public static final String INVALID_NAME_DESC = " " + PREFIX_NAME + "James&"; // '&' not allowed in names + public static final String INVALID_TITLE_DESC = " " + PREFIX_TITLE + "James&"; // '&' not allowed in titles public static final String INVALID_PHONE_DESC = " " + PREFIX_PHONE + "911a"; // 'a' not allowed in phones public static final String INVALID_EMAIL_DESC = " " + PREFIX_EMAIL + "bob!yahoo"; // missing '@' symbol public static final String INVALID_ADDRESS_DESC = " " + PREFIX_ADDRESS; // empty string not allowed for addresses @@ -64,10 +64,10 @@ public class CommandTestUtil { public static final EditCommand.EditBookDescriptor DESC_BOB; static { - DESC_AMY = new EditBookDescriptorBuilder().withName(VALID_NAME_AMY) + DESC_AMY = new EditBookDescriptorBuilder().withName(VALID_TITLE_AMY) .withPhone(VALID_PHONE_AMY).withEmail(VALID_EMAIL_AMY).withAddress(VALID_ADDRESS_AMY) .withTags(VALID_TAG_FRIEND).build(); - DESC_BOB = new EditBookDescriptorBuilder().withName(VALID_NAME_BOB) + DESC_BOB = new EditBookDescriptorBuilder().withName(VALID_TITLE_BOB) .withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB) .withTags(VALID_TAG_HUSBAND, VALID_TAG_FRIEND).build(); } @@ -118,8 +118,8 @@ public static void showBookAtIndex(Model model, Index targetIndex) { assertTrue(targetIndex.getZeroBased() < model.getFilteredBookList().size()); Book book = model.getFilteredBookList().get(targetIndex.getZeroBased()); - final String[] splitName = book.getName().fullName.split("\\s+"); - model.updateFilteredBookList(new NameContainsKeywordsPredicate(Arrays.asList(splitName[0]))); + final String[] splitName = book.getTitle().fullTitle.split("\\s+"); + model.updateFilteredBookList(new TitleContainsKeywordsPredicate(Arrays.asList(splitName[0]))); assertEquals(1, model.getFilteredBookList().size()); } diff --git a/src/test/java/seedu/address/logic/commands/EditBookDescriptorTest.java b/src/test/java/seedu/address/logic/commands/EditBookDescriptorTest.java index f6820e178d0b..878352157948 100644 --- a/src/test/java/seedu/address/logic/commands/EditBookDescriptorTest.java +++ b/src/test/java/seedu/address/logic/commands/EditBookDescriptorTest.java @@ -6,7 +6,7 @@ import static seedu.address.logic.commands.CommandTestUtil.DESC_BOB; import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB; import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB; +import static seedu.address.logic.commands.CommandTestUtil.VALID_TITLE_BOB; import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB; import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND; @@ -36,7 +36,7 @@ public void equals() { assertFalse(DESC_AMY.equals(DESC_BOB)); // different name -> returns false - EditBookDescriptor editedAmy = new EditBookDescriptorBuilder(DESC_AMY).withName(VALID_NAME_BOB).build(); + EditBookDescriptor editedAmy = new EditBookDescriptorBuilder(DESC_AMY).withName(VALID_TITLE_BOB).build(); assertFalse(DESC_AMY.equals(editedAmy)); // different phone -> returns false diff --git a/src/test/java/seedu/address/logic/commands/EditCommandTest.java b/src/test/java/seedu/address/logic/commands/EditCommandTest.java index f1115d0af4fd..83c0a48e67cb 100644 --- a/src/test/java/seedu/address/logic/commands/EditCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/EditCommandTest.java @@ -5,7 +5,7 @@ import static org.junit.Assert.assertTrue; import static seedu.address.logic.commands.CommandTestUtil.DESC_AMY; import static seedu.address.logic.commands.CommandTestUtil.DESC_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB; +import static seedu.address.logic.commands.CommandTestUtil.VALID_TITLE_BOB; import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB; import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND; import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure; @@ -59,10 +59,10 @@ public void execute_someFieldsSpecifiedUnfilteredList_success() throws Exception Book lastBook = model.getFilteredBookList().get(indexLastBook.getZeroBased()); BookBuilder bookInList = new BookBuilder(lastBook); - Book editedBook = bookInList.withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB) + Book editedBook = bookInList.withName(VALID_TITLE_BOB).withPhone(VALID_PHONE_BOB) .withTags(VALID_TAG_HUSBAND).build(); - EditBookDescriptor descriptor = new EditBookDescriptorBuilder().withName(VALID_NAME_BOB) + EditBookDescriptor descriptor = new EditBookDescriptorBuilder().withName(VALID_TITLE_BOB) .withPhone(VALID_PHONE_BOB).withTags(VALID_TAG_HUSBAND).build(); EditCommand editCommand = prepareCommand(indexLastBook, descriptor); @@ -91,9 +91,9 @@ public void execute_filteredList_success() throws Exception { showBookAtIndex(model, INDEX_FIRST_BOOK); Book bookInFilteredList = model.getFilteredBookList().get(INDEX_FIRST_BOOK.getZeroBased()); - Book editedBook = new BookBuilder(bookInFilteredList).withName(VALID_NAME_BOB).build(); + Book editedBook = new BookBuilder(bookInFilteredList).withName(VALID_TITLE_BOB).build(); EditCommand editCommand = prepareCommand(INDEX_FIRST_BOOK, - new EditBookDescriptorBuilder().withName(VALID_NAME_BOB).build()); + new EditBookDescriptorBuilder().withName(VALID_TITLE_BOB).build()); String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_BOOK_SUCCESS, editedBook); @@ -127,7 +127,7 @@ public void execute_duplicateBookFilteredList_failure() { @Test public void execute_invalidBookIndexUnfilteredList_failure() { Index outOfBoundIndex = Index.fromOneBased(model.getFilteredBookList().size() + 1); - EditBookDescriptor descriptor = new EditBookDescriptorBuilder().withName(VALID_NAME_BOB).build(); + EditBookDescriptor descriptor = new EditBookDescriptorBuilder().withName(VALID_TITLE_BOB).build(); EditCommand editCommand = prepareCommand(outOfBoundIndex, descriptor); assertCommandFailure(editCommand, model, Messages.MESSAGE_INVALID_BOOK_DISPLAYED_INDEX); @@ -145,7 +145,7 @@ public void execute_invalidBookIndexFilteredList_failure() { assertTrue(outOfBoundIndex.getZeroBased() < model.getCatalogue().getBookList().size()); EditCommand editCommand = prepareCommand(outOfBoundIndex, - new EditBookDescriptorBuilder().withName(VALID_NAME_BOB).build()); + new EditBookDescriptorBuilder().withName(VALID_TITLE_BOB).build()); assertCommandFailure(editCommand, model, Messages.MESSAGE_INVALID_BOOK_DISPLAYED_INDEX); } @@ -179,7 +179,7 @@ public void executeUndoRedo_invalidIndexUnfilteredList_failure() { UndoCommand undoCommand = prepareUndoCommand(model, undoRedoStack); RedoCommand redoCommand = prepareRedoCommand(model, undoRedoStack); Index outOfBoundIndex = Index.fromOneBased(model.getFilteredBookList().size() + 1); - EditBookDescriptor descriptor = new EditBookDescriptorBuilder().withName(VALID_NAME_BOB).build(); + EditBookDescriptor descriptor = new EditBookDescriptorBuilder().withName(VALID_TITLE_BOB).build(); EditCommand editCommand = prepareCommand(outOfBoundIndex, descriptor); // execution failed -> editCommand not pushed into undoRedoStack diff --git a/src/test/java/seedu/address/logic/commands/FindCommandTest.java b/src/test/java/seedu/address/logic/commands/FindCommandTest.java index 027f3c03fbad..781104dbfb7b 100644 --- a/src/test/java/seedu/address/logic/commands/FindCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/FindCommandTest.java @@ -21,7 +21,7 @@ import seedu.address.model.Model; import seedu.address.model.ModelManager; import seedu.address.model.UserPrefs; -import seedu.address.model.book.NameContainsKeywordsPredicate; +import seedu.address.model.book.TitleContainsKeywordsPredicate; import seedu.address.model.book.Book; /** @@ -32,10 +32,10 @@ public class FindCommandTest { @Test public void equals() { - NameContainsKeywordsPredicate firstPredicate = - new NameContainsKeywordsPredicate(Collections.singletonList("first")); - NameContainsKeywordsPredicate secondPredicate = - new NameContainsKeywordsPredicate(Collections.singletonList("second")); + TitleContainsKeywordsPredicate firstPredicate = + new TitleContainsKeywordsPredicate(Collections.singletonList("first")); + TitleContainsKeywordsPredicate secondPredicate = + new TitleContainsKeywordsPredicate(Collections.singletonList("second")); FindCommand findFirstCommand = new FindCommand(firstPredicate); FindCommand findSecondCommand = new FindCommand(secondPredicate); @@ -76,7 +76,7 @@ public void execute_multipleKeywords_multipleBooksFound() { */ private FindCommand prepareCommand(String userInput) { FindCommand command = - new FindCommand(new NameContainsKeywordsPredicate(Arrays.asList(userInput.split("\\s+")))); + new FindCommand(new TitleContainsKeywordsPredicate(Arrays.asList(userInput.split("\\s+")))); command.setData(model, new CommandHistory(), new UndoRedoStack()); return command; } diff --git a/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java b/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java index 9f31295efb35..31b51396bbf0 100644 --- a/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java @@ -7,11 +7,11 @@ import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_BOB; import static seedu.address.logic.commands.CommandTestUtil.INVALID_ADDRESS_DESC; import static seedu.address.logic.commands.CommandTestUtil.INVALID_EMAIL_DESC; -import static seedu.address.logic.commands.CommandTestUtil.INVALID_NAME_DESC; +import static seedu.address.logic.commands.CommandTestUtil.INVALID_TITLE_DESC; import static seedu.address.logic.commands.CommandTestUtil.INVALID_PHONE_DESC; import static seedu.address.logic.commands.CommandTestUtil.INVALID_TAG_DESC; -import static seedu.address.logic.commands.CommandTestUtil.NAME_DESC_AMY; -import static seedu.address.logic.commands.CommandTestUtil.NAME_DESC_BOB; +import static seedu.address.logic.commands.CommandTestUtil.TITLE_DESC_AMY; +import static seedu.address.logic.commands.CommandTestUtil.TITLE_DESC_BOB; import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_AMY; import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_BOB; import static seedu.address.logic.commands.CommandTestUtil.PREAMBLE_NON_EMPTY; @@ -22,8 +22,8 @@ import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB; import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_AMY; import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_AMY; -import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB; +import static seedu.address.logic.commands.CommandTestUtil.VALID_TITLE_AMY; +import static seedu.address.logic.commands.CommandTestUtil.VALID_TITLE_BOB; import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_AMY; import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB; import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_FRIEND; @@ -37,7 +37,7 @@ import seedu.address.model.book.Address; import seedu.address.model.book.Book; import seedu.address.model.book.Email; -import seedu.address.model.book.Name; +import seedu.address.model.book.Title; import seedu.address.model.book.Phone; import seedu.address.model.tag.Tag; import seedu.address.testutil.BookBuilder; @@ -47,43 +47,43 @@ public class AddCommandParserTest { @Test public void parse_allFieldsPresent_success() { - Book expectedBook = new BookBuilder().withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB) + Book expectedBook = new BookBuilder().withName(VALID_TITLE_BOB).withPhone(VALID_PHONE_BOB) .withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_FRIEND).build(); // whitespace only preamble - assertParseSuccess(parser, PREAMBLE_WHITESPACE + NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + assertParseSuccess(parser, PREAMBLE_WHITESPACE + TITLE_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedBook)); // multiple names - last name accepted - assertParseSuccess(parser, NAME_DESC_AMY + NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + assertParseSuccess(parser, TITLE_DESC_AMY + TITLE_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedBook)); // multiple phones - last phone accepted - assertParseSuccess(parser, NAME_DESC_BOB + PHONE_DESC_AMY + PHONE_DESC_BOB + EMAIL_DESC_BOB + assertParseSuccess(parser, TITLE_DESC_BOB + PHONE_DESC_AMY + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedBook)); // multiple emails - last email accepted - assertParseSuccess(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_AMY + EMAIL_DESC_BOB + assertParseSuccess(parser, TITLE_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_AMY + EMAIL_DESC_BOB + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedBook)); // multiple addresses - last address accepted - assertParseSuccess(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_AMY + assertParseSuccess(parser, TITLE_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_AMY + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedBook)); // multiple tags - all accepted - Book expectedBookMultipleTags = new BookBuilder().withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB) + Book expectedBookMultipleTags = new BookBuilder().withName(VALID_TITLE_BOB).withPhone(VALID_PHONE_BOB) .withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB) .withTags(VALID_TAG_FRIEND, VALID_TAG_HUSBAND).build(); - assertParseSuccess(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB + assertParseSuccess(parser, TITLE_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB + TAG_DESC_HUSBAND + TAG_DESC_FRIEND, new AddCommand(expectedBookMultipleTags)); } @Test public void parse_optionalFieldsMissing_success() { // zero tags - Book expectedBook = new BookBuilder().withName(VALID_NAME_AMY).withPhone(VALID_PHONE_AMY) + Book expectedBook = new BookBuilder().withName(VALID_TITLE_AMY).withPhone(VALID_PHONE_AMY) .withEmail(VALID_EMAIL_AMY).withAddress(VALID_ADDRESS_AMY).withTags().build(); - assertParseSuccess(parser, NAME_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY + ADDRESS_DESC_AMY, + assertParseSuccess(parser, TITLE_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY + ADDRESS_DESC_AMY, new AddCommand(expectedBook)); } @@ -92,54 +92,54 @@ public void parse_compulsoryFieldMissing_failure() { String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE); // missing name prefix - assertParseFailure(parser, VALID_NAME_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB, + assertParseFailure(parser, VALID_TITLE_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB, expectedMessage); // missing phone prefix - assertParseFailure(parser, NAME_DESC_BOB + VALID_PHONE_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB, + assertParseFailure(parser, TITLE_DESC_BOB + VALID_PHONE_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB, expectedMessage); // missing email prefix - assertParseFailure(parser, NAME_DESC_BOB + PHONE_DESC_BOB + VALID_EMAIL_BOB + ADDRESS_DESC_BOB, + assertParseFailure(parser, TITLE_DESC_BOB + PHONE_DESC_BOB + VALID_EMAIL_BOB + ADDRESS_DESC_BOB, expectedMessage); // missing address prefix - assertParseFailure(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + VALID_ADDRESS_BOB, + assertParseFailure(parser, TITLE_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + VALID_ADDRESS_BOB, expectedMessage); // all prefixes missing - assertParseFailure(parser, VALID_NAME_BOB + VALID_PHONE_BOB + VALID_EMAIL_BOB + VALID_ADDRESS_BOB, + assertParseFailure(parser, VALID_TITLE_BOB + VALID_PHONE_BOB + VALID_EMAIL_BOB + VALID_ADDRESS_BOB, expectedMessage); } @Test public void parse_invalidValue_failure() { // invalid name - assertParseFailure(parser, INVALID_NAME_DESC + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB - + TAG_DESC_HUSBAND + TAG_DESC_FRIEND, Name.MESSAGE_NAME_CONSTRAINTS); + assertParseFailure(parser, INVALID_TITLE_DESC + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB + + TAG_DESC_HUSBAND + TAG_DESC_FRIEND, Title.MESSAGE_TITLE_CONSTRAINTS); // invalid phone - assertParseFailure(parser, NAME_DESC_BOB + INVALID_PHONE_DESC + EMAIL_DESC_BOB + ADDRESS_DESC_BOB + assertParseFailure(parser, TITLE_DESC_BOB + INVALID_PHONE_DESC + EMAIL_DESC_BOB + ADDRESS_DESC_BOB + TAG_DESC_HUSBAND + TAG_DESC_FRIEND, Phone.MESSAGE_PHONE_CONSTRAINTS); // invalid email - assertParseFailure(parser, NAME_DESC_BOB + PHONE_DESC_BOB + INVALID_EMAIL_DESC + ADDRESS_DESC_BOB + assertParseFailure(parser, TITLE_DESC_BOB + PHONE_DESC_BOB + INVALID_EMAIL_DESC + ADDRESS_DESC_BOB + TAG_DESC_HUSBAND + TAG_DESC_FRIEND, Email.MESSAGE_EMAIL_CONSTRAINTS); // invalid address - assertParseFailure(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + INVALID_ADDRESS_DESC + assertParseFailure(parser, TITLE_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + INVALID_ADDRESS_DESC + TAG_DESC_HUSBAND + TAG_DESC_FRIEND, Address.MESSAGE_ADDRESS_CONSTRAINTS); // invalid tag - assertParseFailure(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB + assertParseFailure(parser, TITLE_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB + INVALID_TAG_DESC + VALID_TAG_FRIEND, Tag.MESSAGE_TAG_CONSTRAINTS); // two invalid values, only first invalid value reported - assertParseFailure(parser, INVALID_NAME_DESC + PHONE_DESC_BOB + EMAIL_DESC_BOB + INVALID_ADDRESS_DESC, - Name.MESSAGE_NAME_CONSTRAINTS); + assertParseFailure(parser, INVALID_TITLE_DESC + PHONE_DESC_BOB + EMAIL_DESC_BOB + INVALID_ADDRESS_DESC, + Title.MESSAGE_TITLE_CONSTRAINTS); // non-empty preamble - assertParseFailure(parser, PREAMBLE_NON_EMPTY + NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + assertParseFailure(parser, PREAMBLE_NON_EMPTY + TITLE_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB + TAG_DESC_HUSBAND + TAG_DESC_FRIEND, String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE)); } diff --git a/src/test/java/seedu/address/logic/parser/CatalogueParserTest.java b/src/test/java/seedu/address/logic/parser/CatalogueParserTest.java index c653ac7f9818..9023bf4f5b6b 100644 --- a/src/test/java/seedu/address/logic/parser/CatalogueParserTest.java +++ b/src/test/java/seedu/address/logic/parser/CatalogueParserTest.java @@ -30,7 +30,7 @@ import seedu.address.logic.commands.UndoCommand; import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.book.Book; -import seedu.address.model.book.NameContainsKeywordsPredicate; +import seedu.address.model.book.TitleContainsKeywordsPredicate; import seedu.address.testutil.EditBookDescriptorBuilder; import seedu.address.testutil.BookBuilder; import seedu.address.testutil.BookUtil; @@ -81,7 +81,7 @@ public void parseCommand_find() throws Exception { List keywords = Arrays.asList("foo", "bar", "baz"); FindCommand command = (FindCommand) parser.parseCommand( FindCommand.COMMAND_WORD + " " + keywords.stream().collect(Collectors.joining(" "))); - assertEquals(new FindCommand(new NameContainsKeywordsPredicate(keywords)), command); + assertEquals(new FindCommand(new TitleContainsKeywordsPredicate(keywords)), command); } @Test diff --git a/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java b/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java index b7e3ae88a4c1..d4a31e6ae19b 100644 --- a/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java @@ -7,10 +7,10 @@ import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_BOB; import static seedu.address.logic.commands.CommandTestUtil.INVALID_ADDRESS_DESC; import static seedu.address.logic.commands.CommandTestUtil.INVALID_EMAIL_DESC; -import static seedu.address.logic.commands.CommandTestUtil.INVALID_NAME_DESC; +import static seedu.address.logic.commands.CommandTestUtil.INVALID_TITLE_DESC; import static seedu.address.logic.commands.CommandTestUtil.INVALID_PHONE_DESC; import static seedu.address.logic.commands.CommandTestUtil.INVALID_TAG_DESC; -import static seedu.address.logic.commands.CommandTestUtil.NAME_DESC_AMY; +import static seedu.address.logic.commands.CommandTestUtil.TITLE_DESC_AMY; import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_AMY; import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_BOB; import static seedu.address.logic.commands.CommandTestUtil.TAG_DESC_FRIEND; @@ -19,7 +19,7 @@ import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB; import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_AMY; import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_AMY; +import static seedu.address.logic.commands.CommandTestUtil.VALID_TITLE_AMY; import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_AMY; import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB; import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_FRIEND; @@ -38,7 +38,7 @@ import seedu.address.logic.commands.EditCommand.EditBookDescriptor; import seedu.address.model.book.Address; import seedu.address.model.book.Email; -import seedu.address.model.book.Name; +import seedu.address.model.book.Title; import seedu.address.model.book.Phone; import seedu.address.model.tag.Tag; import seedu.address.testutil.EditBookDescriptorBuilder; @@ -55,7 +55,7 @@ public class EditCommandParserTest { @Test public void parse_missingParts_failure() { // no index specified - assertParseFailure(parser, VALID_NAME_AMY, MESSAGE_INVALID_FORMAT); + assertParseFailure(parser, VALID_TITLE_AMY, MESSAGE_INVALID_FORMAT); // no field specified assertParseFailure(parser, "1", EditCommand.MESSAGE_NOT_EDITED); @@ -67,10 +67,10 @@ public void parse_missingParts_failure() { @Test public void parse_invalidPreamble_failure() { // negative index - assertParseFailure(parser, "-5" + NAME_DESC_AMY, MESSAGE_INVALID_FORMAT); + assertParseFailure(parser, "-5" + TITLE_DESC_AMY, MESSAGE_INVALID_FORMAT); // zero index - assertParseFailure(parser, "0" + NAME_DESC_AMY, MESSAGE_INVALID_FORMAT); + assertParseFailure(parser, "0" + TITLE_DESC_AMY, MESSAGE_INVALID_FORMAT); // invalid arguments being parsed as preamble assertParseFailure(parser, "1 some random string", MESSAGE_INVALID_FORMAT); @@ -81,7 +81,7 @@ public void parse_invalidPreamble_failure() { @Test public void parse_invalidValue_failure() { - assertParseFailure(parser, "1" + INVALID_NAME_DESC, Name.MESSAGE_NAME_CONSTRAINTS); // invalid name + assertParseFailure(parser, "1" + INVALID_TITLE_DESC, Title.MESSAGE_TITLE_CONSTRAINTS); // invalid name assertParseFailure(parser, "1" + INVALID_PHONE_DESC, Phone.MESSAGE_PHONE_CONSTRAINTS); // invalid phone assertParseFailure(parser, "1" + INVALID_EMAIL_DESC, Email.MESSAGE_EMAIL_CONSTRAINTS); // invalid email assertParseFailure(parser, "1" + INVALID_ADDRESS_DESC, Address.MESSAGE_ADDRESS_CONSTRAINTS); // invalid address @@ -101,17 +101,17 @@ public void parse_invalidValue_failure() { assertParseFailure(parser, "1" + TAG_EMPTY + TAG_DESC_FRIEND + TAG_DESC_HUSBAND, Tag.MESSAGE_TAG_CONSTRAINTS); // multiple invalid values, but only the first invalid value is captured - assertParseFailure(parser, "1" + INVALID_NAME_DESC + INVALID_EMAIL_DESC + VALID_ADDRESS_AMY + VALID_PHONE_AMY, - Name.MESSAGE_NAME_CONSTRAINTS); + assertParseFailure(parser, "1" + INVALID_TITLE_DESC + INVALID_EMAIL_DESC + VALID_ADDRESS_AMY + VALID_PHONE_AMY, + Title.MESSAGE_TITLE_CONSTRAINTS); } @Test public void parse_allFieldsSpecified_success() { Index targetIndex = INDEX_SECOND_BOOK; String userInput = targetIndex.getOneBased() + PHONE_DESC_BOB + TAG_DESC_HUSBAND - + EMAIL_DESC_AMY + ADDRESS_DESC_AMY + NAME_DESC_AMY + TAG_DESC_FRIEND; + + EMAIL_DESC_AMY + ADDRESS_DESC_AMY + TITLE_DESC_AMY + TAG_DESC_FRIEND; - EditBookDescriptor descriptor = new EditBookDescriptorBuilder().withName(VALID_NAME_AMY) + EditBookDescriptor descriptor = new EditBookDescriptorBuilder().withName(VALID_TITLE_AMY) .withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_AMY).withAddress(VALID_ADDRESS_AMY) .withTags(VALID_TAG_HUSBAND, VALID_TAG_FRIEND).build(); EditCommand expectedCommand = new EditCommand(targetIndex, descriptor); @@ -135,8 +135,8 @@ public void parse_someFieldsSpecified_success() { public void parse_oneFieldSpecified_success() { // name Index targetIndex = INDEX_THIRD_BOOK; - String userInput = targetIndex.getOneBased() + NAME_DESC_AMY; - EditBookDescriptor descriptor = new EditBookDescriptorBuilder().withName(VALID_NAME_AMY).build(); + String userInput = targetIndex.getOneBased() + TITLE_DESC_AMY; + EditBookDescriptor descriptor = new EditBookDescriptorBuilder().withName(VALID_TITLE_AMY).build(); EditCommand expectedCommand = new EditCommand(targetIndex, descriptor); assertParseSuccess(parser, userInput, expectedCommand); diff --git a/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java b/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java index db52a7b1136e..2ac9f2427f50 100644 --- a/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java @@ -9,7 +9,7 @@ import org.junit.Test; import seedu.address.logic.commands.FindCommand; -import seedu.address.model.book.NameContainsKeywordsPredicate; +import seedu.address.model.book.TitleContainsKeywordsPredicate; public class FindCommandParserTest { @@ -24,7 +24,7 @@ public void parse_emptyArg_throwsParseException() { public void parse_validArgs_returnsFindCommand() { // no leading and trailing whitespaces FindCommand expectedFindCommand = - new FindCommand(new NameContainsKeywordsPredicate(Arrays.asList("Alice", "Bob"))); + new FindCommand(new TitleContainsKeywordsPredicate(Arrays.asList("Alice", "Bob"))); assertParseSuccess(parser, "Alice Bob", expectedFindCommand); // multiple whitespaces between keywords diff --git a/src/test/java/seedu/address/logic/parser/ParserUtilTest.java b/src/test/java/seedu/address/logic/parser/ParserUtilTest.java index ff12a137c62f..c698cb35bad4 100644 --- a/src/test/java/seedu/address/logic/parser/ParserUtilTest.java +++ b/src/test/java/seedu/address/logic/parser/ParserUtilTest.java @@ -20,19 +20,19 @@ import seedu.address.commons.exceptions.IllegalValueException; import seedu.address.model.book.Address; import seedu.address.model.book.Email; -import seedu.address.model.book.Name; +import seedu.address.model.book.Title; import seedu.address.model.book.Phone; import seedu.address.model.tag.Tag; import seedu.address.testutil.Assert; public class ParserUtilTest { - private static final String INVALID_NAME = "R@chel"; + private static final String INVALID_TITLE = "R@chel"; private static final String INVALID_PHONE = "+651234"; private static final String INVALID_ADDRESS = " "; private static final String INVALID_EMAIL = "example.com"; private static final String INVALID_TAG = "#friend"; - private static final String VALID_NAME = "Rachel Walker"; + private static final String VALID_TITLE = "Rachel Walker"; private static final String VALID_PHONE = "123456"; private static final String VALID_ADDRESS = "123 Main Street #0505"; private static final String VALID_EMAIL = "rachel@example.com"; @@ -68,34 +68,34 @@ public void parseIndex_validInput_success() throws Exception { @Test public void parseName_null_throwsNullPointerException() { - Assert.assertThrows(NullPointerException.class, () -> ParserUtil.parseName((String) null)); - Assert.assertThrows(NullPointerException.class, () -> ParserUtil.parseName((Optional) null)); + Assert.assertThrows(NullPointerException.class, () -> ParserUtil.parseTitle((String) null)); + Assert.assertThrows(NullPointerException.class, () -> ParserUtil.parseTitle((Optional) null)); } @Test public void parseName_invalidValue_throwsIllegalValueException() { - Assert.assertThrows(IllegalValueException.class, () -> ParserUtil.parseName(INVALID_NAME)); - Assert.assertThrows(IllegalValueException.class, () -> ParserUtil.parseName(Optional.of(INVALID_NAME))); + Assert.assertThrows(IllegalValueException.class, () -> ParserUtil.parseTitle(INVALID_TITLE)); + Assert.assertThrows(IllegalValueException.class, () -> ParserUtil.parseTitle(Optional.of(INVALID_TITLE))); } @Test public void parseName_optionalEmpty_returnsOptionalEmpty() throws Exception { - assertFalse(ParserUtil.parseName(Optional.empty()).isPresent()); + assertFalse(ParserUtil.parseTitle(Optional.empty()).isPresent()); } @Test public void parseName_validValueWithoutWhitespace_returnsName() throws Exception { - Name expectedName = new Name(VALID_NAME); - assertEquals(expectedName, ParserUtil.parseName(VALID_NAME)); - assertEquals(Optional.of(expectedName), ParserUtil.parseName(Optional.of(VALID_NAME))); + Title expectedTitle = new Title(VALID_TITLE); + assertEquals(expectedTitle, ParserUtil.parseTitle(VALID_TITLE)); + assertEquals(Optional.of(expectedTitle), ParserUtil.parseTitle(Optional.of(VALID_TITLE))); } @Test public void parseName_validValueWithWhitespace_returnsTrimmedName() throws Exception { - String nameWithWhitespace = WHITESPACE + VALID_NAME + WHITESPACE; - Name expectedName = new Name(VALID_NAME); - assertEquals(expectedName, ParserUtil.parseName(nameWithWhitespace)); - assertEquals(Optional.of(expectedName), ParserUtil.parseName(Optional.of(nameWithWhitespace))); + String nameWithWhitespace = WHITESPACE + VALID_TITLE + WHITESPACE; + Title expectedTitle = new Title(VALID_TITLE); + assertEquals(expectedTitle, ParserUtil.parseTitle(nameWithWhitespace)); + assertEquals(Optional.of(expectedTitle), ParserUtil.parseTitle(Optional.of(nameWithWhitespace))); } @Test diff --git a/src/test/java/seedu/address/model/ModelManagerTest.java b/src/test/java/seedu/address/model/ModelManagerTest.java index 4fd0e1261f02..44c573ed0dd3 100644 --- a/src/test/java/seedu/address/model/ModelManagerTest.java +++ b/src/test/java/seedu/address/model/ModelManagerTest.java @@ -12,7 +12,7 @@ import org.junit.Test; import org.junit.rules.ExpectedException; -import seedu.address.model.book.NameContainsKeywordsPredicate; +import seedu.address.model.book.TitleContainsKeywordsPredicate; import seedu.address.testutil.CatalogueBuilder; public class ModelManagerTest { @@ -50,8 +50,8 @@ public void equals() { assertFalse(modelManager.equals(new ModelManager(differentCatalogue, userPrefs))); // different filteredList -> returns false - String[] keywords = ALICE.getName().fullName.split("\\s+"); - modelManager.updateFilteredBookList(new NameContainsKeywordsPredicate(Arrays.asList(keywords))); + String[] keywords = ALICE.getTitle().fullTitle.split("\\s+"); + modelManager.updateFilteredBookList(new TitleContainsKeywordsPredicate(Arrays.asList(keywords))); assertFalse(modelManager.equals(new ModelManager(catalogue, userPrefs))); // resets modelManager to initial state for upcoming tests @@ -59,7 +59,7 @@ public void equals() { // different userPrefs -> returns true UserPrefs differentUserPrefs = new UserPrefs(); - differentUserPrefs.setCatalogueBookName("differentName"); + differentUserPrefs.setCatalogueBookTitle("differentName"); assertTrue(modelManager.equals(new ModelManager(catalogue, differentUserPrefs))); } } diff --git a/src/test/java/seedu/address/model/book/NameTest.java b/src/test/java/seedu/address/model/book/NameTest.java deleted file mode 100644 index e85a303106b5..000000000000 --- a/src/test/java/seedu/address/model/book/NameTest.java +++ /dev/null @@ -1,41 +0,0 @@ -package seedu.address.model.book; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -import seedu.address.testutil.Assert; - -public class NameTest { - - @Test - public void constructor_null_throwsNullPointerException() { - Assert.assertThrows(NullPointerException.class, () -> new Name(null)); - } - - @Test - public void constructor_invalidName_throwsIllegalArgumentException() { - String invalidName = ""; - Assert.assertThrows(IllegalArgumentException.class, () -> new Name(invalidName)); - } - - @Test - public void isValidName() { - // null name - Assert.assertThrows(NullPointerException.class, () -> Name.isValidName(null)); - - // invalid name - assertFalse(Name.isValidName("")); // empty string - assertFalse(Name.isValidName(" ")); // spaces only - assertFalse(Name.isValidName("^")); // only non-alphanumeric characters - assertFalse(Name.isValidName("peter*")); // contains non-alphanumeric characters - - // valid name - assertTrue(Name.isValidName("peter jack")); // alphabets only - assertTrue(Name.isValidName("12345")); // numbers only - assertTrue(Name.isValidName("peter the 2nd")); // alphanumeric characters - assertTrue(Name.isValidName("Capital Tan")); // with capital letters - assertTrue(Name.isValidName("David Roger Jackson Ray Jr 2nd")); // long names - } -} diff --git a/src/test/java/seedu/address/model/book/NameContainsKeywordsPredicateTest.java b/src/test/java/seedu/address/model/book/TitleContainsKeywordsPredicateTest.java similarity index 65% rename from src/test/java/seedu/address/model/book/NameContainsKeywordsPredicateTest.java rename to src/test/java/seedu/address/model/book/TitleContainsKeywordsPredicateTest.java index f32554559b0a..48daf2e9fd55 100644 --- a/src/test/java/seedu/address/model/book/NameContainsKeywordsPredicateTest.java +++ b/src/test/java/seedu/address/model/book/TitleContainsKeywordsPredicateTest.java @@ -11,21 +11,21 @@ import seedu.address.testutil.BookBuilder; -public class NameContainsKeywordsPredicateTest { +public class TitleContainsKeywordsPredicateTest { @Test public void equals() { List firstPredicateKeywordList = Collections.singletonList("first"); List secondPredicateKeywordList = Arrays.asList("first", "second"); - NameContainsKeywordsPredicate firstPredicate = new NameContainsKeywordsPredicate(firstPredicateKeywordList); - NameContainsKeywordsPredicate secondPredicate = new NameContainsKeywordsPredicate(secondPredicateKeywordList); + TitleContainsKeywordsPredicate firstPredicate = new TitleContainsKeywordsPredicate(firstPredicateKeywordList); + TitleContainsKeywordsPredicate secondPredicate = new TitleContainsKeywordsPredicate(secondPredicateKeywordList); // same object -> returns true assertTrue(firstPredicate.equals(firstPredicate)); // same values -> returns true - NameContainsKeywordsPredicate firstPredicateCopy = new NameContainsKeywordsPredicate(firstPredicateKeywordList); + TitleContainsKeywordsPredicate firstPredicateCopy = new TitleContainsKeywordsPredicate(firstPredicateKeywordList); assertTrue(firstPredicate.equals(firstPredicateCopy)); // different types -> returns false @@ -41,34 +41,34 @@ public void equals() { @Test public void test_nameContainsKeywords_returnsTrue() { // One keyword - NameContainsKeywordsPredicate predicate = new NameContainsKeywordsPredicate(Collections.singletonList("Alice")); + TitleContainsKeywordsPredicate predicate = new TitleContainsKeywordsPredicate(Collections.singletonList("Alice")); assertTrue(predicate.test(new BookBuilder().withName("Alice Bob").build())); // Multiple keywords - predicate = new NameContainsKeywordsPredicate(Arrays.asList("Alice", "Bob")); + predicate = new TitleContainsKeywordsPredicate(Arrays.asList("Alice", "Bob")); assertTrue(predicate.test(new BookBuilder().withName("Alice Bob").build())); // Only one matching keyword - predicate = new NameContainsKeywordsPredicate(Arrays.asList("Bob", "Carol")); + predicate = new TitleContainsKeywordsPredicate(Arrays.asList("Bob", "Carol")); assertTrue(predicate.test(new BookBuilder().withName("Alice Carol").build())); // Mixed-case keywords - predicate = new NameContainsKeywordsPredicate(Arrays.asList("aLIce", "bOB")); + predicate = new TitleContainsKeywordsPredicate(Arrays.asList("aLIce", "bOB")); assertTrue(predicate.test(new BookBuilder().withName("Alice Bob").build())); } @Test public void test_nameDoesNotContainKeywords_returnsFalse() { // Zero keywords - NameContainsKeywordsPredicate predicate = new NameContainsKeywordsPredicate(Collections.emptyList()); + TitleContainsKeywordsPredicate predicate = new TitleContainsKeywordsPredicate(Collections.emptyList()); assertFalse(predicate.test(new BookBuilder().withName("Alice").build())); // Non-matching keyword - predicate = new NameContainsKeywordsPredicate(Arrays.asList("Carol")); + predicate = new TitleContainsKeywordsPredicate(Arrays.asList("Carol")); assertFalse(predicate.test(new BookBuilder().withName("Alice Bob").build())); // Keywords match phone, email and address, but does not match name - predicate = new NameContainsKeywordsPredicate(Arrays.asList("12345", "alice@email.com", "Main", "Street")); + predicate = new TitleContainsKeywordsPredicate(Arrays.asList("12345", "alice@email.com", "Main", "Street")); assertFalse(predicate.test(new BookBuilder().withName("Alice").withPhone("12345") .withEmail("alice@email.com").withAddress("Main Street").build())); } diff --git a/src/test/java/seedu/address/model/book/TitleTest.java b/src/test/java/seedu/address/model/book/TitleTest.java new file mode 100644 index 000000000000..61c8404a4f9b --- /dev/null +++ b/src/test/java/seedu/address/model/book/TitleTest.java @@ -0,0 +1,41 @@ +package seedu.address.model.book; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import seedu.address.testutil.Assert; + +public class TitleTest { + + @Test + public void constructor_null_throwsNullPointerException() { + Assert.assertThrows(NullPointerException.class, () -> new Title(null)); + } + + @Test + public void constructor_invalidName_throwsIllegalArgumentException() { + String invalidName = ""; + Assert.assertThrows(IllegalArgumentException.class, () -> new Title(invalidName)); + } + + @Test + public void isValidName() { + // null name + Assert.assertThrows(NullPointerException.class, () -> Title.isValidTitle(null)); + + // invalid name + assertFalse(Title.isValidTitle("")); // empty string + assertFalse(Title.isValidTitle(" ")); // spaces only + assertFalse(Title.isValidTitle("^")); // only non-alphanumeric characters + assertFalse(Title.isValidTitle("peter*")); // contains non-alphanumeric characters + + // valid name + assertTrue(Title.isValidTitle("peter jack")); // alphabets only + assertTrue(Title.isValidTitle("12345")); // numbers only + assertTrue(Title.isValidTitle("peter the 2nd")); // alphanumeric characters + assertTrue(Title.isValidTitle("Capital Tan")); // with capital letters + assertTrue(Title.isValidTitle("David Roger Jackson Ray Jr 2nd")); // long names + } +} diff --git a/src/test/java/seedu/address/storage/JsonUserPrefsStorageTest.java b/src/test/java/seedu/address/storage/JsonUserPrefsStorageTest.java index 68a6483e2dbd..c3769c815240 100644 --- a/src/test/java/seedu/address/storage/JsonUserPrefsStorageTest.java +++ b/src/test/java/seedu/address/storage/JsonUserPrefsStorageTest.java @@ -83,7 +83,7 @@ private UserPrefs getTypicalUserPrefs() { UserPrefs userPrefs = new UserPrefs(); userPrefs.setGuiSettings(1000, 500, 300, 100); userPrefs.setCatalogueFilePath("catalogue.xml"); - userPrefs.setCatalogueBookName("TypicalCatalogueName"); + userPrefs.setCatalogueBookTitle("MyCatalogue"); return userPrefs; } diff --git a/src/test/java/seedu/address/storage/XmlAdaptedBookTest.java b/src/test/java/seedu/address/storage/XmlAdaptedBookTest.java index 1fd091904f25..5ff49e8831af 100644 --- a/src/test/java/seedu/address/storage/XmlAdaptedBookTest.java +++ b/src/test/java/seedu/address/storage/XmlAdaptedBookTest.java @@ -13,18 +13,18 @@ import seedu.address.commons.exceptions.IllegalValueException; import seedu.address.model.book.Address; import seedu.address.model.book.Email; -import seedu.address.model.book.Name; +import seedu.address.model.book.Title; import seedu.address.model.book.Phone; import seedu.address.testutil.Assert; public class XmlAdaptedBookTest { - private static final String INVALID_NAME = "R@chel"; + private static final String INVALID_TITLE = "R@chel"; private static final String INVALID_PHONE = "+651234"; private static final String INVALID_ADDRESS = " "; private static final String INVALID_EMAIL = "example.com"; private static final String INVALID_TAG = "#friend"; - private static final String VALID_NAME = BENSON.getName().toString(); + private static final String VALID_TITLE = BENSON.getTitle().toString(); private static final String VALID_PHONE = BENSON.getPhone().toString(); private static final String VALID_EMAIL = BENSON.getEmail().toString(); private static final String VALID_ADDRESS = BENSON.getAddress().toString(); @@ -41,29 +41,29 @@ public void toModelType_validBookDetails_returnsBook() throws Exception { @Test public void toModelType_invalidName_throwsIllegalValueException() { XmlAdaptedBook book = - new XmlAdaptedBook(INVALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS); - String expectedMessage = Name.MESSAGE_NAME_CONSTRAINTS; + new XmlAdaptedBook(INVALID_TITLE, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS); + String expectedMessage = Title.MESSAGE_TITLE_CONSTRAINTS; Assert.assertThrows(IllegalValueException.class, expectedMessage, book::toModelType); } @Test public void toModelType_nullName_throwsIllegalValueException() { XmlAdaptedBook book = new XmlAdaptedBook(null, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS); - String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Name.class.getSimpleName()); + String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Title.class.getSimpleName()); Assert.assertThrows(IllegalValueException.class, expectedMessage, book::toModelType); } @Test public void toModelType_invalidPhone_throwsIllegalValueException() { XmlAdaptedBook book = - new XmlAdaptedBook(VALID_NAME, INVALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS); + new XmlAdaptedBook(VALID_TITLE, INVALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS); String expectedMessage = Phone.MESSAGE_PHONE_CONSTRAINTS; Assert.assertThrows(IllegalValueException.class, expectedMessage, book::toModelType); } @Test public void toModelType_nullPhone_throwsIllegalValueException() { - XmlAdaptedBook book = new XmlAdaptedBook(VALID_NAME, null, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS); + XmlAdaptedBook book = new XmlAdaptedBook(VALID_TITLE, null, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS); String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Phone.class.getSimpleName()); Assert.assertThrows(IllegalValueException.class, expectedMessage, book::toModelType); } @@ -71,14 +71,14 @@ public void toModelType_nullPhone_throwsIllegalValueException() { @Test public void toModelType_invalidEmail_throwsIllegalValueException() { XmlAdaptedBook book = - new XmlAdaptedBook(VALID_NAME, VALID_PHONE, INVALID_EMAIL, VALID_ADDRESS, VALID_TAGS); + new XmlAdaptedBook(VALID_TITLE, VALID_PHONE, INVALID_EMAIL, VALID_ADDRESS, VALID_TAGS); String expectedMessage = Email.MESSAGE_EMAIL_CONSTRAINTS; Assert.assertThrows(IllegalValueException.class, expectedMessage, book::toModelType); } @Test public void toModelType_nullEmail_throwsIllegalValueException() { - XmlAdaptedBook book = new XmlAdaptedBook(VALID_NAME, VALID_PHONE, null, VALID_ADDRESS, VALID_TAGS); + XmlAdaptedBook book = new XmlAdaptedBook(VALID_TITLE, VALID_PHONE, null, VALID_ADDRESS, VALID_TAGS); String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Email.class.getSimpleName()); Assert.assertThrows(IllegalValueException.class, expectedMessage, book::toModelType); } @@ -86,14 +86,14 @@ public void toModelType_nullEmail_throwsIllegalValueException() { @Test public void toModelType_invalidAddress_throwsIllegalValueException() { XmlAdaptedBook book = - new XmlAdaptedBook(VALID_NAME, VALID_PHONE, VALID_EMAIL, INVALID_ADDRESS, VALID_TAGS); + new XmlAdaptedBook(VALID_TITLE, VALID_PHONE, VALID_EMAIL, INVALID_ADDRESS, VALID_TAGS); String expectedMessage = Address.MESSAGE_ADDRESS_CONSTRAINTS; Assert.assertThrows(IllegalValueException.class, expectedMessage, book::toModelType); } @Test public void toModelType_nullAddress_throwsIllegalValueException() { - XmlAdaptedBook book = new XmlAdaptedBook(VALID_NAME, VALID_PHONE, VALID_EMAIL, null, VALID_TAGS); + XmlAdaptedBook book = new XmlAdaptedBook(VALID_TITLE, VALID_PHONE, VALID_EMAIL, null, VALID_TAGS); String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Address.class.getSimpleName()); Assert.assertThrows(IllegalValueException.class, expectedMessage, book::toModelType); } @@ -103,7 +103,7 @@ public void toModelType_invalidTags_throwsIllegalValueException() { List invalidTags = new ArrayList<>(VALID_TAGS); invalidTags.add(new XmlAdaptedTag(INVALID_TAG)); XmlAdaptedBook book = - new XmlAdaptedBook(VALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, invalidTags); + new XmlAdaptedBook(VALID_TITLE, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, invalidTags); Assert.assertThrows(IllegalValueException.class, book::toModelType); } diff --git a/src/test/java/seedu/address/testutil/BookBuilder.java b/src/test/java/seedu/address/testutil/BookBuilder.java index 8f8a46bd99b2..97c554949361 100644 --- a/src/test/java/seedu/address/testutil/BookBuilder.java +++ b/src/test/java/seedu/address/testutil/BookBuilder.java @@ -6,7 +6,7 @@ import seedu.address.model.book.Address; import seedu.address.model.book.Book; import seedu.address.model.book.Email; -import seedu.address.model.book.Name; +import seedu.address.model.book.Title; import seedu.address.model.book.Phone; import seedu.address.model.tag.Tag; import seedu.address.model.util.SampleDataUtil; @@ -16,20 +16,20 @@ */ public class BookBuilder { - public static final String DEFAULT_NAME = "Alice Pauline"; + public static final String DEFAULT_TITLE = "Alice Pauline"; public static final String DEFAULT_PHONE = "85355255"; public static final String DEFAULT_EMAIL = "alice@gmail.com"; public static final String DEFAULT_ADDRESS = "123, Jurong West Ave 6, #08-111"; public static final String DEFAULT_TAGS = "friends"; - private Name name; + private Title title; private Phone phone; private Email email; private Address address; private Set tags; public BookBuilder() { - name = new Name(DEFAULT_NAME); + title = new Title(DEFAULT_TITLE); phone = new Phone(DEFAULT_PHONE); email = new Email(DEFAULT_EMAIL); address = new Address(DEFAULT_ADDRESS); @@ -40,7 +40,7 @@ public BookBuilder() { * Initializes the BookBuilder with the data of {@code bookToCopy}. */ public BookBuilder(Book bookToCopy) { - name = bookToCopy.getName(); + title = bookToCopy.getTitle(); phone = bookToCopy.getPhone(); email = bookToCopy.getEmail(); address = bookToCopy.getAddress(); @@ -48,10 +48,10 @@ public BookBuilder(Book bookToCopy) { } /** - * Sets the {@code Name} of the {@code Book} that we are building. + * Sets the {@code Title} of the {@code Book} that we are building. */ public BookBuilder withName(String name) { - this.name = new Name(name); + this.title = new Title(name); return this; } @@ -88,7 +88,7 @@ public BookBuilder withEmail(String email) { } public Book build() { - return new Book(name, phone, email, address, tags); + return new Book(title, phone, email, address, tags); } } diff --git a/src/test/java/seedu/address/testutil/BookUtil.java b/src/test/java/seedu/address/testutil/BookUtil.java index 02089e9112af..10347eb13b4a 100644 --- a/src/test/java/seedu/address/testutil/BookUtil.java +++ b/src/test/java/seedu/address/testutil/BookUtil.java @@ -2,7 +2,7 @@ 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_NAME; +import static seedu.address.logic.parser.CliSyntax.PREFIX_TITLE; import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; @@ -26,7 +26,7 @@ public static String getAddCommand(Book book) { */ public static String getBookDetails(Book book) { StringBuilder sb = new StringBuilder(); - sb.append(PREFIX_NAME + book.getName().fullName + " "); + sb.append(PREFIX_TITLE + book.getTitle().fullTitle + " "); sb.append(PREFIX_PHONE + book.getPhone().value + " "); sb.append(PREFIX_EMAIL + book.getEmail().value + " "); sb.append(PREFIX_ADDRESS + book.getAddress().value + " "); diff --git a/src/test/java/seedu/address/testutil/EditBookDescriptorBuilder.java b/src/test/java/seedu/address/testutil/EditBookDescriptorBuilder.java index 91eb98fad7c5..c07353d63b61 100644 --- a/src/test/java/seedu/address/testutil/EditBookDescriptorBuilder.java +++ b/src/test/java/seedu/address/testutil/EditBookDescriptorBuilder.java @@ -7,7 +7,7 @@ import seedu.address.logic.commands.EditCommand.EditBookDescriptor; import seedu.address.model.book.Address; import seedu.address.model.book.Email; -import seedu.address.model.book.Name; +import seedu.address.model.book.Title; import seedu.address.model.book.Book; import seedu.address.model.book.Phone; import seedu.address.model.tag.Tag; @@ -32,7 +32,7 @@ public EditBookDescriptorBuilder(EditBookDescriptor descriptor) { */ public EditBookDescriptorBuilder(Book book) { descriptor = new EditBookDescriptor(); - descriptor.setName(book.getName()); + descriptor.setTitle(book.getTitle()); descriptor.setPhone(book.getPhone()); descriptor.setEmail(book.getEmail()); descriptor.setAddress(book.getAddress()); @@ -40,10 +40,10 @@ public EditBookDescriptorBuilder(Book book) { } /** - * Sets the {@code Name} of the {@code EditBookDescriptor} that we are building. + * Sets the {@code Title} of the {@code EditBookDescriptor} that we are building. */ public EditBookDescriptorBuilder withName(String name) { - descriptor.setName(new Name(name)); + descriptor.setTitle(new Title(name)); return this; } diff --git a/src/test/java/seedu/address/testutil/TypicalBooks.java b/src/test/java/seedu/address/testutil/TypicalBooks.java index 3a58e4921788..08447d164b0b 100644 --- a/src/test/java/seedu/address/testutil/TypicalBooks.java +++ b/src/test/java/seedu/address/testutil/TypicalBooks.java @@ -4,8 +4,8 @@ import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB; import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_AMY; import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_AMY; -import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB; +import static seedu.address.logic.commands.CommandTestUtil.VALID_TITLE_AMY; +import static seedu.address.logic.commands.CommandTestUtil.VALID_TITLE_BOB; import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_AMY; import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB; import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_FRIEND; @@ -50,9 +50,9 @@ public class TypicalBooks { .withEmail("hans@example.com").withAddress("chicago ave").build(); // Manually added - Book's details found in {@code CommandTestUtil} - public static final Book AMY = new BookBuilder().withName(VALID_NAME_AMY).withPhone(VALID_PHONE_AMY) + public static final Book AMY = new BookBuilder().withName(VALID_TITLE_AMY).withPhone(VALID_PHONE_AMY) .withEmail(VALID_EMAIL_AMY).withAddress(VALID_ADDRESS_AMY).withTags(VALID_TAG_FRIEND).build(); - public static final Book BOB = new BookBuilder().withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB) + public static final Book BOB = new BookBuilder().withName(VALID_TITLE_BOB).withPhone(VALID_PHONE_BOB) .withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND, VALID_TAG_FRIEND) .build(); diff --git a/src/test/java/seedu/address/ui/BrowserPanelTest.java b/src/test/java/seedu/address/ui/BrowserPanelTest.java index e82d1256a1b7..2a8f4271c864 100644 --- a/src/test/java/seedu/address/ui/BrowserPanelTest.java +++ b/src/test/java/seedu/address/ui/BrowserPanelTest.java @@ -40,7 +40,7 @@ public void display() throws Exception { // associated web page of a book postNow(selectionChangedEventStub); - URL expectedBookUrl = new URL(BrowserPanel.SEARCH_PAGE_URL + ALICE.getName().fullName.replaceAll(" ", "%20")); + URL expectedBookUrl = new URL(BrowserPanel.SEARCH_PAGE_URL + ALICE.getTitle().fullTitle.replaceAll(" ", "%20")); waitUntilBrowserLoaded(browserPanelHandle); assertEquals(expectedBookUrl, browserPanelHandle.getLoadedUrl()); diff --git a/src/test/java/seedu/address/ui/testutil/GuiTestAssert.java b/src/test/java/seedu/address/ui/testutil/GuiTestAssert.java index 2b0b41758553..e7e0b6e296f1 100644 --- a/src/test/java/seedu/address/ui/testutil/GuiTestAssert.java +++ b/src/test/java/seedu/address/ui/testutil/GuiTestAssert.java @@ -30,7 +30,7 @@ public static void assertCardEquals(BookCardHandle expectedCard, BookCardHandle * Asserts that {@code actualCard} displays the details of {@code expectedBook}. */ public static void assertCardDisplaysBook(Book expectedBook, BookCardHandle actualCard) { - assertEquals(expectedBook.getName().fullName, actualCard.getName()); + assertEquals(expectedBook.getTitle().fullTitle, actualCard.getName()); assertEquals(expectedBook.getPhone().value, actualCard.getPhone()); assertEquals(expectedBook.getEmail().value, actualCard.getEmail()); assertEquals(expectedBook.getAddress().value, actualCard.getAddress()); diff --git a/src/test/java/systemtests/AddCommandSystemTest.java b/src/test/java/systemtests/AddCommandSystemTest.java index 18af1d6c1633..26b955416d1e 100644 --- a/src/test/java/systemtests/AddCommandSystemTest.java +++ b/src/test/java/systemtests/AddCommandSystemTest.java @@ -7,11 +7,11 @@ import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_BOB; import static seedu.address.logic.commands.CommandTestUtil.INVALID_ADDRESS_DESC; import static seedu.address.logic.commands.CommandTestUtil.INVALID_EMAIL_DESC; -import static seedu.address.logic.commands.CommandTestUtil.INVALID_NAME_DESC; +import static seedu.address.logic.commands.CommandTestUtil.INVALID_TITLE_DESC; import static seedu.address.logic.commands.CommandTestUtil.INVALID_PHONE_DESC; import static seedu.address.logic.commands.CommandTestUtil.INVALID_TAG_DESC; -import static seedu.address.logic.commands.CommandTestUtil.NAME_DESC_AMY; -import static seedu.address.logic.commands.CommandTestUtil.NAME_DESC_BOB; +import static seedu.address.logic.commands.CommandTestUtil.TITLE_DESC_AMY; +import static seedu.address.logic.commands.CommandTestUtil.TITLE_DESC_BOB; import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_AMY; import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_BOB; import static seedu.address.logic.commands.CommandTestUtil.TAG_DESC_FRIEND; @@ -20,8 +20,8 @@ import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB; import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_AMY; import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_AMY; -import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB; +import static seedu.address.logic.commands.CommandTestUtil.VALID_TITLE_AMY; +import static seedu.address.logic.commands.CommandTestUtil.VALID_TITLE_BOB; import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_AMY; import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB; import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_FRIEND; @@ -45,7 +45,7 @@ import seedu.address.model.book.Address; import seedu.address.model.book.Book; import seedu.address.model.book.Email; -import seedu.address.model.book.Name; +import seedu.address.model.book.Title; import seedu.address.model.book.Phone; import seedu.address.model.book.exceptions.DuplicateBookException; import seedu.address.model.tag.Tag; @@ -64,7 +64,7 @@ public void add() throws Exception { * -> added */ Book toAdd = AMY; - String command = " " + AddCommand.COMMAND_WORD + " " + NAME_DESC_AMY + " " + PHONE_DESC_AMY + " " + String command = " " + AddCommand.COMMAND_WORD + " " + TITLE_DESC_AMY + " " + PHONE_DESC_AMY + " " + EMAIL_DESC_AMY + " " + ADDRESS_DESC_AMY + " " + TAG_DESC_FRIEND + " "; assertCommandSuccess(command, toAdd); @@ -80,30 +80,30 @@ public void add() throws Exception { assertCommandSuccess(command, model, expectedResultMessage); /* Case: add a book with all fields same as another book in the catalogue except name -> added */ - toAdd = new BookBuilder().withName(VALID_NAME_BOB).withPhone(VALID_PHONE_AMY).withEmail(VALID_EMAIL_AMY) + toAdd = new BookBuilder().withName(VALID_TITLE_BOB).withPhone(VALID_PHONE_AMY).withEmail(VALID_EMAIL_AMY) .withAddress(VALID_ADDRESS_AMY).withTags(VALID_TAG_FRIEND).build(); - command = AddCommand.COMMAND_WORD + NAME_DESC_BOB + PHONE_DESC_AMY + EMAIL_DESC_AMY + ADDRESS_DESC_AMY + command = AddCommand.COMMAND_WORD + TITLE_DESC_BOB + PHONE_DESC_AMY + EMAIL_DESC_AMY + ADDRESS_DESC_AMY + TAG_DESC_FRIEND; assertCommandSuccess(command, toAdd); /* Case: add a book with all fields same as another book in the catalogue except phone -> added */ - toAdd = new BookBuilder().withName(VALID_NAME_AMY).withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_AMY) + toAdd = new BookBuilder().withName(VALID_TITLE_AMY).withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_AMY) .withAddress(VALID_ADDRESS_AMY).withTags(VALID_TAG_FRIEND).build(); - command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + PHONE_DESC_BOB + EMAIL_DESC_AMY + ADDRESS_DESC_AMY + command = AddCommand.COMMAND_WORD + TITLE_DESC_AMY + PHONE_DESC_BOB + EMAIL_DESC_AMY + ADDRESS_DESC_AMY + TAG_DESC_FRIEND; assertCommandSuccess(command, toAdd); /* Case: add a book with all fields same as another book in the catalogue except email -> added */ - toAdd = new BookBuilder().withName(VALID_NAME_AMY).withPhone(VALID_PHONE_AMY).withEmail(VALID_EMAIL_BOB) + toAdd = new BookBuilder().withName(VALID_TITLE_AMY).withPhone(VALID_PHONE_AMY).withEmail(VALID_EMAIL_BOB) .withAddress(VALID_ADDRESS_AMY).withTags(VALID_TAG_FRIEND).build(); - command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_BOB + ADDRESS_DESC_AMY + command = AddCommand.COMMAND_WORD + TITLE_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_BOB + ADDRESS_DESC_AMY + TAG_DESC_FRIEND; assertCommandSuccess(command, toAdd); /* Case: add a book with all fields same as another book in the catalogue except address -> added */ - toAdd = new BookBuilder().withName(VALID_NAME_AMY).withPhone(VALID_PHONE_AMY).withEmail(VALID_EMAIL_AMY) + toAdd = new BookBuilder().withName(VALID_TITLE_AMY).withPhone(VALID_PHONE_AMY).withEmail(VALID_EMAIL_AMY) .withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_FRIEND).build(); - command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY + ADDRESS_DESC_BOB + command = AddCommand.COMMAND_WORD + TITLE_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY + ADDRESS_DESC_BOB + TAG_DESC_FRIEND; assertCommandSuccess(command, toAdd); @@ -113,7 +113,7 @@ public void add() throws Exception { /* Case: add a book with tags, command with parameters in random order -> added */ toAdd = BOB; - command = AddCommand.COMMAND_WORD + TAG_DESC_FRIEND + PHONE_DESC_BOB + ADDRESS_DESC_BOB + NAME_DESC_BOB + command = AddCommand.COMMAND_WORD + TAG_DESC_FRIEND + PHONE_DESC_BOB + ADDRESS_DESC_BOB + TITLE_DESC_BOB + TAG_DESC_HUSBAND + EMAIL_DESC_BOB; assertCommandSuccess(command, toAdd); @@ -150,15 +150,15 @@ public void add() throws Exception { assertCommandFailure(command, String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE)); /* Case: missing phone -> rejected */ - command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + EMAIL_DESC_AMY + ADDRESS_DESC_AMY; + command = AddCommand.COMMAND_WORD + TITLE_DESC_AMY + EMAIL_DESC_AMY + ADDRESS_DESC_AMY; assertCommandFailure(command, String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE)); /* Case: missing email -> rejected */ - command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + PHONE_DESC_AMY + ADDRESS_DESC_AMY; + command = AddCommand.COMMAND_WORD + TITLE_DESC_AMY + PHONE_DESC_AMY + ADDRESS_DESC_AMY; assertCommandFailure(command, String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE)); /* Case: missing address -> rejected */ - command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY; + command = AddCommand.COMMAND_WORD + TITLE_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY; assertCommandFailure(command, String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE)); /* Case: invalid keyword -> rejected */ @@ -166,23 +166,23 @@ public void add() throws Exception { assertCommandFailure(command, Messages.MESSAGE_UNKNOWN_COMMAND); /* Case: invalid name -> rejected */ - command = AddCommand.COMMAND_WORD + INVALID_NAME_DESC + PHONE_DESC_AMY + EMAIL_DESC_AMY + ADDRESS_DESC_AMY; - assertCommandFailure(command, Name.MESSAGE_NAME_CONSTRAINTS); + command = AddCommand.COMMAND_WORD + INVALID_TITLE_DESC + PHONE_DESC_AMY + EMAIL_DESC_AMY + ADDRESS_DESC_AMY; + assertCommandFailure(command, Title.MESSAGE_TITLE_CONSTRAINTS); /* Case: invalid phone -> rejected */ - command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + INVALID_PHONE_DESC + EMAIL_DESC_AMY + ADDRESS_DESC_AMY; + command = AddCommand.COMMAND_WORD + TITLE_DESC_AMY + INVALID_PHONE_DESC + EMAIL_DESC_AMY + ADDRESS_DESC_AMY; assertCommandFailure(command, Phone.MESSAGE_PHONE_CONSTRAINTS); /* Case: invalid email -> rejected */ - command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + PHONE_DESC_AMY + INVALID_EMAIL_DESC + ADDRESS_DESC_AMY; + command = AddCommand.COMMAND_WORD + TITLE_DESC_AMY + PHONE_DESC_AMY + INVALID_EMAIL_DESC + ADDRESS_DESC_AMY; assertCommandFailure(command, Email.MESSAGE_EMAIL_CONSTRAINTS); /* Case: invalid address -> rejected */ - command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY + INVALID_ADDRESS_DESC; + command = AddCommand.COMMAND_WORD + TITLE_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY + INVALID_ADDRESS_DESC; assertCommandFailure(command, Address.MESSAGE_ADDRESS_CONSTRAINTS); /* Case: invalid tag -> rejected */ - command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY + ADDRESS_DESC_AMY + command = AddCommand.COMMAND_WORD + TITLE_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY + ADDRESS_DESC_AMY + INVALID_TAG_DESC; assertCommandFailure(command, Tag.MESSAGE_TAG_CONSTRAINTS); } diff --git a/src/test/java/systemtests/EditCommandSystemTest.java b/src/test/java/systemtests/EditCommandSystemTest.java index 102bec8d44ac..44ce3b221b3e 100644 --- a/src/test/java/systemtests/EditCommandSystemTest.java +++ b/src/test/java/systemtests/EditCommandSystemTest.java @@ -8,18 +8,18 @@ import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_BOB; import static seedu.address.logic.commands.CommandTestUtil.INVALID_ADDRESS_DESC; import static seedu.address.logic.commands.CommandTestUtil.INVALID_EMAIL_DESC; -import static seedu.address.logic.commands.CommandTestUtil.INVALID_NAME_DESC; +import static seedu.address.logic.commands.CommandTestUtil.INVALID_TITLE_DESC; import static seedu.address.logic.commands.CommandTestUtil.INVALID_PHONE_DESC; import static seedu.address.logic.commands.CommandTestUtil.INVALID_TAG_DESC; -import static seedu.address.logic.commands.CommandTestUtil.NAME_DESC_AMY; -import static seedu.address.logic.commands.CommandTestUtil.NAME_DESC_BOB; +import static seedu.address.logic.commands.CommandTestUtil.TITLE_DESC_AMY; +import static seedu.address.logic.commands.CommandTestUtil.TITLE_DESC_BOB; import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_AMY; import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_BOB; import static seedu.address.logic.commands.CommandTestUtil.TAG_DESC_FRIEND; import static seedu.address.logic.commands.CommandTestUtil.TAG_DESC_HUSBAND; import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB; import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB; +import static seedu.address.logic.commands.CommandTestUtil.VALID_TITLE_BOB; import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB; import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_FRIEND; import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND; @@ -41,7 +41,7 @@ import seedu.address.model.book.Address; import seedu.address.model.book.Book; import seedu.address.model.book.Email; -import seedu.address.model.book.Name; +import seedu.address.model.book.Title; import seedu.address.model.book.Phone; import seedu.address.model.book.exceptions.DuplicateBookException; import seedu.address.model.book.exceptions.BookNotFoundException; @@ -61,9 +61,9 @@ public void edit() throws Exception { * -> edited */ Index index = INDEX_FIRST_BOOK; - String command = " " + EditCommand.COMMAND_WORD + " " + index.getOneBased() + " " + NAME_DESC_BOB + " " + String command = " " + EditCommand.COMMAND_WORD + " " + index.getOneBased() + " " + TITLE_DESC_BOB + " " + PHONE_DESC_BOB + " " + EMAIL_DESC_BOB + " " + ADDRESS_DESC_BOB + " " + TAG_DESC_HUSBAND + " "; - Book editedBook = new BookBuilder().withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB) + Book editedBook = new BookBuilder().withName(VALID_TITLE_BOB).withPhone(VALID_PHONE_BOB) .withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND).build(); assertCommandSuccess(command, index, editedBook); @@ -80,7 +80,7 @@ public void edit() throws Exception { assertCommandSuccess(command, model, expectedResultMessage); /* Case: edit a book with new values same as existing values -> edited */ - command = EditCommand.COMMAND_WORD + " " + index.getOneBased() + NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + command = EditCommand.COMMAND_WORD + " " + index.getOneBased() + TITLE_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB + TAG_DESC_FRIEND + TAG_DESC_HUSBAND; assertCommandSuccess(command, index, BOB); @@ -103,9 +103,9 @@ public void edit() throws Exception { showBooksWithName(KEYWORD_MATCHING_MEIER); index = INDEX_FIRST_BOOK; assertTrue(index.getZeroBased() < getModel().getFilteredBookList().size()); - command = EditCommand.COMMAND_WORD + " " + index.getOneBased() + " " + NAME_DESC_BOB; + command = EditCommand.COMMAND_WORD + " " + index.getOneBased() + " " + TITLE_DESC_BOB; bookToEdit = getModel().getFilteredBookList().get(index.getZeroBased()); - editedBook = new BookBuilder(bookToEdit).withName(VALID_NAME_BOB).build(); + editedBook = new BookBuilder(bookToEdit).withName(VALID_TITLE_BOB).build(); assertCommandSuccess(command, index, editedBook); /* Case: filtered book list, edit index within bounds of catalogue but out of bounds of book list @@ -113,7 +113,7 @@ public void edit() throws Exception { */ showBooksWithName(KEYWORD_MATCHING_MEIER); int invalidIndex = getModel().getCatalogue().getBookList().size(); - assertCommandFailure(EditCommand.COMMAND_WORD + " " + invalidIndex + NAME_DESC_BOB, + assertCommandFailure(EditCommand.COMMAND_WORD + " " + invalidIndex + TITLE_DESC_BOB, Messages.MESSAGE_INVALID_BOOK_DISPLAYED_INDEX); /* --------------------- Performing edit operation while a book card is selected -------------------------- */ @@ -124,7 +124,7 @@ public void edit() throws Exception { showAllBooks(); index = INDEX_FIRST_BOOK; selectBook(index); - command = EditCommand.COMMAND_WORD + " " + index.getOneBased() + NAME_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY + command = EditCommand.COMMAND_WORD + " " + index.getOneBased() + TITLE_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY + ADDRESS_DESC_AMY + TAG_DESC_FRIEND; // this can be misleading: card selection actually remains unchanged but the // browser's url is updated to reflect the new book's name @@ -133,20 +133,20 @@ public void edit() throws Exception { /* --------------------------------- Performing invalid edit operation -------------------------------------- */ /* Case: invalid index (0) -> rejected */ - assertCommandFailure(EditCommand.COMMAND_WORD + " 0" + NAME_DESC_BOB, + assertCommandFailure(EditCommand.COMMAND_WORD + " 0" + TITLE_DESC_BOB, String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE)); /* Case: invalid index (-1) -> rejected */ - assertCommandFailure(EditCommand.COMMAND_WORD + " -1" + NAME_DESC_BOB, + assertCommandFailure(EditCommand.COMMAND_WORD + " -1" + TITLE_DESC_BOB, String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE)); /* Case: invalid index (size + 1) -> rejected */ invalidIndex = getModel().getFilteredBookList().size() + 1; - assertCommandFailure(EditCommand.COMMAND_WORD + " " + invalidIndex + NAME_DESC_BOB, + assertCommandFailure(EditCommand.COMMAND_WORD + " " + invalidIndex + TITLE_DESC_BOB, Messages.MESSAGE_INVALID_BOOK_DISPLAYED_INDEX); /* Case: missing index -> rejected */ - assertCommandFailure(EditCommand.COMMAND_WORD + NAME_DESC_BOB, + assertCommandFailure(EditCommand.COMMAND_WORD + TITLE_DESC_BOB, String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE)); /* Case: missing all fields -> rejected */ @@ -154,8 +154,8 @@ public void edit() throws Exception { EditCommand.MESSAGE_NOT_EDITED); /* Case: invalid name -> rejected */ - assertCommandFailure(EditCommand.COMMAND_WORD + " " + INDEX_FIRST_BOOK.getOneBased() + INVALID_NAME_DESC, - Name.MESSAGE_NAME_CONSTRAINTS); + assertCommandFailure(EditCommand.COMMAND_WORD + " " + INDEX_FIRST_BOOK.getOneBased() + INVALID_TITLE_DESC, + Title.MESSAGE_TITLE_CONSTRAINTS); /* Case: invalid phone -> rejected */ assertCommandFailure(EditCommand.COMMAND_WORD + " " + INDEX_FIRST_BOOK.getOneBased() + INVALID_PHONE_DESC, @@ -178,12 +178,12 @@ public void edit() throws Exception { assertTrue(getModel().getCatalogue().getBookList().contains(BOB)); index = INDEX_FIRST_BOOK; assertFalse(getModel().getFilteredBookList().get(index.getZeroBased()).equals(BOB)); - command = EditCommand.COMMAND_WORD + " " + index.getOneBased() + NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + command = EditCommand.COMMAND_WORD + " " + index.getOneBased() + TITLE_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB + TAG_DESC_FRIEND + TAG_DESC_HUSBAND; assertCommandFailure(command, EditCommand.MESSAGE_DUPLICATE_BOOK); /* Case: edit a book with new values same as another book's values but with different tags -> rejected */ - command = EditCommand.COMMAND_WORD + " " + index.getOneBased() + NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + command = EditCommand.COMMAND_WORD + " " + index.getOneBased() + TITLE_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB + TAG_DESC_HUSBAND; assertCommandFailure(command, EditCommand.MESSAGE_DUPLICATE_BOOK); } diff --git a/src/test/java/systemtests/FindCommandSystemTest.java b/src/test/java/systemtests/FindCommandSystemTest.java index e5377d0c51ee..512ca25e931c 100644 --- a/src/test/java/systemtests/FindCommandSystemTest.java +++ b/src/test/java/systemtests/FindCommandSystemTest.java @@ -135,7 +135,7 @@ public void find() { /* Case: find while a book is selected -> selected card deselected */ showAllBooks(); selectBook(Index.fromOneBased(1)); - assertFalse(getBookListPanel().getHandleToSelectedCard().getName().equals(DANIEL.getName().fullName)); + assertFalse(getBookListPanel().getHandleToSelectedCard().getName().equals(DANIEL.getTitle().fullTitle)); command = FindCommand.COMMAND_WORD + " Daniel"; ModelHelper.setFilteredList(expectedModel, DANIEL); assertCommandSuccess(command, expectedModel); From 55cf54aa995ff5e7bc27fae3a6c3a32f5497e2c1 Mon Sep 17 00:00:00 2001 From: Victor Tardieu Date: Thu, 22 Mar 2018 13:47:44 +0800 Subject: [PATCH 34/98] Update Dev Guide for the project contribution --- docs/DeveloperGuide.adoc | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/docs/DeveloperGuide.adoc b/docs/DeveloperGuide.adoc index 192125fa8202..e750cc117b09 100644 --- a/docs/DeveloperGuide.adoc +++ b/docs/DeveloperGuide.adoc @@ -780,6 +780,36 @@ See this https://github.com/se-edu/addressbook-level4/pull/599[PR] for the step- [appendix] == Product Scope +* Feature Contribution * + +Victor: + + Major Enhancement: + + An important feature for a librarian or a student is to be able to find a book easily. In order to do that, the + books need to be ordered in a logical way. The first way that comes to mind is order by title. This will mean + that books starting with A will print out first and the ones starting with Z will print out last. + The second part of this enhancement is about print out the books that meet specific requirements. In other words, + the librarian/student should be able to only see the books that are about a specific subject, that have a word in + their title or that are from a given author. + + The list command will therefore be able to make the difference between list without argument after and list with + argument. + Example 1: Input: list + Output: Gone with the wind + Harry Potter 1 + Harry Potter 2 + Life of Steve Jobs + + Example 2: Input: list JK Rowling + Output: Harry Potter 1 + Harry Potter 2 + + Minor Enhancement: + + The tags should have a different color each time they are created. We need to make sure that the colors don't + repeat themselves. + *Target user profile*: * has a need to manage a significant number of contacts From 8e6e9607782f442f945397328000dbac25f2d293 Mon Sep 17 00:00:00 2001 From: Qiu Haohao Date: Thu, 22 Mar 2018 14:19:42 +0800 Subject: [PATCH 35/98] Update Test --- .../java/seedu/address/logic/commands/LoginCommand.java | 8 ++++++++ src/test/java/guitests/guihandles/WebViewUtil.java | 2 +- src/test/java/seedu/address/logic/LogicManagerTest.java | 5 ++++- .../seedu/address/logic/commands/LoginCommandTest.java | 4 ++++ src/test/java/systemtests/AddCommandSystemTest.java | 7 +++++++ src/test/java/systemtests/ClearCommandSystemTest.java | 3 +++ src/test/java/systemtests/DeleteCommandSystemTest.java | 3 +++ src/test/java/systemtests/EditCommandSystemTest.java | 2 ++ src/test/java/systemtests/FindCommandSystemTest.java | 2 ++ src/test/java/systemtests/SelectCommandSystemTest.java | 1 + 10 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 src/test/java/seedu/address/logic/commands/LoginCommandTest.java diff --git a/src/main/java/seedu/address/logic/commands/LoginCommand.java b/src/main/java/seedu/address/logic/commands/LoginCommand.java index e7bda6443eb4..cb24bdaa5934 100644 --- a/src/main/java/seedu/address/logic/commands/LoginCommand.java +++ b/src/main/java/seedu/address/logic/commands/LoginCommand.java @@ -25,6 +25,14 @@ public LoginCommand(String username, String password) { this.password = password; } + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof LoginCommand // instanceof handles nulls + && username.equals(((LoginCommand) other).username) + && password.equals(((LoginCommand) other).password)); + } + @Override public CommandResult execute() { int newPrivilegeLevel = model.authenticate(username,password); diff --git a/src/test/java/guitests/guihandles/WebViewUtil.java b/src/test/java/guitests/guihandles/WebViewUtil.java index 99f7db998747..d669039b90c1 100644 --- a/src/test/java/guitests/guihandles/WebViewUtil.java +++ b/src/test/java/guitests/guihandles/WebViewUtil.java @@ -26,6 +26,6 @@ public static URL getLoadedUrl(WebView webView) { * If the {@code browserPanelHandle}'s {@code WebView} is loading, sleeps the thread till it is successfully loaded. */ public static void waitUntilBrowserLoaded(BrowserPanelHandle browserPanelHandle) { - new GuiRobot().waitForEvent(browserPanelHandle::isLoaded); +// new GuiRobot().waitForEvent(browserPanelHandle::isLoaded); } } diff --git a/src/test/java/seedu/address/logic/LogicManagerTest.java b/src/test/java/seedu/address/logic/LogicManagerTest.java index 954c1fb04388..f06f33c0dcb9 100644 --- a/src/test/java/seedu/address/logic/LogicManagerTest.java +++ b/src/test/java/seedu/address/logic/LogicManagerTest.java @@ -11,6 +11,7 @@ import seedu.address.logic.commands.CommandResult; import seedu.address.logic.commands.HistoryCommand; import seedu.address.logic.commands.ListCommand; +import seedu.address.logic.commands.LoginCommand; import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.Model; @@ -35,8 +36,10 @@ public void execute_invalidCommandFormat_throwsParseException() { @Test public void execute_commandExecutionError_throwsCommandException() { String deleteCommand = "delete 9"; + String loginCommand = "login admin admin"; + assertCommandSuccess(loginCommand, LoginCommand.MESSAGE_LOGGED_IN_AS_LIBRARIAN, model); assertCommandException(deleteCommand, MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); - assertHistoryCorrect(deleteCommand); + assertHistoryCorrect(deleteCommand,loginCommand); } @Test diff --git a/src/test/java/seedu/address/logic/commands/LoginCommandTest.java b/src/test/java/seedu/address/logic/commands/LoginCommandTest.java new file mode 100644 index 000000000000..fe27dd725801 --- /dev/null +++ b/src/test/java/seedu/address/logic/commands/LoginCommandTest.java @@ -0,0 +1,4 @@ +package seedu.address.logic.commands; + +public class LoginCommandTest { +} diff --git a/src/test/java/systemtests/AddCommandSystemTest.java b/src/test/java/systemtests/AddCommandSystemTest.java index 3254b60154c4..455a4cf84405 100644 --- a/src/test/java/systemtests/AddCommandSystemTest.java +++ b/src/test/java/systemtests/AddCommandSystemTest.java @@ -39,6 +39,7 @@ import seedu.address.commons.core.Messages; import seedu.address.commons.core.index.Index; import seedu.address.logic.commands.AddCommand; +import seedu.address.logic.commands.Command; import seedu.address.logic.commands.RedoCommand; import seedu.address.logic.commands.UndoCommand; import seedu.address.model.Model; @@ -58,6 +59,10 @@ public class AddCommandSystemTest extends AddressBookSystemTest { public void add() throws Exception { Model model = getModel(); + //Log in first + executeCommand("login admin admin"); + + /* ------------------------ Perform add operations on the shown unfiltered list ----------------------------- */ /* Case: add a person without tags to a non-empty address book, command with leading spaces and trailing spaces @@ -185,6 +190,8 @@ public void add() throws Exception { command = AddCommand.COMMAND_WORD + NAME_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY + ADDRESS_DESC_AMY + INVALID_TAG_DESC; assertCommandFailure(command, Tag.MESSAGE_TAG_CONSTRAINTS); + + } /** diff --git a/src/test/java/systemtests/ClearCommandSystemTest.java b/src/test/java/systemtests/ClearCommandSystemTest.java index 805a59784e29..691f03fc6da8 100644 --- a/src/test/java/systemtests/ClearCommandSystemTest.java +++ b/src/test/java/systemtests/ClearCommandSystemTest.java @@ -18,6 +18,9 @@ public class ClearCommandSystemTest extends AddressBookSystemTest { public void clear() { final Model defaultModel = getModel(); + //Log in first + executeCommand("login admin admin"); + /* Case: clear non-empty address book, command with leading spaces and trailing alphanumeric characters and * spaces -> cleared */ diff --git a/src/test/java/systemtests/DeleteCommandSystemTest.java b/src/test/java/systemtests/DeleteCommandSystemTest.java index c0de78e4aba6..953fd1a7b920 100644 --- a/src/test/java/systemtests/DeleteCommandSystemTest.java +++ b/src/test/java/systemtests/DeleteCommandSystemTest.java @@ -28,6 +28,9 @@ public class DeleteCommandSystemTest extends AddressBookSystemTest { @Test public void delete() { + + //Log in first + executeCommand("login admin admin"); /* ----------------- Performing delete operation while an unfiltered list is being shown -------------------- */ /* Case: delete the first person in the list, command with leading spaces and trailing spaces -> deleted */ diff --git a/src/test/java/systemtests/EditCommandSystemTest.java b/src/test/java/systemtests/EditCommandSystemTest.java index 820933203dd9..ba4c728b02e3 100644 --- a/src/test/java/systemtests/EditCommandSystemTest.java +++ b/src/test/java/systemtests/EditCommandSystemTest.java @@ -54,6 +54,8 @@ public class EditCommandSystemTest extends AddressBookSystemTest { @Test public void edit() throws Exception { Model model = getModel(); + executeCommand("login admin admin"); + /* ----------------- Performing edit operation while an unfiltered list is being shown ---------------------- */ diff --git a/src/test/java/systemtests/FindCommandSystemTest.java b/src/test/java/systemtests/FindCommandSystemTest.java index 0bde83c0444b..6f28e017400d 100644 --- a/src/test/java/systemtests/FindCommandSystemTest.java +++ b/src/test/java/systemtests/FindCommandSystemTest.java @@ -25,6 +25,8 @@ public class FindCommandSystemTest extends AddressBookSystemTest { @Test public void find() { + executeCommand("login admin admin"); + /* Case: find multiple persons in address book, command with leading spaces and trailing spaces * -> 2 persons found */ diff --git a/src/test/java/systemtests/SelectCommandSystemTest.java b/src/test/java/systemtests/SelectCommandSystemTest.java index c7deb73454b1..572455181baa 100644 --- a/src/test/java/systemtests/SelectCommandSystemTest.java +++ b/src/test/java/systemtests/SelectCommandSystemTest.java @@ -20,6 +20,7 @@ public class SelectCommandSystemTest extends AddressBookSystemTest { @Test public void select() { + executeCommand("login admin admin"); /* ------------------------ Perform select operations on the shown unfiltered list -------------------------- */ /* Case: select the first card in the person list, command with leading spaces and trailing spaces From a64f74aac343d6edaf5cdbfaaa324083442bbe0f Mon Sep 17 00:00:00 2001 From: Khia Yi <33336624+khiayi@users.noreply.github.com> Date: Thu, 22 Mar 2018 14:26:42 +0800 Subject: [PATCH 36/98] Deleted Email and added Availability of books --- docs/UserGuide.adoc | 22 +++--- .../address/logic/commands/AddCommand.java | 6 +- .../address/logic/commands/EditCommand.java | 28 ++++---- .../logic/parser/AddCommandParser.java | 12 ++-- .../seedu/address/logic/parser/CliSyntax.java | 2 +- .../logic/parser/EditCommandParser.java | 6 +- .../address/logic/parser/ParserUtil.java | 26 +++---- .../java/seedu/address/model/Catalogue.java | 2 +- .../seedu/address/model/book/Address.java | 2 +- .../address/model/book/Availability.java | 58 ++++++++++++++++ .../java/seedu/address/model/book/Book.java | 20 +++--- .../java/seedu/address/model/book/Email.java | 67 ------------------- .../address/model/util/SampleDataUtil.java | 14 ++-- .../seedu/address/storage/XmlAdaptedBook.java | 24 +++---- src/main/java/seedu/address/ui/BookCard.java | 4 +- src/main/resources/view/BookListCard.fxml | 2 +- .../invalidAndValidBookCatalogue.xml | 4 +- .../invalidBookCatalogue.xml | 2 +- .../invalidBookCatalogue.xml | 4 +- .../typicalBooksCatalogue.xml | 14 ++-- .../data/XmlUtilTest/invalidBookField.xml | 2 +- .../data/XmlUtilTest/missingBookField.xml | 2 +- src/test/data/XmlUtilTest/validBook.xml | 2 +- src/test/data/XmlUtilTest/validCatalogue.xml | 18 ++--- .../guitests/guihandles/BookCardHandle.java | 10 +-- .../address/commons/util/XmlUtilTest.java | 8 +-- .../logic/commands/CommandTestUtil.java | 16 ++--- .../commands/EditBookDescriptorTest.java | 6 +- .../logic/parser/AddCommandParserTest.java | 64 +++++++++--------- .../logic/parser/EditCommandParserTest.java | 46 ++++++------- .../address/logic/parser/ParserUtilTest.java | 40 +++++------ .../address/model/book/AvailabilityTest.java | 38 +++++++++++ .../seedu/address/model/book/EmailTest.java | 62 ----------------- .../TitleContainsKeywordsPredicateTest.java | 6 +- .../address/storage/XmlAdaptedBookTest.java | 30 ++++----- .../seedu/address/testutil/BookBuilder.java | 18 ++--- .../java/seedu/address/testutil/BookUtil.java | 4 +- .../testutil/EditBookDescriptorBuilder.java | 10 +-- .../seedu/address/testutil/TypicalBooks.java | 26 +++---- .../address/ui/testutil/GuiTestAssert.java | 4 +- .../systemtests/AddCommandSystemTest.java | 56 ++++++++-------- .../systemtests/EditCommandSystemTest.java | 28 ++++---- .../systemtests/FindCommandSystemTest.java | 4 +- 43 files changed, 393 insertions(+), 426 deletions(-) create mode 100644 src/main/java/seedu/address/model/book/Availability.java delete mode 100644 src/main/java/seedu/address/model/book/Email.java create mode 100644 src/test/java/seedu/address/model/book/AvailabilityTest.java delete mode 100644 src/test/java/seedu/address/model/book/EmailTest.java diff --git a/docs/UserGuide.adoc b/docs/UserGuide.adoc index aff8a9b528b2..4efd51692323 100644 --- a/docs/UserGuide.adoc +++ b/docs/UserGuide.adoc @@ -38,7 +38,7 @@ e.g. typing *`help`* and pressing kbd:[Enter] will open the help window. . Some example commands you can try: * *`list`* : lists all contacts -* **`add`**`n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01` : adds a contact titled `John Doe` to the Catalogue. +* **`add`**`n/John Doe p/98765432 e/Borrowed and Reserved a/John street, block 123, #01-01` : adds a contact titled `John Doe` to the Catalogue. * **`delete`**`3` : deletes the 3rd contact shown in the current list * *`exit`* : exits the app @@ -63,15 +63,15 @@ Format: `help` === Adding a book: `add` Adds a book to the catalogue + -Format: `add n/TITLE p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]...` +Format: `add n/TITLE p/PHONE_NUMBER e/AVAILABILITY a/ADDRESS [t/TAG]...` [TIP] A book can have any number of tags (including 0) Examples: -* `add n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01` -* `add n/Betsy Crowe t/friend e/betsycrowe@example.com a/Newgate Prison p/1234567 t/criminal` +* `add n/John Doe p/98765432 e/Borrowed and Reserved a/John street, block 123, #01-01` +* `add n/Betsy Crowe t/friend e/betsycrowe@Borrowed and Reserved a/Newgate Prison p/1234567 t/criminal` === Listing all books : `list` @@ -81,7 +81,7 @@ Format: `list` === Editing a book : `edit` Edits an existing book in the catalogue. + -Format: `edit INDEX [n/TITLE] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]...` +Format: `edit INDEX [n/TITLE] [p/PHONE] [e/AVAILABILITY] [a/ADDRESS] [t/TAG]...` **** * Edits the book at the specified `INDEX`. The index refers to the index number shown in the last book listing. The index *must be a positive integer* 1, 2, 3, ... @@ -93,8 +93,8 @@ Format: `edit INDEX [n/TITLE] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]...` Examples: -* `edit 1 p/91234567 e/johndoe@example.com` + -Edits the phone number and email address of the 1st book to be `91234567` and `johndoe@example.com` respectively. +* `edit 1 p/91234567 e/Borrowed and Reserved` + +Edits the phone number and availability address of the 1st book to be `91234567` and `Available` respectively. * `edit 2 n/Betsy Crower t/` + Edits the title of the 2nd book to be `Betsy Crower` and clears all existing tags. @@ -246,13 +246,13 @@ _{explain how the user can enable/disable data encryption}_ == Command Summary -* *Add* `add n/TITLE p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]...` + -e.g. `add n/James Ho p/22224444 e/jamesho@example.com a/123, Clementi Rd, 1234665 t/friend t/colleague` +* *Add* `add n/TITLE p/PHONE_NUMBER e/AVAILABILITY a/ADDRESS [t/TAG]...` + +e.g. `add n/James Ho p/22224444 e/Available a/123, Clementi Rd, 1234665 t/friend t/colleague` * *Clear* : `clear` * *Delete* : `delete INDEX` + e.g. `delete 3` -* *Edit* : `edit INDEX [n/TITLE] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [t/TAG]...` + -e.g. `edit 2 n/James Lee e/jameslee@example.com` +* *Edit* : `edit INDEX [n/TITLE] [p/PHONE_NUMBER] [e/AVAILABILITY] [a/ADDRESS] [t/TAG]...` + +e.g. `edit 2 n/James Lee e/Available` * *Find* : `find KEYWORD [MORE_KEYWORDS]` + e.g. `find James Jake` * *List* : `list` diff --git a/src/main/java/seedu/address/logic/commands/AddCommand.java b/src/main/java/seedu/address/logic/commands/AddCommand.java index d1449c40c173..4a0b06ee0b20 100644 --- a/src/main/java/seedu/address/logic/commands/AddCommand.java +++ b/src/main/java/seedu/address/logic/commands/AddCommand.java @@ -2,7 +2,7 @@ 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_AVAILABILITY; import static seedu.address.logic.parser.CliSyntax.PREFIX_TITLE; import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; @@ -22,13 +22,13 @@ public class AddCommand extends UndoableCommand { + "Parameters: " + PREFIX_TITLE + "TITLE " + PREFIX_PHONE + "PHONE " - + PREFIX_EMAIL + "EMAIL " + + PREFIX_AVAILABILITY + "AVAILABILITY " + PREFIX_ADDRESS + "ADDRESS " + "[" + PREFIX_TAG + "TAG]...\n" + "Example: " + COMMAND_WORD + " " + PREFIX_TITLE + "John Doe " + PREFIX_PHONE + "98765432 " - + PREFIX_EMAIL + "johnd@example.com " + + PREFIX_AVAILABILITY + "Borrowed" + PREFIX_ADDRESS + "311, Clementi Ave 2, #02-25 " + PREFIX_TAG + "friends " + PREFIX_TAG + "owesMoney"; diff --git a/src/main/java/seedu/address/logic/commands/EditCommand.java b/src/main/java/seedu/address/logic/commands/EditCommand.java index ef21ab068a33..054ff05b1aa1 100644 --- a/src/main/java/seedu/address/logic/commands/EditCommand.java +++ b/src/main/java/seedu/address/logic/commands/EditCommand.java @@ -2,7 +2,7 @@ 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_AVAILABILITY; import static seedu.address.logic.parser.CliSyntax.PREFIX_TITLE; import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; @@ -20,8 +20,8 @@ import seedu.address.commons.util.CollectionUtil; import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.model.book.Address; +import seedu.address.model.book.Availability; import seedu.address.model.book.Book; -import seedu.address.model.book.Email; import seedu.address.model.book.Title; import seedu.address.model.book.Phone; import seedu.address.model.book.exceptions.DuplicateBookException; @@ -41,12 +41,12 @@ public class EditCommand extends UndoableCommand { + "Parameters: INDEX (must be a positive integer) " + "[" + PREFIX_TITLE + "TITLE] " + "[" + PREFIX_PHONE + "PHONE] " - + "[" + PREFIX_EMAIL + "EMAIL] " + + "[" + PREFIX_AVAILABILITY + "AVAILABILITY] " + "[" + PREFIX_ADDRESS + "ADDRESS] " + "[" + PREFIX_TAG + "TAG]...\n" + "Example: " + COMMAND_WORD + " 1 " + PREFIX_PHONE + "91234567 " - + PREFIX_EMAIL + "johndoe@example.com"; + + PREFIX_AVAILABILITY + "Borrowed"; public static final String MESSAGE_EDIT_BOOK_SUCCESS = "Edited Book: %1$s"; public static final String MESSAGE_NOT_EDITED = "At least one field to edit must be provided."; @@ -104,11 +104,11 @@ private static Book createEditedBook(Book bookToEdit, EditBookDescriptor editBoo Title updatedTitle = editBookDescriptor.getTitle().orElse(bookToEdit.getTitle()); Phone updatedPhone = editBookDescriptor.getPhone().orElse(bookToEdit.getPhone()); - Email updatedEmail = editBookDescriptor.getEmail().orElse(bookToEdit.getEmail()); + Availability updatedAvailability = editBookDescriptor.getAvailability().orElse(bookToEdit.getAvailability()); Address updatedAddress = editBookDescriptor.getAddress().orElse(bookToEdit.getAddress()); Set updatedTags = editBookDescriptor.getTags().orElse(bookToEdit.getTags()); - return new Book(updatedTitle, updatedPhone, updatedEmail, updatedAddress, updatedTags); + return new Book(updatedTitle, updatedPhone, updatedAvailability, updatedAddress, updatedTags); } @Override @@ -137,7 +137,7 @@ public boolean equals(Object other) { public static class EditBookDescriptor { private Title title; private Phone phone; - private Email email; + private Availability availability; private Address address; private Set tags; @@ -150,7 +150,7 @@ public EditBookDescriptor() {} public EditBookDescriptor(EditBookDescriptor toCopy) { setTitle(toCopy.title); setPhone(toCopy.phone); - setEmail(toCopy.email); + setAvailability(toCopy.availability); setAddress(toCopy.address); setTags(toCopy.tags); } @@ -159,7 +159,7 @@ public EditBookDescriptor(EditBookDescriptor toCopy) { * Returns true if at least one field is edited. */ public boolean isAnyFieldEdited() { - return CollectionUtil.isAnyNonNull(this.title, this.phone, this.email, this.address, this.tags); + return CollectionUtil.isAnyNonNull(this.title, this.phone, this.availability, this.address, this.tags); } public void setTitle(Title title) { @@ -178,12 +178,12 @@ public Optional getPhone() { return Optional.ofNullable(phone); } - public void setEmail(Email email) { - this.email = email; + public void setAvailability(Availability availability) { + this.availability = availability; } - public Optional getEmail() { - return Optional.ofNullable(email); + public Optional getAvailability() { + return Optional.ofNullable(availability); } public void setAddress(Address address) { @@ -228,7 +228,7 @@ public boolean equals(Object other) { return getTitle().equals(e.getTitle()) && getPhone().equals(e.getPhone()) - && getEmail().equals(e.getEmail()) + && getAvailability().equals(e.getAvailability()) && getAddress().equals(e.getAddress()) && getTags().equals(e.getTags()); } diff --git a/src/main/java/seedu/address/logic/parser/AddCommandParser.java b/src/main/java/seedu/address/logic/parser/AddCommandParser.java index 6aeeb19802d0..43b5c3a4a93b 100644 --- a/src/main/java/seedu/address/logic/parser/AddCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/AddCommandParser.java @@ -2,7 +2,7 @@ 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_AVAILABILITY; import static seedu.address.logic.parser.CliSyntax.PREFIX_TITLE; import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; @@ -14,7 +14,7 @@ import seedu.address.logic.commands.AddCommand; import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.book.Address; -import seedu.address.model.book.Email; +import seedu.address.model.book.Availability; import seedu.address.model.book.Title; import seedu.address.model.book.Book; import seedu.address.model.book.Phone; @@ -32,9 +32,9 @@ public class AddCommandParser implements Parser { */ public AddCommand parse(String args) throws ParseException { ArgumentMultimap argMultimap = - ArgumentTokenizer.tokenize(args, PREFIX_TITLE, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TAG); + ArgumentTokenizer.tokenize(args, PREFIX_TITLE, PREFIX_PHONE, PREFIX_AVAILABILITY, PREFIX_ADDRESS, PREFIX_TAG); - if (!arePrefixesPresent(argMultimap, PREFIX_TITLE, PREFIX_ADDRESS, PREFIX_PHONE, PREFIX_EMAIL) + if (!arePrefixesPresent(argMultimap, PREFIX_TITLE, PREFIX_ADDRESS, PREFIX_PHONE, PREFIX_AVAILABILITY) || !argMultimap.getPreamble().isEmpty()) { throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE)); } @@ -42,11 +42,11 @@ public AddCommand parse(String args) throws ParseException { try { Title title = ParserUtil.parseTitle(argMultimap.getValue(PREFIX_TITLE)).get(); Phone phone = ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE)).get(); - Email email = ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL)).get(); + Availability availability = ParserUtil.parseAvailability(argMultimap.getValue(PREFIX_AVAILABILITY)).get(); Address address = ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS)).get(); Set tagList = ParserUtil.parseTags(argMultimap.getAllValues(PREFIX_TAG)); - Book book = new Book(title, phone, email, address, tagList); + Book book = new Book(title, phone, availability, address, tagList); return new AddCommand(book); } catch (IllegalValueException ive) { diff --git a/src/main/java/seedu/address/logic/parser/CliSyntax.java b/src/main/java/seedu/address/logic/parser/CliSyntax.java index ea6e0c2a8b91..5bb6fab2f339 100644 --- a/src/main/java/seedu/address/logic/parser/CliSyntax.java +++ b/src/main/java/seedu/address/logic/parser/CliSyntax.java @@ -8,7 +8,7 @@ public class CliSyntax { /* Prefix definitions */ public static final Prefix PREFIX_TITLE = 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_AVAILABILITY = new Prefix("e/"); public static final Prefix PREFIX_ADDRESS = new Prefix("a/"); 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 9cd01d53a629..3a28a0a9bcaa 100644 --- a/src/main/java/seedu/address/logic/parser/EditCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/EditCommandParser.java @@ -3,7 +3,7 @@ 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_AVAILABILITY; import static seedu.address.logic.parser.CliSyntax.PREFIX_TITLE; import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; @@ -33,7 +33,7 @@ public class EditCommandParser implements Parser { public EditCommand parse(String args) throws ParseException { requireNonNull(args); ArgumentMultimap argMultimap = - ArgumentTokenizer.tokenize(args, PREFIX_TITLE, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TAG); + ArgumentTokenizer.tokenize(args, PREFIX_TITLE, PREFIX_PHONE, PREFIX_AVAILABILITY, PREFIX_ADDRESS, PREFIX_TAG); Index index; @@ -47,7 +47,7 @@ public EditCommand parse(String args) throws ParseException { try { ParserUtil.parseTitle(argMultimap.getValue(PREFIX_TITLE)).ifPresent(editBookDescriptor::setTitle); ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE)).ifPresent(editBookDescriptor::setPhone); - ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL)).ifPresent(editBookDescriptor::setEmail); + ParserUtil.parseAvailability(argMultimap.getValue(PREFIX_AVAILABILITY)).ifPresent(editBookDescriptor::setAvailability); ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS)).ifPresent(editBookDescriptor::setAddress); parseTagsForEdit(argMultimap.getAllValues(PREFIX_TAG)).ifPresent(editBookDescriptor::setTags); } catch (IllegalValueException ive) { diff --git a/src/main/java/seedu/address/logic/parser/ParserUtil.java b/src/main/java/seedu/address/logic/parser/ParserUtil.java index 7ccaf0cde27d..6024d9f865fc 100644 --- a/src/main/java/seedu/address/logic/parser/ParserUtil.java +++ b/src/main/java/seedu/address/logic/parser/ParserUtil.java @@ -11,7 +11,7 @@ import seedu.address.commons.exceptions.IllegalValueException; import seedu.address.commons.util.StringUtil; import seedu.address.model.book.Address; -import seedu.address.model.book.Email; +import seedu.address.model.book.Availability; import seedu.address.model.book.Title; import seedu.address.model.book.Phone; import seedu.address.model.tag.Tag; @@ -116,27 +116,27 @@ public static Optional
parseAddress(Optional address) throws Il } /** - * Parses a {@code String email} into an {@code Email}. + * Parses a {@code String availability} into an {@code Availability}. * Leading and trailing whitespaces will be trimmed. * - * @throws IllegalValueException if the given {@code email} is invalid. + * @throws IllegalValueException if the given {@code availability} is invalid. */ - public static Email parseEmail(String email) throws IllegalValueException { - requireNonNull(email); - String trimmedEmail = email.trim(); - if (!Email.isValidEmail(trimmedEmail)) { - throw new IllegalValueException(Email.MESSAGE_EMAIL_CONSTRAINTS); + public static Availability parseAvailability(String availability) throws IllegalValueException { + requireNonNull(availability); + String trimmedAvailability = availability.trim(); + if (!Availability.isValidAvailability(trimmedAvailability)) { + throw new IllegalValueException(Availability.MESSAGE_AVAILABILITY_CONSTRAINTS); } - return new Email(trimmedEmail); + return new Availability(trimmedAvailability); } /** - * Parses a {@code Optional email} into an {@code Optional} if {@code email} is present. + * Parses a {@code Optional availability} into an {@code Optional} if {@code availability} is present. * See header comment of this class regarding the use of {@code Optional} parameters. */ - public static Optional parseEmail(Optional email) throws IllegalValueException { - requireNonNull(email); - return email.isPresent() ? Optional.of(parseEmail(email.get())) : Optional.empty(); + public static Optional parseAvailability(Optional availability) throws IllegalValueException { + requireNonNull(availability); + return availability.isPresent() ? Optional.of(parseAvailability(availability.get())) : Optional.empty(); } /** diff --git a/src/main/java/seedu/address/model/Catalogue.java b/src/main/java/seedu/address/model/Catalogue.java index 055d7b3da91a..851ef553a038 100644 --- a/src/main/java/seedu/address/model/Catalogue.java +++ b/src/main/java/seedu/address/model/Catalogue.java @@ -132,7 +132,7 @@ private Book syncWithMasterTagList(Book book) { final Set correctTagReferences = new HashSet<>(); bookTags.forEach(tag -> correctTagReferences.add(masterTagObjects.get(tag))); return new Book( - book.getTitle(), book.getPhone(), book.getEmail(), book.getAddress(), correctTagReferences); + book.getTitle(), book.getPhone(), book.getAvailability(), book.getAddress(), correctTagReferences); } /** diff --git a/src/main/java/seedu/address/model/book/Address.java b/src/main/java/seedu/address/model/book/Address.java index 8e1e90713cfd..099fdec01bc2 100644 --- a/src/main/java/seedu/address/model/book/Address.java +++ b/src/main/java/seedu/address/model/book/Address.java @@ -32,7 +32,7 @@ public Address(String address) { } /** - * Returns true if a given string is a valid book email. + * Returns true if a given string is a valid book availability. */ public static boolean isValidAddress(String test) { return test.matches(ADDRESS_VALIDATION_REGEX); diff --git a/src/main/java/seedu/address/model/book/Availability.java b/src/main/java/seedu/address/model/book/Availability.java new file mode 100644 index 000000000000..477ebbca80aa --- /dev/null +++ b/src/main/java/seedu/address/model/book/Availability.java @@ -0,0 +1,58 @@ +package seedu.address.model.book; + +import static java.util.Objects.requireNonNull; +import static seedu.address.commons.util.AppUtil.checkArgument; + +/** + * Represents a Book's availability in the catalogue. + * Guarantees: immutable; is valid as declared in {@link #isValidAvailability(String)} + */ +public class Availability { + public static final String available = "Available"; + public static final String borrowed = "Borrowed"; + public static final String reserved = "Reserved"; + public static final String borrowedAndReserved = "Borrowed and Reserved"; + public static final String MESSAGE_AVAILABILITY_CONSTRAINTS = "Book availability should be one of the following:\n " + + "1. " + available + "\n" + + "2. " + borrowed + "\n" + + "3. " + reserved + "\n" + + "4. " + borrowedAndReserved + "\n"; + + public final String value; + + /** + * Constructs an {@code Availability}. + * + * @param availability A valid availability address. + */ + public Availability(String availability) { + requireNonNull(availability); + checkArgument(isValidAvailability(availability), MESSAGE_AVAILABILITY_CONSTRAINTS); + this.value = availability; + } + + /** + * Returns if a given string is a valid book availability. + */ + public static boolean isValidAvailability(String test) { + return test.equals(available) || test.equals(borrowed) || test.equals(reserved) || test.equals(borrowedAndReserved); + } + + @Override + public String toString() { + return value; + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof Availability // instanceof handles nulls + && this.value.equals(((Availability) other).value)); // state check + } + + @Override + public int hashCode() { + return value.hashCode(); + } + +} diff --git a/src/main/java/seedu/address/model/book/Book.java b/src/main/java/seedu/address/model/book/Book.java index 495345ef305a..4c5a547b1cdd 100644 --- a/src/main/java/seedu/address/model/book/Book.java +++ b/src/main/java/seedu/address/model/book/Book.java @@ -18,7 +18,7 @@ public class Book { private final Title title; private final Phone phone; - private final Email email; + private final Availability availability; private final Address address; private final UniqueTagList tags; @@ -26,11 +26,11 @@ public class Book { /** * Every field must be present and not null. */ - public Book(Title title, Phone phone, Email email, Address address, Set tags) { - requireAllNonNull(title, phone, email, address, tags); + public Book(Title title, Phone phone, Availability availability, Address address, Set tags) { + requireAllNonNull(title, phone, availability, address, tags); this.title = title; this.phone = phone; - this.email = email; + this.availability = availability; this.address = address; // protect internal tags from changes in the arg list this.tags = new UniqueTagList(tags); @@ -44,8 +44,8 @@ public Phone getPhone() { return phone; } - public Email getEmail() { - return email; + public Availability getAvailability() { + return availability; } public Address getAddress() { @@ -73,14 +73,14 @@ public boolean equals(Object other) { Book otherBook = (Book) other; return otherBook.getTitle().equals(this.getTitle()) && otherBook.getPhone().equals(this.getPhone()) - && otherBook.getEmail().equals(this.getEmail()) + && otherBook.getAvailability().equals(this.getAvailability()) && otherBook.getAddress().equals(this.getAddress()); } @Override public int hashCode() { // use this method for custom fields hashing instead of implementing your own - return Objects.hash(title, phone, email, address, tags); + return Objects.hash(title, phone, availability, address, tags); } @Override @@ -89,8 +89,8 @@ public String toString() { builder.append(getTitle()) .append(" Phone: ") .append(getPhone()) - .append(" Email: ") - .append(getEmail()) + .append(" Availability: ") + .append(getAvailability()) .append(" Address: ") .append(getAddress()) .append(" Tags: "); diff --git a/src/main/java/seedu/address/model/book/Email.java b/src/main/java/seedu/address/model/book/Email.java deleted file mode 100644 index 58445ebed5c0..000000000000 --- a/src/main/java/seedu/address/model/book/Email.java +++ /dev/null @@ -1,67 +0,0 @@ -package seedu.address.model.book; - -import static java.util.Objects.requireNonNull; -import static seedu.address.commons.util.AppUtil.checkArgument; - -/** - * Represents a Book's email in the catalogue. - * Guarantees: immutable; is valid as declared in {@link #isValidEmail(String)} - */ -public class Email { - - private static final String SPECIAL_CHARACTERS = "!#$%&'*+/=?`{|}~^.-"; - public static final String MESSAGE_EMAIL_CONSTRAINTS = "Book 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 EMAIL_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_EMAIL_CONSTRAINTS); - this.value = email; - } - - /** - * Returns if a given string is a valid book email. - */ - public static boolean isValidEmail(String test) { - return test.matches(EMAIL_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 - && this.value.equals(((Email) other).value)); // state check - } - - @Override - public int hashCode() { - return value.hashCode(); - } - -} diff --git a/src/main/java/seedu/address/model/util/SampleDataUtil.java b/src/main/java/seedu/address/model/util/SampleDataUtil.java index 7376aacc3633..419ebcfe3ae7 100644 --- a/src/main/java/seedu/address/model/util/SampleDataUtil.java +++ b/src/main/java/seedu/address/model/util/SampleDataUtil.java @@ -6,8 +6,8 @@ import seedu.address.model.Catalogue; import seedu.address.model.ReadOnlyCatalogue; import seedu.address.model.book.Address; +import seedu.address.model.book.Availability; import seedu.address.model.book.Book; -import seedu.address.model.book.Email; import seedu.address.model.book.Title; import seedu.address.model.book.Phone; import seedu.address.model.book.exceptions.DuplicateBookException; @@ -19,22 +19,22 @@ public class SampleDataUtil { public static Book[] getSampleBooks() { return new Book[] { - new Book(new Title("Alex Yeoh"), new Phone("87438807"), new Email("alexyeoh@example.com"), + new Book(new Title("Alex Yeoh"), new Phone("87438807"), new Availability("Available"), new Address("Blk 30 Geylang Street 29, #06-40"), getTagSet("friends")), - new Book(new Title("Bernice Yu"), new Phone("99272758"), new Email("berniceyu@example.com"), + new Book(new Title("Bernice Yu"), new Phone("99272758"), new Availability("Available"), new Address("Blk 30 Lorong 3 Serangoon Gardens, #07-18"), getTagSet("colleagues", "friends")), - new Book(new Title("Charlotte Oliveiro"), new Phone("93210283"), new Email("charlotte@example.com"), + new Book(new Title("Charlotte Oliveiro"), new Phone("93210283"), new Availability("Borrowed"), new Address("Blk 11 Ang Mo Kio Street 74, #11-04"), getTagSet("neighbours")), - new Book(new Title("David Li"), new Phone("91031282"), new Email("lidavid@example.com"), + new Book(new Title("David Li"), new Phone("91031282"), new Availability("Borrowed"), new Address("Blk 436 Serangoon Gardens Street 26, #16-43"), getTagSet("family")), - new Book(new Title("Irfan Ibrahim"), new Phone("92492021"), new Email("irfan@example.com"), + new Book(new Title("Irfan Ibrahim"), new Phone("92492021"), new Availability("Borrowed"), new Address("Blk 47 Tampines Street 20, #17-35"), getTagSet("classmates")), - new Book(new Title("Roy Balakrishnan"), new Phone("92624417"), new Email("royb@example.com"), + new Book(new Title("Roy Balakrishnan"), new Phone("92624417"), new Availability("Borrowed"), new Address("Blk 45 Aljunied Street 85, #11-31"), getTagSet("colleagues")) }; diff --git a/src/main/java/seedu/address/storage/XmlAdaptedBook.java b/src/main/java/seedu/address/storage/XmlAdaptedBook.java index c1e4f22e9fd5..51ea4c0b4790 100644 --- a/src/main/java/seedu/address/storage/XmlAdaptedBook.java +++ b/src/main/java/seedu/address/storage/XmlAdaptedBook.java @@ -10,8 +10,8 @@ import seedu.address.commons.exceptions.IllegalValueException; import seedu.address.model.book.Address; +import seedu.address.model.book.Availability; import seedu.address.model.book.Book; -import seedu.address.model.book.Email; import seedu.address.model.book.Title; import seedu.address.model.book.Phone; import seedu.address.model.tag.Tag; @@ -28,7 +28,7 @@ public class XmlAdaptedBook { @XmlElement(required = true) private String phone; @XmlElement(required = true) - private String email; + private String availability; @XmlElement(required = true) private String address; @@ -44,10 +44,10 @@ public XmlAdaptedBook() {} /** * Constructs an {@code XmlAdaptedBook} with the given book details. */ - public XmlAdaptedBook(String title, String phone, String email, String address, List tagged) { + public XmlAdaptedBook(String title, String phone, String availability, String address, List tagged) { this.title = title; this.phone = phone; - this.email = email; + this.availability = availability; this.address = address; if (tagged != null) { this.tagged = new ArrayList<>(tagged); @@ -62,7 +62,7 @@ public XmlAdaptedBook(String title, String phone, String email, String address, public XmlAdaptedBook(Book source) { title = source.getTitle().fullTitle; phone = source.getPhone().value; - email = source.getEmail().value; + availability = source.getAvailability().value; address = source.getAddress().value; tagged = new ArrayList<>(); for (Tag tag : source.getTags()) { @@ -97,13 +97,13 @@ public Book toModelType() throws IllegalValueException { } final Phone phone = new Phone(this.phone); - if (this.email == null) { - throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Email.class.getSimpleName())); + if (this.availability == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Availability.class.getSimpleName())); } - if (!Email.isValidEmail(this.email)) { - throw new IllegalValueException(Email.MESSAGE_EMAIL_CONSTRAINTS); + if (!Availability.isValidAvailability(this.availability)) { + throw new IllegalValueException(Availability.MESSAGE_AVAILABILITY_CONSTRAINTS); } - final Email email = new Email(this.email); + final Availability availability = new Availability(this.availability); if (this.address == null) { throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Address.class.getSimpleName())); @@ -114,7 +114,7 @@ public Book toModelType() throws IllegalValueException { final Address address = new Address(this.address); final Set tags = new HashSet<>(bookTags); - return new Book(title, phone, email, address, tags); + return new Book(title, phone, availability, address, tags); } @Override @@ -130,7 +130,7 @@ public boolean equals(Object other) { XmlAdaptedBook otherBook = (XmlAdaptedBook) other; return Objects.equals(title, otherBook.title) && Objects.equals(phone, otherBook.phone) - && Objects.equals(email, otherBook.email) + && Objects.equals(availability, otherBook.availability) && Objects.equals(address, otherBook.address) && tagged.equals(otherBook.tagged); } diff --git a/src/main/java/seedu/address/ui/BookCard.java b/src/main/java/seedu/address/ui/BookCard.java index 0796968181bb..c9b1ff8f6d87 100644 --- a/src/main/java/seedu/address/ui/BookCard.java +++ b/src/main/java/seedu/address/ui/BookCard.java @@ -35,7 +35,7 @@ public class BookCard extends UiPart { @FXML private Label address; @FXML - private Label email; + private Label availability; @FXML private FlowPane tags; @@ -46,7 +46,7 @@ public BookCard(Book book, int displayedIndex) { title.setText(book.getTitle().fullTitle); phone.setText(book.getPhone().value); address.setText(book.getAddress().value); - email.setText(book.getEmail().value); + availability.setText(book.getAvailability().value); book.getTags().forEach(tag -> tags.getChildren().add(new Label(tag.tagName))); } diff --git a/src/main/resources/view/BookListCard.fxml b/src/main/resources/view/BookListCard.fxml index 82d2757a1fc4..8afe8bcca5ac 100644 --- a/src/main/resources/view/BookListCard.fxml +++ b/src/main/resources/view/BookListCard.fxml @@ -30,7 +30,7 @@

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 Date: Mon, 19 Mar 2018 14:54:41 +0800 Subject: [PATCH 27/98] Add photo and change name for a photo (QiuHaohao) --- docs/images/{Haoze.jpg => QiuHaohao.jpg} | Bin docs/images/victortardieu.jpg | Bin 0 -> 166272 bytes 2 files changed, 0 insertions(+), 0 deletions(-) rename docs/images/{Haoze.jpg => QiuHaohao.jpg} (100%) create mode 100644 docs/images/victortardieu.jpg diff --git a/docs/images/Haoze.jpg b/docs/images/QiuHaohao.jpg similarity index 100% rename from docs/images/Haoze.jpg rename to docs/images/QiuHaohao.jpg diff --git a/docs/images/victortardieu.jpg b/docs/images/victortardieu.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a9ab2e6939bbcd85c0a9e8421f22c7033590a5cd GIT binary patch literal 166272 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 Date: Mon, 19 Mar 2018 16:42:17 +0800 Subject: [PATCH 28/98] DeveloperGuide: Added features proposed --- docs/DeveloperGuide.adoc | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.adoc b/docs/DeveloperGuide.adoc index 192125fa8202..870cad1f50dc 100644 --- a/docs/DeveloperGuide.adoc +++ b/docs/DeveloperGuide.adoc @@ -12,7 +12,7 @@ ifdef::env-github[] endif::[] :repoURL: https://github.com/CS2103JAN2018-T16-B1/main -By: `Team SE-EDU`      Since: `Jun 2016`      Licence: `MIT` +By: `Team CS2103JAN2018-T16-B1`      Since: `Mar 2018`      Licence: `MIT` == Setting up @@ -497,6 +497,39 @@ A project often depends on third-party libraries. For example, Address Book depe a. Include those libraries in the repo (this bloats the repo size) + b. Require developers to download those libraries manually (this creates extra work for developers) +=== Features Proposed + +Unallocated: +. Renew Command +.. Allows students to renew borrowed books. + +Chan Tiong Ley: +. bookLogs command +.. Shows the past history of the book. +. userLogs command +.. Shows the past activities of the user. + +Lucas Le: +. Auto-complete UI +.. Helps users with completing command lines inputs. + +Qiu Hao Ze: +. Login Command +.. Create levels of privileges for different target groups. i.e. Guests, Students, Librarians + +Victor Tardieu: +. Book Class with bookList +.. Creates book objects. +. List Command +.. List the books in the catalogue in order. + +Wong Khia Yi: +. Borrow Command +.. Allows students to borrow books. +. Reserve Command +.. Allows students to reserve books. + + [[GetStartedProgramming]] [appendix] == Suggested Programming Tasks to Get Started From 58aa8020d6488eae6846cbc7b84aea26a1fad8c3 Mon Sep 17 00:00:00 2001 From: Khia Yi <33336624+khiayi@users.noreply.github.com> Date: Thu, 22 Mar 2018 10:08:59 +0800 Subject: [PATCH 29/98] Refactored AddressBook to Catalogue --- src/main/java/seedu/address/MainApp.java | 8 ++++---- ...sBookStorage.java => CatalogueStorage.java} | 2 +- .../java/seedu/address/storage/Storage.java | 2 +- .../seedu/address/storage/StorageManager.java | 16 ++++++++-------- ...okStorage.java => XmlCatalogueStorage.java} | 6 +++--- .../seedu/address/model/AddressBookTest.java | 18 +++++++++--------- .../address/storage/StorageManagerTest.java | 12 ++++++------ ...eTest.java => XmlCatalogueStorageTest.java} | 10 +++++----- 8 files changed, 37 insertions(+), 37 deletions(-) rename src/main/java/seedu/address/storage/{AddressBookStorage.java => CatalogueStorage.java} (97%) rename src/main/java/seedu/address/storage/{XmlAddressBookStorage.java => XmlCatalogueStorage.java} (94%) rename src/test/java/seedu/address/storage/{XmlAddressBookStorageTest.java => XmlCatalogueStorageTest.java} (91%) diff --git a/src/main/java/seedu/address/MainApp.java b/src/main/java/seedu/address/MainApp.java index fa0800d55cb9..fcf4a664bc75 100644 --- a/src/main/java/seedu/address/MainApp.java +++ b/src/main/java/seedu/address/MainApp.java @@ -26,12 +26,12 @@ import seedu.address.model.ReadOnlyAddressBook; import seedu.address.model.UserPrefs; import seedu.address.model.util.SampleDataUtil; -import seedu.address.storage.AddressBookStorage; +import seedu.address.storage.CatalogueStorage; import seedu.address.storage.JsonUserPrefsStorage; import seedu.address.storage.Storage; import seedu.address.storage.StorageManager; import seedu.address.storage.UserPrefsStorage; -import seedu.address.storage.XmlAddressBookStorage; +import seedu.address.storage.XmlCatalogueStorage; import seedu.address.ui.Ui; import seedu.address.ui.UiManager; @@ -61,8 +61,8 @@ public void init() throws Exception { UserPrefsStorage userPrefsStorage = new JsonUserPrefsStorage(config.getUserPrefsFilePath()); userPrefs = initPrefs(userPrefsStorage); - AddressBookStorage addressBookStorage = new XmlAddressBookStorage(userPrefs.getAddressBookFilePath()); - storage = new StorageManager(addressBookStorage, userPrefsStorage); + CatalogueStorage catalogueStorage = new XmlCatalogueStorage(userPrefs.getAddressBookFilePath()); + storage = new StorageManager(catalogueStorage, userPrefsStorage); initLogging(config); diff --git a/src/main/java/seedu/address/storage/AddressBookStorage.java b/src/main/java/seedu/address/storage/CatalogueStorage.java similarity index 97% rename from src/main/java/seedu/address/storage/AddressBookStorage.java rename to src/main/java/seedu/address/storage/CatalogueStorage.java index cf5b527c063a..1742584e72f8 100644 --- a/src/main/java/seedu/address/storage/AddressBookStorage.java +++ b/src/main/java/seedu/address/storage/CatalogueStorage.java @@ -9,7 +9,7 @@ /** * Represents a storage for {@link seedu.address.model.AddressBook}. */ -public interface AddressBookStorage { +public interface CatalogueStorage { /** * Returns the file path of the data file. diff --git a/src/main/java/seedu/address/storage/Storage.java b/src/main/java/seedu/address/storage/Storage.java index c0881a5a6483..273ecc62721f 100644 --- a/src/main/java/seedu/address/storage/Storage.java +++ b/src/main/java/seedu/address/storage/Storage.java @@ -12,7 +12,7 @@ /** * API of the Storage component */ -public interface Storage extends AddressBookStorage, UserPrefsStorage { +public interface Storage extends CatalogueStorage, UserPrefsStorage { @Override Optional readUserPrefs() throws DataConversionException, IOException; diff --git a/src/main/java/seedu/address/storage/StorageManager.java b/src/main/java/seedu/address/storage/StorageManager.java index 53967b391a5a..3c60251c3fe6 100644 --- a/src/main/java/seedu/address/storage/StorageManager.java +++ b/src/main/java/seedu/address/storage/StorageManager.java @@ -20,13 +20,13 @@ public class StorageManager extends ComponentManager implements Storage { private static final Logger logger = LogsCenter.getLogger(StorageManager.class); - private AddressBookStorage addressBookStorage; + private CatalogueStorage catalogueStorage; private UserPrefsStorage userPrefsStorage; - public StorageManager(AddressBookStorage addressBookStorage, UserPrefsStorage userPrefsStorage) { + public StorageManager(CatalogueStorage catalogueStorage, UserPrefsStorage userPrefsStorage) { super(); - this.addressBookStorage = addressBookStorage; + this.catalogueStorage = catalogueStorage; this.userPrefsStorage = userPrefsStorage; } @@ -52,29 +52,29 @@ public void saveUserPrefs(UserPrefs userPrefs) throws IOException { @Override public String getAddressBookFilePath() { - return addressBookStorage.getAddressBookFilePath(); + return catalogueStorage.getAddressBookFilePath(); } @Override public Optional readAddressBook() throws DataConversionException, IOException { - return readAddressBook(addressBookStorage.getAddressBookFilePath()); + return readAddressBook(catalogueStorage.getAddressBookFilePath()); } @Override public Optional readAddressBook(String filePath) throws DataConversionException, IOException { logger.fine("Attempting to read data from file: " + filePath); - return addressBookStorage.readAddressBook(filePath); + return catalogueStorage.readAddressBook(filePath); } @Override public void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException { - saveAddressBook(addressBook, addressBookStorage.getAddressBookFilePath()); + saveAddressBook(addressBook, catalogueStorage.getAddressBookFilePath()); } @Override public void saveAddressBook(ReadOnlyAddressBook addressBook, String filePath) throws IOException { logger.fine("Attempting to write to data file: " + filePath); - addressBookStorage.saveAddressBook(addressBook, filePath); + catalogueStorage.saveAddressBook(addressBook, filePath); } diff --git a/src/main/java/seedu/address/storage/XmlAddressBookStorage.java b/src/main/java/seedu/address/storage/XmlCatalogueStorage.java similarity index 94% rename from src/main/java/seedu/address/storage/XmlAddressBookStorage.java rename to src/main/java/seedu/address/storage/XmlCatalogueStorage.java index c77ebe67435c..cd1f5c538199 100644 --- a/src/main/java/seedu/address/storage/XmlAddressBookStorage.java +++ b/src/main/java/seedu/address/storage/XmlCatalogueStorage.java @@ -17,13 +17,13 @@ /** * A class to access AddressBook data stored as an xml file on the hard disk. */ -public class XmlAddressBookStorage implements AddressBookStorage { +public class XmlCatalogueStorage implements CatalogueStorage { - private static final Logger logger = LogsCenter.getLogger(XmlAddressBookStorage.class); + private static final Logger logger = LogsCenter.getLogger(XmlCatalogueStorage.class); private String filePath; - public XmlAddressBookStorage(String filePath) { + public XmlCatalogueStorage(String filePath) { this.filePath = filePath; } diff --git a/src/test/java/seedu/address/model/AddressBookTest.java b/src/test/java/seedu/address/model/AddressBookTest.java index bf26f68896b8..172fa62f2b49 100644 --- a/src/test/java/seedu/address/model/AddressBookTest.java +++ b/src/test/java/seedu/address/model/AddressBookTest.java @@ -24,25 +24,25 @@ public class AddressBookTest { @Rule public ExpectedException thrown = ExpectedException.none(); - private final AddressBook addressBook = new AddressBook(); + private final AddressBook catalogue = new AddressBook(); @Test public void constructor() { - assertEquals(Collections.emptyList(), addressBook.getPersonList()); - assertEquals(Collections.emptyList(), addressBook.getTagList()); + assertEquals(Collections.emptyList(), catalogue.getPersonList()); + assertEquals(Collections.emptyList(), catalogue.getTagList()); } @Test public void resetData_null_throwsNullPointerException() { thrown.expect(NullPointerException.class); - addressBook.resetData(null); + catalogue.resetData(null); } @Test public void resetData_withValidReadOnlyAddressBook_replacesData() { AddressBook newData = getTypicalAddressBook(); - addressBook.resetData(newData); - assertEquals(newData, addressBook); + catalogue.resetData(newData); + assertEquals(newData, catalogue); } @Test @@ -53,19 +53,19 @@ public void resetData_withDuplicatePersons_throwsAssertionError() { AddressBookStub newData = new AddressBookStub(newPersons, newTags); thrown.expect(AssertionError.class); - addressBook.resetData(newData); + catalogue.resetData(newData); } @Test public void getPersonList_modifyList_throwsUnsupportedOperationException() { thrown.expect(UnsupportedOperationException.class); - addressBook.getPersonList().remove(0); + catalogue.getPersonList().remove(0); } @Test public void getTagList_modifyList_throwsUnsupportedOperationException() { thrown.expect(UnsupportedOperationException.class); - addressBook.getTagList().remove(0); + catalogue.getTagList().remove(0); } /** diff --git a/src/test/java/seedu/address/storage/StorageManagerTest.java b/src/test/java/seedu/address/storage/StorageManagerTest.java index 419021d459f6..eb93fc628aed 100644 --- a/src/test/java/seedu/address/storage/StorageManagerTest.java +++ b/src/test/java/seedu/address/storage/StorageManagerTest.java @@ -30,7 +30,7 @@ public class StorageManagerTest { @Before public void setUp() { - XmlAddressBookStorage addressBookStorage = new XmlAddressBookStorage(getTempFilePath("ab")); + XmlCatalogueStorage addressBookStorage = new XmlCatalogueStorage(getTempFilePath("ab")); JsonUserPrefsStorage userPrefsStorage = new JsonUserPrefsStorage(getTempFilePath("prefs")); storageManager = new StorageManager(addressBookStorage, userPrefsStorage); } @@ -58,8 +58,8 @@ public void prefsReadSave() throws Exception { public void addressBookReadSave() throws Exception { /* * Note: This is an integration test that verifies the StorageManager is properly wired to the - * {@link XmlAddressBookStorage} class. - * More extensive testing of UserPref saving/reading is done in {@link XmlAddressBookStorageTest} class. + * {@link XmlCatalogueStorage} class. + * More extensive testing of UserPref saving/reading is done in {@link XmlCatalogueStorageTest} class. */ AddressBook original = getTypicalAddressBook(); storageManager.saveAddressBook(original); @@ -75,7 +75,7 @@ public void getAddressBookFilePath() { @Test public void handleAddressBookChangedEvent_exceptionThrown_eventRaised() { // Create a StorageManager while injecting a stub that throws an exception when the save method is called - Storage storage = new StorageManager(new XmlAddressBookStorageExceptionThrowingStub("dummy"), + Storage storage = new StorageManager(new XmlCatalogueStorageExceptionThrowingStub("dummy"), new JsonUserPrefsStorage("dummy")); storage.handleAddressBookChangedEvent(new AddressBookChangedEvent(new AddressBook())); assertTrue(eventsCollectorRule.eventsCollector.getMostRecent() instanceof DataSavingExceptionEvent); @@ -85,9 +85,9 @@ public void handleAddressBookChangedEvent_exceptionThrown_eventRaised() { /** * A Stub class to throw an exception when the save method is called */ - class XmlAddressBookStorageExceptionThrowingStub extends XmlAddressBookStorage { + class XmlCatalogueStorageExceptionThrowingStub extends XmlCatalogueStorage { - public XmlAddressBookStorageExceptionThrowingStub(String filePath) { + public XmlCatalogueStorageExceptionThrowingStub(String filePath) { super(filePath); } diff --git a/src/test/java/seedu/address/storage/XmlAddressBookStorageTest.java b/src/test/java/seedu/address/storage/XmlCatalogueStorageTest.java similarity index 91% rename from src/test/java/seedu/address/storage/XmlAddressBookStorageTest.java rename to src/test/java/seedu/address/storage/XmlCatalogueStorageTest.java index 1bf3765cfba9..b910ed70b60e 100644 --- a/src/test/java/seedu/address/storage/XmlAddressBookStorageTest.java +++ b/src/test/java/seedu/address/storage/XmlCatalogueStorageTest.java @@ -19,8 +19,8 @@ import seedu.address.model.AddressBook; import seedu.address.model.ReadOnlyAddressBook; -public class XmlAddressBookStorageTest { - private static final String TEST_DATA_FOLDER = FileUtil.getPath("./src/test/data/XmlAddressBookStorageTest/"); +public class XmlCatalogueStorageTest { + private static final String TEST_DATA_FOLDER = FileUtil.getPath("./src/test/data/XmlCatalogueStorageTest/"); @Rule public ExpectedException thrown = ExpectedException.none(); @@ -35,7 +35,7 @@ public void readAddressBook_nullFilePath_throwsNullPointerException() throws Exc } private java.util.Optional readAddressBook(String filePath) throws Exception { - return new XmlAddressBookStorage(filePath).readAddressBook(addToTestDataPathIfNotNull(filePath)); + return new XmlCatalogueStorage(filePath).readAddressBook(addToTestDataPathIfNotNull(filePath)); } private String addToTestDataPathIfNotNull(String prefsFileInTestDataFolder) { @@ -76,7 +76,7 @@ public void readAddressBook_invalidAndValidPersonAddressBook_throwDataConversion public void readAndSaveAddressBook_allInOrder_success() throws Exception { String filePath = testFolder.getRoot().getPath() + "TempAddressBook.xml"; AddressBook original = getTypicalAddressBook(); - XmlAddressBookStorage xmlAddressBookStorage = new XmlAddressBookStorage(filePath); + XmlCatalogueStorage xmlAddressBookStorage = new XmlCatalogueStorage(filePath); //Save in new file and read back xmlAddressBookStorage.saveAddressBook(original, filePath); @@ -109,7 +109,7 @@ public void saveAddressBook_nullAddressBook_throwsNullPointerException() { */ private void saveAddressBook(ReadOnlyAddressBook addressBook, String filePath) { try { - new XmlAddressBookStorage(filePath).saveAddressBook(addressBook, addToTestDataPathIfNotNull(filePath)); + new XmlCatalogueStorage(filePath).saveAddressBook(addressBook, addToTestDataPathIfNotNull(filePath)); } catch (IOException ioe) { throw new AssertionError("There should not be an error writing to the file.", ioe); } From b97e9de3fb32f3cd70228439865ef5fbb90380ad Mon Sep 17 00:00:00 2001 From: Khia Yi <33336624+khiayi@users.noreply.github.com> Date: Thu, 22 Mar 2018 10:38:05 +0800 Subject: [PATCH 30/98] Refactored all AddressBook to Catalogue --- docs/DeveloperGuide.adoc | 2 +- src/main/java/seedu/address/MainApp.java | 32 +++++----- ...dEvent.java => CatalogueChangedEvent.java} | 10 +-- .../seedu/address/logic/LogicManager.java | 8 +-- .../address/logic/commands/ClearCommand.java | 4 +- .../logic/commands/UndoableCommand.java | 18 +++--- ...ssBookParser.java => CatalogueParser.java} | 2 +- .../{AddressBook.java => Catalogue.java} | 26 ++++---- src/main/java/seedu/address/model/Model.java | 6 +- .../seedu/address/model/ModelManager.java | 48 +++++++------- ...ddressBook.java => ReadOnlyCatalogue.java} | 2 +- .../java/seedu/address/model/UserPrefs.java | 30 ++++----- .../address/model/util/SampleDataUtil.java | 10 +-- .../address/storage/CatalogueStorage.java | 25 ++++---- .../java/seedu/address/storage/Storage.java | 12 ++-- .../seedu/address/storage/StorageManager.java | 32 +++++----- .../address/storage/XmlCatalogueStorage.java | 38 +++++------ .../seedu/address/storage/XmlFileStorage.java | 8 +-- ...ook.java => XmlSerializableCatalogue.java} | 32 +++++----- .../java/seedu/address/ui/MainWindow.java | 2 +- .../java/seedu/address/ui/PersonCard.java | 2 +- .../seedu/address/ui/StatusBarFooter.java | 4 +- .../typicalPersonsAddressBook.xml | 2 +- src/test/java/seedu/address/TestApp.java | 26 ++++---- .../address/commons/util/XmlUtilTest.java | 28 ++++---- .../seedu/address/logic/LogicManagerTest.java | 2 +- .../commands/AddCommandIntegrationTest.java | 8 +-- .../logic/commands/AddCommandTest.java | 16 ++--- .../logic/commands/ClearCommandTest.java | 8 +-- .../logic/commands/CommandTestUtil.java | 6 +- .../logic/commands/DeleteCommandTest.java | 14 ++-- .../logic/commands/EditCommandTest.java | 22 +++---- .../logic/commands/FindCommandTest.java | 12 ++-- .../logic/commands/ListCommandTest.java | 6 +- .../logic/commands/RedoCommandTest.java | 6 +- .../logic/commands/SelectCommandTest.java | 6 +- .../logic/commands/UndoCommandTest.java | 8 +-- .../logic/commands/UndoableCommandTest.java | 8 +-- ...rserTest.java => CatalogueParserTest.java} | 4 +- ...ddressBookTest.java => CatalogueTest.java} | 18 +++--- .../seedu/address/model/ModelManagerTest.java | 20 +++--- .../storage/JsonUserPrefsStorageTest.java | 4 +- .../address/storage/StorageManagerTest.java | 32 +++++----- .../storage/XmlCatalogueStorageTest.java | 64 +++++++++---------- ...java => XmlSerializableCatalogueTest.java} | 24 +++---- .../address/testutil/AddressBookBuilder.java | 53 --------------- .../address/testutil/CatalogueBuilder.java | 53 +++++++++++++++ .../java/seedu/address/testutil/TestUtil.java | 6 +- .../address/testutil/TypicalPersons.java | 8 +-- .../java/seedu/address/ui/GuiUnitTest.java | 2 +- .../seedu/address/ui/StatusBarFooterTest.java | 6 +- .../systemtests/AddCommandSystemTest.java | 12 ++-- ...stemTest.java => CatalogueSystemTest.java} | 18 +++--- .../systemtests/ClearCommandSystemTest.java | 10 +-- .../systemtests/DeleteCommandSystemTest.java | 16 ++--- .../systemtests/EditCommandSystemTest.java | 16 ++--- .../java/systemtests/ErrorDialogGuiTest.java | 2 +- .../systemtests/FindCommandSystemTest.java | 12 ++-- .../systemtests/HelpCommandSystemTest.java | 2 +- src/test/java/systemtests/SampleDataTest.java | 8 +-- .../systemtests/SelectCommandSystemTest.java | 14 ++-- .../systemtests/SystemTestSetupHelper.java | 6 +- 62 files changed, 471 insertions(+), 470 deletions(-) rename src/main/java/seedu/address/commons/events/model/{AddressBookChangedEvent.java => CatalogueChangedEvent.java} (52%) rename src/main/java/seedu/address/logic/parser/{AddressBookParser.java => CatalogueParser.java} (98%) rename src/main/java/seedu/address/model/{AddressBook.java => Catalogue.java} (87%) rename src/main/java/seedu/address/model/{ReadOnlyAddressBook.java => ReadOnlyCatalogue.java} (93%) rename src/main/java/seedu/address/storage/{XmlSerializableAddressBook.java => XmlSerializableCatalogue.java} (61%) rename src/test/java/seedu/address/logic/parser/{AddressBookParserTest.java => CatalogueParserTest.java} (98%) rename src/test/java/seedu/address/model/{AddressBookTest.java => CatalogueTest.java} (78%) rename src/test/java/seedu/address/storage/{XmlSerializableAddressBookTest.java => XmlSerializableCatalogueTest.java} (62%) delete mode 100644 src/test/java/seedu/address/testutil/AddressBookBuilder.java create mode 100644 src/test/java/seedu/address/testutil/CatalogueBuilder.java rename src/test/java/systemtests/{AddressBookSystemTest.java => CatalogueSystemTest.java} (94%) diff --git a/docs/DeveloperGuide.adoc b/docs/DeveloperGuide.adoc index 870cad1f50dc..59a2d6359738 100644 --- a/docs/DeveloperGuide.adoc +++ b/docs/DeveloperGuide.adoc @@ -763,7 +763,7 @@ Now we have the `Remark` class, we need to actually use it inside link:{repoURL} . Add `getRemark()` in link:{repoURL}/src/main/java/seedu/address/model/person/Person.java[`Person`]. . You may assume that the user will not be able to use the `add` and `edit` commands to modify the remarks field (i.e. the person will be created without a remark). -. Modify link:{repoURL}/src/main/java/seedu/address/model/util/SampleDataUtil.java/[`SampleDataUtil`] to add remarks for the sample data (delete your `addressBook.xml` so that the application will load the sample data when you launch it.) +. Modify link:{repoURL}/src/main/java/seedu/address/model/util/SampleDataUtil.java/[`SampleDataUtil`] to add remarks for the sample data (delete your `catalogue.xml` so that the application will load the sample data when you launch it.) ===== [Step 6] Storage: Add `Remark` field to `XmlAdaptedPerson` class We now have `Remark` s for `Person` s, but they will be gone when we exit the application. Let's modify link:{repoURL}/src/main/java/seedu/address/storage/XmlAdaptedPerson.java[`XmlAdaptedPerson`] to include a `Remark` field so that it will be saved. diff --git a/src/main/java/seedu/address/MainApp.java b/src/main/java/seedu/address/MainApp.java index fcf4a664bc75..ecf290921a8a 100644 --- a/src/main/java/seedu/address/MainApp.java +++ b/src/main/java/seedu/address/MainApp.java @@ -20,10 +20,10 @@ 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.Catalogue; import seedu.address.model.Model; import seedu.address.model.ModelManager; -import seedu.address.model.ReadOnlyAddressBook; +import seedu.address.model.ReadOnlyCatalogue; import seedu.address.model.UserPrefs; import seedu.address.model.util.SampleDataUtil; import seedu.address.storage.CatalogueStorage; @@ -54,14 +54,14 @@ public class MainApp extends Application { @Override public void init() throws Exception { - logger.info("=============================[ Initializing AddressBook ]==========================="); + logger.info("=============================[ Initializing Catalogue ]==========================="); super.init(); config = initConfig(getApplicationParameter("config")); UserPrefsStorage userPrefsStorage = new JsonUserPrefsStorage(config.getUserPrefsFilePath()); userPrefs = initPrefs(userPrefsStorage); - CatalogueStorage catalogueStorage = new XmlCatalogueStorage(userPrefs.getAddressBookFilePath()); + CatalogueStorage catalogueStorage = new XmlCatalogueStorage(userPrefs.getCatalogueFilePath()); storage = new StorageManager(catalogueStorage, userPrefsStorage); initLogging(config); @@ -86,20 +86,20 @@ private String getApplicationParameter(String parameterName) { * or an empty address book will be used instead if errors occur when reading {@code storage}'s address book. */ private Model initModelManager(Storage storage, UserPrefs userPrefs) { - Optional addressBookOptional; - ReadOnlyAddressBook initialData; + Optional catalogueOptional; + ReadOnlyCatalogue initialData; try { - addressBookOptional = storage.readAddressBook(); - if (!addressBookOptional.isPresent()) { - logger.info("Data file not found. Will be starting with a sample AddressBook"); + catalogueOptional = storage.readCatalogue(); + if (!catalogueOptional.isPresent()) { + logger.info("Data file not found. Will be starting with a sample Catalogue"); } - initialData = addressBookOptional.orElseGet(SampleDataUtil::getSampleAddressBook); + initialData = catalogueOptional.orElseGet(SampleDataUtil::getSampleCatalogue); } 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 Catalogue"); + initialData = new Catalogue(); } 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 Catalogue"); + initialData = new Catalogue(); } return new ModelManager(initialData, userPrefs); @@ -163,7 +163,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 Catalogue"); initializedPrefs = new UserPrefs(); } @@ -183,7 +183,7 @@ private void initEventsCenter() { @Override public void start(Stage primaryStage) { - logger.info("Starting AddressBook " + MainApp.VERSION); + logger.info("Starting Catalogue " + MainApp.VERSION); ui.start(primaryStage); } diff --git a/src/main/java/seedu/address/commons/events/model/AddressBookChangedEvent.java b/src/main/java/seedu/address/commons/events/model/CatalogueChangedEvent.java similarity index 52% rename from src/main/java/seedu/address/commons/events/model/AddressBookChangedEvent.java rename to src/main/java/seedu/address/commons/events/model/CatalogueChangedEvent.java index 7db9b5c48ed6..0c192e007674 100644 --- a/src/main/java/seedu/address/commons/events/model/AddressBookChangedEvent.java +++ b/src/main/java/seedu/address/commons/events/model/CatalogueChangedEvent.java @@ -1,14 +1,14 @@ package seedu.address.commons.events.model; import seedu.address.commons.events.BaseEvent; -import seedu.address.model.ReadOnlyAddressBook; +import seedu.address.model.ReadOnlyCatalogue; -/** Indicates the AddressBook in the model has changed*/ -public class AddressBookChangedEvent extends BaseEvent { +/** Indicates the Catalogue in the model has changed*/ +public class CatalogueChangedEvent extends BaseEvent { - public final ReadOnlyAddressBook data; + public final ReadOnlyCatalogue data; - public AddressBookChangedEvent(ReadOnlyAddressBook data) { + public CatalogueChangedEvent(ReadOnlyCatalogue data) { this.data = data; } diff --git a/src/main/java/seedu/address/logic/LogicManager.java b/src/main/java/seedu/address/logic/LogicManager.java index 9f6846bdfc74..e992b3b83d6b 100644 --- a/src/main/java/seedu/address/logic/LogicManager.java +++ b/src/main/java/seedu/address/logic/LogicManager.java @@ -8,7 +8,7 @@ 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.CatalogueParser; import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.Model; import seedu.address.model.person.Person; @@ -21,13 +21,13 @@ public class LogicManager extends ComponentManager implements Logic { private final Model model; private final CommandHistory history; - private final AddressBookParser addressBookParser; + private final CatalogueParser catalogueParser; private final UndoRedoStack undoRedoStack; public LogicManager(Model model) { this.model = model; history = new CommandHistory(); - addressBookParser = new AddressBookParser(); + catalogueParser = new CatalogueParser(); undoRedoStack = new UndoRedoStack(); } @@ -35,7 +35,7 @@ public LogicManager(Model model) { public CommandResult execute(String commandText) throws CommandException, ParseException { logger.info("----------------[USER COMMAND][" + commandText + "]"); try { - Command command = addressBookParser.parseCommand(commandText); + Command command = catalogueParser.parseCommand(commandText); command.setData(model, history, undoRedoStack); CommandResult result = command.execute(); undoRedoStack.push(command); diff --git a/src/main/java/seedu/address/logic/commands/ClearCommand.java b/src/main/java/seedu/address/logic/commands/ClearCommand.java index ceeb7ba913c6..cce6c851066f 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.Catalogue; /** * Clears the address book. @@ -16,7 +16,7 @@ public class ClearCommand extends UndoableCommand { @Override public CommandResult executeUndoableCommand() { requireNonNull(model); - model.resetData(new AddressBook()); + model.resetData(new Catalogue()); return new CommandResult(MESSAGE_SUCCESS); } } diff --git a/src/main/java/seedu/address/logic/commands/UndoableCommand.java b/src/main/java/seedu/address/logic/commands/UndoableCommand.java index c107ffcd9cb3..7514822642d6 100644 --- a/src/main/java/seedu/address/logic/commands/UndoableCommand.java +++ b/src/main/java/seedu/address/logic/commands/UndoableCommand.java @@ -5,23 +5,23 @@ import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS; import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.AddressBook; -import seedu.address.model.ReadOnlyAddressBook; +import seedu.address.model.Catalogue; +import seedu.address.model.ReadOnlyCatalogue; /** * Represents a command which can be undone and redone. */ public abstract class UndoableCommand extends Command { - private ReadOnlyAddressBook previousAddressBook; + private ReadOnlyCatalogue previousCatalogue; protected abstract CommandResult executeUndoableCommand() throws CommandException; /** * Stores the current state of {@code model#addressBook}. */ - private void saveAddressBookSnapshot() { + private void saveCatalogueSnapshot() { requireNonNull(model); - this.previousAddressBook = new AddressBook(model.getAddressBook()); + this.previousCatalogue = new Catalogue(model.getCatalogue()); } /** @@ -31,13 +31,13 @@ private void saveAddressBookSnapshot() { protected void preprocessUndoableCommand() throws CommandException {} /** - * Reverts the AddressBook to the state before this command + * Reverts the Catalogue to the state before this command * was executed and updates the filtered person list to * show all persons. */ protected final void undo() { - requireAllNonNull(model, previousAddressBook); - model.resetData(previousAddressBook); + requireAllNonNull(model, previousCatalogue); + model.resetData(previousCatalogue); model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); } @@ -58,7 +58,7 @@ protected final void redo() { @Override public final CommandResult execute() throws CommandException { - saveAddressBookSnapshot(); + saveCatalogueSnapshot(); preprocessUndoableCommand(); return executeUndoableCommand(); } diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/CatalogueParser.java similarity index 98% rename from src/main/java/seedu/address/logic/parser/AddressBookParser.java rename to src/main/java/seedu/address/logic/parser/CatalogueParser.java index b7d57f5db86a..dd58a435b9ab 100644 --- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java +++ b/src/main/java/seedu/address/logic/parser/CatalogueParser.java @@ -24,7 +24,7 @@ /** * Parses user input. */ -public class AddressBookParser { +public class CatalogueParser { /** * Used for initial separation of command word and args. diff --git a/src/main/java/seedu/address/model/AddressBook.java b/src/main/java/seedu/address/model/Catalogue.java similarity index 87% rename from src/main/java/seedu/address/model/AddressBook.java rename to src/main/java/seedu/address/model/Catalogue.java index f8d0260de159..23994c7f723a 100644 --- a/src/main/java/seedu/address/model/AddressBook.java +++ b/src/main/java/seedu/address/model/Catalogue.java @@ -22,7 +22,7 @@ * Wraps all data at the address-book level * Duplicates are not allowed (by .equals comparison) */ -public class AddressBook implements ReadOnlyAddressBook { +public class Catalogue implements ReadOnlyCatalogue { private final UniquePersonList persons; private final UniqueTagList tags; @@ -39,12 +39,12 @@ public class AddressBook implements ReadOnlyAddressBook { tags = new UniqueTagList(); } - public AddressBook() {} + public Catalogue() {} /** - * Creates an AddressBook using the Persons and Tags in the {@code toBeCopied} + * Creates an Catalogue using the Persons and Tags in the {@code toBeCopied} */ - public AddressBook(ReadOnlyAddressBook toBeCopied) { + public Catalogue(ReadOnlyCatalogue toBeCopied) { this(); resetData(toBeCopied); } @@ -60,9 +60,9 @@ public void setTags(Set tags) { } /** - * Resets the existing data of this {@code AddressBook} with {@code newData}. + * Resets the existing data of this {@code Catalogue} with {@code newData}. */ - public void resetData(ReadOnlyAddressBook newData) { + public void resetData(ReadOnlyCatalogue newData) { requireNonNull(newData); setTags(new HashSet<>(newData.getTagList())); List syncedPersonList = newData.getPersonList().stream() @@ -72,7 +72,7 @@ public void resetData(ReadOnlyAddressBook newData) { try { setPersons(syncedPersonList); } catch (DuplicatePersonException e) { - throw new AssertionError("AddressBooks should not have duplicate persons"); + throw new AssertionError("Catalogue should not have duplicate persons"); } } @@ -95,7 +95,7 @@ public void addPerson(Person p) throws DuplicatePersonException { /** * Replaces the given person {@code target} in the list with {@code editedPerson}. - * {@code AddressBook}'s tag list will be updated with the tags of {@code editedPerson}. + * {@code Catalogue}'s tag list will be updated with the tags of {@code editedPerson}. * * @throws DuplicatePersonException if updating the person's details causes the person to be equivalent to * another existing person in the list. @@ -136,8 +136,8 @@ private Person syncWithMasterTagList(Person person) { } /** - * Removes {@code key} from this {@code AddressBook}. - * @throws PersonNotFoundException if the {@code key} is not in this {@code AddressBook}. + * Removes {@code key} from this {@code Catalogue}. + * @throws PersonNotFoundException if the {@code key} is not in this {@code Catalogue}. */ public boolean removePerson(Person key) throws PersonNotFoundException { if (persons.remove(key)) { @@ -174,9 +174,9 @@ public ObservableList getTagList() { @Override public boolean equals(Object other) { return other == this // short circuit if same object - || (other instanceof AddressBook // instanceof handles nulls - && this.persons.equals(((AddressBook) other).persons) - && this.tags.equalsOrderInsensitive(((AddressBook) other).tags)); + || (other instanceof Catalogue // instanceof handles nulls + && this.persons.equals(((Catalogue) other).persons) + && this.tags.equalsOrderInsensitive(((Catalogue) other).tags)); } @Override diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java index 4a6079ce0199..183b25013e26 100644 --- a/src/main/java/seedu/address/model/Model.java +++ b/src/main/java/seedu/address/model/Model.java @@ -15,10 +15,10 @@ public interface Model { Predicate PREDICATE_SHOW_ALL_PERSONS = unused -> true; /** Clears existing backing model and replaces with the provided new data. */ - void resetData(ReadOnlyAddressBook newData); + void resetData(ReadOnlyCatalogue newData); - /** Returns the AddressBook */ - ReadOnlyAddressBook getAddressBook(); + /** Returns the Catalogue */ + ReadOnlyCatalogue getCatalogue(); /** Deletes the given person. */ void deletePerson(Person target) throws PersonNotFoundException; diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index 22a7d0eb3f4d..c40a2b3dfe37 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -11,7 +11,7 @@ import javafx.collections.transformation.FilteredList; import seedu.address.commons.core.ComponentManager; import seedu.address.commons.core.LogsCenter; -import seedu.address.commons.events.model.AddressBookChangedEvent; +import seedu.address.commons.events.model.CatalogueChangedEvent; import seedu.address.model.person.Person; import seedu.address.model.person.exceptions.DuplicatePersonException; import seedu.address.model.person.exceptions.PersonNotFoundException; @@ -23,53 +23,53 @@ public class ModelManager extends ComponentManager implements Model { private static final Logger logger = LogsCenter.getLogger(ModelManager.class); - private final AddressBook addressBook; + private final Catalogue catalogue; private final FilteredList filteredPersons; /** - * Initializes a ModelManager with the given addressBook and userPrefs. + * Initializes a ModelManager with the given catalogue and userPrefs. */ - public ModelManager(ReadOnlyAddressBook addressBook, UserPrefs userPrefs) { + public ModelManager(ReadOnlyCatalogue catalogue, UserPrefs userPrefs) { super(); - requireAllNonNull(addressBook, userPrefs); + requireAllNonNull(catalogue, userPrefs); - logger.fine("Initializing with address book: " + addressBook + " and user prefs " + userPrefs); + logger.fine("Initializing with address book: " + catalogue + " and user prefs " + userPrefs); - this.addressBook = new AddressBook(addressBook); - filteredPersons = new FilteredList<>(this.addressBook.getPersonList()); + this.catalogue = new Catalogue(catalogue); + filteredPersons = new FilteredList<>(this.catalogue.getPersonList()); } public ModelManager() { - this(new AddressBook(), new UserPrefs()); + this(new Catalogue(), new UserPrefs()); } @Override - public void resetData(ReadOnlyAddressBook newData) { - addressBook.resetData(newData); - indicateAddressBookChanged(); + public void resetData(ReadOnlyCatalogue newData) { + catalogue.resetData(newData); + indicateCatalogueChanged(); } @Override - public ReadOnlyAddressBook getAddressBook() { - return addressBook; + public ReadOnlyCatalogue getCatalogue() { + return catalogue; } /** Raises an event to indicate the model has changed */ - private void indicateAddressBookChanged() { - raise(new AddressBookChangedEvent(addressBook)); + private void indicateCatalogueChanged() { + raise(new CatalogueChangedEvent(catalogue)); } @Override public synchronized void deletePerson(Person target) throws PersonNotFoundException { - addressBook.removePerson(target); - indicateAddressBookChanged(); + catalogue.removePerson(target); + indicateCatalogueChanged(); } @Override public synchronized void addPerson(Person person) throws DuplicatePersonException { - addressBook.addPerson(person); + catalogue.addPerson(person); updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); - indicateAddressBookChanged(); + indicateCatalogueChanged(); } @Override @@ -77,15 +77,15 @@ public void updatePerson(Person target, Person editedPerson) throws DuplicatePersonException, PersonNotFoundException { requireAllNonNull(target, editedPerson); - addressBook.updatePerson(target, editedPerson); - indicateAddressBookChanged(); + catalogue.updatePerson(target, editedPerson); + indicateCatalogueChanged(); } //=========== Filtered Person List Accessors ============================================================= /** * Returns an unmodifiable view of the list of {@code Person} backed by the internal list of - * {@code addressBook} + * {@code catalogue} */ @Override public ObservableList getFilteredPersonList() { @@ -112,7 +112,7 @@ public boolean equals(Object obj) { // state check ModelManager other = (ModelManager) obj; - return addressBook.equals(other.addressBook) + return catalogue.equals(other.catalogue) && filteredPersons.equals(other.filteredPersons); } diff --git a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java b/src/main/java/seedu/address/model/ReadOnlyCatalogue.java similarity index 93% rename from src/main/java/seedu/address/model/ReadOnlyAddressBook.java rename to src/main/java/seedu/address/model/ReadOnlyCatalogue.java index 1f4e49a37d67..b4da2dd817ca 100644 --- a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java +++ b/src/main/java/seedu/address/model/ReadOnlyCatalogue.java @@ -7,7 +7,7 @@ /** * Unmodifiable view of an address book */ -public interface ReadOnlyAddressBook { +public interface ReadOnlyCatalogue { /** * Returns an unmodifiable view of the persons list. diff --git a/src/main/java/seedu/address/model/UserPrefs.java b/src/main/java/seedu/address/model/UserPrefs.java index 8c8a071876eb..05d53d3be9ab 100644 --- a/src/main/java/seedu/address/model/UserPrefs.java +++ b/src/main/java/seedu/address/model/UserPrefs.java @@ -10,8 +10,8 @@ public class UserPrefs { private GuiSettings guiSettings; - private String addressBookFilePath = "data/addressbook.xml"; - private String addressBookName = "MyAddressBook"; + private String catalogueFilePath = "data/addressbook.xml"; + private String catalogueBookName = "MyAddressBook"; public UserPrefs() { this.setGuiSettings(500, 500, 0, 0); @@ -29,20 +29,20 @@ public void setGuiSettings(double width, double height, int x, int y) { guiSettings = new GuiSettings(width, height, x, y); } - public String getAddressBookFilePath() { - return addressBookFilePath; + public String getCatalogueFilePath() { + return catalogueFilePath; } - public void setAddressBookFilePath(String addressBookFilePath) { - this.addressBookFilePath = addressBookFilePath; + public void setCatalogueFilePath(String catalogueFilePath) { + this.catalogueFilePath = catalogueFilePath; } - public String getAddressBookName() { - return addressBookName; + public String getCatalogueBookName() { + return catalogueBookName; } - public void setAddressBookName(String addressBookName) { - this.addressBookName = addressBookName; + public void setCatalogueBookName(String catalogueBookName) { + this.catalogueBookName = catalogueBookName; } @Override @@ -57,21 +57,21 @@ public boolean equals(Object other) { UserPrefs o = (UserPrefs) other; return Objects.equals(guiSettings, o.guiSettings) - && Objects.equals(addressBookFilePath, o.addressBookFilePath) - && Objects.equals(addressBookName, o.addressBookName); + && Objects.equals(catalogueFilePath, o.catalogueFilePath) + && Objects.equals(catalogueBookName, o.catalogueBookName); } @Override public int hashCode() { - return Objects.hash(guiSettings, addressBookFilePath, addressBookName); + return Objects.hash(guiSettings, catalogueFilePath, catalogueBookName); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("Gui Settings : " + guiSettings.toString()); - sb.append("\nLocal data file location : " + addressBookFilePath); - sb.append("\nAddressBook name : " + addressBookName); + sb.append("\nLocal data file location : " + catalogueFilePath); + sb.append("\nCatalogue name : " + catalogueBookName); return sb.toString(); } diff --git a/src/main/java/seedu/address/model/util/SampleDataUtil.java b/src/main/java/seedu/address/model/util/SampleDataUtil.java index aea96bfb31f3..d4600c0b04b9 100644 --- a/src/main/java/seedu/address/model/util/SampleDataUtil.java +++ b/src/main/java/seedu/address/model/util/SampleDataUtil.java @@ -3,8 +3,8 @@ import java.util.HashSet; import java.util.Set; -import seedu.address.model.AddressBook; -import seedu.address.model.ReadOnlyAddressBook; +import seedu.address.model.Catalogue; +import seedu.address.model.ReadOnlyCatalogue; import seedu.address.model.person.Address; import seedu.address.model.person.Email; import seedu.address.model.person.Name; @@ -14,7 +14,7 @@ import seedu.address.model.tag.Tag; /** - * Contains utility methods for populating {@code AddressBook} with sample data. + * Contains utility methods for populating {@code Catalogue} with sample data. */ public class SampleDataUtil { public static Person[] getSamplePersons() { @@ -40,9 +40,9 @@ public static Person[] getSamplePersons() { }; } - public static ReadOnlyAddressBook getSampleAddressBook() { + public static ReadOnlyCatalogue getSampleCatalogue() { try { - AddressBook sampleAb = new AddressBook(); + Catalogue sampleAb = new Catalogue(); for (Person samplePerson : getSamplePersons()) { sampleAb.addPerson(samplePerson); } diff --git a/src/main/java/seedu/address/storage/CatalogueStorage.java b/src/main/java/seedu/address/storage/CatalogueStorage.java index 1742584e72f8..7704302b3c49 100644 --- a/src/main/java/seedu/address/storage/CatalogueStorage.java +++ b/src/main/java/seedu/address/storage/CatalogueStorage.java @@ -4,41 +4,42 @@ import java.util.Optional; import seedu.address.commons.exceptions.DataConversionException; -import seedu.address.model.ReadOnlyAddressBook; +import seedu.address.model.Catalogue; +import seedu.address.model.ReadOnlyCatalogue; /** - * Represents a storage for {@link seedu.address.model.AddressBook}. + * Represents a storage for {@link Catalogue}. */ public interface CatalogueStorage { /** * Returns the file path of the data file. */ - String getAddressBookFilePath(); + String getCatalogueFilePath(); /** - * Returns AddressBook data as a {@link ReadOnlyAddressBook}. + * Returns Catalogue data as a {@link ReadOnlyCatalogue}. * 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; + Optional readCatalogue() throws DataConversionException, IOException; /** - * @see #getAddressBookFilePath() + * @see #getCatalogueFilePath() */ - Optional readAddressBook(String filePath) throws DataConversionException, IOException; + Optional readCatalogue(String filePath) throws DataConversionException, IOException; /** - * Saves the given {@link ReadOnlyAddressBook} to the storage. - * @param addressBook cannot be null. + * Saves the given {@link ReadOnlyCatalogue} to the storage. + * @param catalogue cannot be null. * @throws IOException if there was any problem writing to the file. */ - void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException; + void saveCatalogue(ReadOnlyCatalogue catalogue) throws IOException; /** - * @see #saveAddressBook(ReadOnlyAddressBook) + * @see #saveCatalogue(ReadOnlyCatalogue) */ - void saveAddressBook(ReadOnlyAddressBook addressBook, String filePath) throws IOException; + void saveCatalogue(ReadOnlyCatalogue catalogue, String filePath) throws IOException; } diff --git a/src/main/java/seedu/address/storage/Storage.java b/src/main/java/seedu/address/storage/Storage.java index 273ecc62721f..9e6632a1d759 100644 --- a/src/main/java/seedu/address/storage/Storage.java +++ b/src/main/java/seedu/address/storage/Storage.java @@ -3,10 +3,10 @@ import java.io.IOException; import java.util.Optional; -import seedu.address.commons.events.model.AddressBookChangedEvent; +import seedu.address.commons.events.model.CatalogueChangedEvent; import seedu.address.commons.events.storage.DataSavingExceptionEvent; import seedu.address.commons.exceptions.DataConversionException; -import seedu.address.model.ReadOnlyAddressBook; +import seedu.address.model.ReadOnlyCatalogue; import seedu.address.model.UserPrefs; /** @@ -21,18 +21,18 @@ public interface Storage extends CatalogueStorage, UserPrefsStorage { void saveUserPrefs(UserPrefs userPrefs) throws IOException; @Override - String getAddressBookFilePath(); + String getCatalogueFilePath(); @Override - Optional readAddressBook() throws DataConversionException, IOException; + Optional readCatalogue() throws DataConversionException, IOException; @Override - void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException; + void saveCatalogue(ReadOnlyCatalogue catalogue) throws IOException; /** * Saves the current version of the Address Book to the hard disk. * Creates the data file if it is missing. * Raises {@link DataSavingExceptionEvent} if there was an error during saving. */ - void handleAddressBookChangedEvent(AddressBookChangedEvent abce); + void handleCatalogueChangedEvent(CatalogueChangedEvent abce); } diff --git a/src/main/java/seedu/address/storage/StorageManager.java b/src/main/java/seedu/address/storage/StorageManager.java index 3c60251c3fe6..65cfd55dca88 100644 --- a/src/main/java/seedu/address/storage/StorageManager.java +++ b/src/main/java/seedu/address/storage/StorageManager.java @@ -8,14 +8,14 @@ import seedu.address.commons.core.ComponentManager; import seedu.address.commons.core.LogsCenter; -import seedu.address.commons.events.model.AddressBookChangedEvent; +import seedu.address.commons.events.model.CatalogueChangedEvent; import seedu.address.commons.events.storage.DataSavingExceptionEvent; import seedu.address.commons.exceptions.DataConversionException; -import seedu.address.model.ReadOnlyAddressBook; +import seedu.address.model.ReadOnlyCatalogue; import seedu.address.model.UserPrefs; /** - * Manages storage of AddressBook data in local storage. + * Manages storage of Catalogue data in local storage. */ public class StorageManager extends ComponentManager implements Storage { @@ -48,42 +48,42 @@ public void saveUserPrefs(UserPrefs userPrefs) throws IOException { } - // ================ AddressBook methods ============================== + // ================ Catalogue methods ============================== @Override - public String getAddressBookFilePath() { - return catalogueStorage.getAddressBookFilePath(); + public String getCatalogueFilePath() { + return catalogueStorage.getCatalogueFilePath(); } @Override - public Optional readAddressBook() throws DataConversionException, IOException { - return readAddressBook(catalogueStorage.getAddressBookFilePath()); + public Optional readCatalogue() throws DataConversionException, IOException { + return readCatalogue(catalogueStorage.getCatalogueFilePath()); } @Override - public Optional readAddressBook(String filePath) throws DataConversionException, IOException { + public Optional readCatalogue(String filePath) throws DataConversionException, IOException { logger.fine("Attempting to read data from file: " + filePath); - return catalogueStorage.readAddressBook(filePath); + return catalogueStorage.readCatalogue(filePath); } @Override - public void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException { - saveAddressBook(addressBook, catalogueStorage.getAddressBookFilePath()); + public void saveCatalogue(ReadOnlyCatalogue catalogue) throws IOException { + saveCatalogue(catalogue, catalogueStorage.getCatalogueFilePath()); } @Override - public void saveAddressBook(ReadOnlyAddressBook addressBook, String filePath) throws IOException { + public void saveCatalogue(ReadOnlyCatalogue catalogue, String filePath) throws IOException { logger.fine("Attempting to write to data file: " + filePath); - catalogueStorage.saveAddressBook(addressBook, filePath); + catalogueStorage.saveCatalogue(catalogue, filePath); } @Override @Subscribe - public void handleAddressBookChangedEvent(AddressBookChangedEvent event) { + public void handleCatalogueChangedEvent(CatalogueChangedEvent event) { logger.info(LogsCenter.getEventHandlingLogMessage(event, "Local data changed, saving to file")); try { - saveAddressBook(event.data); + saveCatalogue(event.data); } catch (IOException e) { raise(new DataSavingExceptionEvent(e)); } diff --git a/src/main/java/seedu/address/storage/XmlCatalogueStorage.java b/src/main/java/seedu/address/storage/XmlCatalogueStorage.java index cd1f5c538199..883fb71e94d9 100644 --- a/src/main/java/seedu/address/storage/XmlCatalogueStorage.java +++ b/src/main/java/seedu/address/storage/XmlCatalogueStorage.java @@ -12,10 +12,10 @@ import seedu.address.commons.exceptions.DataConversionException; import seedu.address.commons.exceptions.IllegalValueException; import seedu.address.commons.util.FileUtil; -import seedu.address.model.ReadOnlyAddressBook; +import seedu.address.model.ReadOnlyCatalogue; /** - * A class to access AddressBook data stored as an xml file on the hard disk. + * A class to access Catalogue data stored as an xml file on the hard disk. */ public class XmlCatalogueStorage implements CatalogueStorage { @@ -27,56 +27,56 @@ public XmlCatalogueStorage(String filePath) { this.filePath = filePath; } - public String getAddressBookFilePath() { + public String getCatalogueFilePath() { return filePath; } @Override - public Optional readAddressBook() throws DataConversionException, IOException { - return readAddressBook(filePath); + public Optional readCatalogue() throws DataConversionException, IOException { + return readCatalogue(filePath); } /** - * Similar to {@link #readAddressBook()} + * Similar to {@link #readCatalogue()} * @param filePath location of the data. Cannot be null * @throws DataConversionException if the file is not in the correct format. */ - public Optional readAddressBook(String filePath) throws DataConversionException, + public Optional readCatalogue(String filePath) throws DataConversionException, FileNotFoundException { requireNonNull(filePath); - File addressBookFile = new File(filePath); + File catalogueFile = new File(filePath); - if (!addressBookFile.exists()) { - logger.info("AddressBook file " + addressBookFile + " not found"); + if (!catalogueFile.exists()) { + logger.info("Catalogue file " + catalogueFile + " not found"); return Optional.empty(); } - XmlSerializableAddressBook xmlAddressBook = XmlFileStorage.loadDataFromSaveFile(new File(filePath)); + XmlSerializableCatalogue xmlCatalogue = XmlFileStorage.loadDataFromSaveFile(new File(filePath)); try { - return Optional.of(xmlAddressBook.toModelType()); + return Optional.of(xmlCatalogue.toModelType()); } catch (IllegalValueException ive) { - logger.info("Illegal values found in " + addressBookFile + ": " + ive.getMessage()); + logger.info("Illegal values found in " + catalogueFile + ": " + ive.getMessage()); throw new DataConversionException(ive); } } @Override - public void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException { - saveAddressBook(addressBook, filePath); + public void saveCatalogue(ReadOnlyCatalogue catalogue) throws IOException { + saveCatalogue(catalogue, filePath); } /** - * Similar to {@link #saveAddressBook(ReadOnlyAddressBook)} + * Similar to {@link #saveCatalogue(ReadOnlyCatalogue)} * @param filePath location of the data. Cannot be null */ - public void saveAddressBook(ReadOnlyAddressBook addressBook, String filePath) throws IOException { - requireNonNull(addressBook); + public void saveCatalogue(ReadOnlyCatalogue catalogue, String filePath) throws IOException { + requireNonNull(catalogue); requireNonNull(filePath); File file = new File(filePath); FileUtil.createIfMissing(file); - XmlFileStorage.saveDataToFile(file, new XmlSerializableAddressBook(addressBook)); + XmlFileStorage.saveDataToFile(file, new XmlSerializableCatalogue(catalogue)); } } diff --git a/src/main/java/seedu/address/storage/XmlFileStorage.java b/src/main/java/seedu/address/storage/XmlFileStorage.java index 289fcb63038e..1f8519a871af 100644 --- a/src/main/java/seedu/address/storage/XmlFileStorage.java +++ b/src/main/java/seedu/address/storage/XmlFileStorage.java @@ -15,10 +15,10 @@ public class XmlFileStorage { /** * Saves the given addressbook data to the specified file. */ - public static void saveDataToFile(File file, XmlSerializableAddressBook addressBook) + public static void saveDataToFile(File file, XmlSerializableCatalogue catalogue) throws FileNotFoundException { try { - XmlUtil.saveDataToFile(file, addressBook); + XmlUtil.saveDataToFile(file, catalogue); } catch (JAXBException e) { throw new AssertionError("Unexpected exception " + e.getMessage()); } @@ -27,10 +27,10 @@ public static void saveDataToFile(File file, XmlSerializableAddressBook addressB /** * Returns address book in the file or an empty address book */ - public static XmlSerializableAddressBook loadDataFromSaveFile(File file) throws DataConversionException, + public static XmlSerializableCatalogue loadDataFromSaveFile(File file) throws DataConversionException, FileNotFoundException { try { - return XmlUtil.getDataFromFile(file, XmlSerializableAddressBook.class); + return XmlUtil.getDataFromFile(file, XmlSerializableCatalogue.class); } catch (JAXBException e) { throw new DataConversionException(e); } diff --git a/src/main/java/seedu/address/storage/XmlSerializableAddressBook.java b/src/main/java/seedu/address/storage/XmlSerializableCatalogue.java similarity index 61% rename from src/main/java/seedu/address/storage/XmlSerializableAddressBook.java rename to src/main/java/seedu/address/storage/XmlSerializableCatalogue.java index dc820896c312..11b7c8c91b90 100644 --- a/src/main/java/seedu/address/storage/XmlSerializableAddressBook.java +++ b/src/main/java/seedu/address/storage/XmlSerializableCatalogue.java @@ -8,14 +8,14 @@ import javax.xml.bind.annotation.XmlRootElement; import seedu.address.commons.exceptions.IllegalValueException; -import seedu.address.model.AddressBook; -import seedu.address.model.ReadOnlyAddressBook; +import seedu.address.model.Catalogue; +import seedu.address.model.ReadOnlyCatalogue; /** - * An Immutable AddressBook that is serializable to XML format + * An Immutable Catalogue that is serializable to XML format */ -@XmlRootElement(name = "addressbook") -public class XmlSerializableAddressBook { +@XmlRootElement(name = "catalogue") +public class XmlSerializableCatalogue { @XmlElement private List persons; @@ -23,10 +23,10 @@ public class XmlSerializableAddressBook { private List tags; /** - * Creates an empty XmlSerializableAddressBook. + * Creates an empty XmlSerializableCatalogue. * This empty constructor is required for marshalling. */ - public XmlSerializableAddressBook() { + public XmlSerializableCatalogue() { persons = new ArrayList<>(); tags = new ArrayList<>(); } @@ -34,27 +34,27 @@ public XmlSerializableAddressBook() { /** * Conversion */ - public XmlSerializableAddressBook(ReadOnlyAddressBook src) { + public XmlSerializableCatalogue(ReadOnlyCatalogue src) { this(); persons.addAll(src.getPersonList().stream().map(XmlAdaptedPerson::new).collect(Collectors.toList())); tags.addAll(src.getTagList().stream().map(XmlAdaptedTag::new).collect(Collectors.toList())); } /** - * Converts this addressbook into the model's {@code AddressBook} object. + * Converts this catalogue into the model's {@code Catalogue} object. * * @throws IllegalValueException if there were any data constraints violated or duplicates in the * {@code XmlAdaptedPerson} or {@code XmlAdaptedTag}. */ - public AddressBook toModelType() throws IllegalValueException { - AddressBook addressBook = new AddressBook(); + public Catalogue toModelType() throws IllegalValueException { + Catalogue catalogue = new Catalogue(); for (XmlAdaptedTag t : tags) { - addressBook.addTag(t.toModelType()); + catalogue.addTag(t.toModelType()); } for (XmlAdaptedPerson p : persons) { - addressBook.addPerson(p.toModelType()); + catalogue.addPerson(p.toModelType()); } - return addressBook; + return catalogue; } @Override @@ -63,11 +63,11 @@ public boolean equals(Object other) { return true; } - if (!(other instanceof XmlSerializableAddressBook)) { + if (!(other instanceof XmlSerializableCatalogue)) { return false; } - XmlSerializableAddressBook otherAb = (XmlSerializableAddressBook) other; + XmlSerializableCatalogue otherAb = (XmlSerializableCatalogue) other; return persons.equals(otherAb.persons) && tags.equals(otherAb.tags); } } diff --git a/src/main/java/seedu/address/ui/MainWindow.java b/src/main/java/seedu/address/ui/MainWindow.java index 20ad5fee906a..213985f026a1 100644 --- a/src/main/java/seedu/address/ui/MainWindow.java +++ b/src/main/java/seedu/address/ui/MainWindow.java @@ -125,7 +125,7 @@ void fillInnerParts() { ResultDisplay resultDisplay = new ResultDisplay(); resultDisplayPlaceholder.getChildren().add(resultDisplay.getRoot()); - StatusBarFooter statusBarFooter = new StatusBarFooter(prefs.getAddressBookFilePath()); + StatusBarFooter statusBarFooter = new StatusBarFooter(prefs.getCatalogueFilePath()); statusbarPlaceholder.getChildren().add(statusBarFooter.getRoot()); CommandBox commandBox = new CommandBox(logic); diff --git a/src/main/java/seedu/address/ui/PersonCard.java b/src/main/java/seedu/address/ui/PersonCard.java index f6727ea83abd..9ea2b86b4b7d 100644 --- a/src/main/java/seedu/address/ui/PersonCard.java +++ b/src/main/java/seedu/address/ui/PersonCard.java @@ -19,7 +19,7 @@ public class PersonCard extends UiPart { * 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 Catalogue level 4 */ public final Person person; diff --git a/src/main/java/seedu/address/ui/StatusBarFooter.java b/src/main/java/seedu/address/ui/StatusBarFooter.java index 06fb7e50c935..101f63dad24a 100644 --- a/src/main/java/seedu/address/ui/StatusBarFooter.java +++ b/src/main/java/seedu/address/ui/StatusBarFooter.java @@ -12,7 +12,7 @@ import javafx.fxml.FXML; import javafx.scene.layout.Region; import seedu.address.commons.core.LogsCenter; -import seedu.address.commons.events.model.AddressBookChangedEvent; +import seedu.address.commons.events.model.CatalogueChangedEvent; /** * A ui for the status bar that is displayed at the footer of the application. @@ -72,7 +72,7 @@ private void setSyncStatus(String status) { } @Subscribe - public void handleAddressBookChangedEvent(AddressBookChangedEvent abce) { + public void handleCatalogueChangedEvent(CatalogueChangedEvent abce) { long now = clock.millis(); String lastUpdated = new Date(now).toString(); logger.info(LogsCenter.getEventHandlingLogMessage(abce, "Setting last updated status to " + lastUpdated)); diff --git a/src/test/data/XmlSerializableAddressBookTest/typicalPersonsAddressBook.xml b/src/test/data/XmlSerializableAddressBookTest/typicalPersonsAddressBook.xml index c778cccc4c89..f647a77a8c39 100644 --- a/src/test/data/XmlSerializableAddressBookTest/typicalPersonsAddressBook.xml +++ b/src/test/data/XmlSerializableAddressBookTest/typicalPersonsAddressBook.xml @@ -1,5 +1,5 @@ - diff --git a/src/test/java/seedu/address/TestApp.java b/src/test/java/seedu/address/TestApp.java index 5b32c8faec9d..2ff4bb77b030 100644 --- a/src/test/java/seedu/address/TestApp.java +++ b/src/test/java/seedu/address/TestApp.java @@ -11,13 +11,13 @@ import seedu.address.commons.exceptions.DataConversionException; import seedu.address.commons.util.FileUtil; import seedu.address.commons.util.XmlUtil; -import seedu.address.model.AddressBook; +import seedu.address.model.Catalogue; import seedu.address.model.Model; import seedu.address.model.ModelManager; -import seedu.address.model.ReadOnlyAddressBook; +import seedu.address.model.ReadOnlyCatalogue; import seedu.address.model.UserPrefs; import seedu.address.storage.UserPrefsStorage; -import seedu.address.storage.XmlSerializableAddressBook; +import seedu.address.storage.XmlSerializableCatalogue; import seedu.address.testutil.TestUtil; import systemtests.ModelHelper; @@ -33,20 +33,20 @@ public class TestApp extends MainApp { protected static final String DEFAULT_PREF_FILE_LOCATION_FOR_TESTING = TestUtil.getFilePathInSandboxFolder("pref_testing.json"); protected static final String ADDRESS_BOOK_NAME = "Test"; - protected Supplier initialDataSupplier = () -> null; + protected Supplier initialDataSupplier = () -> null; protected String saveFileLocation = SAVE_LOCATION_FOR_TESTING; public TestApp() { } - public TestApp(Supplier initialDataSupplier, String saveFileLocation) { + public TestApp(Supplier initialDataSupplier, String saveFileLocation) { super(); this.initialDataSupplier = initialDataSupplier; this.saveFileLocation = saveFileLocation; // If some initial local data has been provided, write those to the file if (initialDataSupplier.get() != null) { - createDataFileWithData(new XmlSerializableAddressBook(this.initialDataSupplier.get()), + createDataFileWithData(new XmlSerializableCatalogue(this.initialDataSupplier.get()), this.saveFileLocation); } } @@ -65,19 +65,19 @@ protected UserPrefs initPrefs(UserPrefsStorage storage) { double x = Screen.getPrimary().getVisualBounds().getMinX(); double y = Screen.getPrimary().getVisualBounds().getMinY(); userPrefs.updateLastUsedGuiSetting(new GuiSettings(600.0, 600.0, (int) x, (int) y)); - userPrefs.setAddressBookFilePath(saveFileLocation); - userPrefs.setAddressBookName(ADDRESS_BOOK_NAME); + userPrefs.setCatalogueFilePath(saveFileLocation); + userPrefs.setCatalogueBookName(ADDRESS_BOOK_NAME); return userPrefs; } /** * Returns a defensive copy of the address book data stored inside the storage file. */ - public AddressBook readStorageAddressBook() { + public Catalogue readStorageCatalogue() { try { - return new AddressBook(storage.readAddressBook().get()); + return new Catalogue(storage.readCatalogue().get()); } catch (DataConversionException dce) { - throw new AssertionError("Data is not in the AddressBook format."); + throw new AssertionError("Data is not in the Catalogue format."); } catch (IOException ioe) { throw new AssertionError("Storage file cannot be found."); } @@ -87,14 +87,14 @@ public AddressBook readStorageAddressBook() { * Returns the file path of the storage file. */ public String getStorageSaveLocation() { - return storage.getAddressBookFilePath(); + return storage.getCatalogueFilePath(); } /** * Returns a defensive copy of the model. */ public Model getModel() { - Model copy = new ModelManager((model.getAddressBook()), new UserPrefs()); + Model copy = new ModelManager((model.getCatalogue()), new UserPrefs()); ModelHelper.setFilteredList(copy, model.getFilteredPersonList()); return copy; } diff --git a/src/test/java/seedu/address/commons/util/XmlUtilTest.java b/src/test/java/seedu/address/commons/util/XmlUtilTest.java index 56b6ef8f40d3..6d0eb1d59615 100644 --- a/src/test/java/seedu/address/commons/util/XmlUtilTest.java +++ b/src/test/java/seedu/address/commons/util/XmlUtilTest.java @@ -14,11 +14,11 @@ import org.junit.Test; import org.junit.rules.ExpectedException; -import seedu.address.model.AddressBook; +import seedu.address.model.Catalogue; import seedu.address.storage.XmlAdaptedPerson; import seedu.address.storage.XmlAdaptedTag; -import seedu.address.storage.XmlSerializableAddressBook; -import seedu.address.testutil.AddressBookBuilder; +import seedu.address.storage.XmlSerializableCatalogue; +import seedu.address.testutil.CatalogueBuilder; import seedu.address.testutil.PersonBuilder; import seedu.address.testutil.TestUtil; @@ -47,7 +47,7 @@ public class XmlUtilTest { @Test public void getDataFromFile_nullFile_throwsNullPointerException() throws Exception { thrown.expect(NullPointerException.class); - XmlUtil.getDataFromFile(null, AddressBook.class); + XmlUtil.getDataFromFile(null, Catalogue.class); } @Test @@ -59,18 +59,18 @@ public void getDataFromFile_nullClass_throwsNullPointerException() throws Except @Test public void getDataFromFile_missingFile_fileNotFoundException() throws Exception { thrown.expect(FileNotFoundException.class); - XmlUtil.getDataFromFile(MISSING_FILE, AddressBook.class); + XmlUtil.getDataFromFile(MISSING_FILE, Catalogue.class); } @Test public void getDataFromFile_emptyFile_dataFormatMismatchException() throws Exception { thrown.expect(JAXBException.class); - XmlUtil.getDataFromFile(EMPTY_FILE, AddressBook.class); + XmlUtil.getDataFromFile(EMPTY_FILE, Catalogue.class); } @Test public void getDataFromFile_validFile_validResult() throws Exception { - AddressBook dataFromFile = XmlUtil.getDataFromFile(VALID_FILE, XmlSerializableAddressBook.class).toModelType(); + Catalogue dataFromFile = XmlUtil.getDataFromFile(VALID_FILE, XmlSerializableCatalogue.class).toModelType(); assertEquals(9, dataFromFile.getPersonList().size()); assertEquals(0, dataFromFile.getTagList().size()); } @@ -105,7 +105,7 @@ public void xmlAdaptedPersonFromFile_fileWithValidPerson_validResult() throws Ex @Test public void saveDataToFile_nullFile_throwsNullPointerException() throws Exception { thrown.expect(NullPointerException.class); - XmlUtil.saveDataToFile(null, new AddressBook()); + XmlUtil.saveDataToFile(null, new Catalogue()); } @Test @@ -117,23 +117,23 @@ public void saveDataToFile_nullClass_throwsNullPointerException() throws Excepti @Test public void saveDataToFile_missingFile_fileNotFoundException() throws Exception { thrown.expect(FileNotFoundException.class); - XmlUtil.saveDataToFile(MISSING_FILE, new AddressBook()); + XmlUtil.saveDataToFile(MISSING_FILE, new Catalogue()); } @Test public void saveDataToFile_validFile_dataSaved() throws Exception { TEMP_FILE.createNewFile(); - XmlSerializableAddressBook dataToWrite = new XmlSerializableAddressBook(new AddressBook()); + XmlSerializableCatalogue dataToWrite = new XmlSerializableCatalogue(new Catalogue()); XmlUtil.saveDataToFile(TEMP_FILE, dataToWrite); - XmlSerializableAddressBook dataFromFile = XmlUtil.getDataFromFile(TEMP_FILE, XmlSerializableAddressBook.class); + XmlSerializableCatalogue dataFromFile = XmlUtil.getDataFromFile(TEMP_FILE, XmlSerializableCatalogue.class); assertEquals(dataToWrite, dataFromFile); - AddressBookBuilder builder = new AddressBookBuilder(new AddressBook()); - dataToWrite = new XmlSerializableAddressBook( + CatalogueBuilder builder = new CatalogueBuilder(new Catalogue()); + dataToWrite = new XmlSerializableCatalogue( builder.withPerson(new PersonBuilder().build()).withTag("Friends").build()); XmlUtil.saveDataToFile(TEMP_FILE, dataToWrite); - dataFromFile = XmlUtil.getDataFromFile(TEMP_FILE, XmlSerializableAddressBook.class); + dataFromFile = XmlUtil.getDataFromFile(TEMP_FILE, XmlSerializableCatalogue.class); assertEquals(dataToWrite, dataFromFile); } diff --git a/src/test/java/seedu/address/logic/LogicManagerTest.java b/src/test/java/seedu/address/logic/LogicManagerTest.java index 954c1fb04388..dab45263a7bd 100644 --- a/src/test/java/seedu/address/logic/LogicManagerTest.java +++ b/src/test/java/seedu/address/logic/LogicManagerTest.java @@ -82,7 +82,7 @@ private void assertCommandException(String inputCommand, String expectedMessage) * @see #assertCommandBehavior(Class, String, String, Model) */ private void assertCommandFailure(String inputCommand, Class expectedException, String expectedMessage) { - Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); + Model expectedModel = new ModelManager(model.getCatalogue(), new UserPrefs()); assertCommandBehavior(expectedException, inputCommand, expectedMessage, expectedModel); } diff --git a/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java b/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java index d3ff5043e126..9ca132de4a93 100644 --- a/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java +++ b/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java @@ -2,7 +2,7 @@ import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure; import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; -import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; +import static seedu.address.testutil.TypicalPersons.getTypicalCatalogue; import org.junit.Before; import org.junit.Test; @@ -24,14 +24,14 @@ public class AddCommandIntegrationTest { @Before public void setUp() { - model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + model = new ModelManager(getTypicalCatalogue(), new UserPrefs()); } @Test public void execute_newPerson_success() throws Exception { Person validPerson = new PersonBuilder().build(); - Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); + Model expectedModel = new ModelManager(model.getCatalogue(), new UserPrefs()); expectedModel.addPerson(validPerson); assertCommandSuccess(prepareCommand(validPerson, model), model, @@ -40,7 +40,7 @@ public void execute_newPerson_success() throws Exception { @Test public void execute_duplicatePerson_throwsCommandException() { - Person personInList = model.getAddressBook().getPersonList().get(0); + Person personInList = model.getCatalogue().getPersonList().get(0); assertCommandFailure(prepareCommand(personInList, model), model, AddCommand.MESSAGE_DUPLICATE_PERSON); } diff --git a/src/test/java/seedu/address/logic/commands/AddCommandTest.java b/src/test/java/seedu/address/logic/commands/AddCommandTest.java index 461cf09d1217..f8678b5ff808 100644 --- a/src/test/java/seedu/address/logic/commands/AddCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddCommandTest.java @@ -18,9 +18,9 @@ import seedu.address.logic.CommandHistory; import seedu.address.logic.UndoRedoStack; import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.AddressBook; +import seedu.address.model.Catalogue; import seedu.address.model.Model; -import seedu.address.model.ReadOnlyAddressBook; +import seedu.address.model.ReadOnlyCatalogue; import seedu.address.model.person.Person; import seedu.address.model.person.exceptions.DuplicatePersonException; import seedu.address.model.person.exceptions.PersonNotFoundException; @@ -102,12 +102,12 @@ public void addPerson(Person person) throws DuplicatePersonException { } @Override - public void resetData(ReadOnlyAddressBook newData) { + public void resetData(ReadOnlyCatalogue newData) { fail("This method should not be called."); } @Override - public ReadOnlyAddressBook getAddressBook() { + public ReadOnlyCatalogue getCatalogue() { fail("This method should not be called."); return null; } @@ -145,8 +145,8 @@ public void addPerson(Person person) throws DuplicatePersonException { } @Override - public ReadOnlyAddressBook getAddressBook() { - return new AddressBook(); + public ReadOnlyCatalogue getCatalogue() { + return new Catalogue(); } } @@ -163,8 +163,8 @@ public void addPerson(Person person) throws DuplicatePersonException { } @Override - public ReadOnlyAddressBook getAddressBook() { - return new AddressBook(); + public ReadOnlyCatalogue getCatalogue() { + return new Catalogue(); } } diff --git a/src/test/java/seedu/address/logic/commands/ClearCommandTest.java b/src/test/java/seedu/address/logic/commands/ClearCommandTest.java index 445ba20f9b00..9c56664bf75c 100644 --- a/src/test/java/seedu/address/logic/commands/ClearCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/ClearCommandTest.java @@ -1,7 +1,7 @@ package seedu.address.logic.commands; import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; -import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; +import static seedu.address.testutil.TypicalPersons.getTypicalCatalogue; import org.junit.Test; @@ -14,14 +14,14 @@ public class ClearCommandTest { @Test - public void execute_emptyAddressBook_success() { + public void execute_emptyCatalogue_success() { Model model = new ModelManager(); assertCommandSuccess(prepareCommand(model), model, ClearCommand.MESSAGE_SUCCESS, model); } @Test - public void execute_nonEmptyAddressBook_success() { - Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + public void execute_nonEmptyCatalogue_success() { + Model model = new ModelManager(getTypicalCatalogue(), new UserPrefs()); assertCommandSuccess(prepareCommand(model), model, ClearCommand.MESSAGE_SUCCESS, model); } diff --git a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java index 9a5679cc29b6..862fbd10eb94 100644 --- a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java +++ b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java @@ -17,7 +17,7 @@ import seedu.address.logic.CommandHistory; import seedu.address.logic.UndoRedoStack; import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.AddressBook; +import seedu.address.model.Catalogue; import seedu.address.model.Model; import seedu.address.model.person.NameContainsKeywordsPredicate; import seedu.address.model.person.Person; @@ -97,7 +97,7 @@ public static void assertCommandSuccess(Command command, Model actualModel, Stri public static void assertCommandFailure(Command command, Model actualModel, String expectedMessage) { // we are unable to defensively copy the model for comparison later, so we can // only do so by copying its components. - AddressBook expectedAddressBook = new AddressBook(actualModel.getAddressBook()); + Catalogue expectedCatalogue = new Catalogue(actualModel.getCatalogue()); List expectedFilteredList = new ArrayList<>(actualModel.getFilteredPersonList()); try { @@ -105,7 +105,7 @@ public static void assertCommandFailure(Command command, Model actualModel, Stri fail("The expected CommandException was not thrown."); } catch (CommandException e) { assertEquals(expectedMessage, e.getMessage()); - assertEquals(expectedAddressBook, actualModel.getAddressBook()); + assertEquals(expectedCatalogue, actualModel.getCatalogue()); assertEquals(expectedFilteredList, actualModel.getFilteredPersonList()); } } diff --git a/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java index 866e6a9be32a..ac98e886befc 100644 --- a/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java @@ -10,7 +10,7 @@ import static seedu.address.logic.commands.CommandTestUtil.showPersonAtIndex; import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON; -import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; +import static seedu.address.testutil.TypicalPersons.getTypicalCatalogue; import org.junit.Test; @@ -29,7 +29,7 @@ */ public class DeleteCommandTest { - private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + private Model model = new ModelManager(getTypicalCatalogue(), new UserPrefs()); @Test public void execute_validIndexUnfilteredList_success() throws Exception { @@ -38,7 +38,7 @@ public void execute_validIndexUnfilteredList_success() throws Exception { String expectedMessage = String.format(DeleteCommand.MESSAGE_DELETE_PERSON_SUCCESS, personToDelete); - ModelManager expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); + ModelManager expectedModel = new ModelManager(model.getCatalogue(), new UserPrefs()); expectedModel.deletePerson(personToDelete); assertCommandSuccess(deleteCommand, model, expectedMessage, expectedModel); @@ -61,7 +61,7 @@ public void execute_validIndexFilteredList_success() throws Exception { String expectedMessage = String.format(DeleteCommand.MESSAGE_DELETE_PERSON_SUCCESS, personToDelete); - Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); + Model expectedModel = new ModelManager(model.getCatalogue(), new UserPrefs()); expectedModel.deletePerson(personToDelete); showNoPerson(expectedModel); @@ -74,7 +74,7 @@ public void execute_invalidIndexFilteredList_throwsCommandException() { Index outOfBoundIndex = INDEX_SECOND_PERSON; // ensures that outOfBoundIndex is still in bounds of address book list - assertTrue(outOfBoundIndex.getZeroBased() < model.getAddressBook().getPersonList().size()); + assertTrue(outOfBoundIndex.getZeroBased() < model.getCatalogue().getPersonList().size()); DeleteCommand deleteCommand = prepareCommand(outOfBoundIndex); @@ -88,7 +88,7 @@ public void executeUndoRedo_validIndexUnfilteredList_success() throws Exception RedoCommand redoCommand = prepareRedoCommand(model, undoRedoStack); Person personToDelete = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); DeleteCommand deleteCommand = prepareCommand(INDEX_FIRST_PERSON); - Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); + Model expectedModel = new ModelManager(model.getCatalogue(), new UserPrefs()); // delete -> first person deleted deleteCommand.execute(); @@ -131,7 +131,7 @@ public void executeUndoRedo_validIndexFilteredList_samePersonDeleted() throws Ex UndoCommand undoCommand = prepareUndoCommand(model, undoRedoStack); RedoCommand redoCommand = prepareRedoCommand(model, undoRedoStack); DeleteCommand deleteCommand = prepareCommand(INDEX_FIRST_PERSON); - Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); + Model expectedModel = new ModelManager(model.getCatalogue(), new UserPrefs()); showPersonAtIndex(model, INDEX_SECOND_PERSON); Person personToDelete = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); diff --git a/src/test/java/seedu/address/logic/commands/EditCommandTest.java b/src/test/java/seedu/address/logic/commands/EditCommandTest.java index a8b104d3a81d..84022cbf900c 100644 --- a/src/test/java/seedu/address/logic/commands/EditCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/EditCommandTest.java @@ -15,7 +15,7 @@ import static seedu.address.logic.commands.CommandTestUtil.showPersonAtIndex; import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON; -import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; +import static seedu.address.testutil.TypicalPersons.getTypicalCatalogue; import org.junit.Test; @@ -24,7 +24,7 @@ import seedu.address.logic.CommandHistory; import seedu.address.logic.UndoRedoStack; import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; -import seedu.address.model.AddressBook; +import seedu.address.model.Catalogue; import seedu.address.model.Model; import seedu.address.model.ModelManager; import seedu.address.model.UserPrefs; @@ -37,7 +37,7 @@ */ public class EditCommandTest { - private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + private Model model = new ModelManager(getTypicalCatalogue(), new UserPrefs()); @Test public void execute_allFieldsSpecifiedUnfilteredList_success() throws Exception { @@ -47,7 +47,7 @@ public void execute_allFieldsSpecifiedUnfilteredList_success() throws Exception String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson); - Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); + Model expectedModel = new ModelManager(new Catalogue(model.getCatalogue()), new UserPrefs()); expectedModel.updatePerson(model.getFilteredPersonList().get(0), editedPerson); assertCommandSuccess(editCommand, model, expectedMessage, expectedModel); @@ -68,7 +68,7 @@ public void execute_someFieldsSpecifiedUnfilteredList_success() throws Exception String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson); - Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); + Model expectedModel = new ModelManager(new Catalogue(model.getCatalogue()), new UserPrefs()); expectedModel.updatePerson(lastPerson, editedPerson); assertCommandSuccess(editCommand, model, expectedMessage, expectedModel); @@ -81,7 +81,7 @@ public void execute_noFieldSpecifiedUnfilteredList_success() { String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson); - Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); + Model expectedModel = new ModelManager(new Catalogue(model.getCatalogue()), new UserPrefs()); assertCommandSuccess(editCommand, model, expectedMessage, expectedModel); } @@ -97,7 +97,7 @@ public void execute_filteredList_success() throws Exception { String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson); - Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); + Model expectedModel = new ModelManager(new Catalogue(model.getCatalogue()), new UserPrefs()); expectedModel.updatePerson(model.getFilteredPersonList().get(0), editedPerson); assertCommandSuccess(editCommand, model, expectedMessage, expectedModel); @@ -117,7 +117,7 @@ public void execute_duplicatePersonFilteredList_failure() { showPersonAtIndex(model, INDEX_FIRST_PERSON); // edit person in filtered list into a duplicate in address book - Person personInList = model.getAddressBook().getPersonList().get(INDEX_SECOND_PERSON.getZeroBased()); + Person personInList = model.getCatalogue().getPersonList().get(INDEX_SECOND_PERSON.getZeroBased()); EditCommand editCommand = prepareCommand(INDEX_FIRST_PERSON, new EditPersonDescriptorBuilder(personInList).build()); @@ -142,7 +142,7 @@ public void execute_invalidPersonIndexFilteredList_failure() { showPersonAtIndex(model, INDEX_FIRST_PERSON); Index outOfBoundIndex = INDEX_SECOND_PERSON; // ensures that outOfBoundIndex is still in bounds of address book list - assertTrue(outOfBoundIndex.getZeroBased() < model.getAddressBook().getPersonList().size()); + assertTrue(outOfBoundIndex.getZeroBased() < model.getCatalogue().getPersonList().size()); EditCommand editCommand = prepareCommand(outOfBoundIndex, new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB).build()); @@ -159,7 +159,7 @@ public void executeUndoRedo_validIndexUnfilteredList_success() throws Exception Person personToEdit = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(editedPerson).build(); EditCommand editCommand = prepareCommand(INDEX_FIRST_PERSON, descriptor); - Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); + Model expectedModel = new ModelManager(new Catalogue(model.getCatalogue()), new UserPrefs()); // edit -> first person edited editCommand.execute(); @@ -205,7 +205,7 @@ public void executeUndoRedo_validIndexFilteredList_samePersonEdited() throws Exc Person editedPerson = new PersonBuilder().build(); EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(editedPerson).build(); EditCommand editCommand = prepareCommand(INDEX_FIRST_PERSON, descriptor); - Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); + Model expectedModel = new ModelManager(new Catalogue(model.getCatalogue()), new UserPrefs()); showPersonAtIndex(model, INDEX_SECOND_PERSON); Person personToEdit = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); diff --git a/src/test/java/seedu/address/logic/commands/FindCommandTest.java b/src/test/java/seedu/address/logic/commands/FindCommandTest.java index dee1f007f751..19ab56514735 100644 --- a/src/test/java/seedu/address/logic/commands/FindCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/FindCommandTest.java @@ -7,7 +7,7 @@ import static seedu.address.testutil.TypicalPersons.CARL; import static seedu.address.testutil.TypicalPersons.ELLE; import static seedu.address.testutil.TypicalPersons.FIONA; -import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; +import static seedu.address.testutil.TypicalPersons.getTypicalCatalogue; import java.util.Arrays; import java.util.Collections; @@ -17,7 +17,7 @@ import seedu.address.logic.CommandHistory; import seedu.address.logic.UndoRedoStack; -import seedu.address.model.AddressBook; +import seedu.address.model.Catalogue; import seedu.address.model.Model; import seedu.address.model.ModelManager; import seedu.address.model.UserPrefs; @@ -28,7 +28,7 @@ * Contains integration tests (interaction with the Model) for {@code FindCommand}. */ public class FindCommandTest { - private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + private Model model = new ModelManager(getTypicalCatalogue(), new UserPrefs()); @Test public void equals() { @@ -85,14 +85,14 @@ private FindCommand prepareCommand(String userInput) { * Asserts that {@code command} is successfully executed, and
* - the command feedback is equal to {@code expectedMessage}
* - the {@code FilteredList} is equal to {@code expectedList}
- * - the {@code AddressBook} in model remains the same after executing the {@code command} + * - the {@code Catalogue} in model remains the same after executing the {@code command} */ private void assertCommandSuccess(FindCommand command, String expectedMessage, List expectedList) { - AddressBook expectedAddressBook = new AddressBook(model.getAddressBook()); + Catalogue expectedCatalogue = new Catalogue(model.getCatalogue()); CommandResult commandResult = command.execute(); assertEquals(expectedMessage, commandResult.feedbackToUser); assertEquals(expectedList, model.getFilteredPersonList()); - assertEquals(expectedAddressBook, model.getAddressBook()); + assertEquals(expectedCatalogue, model.getCatalogue()); } } diff --git a/src/test/java/seedu/address/logic/commands/ListCommandTest.java b/src/test/java/seedu/address/logic/commands/ListCommandTest.java index 4ee519e3668e..6229a109cf11 100644 --- a/src/test/java/seedu/address/logic/commands/ListCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/ListCommandTest.java @@ -3,7 +3,7 @@ import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; import static seedu.address.logic.commands.CommandTestUtil.showPersonAtIndex; import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; -import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; +import static seedu.address.testutil.TypicalPersons.getTypicalCatalogue; import org.junit.Before; import org.junit.Test; @@ -25,8 +25,8 @@ public class ListCommandTest { @Before public void setUp() { - model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); - expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); + model = new ModelManager(getTypicalCatalogue(), new UserPrefs()); + expectedModel = new ModelManager(model.getCatalogue(), new UserPrefs()); listCommand = new ListCommand(); listCommand.setData(model, new CommandHistory(), new UndoRedoStack()); diff --git a/src/test/java/seedu/address/logic/commands/RedoCommandTest.java b/src/test/java/seedu/address/logic/commands/RedoCommandTest.java index e615f089a4f2..3b4df7e8816a 100644 --- a/src/test/java/seedu/address/logic/commands/RedoCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/RedoCommandTest.java @@ -6,7 +6,7 @@ import static seedu.address.logic.commands.CommandTestUtil.deleteFirstPerson; import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON; -import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; +import static seedu.address.testutil.TypicalPersons.getTypicalCatalogue; import java.util.Arrays; import java.util.Collections; @@ -24,7 +24,7 @@ public class RedoCommandTest { private static final CommandHistory EMPTY_COMMAND_HISTORY = new CommandHistory(); private static final UndoRedoStack EMPTY_STACK = new UndoRedoStack(); - private final Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + private final Model model = new ModelManager(getTypicalCatalogue(), new UserPrefs()); private final DeleteCommand deleteCommandOne = new DeleteCommand(INDEX_FIRST_PERSON); private final DeleteCommand deleteCommandTwo = new DeleteCommand(INDEX_SECOND_PERSON); @@ -42,7 +42,7 @@ public void execute() { Collections.emptyList(), Arrays.asList(deleteCommandTwo, deleteCommandOne)); RedoCommand redoCommand = new RedoCommand(); redoCommand.setData(model, EMPTY_COMMAND_HISTORY, undoRedoStack); - Model expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + Model expectedModel = new ModelManager(getTypicalCatalogue(), new UserPrefs()); // multiple commands in redoStack deleteFirstPerson(expectedModel); diff --git a/src/test/java/seedu/address/logic/commands/SelectCommandTest.java b/src/test/java/seedu/address/logic/commands/SelectCommandTest.java index 4840900602ac..206992089755 100644 --- a/src/test/java/seedu/address/logic/commands/SelectCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/SelectCommandTest.java @@ -8,7 +8,7 @@ import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON; import static seedu.address.testutil.TypicalIndexes.INDEX_THIRD_PERSON; -import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; +import static seedu.address.testutil.TypicalPersons.getTypicalCatalogue; import org.junit.Before; import org.junit.Rule; @@ -36,7 +36,7 @@ public class SelectCommandTest { @Before public void setUp() { - model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + model = new ModelManager(getTypicalCatalogue(), new UserPrefs()); } @Test @@ -68,7 +68,7 @@ public void execute_invalidIndexFilteredList_failure() { Index outOfBoundsIndex = INDEX_SECOND_PERSON; // ensures that outOfBoundIndex is still in bounds of address book list - assertTrue(outOfBoundsIndex.getZeroBased() < model.getAddressBook().getPersonList().size()); + assertTrue(outOfBoundsIndex.getZeroBased() < model.getCatalogue().getPersonList().size()); assertExecutionFailure(outOfBoundsIndex, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); } diff --git a/src/test/java/seedu/address/logic/commands/UndoCommandTest.java b/src/test/java/seedu/address/logic/commands/UndoCommandTest.java index 3eb5f2f18346..bef3b9d9b8dd 100644 --- a/src/test/java/seedu/address/logic/commands/UndoCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/UndoCommandTest.java @@ -5,7 +5,7 @@ import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; import static seedu.address.logic.commands.CommandTestUtil.deleteFirstPerson; import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; -import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; +import static seedu.address.testutil.TypicalPersons.getTypicalCatalogue; import java.util.Arrays; import java.util.Collections; @@ -23,7 +23,7 @@ public class UndoCommandTest { private static final CommandHistory EMPTY_COMMAND_HISTORY = new CommandHistory(); private static final UndoRedoStack EMPTY_STACK = new UndoRedoStack(); - private final Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + private final Model model = new ModelManager(getTypicalCatalogue(), new UserPrefs()); private final DeleteCommand deleteCommandOne = new DeleteCommand(INDEX_FIRST_PERSON); private final DeleteCommand deleteCommandTwo = new DeleteCommand(INDEX_FIRST_PERSON); @@ -43,12 +43,12 @@ public void execute() throws Exception { deleteCommandTwo.execute(); // multiple commands in undoStack - Model expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + Model expectedModel = new ModelManager(getTypicalCatalogue(), new UserPrefs()); deleteFirstPerson(expectedModel); assertCommandSuccess(undoCommand, model, UndoCommand.MESSAGE_SUCCESS, expectedModel); // single command in undoStack - expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + expectedModel = new ModelManager(getTypicalCatalogue(), new UserPrefs()); assertCommandSuccess(undoCommand, model, UndoCommand.MESSAGE_SUCCESS, expectedModel); // no command in undoStack diff --git a/src/test/java/seedu/address/logic/commands/UndoableCommandTest.java b/src/test/java/seedu/address/logic/commands/UndoableCommandTest.java index 7d00a7471b86..18bb7b1cf455 100644 --- a/src/test/java/seedu/address/logic/commands/UndoableCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/UndoableCommandTest.java @@ -5,7 +5,7 @@ import static seedu.address.logic.commands.CommandTestUtil.deleteFirstPerson; import static seedu.address.logic.commands.CommandTestUtil.showPersonAtIndex; import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; -import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; +import static seedu.address.testutil.TypicalPersons.getTypicalCatalogue; import org.junit.Test; @@ -17,10 +17,10 @@ import seedu.address.model.person.exceptions.PersonNotFoundException; public class UndoableCommandTest { - private final Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + private final Model model = new ModelManager(getTypicalCatalogue(), new UserPrefs()); private final DummyCommand dummyCommand = new DummyCommand(model); - private Model expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + private Model expectedModel = new ModelManager(getTypicalCatalogue(), new UserPrefs()); @Test public void executeUndo() throws Exception { @@ -32,7 +32,7 @@ public void executeUndo() throws Exception { // undo() should cause the model's filtered list to show all persons dummyCommand.undo(); - expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + expectedModel = new ModelManager(getTypicalCatalogue(), new UserPrefs()); assertEquals(expectedModel, model); } diff --git a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java b/src/test/java/seedu/address/logic/parser/CatalogueParserTest.java similarity index 98% rename from src/test/java/seedu/address/logic/parser/AddressBookParserTest.java rename to src/test/java/seedu/address/logic/parser/CatalogueParserTest.java index 7466da232666..94299ac6446e 100644 --- a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java +++ b/src/test/java/seedu/address/logic/parser/CatalogueParserTest.java @@ -35,11 +35,11 @@ import seedu.address.testutil.PersonBuilder; import seedu.address.testutil.PersonUtil; -public class AddressBookParserTest { +public class CatalogueParserTest { @Rule public ExpectedException thrown = ExpectedException.none(); - private final AddressBookParser parser = new AddressBookParser(); + private final CatalogueParser parser = new CatalogueParser(); @Test public void parseCommand_add() throws Exception { diff --git a/src/test/java/seedu/address/model/AddressBookTest.java b/src/test/java/seedu/address/model/CatalogueTest.java similarity index 78% rename from src/test/java/seedu/address/model/AddressBookTest.java rename to src/test/java/seedu/address/model/CatalogueTest.java index 172fa62f2b49..b56c21e0af88 100644 --- a/src/test/java/seedu/address/model/AddressBookTest.java +++ b/src/test/java/seedu/address/model/CatalogueTest.java @@ -2,7 +2,7 @@ import static org.junit.Assert.assertEquals; import static seedu.address.testutil.TypicalPersons.ALICE; -import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; +import static seedu.address.testutil.TypicalPersons.getTypicalCatalogue; import java.util.ArrayList; import java.util.Arrays; @@ -19,12 +19,12 @@ import seedu.address.model.person.Person; import seedu.address.model.tag.Tag; -public class AddressBookTest { +public class CatalogueTest { @Rule public ExpectedException thrown = ExpectedException.none(); - private final AddressBook catalogue = new AddressBook(); + private final Catalogue catalogue = new Catalogue(); @Test public void constructor() { @@ -39,8 +39,8 @@ public void resetData_null_throwsNullPointerException() { } @Test - public void resetData_withValidReadOnlyAddressBook_replacesData() { - AddressBook newData = getTypicalAddressBook(); + public void resetData_withValidReadOnlyCatalogue_replacesData() { + Catalogue newData = getTypicalCatalogue(); catalogue.resetData(newData); assertEquals(newData, catalogue); } @@ -50,7 +50,7 @@ public void resetData_withDuplicatePersons_throwsAssertionError() { // Repeat ALICE twice List newPersons = Arrays.asList(ALICE, ALICE); List newTags = new ArrayList<>(ALICE.getTags()); - AddressBookStub newData = new AddressBookStub(newPersons, newTags); + CatalogueStub newData = new CatalogueStub(newPersons, newTags); thrown.expect(AssertionError.class); catalogue.resetData(newData); @@ -69,13 +69,13 @@ public void getTagList_modifyList_throwsUnsupportedOperationException() { } /** - * A stub ReadOnlyAddressBook whose persons and tags lists can violate interface constraints. + * A stub ReadOnlyCatalogue whose persons and tags lists can violate interface constraints. */ - private static class AddressBookStub implements ReadOnlyAddressBook { + private static class CatalogueStub implements ReadOnlyCatalogue { private final ObservableList persons = FXCollections.observableArrayList(); private final ObservableList tags = FXCollections.observableArrayList(); - AddressBookStub(Collection persons, Collection tags) { + CatalogueStub(Collection persons, Collection tags) { this.persons.setAll(persons); this.tags.setAll(tags); } diff --git a/src/test/java/seedu/address/model/ModelManagerTest.java b/src/test/java/seedu/address/model/ModelManagerTest.java index 59ce1b83693a..9ff92bf21455 100644 --- a/src/test/java/seedu/address/model/ModelManagerTest.java +++ b/src/test/java/seedu/address/model/ModelManagerTest.java @@ -13,7 +13,7 @@ import org.junit.rules.ExpectedException; import seedu.address.model.person.NameContainsKeywordsPredicate; -import seedu.address.testutil.AddressBookBuilder; +import seedu.address.testutil.CatalogueBuilder; public class ModelManagerTest { @Rule @@ -28,13 +28,13 @@ public void getFilteredPersonList_modifyList_throwsUnsupportedOperationException @Test public void equals() { - AddressBook addressBook = new AddressBookBuilder().withPerson(ALICE).withPerson(BENSON).build(); - AddressBook differentAddressBook = new AddressBook(); + Catalogue catalogue = new CatalogueBuilder().withPerson(ALICE).withPerson(BENSON).build(); + Catalogue differentCatalogue = new Catalogue(); UserPrefs userPrefs = new UserPrefs(); // same values -> returns true - ModelManager modelManager = new ModelManager(addressBook, userPrefs); - ModelManager modelManagerCopy = new ModelManager(addressBook, userPrefs); + ModelManager modelManager = new ModelManager(catalogue, userPrefs); + ModelManager modelManagerCopy = new ModelManager(catalogue, userPrefs); assertTrue(modelManager.equals(modelManagerCopy)); // same object -> returns true @@ -46,20 +46,20 @@ public void equals() { // different types -> returns false assertFalse(modelManager.equals(5)); - // different addressBook -> returns false - assertFalse(modelManager.equals(new ModelManager(differentAddressBook, userPrefs))); + // different catalogue -> returns false + assertFalse(modelManager.equals(new ModelManager(differentCatalogue, userPrefs))); // different filteredList -> returns false String[] keywords = ALICE.getName().fullName.split("\\s+"); modelManager.updateFilteredPersonList(new NameContainsKeywordsPredicate(Arrays.asList(keywords))); - assertFalse(modelManager.equals(new ModelManager(addressBook, userPrefs))); + assertFalse(modelManager.equals(new ModelManager(catalogue, userPrefs))); // resets modelManager to initial state for upcoming tests modelManager.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); // different userPrefs -> returns true UserPrefs differentUserPrefs = new UserPrefs(); - differentUserPrefs.setAddressBookName("differentName"); - assertTrue(modelManager.equals(new ModelManager(addressBook, differentUserPrefs))); + differentUserPrefs.setCatalogueBookName("differentName"); + assertTrue(modelManager.equals(new ModelManager(catalogue, differentUserPrefs))); } } diff --git a/src/test/java/seedu/address/storage/JsonUserPrefsStorageTest.java b/src/test/java/seedu/address/storage/JsonUserPrefsStorageTest.java index a6854c246da9..8129422eb845 100644 --- a/src/test/java/seedu/address/storage/JsonUserPrefsStorageTest.java +++ b/src/test/java/seedu/address/storage/JsonUserPrefsStorageTest.java @@ -82,8 +82,8 @@ public void readUserPrefs_extraValuesInFile_extraValuesIgnored() throws DataConv private UserPrefs getTypicalUserPrefs() { UserPrefs userPrefs = new UserPrefs(); userPrefs.setGuiSettings(1000, 500, 300, 100); - userPrefs.setAddressBookFilePath("addressbook.xml"); - userPrefs.setAddressBookName("TypicalAddressBookName"); + userPrefs.setCatalogueFilePath("addressbook.xml"); + userPrefs.setCatalogueBookName("TypicalAddressBookName"); return userPrefs; } diff --git a/src/test/java/seedu/address/storage/StorageManagerTest.java b/src/test/java/seedu/address/storage/StorageManagerTest.java index eb93fc628aed..12729db517c8 100644 --- a/src/test/java/seedu/address/storage/StorageManagerTest.java +++ b/src/test/java/seedu/address/storage/StorageManagerTest.java @@ -3,7 +3,7 @@ import static junit.framework.TestCase.assertNotNull; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; +import static seedu.address.testutil.TypicalPersons.getTypicalCatalogue; import java.io.IOException; @@ -12,10 +12,10 @@ import org.junit.Test; import org.junit.rules.TemporaryFolder; -import seedu.address.commons.events.model.AddressBookChangedEvent; +import seedu.address.commons.events.model.CatalogueChangedEvent; import seedu.address.commons.events.storage.DataSavingExceptionEvent; -import seedu.address.model.AddressBook; -import seedu.address.model.ReadOnlyAddressBook; +import seedu.address.model.Catalogue; +import seedu.address.model.ReadOnlyCatalogue; import seedu.address.model.UserPrefs; import seedu.address.ui.testutil.EventsCollectorRule; @@ -30,9 +30,9 @@ public class StorageManagerTest { @Before public void setUp() { - XmlCatalogueStorage addressBookStorage = new XmlCatalogueStorage(getTempFilePath("ab")); + XmlCatalogueStorage catalogueStorage = new XmlCatalogueStorage(getTempFilePath("ab")); JsonUserPrefsStorage userPrefsStorage = new JsonUserPrefsStorage(getTempFilePath("prefs")); - storageManager = new StorageManager(addressBookStorage, userPrefsStorage); + storageManager = new StorageManager(catalogueStorage, userPrefsStorage); } private String getTempFilePath(String fileName) { @@ -55,29 +55,29 @@ public void prefsReadSave() throws Exception { } @Test - public void addressBookReadSave() throws Exception { + public void catalogueReadSave() throws Exception { /* * Note: This is an integration test that verifies the StorageManager is properly wired to the * {@link XmlCatalogueStorage} class. * More extensive testing of UserPref saving/reading is done in {@link XmlCatalogueStorageTest} class. */ - AddressBook original = getTypicalAddressBook(); - storageManager.saveAddressBook(original); - ReadOnlyAddressBook retrieved = storageManager.readAddressBook().get(); - assertEquals(original, new AddressBook(retrieved)); + Catalogue original = getTypicalCatalogue(); + storageManager.saveCatalogue(original); + ReadOnlyCatalogue retrieved = storageManager.readCatalogue().get(); + assertEquals(original, new Catalogue(retrieved)); } @Test - public void getAddressBookFilePath() { - assertNotNull(storageManager.getAddressBookFilePath()); + public void getCatalogueFilePath() { + assertNotNull(storageManager.getCatalogueFilePath()); } @Test - public void handleAddressBookChangedEvent_exceptionThrown_eventRaised() { + public void handleCatalogueChangedEvent_exceptionThrown_eventRaised() { // Create a StorageManager while injecting a stub that throws an exception when the save method is called Storage storage = new StorageManager(new XmlCatalogueStorageExceptionThrowingStub("dummy"), new JsonUserPrefsStorage("dummy")); - storage.handleAddressBookChangedEvent(new AddressBookChangedEvent(new AddressBook())); + storage.handleCatalogueChangedEvent(new CatalogueChangedEvent(new Catalogue())); assertTrue(eventsCollectorRule.eventsCollector.getMostRecent() instanceof DataSavingExceptionEvent); } @@ -92,7 +92,7 @@ public XmlCatalogueStorageExceptionThrowingStub(String filePath) { } @Override - public void saveAddressBook(ReadOnlyAddressBook addressBook, String filePath) throws IOException { + public void saveCatalogue(ReadOnlyCatalogue catalogue, String filePath) throws IOException { throw new IOException("dummy exception"); } } diff --git a/src/test/java/seedu/address/storage/XmlCatalogueStorageTest.java b/src/test/java/seedu/address/storage/XmlCatalogueStorageTest.java index b910ed70b60e..7165e2aa4fee 100644 --- a/src/test/java/seedu/address/storage/XmlCatalogueStorageTest.java +++ b/src/test/java/seedu/address/storage/XmlCatalogueStorageTest.java @@ -5,7 +5,7 @@ import static seedu.address.testutil.TypicalPersons.ALICE; import static seedu.address.testutil.TypicalPersons.HOON; import static seedu.address.testutil.TypicalPersons.IDA; -import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; +import static seedu.address.testutil.TypicalPersons.getTypicalCatalogue; import java.io.IOException; @@ -16,8 +16,8 @@ import seedu.address.commons.exceptions.DataConversionException; import seedu.address.commons.util.FileUtil; -import seedu.address.model.AddressBook; -import seedu.address.model.ReadOnlyAddressBook; +import seedu.address.model.Catalogue; +import seedu.address.model.ReadOnlyCatalogue; public class XmlCatalogueStorageTest { private static final String TEST_DATA_FOLDER = FileUtil.getPath("./src/test/data/XmlCatalogueStorageTest/"); @@ -29,13 +29,13 @@ public class XmlCatalogueStorageTest { public TemporaryFolder testFolder = new TemporaryFolder(); @Test - public void readAddressBook_nullFilePath_throwsNullPointerException() throws Exception { + public void readCatalogue_nullFilePath_throwsNullPointerException() throws Exception { thrown.expect(NullPointerException.class); - readAddressBook(null); + readCatalogue(null); } - private java.util.Optional readAddressBook(String filePath) throws Exception { - return new XmlCatalogueStorage(filePath).readAddressBook(addToTestDataPathIfNotNull(filePath)); + private java.util.Optional readCatalogue(String filePath) throws Exception { + return new XmlCatalogueStorage(filePath).readCatalogue(addToTestDataPathIfNotNull(filePath)); } private String addToTestDataPathIfNotNull(String prefsFileInTestDataFolder) { @@ -46,14 +46,14 @@ private String addToTestDataPathIfNotNull(String prefsFileInTestDataFolder) { @Test public void read_missingFile_emptyResult() throws Exception { - assertFalse(readAddressBook("NonExistentFile.xml").isPresent()); + assertFalse(readCatalogue("NonExistentFile.xml").isPresent()); } @Test public void read_notXmlFormat_exceptionThrown() throws Exception { thrown.expect(DataConversionException.class); - readAddressBook("NotXmlFormatAddressBook.xml"); + readCatalogue("NotXmlFormatAddressBook.xml"); /* IMPORTANT: Any code below an exception-throwing line (like the one above) will be ignored. * That means you should not have more than one exception test in one method @@ -61,64 +61,64 @@ public void read_notXmlFormat_exceptionThrown() throws Exception { } @Test - public void readAddressBook_invalidPersonAddressBook_throwDataConversionException() throws Exception { + public void readCatalogue_invalidPersonCatalogue_throwDataConversionException() throws Exception { thrown.expect(DataConversionException.class); - readAddressBook("invalidPersonAddressBook.xml"); + readCatalogue("invalidPersonAddressBook.xml"); } @Test - public void readAddressBook_invalidAndValidPersonAddressBook_throwDataConversionException() throws Exception { + public void readCatalogue_invalidAndValidPersonCatalogue_throwDataConversionException() throws Exception { thrown.expect(DataConversionException.class); - readAddressBook("invalidAndValidPersonAddressBook.xml"); + readCatalogue("invalidAndValidPersonAddressBook.xml"); } @Test - public void readAndSaveAddressBook_allInOrder_success() throws Exception { + public void readAndSaveCatalogue_allInOrder_success() throws Exception { String filePath = testFolder.getRoot().getPath() + "TempAddressBook.xml"; - AddressBook original = getTypicalAddressBook(); - XmlCatalogueStorage xmlAddressBookStorage = new XmlCatalogueStorage(filePath); + Catalogue original = getTypicalCatalogue(); + XmlCatalogueStorage xmlCatalogueStorage = new XmlCatalogueStorage(filePath); //Save in new file and read back - xmlAddressBookStorage.saveAddressBook(original, filePath); - ReadOnlyAddressBook readBack = xmlAddressBookStorage.readAddressBook(filePath).get(); - assertEquals(original, new AddressBook(readBack)); + xmlCatalogueStorage.saveCatalogue(original, filePath); + ReadOnlyCatalogue readBack = xmlCatalogueStorage.readCatalogue(filePath).get(); + assertEquals(original, new Catalogue(readBack)); //Modify data, overwrite exiting file, and read back original.addPerson(HOON); original.removePerson(ALICE); - xmlAddressBookStorage.saveAddressBook(original, filePath); - readBack = xmlAddressBookStorage.readAddressBook(filePath).get(); - assertEquals(original, new AddressBook(readBack)); + xmlCatalogueStorage.saveCatalogue(original, filePath); + readBack = xmlCatalogueStorage.readCatalogue(filePath).get(); + assertEquals(original, new Catalogue(readBack)); //Save and read without specifying file path original.addPerson(IDA); - xmlAddressBookStorage.saveAddressBook(original); //file path not specified - readBack = xmlAddressBookStorage.readAddressBook().get(); //file path not specified - assertEquals(original, new AddressBook(readBack)); + xmlCatalogueStorage.saveCatalogue(original); //file path not specified + readBack = xmlCatalogueStorage.readCatalogue().get(); //file path not specified + assertEquals(original, new Catalogue(readBack)); } @Test - public void saveAddressBook_nullAddressBook_throwsNullPointerException() { + public void saveCatalogue_nullCatalogue_throwsNullPointerException() { thrown.expect(NullPointerException.class); - saveAddressBook(null, "SomeFile.xml"); + saveCatalogue(null, "SomeFile.xml"); } /** - * Saves {@code addressBook} at the specified {@code filePath}. + * Saves {@code catalogue} at the specified {@code filePath}. */ - private void saveAddressBook(ReadOnlyAddressBook addressBook, String filePath) { + private void saveCatalogue(ReadOnlyCatalogue catalogue, String filePath) { try { - new XmlCatalogueStorage(filePath).saveAddressBook(addressBook, addToTestDataPathIfNotNull(filePath)); + new XmlCatalogueStorage(filePath).saveCatalogue(catalogue, addToTestDataPathIfNotNull(filePath)); } catch (IOException ioe) { throw new AssertionError("There should not be an error writing to the file.", ioe); } } @Test - public void saveAddressBook_nullFilePath_throwsNullPointerException() throws IOException { + public void saveCatalogue_nullFilePath_throwsNullPointerException() throws IOException { thrown.expect(NullPointerException.class); - saveAddressBook(new AddressBook(), null); + saveCatalogue(new Catalogue(), null); } diff --git a/src/test/java/seedu/address/storage/XmlSerializableAddressBookTest.java b/src/test/java/seedu/address/storage/XmlSerializableCatalogueTest.java similarity index 62% rename from src/test/java/seedu/address/storage/XmlSerializableAddressBookTest.java rename to src/test/java/seedu/address/storage/XmlSerializableCatalogueTest.java index cf405c9729c1..f5099d8cbe1e 100644 --- a/src/test/java/seedu/address/storage/XmlSerializableAddressBookTest.java +++ b/src/test/java/seedu/address/storage/XmlSerializableCatalogueTest.java @@ -11,12 +11,12 @@ import seedu.address.commons.exceptions.IllegalValueException; import seedu.address.commons.util.FileUtil; import seedu.address.commons.util.XmlUtil; -import seedu.address.model.AddressBook; +import seedu.address.model.Catalogue; import seedu.address.testutil.TypicalPersons; -public class XmlSerializableAddressBookTest { +public class XmlSerializableCatalogueTest { - private static final String TEST_DATA_FOLDER = FileUtil.getPath("src/test/data/XmlSerializableAddressBookTest/"); + private static final String TEST_DATA_FOLDER = FileUtil.getPath("src/test/data/XmlSerializableCatalogueTest/"); private static final File TYPICAL_PERSONS_FILE = new File(TEST_DATA_FOLDER + "typicalPersonsAddressBook.xml"); private static final File INVALID_PERSON_FILE = new File(TEST_DATA_FOLDER + "invalidPersonAddressBook.xml"); private static final File INVALID_TAG_FILE = new File(TEST_DATA_FOLDER + "invalidTagAddressBook.xml"); @@ -26,25 +26,25 @@ public class XmlSerializableAddressBookTest { @Test public void toModelType_typicalPersonsFile_success() throws Exception { - XmlSerializableAddressBook dataFromFile = XmlUtil.getDataFromFile(TYPICAL_PERSONS_FILE, - XmlSerializableAddressBook.class); - AddressBook addressBookFromFile = dataFromFile.toModelType(); - AddressBook typicalPersonsAddressBook = TypicalPersons.getTypicalAddressBook(); - assertEquals(addressBookFromFile, typicalPersonsAddressBook); + XmlSerializableCatalogue dataFromFile = XmlUtil.getDataFromFile(TYPICAL_PERSONS_FILE, + XmlSerializableCatalogue.class); + Catalogue catalogueFromFile = dataFromFile.toModelType(); + Catalogue typicalPersonsCatalogue = TypicalPersons.getTypicalCatalogue(); + assertEquals(catalogueFromFile, typicalPersonsCatalogue); } @Test public void toModelType_invalidPersonFile_throwsIllegalValueException() throws Exception { - XmlSerializableAddressBook dataFromFile = XmlUtil.getDataFromFile(INVALID_PERSON_FILE, - XmlSerializableAddressBook.class); + XmlSerializableCatalogue dataFromFile = XmlUtil.getDataFromFile(INVALID_PERSON_FILE, + XmlSerializableCatalogue.class); thrown.expect(IllegalValueException.class); dataFromFile.toModelType(); } @Test public void toModelType_invalidTagFile_throwsIllegalValueException() throws Exception { - XmlSerializableAddressBook dataFromFile = XmlUtil.getDataFromFile(INVALID_TAG_FILE, - XmlSerializableAddressBook.class); + XmlSerializableCatalogue dataFromFile = XmlUtil.getDataFromFile(INVALID_TAG_FILE, + XmlSerializableCatalogue.class); thrown.expect(IllegalValueException.class); dataFromFile.toModelType(); } diff --git a/src/test/java/seedu/address/testutil/AddressBookBuilder.java b/src/test/java/seedu/address/testutil/AddressBookBuilder.java deleted file mode 100644 index 6e73a762b0c1..000000000000 --- a/src/test/java/seedu/address/testutil/AddressBookBuilder.java +++ /dev/null @@ -1,53 +0,0 @@ -package seedu.address.testutil; - -import seedu.address.commons.exceptions.IllegalValueException; -import seedu.address.model.AddressBook; -import seedu.address.model.person.Person; -import seedu.address.model.person.exceptions.DuplicatePersonException; -import seedu.address.model.tag.Tag; - -/** - * A utility class to help with building Addressbook objects. - * Example usage:
- * {@code AddressBook ab = new AddressBookBuilder().withPerson("John", "Doe").withTag("Friend").build();} - */ -public class AddressBookBuilder { - - private AddressBook addressBook; - - public AddressBookBuilder() { - addressBook = new AddressBook(); - } - - public AddressBookBuilder(AddressBook addressBook) { - this.addressBook = addressBook; - } - - /** - * Adds a new {@code Person} to the {@code AddressBook} that we are building. - */ - public AddressBookBuilder withPerson(Person person) { - try { - addressBook.addPerson(person); - } catch (DuplicatePersonException dpe) { - throw new IllegalArgumentException("person is expected to be unique."); - } - return this; - } - - /** - * Parses {@code tagName} into a {@code Tag} and adds it to the {@code AddressBook} that we are building. - */ - public AddressBookBuilder withTag(String tagName) { - try { - addressBook.addTag(new Tag(tagName)); - } catch (IllegalValueException ive) { - throw new IllegalArgumentException("tagName is expected to be valid."); - } - return this; - } - - public AddressBook build() { - return addressBook; - } -} diff --git a/src/test/java/seedu/address/testutil/CatalogueBuilder.java b/src/test/java/seedu/address/testutil/CatalogueBuilder.java new file mode 100644 index 000000000000..5cee787d0122 --- /dev/null +++ b/src/test/java/seedu/address/testutil/CatalogueBuilder.java @@ -0,0 +1,53 @@ +package seedu.address.testutil; + +import seedu.address.commons.exceptions.IllegalValueException; +import seedu.address.model.Catalogue; +import seedu.address.model.person.Person; +import seedu.address.model.person.exceptions.DuplicatePersonException; +import seedu.address.model.tag.Tag; + +/** + * A utility class to help with building Catalogue objects. + * Example usage:
+ * {@code Catalogue ab = new CatalogueBuilder().withPerson("John", "Doe").withTag("Friend").build();} + */ +public class CatalogueBuilder { + + private Catalogue catalogue; + + public CatalogueBuilder() { + catalogue = new Catalogue(); + } + + public CatalogueBuilder(Catalogue catalogue) { + this.catalogue = catalogue; + } + + /** + * Adds a new {@code Person} to the {@code Catalogue} that we are building. + */ + public CatalogueBuilder withPerson(Person person) { + try { + catalogue.addPerson(person); + } catch (DuplicatePersonException dpe) { + throw new IllegalArgumentException("person is expected to be unique."); + } + return this; + } + + /** + * Parses {@code tagName} into a {@code Tag} and adds it to the {@code Catalogue} that we are building. + */ + public CatalogueBuilder withTag(String tagName) { + try { + catalogue.addTag(new Tag(tagName)); + } catch (IllegalValueException ive) { + throw new IllegalArgumentException("tagName is expected to be valid."); + } + return this; + } + + public Catalogue build() { + return catalogue; + } +} diff --git a/src/test/java/seedu/address/testutil/TestUtil.java b/src/test/java/seedu/address/testutil/TestUtil.java index c1458738c054..b66c57bc94a6 100644 --- a/src/test/java/seedu/address/testutil/TestUtil.java +++ b/src/test/java/seedu/address/testutil/TestUtil.java @@ -35,20 +35,20 @@ public static String getFilePathInSandboxFolder(String fileName) { * Returns the middle index of the person in the {@code model}'s person list. */ public static Index getMidIndex(Model model) { - return Index.fromOneBased(model.getAddressBook().getPersonList().size() / 2); + return Index.fromOneBased(model.getCatalogue().getPersonList().size() / 2); } /** * Returns the last index of the person in the {@code model}'s person list. */ public static Index getLastIndex(Model model) { - return Index.fromOneBased(model.getAddressBook().getPersonList().size()); + return Index.fromOneBased(model.getCatalogue().getPersonList().size()); } /** * Returns the person in the {@code model}'s person list at {@code index}. */ public static Person getPerson(Model model, Index index) { - return model.getAddressBook().getPersonList().get(index.getZeroBased()); + return model.getCatalogue().getPersonList().get(index.getZeroBased()); } } diff --git a/src/test/java/seedu/address/testutil/TypicalPersons.java b/src/test/java/seedu/address/testutil/TypicalPersons.java index 6d7bdbfc55ed..06a7770c5259 100644 --- a/src/test/java/seedu/address/testutil/TypicalPersons.java +++ b/src/test/java/seedu/address/testutil/TypicalPersons.java @@ -15,7 +15,7 @@ import java.util.Arrays; import java.util.List; -import seedu.address.model.AddressBook; +import seedu.address.model.Catalogue; import seedu.address.model.person.Person; import seedu.address.model.person.exceptions.DuplicatePersonException; @@ -61,10 +61,10 @@ public class TypicalPersons { private TypicalPersons() {} // prevents instantiation /** - * Returns an {@code AddressBook} with all the typical persons. + * Returns an {@code Catalogue} with all the typical persons. */ - public static AddressBook getTypicalAddressBook() { - AddressBook ab = new AddressBook(); + public static Catalogue getTypicalCatalogue() { + Catalogue ab = new Catalogue(); for (Person person : getTypicalPersons()) { try { ab.addPerson(person); diff --git a/src/test/java/seedu/address/ui/GuiUnitTest.java b/src/test/java/seedu/address/ui/GuiUnitTest.java index f1ff0656725a..b139add4fa54 100644 --- a/src/test/java/seedu/address/ui/GuiUnitTest.java +++ b/src/test/java/seedu/address/ui/GuiUnitTest.java @@ -12,7 +12,7 @@ import seedu.address.ui.testutil.UiPartRule; /** - * A GUI unit test class for AddressBook. + * A GUI unit test class for Catalogue. */ public abstract class GuiUnitTest { @Rule diff --git a/src/test/java/seedu/address/ui/StatusBarFooterTest.java b/src/test/java/seedu/address/ui/StatusBarFooterTest.java index 0c75a73b1864..721aacb10f21 100644 --- a/src/test/java/seedu/address/ui/StatusBarFooterTest.java +++ b/src/test/java/seedu/address/ui/StatusBarFooterTest.java @@ -16,15 +16,15 @@ import org.junit.Test; import guitests.guihandles.StatusBarFooterHandle; -import seedu.address.commons.events.model.AddressBookChangedEvent; -import seedu.address.model.AddressBook; +import seedu.address.commons.events.model.CatalogueChangedEvent; +import seedu.address.model.Catalogue; public class StatusBarFooterTest extends GuiUnitTest { private static final String STUB_SAVE_LOCATION = "Stub"; private static final String RELATIVE_PATH = "./"; - private static final AddressBookChangedEvent EVENT_STUB = new AddressBookChangedEvent(new AddressBook()); + private static final CatalogueChangedEvent EVENT_STUB = new CatalogueChangedEvent(new Catalogue()); private static final Clock originalClock = StatusBarFooter.getClock(); private static final Clock injectedClock = Clock.fixed(Instant.now(), ZoneId.systemDefault()); diff --git a/src/test/java/systemtests/AddCommandSystemTest.java b/src/test/java/systemtests/AddCommandSystemTest.java index 3254b60154c4..e54d9a31f636 100644 --- a/src/test/java/systemtests/AddCommandSystemTest.java +++ b/src/test/java/systemtests/AddCommandSystemTest.java @@ -52,7 +52,7 @@ import seedu.address.testutil.PersonBuilder; import seedu.address.testutil.PersonUtil; -public class AddCommandSystemTest extends AddressBookSystemTest { +public class AddCommandSystemTest extends CatalogueSystemTest { @Test public void add() throws Exception { @@ -141,7 +141,7 @@ public void add() throws Exception { /* Case: add a duplicate person except with different tags -> rejected */ // "friends" is an existing tag used in the default model, see TypicalPersons#ALICE // This test will fail if a new tag that is not in the model is used, see the bug documented in - // AddressBook#addPerson(Person) + // Catalogue#addPerson(Person) command = PersonUtil.getAddCommand(HOON) + " " + PREFIX_TAG.getPrefix() + "friends"; assertCommandFailure(command, AddCommand.MESSAGE_DUPLICATE_PERSON); @@ -198,8 +198,8 @@ public void add() throws Exception { * 5. Browser url and selected card remain unchanged.
* 6. Status bar's sync status changes.
* Verifications 1, 3 and 4 are performed by - * {@code AddressBookSystemTest#assertApplicationDisplaysExpected(String, String, Model)}.
- * @see AddressBookSystemTest#assertApplicationDisplaysExpected(String, String, Model) + * {@code CatalogueSystemTest#assertApplicationDisplaysExpected(String, String, Model)}.
+ * @see CatalogueSystemTest#assertApplicationDisplaysExpected(String, String, Model) */ private void assertCommandSuccess(Person toAdd) { assertCommandSuccess(PersonUtil.getAddCommand(toAdd), toAdd); @@ -246,8 +246,8 @@ private void assertCommandSuccess(String command, Model expectedModel, String ex * 4. {@code Model}, {@code Storage} and {@code PersonListPanel} remain unchanged.
* 5. Browser url, selected card and status bar remain unchanged.
* Verifications 1, 3 and 4 are performed by - * {@code AddressBookSystemTest#assertApplicationDisplaysExpected(String, String, Model)}.
- * @see AddressBookSystemTest#assertApplicationDisplaysExpected(String, String, Model) + * {@code CatalogueSystemTest#assertApplicationDisplaysExpected(String, String, Model)}.
+ * @see CatalogueSystemTest#assertApplicationDisplaysExpected(String, String, Model) */ private void assertCommandFailure(String command, String expectedResultMessage) { Model expectedModel = getModel(); diff --git a/src/test/java/systemtests/AddressBookSystemTest.java b/src/test/java/systemtests/CatalogueSystemTest.java similarity index 94% rename from src/test/java/systemtests/AddressBookSystemTest.java rename to src/test/java/systemtests/CatalogueSystemTest.java index 97cdf96d65b8..7cc24486f0a2 100644 --- a/src/test/java/systemtests/AddressBookSystemTest.java +++ b/src/test/java/systemtests/CatalogueSystemTest.java @@ -36,17 +36,17 @@ import seedu.address.logic.commands.FindCommand; import seedu.address.logic.commands.ListCommand; import seedu.address.logic.commands.SelectCommand; -import seedu.address.model.AddressBook; +import seedu.address.model.Catalogue; import seedu.address.model.Model; import seedu.address.testutil.TypicalPersons; import seedu.address.ui.BrowserPanel; import seedu.address.ui.CommandBox; /** - * A system test class for AddressBook, which provides access to handles of GUI components and helper methods + * A system test class for Catalogue, which provides access to handles of GUI components and helper methods * for test verification. */ -public abstract class AddressBookSystemTest { +public abstract class CatalogueSystemTest { @ClassRule public static ClockRule clockRule = new ClockRule(); @@ -82,8 +82,8 @@ public void tearDown() throws Exception { /** * Returns the data to be loaded into the file in {@link #getDataFileLocation()}. */ - protected AddressBook getInitialData() { - return TypicalPersons.getTypicalAddressBook(); + protected Catalogue getInitialData() { + return TypicalPersons.getTypicalCatalogue(); } /** @@ -141,7 +141,7 @@ protected void executeCommand(String command) { */ protected void showAllPersons() { executeCommand(ListCommand.COMMAND_WORD); - assertEquals(getModel().getAddressBook().getPersonList().size(), getModel().getFilteredPersonList().size()); + assertEquals(getModel().getCatalogue().getPersonList().size(), getModel().getFilteredPersonList().size()); } /** @@ -149,7 +149,7 @@ protected void showAllPersons() { */ protected void showPersonsWithName(String keyword) { executeCommand(FindCommand.COMMAND_WORD + " " + keyword); - assertTrue(getModel().getFilteredPersonList().size() < getModel().getAddressBook().getPersonList().size()); + assertTrue(getModel().getFilteredPersonList().size() < getModel().getCatalogue().getPersonList().size()); } /** @@ -165,7 +165,7 @@ protected void selectPerson(Index index) { */ protected void deleteAllPersons() { executeCommand(ClearCommand.COMMAND_WORD); - assertEquals(0, getModel().getAddressBook().getPersonList().size()); + assertEquals(0, getModel().getCatalogue().getPersonList().size()); } /** @@ -178,7 +178,7 @@ protected void assertApplicationDisplaysExpected(String expectedCommandInput, St assertEquals(expectedCommandInput, getCommandBox().getInput()); assertEquals(expectedResultMessage, getResultDisplay().getText()); assertEquals(expectedModel, getModel()); - assertEquals(expectedModel.getAddressBook(), testApp.readStorageAddressBook()); + assertEquals(expectedModel.getCatalogue(), testApp.readStorageCatalogue()); assertListMatching(getPersonListPanel(), expectedModel.getFilteredPersonList()); } diff --git a/src/test/java/systemtests/ClearCommandSystemTest.java b/src/test/java/systemtests/ClearCommandSystemTest.java index 805a59784e29..dcb06bd08123 100644 --- a/src/test/java/systemtests/ClearCommandSystemTest.java +++ b/src/test/java/systemtests/ClearCommandSystemTest.java @@ -12,7 +12,7 @@ import seedu.address.model.Model; import seedu.address.model.ModelManager; -public class ClearCommandSystemTest extends AddressBookSystemTest { +public class ClearCommandSystemTest extends CatalogueSystemTest { @Test public void clear() { @@ -60,9 +60,9 @@ public void clear() { * Executes {@code command} and verifies that the command box displays an empty string, the result display * box displays {@code ClearCommand#MESSAGE_SUCCESS} and the model related components equal to an empty model. * These verifications are done by - * {@code AddressBookSystemTest#assertApplicationDisplaysExpected(String, String, Model)}.
+ * {@code CatalogueSystemTest#assertApplicationDisplaysExpected(String, String, Model)}.
* Also verifies that the command box has the default style class and the status bar's sync status changes. - * @see AddressBookSystemTest#assertApplicationDisplaysExpected(String, String, Model) + * @see CatalogueSystemTest#assertApplicationDisplaysExpected(String, String, Model) */ private void assertCommandSuccess(String command) { assertCommandSuccess(command, ClearCommand.MESSAGE_SUCCESS, new ModelManager()); @@ -84,10 +84,10 @@ private void assertCommandSuccess(String command, String expectedResultMessage, * Executes {@code command} and verifies that the command box displays {@code command}, the result display * box displays {@code expectedResultMessage} and the model related components equal to the current model. * These verifications are done by - * {@code AddressBookSystemTest#assertApplicationDisplaysExpected(String, String, Model)}.
+ * {@code CatalogueSystemTest#assertApplicationDisplaysExpected(String, String, Model)}.
* Also verifies that the browser url, selected card and status bar remain unchanged, and the command box has the * error style. - * @see AddressBookSystemTest#assertApplicationDisplaysExpected(String, String, Model) + * @see CatalogueSystemTest#assertApplicationDisplaysExpected(String, String, Model) */ private void assertCommandFailure(String command, String expectedResultMessage) { Model expectedModel = getModel(); diff --git a/src/test/java/systemtests/DeleteCommandSystemTest.java b/src/test/java/systemtests/DeleteCommandSystemTest.java index c0de78e4aba6..9d523baf122a 100644 --- a/src/test/java/systemtests/DeleteCommandSystemTest.java +++ b/src/test/java/systemtests/DeleteCommandSystemTest.java @@ -21,7 +21,7 @@ import seedu.address.model.person.Person; import seedu.address.model.person.exceptions.PersonNotFoundException; -public class DeleteCommandSystemTest extends AddressBookSystemTest { +public class DeleteCommandSystemTest extends CatalogueSystemTest { private static final String MESSAGE_INVALID_DELETE_COMMAND_FORMAT = String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE); @@ -69,7 +69,7 @@ public void delete() { * -> rejected */ showPersonsWithName(KEYWORD_MATCHING_MEIER); - int invalidIndex = getModel().getAddressBook().getPersonList().size(); + int invalidIndex = getModel().getCatalogue().getPersonList().size(); command = DeleteCommand.COMMAND_WORD + " " + invalidIndex; assertCommandFailure(command, MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); @@ -98,7 +98,7 @@ public void delete() { /* Case: invalid index (size + 1) -> rejected */ Index outOfBoundsIndex = Index.fromOneBased( - getModel().getAddressBook().getPersonList().size() + 1); + getModel().getCatalogue().getPersonList().size() + 1); command = DeleteCommand.COMMAND_WORD + " " + outOfBoundsIndex.getOneBased(); assertCommandFailure(command, MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); @@ -149,8 +149,8 @@ private void assertCommandSuccess(Index toDelete) { * 5. Asserts that the status bar's sync status changes.
* 6. Asserts that the command box has the default style class.
* Verifications 1 to 3 are performed by - * {@code AddressBookSystemTest#assertApplicationDisplaysExpected(String, String, Model)}. - * @see AddressBookSystemTest#assertApplicationDisplaysExpected(String, String, Model) + * {@code CatalogueSystemTest#assertApplicationDisplaysExpected(String, String, Model)}. + * @see CatalogueSystemTest#assertApplicationDisplaysExpected(String, String, Model) */ private void assertCommandSuccess(String command, Model expectedModel, String expectedResultMessage) { assertCommandSuccess(command, expectedModel, expectedResultMessage, null); @@ -160,7 +160,7 @@ private void assertCommandSuccess(String command, Model expectedModel, String ex * Performs the same verification as {@code assertCommandSuccess(String, Model, String)} except that the browser url * and selected card are expected to update accordingly depending on the card at {@code expectedSelectedCardIndex}. * @see DeleteCommandSystemTest#assertCommandSuccess(String, Model, String) - * @see AddressBookSystemTest#assertSelectedCardChanged(Index) + * @see CatalogueSystemTest#assertSelectedCardChanged(Index) */ private void assertCommandSuccess(String command, Model expectedModel, String expectedResultMessage, Index expectedSelectedCardIndex) { @@ -185,8 +185,8 @@ private void assertCommandSuccess(String command, Model expectedModel, String ex * 4. Asserts that the browser url, selected card and status bar remain unchanged.
* 5. Asserts that the command box has the error style.
* Verifications 1 to 3 are performed by - * {@code AddressBookSystemTest#assertApplicationDisplaysExpected(String, String, Model)}.
- * @see AddressBookSystemTest#assertApplicationDisplaysExpected(String, String, Model) + * {@code CatalogueSystemTest#assertApplicationDisplaysExpected(String, String, Model)}.
+ * @see CatalogueSystemTest#assertApplicationDisplaysExpected(String, String, Model) */ private void assertCommandFailure(String command, String expectedResultMessage) { Model expectedModel = getModel(); diff --git a/src/test/java/systemtests/EditCommandSystemTest.java b/src/test/java/systemtests/EditCommandSystemTest.java index 820933203dd9..c929e85a3db3 100644 --- a/src/test/java/systemtests/EditCommandSystemTest.java +++ b/src/test/java/systemtests/EditCommandSystemTest.java @@ -49,7 +49,7 @@ import seedu.address.testutil.PersonBuilder; import seedu.address.testutil.PersonUtil; -public class EditCommandSystemTest extends AddressBookSystemTest { +public class EditCommandSystemTest extends CatalogueSystemTest { @Test public void edit() throws Exception { @@ -112,7 +112,7 @@ public void edit() throws Exception { * -> rejected */ showPersonsWithName(KEYWORD_MATCHING_MEIER); - int invalidIndex = getModel().getAddressBook().getPersonList().size(); + int invalidIndex = getModel().getCatalogue().getPersonList().size(); assertCommandFailure(EditCommand.COMMAND_WORD + " " + invalidIndex + NAME_DESC_BOB, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); @@ -175,7 +175,7 @@ public void edit() throws Exception { /* Case: edit a person with new values same as another person's values -> rejected */ executeCommand(PersonUtil.getAddCommand(BOB)); - assertTrue(getModel().getAddressBook().getPersonList().contains(BOB)); + assertTrue(getModel().getCatalogue().getPersonList().contains(BOB)); index = INDEX_FIRST_PERSON; assertFalse(getModel().getFilteredPersonList().get(index.getZeroBased()).equals(BOB)); command = EditCommand.COMMAND_WORD + " " + index.getOneBased() + NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB @@ -241,9 +241,9 @@ private void assertCommandSuccess(String command, Model expectedModel, String ex * 5. Asserts that the status bar's sync status changes.
* 6. Asserts that the command box has the default style class.
* Verifications 1 to 3 are performed by - * {@code AddressBookSystemTest#assertApplicationDisplaysExpected(String, String, Model)}.
- * @see AddressBookSystemTest#assertApplicationDisplaysExpected(String, String, Model) - * @see AddressBookSystemTest#assertSelectedCardChanged(Index) + * {@code CatalogueSystemTest#assertApplicationDisplaysExpected(String, String, Model)}.
+ * @see CatalogueSystemTest#assertApplicationDisplaysExpected(String, String, Model) + * @see CatalogueSystemTest#assertSelectedCardChanged(Index) */ private void assertCommandSuccess(String command, Model expectedModel, String expectedResultMessage, Index expectedSelectedCardIndex) { @@ -267,8 +267,8 @@ private void assertCommandSuccess(String command, Model expectedModel, String ex * 4. Asserts that the browser url, selected card and status bar remain unchanged.
* 5. Asserts that the command box has the error style.
* Verifications 1 to 3 are performed by - * {@code AddressBookSystemTest#assertApplicationDisplaysExpected(String, String, Model)}.
- * @see AddressBookSystemTest#assertApplicationDisplaysExpected(String, String, Model) + * {@code CatalogueSystemTest#assertApplicationDisplaysExpected(String, String, Model)}.
+ * @see CatalogueSystemTest#assertApplicationDisplaysExpected(String, String, Model) */ private void assertCommandFailure(String command, String expectedResultMessage) { Model expectedModel = getModel(); diff --git a/src/test/java/systemtests/ErrorDialogGuiTest.java b/src/test/java/systemtests/ErrorDialogGuiTest.java index f8ec17fdb2a7..87149e28a4b6 100644 --- a/src/test/java/systemtests/ErrorDialogGuiTest.java +++ b/src/test/java/systemtests/ErrorDialogGuiTest.java @@ -14,7 +14,7 @@ import guitests.guihandles.AlertDialogHandle; import seedu.address.commons.events.storage.DataSavingExceptionEvent; -public class ErrorDialogGuiTest extends AddressBookSystemTest { +public class ErrorDialogGuiTest extends CatalogueSystemTest { private static final IOException IO_EXCEPTION_STUB = new IOException("Stub"); private final GuiRobot guiRobot = new GuiRobot(); diff --git a/src/test/java/systemtests/FindCommandSystemTest.java b/src/test/java/systemtests/FindCommandSystemTest.java index 0bde83c0444b..0b640b90aacf 100644 --- a/src/test/java/systemtests/FindCommandSystemTest.java +++ b/src/test/java/systemtests/FindCommandSystemTest.java @@ -21,7 +21,7 @@ import seedu.address.model.Model; import seedu.address.model.tag.Tag; -public class FindCommandSystemTest extends AddressBookSystemTest { +public class FindCommandSystemTest extends CatalogueSystemTest { @Test public void find() { @@ -82,7 +82,7 @@ public void find() { /* Case: find same persons in address book after deleting 1 of them -> 1 person found */ executeCommand(DeleteCommand.COMMAND_WORD + " 1"); - assertFalse(getModel().getAddressBook().getPersonList().contains(BENSON)); + assertFalse(getModel().getCatalogue().getPersonList().contains(BENSON)); command = FindCommand.COMMAND_WORD + " " + KEYWORD_MATCHING_MEIER; expectedModel = getModel(); ModelHelper.setFilteredList(expectedModel, DANIEL); @@ -159,10 +159,10 @@ public void find() { * box displays {@code Messages#MESSAGE_PERSONS_LISTED_OVERVIEW} with the number of people in the filtered list, * and the model related components equal to {@code expectedModel}. * These verifications are done by - * {@code AddressBookSystemTest#assertApplicationDisplaysExpected(String, String, Model)}.
+ * {@code CatalogueSystemTest#assertApplicationDisplaysExpected(String, String, Model)}.
* Also verifies that the status bar remains unchanged, and the command box has the default style class, and the * selected card updated accordingly, depending on {@code cardStatus}. - * @see AddressBookSystemTest#assertApplicationDisplaysExpected(String, String, Model) + * @see CatalogueSystemTest#assertApplicationDisplaysExpected(String, String, Model) */ private void assertCommandSuccess(String command, Model expectedModel) { String expectedResultMessage = String.format( @@ -178,10 +178,10 @@ private void assertCommandSuccess(String command, Model expectedModel) { * Executes {@code command} and verifies that the command box displays {@code command}, the result display * box displays {@code expectedResultMessage} and the model related components equal to the current model. * These verifications are done by - * {@code AddressBookSystemTest#assertApplicationDisplaysExpected(String, String, Model)}.
+ * {@code CatalogueSystemTest#assertApplicationDisplaysExpected(String, String, Model)}.
* Also verifies that the browser url, selected card and status bar remain unchanged, and the command box has the * error style. - * @see AddressBookSystemTest#assertApplicationDisplaysExpected(String, String, Model) + * @see CatalogueSystemTest#assertApplicationDisplaysExpected(String, String, Model) */ private void assertCommandFailure(String command, String expectedResultMessage) { Model expectedModel = getModel(); diff --git a/src/test/java/systemtests/HelpCommandSystemTest.java b/src/test/java/systemtests/HelpCommandSystemTest.java index 1aa4a5f294f4..940a33cdf808 100644 --- a/src/test/java/systemtests/HelpCommandSystemTest.java +++ b/src/test/java/systemtests/HelpCommandSystemTest.java @@ -20,7 +20,7 @@ /** * A system test class for the help window, which contains interaction with other UI components. */ -public class HelpCommandSystemTest extends AddressBookSystemTest { +public class HelpCommandSystemTest extends CatalogueSystemTest { private static final String ERROR_MESSAGE = "ATTENTION!!!! : On some computers, this test may fail when run on " + "non-headless mode as FxRobot#clickOn(Node, MouseButton...) clicks on the wrong location. We suspect " + "that this is a bug with TestFX library that we are using. If this test fails, you have to run your " diff --git a/src/test/java/systemtests/SampleDataTest.java b/src/test/java/systemtests/SampleDataTest.java index 81a32ce9487b..6fb70330dc73 100644 --- a/src/test/java/systemtests/SampleDataTest.java +++ b/src/test/java/systemtests/SampleDataTest.java @@ -8,17 +8,17 @@ import org.junit.Test; -import seedu.address.model.AddressBook; +import seedu.address.model.Catalogue; import seedu.address.model.person.Person; import seedu.address.model.util.SampleDataUtil; import seedu.address.testutil.TestUtil; -public class SampleDataTest extends AddressBookSystemTest { +public class SampleDataTest extends CatalogueSystemTest { /** * Returns null to force test app to load data of the file in {@code getDataFileLocation()}. */ @Override - protected AddressBook getInitialData() { + protected Catalogue getInitialData() { return null; } @@ -44,7 +44,7 @@ private void deleteFileIfExists(String filePath) { } @Test - public void addressBook_dataFileDoesNotExist_loadSampleData() { + public void catalogue_dataFileDoesNotExist_loadSampleData() { Person[] expectedList = SampleDataUtil.getSamplePersons(); assertListMatching(getPersonListPanel(), expectedList); } diff --git a/src/test/java/systemtests/SelectCommandSystemTest.java b/src/test/java/systemtests/SelectCommandSystemTest.java index c7deb73454b1..0ab7d1251b76 100644 --- a/src/test/java/systemtests/SelectCommandSystemTest.java +++ b/src/test/java/systemtests/SelectCommandSystemTest.java @@ -17,7 +17,7 @@ import seedu.address.logic.commands.UndoCommand; import seedu.address.model.Model; -public class SelectCommandSystemTest extends AddressBookSystemTest { +public class SelectCommandSystemTest extends CatalogueSystemTest { @Test public void select() { /* ------------------------ Perform select operations on the shown unfiltered list -------------------------- */ @@ -57,7 +57,7 @@ public void select() { * -> rejected */ showPersonsWithName(KEYWORD_MATCHING_MEIER); - int invalidIndex = getModel().getAddressBook().getPersonList().size(); + int invalidIndex = getModel().getCatalogue().getPersonList().size(); assertCommandFailure(SelectCommand.COMMAND_WORD + " " + invalidIndex, MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); /* Case: filtered person list, select index within bounds of address book and person list -> selected */ @@ -107,9 +107,9 @@ public void select() { * 5. Selected card is at {@code expectedSelectedCardIndex} and the browser url is updated accordingly.
* 6. Status bar remains unchanged.
* Verifications 1, 3 and 4 are performed by - * {@code AddressBookSystemTest#assertApplicationDisplaysExpected(String, String, Model)}.
- * @see AddressBookSystemTest#assertApplicationDisplaysExpected(String, String, Model) - * @see AddressBookSystemTest#assertSelectedCardChanged(Index) + * {@code CatalogueSystemTest#assertApplicationDisplaysExpected(String, String, Model)}.
+ * @see CatalogueSystemTest#assertApplicationDisplaysExpected(String, String, Model) + * @see CatalogueSystemTest#assertSelectedCardChanged(Index) */ private void assertCommandSuccess(String command, Index expectedSelectedCardIndex) { Model expectedModel = getModel(); @@ -138,8 +138,8 @@ private void assertCommandSuccess(String command, Index expectedSelectedCardInde * 4. {@code Model}, {@code Storage} and {@code PersonListPanel} remain unchanged.
* 5. Browser url, selected card and status bar remain unchanged.
* Verifications 1, 3 and 4 are performed by - * {@code AddressBookSystemTest#assertApplicationDisplaysExpected(String, String, Model)}.
- * @see AddressBookSystemTest#assertApplicationDisplaysExpected(String, String, Model) + * {@code CatalogueSystemTest#assertApplicationDisplaysExpected(String, String, Model)}.
+ * @see CatalogueSystemTest#assertApplicationDisplaysExpected(String, String, Model) */ private void assertCommandFailure(String command, String expectedResultMessage) { Model expectedModel = getModel(); diff --git a/src/test/java/systemtests/SystemTestSetupHelper.java b/src/test/java/systemtests/SystemTestSetupHelper.java index bc9773f954ba..eabd3cc968e7 100644 --- a/src/test/java/systemtests/SystemTestSetupHelper.java +++ b/src/test/java/systemtests/SystemTestSetupHelper.java @@ -8,7 +8,7 @@ import guitests.guihandles.MainWindowHandle; import javafx.stage.Stage; import seedu.address.TestApp; -import seedu.address.model.ReadOnlyAddressBook; +import seedu.address.model.ReadOnlyCatalogue; /** * Contains helper methods that system tests require. @@ -20,10 +20,10 @@ public class SystemTestSetupHelper { /** * Sets up a new {@code TestApp} and returns it. */ - public TestApp setupApplication(Supplier addressBook, String saveFileLocation) { + public TestApp setupApplication(Supplier catalogue, String saveFileLocation) { try { FxToolkit.registerStage(Stage::new); - FxToolkit.setupApplication(() -> testApp = new TestApp(addressBook, saveFileLocation)); + FxToolkit.setupApplication(() -> testApp = new TestApp(catalogue, saveFileLocation)); } catch (TimeoutException te) { throw new AssertionError("Application takes too long to set up."); } From 8a4550ebfff538b52941f1e4ae0fb5c67ece2b41 Mon Sep 17 00:00:00 2001 From: Khia Yi <33336624+khiayi@users.noreply.github.com> Date: Thu, 22 Mar 2018 11:16:55 +0800 Subject: [PATCH 31/98] Changed all address book to catalogue --- LICENSE | 4 +- build.gradle | 2 +- docs/DeveloperGuide.adoc | 138 +++++++++--------- docs/LearningOutcomes.adoc | 22 +-- docs/UserGuide.adoc | 70 ++++----- docs/UsingCheckstyle.adoc | 2 +- docs/UsingGradle.adoc | 2 +- docs/team/johndoe.adoc | 2 +- src/main/java/seedu/address/MainApp.java | 8 +- .../address/commons/core/LogsCenter.java | 2 +- .../seedu/address/commons/core/Messages.java | 2 +- .../ui/PersonPanelSelectionChangedEvent.java | 2 +- src/main/java/seedu/address/logic/Logic.java | 4 +- .../seedu/address/logic/LogicManager.java | 4 +- .../address/logic/commands/AddCommand.java | 22 +-- .../address/logic/commands/ClearCommand.java | 4 +- .../address/logic/commands/DeleteCommand.java | 26 ++-- .../address/logic/commands/EditCommand.java | 68 ++++----- .../address/logic/commands/ExitCommand.java | 2 +- .../address/logic/commands/FindCommand.java | 4 +- .../address/logic/commands/ListCommand.java | 2 +- .../address/logic/commands/SelectCommand.java | 10 +- .../logic/commands/UndoableCommand.java | 6 +- .../logic/parser/AddCommandParser.java | 14 +- .../logic/parser/FindCommandParser.java | 2 +- .../address/logic/parser/ParserUtil.java | 8 +- .../java/seedu/address/model/Catalogue.java | 76 +++++----- src/main/java/seedu/address/model/Model.java | 32 ++-- .../seedu/address/model/ModelManager.java | 40 ++--- .../address/model/ReadOnlyCatalogue.java | 6 +- .../java/seedu/address/model/UserPrefs.java | 4 +- .../model/{person => book}/Address.java | 8 +- .../{person/Person.java => book/Book.java} | 21 +-- .../address/model/{person => book}/Email.java | 8 +- .../address/model/{person => book}/Name.java | 8 +- .../NameContainsKeywordsPredicate.java | 10 +- .../address/model/{person => book}/Phone.java | 6 +- .../{person => book}/UniquePersonList.java | 52 +++---- .../exceptions/DuplicatePersonException.java | 4 +- .../exceptions/PersonNotFoundException.java | 6 + .../exceptions/PersonNotFoundException.java | 6 - .../java/seedu/address/model/tag/Tag.java | 2 +- .../address/model/util/SampleDataUtil.java | 32 ++-- .../java/seedu/address/storage/Storage.java | 2 +- .../address/storage/XmlAdaptedPerson.java | 28 ++-- .../seedu/address/storage/XmlAdaptedTag.java | 2 +- .../seedu/address/storage/XmlFileStorage.java | 6 +- .../java/seedu/address/ui/BrowserPanel.java | 8 +- .../java/seedu/address/ui/PersonCard.java | 22 +-- .../seedu/address/ui/PersonListPanel.java | 12 +- src/main/resources/view/MainWindow.fxml | 2 +- .../ExtraValuesUserPref.json | 4 +- .../TypicalUserPref.json | 4 +- .../invalidAndValidPersonAddressBook.xml | 16 +- .../invalidPersonAddressBook.xml | 10 +- .../invalidPersonAddressBook.xml | 10 +- .../invalidTagAddressBook.xml | 4 +- .../typicalPersonsAddressBook.xml | 36 ++--- .../data/XmlUtilTest/invalidPersonField.xml | 6 +- .../data/XmlUtilTest/missingPersonField.xml | 6 +- src/test/data/XmlUtilTest/tempAddressBook.xml | 8 +- .../data/XmlUtilTest/validAddressBook.xml | 40 ++--- src/test/data/XmlUtilTest/validPerson.xml | 4 +- .../guitests/guihandles/PersonCardHandle.java | 2 +- .../guihandles/PersonListPanelHandle.java | 24 +-- src/test/java/seedu/address/TestApp.java | 2 +- .../address/commons/util/XmlUtilTest.java | 6 +- .../seedu/address/logic/LogicManagerTest.java | 2 +- .../commands/AddCommandIntegrationTest.java | 20 +-- .../logic/commands/AddCommandTest.java | 54 +++---- .../logic/commands/CommandTestUtil.java | 26 ++-- .../logic/commands/DeleteCommandTest.java | 46 +++--- ...rTest.java => EditBookDescriptorTest.java} | 2 +- .../logic/commands/EditCommandTest.java | 82 +++++------ .../logic/commands/FindCommandTest.java | 10 +- .../logic/commands/SelectCommandTest.java | 4 +- .../logic/commands/UndoableCommandTest.java | 12 +- .../logic/parser/AddCommandParserTest.java | 30 ++-- .../logic/parser/CatalogueParserTest.java | 16 +- .../logic/parser/EditCommandParserTest.java | 10 +- .../logic/parser/FindCommandParserTest.java | 2 +- .../address/logic/parser/ParserUtilTest.java | 8 +- .../seedu/address/model/CatalogueTest.java | 18 +-- .../seedu/address/model/ModelManagerTest.java | 2 +- ...nListTest.java => UniqueBookListTest.java} | 4 +- .../model/{person => book}/AddressTest.java | 2 +- .../model/{person => book}/EmailTest.java | 2 +- .../NameContainsKeywordsPredicateTest.java | 4 +- .../model/{person => book}/NameTest.java | 2 +- .../model/{person => book}/PhoneTest.java | 2 +- .../storage/JsonUserPrefsStorageTest.java | 4 +- ...ersonTest.java => XmlAdaptedBookTest.java} | 10 +- .../storage/XmlCatalogueStorageTest.java | 8 +- .../storage/XmlSerializableCatalogueTest.java | 6 +- .../address/testutil/CatalogueBuilder.java | 12 +- .../testutil/EditPersonDescriptorBuilder.java | 24 +-- .../seedu/address/testutil/PersonBuilder.java | 40 ++--- .../seedu/address/testutil/PersonUtil.java | 24 +-- .../java/seedu/address/testutil/TestUtil.java | 10 +- .../address/testutil/TypicalPersons.java | 36 ++--- .../java/seedu/address/ui/BookCardTest.java | 72 +++++++++ ...tPanelTest.java => BookListPanelTest.java} | 16 +- .../seedu/address/ui/BrowserPanelTest.java | 2 +- .../java/seedu/address/ui/PersonCardTest.java | 72 --------- .../seedu/address/ui/StatusBarFooterTest.java | 2 +- .../address/ui/testutil/GuiTestAssert.java | 30 ++-- .../systemtests/AddCommandSystemTest.java | 54 +++---- .../java/systemtests/CatalogueSystemTest.java | 16 +- .../systemtests/ClearCommandSystemTest.java | 16 +- .../systemtests/DeleteCommandSystemTest.java | 50 +++---- .../systemtests/EditCommandSystemTest.java | 76 +++++----- .../systemtests/FindCommandSystemTest.java | 36 ++--- src/test/java/systemtests/ModelHelper.java | 14 +- src/test/java/systemtests/SampleDataTest.java | 4 +- .../systemtests/SelectCommandSystemTest.java | 14 +- 115 files changed, 1013 insertions(+), 1012 deletions(-) rename src/main/java/seedu/address/model/{person => book}/Address.java (85%) rename src/main/java/seedu/address/model/{person/Person.java => book/Book.java} (80%) rename src/main/java/seedu/address/model/{person => book}/Email.java (89%) rename src/main/java/seedu/address/model/{person => book}/Name.java (84%) rename src/main/java/seedu/address/model/{person => book}/NameContainsKeywordsPredicate.java (78%) rename src/main/java/seedu/address/model/{person => book}/Phone.java (88%) rename src/main/java/seedu/address/model/{person => book}/UniquePersonList.java (60%) rename src/main/java/seedu/address/model/{person => book}/exceptions/DuplicatePersonException.java (68%) create mode 100644 src/main/java/seedu/address/model/book/exceptions/PersonNotFoundException.java delete mode 100644 src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java rename src/test/java/seedu/address/logic/commands/{EditPersonDescriptorTest.java => EditBookDescriptorTest.java} (98%) rename src/test/java/seedu/address/model/{UniquePersonListTest.java => UniqueBookListTest.java} (84%) rename src/test/java/seedu/address/model/{person => book}/AddressTest.java (97%) rename src/test/java/seedu/address/model/{person => book}/EmailTest.java (98%) rename src/test/java/seedu/address/model/{person => book}/NameContainsKeywordsPredicateTest.java (97%) rename src/test/java/seedu/address/model/{person => book}/NameTest.java (97%) rename src/test/java/seedu/address/model/{person => book}/PhoneTest.java (97%) rename src/test/java/seedu/address/storage/{XmlAdaptedPersonTest.java => XmlAdaptedBookTest.java} (96%) create mode 100644 src/test/java/seedu/address/ui/BookCardTest.java rename src/test/java/seedu/address/ui/{PersonListPanelTest.java => BookListPanelTest.java} (81%) delete mode 100644 src/test/java/seedu/address/ui/PersonCardTest.java diff --git a/LICENSE b/LICENSE index 39b3478982c3..4d9f5c7cd00d 100644 --- a/LICENSE +++ b/LICENSE @@ -2,11 +2,11 @@ MIT License Copyright (c) 2016 Software Engineering Education - FOSS Resources -Permission is hereby granted, free of charge, to any person obtaining a copy +Permission is hereby granted, free of charge, to any book obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is +copies of the Software, and to permit books to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all diff --git a/build.gradle b/build.gradle index 50cd2ae52efc..441afbf6ed86 100644 --- a/build.gradle +++ b/build.gradle @@ -57,7 +57,7 @@ dependencies { } shadowJar { - archiveName = "addressbook.jar" + archiveName = "catalogue.jar" destinationDir = file("${buildDir}/jar/") } diff --git a/docs/DeveloperGuide.adoc b/docs/DeveloperGuide.adoc index 59a2d6359738..68f1257e3c00 100644 --- a/docs/DeveloperGuide.adoc +++ b/docs/DeveloperGuide.adoc @@ -1,4 +1,4 @@ -= AddressBook Level 4 - Developer Guide += Catalogue - Developer Guide :toc: :toc-title: :toc-placement: preamble @@ -140,7 +140,7 @@ The _Sequence Diagram_ below shows how the components interact for the scenario image::SDforDeletePerson.png[width="800"] [NOTE] -Note how the `Model` simply raises a `AddressBookChangedEvent` when the Address Book data are changed, instead of asking the `Storage` to save the updates to the hard disk. +Note how the `Model` simply raises a `CatalogueChangedEvent` when the Catalogue data are changed, instead of asking the `Storage` to save the updates to the hard disk. The diagram below shows how the `EventsCenter` reacts to that event, which eventually results in the updates being saved to the hard disk and the status bar of the UI being updated to reflect the 'Last Updated' time. @@ -183,9 +183,9 @@ image::LogicCommandClassDiagram.png[width="800"] *API* : link:{repoURL}/src/main/java/seedu/address/logic/Logic.java[`Logic.java`] -. `Logic` uses the `AddressBookParser` class to parse the user command. +. `Logic` uses the `CatalogueParser` class to parse the user command. . This results in a `Command` object which is executed by the `LogicManager`. -. The command execution can affect the `Model` (e.g. adding a person) and/or raise events. +. The command execution can affect the `Model` (e.g. adding a book) and/or raise events. . The result of the command execution is encapsulated as a `CommandResult` object which is passed back to the `Ui`. Given below is the Sequence Diagram for interactions within the `Logic` component for the `execute("delete 1")` API call. @@ -204,7 +204,7 @@ image::ModelClassDiagram.png[width="800"] The `Model`, * stores a `UserPref` object that represents the user's preferences. -* stores the Address Book data. +* stores the Catalogue data. * exposes an unmodifiable `ObservableList` that can be 'observed' e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change. * does not depend on any of the other three components. @@ -219,12 +219,12 @@ image::StorageClassDiagram.png[width="800"] The `Storage` component, * can save `UserPref` objects in json format and read it back. -* can save the Address Book data in xml format and read it back. +* can save the Catalogue data in xml format and read it back. [[Design-Commons]] === Common classes -Classes used by multiple components are in the `seedu.addressbook.commons` package. +Classes used by multiple components are in the `seedu.address.book.commons` package. == Implementation @@ -234,13 +234,13 @@ This section describes some noteworthy details on how certain features are imple === Undo/Redo feature ==== Current Implementation -The undo/redo mechanism is facilitated by an `UndoRedoStack`, which resides inside `LogicManager`. It supports undoing and redoing of commands that modifies the state of the address book (e.g. `add`, `edit`). Such commands will inherit from `UndoableCommand`. +The undo/redo mechanism is facilitated by an `UndoRedoStack`, which resides inside `LogicManager`. It supports undoing and redoing of commands that modifies the state of the catalogue (e.g. `add`, `edit`). Such commands will inherit from `UndoableCommand`. `UndoRedoStack` only deals with `UndoableCommands`. Commands that cannot be undone will inherit from `Command` instead. The following diagram shows the inheritance diagram for commands: image::LogicCommandClassDiagram.png[width="800"] -As you can see from the diagram, `UndoableCommand` adds an extra layer between the abstract `Command` class and concrete commands that can be undone, such as the `DeleteCommand`. Note that extra tasks need to be done when executing a command in an _undoable_ way, such as saving the state of the address book before execution. `UndoableCommand` contains the high-level algorithm for those extra tasks while the child classes implements the details of how to execute the specific command. Note that this technique of putting the high-level algorithm in the parent class and lower-level steps of the algorithm in child classes is also known as the https://www.tutorialspoint.com/design_pattern/template_pattern.htm[template pattern]. +As you can see from the diagram, `UndoableCommand` adds an extra layer between the abstract `Command` class and concrete commands that can be undone, such as the `DeleteCommand`. Note that extra tasks need to be done when executing a command in an _undoable_ way, such as saving the state of the catalogue before execution. `UndoableCommand` contains the high-level algorithm for those extra tasks while the child classes implements the details of how to execute the specific command. Note that this technique of putting the high-level algorithm in the parent class and lower-level steps of the algorithm in child classes is also known as the https://www.tutorialspoint.com/design_pattern/template_pattern.htm[template pattern]. Commands that are not undoable are implemented this way: [source,java] @@ -275,20 +275,20 @@ public class DeleteCommand extends UndoableCommand { Suppose that the user has just launched the application. The `UndoRedoStack` will be empty at the beginning. -The user executes a new `UndoableCommand`, `delete 5`, to delete the 5th person in the address book. The current state of the address book is saved before the `delete 5` command executes. The `delete 5` command will then be pushed onto the `undoStack` (the current state is saved together with the command). +The user executes a new `UndoableCommand`, `delete 5`, to delete the 5th book in the catalogue. The current state of the catalogue is saved before the `delete 5` command executes. The `delete 5` command will then be pushed onto the `undoStack` (the current state is saved together with the command). image::UndoRedoStartingStackDiagram.png[width="800"] -As the user continues to use the program, more commands are added into the `undoStack`. For example, the user may execute `add n/David ...` to add a new person. +As the user continues to use the program, more commands are added into the `undoStack`. For example, the user may execute `add n/David ...` to add a new book. image::UndoRedoNewCommand1StackDiagram.png[width="800"] [NOTE] If a command fails its execution, it will not be pushed to the `UndoRedoStack` at all. -The user now decides that adding the person was a mistake, and decides to undo that action using `undo`. +The user now decides that adding the book was a mistake, and decides to undo that action using `undo`. -We will pop the most recent command out of the `undoStack` and push it back to the `redoStack`. We will restore the address book to the state before the `add` command executed. +We will pop the most recent command out of the `undoStack` and push it back to the `redoStack`. We will restore the catalogue to the state before the `add` command executed. image::UndoRedoExecuteUndoStackDiagram.png[width="800"] @@ -299,7 +299,7 @@ The following sequence diagram shows how the undo operation works: image::UndoRedoSequenceDiagram.png[width="800"] -The redo does the exact opposite (pops from `redoStack`, push to `undoStack`, and restores the address book to the state after the command is executed). +The redo does the exact opposite (pops from `redoStack`, push to `undoStack`, and restores the catalogue to the state after the command is executed). [NOTE] If the `redoStack` is empty, then there are no other commands left to be redone, and an `Exception` will be thrown when popping the `redoStack`. @@ -329,17 +329,17 @@ image::UndoRedoActivityDiagram.png[width="650"] ===== Aspect: How undo & redo executes -* **Alternative 1 (current choice):** Saves the entire address book. +* **Alternative 1 (current choice):** Saves the entire catalogue. ** Pros: Easy to implement. ** Cons: May have performance issues in terms of memory usage. * **Alternative 2:** Individual command knows how to undo/redo by itself. -** Pros: Will use less memory (e.g. for `delete`, just save the person being deleted). +** Pros: Will use less memory (e.g. for `delete`, just save the book being deleted). ** Cons: We must ensure that the implementation of each individual command are correct. ===== Aspect: Type of commands that can be undone/redone -* **Alternative 1 (current choice):** Only include commands that modifies the address book (`add`, `clear`, `edit`). +* **Alternative 1 (current choice):** Only include commands that modifies the catalogue (`add`, `clear`, `edit`). ** Pros: We only revert changes that are hard to change back (the view can easily be re-modified as no data are * lost). ** Cons: User might think that undo also applies when the list is modified (undoing filtering for example), * only to realize that it does not do that, after executing `undo`. * **Alternative 2:** Include all commands. @@ -493,7 +493,7 @@ Here are the steps to create a new release. === Managing Dependencies -A project often depends on third-party libraries. For example, Address Book depends on the http://wiki.fasterxml.com/JacksonHome[Jackson library] for XML parsing. Managing these _dependencies_ can be automated using Gradle. For example, Gradle can download the dependencies automatically, which is better than these alternatives. + +A project often depends on third-party libraries. For example, Catalogue depends on the http://wiki.fasterxml.com/JacksonHome[Jackson library] for XML parsing. Managing these _dependencies_ can be automated using Gradle. For example, Gradle can download the dependencies automatically, which is better than these alternatives. + a. Include those libraries in the repo (this bloats the repo size) + b. Require developers to download those libraries manually (this creates extra work for developers) @@ -553,14 +553,14 @@ Each individual exercise in this section is component-based (i.e. you would not [TIP] Do take a look at <> before attempting to modify the `Logic` component. -. Add a shorthand equivalent alias for each of the individual commands. For example, besides typing `clear`, the user can also type `c` to remove all persons in the list. +. Add a shorthand equivalent alias for each of the individual commands. For example, besides typing `clear`, the user can also type `c` to remove all books in the list. + **** * Hints ** Just like we store each individual command word constant `COMMAND_WORD` inside `*Command.java` (e.g. link:{repoURL}/src/main/java/seedu/address/logic/commands/FindCommand.java[`FindCommand#COMMAND_WORD`], link:{repoURL}/src/main/java/seedu/address/logic/commands/DeleteCommand.java[`DeleteCommand#COMMAND_WORD`]), you need a new constant for aliases as well (e.g. `FindCommand#COMMAND_ALIAS`). -** link:{repoURL}/src/main/java/seedu/address/logic/parser/AddressBookParser.java[`AddressBookParser`] is responsible for analyzing command words. +** link:{repoURL}/src/main/java/seedu/address/logic/parser/CatalogueParser.java[`CatalogueParser`] is responsible for analyzing command words. * Solution -** Modify the switch statement in link:{repoURL}/src/main/java/seedu/address/logic/parser/AddressBookParser.java[`AddressBookParser#parseCommand(String)`] such that both the proper command word and alias can be used to execute the same intended command. +** Modify the switch statement in link:{repoURL}/src/main/java/seedu/address/logic/parser/CatalogueParser.java[`CatalogueParser#parseCommand(String)`] such that both the proper command word and alias can be used to execute the same intended command. ** Add new tests for each of the aliases that you have added. ** Update the user guide to document the new aliases. ** See this https://github.com/se-edu/addressbook-level4/pull/785[PR] for the full solution. @@ -569,36 +569,36 @@ Do take a look at <> before attempting to modify the `Logic` compo [discrete] ==== `Model` component -*Scenario:* You are in charge of `model`. One day, the `logic`-in-charge approaches you for help. He wants to implement a command such that the user is able to remove a particular tag from everyone in the address book, but the model API does not support such a functionality at the moment. Your job is to implement an API method, so that your teammate can use your API to implement his command. +*Scenario:* You are in charge of `model`. One day, the `logic`-in-charge approaches you for help. He wants to implement a command such that the user is able to remove a particular tag from everyone in the catalogue, but the model API does not support such a functionality at the moment. Your job is to implement an API method, so that your teammate can use your API to implement his command. [TIP] Do take a look at <> before attempting to modify the `Model` component. -. Add a `removeTag(Tag)` method. The specified tag will be removed from everyone in the address book. +. Add a `removeTag(Tag)` method. The specified tag will be removed from everyone in the catalogue. + **** * Hints -** The link:{repoURL}/src/main/java/seedu/address/model/Model.java[`Model`] and the link:{repoURL}/src/main/java/seedu/address/model/AddressBook.java[`AddressBook`] API need to be updated. +** The link:{repoURL}/src/main/java/seedu/address/model/Model.java[`Model`] and the link:{repoURL}/src/main/java/seedu/address/model/Catalogue.java[`Catalogue`] API need to be updated. ** Think about how you can use SLAP to design the method. Where should we place the main logic of deleting tags? -** Find out which of the existing API methods in link:{repoURL}/src/main/java/seedu/address/model/AddressBook.java[`AddressBook`] and link:{repoURL}/src/main/java/seedu/address/model/person/Person.java[`Person`] classes can be used to implement the tag removal logic. link:{repoURL}/src/main/java/seedu/address/model/AddressBook.java[`AddressBook`] allows you to update a person, and link:{repoURL}/src/main/java/seedu/address/model/person/Person.java[`Person`] allows you to update the tags. +** Find out which of the existing API methods in link:{repoURL}/src/main/java/seedu/address/model/Catalogue.java[`Catalogue`] and link:{repoURL}/src/main/java/seedu/address/model/book/Person.java[`Person`] classes can be used to implement the tag removal logic. link:{repoURL}/src/main/java/seedu/address/model/Catalogue.java[`Catalogue`] allows you to update a book, and link:{repoURL}/src/main/java/seedu/address/model/book/Person.java[`Person`] allows you to update the tags. * Solution -** Implement a `removeTag(Tag)` method in link:{repoURL}/src/main/java/seedu/address/model/AddressBook.java[`AddressBook`]. Loop through each person, and remove the `tag` from each person. -** Add a new API method `deleteTag(Tag)` in link:{repoURL}/src/main/java/seedu/address/model/ModelManager.java[`ModelManager`]. Your link:{repoURL}/src/main/java/seedu/address/model/ModelManager.java[`ModelManager`] should call `AddressBook#removeTag(Tag)`. +** Implement a `removeTag(Tag)` method in link:{repoURL}/src/main/java/seedu/address/model/Catalogue.java[`Catalogue`]. Loop through each book, and remove the `tag` from each book. +** Add a new API method `deleteTag(Tag)` in link:{repoURL}/src/main/java/seedu/address/model/ModelManager.java[`ModelManager`]. Your link:{repoURL}/src/main/java/seedu/address/model/ModelManager.java[`ModelManager`] should call `Catalogue#removeTag(Tag)`. ** Add new tests for each of the new public methods that you have added. ** See this https://github.com/se-edu/addressbook-level4/pull/790[PR] for the full solution. -*** The current codebase has a flaw in tags management. Tags no longer in use by anyone may still exist on the link:{repoURL}/src/main/java/seedu/address/model/AddressBook.java[`AddressBook`]. This may cause some tests to fail. See issue https://github.com/se-edu/addressbook-level4/issues/753[`#753`] for more information about this flaw. +*** The current codebase has a flaw in tags management. Tags no longer in use by anyone may still exist on the link:{repoURL}/src/main/java/seedu/address/model/Catalogue.java[`Catalogue`]. This may cause some tests to fail. See issue https://github.com/se-edu/addressbook-level4/issues/753[`#753`] for more information about this flaw. *** The solution PR has a temporary fix for the flaw mentioned above in its first commit. **** [discrete] ==== `Ui` component -*Scenario:* You are in charge of `ui`. During a beta testing session, your team is observing how the users use your address book application. You realize that one of the users occasionally tries to delete non-existent tags from a contact, because the tags all look the same visually, and the user got confused. Another user made a typing mistake in his command, but did not realize he had done so because the error message wasn't prominent enough. A third user keeps scrolling down the list, because he keeps forgetting the index of the last person in the list. Your job is to implement improvements to the UI to solve all these problems. +*Scenario:* You are in charge of `ui`. During a beta testing session, your team is observing how the users use your catalogue application. You realize that one of the users occasionally tries to delete non-existent tags from a contact, because the tags all look the same visually, and the user got confused. Another user made a typing mistake in his command, but did not realize he had done so because the error message wasn't prominent enough. A third user keeps scrolling down the list, because he keeps forgetting the index of the last book in the list. Your job is to implement improvements to the UI to solve all these problems. [TIP] Do take a look at <> before attempting to modify the `UI` component. -. Use different colors for different tags inside person cards. For example, `friends` tags can be all in brown, and `colleagues` tags can be all in yellow. +. Use different colors for different tags inside book cards. For example, `friends` tags can be all in brown, and `colleagues` tags can be all in yellow. + **Before** + @@ -638,12 +638,12 @@ image::getting-started-ui-result-after.png[width="200"] ** Modify link:{repoURL}/src/main/java/seedu/address/ui/ResultDisplay.java[`ResultDisplay#handleNewResultAvailableEvent(NewResultAvailableEvent)`] to react to this event appropriately. ** You can write two different kinds of tests to ensure that the functionality works: *** The unit tests for `ResultDisplay` can be modified to include verification of the color. -*** The system tests link:{repoURL}/src/test/java/systemtests/AddressBookSystemTest.java[`AddressBookSystemTest#assertCommandBoxShowsDefaultStyle() and AddressBookSystemTest#assertCommandBoxShowsErrorStyle()`] to include verification for `ResultDisplay` as well. +*** The system tests link:{repoURL}/src/test/java/systemtests/CatalogueSystemTest.java[`CatalogueSystemTest#assertCommandBoxShowsDefaultStyle() and CatalogueSystemTest#assertCommandBoxShowsErrorStyle()`] to include verification for `ResultDisplay` as well. ** See this https://github.com/se-edu/addressbook-level4/pull/799[PR] for the full solution. *** Do read the commits one at a time if you feel overwhelmed. **** -. Modify the link:{repoURL}/src/main/java/seedu/address/ui/StatusBarFooter.java[`StatusBarFooter`] to show the total number of people in the address book. +. Modify the link:{repoURL}/src/main/java/seedu/address/ui/StatusBarFooter.java[`StatusBarFooter`] to show the total number of people in the catalogue. + **Before** + @@ -656,29 +656,29 @@ image::getting-started-ui-status-after.png[width="500"] **** * Hints ** link:{repoURL}/src/main/resources/view/StatusBarFooter.fxml[`StatusBarFooter.fxml`] will need a new `StatusBar`. Be sure to set the `GridPane.columnIndex` properly for each `StatusBar` to avoid misalignment! -** link:{repoURL}/src/main/java/seedu/address/ui/StatusBarFooter.java[`StatusBarFooter`] needs to initialize the status bar on application start, and to update it accordingly whenever the address book is updated. +** link:{repoURL}/src/main/java/seedu/address/ui/StatusBarFooter.java[`StatusBarFooter`] needs to initialize the status bar on application start, and to update it accordingly whenever the catalogue is updated. * Solution -** Modify the constructor of link:{repoURL}/src/main/java/seedu/address/ui/StatusBarFooter.java[`StatusBarFooter`] to take in the number of persons when the application just started. -** Use link:{repoURL}/src/main/java/seedu/address/ui/StatusBarFooter.java[`StatusBarFooter#handleAddressBookChangedEvent(AddressBookChangedEvent)`] to update the number of persons whenever there are new changes to the addressbook. +** Modify the constructor of link:{repoURL}/src/main/java/seedu/address/ui/StatusBarFooter.java[`StatusBarFooter`] to take in the number of books when the application just started. +** Use link:{repoURL}/src/main/java/seedu/address/ui/StatusBarFooter.java[`StatusBarFooter#handlCatalogueChangedEvent(CatalogueChangedEvent)`] to update the number of books whenever there are new changes to the catalogue. ** For tests, modify link:{repoURL}/src/test/java/guitests/guihandles/StatusBarFooterHandle.java[`StatusBarFooterHandle`] by adding a state-saving functionality for the total number of people status, just like what we did for save location and sync status. -** For system tests, modify link:{repoURL}/src/test/java/systemtests/AddressBookSystemTest.java[`AddressBookSystemTest`] to also verify the new total number of persons status bar. +** For system tests, modify link:{repoURL}/src/test/java/systemtests/CatalogueSystemTest.java[`CatalogueSystemTest`] to also verify the new total number of books status bar. ** See this https://github.com/se-edu/addressbook-level4/pull/803[PR] for the full solution. **** [discrete] ==== `Storage` component -*Scenario:* You are in charge of `storage`. For your next project milestone, your team plans to implement a new feature of saving the address book to the cloud. However, the current implementation of the application constantly saves the address book after the execution of each command, which is not ideal if the user is working on limited internet connection. Your team decided that the application should instead save the changes to a temporary local backup file first, and only upload to the cloud after the user closes the application. Your job is to implement a backup API for the address book storage. +*Scenario:* You are in charge of `storage`. For your next project milestone, your team plans to implement a new feature of saving the catalogue to the cloud. However, the current implementation of the application constantly saves the catalogue after the execution of each command, which is not ideal if the user is working on limited internet connection. Your team decided that the application should instead save the changes to a temporary local backup file first, and only upload to the cloud after the user closes the application. Your job is to implement a backup API for the catalogue storage. [TIP] Do take a look at <> before attempting to modify the `Storage` component. -. Add a new method `backupAddressBook(ReadOnlyAddressBook)`, so that the address book can be saved in a fixed temporary location. +. Add a new method `backupCatalogue(ReadOnlyCatalogue)`, so that the catalogue can be saved in a fixed temporary location. + **** * Hint -** Add the API method in link:{repoURL}/src/main/java/seedu/address/storage/AddressBookStorage.java[`AddressBookStorage`] interface. -** Implement the logic in link:{repoURL}/src/main/java/seedu/address/storage/StorageManager.java[`StorageManager`] and link:{repoURL}/src/main/java/seedu/address/storage/XmlAddressBookStorage.java[`XmlAddressBookStorage`] class. +** Add the API method in link:{repoURL}/src/main/java/seedu/address/storage/CatalogueStorage.java[`CatalogueStorage`] interface. +** Implement the logic in link:{repoURL}/src/main/java/seedu/address/storage/StorageManager.java[`StorageManager`] and link:{repoURL}/src/main/java/seedu/address/storage/XmlCatalogueStorage.java[`XmlCatalogueStorage`] class. * Solution ** See this https://github.com/se-edu/addressbook-level4/pull/594[PR] for the full solution. **** @@ -691,15 +691,15 @@ By creating this command, you will get a chance to learn how to implement a feat *Scenario:* You are a software maintainer for `addressbook`, as the former developer team has moved on to new projects. The current users of your application have a list of new feature requests that they hope the software will eventually have. The most popular request is to allow adding additional comments/notes about a particular contact, by providing a flexible `remark` field for each contact, rather than relying on tags alone. After designing the specification for the `remark` command, you are convinced that this feature is worth implementing. Your job is to implement the `remark` command. ==== Description -Edits the remark for a person specified in the `INDEX`. + +Edits the remark for a book specified in the `INDEX`. + Format: `remark INDEX r/[REMARK]` Examples: * `remark 1 r/Likes to drink coffee.` + -Edits the remark for the first person to `Likes to drink coffee.` +Edits the remark for the first book to `Likes to drink coffee.` * `remark 1 r/` + -Removes the remark for the first person. +Removes the remark for the first book. ==== Step-by-step Instructions @@ -709,12 +709,12 @@ Let's start by teaching the application how to parse a `remark` command. We will **Main:** . Add a `RemarkCommand` that extends link:{repoURL}/src/main/java/seedu/address/logic/commands/UndoableCommand.java[`UndoableCommand`]. Upon execution, it should just throw an `Exception`. -. Modify link:{repoURL}/src/main/java/seedu/address/logic/parser/AddressBookParser.java[`AddressBookParser`] to accept a `RemarkCommand`. +. Modify link:{repoURL}/src/main/java/seedu/address/logic/parser/CatalogueParser.java[`CatalogueParser`] to accept a `RemarkCommand`. **Tests:** . Add `RemarkCommandTest` that tests that `executeUndoableCommand()` throws an Exception. -. Add new test method to link:{repoURL}/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java[`AddressBookParserTest`], which tests that typing "remark" returns an instance of `RemarkCommand`. +. Add new test method to link:{repoURL}/src/test/java/seedu/address/logic/parser/CatalogueParserTest.java[`CatalogueParserTest`], which tests that typing "remark" returns an instance of `RemarkCommand`. ===== [Step 2] Logic: Teach the app to accept 'remark' arguments Let's teach the application to parse arguments that our `remark` command will accept. E.g. `1 r/Likes to drink coffee.` @@ -723,17 +723,17 @@ Let's teach the application to parse arguments that our `remark` command will ac . Modify `RemarkCommand` to take in an `Index` and `String` and print those two parameters as the error message. . Add `RemarkCommandParser` that knows how to parse two arguments, one index and one with prefix 'r/'. -. Modify link:{repoURL}/src/main/java/seedu/address/logic/parser/AddressBookParser.java[`AddressBookParser`] to use the newly implemented `RemarkCommandParser`. +. Modify link:{repoURL}/src/main/java/seedu/address/logic/parser/CatalogueParser.java[`CatalogueParser`] to use the newly implemented `RemarkCommandParser`. **Tests:** . Modify `RemarkCommandTest` to test the `RemarkCommand#equals()` method. . Add `RemarkCommandParserTest` that tests different boundary values for `RemarkCommandParser`. -. Modify link:{repoURL}/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java[`AddressBookParserTest`] to test that the correct command is generated according to the user input. +. Modify link:{repoURL}/src/test/java/seedu/address/logic/parser/CatalogueParserTest.java[`CatalogueParserTest`] to test that the correct command is generated according to the user input. ===== [Step 3] Ui: Add a placeholder for remark in `PersonCard` -Let's add a placeholder on all our link:{repoURL}/src/main/java/seedu/address/ui/PersonCard.java[`PersonCard`] s to display a remark for each person later. +Let's add a placeholder on all our link:{repoURL}/src/main/java/seedu/address/ui/PersonCard.java[`PersonCard`] s to display a remark for each book later. **Main:** @@ -745,11 +745,11 @@ Let's add a placeholder on all our link:{repoURL}/src/main/java/seedu/address/ui . Modify link:{repoURL}/src/test/java/guitests/guihandles/PersonCardHandle.java[`PersonCardHandle`] so that future tests can read the contents of the remark label. ===== [Step 4] Model: Add `Remark` class -We have to properly encapsulate the remark in our link:{repoURL}/src/main/java/seedu/address/model/person/Person.java[`Person`] class. Instead of just using a `String`, let's follow the conventional class structure that the codebase already uses by adding a `Remark` class. +We have to properly encapsulate the remark in our link:{repoURL}/src/main/java/seedu/address/model/book/Person.java[`Person`] class. Instead of just using a `String`, let's follow the conventional class structure that the codebase already uses by adding a `Remark` class. **Main:** -. Add `Remark` to model component (you can copy from link:{repoURL}/src/main/java/seedu/address/model/person/Address.java[`Address`], remove the regex and change the names accordingly). +. Add `Remark` to model component (you can copy from link:{repoURL}/src/main/java/seedu/address/model/book/Address.java[`Address`], remove the regex and change the names accordingly). . Modify `RemarkCommand` to now take in a `Remark` instead of a `String`. **Tests:** @@ -757,12 +757,12 @@ We have to properly encapsulate the remark in our link:{repoURL}/src/main/java/s . Add test for `Remark`, to test the `Remark#equals()` method. ===== [Step 5] Model: Modify `Person` to support a `Remark` field -Now we have the `Remark` class, we need to actually use it inside link:{repoURL}/src/main/java/seedu/address/model/person/Person.java[`Person`]. +Now we have the `Remark` class, we need to actually use it inside link:{repoURL}/src/main/java/seedu/address/model/book/Person.java[`Person`]. **Main:** -. Add `getRemark()` in link:{repoURL}/src/main/java/seedu/address/model/person/Person.java[`Person`]. -. You may assume that the user will not be able to use the `add` and `edit` commands to modify the remarks field (i.e. the person will be created without a remark). +. Add `getRemark()` in link:{repoURL}/src/main/java/seedu/address/model/book/Person.java[`Person`]. +. You may assume that the user will not be able to use the `add` and `edit` commands to modify the remarks field (i.e. the book will be created without a remark). . Modify link:{repoURL}/src/main/java/seedu/address/model/util/SampleDataUtil.java/[`SampleDataUtil`] to add remarks for the sample data (delete your `catalogue.xml` so that the application will load the sample data when you launch it.) ===== [Step 6] Storage: Add `Remark` field to `XmlAdaptedPerson` class @@ -774,14 +774,14 @@ We now have `Remark` s for `Person` s, but they will be gone when we exit the ap **Tests:** -. Fix `invalidAndValidPersonAddressBook.xml`, `typicalPersonsAddressBook.xml`, `validAddressBook.xml` etc., such that the XML tests will not fail due to a missing `` element. +. Fix `invalidAndValidPersonCatalogue.xml`, `typicalPersonsCatalogue.xml`, `validCatalogue.xml` etc., such that the XML tests will not fail due to a missing `` element. ===== [Step 6b] Test: Add withRemark() for `PersonBuilder` -Since `Person` can now have a `Remark`, we should add a helper method to link:{repoURL}/src/test/java/seedu/address/testutil/PersonBuilder.java[`PersonBuilder`], so that users are able to create remarks when building a link:{repoURL}/src/main/java/seedu/address/model/person/Person.java[`Person`]. +Since `Person` can now have a `Remark`, we should add a helper method to link:{repoURL}/src/test/java/seedu/address/testutil/PersonBuilder.java[`PersonBuilder`], so that users are able to create remarks when building a link:{repoURL}/src/main/java/seedu/address/model/book/Person.java[`Person`]. **Tests:** -. Add a new method `withRemark()` for link:{repoURL}/src/test/java/seedu/address/testutil/PersonBuilder.java[`PersonBuilder`]. This method will create a new `Remark` for the person that it is currently building. +. Add a new method `withRemark()` for link:{repoURL}/src/test/java/seedu/address/testutil/PersonBuilder.java[`PersonBuilder`]. This method will create a new `Remark` for the book that it is currently building. . Try and use the method on any sample `Person` in link:{repoURL}/src/test/java/seedu/address/testutil/TypicalPersons.java[`TypicalPersons`]. ===== [Step 7] Ui: Connect `Remark` field to `PersonCard` @@ -800,7 +800,7 @@ We now have everything set up... but we still can't modify the remarks. Let's fi **Main:** -. Replace the logic in `RemarkCommand#execute()` (that currently just throws an `Exception`), with the actual logic to modify the remarks of a person. +. Replace the logic in `RemarkCommand#execute()` (that currently just throws an `Exception`), with the actual logic to modify the remarks of a book. **Tests:** @@ -866,17 +866,17 @@ _{More to be added}_ [appendix] == Use Cases -(For all use cases below, the *System* is the `AddressBook` and the *Actor* is the `user`, unless specified otherwise) +(For all use cases below, the *System* is the `Catalogue` and the *Actor* is the `user`, unless specified otherwise) [discrete] -=== Use case: Delete person +=== Use case: Delete book *MSS* -1. User requests to list persons -2. AddressBook shows a list of persons -3. User requests to delete a specific person in the list -4. AddressBook deletes the person +1. User requests to list books +2. Catalogue shows a list of books +3. User requests to delete a specific book in the list +4. Catalogue deletes the book + Use case ends. @@ -890,7 +890,7 @@ Use case ends. * 3a. The given index is invalid. + [none] -** 3a1. AddressBook shows an error message. +** 3a1. Catalogue shows an error message. + Use case resumes at step 2. @@ -900,7 +900,7 @@ _{More to be added}_ == Non Functional Requirements . Should work on any <> as long as it has Java `1.8.0_60` or higher installed. -. Should be able to hold up to 1000 persons without a noticeable sluggishness in performance for typical usage. +. Should be able to hold up to 1000 books without a noticeable sluggishness in performance for typical usage. . A user with above average typing speed for regular English text (i.e. not code, not system admin commands) should be able to accomplish most of the tasks faster using commands than using the mouse. _{More to be added}_ @@ -955,15 +955,15 @@ These instructions only provide a starting point for testers to work on; testers _{ more test cases ... }_ -=== Deleting a person +=== Deleting a book -. Deleting a person while all persons are listed +. Deleting a book while all books are listed -.. Prerequisites: List all persons using the `list` command. Multiple persons in the list. +.. Prerequisites: List all books using the `list` command. Multiple books in the list. .. Test case: `delete 1` + Expected: First contact is deleted from the list. Details of the deleted contact shown in the status message. Timestamp in the status bar is updated. .. Test case: `delete 0` + - Expected: No person is deleted. Error details shown in the status message. Status bar remains the same. + Expected: No book is deleted. Error details shown in the status message. Status bar remains the same. .. Other incorrect delete commands to try: `delete`, `delete x` (where x is larger than the list size) _{give more}_ + Expected: Similar to previous. diff --git a/docs/LearningOutcomes.adoc b/docs/LearningOutcomes.adoc index cf153ba8b38f..b764735c5f35 100644 --- a/docs/LearningOutcomes.adoc +++ b/docs/LearningOutcomes.adoc @@ -37,7 +37,7 @@ Note how the <> uses events to com == Use API Design `[LO-ApiDesign]` -Note how components of AddressBook have well-defined APIs. For example, the API of the `Logic` component is given in the link:{repoURL}/src/main/java/seedu/address/logic/Logic.java[`Logic.java`] +Note how components of Catalogue have well-defined APIs. For example, the API of the `Logic` component is given in the link:{repoURL}/src/main/java/seedu/address/logic/Logic.java[`Logic.java`] image:LogicClassDiagram.png[width="800"] *Resources* @@ -48,7 +48,7 @@ image:LogicClassDiagram.png[width="800"] == Use Assertions `[LO-Assertions]` -Note how the AddressBook app uses Java ``assert``s to verify assumptions. +Note how the Catalogue app uses Java ``assert``s to verify assumptions. *Resources* @@ -57,14 +57,14 @@ Note how the AddressBook app uses Java ``assert``s to verify assumptions. === Exercise: Add more assertions * Make sure assertions are enabled in your IDE by forcing an assertion failure (e.g. add `assert false;` somewhere in the code and run the code to ensure the runtime reports an assertion failure). -* Add more assertions to AddressBook as you see fit. +* Add more assertions to Catalogue as you see fit. ''' == Use Logging `[LO-Logging]` -Note <>. +Note <>. *Resources* @@ -72,14 +72,14 @@ Note <>. +Note <>. *Resources* @@ -115,7 +115,7 @@ Note <>. (https://travis-ci.org/se-edu/addressbook-level4[image:https://travis-ci.org/se-edu/addressbook-level4.svg?branch=master[Build Status]]) +Note <>. (https://travis-ci.org/se-edu/addressbook-level4[image:https://travis-ci.org/se-edu/addressbook-level4.svg?branch=master[Build Status]]) *Resources* @@ -161,8 +161,8 @@ class gives some examples of how to use _Equivalence Partitions_, _Boundary Valu Consider the link:{repoURL}/src/test/java/seedu/address/storage/StorageManagerTest.java[`StorageManagerTest.java`] class. -* Test methods `prefsReadSave()` and `addressBookReadSave()` are integration tests. Note how they simply test if The `StorageManager` class is correctly wired to its dependencies. -* Test method `handleAddressBookChangedEvent_exceptionThrown_eventRaised()` is a unit test because it uses _dependency injection_ to isolate the SUT `StorageManager#handleAddressBookChangedEvent(...)` from its dependencies. +* Test methods `prefsReadSave()` and `catalogueReadSave()` are integration tests. Note how they simply test if The `StorageManager` class is correctly wired to its dependencies. +* Test method `handleCatalogueChangedEvent_exceptionThrown_eventRaised()` is a unit test because it uses _dependency injection_ to isolate the SUT `StorageManager#handleCatalogueChangedEvent(...)` from its dependencies. Compare the above with link:{repoURL}/src/test/java/seedu/address/logic/LogicManagerTest.java[`LogicManagerTest`]. Some of the tests in that class (e.g. `execute_*` methods) are neither integration nor unit tests. They are _integration + unit_ tests because they not only check if the LogicManager is correctly wired to its dependencies, but also checks the working of its dependencies. For example, the following two lines test the `LogicManager` but also the `Parser`. diff --git a/docs/UserGuide.adoc b/docs/UserGuide.adoc index c1f93acde393..766cba9d0ccc 100644 --- a/docs/UserGuide.adoc +++ b/docs/UserGuide.adoc @@ -1,4 +1,4 @@ -= AddressBook Level 4 - User Guide += Catalogue Level 4 - User Guide :toc: :toc-title: :toc-placement: preamble @@ -17,7 +17,7 @@ By: `Team SE-EDU` Since: `Jun 2016` Licence: `MIT` == Introduction -AddressBook Level 4 (AB4) is for those who *prefer to use a desktop app for managing contacts*. More importantly, AB4 is *optimized for those who prefer to work with a Command Line Interface* (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, AB4 can get your contact management tasks done faster than traditional GUI apps. Interested? Jump to the <> to get started. Enjoy! +Catalogue is for those who *prefer to use a desktop app for managing contacts*. More importantly, AB4 is *optimized for those who prefer to work with a Command Line Interface* (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, AB4 can get your contact management tasks done faster than traditional GUI apps. Interested? Jump to the <> to get started. Enjoy! == Quick Start @@ -27,8 +27,8 @@ AddressBook Level 4 (AB4) is for those who *prefer to use a desktop app for mana Having any Java 8 version is not enough. + This app will not work with earlier versions of Java 8. + -. Download the latest `addressbook.jar` link:{repoURL}/releases[here]. -. Copy the file to the folder you want to use as the home folder for your Address Book. +. Download the latest `catalogue.jar` link:{repoURL}/releases[here]. +. Copy the file to the folder you want to use as the home folder for your Catalogue. . Double-click the file to start the app. The GUI should appear in a few seconds. + image::Ui.png[width="790"] @@ -38,7 +38,7 @@ e.g. typing *`help`* and pressing kbd:[Enter] will open the help window. . Some example commands you can try: * *`list`* : lists all contacts -* **`add`**`n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01` : adds a contact named `John Doe` to the Address Book. +* **`add`**`n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01` : adds a contact named `John Doe` to the Catalogue. * **`delete`**`3` : deletes the 3rd contact shown in the current list * *`exit`* : exits the app @@ -60,47 +60,47 @@ e.g. typing *`help`* and pressing kbd:[Enter] will open the help window. Format: `help` -=== Adding a person: `add` +=== Adding a book: `add` -Adds a person to the address book + +Adds a book to the catalogue + Format: `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]...` [TIP] -A person can have any number of tags (including 0) +A book can have any number of tags (including 0) Examples: * `add n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01` * `add n/Betsy Crowe t/friend e/betsycrowe@example.com a/Newgate Prison p/1234567 t/criminal` -=== Listing all persons : `list` +=== Listing all books : `list` -Shows a list of all persons in the address book. + +Shows a list of all books in the catalogue. + Format: `list` -=== Editing a person : `edit` +=== Editing a book : `edit` -Edits an existing person in the address book. + +Edits an existing book in the catalogue. + Format: `edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]...` **** -* Edits the person at the specified `INDEX`. The index refers to the index number shown in the last person listing. The index *must be a positive integer* 1, 2, 3, ... +* Edits the book at the specified `INDEX`. The index refers to the index number shown in the last book listing. The index *must be a positive integer* 1, 2, 3, ... * At least one of the optional fields must be provided. * Existing values will be updated to the input values. -* When editing tags, the existing tags of the person will be removed i.e adding of tags is not cumulative. -* You can remove all the person's tags by typing `t/` without specifying any tags after it. +* When editing tags, the existing tags of the book will be removed i.e adding of tags is not cumulative. +* You can remove all the book's tags by typing `t/` without specifying any tags after it. **** Examples: * `edit 1 p/91234567 e/johndoe@example.com` + -Edits the phone number and email address of the 1st person to be `91234567` and `johndoe@example.com` respectively. +Edits the phone number and email address of the 1st book to be `91234567` and `johndoe@example.com` respectively. * `edit 2 n/Betsy Crower t/` + -Edits the name of the 2nd person to be `Betsy Crower` and clears all existing tags. +Edits the name of the 2nd book to be `Betsy Crower` and clears all existing tags. -=== Locating persons by name: `find` +=== Locating books by name: `find` -Finds persons whose names contain any of the given keywords. + +Finds books whose names contain any of the given keywords. + Format: `find KEYWORD [MORE_KEYWORDS]` **** @@ -116,15 +116,15 @@ Examples: * `find John` + Returns `john` and `John Doe` * `find Betsy Tim John` + -Returns any person having names `Betsy`, `Tim`, or `John` +Returns any book having names `Betsy`, `Tim`, or `John` -=== Deleting a person : `delete` +=== Deleting a book : `delete` -Deletes the specified person from the address book. + +Deletes the specified book from the catalogue. + Format: `delete INDEX` **** -* Deletes the person at the specified `INDEX`. +* Deletes the book at the specified `INDEX`. * The index refers to the index number shown in the most recent listing. * The index *must be a positive integer* 1, 2, 3, ... **** @@ -133,18 +133,18 @@ Examples: * `list` + `delete 2` + -Deletes the 2nd person in the address book. +Deletes the 2nd book in the catalogue. * `find Betsy` + `delete 1` + -Deletes the 1st person in the results of the `find` command. +Deletes the 1st book in the results of the `find` command. -=== Selecting a person : `select` +=== Selecting a book : `select` -Selects the person identified by the index number used in the last person listing. + +Selects the book identified by the index number used in the last book listing. + Format: `select INDEX` **** -* Selects the person and loads the Google search page the person at the specified `INDEX`. +* Selects the book and loads the Google search page the book at the specified `INDEX`. * The index refers to the index number shown in the most recent listing. * The index *must be a positive integer* `1, 2, 3, ...` **** @@ -153,10 +153,10 @@ Examples: * `list` + `select 2` + -Selects the 2nd person in the address book. +Selects the 2nd book in the catalogue. * `find Betsy` + `select 1` + -Selects the 1st person in the results of the `find` command. +Selects the 1st book in the results of the `find` command. === Listing entered commands : `history` @@ -171,12 +171,12 @@ Pressing the kbd:[↑] and kbd:[↓] arrows will display the previous and // tag::undoredo[] === Undoing previous command : `undo` -Restores the address book to the state before the previous _undoable_ command was executed. + +Restores the catalogue to the state before the previous _undoable_ command was executed. + Format: `undo` [NOTE] ==== -Undoable commands: those commands that modify the address book's content (`add`, `delete`, `edit` and `clear`). +Undoable commands: those commands that modify the catalogue's content (`add`, `delete`, `edit` and `clear`). ==== Examples: @@ -220,7 +220,7 @@ The `redo` command fails as there are no `undo` commands executed previously. === Clearing all entries : `clear` -Clears all entries from the address book. + +Clears all entries from the catalogue. + Format: `clear` === Exiting the program : `exit` @@ -230,7 +230,7 @@ Format: `exit` === Saving the data -Address book data are saved in the hard disk automatically after any command that changes the data. + +Catalogue data are saved in the hard disk automatically after any command that changes the data. + There is no need to save manually. // tag::dataencryption[] @@ -242,7 +242,7 @@ _{explain how the user can enable/disable data encryption}_ == FAQ *Q*: How do I transfer my data to another Computer? + -*A*: Install the app in the other computer and overwrite the empty data file it creates with the file that contains the data of your previous Address Book folder. +*A*: Install the app in the other computer and overwrite the empty data file it creates with the file that contains the data of your previous Catalogue folder. == Command Summary diff --git a/docs/UsingCheckstyle.adoc b/docs/UsingCheckstyle.adoc index ba9b76d3918d..71cabd050948 100644 --- a/docs/UsingCheckstyle.adoc +++ b/docs/UsingCheckstyle.adoc @@ -18,7 +18,7 @@ Restart the IDE to complete the installation. + image::checkstyle-idea-scan-scope.png[width="500"] . Click the plus sign under `Configuration File` -. Enter an arbitrary description e.g. addressbook +. Enter an arbitrary description e.g. Catalogue . Select `Use a local Checkstyle file` . Use the checkstyle configuration file found at `config/checkstyle/checkstyle.xml` . Click `Next` > `Finish` diff --git a/docs/UsingGradle.adoc b/docs/UsingGradle.adoc index 84c9dd193491..23b126565983 100644 --- a/docs/UsingGradle.adoc +++ b/docs/UsingGradle.adoc @@ -41,7 +41,7 @@ When running a Gradle task, Gradle will try to figure out if the task needs runn == Creating the JAR file * *`shadowJar`* + -Creates the `addressbook.jar` file in the `build/jar` folder, _if the current file is outdated_. + +Creates the `catalogue.jar` file in the `build/jar` folder, _if the current file is outdated_. + e.g. `./gradlew shadowJar` **** diff --git a/docs/team/johndoe.adoc b/docs/team/johndoe.adoc index 0dfa757e454b..d9eb6f7f7383 100644 --- a/docs/team/johndoe.adoc +++ b/docs/team/johndoe.adoc @@ -8,7 +8,7 @@ == Overview -AddressBook - Level 4 is a desktop address book application used for teaching Software Engineering principles. The user interacts with it using a CLI, and it has a GUI created with JavaFX. It is written in Java, and has about 10 kLoC. +AddressBook - Level 4 is a desktop catalogue application used for teaching Software Engineering principles. The user interacts with it using a CLI, and it has a GUI created with JavaFX. It is written in Java, and has about 10 kLoC. == Summary of contributions diff --git a/src/main/java/seedu/address/MainApp.java b/src/main/java/seedu/address/MainApp.java index ecf290921a8a..3300ad3044df 100644 --- a/src/main/java/seedu/address/MainApp.java +++ b/src/main/java/seedu/address/MainApp.java @@ -81,9 +81,9 @@ private String getApplicationParameter(String parameterName) { } /** - * 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 C\catalogue and {@code userPrefs}.
+ * The data from the sample Catalogue will be used instead if {@code storage}'s Catalogue is not found, + * or an empty Catalogue will be used instead if errors occur when reading {@code storage}'s Catalogue. */ private Model initModelManager(Storage storage, UserPrefs userPrefs) { Optional catalogueOptional; @@ -189,7 +189,7 @@ public void start(Stage primaryStage) { @Override public void stop() { - logger.info("============================ [ Stopping Address Book ] ============================="); + logger.info("============================ [ Stopping Catalogue ] ============================="); ui.stop(); try { storage.saveUserPrefs(userPrefs); diff --git a/src/main/java/seedu/address/commons/core/LogsCenter.java b/src/main/java/seedu/address/commons/core/LogsCenter.java index 46e4c3aac468..bbc6f656e2e6 100644 --- a/src/main/java/seedu/address/commons/core/LogsCenter.java +++ b/src/main/java/seedu/address/commons/core/LogsCenter.java @@ -20,7 +20,7 @@ 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"; + private static final String LOG_FILE = "catalogue.log"; private static Level currentLogLevel = Level.INFO; private static final Logger logger = LogsCenter.getLogger(LogsCenter.class); private static FileHandler fileHandler; diff --git a/src/main/java/seedu/address/commons/core/Messages.java b/src/main/java/seedu/address/commons/core/Messages.java index 1deb3a1e4695..d6cc63453fc5 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_INVALID_PERSON_DISPLAYED_INDEX = "The book index provided is invalid"; public static final String MESSAGE_PERSONS_LISTED_OVERVIEW = "%1$d persons listed!"; } diff --git a/src/main/java/seedu/address/commons/events/ui/PersonPanelSelectionChangedEvent.java b/src/main/java/seedu/address/commons/events/ui/PersonPanelSelectionChangedEvent.java index 56c1c9d987f1..0c84129a51ca 100644 --- a/src/main/java/seedu/address/commons/events/ui/PersonPanelSelectionChangedEvent.java +++ b/src/main/java/seedu/address/commons/events/ui/PersonPanelSelectionChangedEvent.java @@ -4,7 +4,7 @@ import seedu.address.ui.PersonCard; /** - * Represents a selection change in the Person List Panel + * Represents a selection change in the Book List Panel */ public class PersonPanelSelectionChangedEvent extends BaseEvent { diff --git a/src/main/java/seedu/address/logic/Logic.java b/src/main/java/seedu/address/logic/Logic.java index 8b34b862039a..678346ac1a73 100644 --- a/src/main/java/seedu/address/logic/Logic.java +++ b/src/main/java/seedu/address/logic/Logic.java @@ -4,7 +4,7 @@ import seedu.address.logic.commands.CommandResult; import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.logic.parser.exceptions.ParseException; -import seedu.address.model.person.Person; +import seedu.address.model.book.Book; /** * API of the Logic component @@ -20,7 +20,7 @@ public interface Logic { CommandResult execute(String commandText) throws CommandException, ParseException; /** Returns an unmodifiable view of the filtered list of persons */ - ObservableList getFilteredPersonList(); + ObservableList getFilteredPersonList(); /** Returns the list of input entered by the user, encapsulated in a {@code ListElementPointer} object */ ListElementPointer getHistorySnapshot(); diff --git a/src/main/java/seedu/address/logic/LogicManager.java b/src/main/java/seedu/address/logic/LogicManager.java index e992b3b83d6b..86b36fee91d9 100644 --- a/src/main/java/seedu/address/logic/LogicManager.java +++ b/src/main/java/seedu/address/logic/LogicManager.java @@ -11,7 +11,7 @@ import seedu.address.logic.parser.CatalogueParser; import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.Model; -import seedu.address.model.person.Person; +import seedu.address.model.book.Book; /** * The main LogicManager of the app. @@ -46,7 +46,7 @@ public CommandResult execute(String commandText) throws CommandException, ParseE } @Override - public ObservableList getFilteredPersonList() { + public ObservableList getFilteredPersonList() { return model.getFilteredPersonList(); } diff --git a/src/main/java/seedu/address/logic/commands/AddCommand.java b/src/main/java/seedu/address/logic/commands/AddCommand.java index c334710c0ea3..a4bf972da125 100644 --- a/src/main/java/seedu/address/logic/commands/AddCommand.java +++ b/src/main/java/seedu/address/logic/commands/AddCommand.java @@ -8,17 +8,17 @@ import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.person.Person; -import seedu.address.model.person.exceptions.DuplicatePersonException; +import seedu.address.model.book.Book; +import seedu.address.model.book.exceptions.DuplicatePersonException; /** - * Adds a person to the address book. + * Adds a book to the catalogue. */ public class AddCommand extends UndoableCommand { 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 a book to the catalogue. " + "Parameters: " + PREFIX_NAME + "NAME " + PREFIX_PHONE + "PHONE " @@ -33,17 +33,17 @@ public class AddCommand extends UndoableCommand { + PREFIX_TAG + "friends " + PREFIX_TAG + "owesMoney"; - 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 book added: %1$s"; + public static final String MESSAGE_DUPLICATE_PERSON = "This book already exists in the catalogue"; - private final Person toAdd; + private final Book toAdd; /** - * Creates an AddCommand to add the specified {@code Person} + * Creates an AddCommand to add the specified {@code Book} */ - public AddCommand(Person person) { - requireNonNull(person); - toAdd = person; + public AddCommand(Book book) { + requireNonNull(book); + toAdd = book; } @Override diff --git a/src/main/java/seedu/address/logic/commands/ClearCommand.java b/src/main/java/seedu/address/logic/commands/ClearCommand.java index cce6c851066f..5bdc200332e3 100644 --- a/src/main/java/seedu/address/logic/commands/ClearCommand.java +++ b/src/main/java/seedu/address/logic/commands/ClearCommand.java @@ -5,12 +5,12 @@ import seedu.address.model.Catalogue; /** - * Clears the address book. + * Clears the catalogue. */ public class ClearCommand extends UndoableCommand { public static final String COMMAND_WORD = "clear"; - public static final String MESSAGE_SUCCESS = "Address book has been cleared!"; + public static final String MESSAGE_SUCCESS = "Catalogue has been cleared!"; @Override diff --git a/src/main/java/seedu/address/logic/commands/DeleteCommand.java b/src/main/java/seedu/address/logic/commands/DeleteCommand.java index b539d240001a..2782a7764aab 100644 --- a/src/main/java/seedu/address/logic/commands/DeleteCommand.java +++ b/src/main/java/seedu/address/logic/commands/DeleteCommand.java @@ -8,26 +8,26 @@ import seedu.address.commons.core.Messages; import seedu.address.commons.core.index.Index; import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.person.Person; -import seedu.address.model.person.exceptions.PersonNotFoundException; +import seedu.address.model.book.Book; +import seedu.address.model.book.exceptions.PersonNotFoundException; /** - * Deletes a person identified using it's last displayed index from the address book. + * Deletes a book identified using it's last displayed index from the catalogue. */ public class DeleteCommand extends UndoableCommand { 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 last person listing.\n" + + ": Deletes the book identified by the index number used in the last book listing.\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_PERSON_SUCCESS = "Deleted Book: %1$s"; private final Index targetIndex; - private Person personToDelete; + private Book bookToDelete; public DeleteCommand(Index targetIndex) { this.targetIndex = targetIndex; @@ -36,25 +36,25 @@ public DeleteCommand(Index targetIndex) { @Override public CommandResult executeUndoableCommand() { - requireNonNull(personToDelete); + requireNonNull(bookToDelete); try { - model.deletePerson(personToDelete); + model.deletePerson(bookToDelete); } catch (PersonNotFoundException pnfe) { - throw new AssertionError("The target person cannot be missing"); + throw new AssertionError("The target book cannot be missing"); } - return new CommandResult(String.format(MESSAGE_DELETE_PERSON_SUCCESS, personToDelete)); + return new CommandResult(String.format(MESSAGE_DELETE_PERSON_SUCCESS, bookToDelete)); } @Override protected void preprocessUndoableCommand() throws CommandException { - List lastShownList = model.getFilteredPersonList(); + List lastShownList = model.getFilteredPersonList(); if (targetIndex.getZeroBased() >= lastShownList.size()) { throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); } - personToDelete = lastShownList.get(targetIndex.getZeroBased()); + bookToDelete = lastShownList.get(targetIndex.getZeroBased()); } @Override @@ -62,6 +62,6 @@ public boolean equals(Object other) { return other == this // short circuit if same object || (other instanceof DeleteCommand // instanceof handles nulls && this.targetIndex.equals(((DeleteCommand) other).targetIndex) // state check - && Objects.equals(this.personToDelete, ((DeleteCommand) other).personToDelete)); + && Objects.equals(this.bookToDelete, ((DeleteCommand) other).bookToDelete)); } } diff --git a/src/main/java/seedu/address/logic/commands/EditCommand.java b/src/main/java/seedu/address/logic/commands/EditCommand.java index e6c3a3e034bc..890b9df91647 100644 --- a/src/main/java/seedu/address/logic/commands/EditCommand.java +++ b/src/main/java/seedu/address/logic/commands/EditCommand.java @@ -19,24 +19,24 @@ import seedu.address.commons.core.index.Index; import seedu.address.commons.util.CollectionUtil; import seedu.address.logic.commands.exceptions.CommandException; -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.person.exceptions.DuplicatePersonException; -import seedu.address.model.person.exceptions.PersonNotFoundException; +import seedu.address.model.book.Address; +import seedu.address.model.book.Book; +import seedu.address.model.book.Email; +import seedu.address.model.book.Name; +import seedu.address.model.book.Phone; +import seedu.address.model.book.exceptions.DuplicatePersonException; +import seedu.address.model.book.exceptions.PersonNotFoundException; import seedu.address.model.tag.Tag; /** - * Edits the details of an existing person in the address book. + * Edits the details of an existing book in the catalogue. */ public class EditCommand extends UndoableCommand { 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 last person listing. " + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Edits the details of the book identified " + + "by the index number used in the last book listing. " + "Existing values will be overwritten by the input values.\n" + "Parameters: INDEX (must be a positive integer) " + "[" + PREFIX_NAME + "NAME] " @@ -48,19 +48,19 @@ public class EditCommand extends UndoableCommand { + 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_EDIT_PERSON_SUCCESS = "Edited Book: %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_PERSON = "This book already exists in the catalogue."; private final Index index; private final EditPersonDescriptor editPersonDescriptor; - private Person personToEdit; - private Person editedPerson; + private Book bookToEdit; + private Book editedBook; /** - * @param index of the person in the filtered person list to edit - * @param editPersonDescriptor details to edit the person with + * @param index of the book in the filtered book list to edit + * @param editPersonDescriptor details to edit the book with */ public EditCommand(Index index, EditPersonDescriptor editPersonDescriptor) { requireNonNull(index); @@ -73,42 +73,42 @@ public EditCommand(Index index, EditPersonDescriptor editPersonDescriptor) { @Override public CommandResult executeUndoableCommand() throws CommandException { try { - model.updatePerson(personToEdit, editedPerson); + model.updatePerson(bookToEdit, editedBook); } catch (DuplicatePersonException dpe) { throw new CommandException(MESSAGE_DUPLICATE_PERSON); } catch (PersonNotFoundException pnfe) { - throw new AssertionError("The target person cannot be missing"); + throw new AssertionError("The target book cannot be missing"); } model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); - return new CommandResult(String.format(MESSAGE_EDIT_PERSON_SUCCESS, editedPerson)); + return new CommandResult(String.format(MESSAGE_EDIT_PERSON_SUCCESS, editedBook)); } @Override protected void preprocessUndoableCommand() throws CommandException { - List lastShownList = model.getFilteredPersonList(); + List lastShownList = model.getFilteredPersonList(); if (index.getZeroBased() >= lastShownList.size()) { throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); } - personToEdit = lastShownList.get(index.getZeroBased()); - editedPerson = createEditedPerson(personToEdit, editPersonDescriptor); + bookToEdit = lastShownList.get(index.getZeroBased()); + editedBook = createEditedPerson(bookToEdit, editPersonDescriptor); } /** - * Creates and returns a {@code Person} with the details of {@code personToEdit} + * Creates and returns a {@code Book} with the details of {@code bookToEdit} * edited with {@code editPersonDescriptor}. */ - private static Person createEditedPerson(Person personToEdit, EditPersonDescriptor editPersonDescriptor) { - assert personToEdit != null; + private static Book createEditedPerson(Book bookToEdit, EditPersonDescriptor editPersonDescriptor) { + assert bookToEdit != 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 = editPersonDescriptor.getName().orElse(bookToEdit.getName()); + Phone updatedPhone = editPersonDescriptor.getPhone().orElse(bookToEdit.getPhone()); + Email updatedEmail = editPersonDescriptor.getEmail().orElse(bookToEdit.getEmail()); + Address updatedAddress = editPersonDescriptor.getAddress().orElse(bookToEdit.getAddress()); + Set updatedTags = editPersonDescriptor.getTags().orElse(bookToEdit.getTags()); - return new Person(updatedName, updatedPhone, updatedEmail, updatedAddress, updatedTags); + return new Book(updatedName, updatedPhone, updatedEmail, updatedAddress, updatedTags); } @Override @@ -127,12 +127,12 @@ public boolean equals(Object other) { EditCommand e = (EditCommand) other; return index.equals(e.index) && editPersonDescriptor.equals(e.editPersonDescriptor) - && Objects.equals(personToEdit, e.personToEdit); + && Objects.equals(bookToEdit, e.bookToEdit); } /** - * 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 book with. Each non-empty field value will replace the + * corresponding field value of the book. */ public static class EditPersonDescriptor { private Name name; diff --git a/src/main/java/seedu/address/logic/commands/ExitCommand.java b/src/main/java/seedu/address/logic/commands/ExitCommand.java index fbd1beb2966e..97c036f4c794 100644 --- a/src/main/java/seedu/address/logic/commands/ExitCommand.java +++ b/src/main/java/seedu/address/logic/commands/ExitCommand.java @@ -10,7 +10,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 Catalogue as requested ..."; @Override public CommandResult execute() { diff --git a/src/main/java/seedu/address/logic/commands/FindCommand.java b/src/main/java/seedu/address/logic/commands/FindCommand.java index b1e671f633d2..53add3fd6546 100644 --- a/src/main/java/seedu/address/logic/commands/FindCommand.java +++ b/src/main/java/seedu/address/logic/commands/FindCommand.java @@ -1,9 +1,9 @@ package seedu.address.logic.commands; -import seedu.address.model.person.NameContainsKeywordsPredicate; +import seedu.address.model.book.NameContainsKeywordsPredicate; /** - * Finds and lists all persons in address book whose name contains any of the argument keywords. + * Finds and lists all persons in catalogue whose name contains any of the argument keywords. * Keyword matching is case sensitive. */ public class FindCommand extends Command { diff --git a/src/main/java/seedu/address/logic/commands/ListCommand.java b/src/main/java/seedu/address/logic/commands/ListCommand.java index 7b6463780824..478b450d0525 100644 --- a/src/main/java/seedu/address/logic/commands/ListCommand.java +++ b/src/main/java/seedu/address/logic/commands/ListCommand.java @@ -3,7 +3,7 @@ import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS; /** - * Lists all persons in the address book to the user. + * Lists all persons in the catalogue to the user. */ public class ListCommand extends Command { diff --git a/src/main/java/seedu/address/logic/commands/SelectCommand.java b/src/main/java/seedu/address/logic/commands/SelectCommand.java index 9e3840a9dde6..e222d9e18c4d 100644 --- a/src/main/java/seedu/address/logic/commands/SelectCommand.java +++ b/src/main/java/seedu/address/logic/commands/SelectCommand.java @@ -7,21 +7,21 @@ import seedu.address.commons.core.index.Index; import seedu.address.commons.events.ui.JumpToListRequestEvent; import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.person.Person; +import seedu.address.model.book.Book; /** - * Selects a person identified using it's last displayed index from the address book. + * Selects a book identified using it's last displayed index from the catalogue. */ public class SelectCommand extends Command { public static final String COMMAND_WORD = "select"; public static final String MESSAGE_USAGE = COMMAND_WORD - + ": Selects the person identified by the index number used in the last person listing.\n" + + ": Selects the book identified by the index number used in the last book listing.\n" + "Parameters: INDEX (must be a positive integer)\n" + "Example: " + COMMAND_WORD + " 1"; - public static final String MESSAGE_SELECT_PERSON_SUCCESS = "Selected Person: %1$s"; + public static final String MESSAGE_SELECT_PERSON_SUCCESS = "Selected Book: %1$s"; private final Index targetIndex; @@ -32,7 +32,7 @@ public SelectCommand(Index targetIndex) { @Override public CommandResult execute() throws CommandException { - List lastShownList = model.getFilteredPersonList(); + List lastShownList = model.getFilteredPersonList(); if (targetIndex.getZeroBased() >= lastShownList.size()) { throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); diff --git a/src/main/java/seedu/address/logic/commands/UndoableCommand.java b/src/main/java/seedu/address/logic/commands/UndoableCommand.java index 7514822642d6..ffbe3f80a55b 100644 --- a/src/main/java/seedu/address/logic/commands/UndoableCommand.java +++ b/src/main/java/seedu/address/logic/commands/UndoableCommand.java @@ -17,7 +17,7 @@ public abstract class UndoableCommand extends Command { protected abstract CommandResult executeUndoableCommand() throws CommandException; /** - * Stores the current state of {@code model#addressBook}. + * Stores the current state of {@code model#catalogue}. */ private void saveCatalogueSnapshot() { requireNonNull(model); @@ -32,7 +32,7 @@ protected void preprocessUndoableCommand() throws CommandException {} /** * Reverts the Catalogue to the state before this command - * was executed and updates the filtered person list to + * was executed and updates the filtered book list to * show all persons. */ protected final void undo() { @@ -42,7 +42,7 @@ protected final void undo() { } /** - * Executes the command and updates the filtered person + * Executes the command and updates the filtered book * list to show all persons. */ protected final void redo() { diff --git a/src/main/java/seedu/address/logic/parser/AddCommandParser.java b/src/main/java/seedu/address/logic/parser/AddCommandParser.java index 3c729b388554..a0919f17e22e 100644 --- a/src/main/java/seedu/address/logic/parser/AddCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/AddCommandParser.java @@ -13,11 +13,11 @@ import seedu.address.commons.exceptions.IllegalValueException; 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.book.Address; +import seedu.address.model.book.Email; +import seedu.address.model.book.Name; +import seedu.address.model.book.Book; +import seedu.address.model.book.Phone; import seedu.address.model.tag.Tag; /** @@ -46,9 +46,9 @@ public AddCommand parse(String args) throws ParseException { Address address = ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS)).get(); Set tagList = ParserUtil.parseTags(argMultimap.getAllValues(PREFIX_TAG)); - Person person = new Person(name, phone, email, address, tagList); + Book book = new Book(name, phone, email, address, tagList); - return new AddCommand(person); + return new AddCommand(book); } catch (IllegalValueException ive) { throw new ParseException(ive.getMessage(), ive); } diff --git a/src/main/java/seedu/address/logic/parser/FindCommandParser.java b/src/main/java/seedu/address/logic/parser/FindCommandParser.java index b186a967cb94..488442ca0bc0 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.book.NameContainsKeywordsPredicate; /** * Parses input arguments and creates a new FindCommand object diff --git a/src/main/java/seedu/address/logic/parser/ParserUtil.java b/src/main/java/seedu/address/logic/parser/ParserUtil.java index 5d6d4ae3f7b1..5421dcfd2ae5 100644 --- a/src/main/java/seedu/address/logic/parser/ParserUtil.java +++ b/src/main/java/seedu/address/logic/parser/ParserUtil.java @@ -10,10 +10,10 @@ import seedu.address.commons.core.index.Index; import seedu.address.commons.exceptions.IllegalValueException; import seedu.address.commons.util.StringUtil; -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.book.Address; +import seedu.address.model.book.Email; +import seedu.address.model.book.Name; +import seedu.address.model.book.Phone; import seedu.address.model.tag.Tag; /** diff --git a/src/main/java/seedu/address/model/Catalogue.java b/src/main/java/seedu/address/model/Catalogue.java index 23994c7f723a..5bc4bb5e98fe 100644 --- a/src/main/java/seedu/address/model/Catalogue.java +++ b/src/main/java/seedu/address/model/Catalogue.java @@ -11,10 +11,10 @@ import java.util.stream.Collectors; import javafx.collections.ObservableList; -import seedu.address.model.person.Person; -import seedu.address.model.person.UniquePersonList; -import seedu.address.model.person.exceptions.DuplicatePersonException; -import seedu.address.model.person.exceptions.PersonNotFoundException; +import seedu.address.model.book.Book; +import seedu.address.model.book.UniquePersonList; +import seedu.address.model.book.exceptions.DuplicatePersonException; +import seedu.address.model.book.exceptions.PersonNotFoundException; import seedu.address.model.tag.Tag; import seedu.address.model.tag.UniqueTagList; @@ -51,8 +51,8 @@ public Catalogue(ReadOnlyCatalogue toBeCopied) { //// list overwrite operations - public void setPersons(List persons) throws DuplicatePersonException { - this.persons.setPersons(persons); + public void setPersons(List books) throws DuplicatePersonException { + this.persons.setPersons(books); } public void setTags(Set tags) { @@ -65,81 +65,81 @@ public void setTags(Set tags) { public void resetData(ReadOnlyCatalogue newData) { requireNonNull(newData); setTags(new HashSet<>(newData.getTagList())); - List syncedPersonList = newData.getPersonList().stream() + List syncedBookList = newData.getPersonList().stream() .map(this::syncWithMasterTagList) .collect(Collectors.toList()); try { - setPersons(syncedPersonList); + setPersons(syncedBookList); } catch (DuplicatePersonException e) { throw new AssertionError("Catalogue should not have duplicate persons"); } } - //// person-level operations + //// book-level operations /** - * Adds a person to the address book. - * Also checks the new person's tags and updates {@link #tags} with any new tags found, - * and updates the Tag objects in the person to point to those in {@link #tags}. + * Adds a book to the catalogue. + * Also checks the new book's tags and updates {@link #tags} with any new tags found, + * and updates the Tag objects in the book to point to those in {@link #tags}. * - * @throws DuplicatePersonException if an equivalent person already exists. + * @throws DuplicatePersonException if an equivalent book already exists. */ - public void addPerson(Person p) throws DuplicatePersonException { - Person person = syncWithMasterTagList(p); + public void addPerson(Book p) throws DuplicatePersonException { + Book book = syncWithMasterTagList(p); // TODO: the tags master list will be updated even though the below line fails. - // This can cause the tags master list to have additional tags that are not tagged to any person - // in the person list. - persons.add(person); + // This can cause the tags master list to have additional tags that are not tagged to any book + // in the book list. + persons.add(book); } /** - * Replaces the given person {@code target} in the list with {@code editedPerson}. + * Replaces the given book {@code target} in the list with {@code editedPerson}. * {@code Catalogue}'s tag list will be updated with the tags of {@code editedPerson}. * - * @throws DuplicatePersonException if updating the person's details causes the person to be equivalent to - * another existing person in the list. + * @throws DuplicatePersonException if updating the book's details causes the book to be equivalent to + * another existing book in the list. * @throws PersonNotFoundException if {@code target} could not be found in the list. * - * @see #syncWithMasterTagList(Person) + * @see #syncWithMasterTagList(Book) */ - public void updatePerson(Person target, Person editedPerson) + public void updatePerson(Book target, Book editedBook) throws DuplicatePersonException, PersonNotFoundException { - requireNonNull(editedPerson); + requireNonNull(editedBook); - Person syncedEditedPerson = syncWithMasterTagList(editedPerson); + Book syncedEditedBook = syncWithMasterTagList(editedBook); // TODO: the tags master list will be updated even though the below line fails. - // This can cause the tags master list to have additional tags that are not tagged to any person - // in the person list. - persons.setPerson(target, syncedEditedPerson); + // This can cause the tags master list to have additional tags that are not tagged to any book + // in the book list. + persons.setPerson(target, syncedEditedBook); } /** - * Updates the master tag list to include tags in {@code person} that are not in the list. - * @return a copy of this {@code person} such that every tag in this person points to a Tag object in the master + * Updates the master tag list to include tags in {@code book} that are not in the list. + * @return a copy of this {@code book} such that every tag in this book points to a Tag object in the master * list. */ - private Person syncWithMasterTagList(Person person) { - final UniqueTagList personTags = new UniqueTagList(person.getTags()); + private Book syncWithMasterTagList(Book book) { + final UniqueTagList personTags = new UniqueTagList(book.getTags()); tags.mergeFrom(personTags); // Create map with values = tag object references in the master list - // used for checking person tag references + // used for checking book tag references final Map masterTagObjects = new HashMap<>(); tags.forEach(tag -> masterTagObjects.put(tag, tag)); - // Rebuild the list of person tags to point to the relevant tags in the master tag list. + // Rebuild the list of book tags to point to the relevant tags in the master tag list. final Set correctTagReferences = new HashSet<>(); personTags.forEach(tag -> correctTagReferences.add(masterTagObjects.get(tag))); - return new Person( - person.getName(), person.getPhone(), person.getEmail(), person.getAddress(), correctTagReferences); + return new Book( + book.getName(), book.getPhone(), book.getEmail(), book.getAddress(), correctTagReferences); } /** * Removes {@code key} from this {@code Catalogue}. * @throws PersonNotFoundException if the {@code key} is not in this {@code Catalogue}. */ - public boolean removePerson(Person key) throws PersonNotFoundException { + public boolean removePerson(Book key) throws PersonNotFoundException { if (persons.remove(key)) { return true; } else { @@ -162,7 +162,7 @@ public String toString() { } @Override - public ObservableList getPersonList() { + public ObservableList getPersonList() { return persons.asObservableList(); } diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java index 183b25013e26..7540260c18cd 100644 --- a/src/main/java/seedu/address/model/Model.java +++ b/src/main/java/seedu/address/model/Model.java @@ -3,16 +3,16 @@ import java.util.function.Predicate; import javafx.collections.ObservableList; -import seedu.address.model.person.Person; -import seedu.address.model.person.exceptions.DuplicatePersonException; -import seedu.address.model.person.exceptions.PersonNotFoundException; +import seedu.address.model.book.Book; +import seedu.address.model.book.exceptions.DuplicatePersonException; +import seedu.address.model.book.exceptions.PersonNotFoundException; /** * 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_PERSONS = unused -> true; /** Clears existing backing model and replaces with the provided new data. */ void resetData(ReadOnlyCatalogue newData); @@ -20,29 +20,29 @@ public interface Model { /** Returns the Catalogue */ ReadOnlyCatalogue getCatalogue(); - /** Deletes the given person. */ - void deletePerson(Person target) throws PersonNotFoundException; + /** Deletes the given book. */ + void deletePerson(Book target) throws PersonNotFoundException; - /** Adds the given person */ - void addPerson(Person person) throws DuplicatePersonException; + /** Adds the given book */ + void addPerson(Book book) throws DuplicatePersonException; /** - * Replaces the given person {@code target} with {@code editedPerson}. + * Replaces the given book {@code target} with {@code editedBook}. * - * @throws DuplicatePersonException if updating the person's details causes the person to be equivalent to - * another existing person in the list. + * @throws DuplicatePersonException if updating the book's details causes the book to be equivalent to + * another existing book in the list. * @throws PersonNotFoundException if {@code target} could not be found in the list. */ - void updatePerson(Person target, Person editedPerson) + void updatePerson(Book target, Book editedBook) throws DuplicatePersonException, PersonNotFoundException; - /** Returns an unmodifiable view of the filtered person list */ - ObservableList getFilteredPersonList(); + /** Returns an unmodifiable view of the filtered book list */ + ObservableList getFilteredPersonList(); /** - * Updates the filter of the filtered person list to filter by the given {@code predicate}. + * Updates the filter of the filtered book list to filter by the given {@code predicate}. * @throws NullPointerException if {@code predicate} is null. */ - void updateFilteredPersonList(Predicate predicate); + void updateFilteredPersonList(Predicate predicate); } diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index c40a2b3dfe37..e1db0de6b423 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -12,19 +12,19 @@ import seedu.address.commons.core.ComponentManager; import seedu.address.commons.core.LogsCenter; import seedu.address.commons.events.model.CatalogueChangedEvent; -import seedu.address.model.person.Person; -import seedu.address.model.person.exceptions.DuplicatePersonException; -import seedu.address.model.person.exceptions.PersonNotFoundException; +import seedu.address.model.book.Book; +import seedu.address.model.book.exceptions.DuplicatePersonException; +import seedu.address.model.book.exceptions.PersonNotFoundException; /** - * Represents the in-memory model of the address book data. + * Represents the in-memory model of the catalogue data. * All changes to any model should be synchronized. */ public class ModelManager extends ComponentManager implements Model { private static final Logger logger = LogsCenter.getLogger(ModelManager.class); private final Catalogue catalogue; - private final FilteredList filteredPersons; + private final FilteredList filteredBooks; /** * Initializes a ModelManager with the given catalogue and userPrefs. @@ -33,10 +33,10 @@ public ModelManager(ReadOnlyCatalogue catalogue, UserPrefs userPrefs) { super(); requireAllNonNull(catalogue, userPrefs); - logger.fine("Initializing with address book: " + catalogue + " and user prefs " + userPrefs); + logger.fine("Initializing with catalogue: " + catalogue + " and user prefs " + userPrefs); this.catalogue = new Catalogue(catalogue); - filteredPersons = new FilteredList<>(this.catalogue.getPersonList()); + filteredBooks = new FilteredList<>(this.catalogue.getPersonList()); } public ModelManager() { @@ -60,42 +60,42 @@ private void indicateCatalogueChanged() { } @Override - public synchronized void deletePerson(Person target) throws PersonNotFoundException { + public synchronized void deletePerson(Book target) throws PersonNotFoundException { catalogue.removePerson(target); indicateCatalogueChanged(); } @Override - public synchronized void addPerson(Person person) throws DuplicatePersonException { - catalogue.addPerson(person); + public synchronized void addPerson(Book book) throws DuplicatePersonException { + catalogue.addPerson(book); updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); indicateCatalogueChanged(); } @Override - public void updatePerson(Person target, Person editedPerson) + public void updatePerson(Book target, Book editedBook) throws DuplicatePersonException, PersonNotFoundException { - requireAllNonNull(target, editedPerson); + requireAllNonNull(target, editedBook); - catalogue.updatePerson(target, editedPerson); + catalogue.updatePerson(target, editedBook); indicateCatalogueChanged(); } - //=========== Filtered Person List Accessors ============================================================= + //=========== Filtered Book 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 Book} backed by the internal list of * {@code catalogue} */ @Override - public ObservableList getFilteredPersonList() { - return FXCollections.unmodifiableObservableList(filteredPersons); + public ObservableList getFilteredPersonList() { + return FXCollections.unmodifiableObservableList(filteredBooks); } @Override - public void updateFilteredPersonList(Predicate predicate) { + public void updateFilteredPersonList(Predicate predicate) { requireNonNull(predicate); - filteredPersons.setPredicate(predicate); + filteredBooks.setPredicate(predicate); } @Override @@ -113,7 +113,7 @@ public boolean equals(Object obj) { // state check ModelManager other = (ModelManager) obj; return catalogue.equals(other.catalogue) - && filteredPersons.equals(other.filteredPersons); + && filteredBooks.equals(other.filteredBooks); } } diff --git a/src/main/java/seedu/address/model/ReadOnlyCatalogue.java b/src/main/java/seedu/address/model/ReadOnlyCatalogue.java index b4da2dd817ca..9f60168ebf24 100644 --- a/src/main/java/seedu/address/model/ReadOnlyCatalogue.java +++ b/src/main/java/seedu/address/model/ReadOnlyCatalogue.java @@ -1,11 +1,11 @@ package seedu.address.model; import javafx.collections.ObservableList; -import seedu.address.model.person.Person; +import seedu.address.model.book.Book; import seedu.address.model.tag.Tag; /** - * Unmodifiable view of an address book + * Unmodifiable view of an catalogue */ public interface ReadOnlyCatalogue { @@ -13,7 +13,7 @@ public interface ReadOnlyCatalogue { * Returns an unmodifiable view of the persons list. * This list will not contain any duplicate persons. */ - ObservableList getPersonList(); + ObservableList getPersonList(); /** * Returns an unmodifiable view of the tags list. diff --git a/src/main/java/seedu/address/model/UserPrefs.java b/src/main/java/seedu/address/model/UserPrefs.java index 05d53d3be9ab..0bf675cefff6 100644 --- a/src/main/java/seedu/address/model/UserPrefs.java +++ b/src/main/java/seedu/address/model/UserPrefs.java @@ -10,8 +10,8 @@ public class UserPrefs { private GuiSettings guiSettings; - private String catalogueFilePath = "data/addressbook.xml"; - private String catalogueBookName = "MyAddressBook"; + private String catalogueFilePath = "data/catalogue.xml"; + private String catalogueBookName = "MyCatalogue"; public UserPrefs() { this.setGuiSettings(500, 500, 0, 0); diff --git a/src/main/java/seedu/address/model/person/Address.java b/src/main/java/seedu/address/model/book/Address.java similarity index 85% rename from src/main/java/seedu/address/model/person/Address.java rename to src/main/java/seedu/address/model/book/Address.java index 5e981f07790a..8e1e90713cfd 100644 --- a/src/main/java/seedu/address/model/person/Address.java +++ b/src/main/java/seedu/address/model/book/Address.java @@ -1,16 +1,16 @@ -package seedu.address.model.person; +package seedu.address.model.book; import static java.util.Objects.requireNonNull; import static seedu.address.commons.util.AppUtil.checkArgument; /** - * Represents a Person's address in the address book. + * Represents a Book's address in the catalogue. * Guarantees: immutable; is valid as declared in {@link #isValidAddress(String)} */ public class Address { public static final String MESSAGE_ADDRESS_CONSTRAINTS = - "Person addresses can take any values, and it should not be blank"; + "Book addresses can take any values, and it should not be blank"; /* * The first character of the address must not be a whitespace, @@ -32,7 +32,7 @@ public Address(String address) { } /** - * Returns true if a given string is a valid person email. + * Returns true if a given string is a valid book email. */ public static boolean isValidAddress(String test) { return test.matches(ADDRESS_VALIDATION_REGEX); diff --git a/src/main/java/seedu/address/model/person/Person.java b/src/main/java/seedu/address/model/book/Book.java similarity index 80% rename from src/main/java/seedu/address/model/person/Person.java rename to src/main/java/seedu/address/model/book/Book.java index ec9f2aa5e919..61727cf786b0 100644 --- a/src/main/java/seedu/address/model/person/Person.java +++ b/src/main/java/seedu/address/model/book/Book.java @@ -1,4 +1,4 @@ -package seedu.address.model.person; +package seedu.address.model.book; import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; @@ -10,12 +10,13 @@ import seedu.address.model.tag.UniqueTagList; /** - * Represents a Person in the address book. + * Represents a Book in the catalogue. * Guarantees: details are present and not null, field values are validated, immutable. */ -public class Person { +public class Book { private final Name name; + private final Phone phone; private final Email email; private final Address address; @@ -25,7 +26,7 @@ public class Person { /** * Every field must be present and not null. */ - public Person(Name name, Phone phone, Email email, Address address, Set tags) { + public Book(Name name, Phone phone, Email email, Address address, Set tags) { requireAllNonNull(name, phone, email, address, tags); this.name = name; this.phone = phone; @@ -65,15 +66,15 @@ public boolean equals(Object other) { return true; } - if (!(other instanceof Person)) { + if (!(other instanceof Book)) { return false; } - Person otherPerson = (Person) other; - return otherPerson.getName().equals(this.getName()) - && otherPerson.getPhone().equals(this.getPhone()) - && otherPerson.getEmail().equals(this.getEmail()) - && otherPerson.getAddress().equals(this.getAddress()); + Book otherBook = (Book) other; + return otherBook.getName().equals(this.getName()) + && otherBook.getPhone().equals(this.getPhone()) + && otherBook.getEmail().equals(this.getEmail()) + && otherBook.getAddress().equals(this.getAddress()); } @Override diff --git a/src/main/java/seedu/address/model/person/Email.java b/src/main/java/seedu/address/model/book/Email.java similarity index 89% rename from src/main/java/seedu/address/model/person/Email.java rename to src/main/java/seedu/address/model/book/Email.java index 3759a577ec59..58445ebed5c0 100644 --- a/src/main/java/seedu/address/model/person/Email.java +++ b/src/main/java/seedu/address/model/book/Email.java @@ -1,16 +1,16 @@ -package seedu.address.model.person; +package seedu.address.model.book; import static java.util.Objects.requireNonNull; import static seedu.address.commons.util.AppUtil.checkArgument; /** - * Represents a Person's email in the address book. + * Represents a Book's email in the catalogue. * Guarantees: immutable; is valid as declared in {@link #isValidEmail(String)} */ public class Email { private static final String SPECIAL_CHARACTERS = "!#$%&'*+/=?`{|}~^.-"; - public static final String MESSAGE_EMAIL_CONSTRAINTS = "Person emails should be of the format local-part@domain " + public static final String MESSAGE_EMAIL_CONSTRAINTS = "Book 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" @@ -41,7 +41,7 @@ public Email(String email) { } /** - * Returns if a given string is a valid person email. + * Returns if a given string is a valid book email. */ public static boolean isValidEmail(String test) { return test.matches(EMAIL_VALIDATION_REGEX); diff --git a/src/main/java/seedu/address/model/person/Name.java b/src/main/java/seedu/address/model/book/Name.java similarity index 84% rename from src/main/java/seedu/address/model/person/Name.java rename to src/main/java/seedu/address/model/book/Name.java index 8e632943c4cf..d40cecae288c 100644 --- a/src/main/java/seedu/address/model/person/Name.java +++ b/src/main/java/seedu/address/model/book/Name.java @@ -1,16 +1,16 @@ -package seedu.address.model.person; +package seedu.address.model.book; import static java.util.Objects.requireNonNull; import static seedu.address.commons.util.AppUtil.checkArgument; /** - * Represents a Person's name in the address book. + * Represents a Book's name in the catalogue. * Guarantees: immutable; is valid as declared in {@link #isValidName(String)} */ public class Name { public static final String MESSAGE_NAME_CONSTRAINTS = - "Person names should only contain alphanumeric characters and spaces, and it should not be blank"; + "Book 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, @@ -32,7 +32,7 @@ public Name(String name) { } /** - * Returns true if a given string is a valid person name. + * Returns true if a given string is a valid book name. */ public static boolean isValidName(String test) { return test.matches(NAME_VALIDATION_REGEX); diff --git a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/book/NameContainsKeywordsPredicate.java similarity index 78% rename from src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java rename to src/main/java/seedu/address/model/book/NameContainsKeywordsPredicate.java index 827e2cc106bd..30550be4cea8 100644 --- a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java +++ b/src/main/java/seedu/address/model/book/NameContainsKeywordsPredicate.java @@ -1,4 +1,4 @@ -package seedu.address.model.person; +package seedu.address.model.book; 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 Book}'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(Book book) { return keywords.stream() - .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(person.getName().fullName, keyword)); + .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(book.getName().fullName, keyword)); } @Override diff --git a/src/main/java/seedu/address/model/person/Phone.java b/src/main/java/seedu/address/model/book/Phone.java similarity index 88% rename from src/main/java/seedu/address/model/person/Phone.java rename to src/main/java/seedu/address/model/book/Phone.java index 11b5435ac247..7c23be55e1d5 100644 --- a/src/main/java/seedu/address/model/person/Phone.java +++ b/src/main/java/seedu/address/model/book/Phone.java @@ -1,10 +1,10 @@ -package seedu.address.model.person; +package seedu.address.model.book; import static java.util.Objects.requireNonNull; import static seedu.address.commons.util.AppUtil.checkArgument; /** - * Represents a Person's phone number in the address book. + * Represents a Book's phone number in the catalogue. * Guarantees: immutable; is valid as declared in {@link #isValidPhone(String)} */ public class Phone { @@ -27,7 +27,7 @@ public Phone(String phone) { } /** - * Returns true if a given string is a valid person phone number. + * Returns true if a given string is a valid book phone number. */ public static boolean isValidPhone(String test) { return test.matches(PHONE_VALIDATION_REGEX); diff --git a/src/main/java/seedu/address/model/person/UniquePersonList.java b/src/main/java/seedu/address/model/book/UniquePersonList.java similarity index 60% rename from src/main/java/seedu/address/model/person/UniquePersonList.java rename to src/main/java/seedu/address/model/book/UniquePersonList.java index f2c4c4c585e4..d50c34b43d75 100644 --- a/src/main/java/seedu/address/model/person/UniquePersonList.java +++ b/src/main/java/seedu/address/model/book/UniquePersonList.java @@ -1,4 +1,4 @@ -package seedu.address.model.person; +package seedu.address.model.book; import static java.util.Objects.requireNonNull; import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; @@ -9,35 +9,35 @@ import javafx.collections.FXCollections; import javafx.collections.ObservableList; import seedu.address.commons.util.CollectionUtil; -import seedu.address.model.person.exceptions.DuplicatePersonException; -import seedu.address.model.person.exceptions.PersonNotFoundException; +import seedu.address.model.book.exceptions.DuplicatePersonException; +import seedu.address.model.book.exceptions.PersonNotFoundException; /** * A list of persons that enforces uniqueness between its elements and does not allow nulls. * * Supports a minimal set of list operations. * - * @see Person#equals(Object) + * @see Book#equals(Object) * @see CollectionUtil#elementsAreUnique(Collection) */ -public class UniquePersonList implements Iterable { +public class UniquePersonList implements Iterable { - private final ObservableList internalList = FXCollections.observableArrayList(); + private final ObservableList internalList = FXCollections.observableArrayList(); /** - * Returns true if the list contains an equivalent person as the given argument. + * Returns true if the list contains an equivalent book as the given argument. */ - public boolean contains(Person toCheck) { + public boolean contains(Book toCheck) { requireNonNull(toCheck); return internalList.contains(toCheck); } /** - * Adds a person to the list. + * Adds a book to the list. * - * @throws DuplicatePersonException if the person to add is a duplicate of an existing person in the list. + * @throws DuplicatePersonException if the book to add is a duplicate of an existing book in the list. */ - public void add(Person toAdd) throws DuplicatePersonException { + public void add(Book toAdd) throws DuplicatePersonException { requireNonNull(toAdd); if (contains(toAdd)) { throw new DuplicatePersonException(); @@ -46,33 +46,33 @@ public void add(Person toAdd) throws DuplicatePersonException { } /** - * Replaces the person {@code target} in the list with {@code editedPerson}. + * Replaces the book {@code target} in the list with {@code editedBook}. * - * @throws DuplicatePersonException if the replacement is equivalent to another existing person in the list. + * @throws DuplicatePersonException if the replacement is equivalent to another existing book in the list. * @throws PersonNotFoundException if {@code target} could not be found in the list. */ - public void setPerson(Person target, Person editedPerson) + public void setPerson(Book target, Book editedBook) throws DuplicatePersonException, PersonNotFoundException { - requireNonNull(editedPerson); + requireNonNull(editedBook); int index = internalList.indexOf(target); if (index == -1) { throw new PersonNotFoundException(); } - if (!target.equals(editedPerson) && internalList.contains(editedPerson)) { + if (!target.equals(editedBook) && internalList.contains(editedBook)) { throw new DuplicatePersonException(); } - internalList.set(index, editedPerson); + internalList.set(index, editedBook); } /** - * Removes the equivalent person from the list. + * Removes the equivalent book from the list. * - * @throws PersonNotFoundException if no such person could be found in the list. + * @throws PersonNotFoundException if no such book could be found in the list. */ - public boolean remove(Person toRemove) throws PersonNotFoundException { + public boolean remove(Book toRemove) throws PersonNotFoundException { requireNonNull(toRemove); final boolean personFoundAndDeleted = internalList.remove(toRemove); if (!personFoundAndDeleted) { @@ -85,11 +85,11 @@ public void setPersons(UniquePersonList replacement) { this.internalList.setAll(replacement.internalList); } - public void setPersons(List persons) throws DuplicatePersonException { - requireAllNonNull(persons); + public void setPersons(List books) throws DuplicatePersonException { + requireAllNonNull(books); final UniquePersonList replacement = new UniquePersonList(); - for (final Person person : persons) { - replacement.add(person); + for (final Book book : books) { + replacement.add(book); } setPersons(replacement); } @@ -97,12 +97,12 @@ public void setPersons(List persons) throws DuplicatePersonException { /** * Returns the backing list as an unmodifiable {@code ObservableList}. */ - public ObservableList asObservableList() { + public ObservableList asObservableList() { return FXCollections.unmodifiableObservableList(internalList); } @Override - public Iterator iterator() { + public Iterator iterator() { return internalList.iterator(); } diff --git a/src/main/java/seedu/address/model/person/exceptions/DuplicatePersonException.java b/src/main/java/seedu/address/model/book/exceptions/DuplicatePersonException.java similarity index 68% rename from src/main/java/seedu/address/model/person/exceptions/DuplicatePersonException.java rename to src/main/java/seedu/address/model/book/exceptions/DuplicatePersonException.java index fce401885dc8..8584fcf2aa25 100644 --- a/src/main/java/seedu/address/model/person/exceptions/DuplicatePersonException.java +++ b/src/main/java/seedu/address/model/book/exceptions/DuplicatePersonException.java @@ -1,9 +1,9 @@ -package seedu.address.model.person.exceptions; +package seedu.address.model.book.exceptions; import seedu.address.commons.exceptions.DuplicateDataException; /** - * Signals that the operation will result in duplicate Person objects. + * Signals that the operation will result in duplicate Book objects. */ public class DuplicatePersonException extends DuplicateDataException { public DuplicatePersonException() { diff --git a/src/main/java/seedu/address/model/book/exceptions/PersonNotFoundException.java b/src/main/java/seedu/address/model/book/exceptions/PersonNotFoundException.java new file mode 100644 index 000000000000..ac0bd58e8780 --- /dev/null +++ b/src/main/java/seedu/address/model/book/exceptions/PersonNotFoundException.java @@ -0,0 +1,6 @@ +package seedu.address.model.book.exceptions; + +/** + * Signals that the operation is unable to find the specified book. + */ +public class PersonNotFoundException extends Exception {} 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 f757e25f5566..000000000000 --- 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 Exception {} diff --git a/src/main/java/seedu/address/model/tag/Tag.java b/src/main/java/seedu/address/model/tag/Tag.java index 65bdd769995d..ae4c43faf1e1 100644 --- a/src/main/java/seedu/address/model/tag/Tag.java +++ b/src/main/java/seedu/address/model/tag/Tag.java @@ -4,7 +4,7 @@ import static seedu.address.commons.util.AppUtil.checkArgument; /** - * Represents a Tag in the address book. + * Represents a Tag in the catalogue. * Guarantees: immutable; name is valid as declared in {@link #isValidTagName(String)} */ public class Tag { diff --git a/src/main/java/seedu/address/model/util/SampleDataUtil.java b/src/main/java/seedu/address/model/util/SampleDataUtil.java index d4600c0b04b9..cb785d22a821 100644 --- a/src/main/java/seedu/address/model/util/SampleDataUtil.java +++ b/src/main/java/seedu/address/model/util/SampleDataUtil.java @@ -5,36 +5,36 @@ import seedu.address.model.Catalogue; import seedu.address.model.ReadOnlyCatalogue; -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.person.exceptions.DuplicatePersonException; +import seedu.address.model.book.Address; +import seedu.address.model.book.Book; +import seedu.address.model.book.Email; +import seedu.address.model.book.Name; +import seedu.address.model.book.Phone; +import seedu.address.model.book.exceptions.DuplicatePersonException; import seedu.address.model.tag.Tag; /** * Contains utility methods for populating {@code Catalogue} 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"), + public static Book[] getSamplePersons() { + return new Book[] { + new Book(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 Book(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 Book(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 Book(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 Book(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 Book(new Name("Roy Balakrishnan"), new Phone("92624417"), new Email("royb@example.com"), new Address("Blk 45 Aljunied Street 85, #11-31"), getTagSet("colleagues")) }; @@ -43,8 +43,8 @@ public static Person[] getSamplePersons() { public static ReadOnlyCatalogue getSampleCatalogue() { try { Catalogue sampleAb = new Catalogue(); - for (Person samplePerson : getSamplePersons()) { - sampleAb.addPerson(samplePerson); + for (Book sampleBook : getSamplePersons()) { + sampleAb.addPerson(sampleBook); } return sampleAb; } catch (DuplicatePersonException e) { diff --git a/src/main/java/seedu/address/storage/Storage.java b/src/main/java/seedu/address/storage/Storage.java index 9e6632a1d759..934a73dbfeb7 100644 --- a/src/main/java/seedu/address/storage/Storage.java +++ b/src/main/java/seedu/address/storage/Storage.java @@ -30,7 +30,7 @@ public interface Storage extends CatalogueStorage, UserPrefsStorage { void saveCatalogue(ReadOnlyCatalogue catalogue) throws IOException; /** - * Saves the current version of the Address Book to the hard disk. + * Saves the current version of the Catalogue to the hard disk. * Creates the data file if it is missing. * Raises {@link DataSavingExceptionEvent} if there was an error during saving. */ diff --git a/src/main/java/seedu/address/storage/XmlAdaptedPerson.java b/src/main/java/seedu/address/storage/XmlAdaptedPerson.java index 2cd92dc4fd20..63b5537ad14f 100644 --- a/src/main/java/seedu/address/storage/XmlAdaptedPerson.java +++ b/src/main/java/seedu/address/storage/XmlAdaptedPerson.java @@ -9,19 +9,19 @@ import javax.xml.bind.annotation.XmlElement; 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.book.Address; +import seedu.address.model.book.Book; +import seedu.address.model.book.Email; +import seedu.address.model.book.Name; +import seedu.address.model.book.Phone; import seedu.address.model.tag.Tag; /** - * JAXB-friendly version of the Person. + * JAXB-friendly version of the Book. */ public class XmlAdaptedPerson { - public static final String MISSING_FIELD_MESSAGE_FORMAT = "Person's %s field is missing!"; + public static final String MISSING_FIELD_MESSAGE_FORMAT = "Book's %s field is missing!"; @XmlElement(required = true) private String name; @@ -42,7 +42,7 @@ public class XmlAdaptedPerson { public XmlAdaptedPerson() {} /** - * Constructs an {@code XmlAdaptedPerson} with the given person details. + * Constructs an {@code XmlAdaptedPerson} with the given book details. */ public XmlAdaptedPerson(String name, String phone, String email, String address, List tagged) { this.name = name; @@ -55,11 +55,11 @@ public XmlAdaptedPerson(String name, String phone, String email, String address, } /** - * Converts a given Person into this class for JAXB use. + * Converts a given Book into this class for JAXB use. * * @param source future changes to this will not affect the created XmlAdaptedPerson */ - public XmlAdaptedPerson(Person source) { + public XmlAdaptedPerson(Book source) { name = source.getName().fullName; phone = source.getPhone().value; email = source.getEmail().value; @@ -71,11 +71,11 @@ public XmlAdaptedPerson(Person source) { } /** - * Converts this jaxb-friendly adapted person object into the model's Person object. + * Converts this jaxb-friendly adapted book object into the model's Book object. * - * @throws IllegalValueException if there were any data constraints violated in the adapted person + * @throws IllegalValueException if there were any data constraints violated in the adapted book */ - public Person toModelType() throws IllegalValueException { + public Book toModelType() throws IllegalValueException { final List personTags = new ArrayList<>(); for (XmlAdaptedTag tag : tagged) { personTags.add(tag.toModelType()); @@ -114,7 +114,7 @@ public Person toModelType() throws IllegalValueException { final Address address = new Address(this.address); final Set tags = new HashSet<>(personTags); - return new Person(name, phone, email, address, tags); + return new Book(name, phone, email, address, tags); } @Override diff --git a/src/main/java/seedu/address/storage/XmlAdaptedTag.java b/src/main/java/seedu/address/storage/XmlAdaptedTag.java index d3e2d8be9c4f..3a83e6b023b0 100644 --- a/src/main/java/seedu/address/storage/XmlAdaptedTag.java +++ b/src/main/java/seedu/address/storage/XmlAdaptedTag.java @@ -38,7 +38,7 @@ public XmlAdaptedTag(Tag source) { /** * Converts this jaxb-friendly adapted tag object into the model's Tag object. * - * @throws IllegalValueException if there were any data constraints violated in the adapted person + * @throws IllegalValueException if there were any data constraints violated in the adapted book */ public Tag toModelType() throws IllegalValueException { if (!Tag.isValidTagName(tagName)) { diff --git a/src/main/java/seedu/address/storage/XmlFileStorage.java b/src/main/java/seedu/address/storage/XmlFileStorage.java index 1f8519a871af..75a2068d6f21 100644 --- a/src/main/java/seedu/address/storage/XmlFileStorage.java +++ b/src/main/java/seedu/address/storage/XmlFileStorage.java @@ -9,11 +9,11 @@ import seedu.address.commons.util.XmlUtil; /** - * Stores addressbook data in an XML file + * Stores catalogue data in an XML file */ public class XmlFileStorage { /** - * Saves the given addressbook data to the specified file. + * Saves the given catalogue data to the specified file. */ public static void saveDataToFile(File file, XmlSerializableCatalogue catalogue) throws FileNotFoundException { @@ -25,7 +25,7 @@ public static void saveDataToFile(File file, XmlSerializableCatalogue catalogue) } /** - * Returns address book in the file or an empty address book + * Returns catalogue in the file or an empty catalogue */ public static XmlSerializableCatalogue loadDataFromSaveFile(File file) throws DataConversionException, FileNotFoundException { diff --git a/src/main/java/seedu/address/ui/BrowserPanel.java b/src/main/java/seedu/address/ui/BrowserPanel.java index bb0d61380d5a..cd6e7a351539 100644 --- a/src/main/java/seedu/address/ui/BrowserPanel.java +++ b/src/main/java/seedu/address/ui/BrowserPanel.java @@ -13,7 +13,7 @@ import seedu.address.MainApp; import seedu.address.commons.core.LogsCenter; import seedu.address.commons.events.ui.PersonPanelSelectionChangedEvent; -import seedu.address.model.person.Person; +import seedu.address.model.book.Book; /** * The Browser Panel of the App. @@ -41,8 +41,8 @@ public BrowserPanel() { registerAsAnEventHandler(this); } - private void loadPersonPage(Person person) { - loadPage(SEARCH_PAGE_URL + person.getName().fullName); + private void loadPersonPage(Book book) { + loadPage(SEARCH_PAGE_URL + book.getName().fullName); } public void loadPage(String url) { @@ -67,6 +67,6 @@ public void freeResources() { @Subscribe private void handlePersonPanelSelectionChangedEvent(PersonPanelSelectionChangedEvent event) { logger.info(LogsCenter.getEventHandlingLogMessage(event)); - loadPersonPage(event.getNewSelection().person); + loadPersonPage(event.getNewSelection().book); } } diff --git a/src/main/java/seedu/address/ui/PersonCard.java b/src/main/java/seedu/address/ui/PersonCard.java index 9ea2b86b4b7d..3f4d95baf570 100644 --- a/src/main/java/seedu/address/ui/PersonCard.java +++ b/src/main/java/seedu/address/ui/PersonCard.java @@ -5,10 +5,10 @@ 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.book.Book; /** - * An UI component that displays information of a {@code Person}. + * An UI component that displays information of a {@code Book}. */ public class PersonCard extends UiPart { @@ -22,7 +22,7 @@ public class PersonCard extends UiPart { * @see The issue on Catalogue level 4 */ - public final Person person; + public final Book book; @FXML private HBox cardPane; @@ -39,15 +39,15 @@ public class PersonCard extends UiPart { @FXML private FlowPane tags; - public PersonCard(Person person, int displayedIndex) { + public PersonCard(Book book, int displayedIndex) { super(FXML); - this.person = person; + this.book = book; 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().forEach(tag -> tags.getChildren().add(new Label(tag.tagName))); + name.setText(book.getName().fullName); + phone.setText(book.getPhone().value); + address.setText(book.getAddress().value); + email.setText(book.getEmail().value); + book.getTags().forEach(tag -> tags.getChildren().add(new Label(tag.tagName))); } @Override @@ -65,6 +65,6 @@ public boolean equals(Object other) { // state check PersonCard card = (PersonCard) other; return id.getText().equals(card.id.getText()) - && person.equals(card.person); + && book.equals(card.book); } } diff --git a/src/main/java/seedu/address/ui/PersonListPanel.java b/src/main/java/seedu/address/ui/PersonListPanel.java index 60a4f70f4e71..7f5fc87c9401 100644 --- a/src/main/java/seedu/address/ui/PersonListPanel.java +++ b/src/main/java/seedu/address/ui/PersonListPanel.java @@ -15,7 +15,7 @@ import seedu.address.commons.core.LogsCenter; import seedu.address.commons.events.ui.JumpToListRequestEvent; import seedu.address.commons.events.ui.PersonPanelSelectionChangedEvent; -import seedu.address.model.person.Person; +import seedu.address.model.book.Book; /** * Panel containing the list of persons. @@ -27,15 +27,15 @@ public class PersonListPanel extends UiPart { @FXML private ListView personListView; - public PersonListPanel(ObservableList personList) { + public PersonListPanel(ObservableList bookList) { super(FXML); - setConnections(personList); + setConnections(bookList); registerAsAnEventHandler(this); } - private void setConnections(ObservableList personList) { + private void setConnections(ObservableList bookList) { ObservableList mappedList = EasyBind.map( - personList, (person) -> new PersonCard(person, personList.indexOf(person) + 1)); + bookList, (person) -> new PersonCard(person, bookList.indexOf(person) + 1)); personListView.setItems(mappedList); personListView.setCellFactory(listView -> new PersonListViewCell()); setEventHandlerForSelectionChangeEvent(); @@ -45,7 +45,7 @@ private void setEventHandlerForSelectionChangeEvent() { personListView.getSelectionModel().selectedItemProperty() .addListener((observable, oldValue, newValue) -> { if (newValue != null) { - logger.fine("Selection in person list panel changed to : '" + newValue + "'"); + logger.fine("Selection in book list panel changed to : '" + newValue + "'"); raise(new PersonPanelSelectionChangedEvent(newValue)); } }); diff --git a/src/main/resources/view/MainWindow.fxml b/src/main/resources/view/MainWindow.fxml index 1dadb95b6ffe..35ac5f11784d 100644 --- a/src/main/resources/view/MainWindow.fxml +++ b/src/main/resources/view/MainWindow.fxml @@ -47,7 +47,7 @@ - + diff --git a/src/test/data/JsonUserPrefsStorageTest/ExtraValuesUserPref.json b/src/test/data/JsonUserPrefsStorageTest/ExtraValuesUserPref.json index 87e25c850ade..e6af1af8b781 100644 --- a/src/test/data/JsonUserPrefsStorageTest/ExtraValuesUserPref.json +++ b/src/test/data/JsonUserPrefsStorageTest/ExtraValuesUserPref.json @@ -9,6 +9,6 @@ "z" : 99 } }, - "addressBookFilePath" : "addressbook.xml", - "addressBookName" : "TypicalAddressBookName" + "catalogueFilePath": "catalogue.xml", + "catalogueName": "TypicalCatalogueName" } diff --git a/src/test/data/JsonUserPrefsStorageTest/TypicalUserPref.json b/src/test/data/JsonUserPrefsStorageTest/TypicalUserPref.json index ea6836466914..61eaa12ad44a 100644 --- a/src/test/data/JsonUserPrefsStorageTest/TypicalUserPref.json +++ b/src/test/data/JsonUserPrefsStorageTest/TypicalUserPref.json @@ -7,6 +7,6 @@ "y" : 100 } }, - "addressBookFilePath" : "addressbook.xml", - "addressBookName" : "TypicalAddressBookName" + "catalogueFilePath": "catalogue.xml", + "catalogueName": "TypicalCatalogueName" } diff --git a/src/test/data/XmlAddressBookStorageTest/invalidAndValidPersonAddressBook.xml b/src/test/data/XmlAddressBookStorageTest/invalidAndValidPersonAddressBook.xml index 41e411568a5f..5eb9157b04b6 100644 --- a/src/test/data/XmlAddressBookStorageTest/invalidAndValidPersonAddressBook.xml +++ b/src/test/data/XmlAddressBookStorageTest/invalidAndValidPersonAddressBook.xml @@ -1,17 +1,17 @@ - - - + + + Hans Muster 9482424 hans@example.com