From 5ff1aaecc36f9cbebe408a74992e45fb7e8c5bd5 Mon Sep 17 00:00:00 2001 From: Yufan Date: Fri, 17 Feb 2023 10:04:45 +0800 Subject: [PATCH 001/334] Update gradle.yml add line give Gradle Wrapper permission --- .github/workflows/gradle.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 81267b247eb..be62badb851 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -20,6 +20,9 @@ jobs: - name: Merge to master run: git checkout --progress --force ${{ github.sha }} + + - name: Give execute permissions to Gradle wrapper + run: chmod +x ./gradlew - name: Run repository-wide tests if: runner.os == 'Linux' From 9aa1e2e78965adf1c0e8a258991ba4d3e0fc8f68 Mon Sep 17 00:00:00 2001 From: Yufan Date: Fri, 17 Feb 2023 10:07:57 +0800 Subject: [PATCH 002/334] Update gradle.yml --- .github/workflows/gradle.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index be62badb851..783ebdb6369 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -19,8 +19,7 @@ jobs: ref: master - name: Merge to master - run: git checkout --progress --force ${{ github.sha }} - + run: git checkout --progress --force ${{ github.sha }} - name: Give execute permissions to Gradle wrapper run: chmod +x ./gradlew From e3c2e5f4aa12f25016b4b54a736b04c6f5642f66 Mon Sep 17 00:00:00 2001 From: Yufan Date: Fri, 17 Feb 2023 10:10:06 +0800 Subject: [PATCH 003/334] Update gradle.yml --- .github/workflows/gradle.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 783ebdb6369..af21c7fe4ca 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -19,7 +19,8 @@ jobs: ref: master - name: Merge to master - run: git checkout --progress --force ${{ github.sha }} + run: git checkout --progress --force ${{ github.sha }} + - name: Give execute permissions to Gradle wrapper run: chmod +x ./gradlew @@ -27,7 +28,7 @@ jobs: if: runner.os == 'Linux' working-directory: ${{ github.workspace }}/.github run: ./run-checks.sh - + - name: Validate Gradle Wrapper uses: gradle/wrapper-validation-action@v1 From 276ca13cdfe847697c0ea841b2671e8a2988a31f Mon Sep 17 00:00:00 2001 From: Yufan Date: Fri, 17 Feb 2023 10:14:24 +0800 Subject: [PATCH 004/334] Update gradle.yml --- .github/workflows/gradle.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index af21c7fe4ca..23b130cbb81 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -1,6 +1,8 @@ name: Java CI -on: [push, pull_request] +on: + push: + pull_request: jobs: build: @@ -26,7 +28,7 @@ jobs: - name: Run repository-wide tests if: runner.os == 'Linux' - working-directory: ${{ github.workspace }}/.github + working-directory: ${{ github.workspace }}/.github run: ./run-checks.sh - name: Validate Gradle Wrapper From f599e866167b12b47ffe7002a5d19ed6b9b11e0f Mon Sep 17 00:00:00 2001 From: Yufan Date: Fri, 17 Feb 2023 10:17:52 +0800 Subject: [PATCH 005/334] Update gradle.yml --- .github/workflows/gradle.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 23b130cbb81..9d390cbf9ad 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -22,7 +22,7 @@ jobs: - name: Merge to master run: git checkout --progress --force ${{ github.sha }} - + - name: Give execute permissions to Gradle wrapper run: chmod +x ./gradlew @@ -30,7 +30,7 @@ jobs: if: runner.os == 'Linux' working-directory: ${{ github.workspace }}/.github run: ./run-checks.sh - + - name: Validate Gradle Wrapper uses: gradle/wrapper-validation-action@v1 From 50a2d94283a8a6618da681020c2d28cb344199ac Mon Sep 17 00:00:00 2001 From: YF Date: Fri, 17 Feb 2023 14:17:50 +0800 Subject: [PATCH 006/334] Refactor and Add View Button This commit updates the codebase to use the term "Student" instead of "Person", and "TutorPro" instead of "Address Book", to better reflect the domain of the application. Additionally, a view button has been added to each student card for easier access to their information. --- docs/tutorials/AddRemark.md | 4 +- docs/tutorials/RemovingFields.md | 2 +- src/main/java/seedu/address/MainApp.java | 14 +- .../seedu/address/commons/core/Messages.java | 4 +- 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 | 2 +- .../address/logic/commands/DeleteCommand.java | 6 +- .../address/logic/commands/EditCommand.java | 20 +-- .../address/logic/commands/ExitCommand.java | 2 +- .../address/logic/commands/FindCommand.java | 4 +- .../address/logic/commands/ListCommand.java | 2 +- .../logic/parser/AddCommandParser.java | 12 +- .../logic/parser/FindCommandParser.java | 2 +- .../address/logic/parser/ParserUtil.java | 8 +- .../java/seedu/address/model/AddressBook.java | 20 +-- src/main/java/seedu/address/model/Model.java | 16 +- .../seedu/address/model/ModelManager.java | 16 +- .../address/model/ReadOnlyAddressBook.java | 4 +- .../exceptions/PersonNotFoundException.java | 6 - .../model/{person => student}/Address.java | 2 +- .../model/{person => student}/Email.java | 2 +- .../model/{person => student}/Name.java | 2 +- .../NameContainsKeywordsPredicate.java | 6 +- .../model/{person => student}/Phone.java | 2 +- .../Person.java => student/Student.java} | 12 +- .../UniqueStudentList.java} | 48 ++--- .../DuplicateStudentException.java} | 6 +- .../exceptions/StudentNotFoundException.java | 6 + .../address/model/util/SampleDataUtil.java | 28 +-- .../address/storage/JsonAdaptedPerson.java | 18 +- .../storage/JsonSerializableAddressBook.java | 4 +- .../java/seedu/address/ui/MainWindow.java | 12 +- .../ui/{PersonCard.java => StudentCard.java} | 53 ++++-- .../seedu/address/ui/StudentInfoPage.java | 102 +++++++++++ ...onListPanel.java => StudentListPanel.java} | 23 +-- src/main/java/seedu/address/ui/UiManager.java | 3 +- src/main/resources/images/studentInfoPage.png | Bin 0 -> 23199 bytes src/main/resources/view/HelpWindow.fxml | 1 - src/main/resources/view/MainWindow.fxml | 2 +- src/main/resources/view/StudentInfoPage.css | 9 + src/main/resources/view/StudentInfoPage.fxml | 41 +++++ ...rsonListCard.fxml => StudentListCard.fxml} | 8 + ...onListPanel.fxml => StudentListPanel.fxml} | 0 .../seedu/address/logic/LogicManagerTest.java | 4 +- .../commands/AddCommandIntegrationTest.java | 6 +- .../logic/commands/AddCommandTest.java | 34 ++-- .../logic/commands/CommandTestUtil.java | 8 +- .../logic/commands/DeleteCommandTest.java | 6 +- .../logic/commands/EditCommandTest.java | 18 +- ...st.java => EditStudentDescriptorTest.java} | 2 +- .../logic/commands/FindCommandTest.java | 2 +- .../logic/parser/AddCommandParserTest.java | 16 +- .../logic/parser/AddressBookParserTest.java | 8 +- .../logic/parser/EditCommandParserTest.java | 8 +- .../logic/parser/FindCommandParserTest.java | 2 +- .../address/logic/parser/ParserUtilTest.java | 8 +- .../seedu/address/model/AddressBookTest.java | 18 +- .../seedu/address/model/ModelManagerTest.java | 2 +- .../model/person/UniquePersonListTest.java | 170 ------------------ .../{person => student}/AddressTest.java | 2 +- .../model/{person => student}/EmailTest.java | 2 +- .../NameContainsKeywordsPredicateTest.java | 2 +- .../model/{person => student}/NameTest.java | 2 +- .../model/{person => student}/PhoneTest.java | 2 +- .../StudentTest.java} | 14 +- .../model/student/UniqueStudentListTest.java | 170 ++++++++++++++++++ ...nTest.java => JsonAdaptedStudentTest.java} | 10 +- .../address/testutil/AddressBookBuilder.java | 4 +- .../testutil/EditPersonDescriptorBuilder.java | 12 +- .../seedu/address/testutil/PersonBuilder.java | 16 +- .../seedu/address/testutil/PersonUtil.java | 6 +- .../java/seedu/address/testutil/TestUtil.java | 4 +- .../address/testutil/TypicalPersons.java | 28 +-- 75 files changed, 666 insertions(+), 484 deletions(-) delete mode 100644 src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java rename src/main/java/seedu/address/model/{person => student}/Address.java (97%) rename src/main/java/seedu/address/model/{person => student}/Email.java (98%) rename src/main/java/seedu/address/model/{person => student}/Name.java (97%) rename src/main/java/seedu/address/model/{person => student}/NameContainsKeywordsPredicate.java (90%) rename src/main/java/seedu/address/model/{person => student}/Phone.java (97%) rename src/main/java/seedu/address/model/{person/Person.java => student/Student.java} (91%) rename src/main/java/seedu/address/model/{person/UniquePersonList.java => student/UniqueStudentList.java} (67%) rename src/main/java/seedu/address/model/{person/exceptions/DuplicatePersonException.java => student/exceptions/DuplicateStudentException.java} (57%) create mode 100644 src/main/java/seedu/address/model/student/exceptions/StudentNotFoundException.java rename src/main/java/seedu/address/ui/{PersonCard.java => StudentCard.java} (55%) create mode 100644 src/main/java/seedu/address/ui/StudentInfoPage.java rename src/main/java/seedu/address/ui/{PersonListPanel.java => StudentListPanel.java} (52%) create mode 100644 src/main/resources/images/studentInfoPage.png create mode 100644 src/main/resources/view/StudentInfoPage.css create mode 100644 src/main/resources/view/StudentInfoPage.fxml rename src/main/resources/view/{PersonListCard.fxml => StudentListCard.fxml} (82%) rename src/main/resources/view/{PersonListPanel.fxml => StudentListPanel.fxml} (100%) rename src/test/java/seedu/address/logic/commands/{EditPersonDescriptorTest.java => EditStudentDescriptorTest.java} (98%) delete mode 100644 src/test/java/seedu/address/model/person/UniquePersonListTest.java rename src/test/java/seedu/address/model/{person => student}/AddressTest.java (97%) rename src/test/java/seedu/address/model/{person => student}/EmailTest.java (99%) rename src/test/java/seedu/address/model/{person => student}/NameContainsKeywordsPredicateTest.java (98%) rename src/test/java/seedu/address/model/{person => student}/NameTest.java (97%) rename src/test/java/seedu/address/model/{person => student}/PhoneTest.java (97%) rename src/test/java/seedu/address/model/{person/PersonTest.java => student/StudentTest.java} (87%) create mode 100644 src/test/java/seedu/address/model/student/UniqueStudentListTest.java rename src/test/java/seedu/address/storage/{JsonAdaptedPersonTest.java => JsonAdaptedStudentTest.java} (96%) diff --git a/docs/tutorials/AddRemark.md b/docs/tutorials/AddRemark.md index 880c701042f..4b8e028fad5 100644 --- a/docs/tutorials/AddRemark.md +++ b/docs/tutorials/AddRemark.md @@ -229,7 +229,7 @@ Now that we have all the information that we need, let’s lay the groundwork fo ### Add a new `Remark` class -Create a new `Remark` in `seedu.address.model.person`. Since a `Remark` is a field that is similar to `Address`, we can reuse a significant bit of code. +Create a new `Remark` in `seedu.address.model.student`. Since a `Remark` is a field that is similar to `Address`, we can reuse a significant bit of code. A copy-paste and search-replace later, you should have something like [this](https://github.com/se-edu/addressbook-level3/commit/4516e099699baa9e2d51801bd26f016d812dedcc#diff-41bb13c581e280c686198251ad6cc337cd5e27032772f06ed9bf7f1440995ece). Note how `Remark` has no constrains and thus does not require input validation. @@ -242,7 +242,7 @@ Let’s change `RemarkCommand` and `RemarkCommandParser` to use the new `Remark` Without getting too deep into `fxml`, let’s go on a 5 minute adventure to get some placeholder text to show up for each person. -Simply add the following to [`seedu.address.ui.PersonCard`](https://github.com/se-edu/addressbook-level3/commit/850b78879582f38accb05dd20c245963c65ea599#diff-639834f1e05afe2276a86372adf0fe5f69314642c2d93cfa543d614ce5a76688). +Simply add the following to [`seedu.address.ui.StudentCard`](https://github.com/se-edu/addressbook-level3/commit/850b78879582f38accb05dd20c245963c65ea599#diff-639834f1e05afe2276a86372adf0fe5f69314642c2d93cfa543d614ce5a76688). **`PersonCard.java`:** diff --git a/docs/tutorials/RemovingFields.md b/docs/tutorials/RemovingFields.md index f29169bc924..1f8f05e80f6 100644 --- a/docs/tutorials/RemovingFields.md +++ b/docs/tutorials/RemovingFields.md @@ -28,7 +28,7 @@ IntelliJ IDEA provides a refactoring tool that can identify *most* parts of a re ### Assisted refactoring -The `address` field in `Person` is actually an instance of the `seedu.address.model.person.Address` class. Since removing the `Address` class will break the application, we start by identifying `Address`'s usages. This allows us to see code that depends on `Address` to function properly and edit them on a case-by-case basis. Right-click the `Address` class and select `Refactor` \> `Safe Delete` through the menu. +The `address` field in `Person` is actually an instance of the `seedu.address.model.student.Address` class. Since removing the `Address` class will break the application, we start by identifying `Address`'s usages. This allows us to see code that depends on `Address` to function properly and edit them on a case-by-case basis. Right-click the `Address` class and select `Refactor` \> `Safe Delete` through the menu. * :bulb: To make things simpler, you can unselect the options `Search in comments and strings` and `Search for text occurrences` ![Usages detected](../images/remove/UnsafeDelete.png) diff --git a/src/main/java/seedu/address/MainApp.java b/src/main/java/seedu/address/MainApp.java index 4133aaa0151..4d6bbc493f1 100644 --- a/src/main/java/seedu/address/MainApp.java +++ b/src/main/java/seedu/address/MainApp.java @@ -48,7 +48,7 @@ public class MainApp extends Application { @Override public void init() throws Exception { - logger.info("=============================[ Initializing AddressBook ]==========================="); + logger.info("=============================[ Initializing TutorPro ]==========================="); super.init(); AppParameters appParameters = AppParameters.parse(getParameters()); @@ -79,14 +79,14 @@ private Model initModelManager(Storage storage, ReadOnlyUserPrefs userPrefs) { try { addressBookOptional = storage.readAddressBook(); if (!addressBookOptional.isPresent()) { - logger.info("Data file not found. Will be starting with a sample AddressBook"); + logger.info("Data file not found. Will be starting with a sample TutorPro"); } initialData = addressBookOptional.orElseGet(SampleDataUtil::getSampleAddressBook); } catch (DataConversionException e) { - logger.warning("Data file not in the correct format. Will be starting with an empty AddressBook"); + logger.warning("Data file not in the correct format. Will be starting with an empty TutorPro"); initialData = new AddressBook(); } 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 TutorPro"); initialData = new AddressBook(); } @@ -151,7 +151,7 @@ protected UserPrefs initPrefs(UserPrefsStorage storage) { + "Using default user prefs"); initializedPrefs = new UserPrefs(); } catch (IOException e) { - logger.warning("Problem while reading from the file. Will be starting with an empty AddressBook"); + logger.warning("Problem while reading from the file. Will be starting with an empty TutorPro"); initializedPrefs = new UserPrefs(); } @@ -167,13 +167,13 @@ protected UserPrefs initPrefs(UserPrefsStorage storage) { @Override public void start(Stage primaryStage) { - logger.info("Starting AddressBook " + MainApp.VERSION); + logger.info("Starting TutorPro " + MainApp.VERSION); ui.start(primaryStage); } @Override public void stop() { - logger.info("============================ [ Stopping Address Book ] ============================="); + logger.info("============================ [ Stopping TutorPro ] ============================="); try { storage.saveUserPrefs(model.getUserPrefs()); } catch (IOException e) { diff --git a/src/main/java/seedu/address/commons/core/Messages.java b/src/main/java/seedu/address/commons/core/Messages.java index 1deb3a1e469..a2be1630d6e 100644 --- a/src/main/java/seedu/address/commons/core/Messages.java +++ b/src/main/java/seedu/address/commons/core/Messages.java @@ -7,7 +7,7 @@ public class Messages { public static final String MESSAGE_UNKNOWN_COMMAND = "Unknown command"; public static final String MESSAGE_INVALID_COMMAND_FORMAT = "Invalid command format! \n%1$s"; - public static final String MESSAGE_INVALID_PERSON_DISPLAYED_INDEX = "The person index provided is invalid"; - public static final String MESSAGE_PERSONS_LISTED_OVERVIEW = "%1$d persons listed!"; + public static final String MESSAGE_INVALID_PERSON_DISPLAYED_INDEX = "The student index provided is invalid"; + public static final String MESSAGE_PERSONS_LISTED_OVERVIEW = "%1$d students listed!"; } diff --git a/src/main/java/seedu/address/logic/Logic.java b/src/main/java/seedu/address/logic/Logic.java index 92cd8fa605a..641d315e68d 100644 --- a/src/main/java/seedu/address/logic/Logic.java +++ b/src/main/java/seedu/address/logic/Logic.java @@ -8,7 +8,7 @@ import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.ReadOnlyAddressBook; -import seedu.address.model.person.Person; +import seedu.address.model.student.Student; /** * API of the Logic component @@ -31,7 +31,7 @@ public interface Logic { ReadOnlyAddressBook getAddressBook(); /** Returns an unmodifiable view of the filtered list of persons */ - ObservableList getFilteredPersonList(); + ObservableList getFilteredPersonList(); /** * Returns the user prefs' address book file path. diff --git a/src/main/java/seedu/address/logic/LogicManager.java b/src/main/java/seedu/address/logic/LogicManager.java index 9d9c6d15bdc..489f250d38b 100644 --- a/src/main/java/seedu/address/logic/LogicManager.java +++ b/src/main/java/seedu/address/logic/LogicManager.java @@ -14,7 +14,7 @@ import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.Model; import seedu.address.model.ReadOnlyAddressBook; -import seedu.address.model.person.Person; +import seedu.address.model.student.Student; import seedu.address.storage.Storage; /** @@ -60,7 +60,7 @@ public ReadOnlyAddressBook getAddressBook() { } @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 71656d7c5c8..0c2926da25d 100644 --- a/src/main/java/seedu/address/logic/commands/AddCommand.java +++ b/src/main/java/seedu/address/logic/commands/AddCommand.java @@ -9,16 +9,16 @@ import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.model.Model; -import seedu.address.model.person.Person; +import seedu.address.model.student.Student; /** - * Adds a person to the address book. + * Adds a student to the address book. */ public class AddCommand extends Command { public static final String COMMAND_WORD = "add"; - public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a person to the address book. " + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a student to the address book. " + "Parameters: " + PREFIX_NAME + "NAME " + PREFIX_PHONE + "PHONE " @@ -33,17 +33,17 @@ public class AddCommand extends Command { + 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 student added: %1$s"; + public static final String MESSAGE_DUPLICATE_STUDENT = "This student already exists in the address book"; - private final Person toAdd; + private final Student toAdd; /** - * Creates an AddCommand to add the specified {@code Person} + * Creates an AddCommand to add the specified {@code Student} */ - public AddCommand(Person person) { - requireNonNull(person); - toAdd = person; + public AddCommand(Student student) { + requireNonNull(student); + toAdd = student; } @Override @@ -51,7 +51,7 @@ public CommandResult execute(Model model) throws CommandException { requireNonNull(model); if (model.hasPerson(toAdd)) { - throw new CommandException(MESSAGE_DUPLICATE_PERSON); + throw new CommandException(MESSAGE_DUPLICATE_STUDENT); } model.addPerson(toAdd); diff --git a/src/main/java/seedu/address/logic/commands/ClearCommand.java b/src/main/java/seedu/address/logic/commands/ClearCommand.java index 9c86b1fa6e4..8291af5857b 100644 --- a/src/main/java/seedu/address/logic/commands/ClearCommand.java +++ b/src/main/java/seedu/address/logic/commands/ClearCommand.java @@ -11,7 +11,7 @@ public class ClearCommand extends Command { public static final String COMMAND_WORD = "clear"; - public static final String MESSAGE_SUCCESS = "Address book has been cleared!"; + public static final String MESSAGE_SUCCESS = "TutorPro 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 02fd256acba..0955b5f5a20 100644 --- a/src/main/java/seedu/address/logic/commands/DeleteCommand.java +++ b/src/main/java/seedu/address/logic/commands/DeleteCommand.java @@ -8,7 +8,7 @@ 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.student.Student; /** * Deletes a person identified using it's displayed index from the address book. @@ -33,13 +33,13 @@ public DeleteCommand(Index targetIndex) { @Override public CommandResult execute(Model model) throws CommandException { requireNonNull(model); - List lastShownList = model.getFilteredPersonList(); + List lastShownList = model.getFilteredPersonList(); if (targetIndex.getZeroBased() >= lastShownList.size()) { throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); } - Person personToDelete = lastShownList.get(targetIndex.getZeroBased()); + Student personToDelete = lastShownList.get(targetIndex.getZeroBased()); model.deletePerson(personToDelete); return new CommandResult(String.format(MESSAGE_DELETE_PERSON_SUCCESS, personToDelete)); } diff --git a/src/main/java/seedu/address/logic/commands/EditCommand.java b/src/main/java/seedu/address/logic/commands/EditCommand.java index 7e36114902f..e8bd1a17ae8 100644 --- a/src/main/java/seedu/address/logic/commands/EditCommand.java +++ b/src/main/java/seedu/address/logic/commands/EditCommand.java @@ -19,11 +19,11 @@ import seedu.address.commons.util.CollectionUtil; import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.model.Model; -import seedu.address.model.person.Address; -import seedu.address.model.person.Email; -import seedu.address.model.person.Name; -import seedu.address.model.person.Person; -import seedu.address.model.person.Phone; +import seedu.address.model.student.Address; +import seedu.address.model.student.Email; +import seedu.address.model.student.Name; +import seedu.address.model.student.Phone; +import seedu.address.model.student.Student; import seedu.address.model.tag.Tag; /** @@ -68,14 +68,14 @@ public EditCommand(Index index, EditPersonDescriptor editPersonDescriptor) { @Override public CommandResult execute(Model model) throws CommandException { requireNonNull(model); - List lastShownList = model.getFilteredPersonList(); + List lastShownList = model.getFilteredPersonList(); if (index.getZeroBased() >= lastShownList.size()) { throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); } - Person personToEdit = lastShownList.get(index.getZeroBased()); - Person editedPerson = createEditedPerson(personToEdit, editPersonDescriptor); + Student personToEdit = lastShownList.get(index.getZeroBased()); + Student editedPerson = createEditedPerson(personToEdit, editPersonDescriptor); if (!personToEdit.isSamePerson(editedPerson) && model.hasPerson(editedPerson)) { throw new CommandException(MESSAGE_DUPLICATE_PERSON); @@ -90,7 +90,7 @@ public CommandResult execute(Model model) throws CommandException { * Creates and returns a {@code Person} with the details of {@code personToEdit} * edited with {@code editPersonDescriptor}. */ - private static Person createEditedPerson(Person personToEdit, EditPersonDescriptor editPersonDescriptor) { + private static Student createEditedPerson(Student personToEdit, EditPersonDescriptor editPersonDescriptor) { assert personToEdit != null; Name updatedName = editPersonDescriptor.getName().orElse(personToEdit.getName()); @@ -99,7 +99,7 @@ private static Person createEditedPerson(Person personToEdit, EditPersonDescript Address updatedAddress = editPersonDescriptor.getAddress().orElse(personToEdit.getAddress()); Set updatedTags = editPersonDescriptor.getTags().orElse(personToEdit.getTags()); - return new Person(updatedName, updatedPhone, updatedEmail, updatedAddress, updatedTags); + return new Student(updatedName, updatedPhone, updatedEmail, updatedAddress, updatedTags); } @Override diff --git a/src/main/java/seedu/address/logic/commands/ExitCommand.java b/src/main/java/seedu/address/logic/commands/ExitCommand.java index 3dd85a8ba90..fc1184f8f9d 100644 --- a/src/main/java/seedu/address/logic/commands/ExitCommand.java +++ b/src/main/java/seedu/address/logic/commands/ExitCommand.java @@ -9,7 +9,7 @@ public class ExitCommand extends Command { public static final String COMMAND_WORD = "exit"; - public static final String MESSAGE_EXIT_ACKNOWLEDGEMENT = "Exiting Address Book as requested ..."; + public static final String MESSAGE_EXIT_ACKNOWLEDGEMENT = "Exiting Tutor Pro as requested ..."; @Override public CommandResult execute(Model model) { diff --git a/src/main/java/seedu/address/logic/commands/FindCommand.java b/src/main/java/seedu/address/logic/commands/FindCommand.java index d6b19b0a0de..24515822123 100644 --- a/src/main/java/seedu/address/logic/commands/FindCommand.java +++ b/src/main/java/seedu/address/logic/commands/FindCommand.java @@ -4,7 +4,7 @@ import seedu.address.commons.core.Messages; import seedu.address.model.Model; -import seedu.address.model.person.NameContainsKeywordsPredicate; +import seedu.address.model.student.NameContainsKeywordsPredicate; /** * Finds and lists all persons in address book whose name contains any of the argument keywords. @@ -14,7 +14,7 @@ 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 students whose names contain any of " + "the specified keywords (case-insensitive) and displays them as a list with index numbers.\n" + "Parameters: KEYWORD [MORE_KEYWORDS]...\n" + "Example: " + COMMAND_WORD + " alice bob charlie"; diff --git a/src/main/java/seedu/address/logic/commands/ListCommand.java b/src/main/java/seedu/address/logic/commands/ListCommand.java index 84be6ad2596..4cc6934d2d3 100644 --- a/src/main/java/seedu/address/logic/commands/ListCommand.java +++ b/src/main/java/seedu/address/logic/commands/ListCommand.java @@ -12,7 +12,7 @@ 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 students"; @Override diff --git a/src/main/java/seedu/address/logic/parser/AddCommandParser.java b/src/main/java/seedu/address/logic/parser/AddCommandParser.java index 3b8bfa035e8..6a37fb7a65d 100644 --- a/src/main/java/seedu/address/logic/parser/AddCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/AddCommandParser.java @@ -12,11 +12,11 @@ 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.student.Address; +import seedu.address.model.student.Email; +import seedu.address.model.student.Name; +import seedu.address.model.student.Phone; +import seedu.address.model.student.Student; import seedu.address.model.tag.Tag; /** @@ -44,7 +44,7 @@ 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); + Student person = new Student(name, phone, email, address, tagList); return new AddCommand(person); } diff --git a/src/main/java/seedu/address/logic/parser/FindCommandParser.java b/src/main/java/seedu/address/logic/parser/FindCommandParser.java index 4fb71f23103..9e0833aca08 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.student.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 b117acb9c55..9b2490da468 100644 --- a/src/main/java/seedu/address/logic/parser/ParserUtil.java +++ b/src/main/java/seedu/address/logic/parser/ParserUtil.java @@ -9,10 +9,10 @@ import seedu.address.commons.core.index.Index; import seedu.address.commons.util.StringUtil; import seedu.address.logic.parser.exceptions.ParseException; -import seedu.address.model.person.Address; -import seedu.address.model.person.Email; -import seedu.address.model.person.Name; -import seedu.address.model.person.Phone; +import seedu.address.model.student.Address; +import seedu.address.model.student.Email; +import seedu.address.model.student.Name; +import seedu.address.model.student.Phone; import seedu.address.model.tag.Tag; /** diff --git a/src/main/java/seedu/address/model/AddressBook.java b/src/main/java/seedu/address/model/AddressBook.java index 1a943a0781a..00d87a4b7b8 100644 --- a/src/main/java/seedu/address/model/AddressBook.java +++ b/src/main/java/seedu/address/model/AddressBook.java @@ -5,8 +5,8 @@ import java.util.List; import javafx.collections.ObservableList; -import seedu.address.model.person.Person; -import seedu.address.model.person.UniquePersonList; +import seedu.address.model.student.Student; +import seedu.address.model.student.UniqueStudentList; /** * Wraps all data at the address-book level @@ -14,7 +14,7 @@ */ public class AddressBook implements ReadOnlyAddressBook { - private final UniquePersonList persons; + private final UniqueStudentList persons; /* * The 'unusual' code block below is a non-static initialization block, sometimes used to avoid duplication @@ -24,7 +24,7 @@ public class AddressBook implements ReadOnlyAddressBook { * among constructors. */ { - persons = new UniquePersonList(); + persons = new UniqueStudentList(); } public AddressBook() {} @@ -43,7 +43,7 @@ public AddressBook(ReadOnlyAddressBook toBeCopied) { * Replaces the contents of the person list with {@code persons}. * {@code persons} must not contain duplicate persons. */ - public void setPersons(List persons) { + public void setPersons(List persons) { this.persons.setPersons(persons); } @@ -61,7 +61,7 @@ public void resetData(ReadOnlyAddressBook newData) { /** * Returns true if a person with the same identity as {@code person} exists in the address book. */ - public boolean hasPerson(Person person) { + public boolean hasPerson(Student person) { requireNonNull(person); return persons.contains(person); } @@ -70,7 +70,7 @@ public boolean hasPerson(Person person) { * Adds a person to the address book. * The person must not already exist in the address book. */ - public void addPerson(Person p) { + public void addPerson(Student p) { persons.add(p); } @@ -79,7 +79,7 @@ public void addPerson(Person p) { * {@code target} must exist in the address book. * The person identity of {@code editedPerson} must not be the same as another existing person in the address book. */ - public void setPerson(Person target, Person editedPerson) { + public void setPerson(Student target, Student editedPerson) { requireNonNull(editedPerson); persons.setPerson(target, editedPerson); @@ -89,7 +89,7 @@ public void setPerson(Person target, Person editedPerson) { * Removes {@code key} from this {@code AddressBook}. * {@code key} must exist in the address book. */ - public void removePerson(Person key) { + public void removePerson(Student key) { persons.remove(key); } @@ -102,7 +102,7 @@ public String toString() { } @Override - public ObservableList getPersonList() { + public ObservableList getPersonList() { return persons.asUnmodifiableObservableList(); } diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java index d54df471c1f..0b16afe805b 100644 --- a/src/main/java/seedu/address/model/Model.java +++ b/src/main/java/seedu/address/model/Model.java @@ -5,14 +5,14 @@ import javafx.collections.ObservableList; import seedu.address.commons.core.GuiSettings; -import seedu.address.model.person.Person; +import seedu.address.model.student.Student; /** * 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; /** * Replaces user prefs data with the data in {@code userPrefs}. @@ -55,33 +55,33 @@ public interface Model { /** * Returns true if a person with the same identity as {@code person} exists in the address book. */ - boolean hasPerson(Person person); + boolean hasPerson(Student person); /** * Deletes the given person. * The person must exist in the address book. */ - void deletePerson(Person target); + void deletePerson(Student target); /** * Adds the given person. * {@code person} must not already exist in the address book. */ - void addPerson(Person person); + void addPerson(Student person); /** * Replaces the given person {@code target} with {@code editedPerson}. * {@code target} must exist in the address book. * The person identity of {@code editedPerson} must not be the same as another existing person in the address book. */ - void setPerson(Person target, Person editedPerson); + void setPerson(Student target, Student editedPerson); /** Returns an unmodifiable view of the filtered person list */ - ObservableList getFilteredPersonList(); + ObservableList getFilteredPersonList(); /** * Updates the filter of the filtered person 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 86c1df298d7..7fbd2d3cd76 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.GuiSettings; import seedu.address.commons.core.LogsCenter; -import seedu.address.model.person.Person; +import seedu.address.model.student.Student; /** * Represents the in-memory model of the address book data. @@ -21,7 +21,7 @@ public class ModelManager implements Model { private final AddressBook addressBook; private final UserPrefs userPrefs; - private final FilteredList filteredPersons; + private final FilteredList filteredPersons; /** * Initializes a ModelManager with the given addressBook and userPrefs. @@ -88,24 +88,24 @@ public ReadOnlyAddressBook getAddressBook() { } @Override - public boolean hasPerson(Person person) { + public boolean hasPerson(Student person) { requireNonNull(person); return addressBook.hasPerson(person); } @Override - public void deletePerson(Person target) { + public void deletePerson(Student target) { addressBook.removePerson(target); } @Override - public void addPerson(Person person) { + public void addPerson(Student person) { addressBook.addPerson(person); updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); } @Override - public void setPerson(Person target, Person editedPerson) { + public void setPerson(Student target, Student editedPerson) { requireAllNonNull(target, editedPerson); addressBook.setPerson(target, editedPerson); @@ -118,12 +118,12 @@ public void setPerson(Person target, Person editedPerson) { * {@code versionedAddressBook} */ @Override - public ObservableList getFilteredPersonList() { + public ObservableList getFilteredPersonList() { return filteredPersons; } @Override - public void updateFilteredPersonList(Predicate predicate) { + public void updateFilteredPersonList(Predicate predicate) { requireNonNull(predicate); filteredPersons.setPredicate(predicate); } diff --git a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java b/src/main/java/seedu/address/model/ReadOnlyAddressBook.java index 6ddc2cd9a29..e1c7f661f4d 100644 --- a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java +++ b/src/main/java/seedu/address/model/ReadOnlyAddressBook.java @@ -1,7 +1,7 @@ package seedu.address.model; import javafx.collections.ObservableList; -import seedu.address.model.person.Person; +import seedu.address.model.student.Student; /** * Unmodifiable view of an address book @@ -12,6 +12,6 @@ public interface ReadOnlyAddressBook { * Returns an unmodifiable view of the persons list. * This list will not contain any duplicate persons. */ - ObservableList getPersonList(); + ObservableList getPersonList(); } diff --git a/src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java b/src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java deleted file mode 100644 index fa764426ca7..00000000000 --- a/src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java +++ /dev/null @@ -1,6 +0,0 @@ -package seedu.address.model.person.exceptions; - -/** - * Signals that the operation is unable to find the specified person. - */ -public class PersonNotFoundException extends RuntimeException {} diff --git a/src/main/java/seedu/address/model/person/Address.java b/src/main/java/seedu/address/model/student/Address.java similarity index 97% rename from src/main/java/seedu/address/model/person/Address.java rename to src/main/java/seedu/address/model/student/Address.java index 60472ca22a0..5e04019bde5 100644 --- a/src/main/java/seedu/address/model/person/Address.java +++ b/src/main/java/seedu/address/model/student/Address.java @@ -1,4 +1,4 @@ -package seedu.address.model.person; +package seedu.address.model.student; import static java.util.Objects.requireNonNull; import static seedu.address.commons.util.AppUtil.checkArgument; diff --git a/src/main/java/seedu/address/model/person/Email.java b/src/main/java/seedu/address/model/student/Email.java similarity index 98% rename from src/main/java/seedu/address/model/person/Email.java rename to src/main/java/seedu/address/model/student/Email.java index f866e7133de..f0ffe638dc0 100644 --- a/src/main/java/seedu/address/model/person/Email.java +++ b/src/main/java/seedu/address/model/student/Email.java @@ -1,4 +1,4 @@ -package seedu.address.model.person; +package seedu.address.model.student; import static java.util.Objects.requireNonNull; import static seedu.address.commons.util.AppUtil.checkArgument; diff --git a/src/main/java/seedu/address/model/person/Name.java b/src/main/java/seedu/address/model/student/Name.java similarity index 97% rename from src/main/java/seedu/address/model/person/Name.java rename to src/main/java/seedu/address/model/student/Name.java index 79244d71cf7..c3b387493f2 100644 --- a/src/main/java/seedu/address/model/person/Name.java +++ b/src/main/java/seedu/address/model/student/Name.java @@ -1,4 +1,4 @@ -package seedu.address.model.person; +package seedu.address.model.student; import static java.util.Objects.requireNonNull; import static seedu.address.commons.util.AppUtil.checkArgument; diff --git a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/student/NameContainsKeywordsPredicate.java similarity index 90% rename from src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java rename to src/main/java/seedu/address/model/student/NameContainsKeywordsPredicate.java index c9b5868427c..638d1e82adb 100644 --- a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java +++ b/src/main/java/seedu/address/model/student/NameContainsKeywordsPredicate.java @@ -1,4 +1,4 @@ -package seedu.address.model.person; +package seedu.address.model.student; import java.util.List; import java.util.function.Predicate; @@ -8,7 +8,7 @@ /** * Tests that a {@code Person}'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,7 +16,7 @@ public NameContainsKeywordsPredicate(List keywords) { } @Override - public boolean test(Person person) { + public boolean test(Student person) { return keywords.stream() .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(person.getName().fullName, keyword)); } diff --git a/src/main/java/seedu/address/model/person/Phone.java b/src/main/java/seedu/address/model/student/Phone.java similarity index 97% rename from src/main/java/seedu/address/model/person/Phone.java rename to src/main/java/seedu/address/model/student/Phone.java index 872c76b382f..2ccc9aa4c72 100644 --- a/src/main/java/seedu/address/model/person/Phone.java +++ b/src/main/java/seedu/address/model/student/Phone.java @@ -1,4 +1,4 @@ -package seedu.address.model.person; +package seedu.address.model.student; import static java.util.Objects.requireNonNull; import static seedu.address.commons.util.AppUtil.checkArgument; diff --git a/src/main/java/seedu/address/model/person/Person.java b/src/main/java/seedu/address/model/student/Student.java similarity index 91% rename from src/main/java/seedu/address/model/person/Person.java rename to src/main/java/seedu/address/model/student/Student.java index 8ff1d83fe89..1d5e98ed9d7 100644 --- a/src/main/java/seedu/address/model/person/Person.java +++ b/src/main/java/seedu/address/model/student/Student.java @@ -1,4 +1,4 @@ -package seedu.address.model.person; +package seedu.address.model.student; import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; @@ -13,7 +13,7 @@ * Represents a Person in the address book. * Guarantees: details are present and not null, field values are validated, immutable. */ -public class Person { +public class Student { // Identity fields private final Name name; @@ -27,7 +27,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 Student(Name name, Phone phone, Email email, Address address, Set tags) { requireAllNonNull(name, phone, email, address, tags); this.name = name; this.phone = phone; @@ -64,7 +64,7 @@ public Set getTags() { * Returns true if both persons have the same name. * This defines a weaker notion of equality between two persons. */ - public boolean isSamePerson(Person otherPerson) { + public boolean isSamePerson(Student otherPerson) { if (otherPerson == this) { return true; } @@ -83,11 +83,11 @@ public boolean equals(Object other) { return true; } - if (!(other instanceof Person)) { + if (!(other instanceof Student)) { return false; } - Person otherPerson = (Person) other; + Student otherPerson = (Student) other; return otherPerson.getName().equals(getName()) && otherPerson.getPhone().equals(getPhone()) && otherPerson.getEmail().equals(getEmail()) diff --git a/src/main/java/seedu/address/model/person/UniquePersonList.java b/src/main/java/seedu/address/model/student/UniqueStudentList.java similarity index 67% rename from src/main/java/seedu/address/model/person/UniquePersonList.java rename to src/main/java/seedu/address/model/student/UniqueStudentList.java index 0fee4fe57e6..66e5feb4112 100644 --- a/src/main/java/seedu/address/model/person/UniquePersonList.java +++ b/src/main/java/seedu/address/model/student/UniqueStudentList.java @@ -1,4 +1,4 @@ -package seedu.address.model.person; +package seedu.address.model.student; import static java.util.Objects.requireNonNull; import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; @@ -8,30 +8,30 @@ import javafx.collections.FXCollections; import javafx.collections.ObservableList; -import seedu.address.model.person.exceptions.DuplicatePersonException; -import seedu.address.model.person.exceptions.PersonNotFoundException; +import seedu.address.model.student.exceptions.DuplicateStudentException; +import seedu.address.model.student.exceptions.StudentNotFoundException; /** * A list of persons that enforces uniqueness between its elements and does not allow nulls. * A person is considered unique by comparing using {@code Person#isSamePerson(Person)}. As such, adding and updating of * persons uses Person#isSamePerson(Person) for equality so as to ensure that the person being added or updated is - * unique in terms of identity in the UniquePersonList. However, the removal of a person uses Person#equals(Object) so + * unique in terms of identity in the UniqueStudentList. However, the removal of a person uses Person#equals(Object) so * as to ensure that the person with exactly the same fields will be removed. * * Supports a minimal set of list operations. * - * @see Person#isSamePerson(Person) + * @see Student#isSamePerson(Student) */ -public class UniquePersonList implements Iterable { +public class UniqueStudentList implements Iterable { - private final ObservableList internalList = FXCollections.observableArrayList(); - private final ObservableList internalUnmodifiableList = + private final ObservableList internalList = FXCollections.observableArrayList(); + private final ObservableList internalUnmodifiableList = FXCollections.unmodifiableObservableList(internalList); /** * Returns true if the list contains an equivalent person as the given argument. */ - public boolean contains(Person toCheck) { + public boolean contains(Student toCheck) { requireNonNull(toCheck); return internalList.stream().anyMatch(toCheck::isSamePerson); } @@ -40,10 +40,10 @@ public boolean contains(Person toCheck) { * Adds a person to the list. * The person must not already exist in the list. */ - public void add(Person toAdd) { + public void add(Student toAdd) { requireNonNull(toAdd); if (contains(toAdd)) { - throw new DuplicatePersonException(); + throw new DuplicateStudentException(); } internalList.add(toAdd); } @@ -53,16 +53,16 @@ public void add(Person toAdd) { * {@code target} must exist in the list. * The person identity of {@code editedPerson} must not be the same as another existing person in the list. */ - public void setPerson(Person target, Person editedPerson) { + public void setPerson(Student target, Student editedPerson) { requireAllNonNull(target, editedPerson); int index = internalList.indexOf(target); if (index == -1) { - throw new PersonNotFoundException(); + throw new StudentNotFoundException(); } if (!target.isSamePerson(editedPerson) && contains(editedPerson)) { - throw new DuplicatePersonException(); + throw new DuplicateStudentException(); } internalList.set(index, editedPerson); @@ -72,14 +72,14 @@ public void setPerson(Person target, Person editedPerson) { * Removes the equivalent person from the list. * The person must exist in the list. */ - public void remove(Person toRemove) { + public void remove(Student toRemove) { requireNonNull(toRemove); if (!internalList.remove(toRemove)) { - throw new PersonNotFoundException(); + throw new StudentNotFoundException(); } } - public void setPersons(UniquePersonList replacement) { + public void setPersons(UniqueStudentList replacement) { requireNonNull(replacement); internalList.setAll(replacement.internalList); } @@ -88,10 +88,10 @@ public void setPersons(UniquePersonList replacement) { * Replaces the contents of this list with {@code persons}. * {@code persons} must not contain duplicate persons. */ - public void setPersons(List persons) { + public void setPersons(List persons) { requireAllNonNull(persons); if (!personsAreUnique(persons)) { - throw new DuplicatePersonException(); + throw new DuplicateStudentException(); } internalList.setAll(persons); @@ -100,20 +100,20 @@ public void setPersons(List persons) { /** * Returns the backing list as an unmodifiable {@code ObservableList}. */ - public ObservableList asUnmodifiableObservableList() { + public ObservableList asUnmodifiableObservableList() { return internalUnmodifiableList; } @Override - public Iterator iterator() { + public Iterator iterator() { return internalList.iterator(); } @Override public boolean equals(Object other) { return other == this // short circuit if same object - || (other instanceof UniquePersonList // instanceof handles nulls - && internalList.equals(((UniquePersonList) other).internalList)); + || (other instanceof UniqueStudentList // instanceof handles nulls + && internalList.equals(((UniqueStudentList) other).internalList)); } @Override @@ -124,7 +124,7 @@ public int hashCode() { /** * Returns true if {@code persons} contains only unique persons. */ - private boolean personsAreUnique(List persons) { + private boolean personsAreUnique(List persons) { for (int i = 0; i < persons.size() - 1; i++) { for (int j = i + 1; j < persons.size(); j++) { if (persons.get(i).isSamePerson(persons.get(j))) { diff --git a/src/main/java/seedu/address/model/person/exceptions/DuplicatePersonException.java b/src/main/java/seedu/address/model/student/exceptions/DuplicateStudentException.java similarity index 57% rename from src/main/java/seedu/address/model/person/exceptions/DuplicatePersonException.java rename to src/main/java/seedu/address/model/student/exceptions/DuplicateStudentException.java index d7290f59442..be126bcd35a 100644 --- a/src/main/java/seedu/address/model/person/exceptions/DuplicatePersonException.java +++ b/src/main/java/seedu/address/model/student/exceptions/DuplicateStudentException.java @@ -1,11 +1,11 @@ -package seedu.address.model.person.exceptions; +package seedu.address.model.student.exceptions; /** * Signals that the operation will result in duplicate Persons (Persons are considered duplicates if they have the same * identity). */ -public class DuplicatePersonException extends RuntimeException { - public DuplicatePersonException() { +public class DuplicateStudentException extends RuntimeException { + public DuplicateStudentException() { super("Operation would result in duplicate persons"); } } diff --git a/src/main/java/seedu/address/model/student/exceptions/StudentNotFoundException.java b/src/main/java/seedu/address/model/student/exceptions/StudentNotFoundException.java new file mode 100644 index 00000000000..03722c20ccf --- /dev/null +++ b/src/main/java/seedu/address/model/student/exceptions/StudentNotFoundException.java @@ -0,0 +1,6 @@ +package seedu.address.model.student.exceptions; + +/** + * Signals that the operation is unable to find the specified person. + */ +public class StudentNotFoundException extends RuntimeException {} diff --git a/src/main/java/seedu/address/model/util/SampleDataUtil.java b/src/main/java/seedu/address/model/util/SampleDataUtil.java index 1806da4facf..a2b08d3424c 100644 --- a/src/main/java/seedu/address/model/util/SampleDataUtil.java +++ b/src/main/java/seedu/address/model/util/SampleDataUtil.java @@ -6,35 +6,35 @@ import seedu.address.model.AddressBook; import seedu.address.model.ReadOnlyAddressBook; -import seedu.address.model.person.Address; -import seedu.address.model.person.Email; -import seedu.address.model.person.Name; -import seedu.address.model.person.Person; -import seedu.address.model.person.Phone; +import seedu.address.model.student.Address; +import seedu.address.model.student.Email; +import seedu.address.model.student.Name; +import seedu.address.model.student.Phone; +import seedu.address.model.student.Student; import seedu.address.model.tag.Tag; /** * Contains utility methods for populating {@code AddressBook} 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 Student[] getSamplePersons() { + return new Student[] { + new Student(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 Student(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 Student(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 Student(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 Student(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 Student(new Name("Roy Balakrishnan"), new Phone("92624417"), new Email("royb@example.com"), new Address("Blk 45 Aljunied Street 85, #11-31"), getTagSet("colleagues")) }; @@ -42,7 +42,7 @@ public static Person[] getSamplePersons() { public static ReadOnlyAddressBook getSampleAddressBook() { AddressBook sampleAb = new AddressBook(); - for (Person samplePerson : getSamplePersons()) { + for (Student samplePerson : getSamplePersons()) { sampleAb.addPerson(samplePerson); } return sampleAb; diff --git a/src/main/java/seedu/address/storage/JsonAdaptedPerson.java b/src/main/java/seedu/address/storage/JsonAdaptedPerson.java index a6321cec2ea..f4684c990bd 100644 --- a/src/main/java/seedu/address/storage/JsonAdaptedPerson.java +++ b/src/main/java/seedu/address/storage/JsonAdaptedPerson.java @@ -10,15 +10,15 @@ import com.fasterxml.jackson.annotation.JsonProperty; import seedu.address.commons.exceptions.IllegalValueException; -import seedu.address.model.person.Address; -import seedu.address.model.person.Email; -import seedu.address.model.person.Name; -import seedu.address.model.person.Person; -import seedu.address.model.person.Phone; +import seedu.address.model.student.Address; +import seedu.address.model.student.Email; +import seedu.address.model.student.Name; +import seedu.address.model.student.Phone; +import seedu.address.model.student.Student; import seedu.address.model.tag.Tag; /** - * Jackson-friendly version of {@link Person}. + * Jackson-friendly version of {@link Student}. */ class JsonAdaptedPerson { @@ -49,7 +49,7 @@ public JsonAdaptedPerson(@JsonProperty("name") String name, @JsonProperty("phone /** * Converts a given {@code Person} into this class for Jackson use. */ - public JsonAdaptedPerson(Person source) { + public JsonAdaptedPerson(Student source) { name = source.getName().fullName; phone = source.getPhone().value; email = source.getEmail().value; @@ -64,7 +64,7 @@ public JsonAdaptedPerson(Person source) { * * @throws IllegalValueException if there were any data constraints violated in the adapted person. */ - public Person toModelType() throws IllegalValueException { + public Student toModelType() throws IllegalValueException { final List personTags = new ArrayList<>(); for (JsonAdaptedTag tag : tagged) { personTags.add(tag.toModelType()); @@ -103,7 +103,7 @@ public Person toModelType() throws IllegalValueException { final Address modelAddress = new Address(address); final Set modelTags = new HashSet<>(personTags); - return new Person(modelName, modelPhone, modelEmail, modelAddress, modelTags); + return new Student(modelName, modelPhone, modelEmail, modelAddress, modelTags); } } diff --git a/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java b/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java index 5efd834091d..f01d057f65f 100644 --- a/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java +++ b/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java @@ -11,7 +11,7 @@ import seedu.address.commons.exceptions.IllegalValueException; import seedu.address.model.AddressBook; import seedu.address.model.ReadOnlyAddressBook; -import seedu.address.model.person.Person; +import seedu.address.model.student.Student; /** * An Immutable AddressBook that is serializable to JSON format. @@ -48,7 +48,7 @@ public JsonSerializableAddressBook(ReadOnlyAddressBook source) { public AddressBook toModelType() throws IllegalValueException { AddressBook addressBook = new AddressBook(); for (JsonAdaptedPerson jsonAdaptedPerson : persons) { - Person person = jsonAdaptedPerson.toModelType(); + Student person = jsonAdaptedPerson.toModelType(); if (addressBook.hasPerson(person)) { throw new IllegalValueException(MESSAGE_DUPLICATE_PERSON); } diff --git a/src/main/java/seedu/address/ui/MainWindow.java b/src/main/java/seedu/address/ui/MainWindow.java index 9106c3aa6e5..4a05d270399 100644 --- a/src/main/java/seedu/address/ui/MainWindow.java +++ b/src/main/java/seedu/address/ui/MainWindow.java @@ -28,10 +28,10 @@ public class MainWindow extends UiPart { private final Logger logger = LogsCenter.getLogger(getClass()); private Stage primaryStage; - private Logic logic; + private final Logic logic; // Independent Ui parts residing in this Ui container - private PersonListPanel personListPanel; + private StudentListPanel studentListPanel; private ResultDisplay resultDisplay; private HelpWindow helpWindow; @@ -110,8 +110,8 @@ private void setAccelerator(MenuItem menuItem, KeyCombination keyCombination) { * Fills up all the placeholders of this window. */ void fillInnerParts() { - personListPanel = new PersonListPanel(logic.getFilteredPersonList()); - personListPanelPlaceholder.getChildren().add(personListPanel.getRoot()); + studentListPanel = new StudentListPanel(logic.getFilteredPersonList(), primaryStage); + personListPanelPlaceholder.getChildren().add(studentListPanel.getRoot()); resultDisplay = new ResultDisplay(); resultDisplayPlaceholder.getChildren().add(resultDisplay.getRoot()); @@ -163,8 +163,8 @@ private void handleExit() { primaryStage.hide(); } - public PersonListPanel getPersonListPanel() { - return personListPanel; + public StudentListPanel getPersonListPanel() { + return studentListPanel; } /** diff --git a/src/main/java/seedu/address/ui/PersonCard.java b/src/main/java/seedu/address/ui/StudentCard.java similarity index 55% rename from src/main/java/seedu/address/ui/PersonCard.java rename to src/main/java/seedu/address/ui/StudentCard.java index 7fc927bc5d9..aa59c911992 100644 --- a/src/main/java/seedu/address/ui/PersonCard.java +++ b/src/main/java/seedu/address/ui/StudentCard.java @@ -3,18 +3,21 @@ import java.util.Comparator; import javafx.fxml.FXML; +import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.layout.FlowPane; import javafx.scene.layout.HBox; import javafx.scene.layout.Region; -import seedu.address.model.person.Person; +import javafx.stage.Stage; +import seedu.address.model.student.Student; /** * An UI component that displays information of a {@code Person}. */ -public class PersonCard extends UiPart { +public class StudentCard extends UiPart { - private static final String FXML = "PersonListCard.fxml"; + private static final String FXML = "StudentListCard.fxml"; + private final Stage studentInfoPageStage; /** * Note: Certain keywords such as "location" and "resources" are reserved keywords in JavaFX. @@ -24,8 +27,6 @@ public class PersonCard extends UiPart { * @see The issue on AddressBook level 4 */ - public final Person person; - @FXML private HBox cardPane; @FXML @@ -40,23 +41,45 @@ public class PersonCard extends UiPart { private Label email; @FXML private FlowPane tags; + @FXML + private Button view; + + private final Student student; /** * Creates a {@code PersonCode} with the given {@code Person} and index to display. */ - public PersonCard(Person person, int displayedIndex) { + public StudentCard(Student student, int displayedIndex) { super(FXML); - this.person = person; + this.student = student; + this.studentInfoPageStage = new Stage(); + id.setText(displayedIndex + ". "); - name.setText(person.getName().fullName); - phone.setText(person.getPhone().value); - address.setText(person.getAddress().value); - email.setText(person.getEmail().value); - person.getTags().stream() + name.setText(student.getName().fullName); + phone.setText(student.getPhone().value); + address.setText(student.getAddress().value); + email.setText(student.getEmail().value); + student.getTags().stream() .sorted(Comparator.comparing(tag -> tag.tagName)) .forEach(tag -> tags.getChildren().add(new Label(tag.tagName))); + view.setOnAction(event -> handleViewClick()); + } + + /** + * Handles the view button click event. + */ + @FXML + private void handleViewClick() { + StudentInfoPage infoPage = new StudentInfoPage(student, studentInfoPageStage); + + if (!infoPage.isShowing()) { + infoPage.show(); + } else { + infoPage.focus(); + } } + @Override public boolean equals(Object other) { // short circuit if same object @@ -65,13 +88,13 @@ public boolean equals(Object other) { } // instanceof handles nulls - if (!(other instanceof PersonCard)) { + if (!(other instanceof StudentCard)) { return false; } // state check - PersonCard card = (PersonCard) other; + StudentCard card = (StudentCard) other; return id.getText().equals(card.id.getText()) - && person.equals(card.person); + && student.equals(card.student); } } diff --git a/src/main/java/seedu/address/ui/StudentInfoPage.java b/src/main/java/seedu/address/ui/StudentInfoPage.java new file mode 100644 index 00000000000..9280f16fc1a --- /dev/null +++ b/src/main/java/seedu/address/ui/StudentInfoPage.java @@ -0,0 +1,102 @@ +package seedu.address.ui; + +import java.util.logging.Logger; + +import javafx.fxml.FXML; +import javafx.scene.control.Label; +import javafx.stage.Stage; +import seedu.address.commons.core.LogsCenter; +import seedu.address.model.student.Name; +import seedu.address.model.student.Student; + +/** + * An UI component that displays detailed information of a {@code Student}. + */ +public class StudentInfoPage extends UiPart { + private static final Logger logger = LogsCenter.getLogger(StudentInfoPage.class); + + private static final String FXML = "StudentInfoPage.fxml"; + private Name studentName; + + @FXML + private Label name; + @FXML + private Label phone; + @FXML + private Label address; + @FXML + private Label email; + + /** + * Creates a {@code StudentInfoPage} with the given {@code Student}. + */ + public StudentInfoPage(Student student, Stage stage) { + super(FXML, stage); + studentName = student.getName(); + + name.setText(String.format("Full Name: %s", student.getName().fullName)); + phone.setText(String.format("Phone Number: %s", student.getPhone().value)); + address.setText(String.format("Address: %s", student.getAddress().value)); + email.setText(String.format("Email: %s", student.getEmail().value)); + } + + /** + * Returns true if the help window is currently being shown. + */ + public boolean isShowing() { + return getRoot().isShowing(); + } + + /** + * Hides the help window. + */ + public void hide() { + getRoot().hide(); + } + + /** + * Focuses on the help window. + */ + public void focus() { + getRoot().requestFocus(); + } + + /** + * Shows the help window. + * @throws IllegalStateException + *
    + *
  • + * if this method is called on a thread other than the JavaFX Application Thread. + *
  • + *
  • + * if this method is called during animation or layout processing. + *
  • + *
  • + * if this method is called on the primary stage. + *
  • + *
  • + * if {@code dialogStage} is already showing. + *
  • + *
+ */ + public void show() { + logger.fine(String.format("Showing student info page for %s", name.getText())); + getRoot().show(); + getRoot().setTitle(String.format("Info Page for %s", studentName.fullName)); + getRoot().centerOnScreen(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + + if (!(obj instanceof StudentInfoPage)) { + return false; + } + + StudentInfoPage otherStudentInfoPage = (StudentInfoPage) obj; + return otherStudentInfoPage.getRoot().equals(getRoot()); + } +} diff --git a/src/main/java/seedu/address/ui/PersonListPanel.java b/src/main/java/seedu/address/ui/StudentListPanel.java similarity index 52% rename from src/main/java/seedu/address/ui/PersonListPanel.java rename to src/main/java/seedu/address/ui/StudentListPanel.java index f4c501a897b..8d1c88b1e31 100644 --- a/src/main/java/seedu/address/ui/PersonListPanel.java +++ b/src/main/java/seedu/address/ui/StudentListPanel.java @@ -7,41 +7,42 @@ import javafx.scene.control.ListCell; import javafx.scene.control.ListView; import javafx.scene.layout.Region; +import javafx.stage.Stage; import seedu.address.commons.core.LogsCenter; -import seedu.address.model.person.Person; +import seedu.address.model.student.Student; /** * Panel containing the list of persons. */ -public class PersonListPanel extends UiPart { - private static final String FXML = "PersonListPanel.fxml"; - private final Logger logger = LogsCenter.getLogger(PersonListPanel.class); +public class StudentListPanel extends UiPart { + private static final String FXML = "StudentListPanel.fxml"; + private final Logger logger = LogsCenter.getLogger(StudentListPanel.class); @FXML - private ListView personListView; + private ListView personListView; /** - * Creates a {@code PersonListPanel} with the given {@code ObservableList}. + * Creates a {@code StudentListPanel} with the given {@code ObservableList}. */ - public PersonListPanel(ObservableList personList) { + public StudentListPanel(ObservableList personList, Stage primaryStage) { super(FXML); personListView.setItems(personList); personListView.setCellFactory(listView -> new PersonListViewCell()); } /** - * Custom {@code ListCell} that displays the graphics of a {@code Person} using a {@code PersonCard}. + * Custom {@code ListCell} that displays the graphics of a {@code Person} using a {@code StudentCard}. */ - class PersonListViewCell extends ListCell { + class PersonListViewCell extends ListCell { @Override - protected void updateItem(Person person, boolean empty) { + protected void updateItem(Student person, boolean empty) { super.updateItem(person, empty); if (empty || person == null) { setGraphic(null); setText(null); } else { - setGraphic(new PersonCard(person, getIndex() + 1).getRoot()); + setGraphic(new StudentCard(person, getIndex() + 1).getRoot()); } } } diff --git a/src/main/java/seedu/address/ui/UiManager.java b/src/main/java/seedu/address/ui/UiManager.java index fdf024138bc..3b5692eadae 100644 --- a/src/main/java/seedu/address/ui/UiManager.java +++ b/src/main/java/seedu/address/ui/UiManager.java @@ -22,7 +22,7 @@ public class UiManager implements Ui { private static final Logger logger = LogsCenter.getLogger(UiManager.class); private static final String ICON_APPLICATION = "/images/address_book_32.png"; - private Logic logic; + private final Logic logic; private MainWindow mainWindow; /** @@ -84,5 +84,4 @@ private void showFatalErrorDialogAndShutdown(String title, Throwable e) { Platform.exit(); System.exit(1); } - } diff --git a/src/main/resources/images/studentInfoPage.png b/src/main/resources/images/studentInfoPage.png new file mode 100644 index 0000000000000000000000000000000000000000..58ce5ef18ee5815596f942d01d21eb165d5a7b5d GIT binary patch literal 23199 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 -